ECE 4180 Lab 4 Racing Game
Dependencies: 4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player_appbd
main.cpp@0:a3096c3dccff, 2017-03-16 (annotated)
- Committer:
- deathernater
- Date:
- Thu Mar 16 01:27:09 2017 +0000
- Revision:
- 0:a3096c3dccff
Initial
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
deathernater | 0:a3096c3dccff | 1 | #include "mbed.h" |
deathernater | 0:a3096c3dccff | 2 | #include "rtos.h" |
deathernater | 0:a3096c3dccff | 3 | #include "SDFileSystem.h" |
deathernater | 0:a3096c3dccff | 4 | #include "wave_player.h" |
deathernater | 0:a3096c3dccff | 5 | #include "uLCD_4DGL.h" |
deathernater | 0:a3096c3dccff | 6 | |
deathernater | 0:a3096c3dccff | 7 | #define PI 3.14159 |
deathernater | 0:a3096c3dccff | 8 | |
deathernater | 0:a3096c3dccff | 9 | //Serial Debug |
deathernater | 0:a3096c3dccff | 10 | Serial pc(USBTX, USBRX); |
deathernater | 0:a3096c3dccff | 11 | |
deathernater | 0:a3096c3dccff | 12 | //Joystick |
deathernater | 0:a3096c3dccff | 13 | AnalogIn jsy(p16); |
deathernater | 0:a3096c3dccff | 14 | AnalogIn jsx(p15); |
deathernater | 0:a3096c3dccff | 15 | |
deathernater | 0:a3096c3dccff | 16 | //SD Card |
deathernater | 0:a3096c3dccff | 17 | SDFileSystem sd(p5, p6, p7, p8, "sd"); |
deathernater | 0:a3096c3dccff | 18 | |
deathernater | 0:a3096c3dccff | 19 | //LCD Display |
deathernater | 0:a3096c3dccff | 20 | uLCD_4DGL uLCD(p13, p14, p30); // serial tx, serial rx, reset pin |
deathernater | 0:a3096c3dccff | 21 | |
deathernater | 0:a3096c3dccff | 22 | //Analog Out Jack |
deathernater | 0:a3096c3dccff | 23 | AnalogOut DACout(p18); |
deathernater | 0:a3096c3dccff | 24 | //On Board Speaker |
deathernater | 0:a3096c3dccff | 25 | PwmOut PWMout(p26); |
deathernater | 0:a3096c3dccff | 26 | |
deathernater | 0:a3096c3dccff | 27 | //Audio Player |
deathernater | 0:a3096c3dccff | 28 | wave_player player(&DACout, &PWMout); |
deathernater | 0:a3096c3dccff | 29 | |
deathernater | 0:a3096c3dccff | 30 | //Threads |
deathernater | 0:a3096c3dccff | 31 | Thread audioThread, thread2, thread3, gameDisplayThread; |
deathernater | 0:a3096c3dccff | 32 | |
deathernater | 0:a3096c3dccff | 33 | //Game Data |
deathernater | 0:a3096c3dccff | 34 | float inputLR, inputSpeed; |
deathernater | 0:a3096c3dccff | 35 | int carScrPosX = 63, carScrPosY = 120; |
deathernater | 0:a3096c3dccff | 36 | int carVel = 0, odo = 0; |
deathernater | 0:a3096c3dccff | 37 | bool redraw = true; |
deathernater | 0:a3096c3dccff | 38 | int wallY1 = 6, wallY2 = 36, wallY3 = 68, wallThickness = 8; |
deathernater | 0:a3096c3dccff | 39 | int wallsStart[3], wallsEnd[3], wallsY[3] = {wallY1, wallY2, wallY3}; |
deathernater | 0:a3096c3dccff | 40 | |
deathernater | 0:a3096c3dccff | 41 | void generateWall(int wall) { |
deathernater | 0:a3096c3dccff | 42 | float wallSeed1 = (float) rand() / RAND_MAX * 63; |
deathernater | 0:a3096c3dccff | 43 | float wallSeed2 = (float) rand() / RAND_MAX * 63; |
deathernater | 0:a3096c3dccff | 44 | int wallStart = (int) (wallSeed1 + 0.5); |
deathernater | 0:a3096c3dccff | 45 | int wallEnd = (int) (wallSeed2 + 0.5); |
deathernater | 0:a3096c3dccff | 46 | wallsStart[wall] = wallStart; |
deathernater | 0:a3096c3dccff | 47 | wallsEnd[wall] = wallEnd + wallStart; |
deathernater | 0:a3096c3dccff | 48 | if ((wallsEnd[wall] - wallsStart[wall]) > 110) { |
deathernater | 0:a3096c3dccff | 49 | generateWall(wall); |
deathernater | 0:a3096c3dccff | 50 | } |
deathernater | 0:a3096c3dccff | 51 | } |
deathernater | 0:a3096c3dccff | 52 | |
deathernater | 0:a3096c3dccff | 53 | bool updatePosition() { |
deathernater | 0:a3096c3dccff | 54 | if (jsy > 0.7 && carVel < 8) { |
deathernater | 0:a3096c3dccff | 55 | carVel += 1; |
deathernater | 0:a3096c3dccff | 56 | } else if (jsy < 0.3 && carVel > 0) { |
deathernater | 0:a3096c3dccff | 57 | carVel -= 1; |
deathernater | 0:a3096c3dccff | 58 | } |
deathernater | 0:a3096c3dccff | 59 | if (jsx > 0.55 && (carScrPosX - 4) >= 0) { |
deathernater | 0:a3096c3dccff | 60 | int delta = (int) (jsx / 0.95 * 8 + 0.5); |
deathernater | 0:a3096c3dccff | 61 | if (((carScrPosX - 4) - delta) >= 0) { |
deathernater | 0:a3096c3dccff | 62 | carScrPosX -= delta; |
deathernater | 0:a3096c3dccff | 63 | } |
deathernater | 0:a3096c3dccff | 64 | } else if (jsx < 0.45 && (carScrPosX + 4) <= 127) { |
deathernater | 0:a3096c3dccff | 65 | int delta = (int) ((1 - jsx) / 0.95 * 8 + 0.5); |
deathernater | 0:a3096c3dccff | 66 | if (((carScrPosX + 4) + delta) <= 127) { |
deathernater | 0:a3096c3dccff | 67 | carScrPosX += delta; |
deathernater | 0:a3096c3dccff | 68 | } |
deathernater | 0:a3096c3dccff | 69 | } |
deathernater | 0:a3096c3dccff | 70 | odo += carVel; |
deathernater | 0:a3096c3dccff | 71 | wallsY[0] += carVel; |
deathernater | 0:a3096c3dccff | 72 | wallsY[1] += carVel; |
deathernater | 0:a3096c3dccff | 73 | wallsY[2] += carVel; |
deathernater | 0:a3096c3dccff | 74 | //Check collision |
deathernater | 0:a3096c3dccff | 75 | for (int i = 0; i < 3; i++) { |
deathernater | 0:a3096c3dccff | 76 | if (wallsY[i] > 127) { |
deathernater | 0:a3096c3dccff | 77 | wallsY[i] = 0; |
deathernater | 0:a3096c3dccff | 78 | generateWall(i); |
deathernater | 0:a3096c3dccff | 79 | uLCD.cls(); |
deathernater | 0:a3096c3dccff | 80 | redraw = true; |
deathernater | 0:a3096c3dccff | 81 | } |
deathernater | 0:a3096c3dccff | 82 | if ((carScrPosX - 4) > wallsEnd[i] || (carScrPosX + 4) < wallsStart[i] |
deathernater | 0:a3096c3dccff | 83 | || (carScrPosY - 5) > (wallsY[i] + wallThickness) |
deathernater | 0:a3096c3dccff | 84 | || (carScrPosY + 5) < wallsY[i]) { |
deathernater | 0:a3096c3dccff | 85 | //pc.printf("No Collision\n"); |
deathernater | 0:a3096c3dccff | 86 | Thread::wait(33); |
deathernater | 0:a3096c3dccff | 87 | } else { |
deathernater | 0:a3096c3dccff | 88 | //pc.printf("Crash\n"); |
deathernater | 0:a3096c3dccff | 89 | return false; |
deathernater | 0:a3096c3dccff | 90 | } |
deathernater | 0:a3096c3dccff | 91 | } |
deathernater | 0:a3096c3dccff | 92 | return true; |
deathernater | 0:a3096c3dccff | 93 | } |
deathernater | 0:a3096c3dccff | 94 | |
deathernater | 0:a3096c3dccff | 95 | void playSound() { |
deathernater | 0:a3096c3dccff | 96 | //setup PWM hardware for a Class D style audio output |
deathernater | 0:a3096c3dccff | 97 | PWMout.period(1.0/400000.0); |
deathernater | 0:a3096c3dccff | 98 | while (true) { |
deathernater | 0:a3096c3dccff | 99 | FILE *fp = fopen("/sd/Skrillex_Diplo.wav", "r"); |
deathernater | 0:a3096c3dccff | 100 | if(fp == NULL) { |
deathernater | 0:a3096c3dccff | 101 | error("Could not open file for read\n"); |
deathernater | 0:a3096c3dccff | 102 | } |
deathernater | 0:a3096c3dccff | 103 | player.play(fp); |
deathernater | 0:a3096c3dccff | 104 | fclose(fp); |
deathernater | 0:a3096c3dccff | 105 | Thread::wait(500); |
deathernater | 0:a3096c3dccff | 106 | } |
deathernater | 0:a3096c3dccff | 107 | |
deathernater | 0:a3096c3dccff | 108 | } |
deathernater | 0:a3096c3dccff | 109 | |
deathernater | 0:a3096c3dccff | 110 | int main() { |
deathernater | 0:a3096c3dccff | 111 | audioThread.start(playSound); |
deathernater | 0:a3096c3dccff | 112 | uLCD.baudrate(3000000); //jack up baud rate to max for fast display |
deathernater | 0:a3096c3dccff | 113 | uLCD.media_init(); |
deathernater | 0:a3096c3dccff | 114 | uLCD.set_sector_address(0x003B, 0x5600); |
deathernater | 0:a3096c3dccff | 115 | uLCD.display_image(0,0); |
deathernater | 0:a3096c3dccff | 116 | uLCD.printf("Welcome to Random\nHorizons 3\nThrottle Up!\n(Push Forward)"); |
deathernater | 0:a3096c3dccff | 117 | generateWall(0); |
deathernater | 0:a3096c3dccff | 118 | generateWall(1); |
deathernater | 0:a3096c3dccff | 119 | generateWall(2); |
deathernater | 0:a3096c3dccff | 120 | int oldCarPosX = carScrPosX; |
deathernater | 0:a3096c3dccff | 121 | int oldWallsY[3] = {wallY1, wallY2, wallY3}; |
deathernater | 0:a3096c3dccff | 122 | while (jsy < 0.95) Thread::wait(33); |
deathernater | 0:a3096c3dccff | 123 | uLCD.cls(); |
deathernater | 0:a3096c3dccff | 124 | uLCD.printf("Controls:\nUp (Accel.)\nDown (Brake)\nLeft (Left)\n"); |
deathernater | 0:a3096c3dccff | 125 | uLCD.printf("Right (Right)\nDodge the Walls!!\n"); |
deathernater | 0:a3096c3dccff | 126 | Thread::wait(5000); |
deathernater | 0:a3096c3dccff | 127 | uLCD.cls(); |
deathernater | 0:a3096c3dccff | 128 | do { |
deathernater | 0:a3096c3dccff | 129 | if (oldCarPosX != carScrPosX || redraw) { |
deathernater | 0:a3096c3dccff | 130 | uLCD.filled_rectangle(oldCarPosX - 4, carScrPosY - 5, |
deathernater | 0:a3096c3dccff | 131 | oldCarPosX + 4, carScrPosY + 5, BLACK); |
deathernater | 0:a3096c3dccff | 132 | uLCD.filled_rectangle(carScrPosX - 4, carScrPosY - 5, |
deathernater | 0:a3096c3dccff | 133 | carScrPosX + 4, carScrPosY + 5, BLUE); |
deathernater | 0:a3096c3dccff | 134 | uLCD.filled_rectangle(carScrPosX - 1, carScrPosY - 3, |
deathernater | 0:a3096c3dccff | 135 | carScrPosX + 2, carScrPosY + 3, WHITE); |
deathernater | 0:a3096c3dccff | 136 | redraw = false; |
deathernater | 0:a3096c3dccff | 137 | } |
deathernater | 0:a3096c3dccff | 138 | for (int i = 0; i < 3; i++) { |
deathernater | 0:a3096c3dccff | 139 | if (oldWallsY[i] != wallsY[i]) { |
deathernater | 0:a3096c3dccff | 140 | uLCD.filled_rectangle(wallsStart[i], oldWallsY[i], |
deathernater | 0:a3096c3dccff | 141 | wallsEnd[i], oldWallsY[i] + wallThickness, BLACK); |
deathernater | 0:a3096c3dccff | 142 | uLCD.filled_rectangle(wallsStart[i], wallsY[i], |
deathernater | 0:a3096c3dccff | 143 | wallsEnd[i], wallsY[i] + wallThickness, RED); |
deathernater | 0:a3096c3dccff | 144 | oldWallsY[i] = wallsY[i]; |
deathernater | 0:a3096c3dccff | 145 | } |
deathernater | 0:a3096c3dccff | 146 | } |
deathernater | 0:a3096c3dccff | 147 | oldCarPosX = carScrPosX; |
deathernater | 0:a3096c3dccff | 148 | } while (updatePosition() && odo <= 1280); |
deathernater | 0:a3096c3dccff | 149 | |
deathernater | 0:a3096c3dccff | 150 | if (odo >= 1280) { |
deathernater | 0:a3096c3dccff | 151 | uLCD.text_string("YOU WON!", 0, 0, FONT_7X8, WHITE); |
deathernater | 0:a3096c3dccff | 152 | } else { |
deathernater | 0:a3096c3dccff | 153 | uLCD.set_sector_address(0x003B, 0x5641); |
deathernater | 0:a3096c3dccff | 154 | uLCD.display_image(0,0); |
deathernater | 0:a3096c3dccff | 155 | uLCD.text_string("Crashed:\nGAME OVER", 0, 0, FONT_7X8, WHITE); |
deathernater | 0:a3096c3dccff | 156 | } |
deathernater | 0:a3096c3dccff | 157 | } |