Revenge of the Mouse
Dependencies: 4DGL-uLCD-SE EthernetInterface Game_Synchronizer LCD_fonts MMA8452 SDFileSystem mbed-rtos mbed wave_player
Fork of 2035_Tanks_Shell by
main.cpp@12:088a8203a9bb, 2015-10-25 (annotated)
- Committer:
- jford38
- Date:
- Sun Oct 25 17:57:39 2015 +0000
- Revision:
- 12:088a8203a9bb
- Parent:
- 11:f455e907baba
- Child:
- 14:36c306e26317
All kinds of stuff. Basically, things explode when you hit them now, and tanks can't drive through side of the screen.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jford38 | 6:3be57cf4bd33 | 1 | // Student Side. |
jford38 | 0:899c85cd266f | 2 | |
jford38 | 0:899c85cd266f | 3 | #include "mbed.h" |
jford38 | 6:3be57cf4bd33 | 4 | #include "game_synchronizer.h" |
jford38 | 12:088a8203a9bb | 5 | #include "MMA8452.h" // for accelerometer |
jford38 | 10:5da9b27e050e | 6 | #include "math.h" |
jford38 | 12:088a8203a9bb | 7 | #include <vector> |
jford38 | 10:5da9b27e050e | 8 | |
jford38 | 10:5da9b27e050e | 9 | #define SKY_COLOR 0x7EC0EE |
jford38 | 10:5da9b27e050e | 10 | #define GND_COLOR 0x66CD00 |
jford38 | 10:5da9b27e050e | 11 | #define TANK_RED 0xCD0000 |
jford38 | 10:5da9b27e050e | 12 | #define TANK_BLUE 0x000080 |
jford38 | 10:5da9b27e050e | 13 | #define PI 3.1415926535797 |
jford38 | 6:3be57cf4bd33 | 14 | |
jford38 | 6:3be57cf4bd33 | 15 | DigitalOut led1(LED1); |
jford38 | 6:3be57cf4bd33 | 16 | DigitalOut led2(LED2); |
jford38 | 6:3be57cf4bd33 | 17 | DigitalOut led3(LED3); |
jford38 | 6:3be57cf4bd33 | 18 | DigitalOut led4(LED4); |
jford38 | 0:899c85cd266f | 19 | |
jford38 | 6:3be57cf4bd33 | 20 | DigitalIn pb_l(p24); // left button |
jford38 | 6:3be57cf4bd33 | 21 | DigitalIn pb_r(p21); // right button |
jford38 | 6:3be57cf4bd33 | 22 | DigitalIn pb_u(p22); // up button |
jford38 | 6:3be57cf4bd33 | 23 | DigitalIn pb_d(p23); // down button |
jford38 | 6:3be57cf4bd33 | 24 | |
jford38 | 12:088a8203a9bb | 25 | //MMA8452 acc(p28, p27, 100000); // Accelerometer |
jford38 | 8:e6dd05393290 | 26 | uLCD_4DGL uLCD(p9,p10,p11); // LCD (serial tx, serial rx, reset pin;) |
jford38 | 8:e6dd05393290 | 27 | Game_Synchronizer sync(PLAYER1); // (tx, rx, rst, player mode) |
jford38 | 0:899c85cd266f | 28 | |
jford38 | 12:088a8203a9bb | 29 | Timer frame_timer; |
jford38 | 12:088a8203a9bb | 30 | |
jford38 | 6:3be57cf4bd33 | 31 | // For debug only. Don't use in production code. It will slow your game down a lot. |
jford38 | 6:3be57cf4bd33 | 32 | Serial pc(USBTX, USBRX); |
jford38 | 0:899c85cd266f | 33 | |
jford38 | 7:9506f2d84162 | 34 | |
jford38 | 7:9506f2d84162 | 35 | int game_menu(void) { |
jford38 | 7:9506f2d84162 | 36 | |
jford38 | 7:9506f2d84162 | 37 | // Figure out what mode the game will be run in. |
jford38 | 9:ee330b1ba394 | 38 | |
jford38 | 10:5da9b27e050e | 39 | uLCD.current_orientation = IS_LANDSCAPE; |
jford38 | 9:ee330b1ba394 | 40 | uLCD.locate(0,1); |
jford38 | 9:ee330b1ba394 | 41 | uLCD.puts("Select Mode:"); |
jford38 | 9:ee330b1ba394 | 42 | uLCD.locate(0,3); |
jford38 | 9:ee330b1ba394 | 43 | uLCD.puts(" Single-Player:"); |
jford38 | 9:ee330b1ba394 | 44 | uLCD.locate(0,4); |
jford38 | 9:ee330b1ba394 | 45 | uLCD.puts(" Left Button"); |
jford38 | 9:ee330b1ba394 | 46 | uLCD.locate(0,6); |
jford38 | 9:ee330b1ba394 | 47 | uLCD.puts(" Multi-Player:"); |
jford38 | 9:ee330b1ba394 | 48 | uLCD.locate(0,7); |
jford38 | 9:ee330b1ba394 | 49 | uLCD.puts(" Right Button"); |
jford38 | 7:9506f2d84162 | 50 | // Right button -> Multiplayer |
jford38 | 7:9506f2d84162 | 51 | // Left button -> Single player |
jford38 | 7:9506f2d84162 | 52 | while(1) { |
jford38 | 9:ee330b1ba394 | 53 | if(!pb_r) { return MULTI_PLAYER; } |
jford38 | 9:ee330b1ba394 | 54 | if(!pb_l) { return SINGLE_PLAYER; } |
jford38 | 7:9506f2d84162 | 55 | } |
jford38 | 7:9506f2d84162 | 56 | } |
jford38 | 7:9506f2d84162 | 57 | |
jford38 | 10:5da9b27e050e | 58 | void map_init() { |
jford38 | 10:5da9b27e050e | 59 | sync.background_color(SKY_COLOR); |
jford38 | 10:5da9b27e050e | 60 | sync.cls(); |
jford38 | 10:5da9b27e050e | 61 | sync.filled_rectangle(0,0,128,20, GND_COLOR); |
jford38 | 10:5da9b27e050e | 62 | sync.filled_rectangle(59, 20, 69, 60, BLACK); |
jford38 | 10:5da9b27e050e | 63 | sync.update(); |
jford38 | 10:5da9b27e050e | 64 | } |
jford38 | 10:5da9b27e050e | 65 | |
jford38 | 10:5da9b27e050e | 66 | class Tank { |
jford38 | 10:5da9b27e050e | 67 | public: |
jford38 | 10:5da9b27e050e | 68 | int x, y; |
jford38 | 10:5da9b27e050e | 69 | int w; |
jford38 | 10:5da9b27e050e | 70 | int h; |
jford38 | 10:5da9b27e050e | 71 | int tank_color; |
jford38 | 10:5da9b27e050e | 72 | float barrel_theta; |
jford38 | 10:5da9b27e050e | 73 | int barrel_length; |
jford38 | 10:5da9b27e050e | 74 | int wheel_rad; |
jford38 | 10:5da9b27e050e | 75 | |
jford38 | 12:088a8203a9bb | 76 | |
jford38 | 10:5da9b27e050e | 77 | Tank(int sx, int sy, int width, int height, int color) { |
jford38 | 10:5da9b27e050e | 78 | x = sx; y = sy; |
jford38 | 10:5da9b27e050e | 79 | w = width; h = height; |
jford38 | 10:5da9b27e050e | 80 | tank_color = color; |
jford38 | 10:5da9b27e050e | 81 | barrel_theta = PI/4.0; |
jford38 | 10:5da9b27e050e | 82 | barrel_length = w; |
jford38 | 10:5da9b27e050e | 83 | wheel_rad = 2.0; |
jford38 | 10:5da9b27e050e | 84 | draw(); |
jford38 | 10:5da9b27e050e | 85 | } |
jford38 | 12:088a8203a9bb | 86 | int min_x(void) { |
jford38 | 12:088a8203a9bb | 87 | int barrel_extent = (-barrel_length*cos(barrel_theta) > w/2.0) ? barrel_length*cos(barrel_theta) + w/2.0 : 0; |
jford38 | 12:088a8203a9bb | 88 | return x + barrel_extent; } |
jford38 | 10:5da9b27e050e | 89 | int min_y(void) { return y; } |
jford38 | 12:088a8203a9bb | 90 | int max_x(void) { |
jford38 | 12:088a8203a9bb | 91 | int barrel_extent = (barrel_length*cos(barrel_theta) > w/2.0) ? barrel_length*cos(barrel_theta) : w/2.0; |
jford38 | 12:088a8203a9bb | 92 | return x + w/2.0 + barrel_extent; } |
jford38 | 12:088a8203a9bb | 93 | int max_y(void) { |
jford38 | 12:088a8203a9bb | 94 | int barrel_extent = (sin(barrel_theta) > 0) ? barrel_length*sin(barrel_theta) : 0; |
jford38 | 12:088a8203a9bb | 95 | return y + h + wheel_rad + barrel_extent; } |
jford38 | 12:088a8203a9bb | 96 | |
jford38 | 12:088a8203a9bb | 97 | void barrel_end(int& bx, int& by) { |
jford38 | 12:088a8203a9bb | 98 | bx = x + w/2.0 + (barrel_length+1)*cos(barrel_theta); |
jford38 | 12:088a8203a9bb | 99 | by = y+h+wheel_rad + (barrel_length+1)*sin(barrel_theta); |
jford38 | 12:088a8203a9bb | 100 | } |
jford38 | 10:5da9b27e050e | 101 | |
jford38 | 11:f455e907baba | 102 | void reposition(int new_x, int new_y, float new_theta) { |
jford38 | 12:088a8203a9bb | 103 | float old_theta = barrel_theta; |
jford38 | 12:088a8203a9bb | 104 | int old_x = x; |
jford38 | 12:088a8203a9bb | 105 | int old_y = y; |
jford38 | 12:088a8203a9bb | 106 | int minx = min_x(); |
jford38 | 12:088a8203a9bb | 107 | int miny = min_y(); |
jford38 | 12:088a8203a9bb | 108 | int maxx = max_x(); |
jford38 | 12:088a8203a9bb | 109 | int maxy = max_y(); |
jford38 | 12:088a8203a9bb | 110 | |
jford38 | 12:088a8203a9bb | 111 | x = new_x; y = new_y; barrel_theta = new_theta - (int)(new_theta/PI)*PI; |
jford38 | 12:088a8203a9bb | 112 | |
jford38 | 12:088a8203a9bb | 113 | if(min_x() < 0 || max_x() > 128) { |
jford38 | 12:088a8203a9bb | 114 | x = old_x; y = old_y; barrel_theta = old_theta; |
jford38 | 12:088a8203a9bb | 115 | draw(); |
jford38 | 12:088a8203a9bb | 116 | return; |
jford38 | 12:088a8203a9bb | 117 | } |
jford38 | 12:088a8203a9bb | 118 | |
jford38 | 12:088a8203a9bb | 119 | sync.filled_rectangle(minx, miny, maxx, maxy, SKY_COLOR); |
jford38 | 12:088a8203a9bb | 120 | sync.line(old_x + w/2.0, old_y+h+wheel_rad, old_x + w/2.0 + 1 + barrel_length*cos(old_theta), old_y+h + barrel_length*sin(old_theta), SKY_COLOR); |
jford38 | 10:5da9b27e050e | 121 | draw(); |
jford38 | 10:5da9b27e050e | 122 | } |
jford38 | 10:5da9b27e050e | 123 | void draw() { |
jford38 | 10:5da9b27e050e | 124 | sync.line(x + w/2.0, y+h+wheel_rad, x + w/2.0 + barrel_length*cos(barrel_theta), y+h+wheel_rad + barrel_length*sin(barrel_theta), BLACK); |
jford38 | 10:5da9b27e050e | 125 | sync.filled_rectangle(x, y+wheel_rad, x+w, y+h+wheel_rad, tank_color); |
jford38 | 10:5da9b27e050e | 126 | sync.filled_circle(x+wheel_rad, y+wheel_rad, wheel_rad, BLACK); |
jford38 | 10:5da9b27e050e | 127 | sync.filled_circle(x+w-wheel_rad, y+wheel_rad, wheel_rad, BLACK); |
jford38 | 12:088a8203a9bb | 128 | } |
jford38 | 12:088a8203a9bb | 129 | }; |
jford38 | 12:088a8203a9bb | 130 | |
jford38 | 12:088a8203a9bb | 131 | int convert24to16bpp(int col_24) { |
jford38 | 12:088a8203a9bb | 132 | int b = col_24 & 0xFF; |
jford38 | 12:088a8203a9bb | 133 | int g = (col_24 >> 8) & 0xFF; |
jford38 | 12:088a8203a9bb | 134 | int r = (col_24 >> 16)& 0xFF; |
jford38 | 12:088a8203a9bb | 135 | |
jford38 | 12:088a8203a9bb | 136 | r >>= 3; |
jford38 | 12:088a8203a9bb | 137 | g >>= 2; |
jford38 | 12:088a8203a9bb | 138 | b >>= 3; |
jford38 | 12:088a8203a9bb | 139 | |
jford38 | 12:088a8203a9bb | 140 | return r<<11 | g<<5 | b; |
jford38 | 12:088a8203a9bb | 141 | } |
jford38 | 12:088a8203a9bb | 142 | |
jford38 | 12:088a8203a9bb | 143 | class Bullet{ |
jford38 | 12:088a8203a9bb | 144 | public: |
jford38 | 12:088a8203a9bb | 145 | int x0; |
jford38 | 12:088a8203a9bb | 146 | int y0; |
jford38 | 12:088a8203a9bb | 147 | float vx0; |
jford38 | 12:088a8203a9bb | 148 | float vy0; |
jford38 | 12:088a8203a9bb | 149 | int x; |
jford38 | 12:088a8203a9bb | 150 | int y; |
jford38 | 12:088a8203a9bb | 151 | int speed; |
jford38 | 12:088a8203a9bb | 152 | float time; |
jford38 | 12:088a8203a9bb | 153 | bool in_flight; |
jford38 | 12:088a8203a9bb | 154 | |
jford38 | 12:088a8203a9bb | 155 | Tank* tank; |
jford38 | 12:088a8203a9bb | 156 | |
jford38 | 12:088a8203a9bb | 157 | Bullet(Tank* t) { |
jford38 | 12:088a8203a9bb | 158 | tank = t; |
jford38 | 12:088a8203a9bb | 159 | speed = 30; |
jford38 | 12:088a8203a9bb | 160 | in_flight = false; |
jford38 | 10:5da9b27e050e | 161 | } |
jford38 | 12:088a8203a9bb | 162 | void shoot(void) { |
jford38 | 12:088a8203a9bb | 163 | if(in_flight) {return;} |
jford38 | 12:088a8203a9bb | 164 | time = 0; |
jford38 | 12:088a8203a9bb | 165 | tank->barrel_end(x0, y0); |
jford38 | 12:088a8203a9bb | 166 | x = x0; y = y0; |
jford38 | 12:088a8203a9bb | 167 | vx0 = speed*cos(tank->barrel_theta); |
jford38 | 12:088a8203a9bb | 168 | vy0 = speed*sin(tank->barrel_theta); |
jford38 | 12:088a8203a9bb | 169 | in_flight = true; |
jford38 | 12:088a8203a9bb | 170 | } |
jford38 | 12:088a8203a9bb | 171 | |
jford38 | 12:088a8203a9bb | 172 | void time_step(float dt) { |
jford38 | 12:088a8203a9bb | 173 | if(!in_flight) {return;} |
jford38 | 12:088a8203a9bb | 174 | time += dt; |
jford38 | 12:088a8203a9bb | 175 | int new_x = x0 + vx0*time; |
jford38 | 12:088a8203a9bb | 176 | int new_y = y0 + vy0*time + 0.5*(-9.81)*time*time; |
jford38 | 12:088a8203a9bb | 177 | |
jford38 | 12:088a8203a9bb | 178 | if(new_x == x && new_y == y) { |
jford38 | 12:088a8203a9bb | 179 | return; |
jford38 | 12:088a8203a9bb | 180 | } |
jford38 | 12:088a8203a9bb | 181 | |
jford38 | 12:088a8203a9bb | 182 | if(new_x < 0 || new_x > 128 || new_y < 0 || new_y > 128) { |
jford38 | 12:088a8203a9bb | 183 | in_flight = false; |
jford38 | 12:088a8203a9bb | 184 | return; |
jford38 | 12:088a8203a9bb | 185 | } |
jford38 | 12:088a8203a9bb | 186 | |
jford38 | 12:088a8203a9bb | 187 | int col = sync.read_pixel(new_x, new_y); |
jford38 | 12:088a8203a9bb | 188 | if(col != convert24to16bpp(SKY_COLOR)) { |
jford38 | 12:088a8203a9bb | 189 | if(col == convert24to16bpp(TANK_BLUE)) { |
jford38 | 12:088a8203a9bb | 190 | pc.printf("Player 1 wins!\n"); |
jford38 | 12:088a8203a9bb | 191 | } |
jford38 | 12:088a8203a9bb | 192 | sync.pixel(x, y, SKY_COLOR); |
jford38 | 12:088a8203a9bb | 193 | sync.filled_circle(new_x, new_y, 4, SKY_COLOR); |
jford38 | 12:088a8203a9bb | 194 | in_flight = false; |
jford38 | 12:088a8203a9bb | 195 | return; |
jford38 | 12:088a8203a9bb | 196 | } |
jford38 | 12:088a8203a9bb | 197 | sync.pixel(x, y, SKY_COLOR); |
jford38 | 12:088a8203a9bb | 198 | |
jford38 | 12:088a8203a9bb | 199 | x = new_x; |
jford38 | 12:088a8203a9bb | 200 | y = new_y; |
jford38 | 12:088a8203a9bb | 201 | sync.pixel(x, y, BLACK); |
jford38 | 12:088a8203a9bb | 202 | } |
jford38 | 10:5da9b27e050e | 203 | }; |
jford38 | 10:5da9b27e050e | 204 | |
jford38 | 12:088a8203a9bb | 205 | |
jford38 | 6:3be57cf4bd33 | 206 | void game_init(void) { |
jford38 | 6:3be57cf4bd33 | 207 | |
jford38 | 6:3be57cf4bd33 | 208 | led1 = 0; led2 = 0; led3 = 0; led4 = 0; |
jford38 | 6:3be57cf4bd33 | 209 | |
jford38 | 6:3be57cf4bd33 | 210 | pb_l.mode(PullUp); |
jford38 | 6:3be57cf4bd33 | 211 | pb_r.mode(PullUp); |
jford38 | 6:3be57cf4bd33 | 212 | pb_u.mode(PullUp); |
jford38 | 6:3be57cf4bd33 | 213 | pb_d.mode(PullUp); |
jford38 | 6:3be57cf4bd33 | 214 | |
jford38 | 6:3be57cf4bd33 | 215 | pc.printf("\033[2J\033[0;0H"); // Clear the terminal screen. |
jford38 | 6:3be57cf4bd33 | 216 | pc.printf("I'm alive! Player 1\n"); // Let us know you made it this far. |
jford38 | 7:9506f2d84162 | 217 | int mode = game_menu(); |
jford38 | 9:ee330b1ba394 | 218 | sync.init(&uLCD, mode); // Connect to the other player. |
jford38 | 10:5da9b27e050e | 219 | map_init(); |
jford38 | 6:3be57cf4bd33 | 220 | pc.printf("Initialized...\n"); // Let us know you finished initializing. |
jford38 | 6:3be57cf4bd33 | 221 | } |
jford38 | 6:3be57cf4bd33 | 222 | |
jford38 | 0:899c85cd266f | 223 | int main (void) { |
jford38 | 8:e6dd05393290 | 224 | int* p2_buttons; |
jford38 | 8:e6dd05393290 | 225 | |
jford38 | 8:e6dd05393290 | 226 | game_init(); |
jford38 | 8:e6dd05393290 | 227 | |
jford38 | 12:088a8203a9bb | 228 | Tank t1(4, 21, 12, 8, TANK_RED); |
jford38 | 12:088a8203a9bb | 229 | Tank t2(111, 21, 12, 8, TANK_BLUE); |
jford38 | 12:088a8203a9bb | 230 | Bullet b1(&t1); |
jford38 | 12:088a8203a9bb | 231 | Bullet b2(&t2); |
jford38 | 12:088a8203a9bb | 232 | |
jford38 | 5:cfec780c935b | 233 | |
jford38 | 12:088a8203a9bb | 234 | frame_timer.start(); |
jford38 | 0:899c85cd266f | 235 | while(1) { |
jford38 | 12:088a8203a9bb | 236 | |
jford38 | 12:088a8203a9bb | 237 | //double acc_x, acc_y, acc_z; |
jford38 | 12:088a8203a9bb | 238 | //acc.readXYZGravity(&acc_x,&acc_y,&acc_z); //read accelerometer |
jford38 | 12:088a8203a9bb | 239 | //pc.printf("ACCELERATION X:%f Y:%f Z:%f\n", acc_x, acc_y, acc_z); |
jford38 | 8:e6dd05393290 | 240 | |
jford38 | 8:e6dd05393290 | 241 | p2_buttons = sync.get_button_state(); |
jford38 | 8:e6dd05393290 | 242 | led1 = p2_buttons[0] ^ !pb_u; |
jford38 | 8:e6dd05393290 | 243 | led2 = p2_buttons[1] ^ !pb_r; |
jford38 | 8:e6dd05393290 | 244 | led3 = p2_buttons[2] ^ !pb_d; |
jford38 | 8:e6dd05393290 | 245 | led4 = p2_buttons[3] ^ !pb_l; |
jford38 | 11:f455e907baba | 246 | |
jford38 | 11:f455e907baba | 247 | if(!pb_l) t1.reposition(t1.x-1, t1.y, t1.barrel_theta); |
jford38 | 11:f455e907baba | 248 | if(!pb_r) t1.reposition(t1.x+1, t1.y, t1.barrel_theta); |
jford38 | 11:f455e907baba | 249 | if(p2_buttons[3]) t2.reposition(t2.x-1, t2.y, t2.barrel_theta); |
jford38 | 11:f455e907baba | 250 | if(p2_buttons[1]) t2.reposition(t2.x+1, t2.y, t2.barrel_theta); |
jford38 | 11:f455e907baba | 251 | |
jford38 | 12:088a8203a9bb | 252 | //if(!pb_d) t1.reposition(t1.x, t1.y, t1.barrel_theta-PI/30.0); |
jford38 | 12:088a8203a9bb | 253 | if(!pb_u) t1.reposition(t1.x, t1.y, t1.barrel_theta+PI/30.0); |
jford38 | 11:f455e907baba | 254 | if(p2_buttons[0]) t2.reposition(t2.x, t2.y, t2.barrel_theta+PI/30.0); |
jford38 | 11:f455e907baba | 255 | if(p2_buttons[2]) t2.reposition(t2.x, t2.y, t2.barrel_theta-PI/30.0); |
jford38 | 11:f455e907baba | 256 | |
jford38 | 12:088a8203a9bb | 257 | if(!pb_d) { b1.shoot(); } |
jford38 | 12:088a8203a9bb | 258 | |
jford38 | 12:088a8203a9bb | 259 | b1.time_step(0.01); |
jford38 | 12:088a8203a9bb | 260 | //b2.time_step(1); |
jford38 | 12:088a8203a9bb | 261 | frame_timer.reset(); |
jford38 | 11:f455e907baba | 262 | |
jford38 | 12:088a8203a9bb | 263 | sync.update(); |
jford38 | 3:3ddefff03cb2 | 264 | } |
jford38 | 0:899c85cd266f | 265 | } |