Snake.cpp
1 // SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries 2 // 3 // SPDX-License-Identifier: MIT 4 5 #include "Snake.h" 6 7 void Snake::run() { 8 if (gameRunning) { 9 if ((millis()-lastSnakeMoveTime)>((80-snakeLength)*(80-snakeLength)/20)) { 10 if (!moveSnake()) gameOver(); 11 else lastSnakeMoveTime=millis(); 12 } 13 } 14 } 15 16 void Snake::init() { 17 for (uint8_t y=0;y<16;y++) { 18 for (uint8_t x=0;x<8;x++) { 19 snakeBoard[y][x]=0; 20 } 21 } 22 snakeLength=3; 23 snakeHeadX=random(4)+2; 24 snakeHeadY=random(12)+2; 25 uint8_t moveDirection=random(4); 26 switch (moveDirection) { 27 case 0: // up 28 snakeHeadDX=0; snakeHeadDY=-1; break; 29 case 1: // down 30 snakeHeadDX=0; snakeHeadDY=1; break; 31 case 2: // left 32 snakeHeadDX=-1; snakeHeadDY=0; break; 33 case 3: // right 34 snakeHeadDX=1; snakeHeadDY=0; 35 } 36 // Draw the snake of length=3 37 snakeBoard[snakeHeadY][snakeHeadX]=3; 38 snakeBoard[snakeHeadY-snakeHeadDY][snakeHeadX-snakeHeadDX]=2; 39 snakeBoard[snakeHeadY-snakeHeadDY*2][snakeHeadX-snakeHeadDX*2]=1; 40 placeFood(); 41 gameRunning=true; 42 } 43 44 void Snake::gameOver() { 45 gameRunning=false; 46 Serial.println("Game Over"); 47 } 48 49 void Snake::placeFood() { 50 foodX = random(8); 51 foodY = random(16); 52 while(snakeBoard[foodY][foodX]!=0) { 53 foodX = random(8); 54 foodY = random(16); 55 } 56 snakeBoard[foodY][foodX]=snakeLength+1; 57 } 58 59 bool Snake::moveSnake() { 60 snakeHeadX = (snakeHeadX+snakeHeadDX+8) % 8; 61 snakeHeadY = (snakeHeadY+snakeHeadDY+16)%16; 62 uint8_t temp = snakeBoard[snakeHeadY][snakeHeadX]; 63 // if the new snakeHead is already occupied by part of the snake body, then return false, game over 64 if (temp>1 && temp<=snakeLength) return false; 65 if (snakeHeadX == foodX && snakeHeadY == foodY) { 66 snakeLength+=1; 67 placeFood(); 68 } 69 else { 70 for (uint8_t y=0; y<16; y++) { 71 for (uint8_t x=0; x<8; x++) { 72 if (snakeBoard[y][x]>0 && snakeBoard[y][x]<=snakeLength) snakeBoard[y][x]-=1; 73 } 74 } 75 snakeBoard[snakeHeadY][snakeHeadX]=snakeLength; 76 } 77 allowToChangeDirection=true; 78 return true; 79 } 80 81 void Snake::changeDirection(int8_t dx, int8_t dy) { 82 if (!allowToChangeDirection) return; 83 if ((snakeHeadDX+dx==0 && dx!=0) || (snakeHeadDY+dy==0 && dy!=0)) return; 84 snakeHeadDX=dx; 85 snakeHeadDY=dy; 86 allowToChangeDirection=false; 87 } 88 89 uint8_t* Snake::getActiveBoard(){ 90 for (int8_t y=0; y<16; y++) { 91 uint8_t temp=0; 92 for (int8_t x=0; x<8; x++) { 93 if (snakeBoard[y][x]) temp |= _BV(7-x); 94 } 95 activeSnakeBoard[y]=temp; 96 } 97 return activeSnakeBoard; 98 }