Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed ll16j23s_test_docs
SnakeEngine.cpp
00001 #include "SnakeEngine.h" 00002 00003 SnakeEngine::SnakeEngine() { 00004 //constructor 00005 _menu_select = 0; 00006 _map_select = 0; 00007 _pot2 = 0.5; 00008 _death = false; 00009 score = 0; 00010 00011 } 00012 00013 SnakeEngine::~SnakeEngine() 00014 { 00015 //destructor 00016 } 00017 00018 void SnakeEngine::game_init(Gamepad &pad, N5110 &lcd, FXOS8700CQ &mag){ 00019 game_reset(); //resets game 00020 transition_black(lcd); //transition animations 00021 transition_white(lcd); 00022 map_run(lcd); //displays map 00023 lcd.refresh(); 00024 _food.init(pad, lcd, mag); //initialises food (including new seed for random function 00025 _body.init(); //initialises body 00026 menu_flash(pad, 3); //flashes LEDs 00027 game_state = 3; //sets game_state to the game itself, which changes the active while loop in main.cpp 00028 } 00029 00030 00031 void SnakeEngine::game_run(Gamepad &pad, N5110 &lcd){ 00032 map_run(lcd); //displays the map and calculates relevant map collisions 00033 _body.run(pad, lcd, _death); 00034 _food.run(lcd); 00035 snake_food_collision(pad, lcd); 00036 if (_death == true) { //checks death (either snake-snake collision or snake-wall-collision) 00037 //printf("Dead!"); 00038 game_state = 4; //sets game_state to death, which changes the active while loop in main.cpp 00039 death_init(pad, lcd); //displays death menu 00040 } 00041 } 00042 00043 void SnakeEngine::snake_food_collision(Gamepad &pad, N5110 &lcd) { 00044 if (_food.x == _body.head_x && _food.y == _body.head_y){ //if coords of food and head match 00045 //printf("FOOD!"); 00046 pad.led(3,0.9); //turns on green LEDs 00047 pad.led(6,0.9); 00048 while (_food.rand_pos(pad, lcd) == false){ //while new food coordinates are in the snake/walls 00049 _food.rand_pos(pad, lcd); //choose new coords by rerunning the function 00050 //printf("Reselected food position\n"); 00051 } 00052 _body.add_length(5); //sets length increase 00053 score++; 00054 pad.led(3,0.0); //turns off green LEDs 00055 pad.led(6,0.0); 00056 } 00057 } 00058 00059 void SnakeEngine::map_run(N5110 &lcd) { 00060 switch(_map_select + 1) { //selects chosen map 00061 case 2: 00062 map2_draw(lcd); 00063 snake_map2_collision(); 00064 break; 00065 case 3: 00066 map3_draw(lcd); 00067 snake_map3_collision(); 00068 break; 00069 case 4: 00070 map4_draw(lcd); 00071 snake_map4_collision(); 00072 break; 00073 } 00074 } 00075 00076 void SnakeEngine::snake_map2_collision() { //ring map 00077 if (_body.head_x < 2 || _body.head_x > 81 || _body.head_y < 2 || _body.head_y > 45){ //if snakehead coords exceed the ring coords 00078 _death = true; 00079 } 00080 } 00081 00082 void SnakeEngine::snake_map3_collision() { //cross map 00083 if ((_body.head_x == 40 || _body.head_x == 42) && (_body.head_y < 16 || _body.head_y > 30)){ 00084 //if head is at the either of the N/S walls' x coords, and above (y=18) or below (y=30), trigger death 00085 _death = true; 00086 } else if ((_body.head_x < 16 || _body.head_x > 66) && (_body.head_y == 22 || _body.head_y == 24)){ 00087 //if head is at west of x=18 or east of x=66, and at either of the W/E wall's y coords, trigger death 00088 _death = true; 00089 } 00090 } 00091 00092 void SnakeEngine::snake_map4_collision() { //lanes 00093 _map4_location = 0; 00094 if (_body.head_x == 8 || _body.head_x == 10 || _body.head_x == 40 || _body.head_x == 42 || _body.head_x == 72 || _body.head_x == 74){ 00095 _map4_location += 1; //adjust tracker if x matches upper/lower walls 00096 } //printf("x matches upper/lower walls"); 00097 if (_body.head_y < 12 || _body.head_y > 34){ 00098 _map4_location += 3; //adjust tracker if y matches upper/lower walls 00099 } //printf("y matches upper/lower walls"); 00100 if (_body.head_x == 24 || _body.head_x == 26 || _body.head_x == 56 || _body.head_x == 58){ 00101 _map4_location += 2; //adjust tracker if x matches mid walls 00102 } //printf("x matches mid walls"); 00103 if (_body.head_y > 14 && _body.head_y < 32){ 00104 _map4_location += 2; //adjust tracker if y matches mid walls 00105 } //printf("y matches mid walls"); 00106 if (_map4_location == 4){ //tracker will only be 4 if the correct combination of arguments is triggered - ie 1+3 (upper/lower walls) or 2+2 (mid walls) 00107 _death = true; 00108 } //printf("Wall collision"); 00109 } 00110 00111 void SnakeEngine::map2_draw(N5110 &lcd){ //rings 00112 lcd.drawRect(0, 0, 84, 48,FILL_TRANSPARENT); //outer pixels of ring 00113 lcd.drawRect(1, 1, 82, 46,FILL_TRANSPARENT); //inner pixels 00114 } 00115 00116 void SnakeEngine::map3_draw(N5110 &lcd){ //cross 00117 lcd.drawRect(40, 0, 4, 16,FILL_BLACK); //N wall 00118 lcd.drawRect(68, 22, 16, 4,FILL_BLACK);//E wall 00119 lcd.drawRect(40, 32, 4, 16,FILL_BLACK);//S wall 00120 lcd.drawRect(0, 22, 16, 4,FILL_BLACK); //W wall 00121 } 00122 00123 void SnakeEngine::map4_draw(N5110 &lcd){ //lanes 00124 lcd.drawRect(8, 0, 4, 12,FILL_BLACK);//NW line 00125 lcd.drawRect(8, 36, 4, 12,FILL_BLACK);//SW line 00126 lcd.drawRect(40, 0, 4, 12,FILL_BLACK);//N-mid line 00127 lcd.drawRect(40, 36, 4, 12,FILL_BLACK);//S-mid line 00128 lcd.drawRect(72, 0, 4, 12,FILL_BLACK);//NE line 00129 lcd.drawRect(72, 36, 4, 12,FILL_BLACK);//SE line 00130 lcd.drawRect(24, 16, 4, 16,FILL_BLACK);//mid-W line 00131 lcd.drawRect(56, 16, 4, 16,FILL_BLACK);//mid-E line 00132 } 00133 00134 void SnakeEngine::transition_black(N5110 &lcd) { 00135 for (int j = 0; j < 21; j += 4) { //j iterator controls the size and location of current loop 00136 //printf("j: %d\n", j); 00137 for (int i = 1; i < 84 - (2*j); i += 2) { //i iterator controls length of rectangles 00138 lcd.drawRect(j, j, 1 + i, 4, FILL_BLACK); //top horizontal rectangle grows to the right by adding i iterator to width 00139 lcd.drawRect(83 - j - i, 44 - j, 1 + i, 4, FILL_BLACK); //bottom horizontal rectangle grows to the left by subtracting i iterator from x position, 00140 //and adding i iterator to width 00141 wait_ms(5); 00142 lcd.refresh(); //refreshes screen without clearing it to maintain previous loops' rectangles 00143 } 00144 for (int i = 1; i < 43 - (2*j); i += 2) { //i iterator controls length of rectangles 00145 lcd.drawRect(80 - j, 4 + j, 4, i,FILL_BLACK); //right vertical rectangle grows down by adding i iterator to height 00146 lcd.drawRect(j, 44 - j - i, 4, i,FILL_BLACK); //left vertical rectangle grows up by subtracting i iterator from y position, adds i to height 00147 wait_ms(5); 00148 lcd.refresh(); //refreshes screen without clearing it to maintain previous loops 00149 } 00150 } 00151 } 00152 00153 void SnakeEngine::transition_white(N5110 &lcd) { 00154 //functionally same as black transition function 00155 for (int j = 0; j < 21; j += 4) { //j iterator controls the size and location of current loop 00156 //printf("j: %d\n", j); 00157 for (int i = 1; i < 84 - (2*j); i += 2) { //i iterator controls length of rectangles 00158 lcd.drawRect(j, j, 1 + i, 4, FILL_WHITE); //top horizontal rectangle grows to the right by adding i iterator to width 00159 lcd.drawRect(83 - j - i, 44 - j, 1 + i, 4, FILL_WHITE); //bottom horizontal rectangle grows to the left by subtracting i iterator from x position, 00160 //and adding i iterator to width 00161 wait_ms(5); 00162 lcd.refresh(); //refreshes screen without clearing it to maintain previous loops' rectangles 00163 } 00164 for (int i = 1; i < 43 - (2*j); i += 2) { //i iterator controls length of rectangles 00165 lcd.drawRect(80 - j, 4 + j, 4, i,FILL_WHITE); //right vertical rectangle grows down by adding i iterator to height 00166 lcd.drawRect(j, 44 - j - i, 4, i,FILL_WHITE); //left vertical rectangle grows up by subtracting i iterator from y position, adds i to height 00167 wait_ms(5); 00168 lcd.refresh(); //refreshes screen without clearing it to maintain previous loops 00169 } 00170 } 00171 } 00172 00173 void SnakeEngine::menu1_init(Gamepad &pad, N5110 &lcd){ 00174 contrast(pad, lcd); //adjusts contrast before transitions 00175 transition_black(lcd); 00176 transition_white(lcd); 00177 lcd.refresh(); 00178 //printf("Menu 1\n"); 00179 lcd.printString("SNAKE",27,0); //displays relevant text 00180 lcd.printString("Play",30,2); 00181 lcd.drawCircle(24,19,3,FILL_TRANSPARENT); //draws empty circles for option display 00182 lcd.printString("Maps",30,3); 00183 lcd.drawCircle(24,27,3,FILL_TRANSPARENT); 00184 lcd.refresh(); 00185 menu_flash(pad, 2); //flashes orange LEDs 00186 } 00187 00188 void SnakeEngine::menu1_select(Gamepad &pad, N5110 &lcd, FXOS8700CQ &mag){ 00189 //printf("Menu 1\n"); 00190 if (pad.X_held() == true){ //detect if 'up' selection 00191 _menu_select--; 00192 } else if (pad.B_held() == true){ //detect if 'down' selection 00193 _menu_select++; 00194 } 00195 _menu_select = ((_menu_select % 2) + 2) % 2; //wrap around numbers, ie down on 1 goes to 0 and up on 0 goes to 1 00196 select_circles(lcd, _menu_select + 1); //draw black circle in selected option 00197 //printf("Option: %d\n", _menu_select + 1); 00198 00199 if (pad.A_held() == true){ //if option 1 selected and 'A' held 00200 if (_menu_select == 0){ 00201 game_init(pad, lcd, mag); //Initialise game 00202 } else { //otherwise must be option 2 00203 menu2_init(pad, lcd); //Initialise menu 2 00204 menu_flash(pad, 2); //flashes orange LEDs 00205 } 00206 } 00207 } 00208 00209 void SnakeEngine::menu2_init(Gamepad &pad, N5110 &lcd){ 00210 //printf("Menu 2\n"); 00211 lcd.clear(); 00212 lcd.printString(" MAPS",0,0); //displays relevant text 00213 lcd.printString("Empty",30,2); 00214 lcd.drawCircle(24,19,3,FILL_TRANSPARENT); //draws empty circles for option display 00215 lcd.printString("Ring",30,3); 00216 lcd.drawCircle(24,27,3,FILL_TRANSPARENT); 00217 lcd.printString("Cross",30,4); 00218 lcd.drawCircle(24,35,3,FILL_TRANSPARENT); 00219 lcd.printString("Lanes",30,5); 00220 lcd.drawCircle(24,43,3,FILL_TRANSPARENT); 00221 lcd.refresh(); 00222 game_state = 2; //sets game_state to menu 2, which changes the active while loop in main.cpp 00223 } 00224 00225 void SnakeEngine::menu2_select(Gamepad &pad, N5110 &lcd, FXOS8700CQ &mag){ 00226 00227 select_circles(lcd, _map_select+1); 00228 00229 //printf("Menu 2\n"); 00230 if (pad.X_held() == true){ 00231 _map_select--; 00232 } else if (pad.B_held() == true){ 00233 _map_select++; 00234 } else if (pad.Y_held() == true){ 00235 preview(pad, lcd); //allows short preview of map to be displayed 00236 } else if (pad.A_held() == true){ 00237 game_init(pad, lcd, mag); //intialises game 00238 } 00239 //printf("Map: %d\n", _map_select); 00240 _map_select = ((_map_select % 4) + 4) % 4; //wrap around numbers, ie down on 3 goes to 0 and up on 0 goes to 3 00241 } 00242 00243 00244 void SnakeEngine::death_init(Gamepad &pad, N5110 &lcd){ 00245 _death = 0; //resets death flag 00246 _menu_select = 0; //resets menu select so 'play again' is default 00247 transition_black(lcd); 00248 transition_white(lcd); 00249 //printf("Game over\n"); 00250 lcd.printString(" GAME OVER",3,0); //displays relevant text 00251 lcd.printString(" Score:",0,1); 00252 char buffer[14]; //creates a buffer for the score 00253 sprintf(buffer," %2d",score); 00254 lcd.printString(buffer,0,2); 00255 lcd.printString("Again!",30,4); 00256 lcd.drawCircle(24,35,3,FILL_TRANSPARENT); //draws empty circles for option selection 00257 lcd.printString("Maps",30,5); 00258 lcd.drawCircle(24,43,3,FILL_TRANSPARENT); 00259 lcd.refresh(); 00260 menu_flash(pad, 1); //flashes red LEDs 00261 } 00262 00263 void SnakeEngine::death_select(Gamepad &pad, N5110 &lcd, FXOS8700CQ &mag){ 00264 //printf("Menu 1\n"); 00265 if (pad.X_held() == true){ //detect if 'up' selection 00266 _menu_select--; 00267 } else if (pad.B_held() == true){ //detect if 'down' selection 00268 _menu_select++; 00269 } 00270 _menu_select = ((_menu_select % 2) + 2) % 2; //wrap around numbers, ie down on 2 goes to 1 and up on 1 goes to 2 00271 select_circles(lcd, _menu_select + 3); //draw black circle in selected option 00272 //printf("Option: %d\n", _menu_select + 1); 00273 00274 if (pad.A_held() == true){ //if option 1 selected and 'A' held 00275 if (_menu_select == 0){ 00276 game_init(pad, lcd, mag); 00277 game_state = 3; 00278 } else { 00279 menu2_init(pad, lcd); 00280 menu_flash(pad, 2); 00281 game_state = 2; 00282 } 00283 } 00284 } 00285 00286 void SnakeEngine::select_circles(N5110 &lcd, int line) { 00287 for(int i = 19; i < 52; i += 8) { //iterates over all the circle options' y values 00288 lcd.drawCircle(24,i,2,FILL_WHITE); //remove previous options' black circles 00289 } 00290 lcd.drawCircle(24, 11 + line * 8, 2, FILL_BLACK); //draws black circle in relevant option's blank circle 00291 lcd.refresh(); 00292 wait_ms(200); 00293 } 00294 00295 void SnakeEngine::preview(Gamepad &pad, N5110 &lcd){ 00296 lcd.clear(); 00297 switch(_map_select + 1) { //selects relevant map 00298 case 1: 00299 lcd.clear(); 00300 lcd.printString("(Empty)",21,2); 00301 break; 00302 case 2: 00303 map2_draw(lcd); 00304 //lcd.printString("Ring",30,2); 00305 break; 00306 case 3: 00307 map3_draw(lcd); 00308 //lcd.printString("Cross",27,2); 00309 break; 00310 case 4: 00311 map4_draw(lcd); 00312 //lcd.printString("Spots",27,2); 00313 break; 00314 } 00315 lcd.refresh(); 00316 pad.led(2, 1); 00317 pad.led(5, 1); 00318 wait_ms(1000); //displays for 1 second 00319 pad.led(2, 0); 00320 pad.led(5, 0); 00321 lcd.clear(); 00322 menu2_init(pad, lcd); //re-initialises menu 2 00323 } 00324 00325 void SnakeEngine::contrast(Gamepad &pad, N5110 &lcd){ 00326 _pot2 = pad.read_pot2(); 00327 lcd.setContrast(0.25 + _pot2 * 0.5); //maps pot value to range 0.25 - 0.75 00328 //printf("Contrast: %f\n", 0.25 + _pot2 * 0.5); 00329 } 00330 00331 void SnakeEngine::menu_flash(Gamepad &pad, int led){ 00332 for(int i = 1; i < 7; i++){ 00333 pad.led(led, i % 2); //flash left side LEDs - odd numbers become 1 to turn on, even numbers become 0 to turn off 00334 pad.led(led + 3, i % 2); //flash right side LEDs 00335 wait_ms(100); 00336 } 00337 } 00338 00339 void SnakeEngine::game_reset(){ 00340 score = 0; 00341 _body.reset(); 00342 } 00343
Generated on Fri Jul 15 2022 20:20:44 by
1.7.2