ELEC2645 (2015/16)
/
fy13tmtProject
Simple (basic) snake game
main.cpp
- Committer:
- MsTee
- Date:
- 2016-05-08
- Revision:
- 0:9eb93eff2469
- Child:
- 1:ab8ceac59e71
File content as of revision 0:9eb93eff2469:
/** Thokozile M Tembo 200822004 @file main.cpp @brief Snake Game */ #include "main.h" int main() { lcd.init(); // Initialise LCD init_K64F(); // Initialise connection with buttons welcomeScreen(); // Display welcome screen calibrateJoystick(); // Calibrate the joystick // Read joystick values every 20 ms (50 Hz) joystick_update_ticker.attach(&updateJoystick,0.02); // Initialising random number generator srand(time(NULL)); snake_game(); } void init_K64F() { // Configure serial comms pc.baud(115200); // Call pcb_button_isr function pcb_button.rise(&pcb_button_isr); pcb_button.mode(PullDown); // use PullDown } void welcomeScreen() { lcd.printString("Welcome to" ,15,0); //inserts text for welcome on the first line hence the '1' lcd.printString("Snake Game",15,1); // prints the text in the brackets on the secondline hence '2' lcd.printString("Thokozile",0,3); //prints text in the third line lcd.printString("Tembo",0,4); // prints name in fifth line lcd.printString("200822004",0,5); // prints name in fifth line wait(2); // waits for 2 seconds lcd.clear(); lcd.refresh(); // resets the screen } void calibrateJoystick() { // must not move during calibration joystick.x0 = joy_x; // initial positions in the range 0.0 to 1.0 (0.5 if centred exactly) joystick.y0 = joy_y; } void updateJoystick() { // read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred) joystick.x = joy_x - joystick.x0; joystick.y = joy_y - joystick.y0; joystick.button = joy_button; // read button state // calculate direction depending on x,y values // tolerance allows a little lee-way in case joystick not exactly in the stated direction if (fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = CENTRE; } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = UP; } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { joystick.direction = DOWN; } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { joystick.direction = LEFT; } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { joystick.direction = RIGHT; } else { joystick.direction = UNKNOWN; } } /* Snake Game Logic */ void snake_game() { // Game Variables int snake_x[220]; // Snake parts X int snake_y[220]; // Snake parts Y AppleType apple; // Creating an apple int snake_size = 5; // Initial size of snake int x_direction = 0; int y_direction = 0; int next_x; int next_y; int score = 0; while(1) { switch(game_state) { case INIT: x_direction = 0; y_direction = 0; score = 0; // Clear Screen lcd.clear(); // Draw border lcd.drawRect(1,1,81,45,0); // Reset snake parts for (int i = 0; i < 220; i++) { snake_x[i] = 0; snake_y[i] = 0; } // Draw Initial snake for (int i = 0; i < snake_size; i++) { snake_x[i] = (snake_size-1) - i; snake_y[i] = 0; drawBlock(snake_x[i], snake_y[i]); } apple = placeRandomApple(); lcd.refresh(); game_state = WAIT_FOR_USER; break; case WAIT_FOR_USER: // Wait until user moves joystick to the right or down while ((joystick.direction != RIGHT) && (joystick.direction != DOWN)) { sleep(); } // Go to Play state game_state = PLAY; break; case PLAY: while (game_state == PLAY) { switch (joystick.direction) { case RIGHT: if (x_direction != -1) { // If not opposite x_direction = 1; y_direction = 0; } break; case LEFT: if (x_direction != 1) { // If not opposite x_direction = -1; y_direction = 0; } break; case DOWN: if (y_direction != -1) { // If not opposite x_direction = 0; y_direction = 1; } break; case UP: if (y_direction != 1) { // If not opposite x_direction = 0; y_direction = -1; } break; } next_x = snake_x[0] + x_direction; next_y = snake_y[0] + y_direction; if (getBlock(next_x, next_y) && (next_x != apple.x) && (next_y != apple.y)) { // Hit the snake body game_state = GAME_OVER; } else if ((next_x > 19) || (next_y > 10) || (next_x < 0) || (next_y < 0)) { // Hit the border game_state = GAME_OVER; } else { if ((next_x == apple.x) && (next_y == apple.y)) { // Apple eaten // Increment snake size and score snake_size++; score++; // Place new apple apple = placeRandomApple(); // Don't remove tail } else { // Remove tail eraseBlock(snake_x[snake_size-1], snake_y[snake_size-1]); } // Move all snake parts for (int i = snake_size-1; i > 0; i--) { snake_x[i] = snake_x[i - 1]; snake_y[i] = snake_y[i - 1]; } // Move head in current direction snake_x[0] = next_x; snake_y[0] = next_y; // Draw new head drawBlock(next_x, next_y); // Redraw things on LCD lcd.refresh(); wait_ms(200); } } break; case GAME_OVER: g_pcb_button_flag = 0; // Clear Screen lcd.clear(); lcd.printString("GAME OVER!",2,0); // prints name in fifth line while(!g_pcb_button_flag) { sleep(); } game_state = INIT; break; default: game_state = INIT; } } } AppleType placeRandomApple() { int good_location = 0; AppleType apple; // Look for a new location for an apple while (!good_location) { apple.x = rand() % 20; // 0 to 19 apple.y = rand() % 10; // 0 to 9 // Don't put apple on the snake if (!getBlock(apple.x, apple.y)) good_location = 1; } drawApple(apple.x, apple.y); return apple; } // field_x (0..19), field_y (0..10) void drawBlock(int field_x, int field_y) { // field_x*(block_size)+(border_offset) lcd.drawRect(field_x*4+2, field_y*4+2, 3, 3, 1); } void eraseBlock(int field_x, int field_y) { // Draw an empty square on top // field_x*(block_size)+(border_offset) lcd.drawRect(field_x*4+2, field_y*4+2, 3, 3, 3); } void drawApple(int field_x, int field_y) { int offset_x = field_x*4+2; int offset_y = field_y*4+2; // Drawing an apple pixel by pixel (8 dots) lcd.setPixel(offset_x+1,offset_y); lcd.setPixel(offset_x+2,offset_y); lcd.setPixel(offset_x,offset_y+1); lcd.setPixel(offset_x,offset_y+2); lcd.setPixel(offset_x+3,offset_y+1); lcd.setPixel(offset_x+3,offset_y+2); lcd.setPixel(offset_x+1,offset_y+3); lcd.setPixel(offset_x+2,offset_y+3); } int getBlock(int field_x, int field_y) { int offset_x = field_x*4+2; int offset_y = field_y*4+2; // Pixel at (offset_x+1,offset_y) will be active // for both apple and the snake block return lcd.getPixel(offset_x+1,offset_y); } // This function is called when button is pressed void pcb_button_isr() { g_pcb_button_flag = 1; }