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
Diff: SnakeEngine/SnakeEngine.cpp
- Revision:
- 10:a2d643b3c782
- Parent:
- 9:0571880085cc
--- a/SnakeEngine/SnakeEngine.cpp Mon May 25 20:31:52 2020 +0000 +++ b/SnakeEngine/SnakeEngine.cpp Tue May 26 23:25:09 2020 +0000 @@ -2,12 +2,11 @@ SnakeEngine::SnakeEngine() { //constructor - score = 0; _menu_select = 0; _map_select = 0; - _game_state = 1; _pot2 = 0.5; _death = false; + score = 0; } @@ -17,48 +16,49 @@ } void SnakeEngine::game_init(Gamepad &pad, N5110 &lcd, FXOS8700CQ &mag){ - transition_black(lcd); + game_reset(); //resets game + transition_black(lcd); //transition animations transition_white(lcd); - map_run(lcd); - _food.init(mag); - _body.init(); - _food.rand_pos(pad, lcd); - menu_flash(pad, 3); + map_run(lcd); //displays map + lcd.refresh(); + _food.init(pad, lcd, mag); //initialises food (including new seed for random function + _body.init(); //initialises body + menu_flash(pad, 3); //flashes LEDs + game_state = 3; //sets game_state to the game itself, which changes the active while loop in main.cpp } void SnakeEngine::game_run(Gamepad &pad, N5110 &lcd){ - //input??? - map_run(lcd); - _body.run(pad, lcd, _death); - _food.run(lcd); - snake_food_collision(pad, lcd, _body._length); - if (_death == true) { - printf("Dead!"); - _game_state = 4; - death_init(pad, lcd); + map_run(lcd); //displays the map and calculates relevant map collisions + _body.run(pad, lcd, _death); + _food.run(lcd); + snake_food_collision(pad, lcd); + if (_death == true) { //checks death (either snake-snake collision or snake-wall-collision) + //printf("Dead!"); + game_state = 4; //sets game_state to death, which changes the active while loop in main.cpp + death_init(pad, lcd); //displays death menu } //snake-wall collision } -void SnakeEngine::snake_food_collision(Gamepad &pad, N5110 &lcd, int &_length) { - if (_food._x == _body._x_head && _food._y == _body._y_head){ +void SnakeEngine::snake_food_collision(Gamepad &pad, N5110 &lcd) { + if (_food._x == _body._x_head && _food._y == _body._y_head){ //if coords of food and head match //printf("FOOD!"); - pad.led(3,0.9); + pad.led(3,0.9); //turns on green LEDs pad.led(6,0.9); - while (_food.rand_pos(pad, lcd) == false){ - _food.rand_pos(pad, lcd); - printf("Reselected food position\n"); + while (_food.rand_pos(pad, lcd) == false){ //while new food coordinates are in the snake/walls + _food.rand_pos(pad, lcd); //choose new coords by rerunning the function + //printf("Reselected food position\n"); } - _body.add_length(5); - score++; - pad.led(3,0.0); + _body.add_length(5); //sets length increase + score++; + pad.led(3,0.0); //turns off green LEDs pad.led(6,0.0); } } void SnakeEngine::map_run(N5110 &lcd) { - switch(_map_select+1) { + switch(_map_select+1) { //selects chosen map case 2: map2_draw(lcd); snake_map2_collision(); @@ -74,13 +74,13 @@ } } -void SnakeEngine::snake_map2_collision() { +void SnakeEngine::snake_map2_collision() { //ring map if (_body._x_head < 2 || _body._x_head > 81 || _body._y_head < 2 || _body._y_head > 45){ //if snakehead coords exceed the ring coords _death = true; } } -void SnakeEngine::snake_map3_collision() { +void SnakeEngine::snake_map3_collision() { //cross map if ((_body._x_head == 40 || _body._x_head == 42) && (_body._y_head < 16 || _body._y_head > 30)){ //if head is at the either of the N/S walls' x coords, and above (y=18) or below (y=30), trigger death _death = true; @@ -90,215 +90,211 @@ } } -void SnakeEngine::snake_map4_collision() { - /* - for(int i = 0; i < 48; i++){ - if(_body._x_head == MAP 4 COORDS && _body._y_head == MAP 4 COORDS) { - return true; - } - */ -} - -void SnakeEngine::map2_draw(N5110 &lcd){ - lcd.drawRect(0, 0, 84, 48,FILL_TRANSPARENT); - lcd.drawRect(1, 1, 82, 46,FILL_TRANSPARENT); +void SnakeEngine::snake_map4_collision() { //lanes + _map4_location = 0; + if (_body._x_head == 8 || _body._x_head == 10 || _body._x_head == 40 || _body._x_head == 42 || _body._x_head == 72 || _body._x_head == 74){ + _map4_location += 1; //adjust tracker if x matches upper/lower walls + } //printf("x matches upper/lower walls"); + if (_body._y_head < 12 || _body._y_head > 34){ + _map4_location += 3; //adjust tracker if y matches upper/lower walls + } //printf("y matches upper/lower walls"); + if (_body._x_head == 24 || _body._x_head == 26 || _body._x_head == 56 || _body._x_head == 58){ + _map4_location += 2; //adjust tracker if x matches mid walls + } //printf("x matches mid walls"); + if (_body._y_head > 14 && _body._y_head < 32){ + _map4_location += 2; //adjust tracker if y matches mid walls + } //printf("y matches mid walls"); + 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) + _death = true; + } //printf("Wall collision"); } -void SnakeEngine::map3_draw(N5110 &lcd){ - lcd.drawRect(40, 0, 4, 16,FILL_BLACK); //N wall - lcd.drawRect(68, 22, 16, 4,FILL_BLACK);//E wall - lcd.drawRect(40, 32, 4, 16,FILL_BLACK);//S wall - lcd.drawRect(0, 22, 16, 4,FILL_BLACK); //W wall +void SnakeEngine::map2_draw(N5110 &lcd){ //rings + lcd.drawRect(0, 0, 84, 48,FILL_TRANSPARENT); //outer pixels of ring + lcd.drawRect(1, 1, 82, 46,FILL_TRANSPARENT); //inner pixels +} + +void SnakeEngine::map3_draw(N5110 &lcd){ //cross + lcd.drawRect(40, 0, 4, 16,FILL_BLACK); //N wall + lcd.drawRect(68, 22, 16, 4,FILL_BLACK);//E wall + lcd.drawRect(40, 32, 4, 16,FILL_BLACK);//S wall + lcd.drawRect(0, 22, 16, 4,FILL_BLACK); //W wall } -void SnakeEngine::map4_draw(N5110 &lcd){ - lcd.drawRect(12, 8, 4, 4,FILL_BLACK); //NW square - lcd.drawRect(12, 36, 4, 4,FILL_BLACK);//SW square - lcd.drawRect(68, 8, 4, 4,FILL_BLACK); //NE square - lcd.drawRect(68, 36, 4, 4,FILL_BLACK);//SE square - - lcd.drawRect(38, 6, 8, 8,FILL_BLACK); //N large square - lcd.drawRect(24, 20, 8, 8,FILL_BLACK);//E large square - lcd.drawRect(38, 34, 8, 8,FILL_BLACK);//S large square - lcd.drawRect(52, 20, 8, 8,FILL_BLACK);//W large square +void SnakeEngine::map4_draw(N5110 &lcd){ //lanes + lcd.drawRect(8, 0, 4, 12,FILL_BLACK);//NW line + lcd.drawRect(8, 36, 4, 12,FILL_BLACK);//SW line + lcd.drawRect(40, 0, 4, 12,FILL_BLACK);//N-mid line + lcd.drawRect(40, 36, 4, 12,FILL_BLACK);//S-mid line + lcd.drawRect(72, 0, 4, 12,FILL_BLACK);//NE line + lcd.drawRect(72, 36, 4, 12,FILL_BLACK);//SE line + lcd.drawRect(24, 16, 4, 16,FILL_BLACK);//mid-W line + lcd.drawRect(56, 16, 4, 16,FILL_BLACK);//mid-E line } - void SnakeEngine::transition_black(N5110 &lcd) { - //lcd.clear(); for (int j = 0; j < 21; j += 4) { //j iterator controls the size and location of current loop //printf("j: %d\n", j); for (int i = 1; i < 84 - (2*j); i += 2) { //i iterator controls length of rectangles - lcd.drawRect(j, j, i + 1, 4, FILL_BLACK); //top horizontal rectangle - lcd.drawRect(83 - j - i, 44 - j, i + 1, 4, FILL_BLACK); //bottom horizontal rectangle + lcd.drawRect(j, j, 1 + i, 4, FILL_BLACK); //top horizontal rectangle grows to the right by adding i iterator to width + 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, + //and adding i iterator to width wait_ms(5); - lcd.refresh(); //refreshes screen without clearing it to maintain previous loops + lcd.refresh(); //refreshes screen without clearing it to maintain previous loops' rectangles } for (int i = 1; i < 43 - (2*j); i += 2) { //i iterator controls length of rectangles - lcd.drawRect(80 - j, 4 + j, 4, i,FILL_BLACK); //right vertical rectangle - lcd.drawRect(j, 44 - i - j, 4, i,FILL_BLACK); //left vertical rectangle + lcd.drawRect(80 - j, 4 + j, 4, i,FILL_BLACK); //right vertical rectangle grows down by adding i iterator to height + 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 wait_ms(5); lcd.refresh(); //refreshes screen without clearing it to maintain previous loops } } - //wait_ms(500); } void SnakeEngine::transition_white(N5110 &lcd) { - //lcd.clear(); - for (int j = 0; j < 21; j += 4) { - //printf("j: %d\n", j); - for (int i = 1; i < 84 - (2*j); i += 2) { - lcd.drawRect(j, j, i + 1, 4, FILL_WHITE); - lcd.drawRect(83 - j - i, 44 - j, i + 1, 4, FILL_WHITE); + //functionally same as black transition function + for (int j = 0; j < 21; j += 4) { //j iterator controls the size and location of current loop + //printf("j: %d\n", j); + for (int i = 1; i < 84 - (2*j); i += 2) { //i iterator controls length of rectangles + lcd.drawRect(j, j, 1 + i, 4, FILL_WHITE); //top horizontal rectangle grows to the right by adding i iterator to width + 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, + //and adding i iterator to width wait_ms(5); - lcd.refresh(); + lcd.refresh(); //refreshes screen without clearing it to maintain previous loops' rectangles } - for (int i = 1; i < 43 - (2*j); i += 2) { - lcd.drawRect(80 - j, 4 + j, 4, i,FILL_WHITE); - lcd.drawRect(j, 44 - i - j, 4, i,FILL_WHITE); + for (int i = 1; i < 43 - (2*j); i += 2) { //i iterator controls length of rectangles + lcd.drawRect(80 - j, 4 + j, 4, i,FILL_WHITE); //right vertical rectangle grows down by adding i iterator to height + 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 wait_ms(5); - lcd.refresh(); + lcd.refresh(); //refreshes screen without clearing it to maintain previous loops } } - //wait_ms(500); } void SnakeEngine::menu1_init(Gamepad &pad, N5110 &lcd){ - contrast(pad, lcd); - transition_black(lcd); + contrast(pad, lcd); //adjusts contrast before transitions + transition_black(lcd); transition_white(lcd); - lcd.clear(); lcd.refresh(); //printf("Menu 2\n"); - lcd.printString(" SNAKE",3,0); + lcd.printString("SNAKE",27,0); //displays relevant text lcd.printString("Play",30,2); - lcd.drawCircle(24,19,3,FILL_TRANSPARENT); + lcd.drawCircle(24,19,3,FILL_TRANSPARENT); //draws empty circles for option display lcd.printString("Maps",30,3); lcd.drawCircle(24,27,3,FILL_TRANSPARENT); lcd.refresh(); - menu_flash(pad, 2); + menu_flash(pad, 2); //flashes orange LEDs } -void SnakeEngine::menu1_select(N5110 &lcd, Gamepad &pad, FXOS8700CQ &mag){ +void SnakeEngine::menu1_select(Gamepad &pad, N5110 &lcd, FXOS8700CQ &mag){ //printf("Menu 1\n"); - if (pad.X_pressed() == true){ //detect if 'up' selection - _menu_select--; - } else if (pad.B_pressed() == true){ //detect if 'down' selection + if (pad.X_held() == true){ //detect if 'up' selection + _menu_select--; + } else if (pad.B_held() == true){ //detect if 'down' selection _menu_select++; } - _menu_select = ((_menu_select % 2) + 2) % 2; //wrap around numbers, ie down on 2 goes to 1 and up on 1 goes to 2 + _menu_select = ((_menu_select % 2) + 2) % 2; //wrap around numbers, ie down on 1 goes to 0 and up on 0 goes to 1 select_circles(lcd, _menu_select + 1); //draw black circle in selected option //printf("Option: %d\n", _menu_select + 1); - if (pad.A_pressed() == true){ //if option 1 selected and 'A' pressed + if (pad.A_held() == true){ //if option 1 selected and 'A' held if (_menu_select == 0){ game_init(pad, lcd, mag); //Initialise game - _game_state = 3; //switch state - } else { + } else { //otherwise must be option 2 menu2_init(pad, lcd); //Initialise menu 2 - _game_state = 2; //switch state + menu_flash(pad, 2); //flashes orange LEDs } } } void SnakeEngine::menu2_init(Gamepad &pad, N5110 &lcd){ - //transition_black(lcd); - //transition_white(lcd); - //printf("Menu 1\n"); + //printf("Menu 2\n"); lcd.clear(); - lcd.printString(" MAPS",0,0); + lcd.printString(" MAPS",0,0); //displays relevant text lcd.printString("Empty",30,2); - lcd.drawCircle(24,19,3,FILL_TRANSPARENT); + lcd.drawCircle(24,19,3,FILL_TRANSPARENT); //draws empty circles for option display lcd.printString("Ring",30,3); lcd.drawCircle(24,27,3,FILL_TRANSPARENT); lcd.printString("Cross",30,4); lcd.drawCircle(24,35,3,FILL_TRANSPARENT); - lcd.printString("Spots",30,5); + lcd.printString("Lanes",30,5); lcd.drawCircle(24,43,3,FILL_TRANSPARENT); lcd.refresh(); - menu_flash(pad, 2); + game_state = 2; //sets game_state to menu 2, which changes the active while loop in main.cpp } -void SnakeEngine::menu2_select(N5110 &lcd, Gamepad &pad){ +void SnakeEngine::menu2_select(Gamepad &pad, N5110 &lcd, FXOS8700CQ &mag){ + + select_circles(lcd, _map_select+1); //printf("Menu 2\n"); - if (pad.X_pressed() == true){ + if (pad.X_held() == true){ _map_select--; - } else if (pad.B_pressed() == true){ - _map_select++; - } else if (pad.Y_pressed() == true){ - preview(pad, lcd, _map_select+1); - } else if (pad.A_pressed() == true){ - //game_init(); - _game_state = 3; + } else if (pad.B_held() == true){ + _map_select++; + } else if (pad.Y_held() == true){ + preview(pad, lcd); //allows short preview of map to be displayed + } else if (pad.A_held() == true){ + game_init(pad, lcd, mag); //intialises game } - //printf("Map: %d\n", _map_select); - _map_select = ((_map_select % 4) + 4) % 4; - select_circles(lcd, _map_select+1); + _map_select = ((_map_select % 4) + 4) % 4; //wrap around numbers, ie down on 3 goes to 0 and up on 0 goes to 3 } void SnakeEngine::death_init(Gamepad &pad, N5110 &lcd){ - _death = 0; - _menu_select = 0; + _death = 0; //resets death flag + _menu_select = 0; //resets menu select so 'play again' is default transition_black(lcd); transition_white(lcd); //printf("Game over\n"); - lcd.printString(" GAME OVER",3,0); + lcd.printString(" GAME OVER",3,0); //displays relevant text lcd.printString(" Score:",0,1); - char buffer[14]; + char buffer[14]; //creates a buffer for the score sprintf(buffer," %2d",score); lcd.printString(buffer,0,2); lcd.printString("Again!",30,4); - lcd.drawCircle(24,35,3,FILL_TRANSPARENT); + lcd.drawCircle(24,35,3,FILL_TRANSPARENT); //draws empty circles for option selection lcd.printString("Maps",30,5); lcd.drawCircle(24,43,3,FILL_TRANSPARENT); lcd.refresh(); - menu_flash(pad, 1); + menu_flash(pad, 1); //flashes red LEDs } -void SnakeEngine::death_select(N5110 &lcd, Gamepad &pad, FXOS8700CQ &mag){ +void SnakeEngine::death_select(Gamepad &pad, N5110 &lcd, FXOS8700CQ &mag){ //printf("Menu 1\n"); - if (pad.X_pressed() == true){ //detect if 'up' selection + if (pad.X_held() == true){ //detect if 'up' selection _menu_select--; - } else if (pad.B_pressed() == true){ //detect if 'down' selection + } else if (pad.B_held() == true){ //detect if 'down' selection _menu_select++; } _menu_select = ((_menu_select % 2) + 2) % 2; //wrap around numbers, ie down on 2 goes to 1 and up on 1 goes to 2 select_circles(lcd, _menu_select + 3); //draw black circle in selected option //printf("Option: %d\n", _menu_select + 1); - if (pad.A_pressed() == true){ //if option 1 selected and 'A' pressed + if (pad.A_held() == true){ //if option 1 selected and 'A' held if (_menu_select == 0){ - game_init(pad, lcd, mag); //Initialise game - _game_state = 3; //switch state + game_init(pad, lcd, mag); + game_state = 3; } else { - menu2_init(pad, lcd); //Initialise menu 2 - _game_state = 2; //switch state + menu2_init(pad, lcd); + game_state = 2; } } } void SnakeEngine::select_circles(N5110 &lcd, int line) { - for(int i = 19; i < 52; i +=8) { - lcd.drawCircle(24,i,2,FILL_WHITE); + for(int i = 19; i < 52; i += 8) { //iterates over all the circle options' y values + lcd.drawCircle(24,i,2,FILL_WHITE); //remove previous options' black circles } - lcd.drawCircle(24,11+line*8,2,FILL_BLACK); + lcd.drawCircle(24, 11 + line * 8, 2, FILL_BLACK); //draws black circle in relevant option's blank circle lcd.refresh(); wait_ms(200); - //snake_select1.render(lcd, 0, 8); - //wait_ms(200); - //snake_select2.render(lcd, 0, 8); - //wait_ms(200); - //snake_select3.render(lcd, 0, 8); - //wait_ms(200); } -void SnakeEngine::preview(Gamepad &pad, N5110 &lcd, int _map_select){ +void SnakeEngine::preview(Gamepad &pad, N5110 &lcd){ lcd.clear(); - switch(_map_select) { + switch(_map_select + 1) { //selects relevant map case 1: lcd.clear(); lcd.printString("(Empty)",21,2); @@ -316,22 +312,32 @@ //lcd.printString("Spots",27,2); break; } - lcd.refresh(); - wait_ms(1000); + lcd.refresh(); + pad.led(2, 1); + pad.led(5, 1); + wait_ms(1000); //displays for 1 second + pad.led(2, 0); + pad.led(5, 0); lcd.clear(); - menu2_init(pad, lcd); + menu2_init(pad, lcd); //re-initialises menu 2 } void SnakeEngine::contrast(Gamepad &pad, N5110 &lcd){ _pot2 = pad.read_pot2(); - lcd.setContrast(0.25 + _pot2 * 0.5); + lcd.setContrast(0.25 + _pot2 * 0.5); //maps pot value to range 0.25 - 0.75 //printf("Contrast: %f\n", 0.25 + _pot2 * 0.5); } void SnakeEngine::menu_flash(Gamepad &pad, int led){ for(int i = 1; i < 7; i++){ - pad.led(led, i % 2); - pad.led(led + 3, i % 2); + pad.led(led, i % 2); //flash left side LEDs - odd numbers become 1 to turn on, even numbers become 0 to turn off + pad.led(led + 3, i % 2); //flash right side LEDs wait_ms(100); } -} \ No newline at end of file +} + +void SnakeEngine::game_reset(){ + score = 0; + _body.reset(); +} +