snake game from https://github.com/lancaster-university/microbit-samples/tree/master/source/examples/snake
main.cpp@0:59c42b44cf60, 2017-01-19 (annotated)
- Committer:
- kinga
- Date:
- Thu Jan 19 11:38:22 2017 +0000
- Revision:
- 0:59c42b44cf60
Version 1.0 of the popular snake game
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kinga | 0:59c42b44cf60 | 1 | #include "MicroBit.h" |
kinga | 0:59c42b44cf60 | 2 | |
kinga | 0:59c42b44cf60 | 3 | #define SNAKE_EMPTY 0 |
kinga | 0:59c42b44cf60 | 4 | #define SNAKE_UP 1 |
kinga | 0:59c42b44cf60 | 5 | #define SNAKE_LEFT 2 |
kinga | 0:59c42b44cf60 | 6 | #define SNAKE_RIGHT 3 |
kinga | 0:59c42b44cf60 | 7 | #define SNAKE_DOWN 4 |
kinga | 0:59c42b44cf60 | 8 | |
kinga | 0:59c42b44cf60 | 9 | #define SNAKE_FRAME_DELAY 350 |
kinga | 0:59c42b44cf60 | 10 | #define GROWTH_SPEED 3 |
kinga | 0:59c42b44cf60 | 11 | |
kinga | 0:59c42b44cf60 | 12 | struct Point |
kinga | 0:59c42b44cf60 | 13 | { |
kinga | 0:59c42b44cf60 | 14 | int x; |
kinga | 0:59c42b44cf60 | 15 | int y; |
kinga | 0:59c42b44cf60 | 16 | }; |
kinga | 0:59c42b44cf60 | 17 | |
kinga | 0:59c42b44cf60 | 18 | MicroBit uBit; |
kinga | 0:59c42b44cf60 | 19 | Point head; // Location of the head of our snake. |
kinga | 0:59c42b44cf60 | 20 | Point tail; // Location of the tail of our snake. |
kinga | 0:59c42b44cf60 | 21 | Point food; // Location of food. |
kinga | 0:59c42b44cf60 | 22 | MicroBitImage map(5,5); |
kinga | 0:59c42b44cf60 | 23 | |
kinga | 0:59c42b44cf60 | 24 | void place_food() |
kinga | 0:59c42b44cf60 | 25 | { |
kinga | 0:59c42b44cf60 | 26 | int r = uBit.random(24); |
kinga | 0:59c42b44cf60 | 27 | int x = 0; int y = 0; |
kinga | 0:59c42b44cf60 | 28 | |
kinga | 0:59c42b44cf60 | 29 | while (r > 0) |
kinga | 0:59c42b44cf60 | 30 | { |
kinga | 0:59c42b44cf60 | 31 | x = (x+1) % 5; |
kinga | 0:59c42b44cf60 | 32 | if (x == 0) |
kinga | 0:59c42b44cf60 | 33 | y = (y+1) % 5; |
kinga | 0:59c42b44cf60 | 34 | |
kinga | 0:59c42b44cf60 | 35 | if(map.getPixelValue(x,y) == SNAKE_EMPTY) |
kinga | 0:59c42b44cf60 | 36 | r--; |
kinga | 0:59c42b44cf60 | 37 | } |
kinga | 0:59c42b44cf60 | 38 | |
kinga | 0:59c42b44cf60 | 39 | food.x = x; |
kinga | 0:59c42b44cf60 | 40 | food.y = y; |
kinga | 0:59c42b44cf60 | 41 | } |
kinga | 0:59c42b44cf60 | 42 | |
kinga | 0:59c42b44cf60 | 43 | void snake() |
kinga | 0:59c42b44cf60 | 44 | { |
kinga | 0:59c42b44cf60 | 45 | Point newHead; // Calculated placement of new head position based on user input. |
kinga | 0:59c42b44cf60 | 46 | int hdirection; // Head's direction of travel |
kinga | 0:59c42b44cf60 | 47 | int tdirection; // Tail's direction of travel |
kinga | 0:59c42b44cf60 | 48 | int snakeLength; // number of segments in the snake. |
kinga | 0:59c42b44cf60 | 49 | int growing; // boolean state indicating if we've just eaten some food. |
kinga | 0:59c42b44cf60 | 50 | int score; |
kinga | 0:59c42b44cf60 | 51 | |
kinga | 0:59c42b44cf60 | 52 | // Start in the middle of the screen. |
kinga | 0:59c42b44cf60 | 53 | tail.x = tail.y = 2; |
kinga | 0:59c42b44cf60 | 54 | head.x = head.y = 2; |
kinga | 0:59c42b44cf60 | 55 | snakeLength = 1; |
kinga | 0:59c42b44cf60 | 56 | growing = 0; |
kinga | 0:59c42b44cf60 | 57 | score = 0; |
kinga | 0:59c42b44cf60 | 58 | map.clear(); |
kinga | 0:59c42b44cf60 | 59 | |
kinga | 0:59c42b44cf60 | 60 | uBit.display.image.setPixelValue(head.x, head.y, 255); |
kinga | 0:59c42b44cf60 | 61 | |
kinga | 0:59c42b44cf60 | 62 | // Add some random food. |
kinga | 0:59c42b44cf60 | 63 | place_food(); |
kinga | 0:59c42b44cf60 | 64 | |
kinga | 0:59c42b44cf60 | 65 | while (1) |
kinga | 0:59c42b44cf60 | 66 | { |
kinga | 0:59c42b44cf60 | 67 | // Flash the food is necessary; |
kinga | 0:59c42b44cf60 | 68 | uBit.display.image.setPixelValue(food.x, food.y, uBit.systemTime() % 1000 < 500 ? 0 : 255); |
kinga | 0:59c42b44cf60 | 69 | |
kinga | 0:59c42b44cf60 | 70 | int dx = uBit.accelerometer.getX(); |
kinga | 0:59c42b44cf60 | 71 | int dy = uBit.accelerometer.getY(); |
kinga | 0:59c42b44cf60 | 72 | |
kinga | 0:59c42b44cf60 | 73 | newHead.x = head.x; |
kinga | 0:59c42b44cf60 | 74 | newHead.y = head.y; |
kinga | 0:59c42b44cf60 | 75 | |
kinga | 0:59c42b44cf60 | 76 | if (abs(dx) > abs(dy)) |
kinga | 0:59c42b44cf60 | 77 | { |
kinga | 0:59c42b44cf60 | 78 | if(dx < 0) |
kinga | 0:59c42b44cf60 | 79 | { |
kinga | 0:59c42b44cf60 | 80 | hdirection = SNAKE_LEFT; |
kinga | 0:59c42b44cf60 | 81 | newHead.x = newHead.x == 0 ? 4 : newHead.x-1; |
kinga | 0:59c42b44cf60 | 82 | } |
kinga | 0:59c42b44cf60 | 83 | else |
kinga | 0:59c42b44cf60 | 84 | { |
kinga | 0:59c42b44cf60 | 85 | hdirection = SNAKE_RIGHT; |
kinga | 0:59c42b44cf60 | 86 | newHead.x = newHead.x == 4 ? 0 : newHead.x+1; |
kinga | 0:59c42b44cf60 | 87 | } |
kinga | 0:59c42b44cf60 | 88 | } |
kinga | 0:59c42b44cf60 | 89 | else |
kinga | 0:59c42b44cf60 | 90 | { |
kinga | 0:59c42b44cf60 | 91 | if(dy < 0) |
kinga | 0:59c42b44cf60 | 92 | { |
kinga | 0:59c42b44cf60 | 93 | hdirection = SNAKE_UP; |
kinga | 0:59c42b44cf60 | 94 | newHead.y = newHead.y == 0 ? 4 : newHead.y-1; |
kinga | 0:59c42b44cf60 | 95 | } |
kinga | 0:59c42b44cf60 | 96 | else |
kinga | 0:59c42b44cf60 | 97 | { |
kinga | 0:59c42b44cf60 | 98 | hdirection = SNAKE_DOWN; |
kinga | 0:59c42b44cf60 | 99 | newHead.y = newHead.y == 4 ? 0 : newHead.y+1; |
kinga | 0:59c42b44cf60 | 100 | } |
kinga | 0:59c42b44cf60 | 101 | } |
kinga | 0:59c42b44cf60 | 102 | |
kinga | 0:59c42b44cf60 | 103 | int status = map.getPixelValue(newHead.x, newHead.y); |
kinga | 0:59c42b44cf60 | 104 | if (status == SNAKE_UP || status == SNAKE_DOWN || status == SNAKE_LEFT || status == SNAKE_RIGHT) |
kinga | 0:59c42b44cf60 | 105 | { |
kinga | 0:59c42b44cf60 | 106 | uBit.display.scroll("GAME OVER! SCORE: "); |
kinga | 0:59c42b44cf60 | 107 | uBit.display.scroll(score); |
kinga | 0:59c42b44cf60 | 108 | |
kinga | 0:59c42b44cf60 | 109 | return; |
kinga | 0:59c42b44cf60 | 110 | } |
kinga | 0:59c42b44cf60 | 111 | |
kinga | 0:59c42b44cf60 | 112 | // move the head. |
kinga | 0:59c42b44cf60 | 113 | map.setPixelValue(head.x, head.y, hdirection); |
kinga | 0:59c42b44cf60 | 114 | uBit.display.image.setPixelValue(newHead.x, newHead.y, 255); |
kinga | 0:59c42b44cf60 | 115 | |
kinga | 0:59c42b44cf60 | 116 | if (growing == GROWTH_SPEED) |
kinga | 0:59c42b44cf60 | 117 | { |
kinga | 0:59c42b44cf60 | 118 | growing = 0; |
kinga | 0:59c42b44cf60 | 119 | snakeLength++; |
kinga | 0:59c42b44cf60 | 120 | } |
kinga | 0:59c42b44cf60 | 121 | else |
kinga | 0:59c42b44cf60 | 122 | { |
kinga | 0:59c42b44cf60 | 123 | // move the tail. |
kinga | 0:59c42b44cf60 | 124 | tdirection = map.getPixelValue(tail.x,tail.y); |
kinga | 0:59c42b44cf60 | 125 | map.setPixelValue(tail.x, tail.y, SNAKE_EMPTY); |
kinga | 0:59c42b44cf60 | 126 | uBit.display.image.setPixelValue(tail.x, tail.y, 0); |
kinga | 0:59c42b44cf60 | 127 | |
kinga | 0:59c42b44cf60 | 128 | // Move our record of the tail's location. |
kinga | 0:59c42b44cf60 | 129 | if (snakeLength == 1) |
kinga | 0:59c42b44cf60 | 130 | { |
kinga | 0:59c42b44cf60 | 131 | tail.x = newHead.x; |
kinga | 0:59c42b44cf60 | 132 | tail.y = newHead.y; |
kinga | 0:59c42b44cf60 | 133 | } |
kinga | 0:59c42b44cf60 | 134 | else |
kinga | 0:59c42b44cf60 | 135 | { |
kinga | 0:59c42b44cf60 | 136 | if (tdirection == SNAKE_UP) |
kinga | 0:59c42b44cf60 | 137 | tail.y = tail.y == 0 ? 4 : tail.y-1; |
kinga | 0:59c42b44cf60 | 138 | |
kinga | 0:59c42b44cf60 | 139 | if (tdirection == SNAKE_DOWN) |
kinga | 0:59c42b44cf60 | 140 | tail.y = tail.y == 4 ? 0 : tail.y+1; |
kinga | 0:59c42b44cf60 | 141 | |
kinga | 0:59c42b44cf60 | 142 | if (tdirection == SNAKE_LEFT) |
kinga | 0:59c42b44cf60 | 143 | tail.x = tail.x == 0 ? 4 : tail.x-1; |
kinga | 0:59c42b44cf60 | 144 | |
kinga | 0:59c42b44cf60 | 145 | if (tdirection == SNAKE_RIGHT) |
kinga | 0:59c42b44cf60 | 146 | tail.x = tail.x == 4 ? 0 : tail.x+1; |
kinga | 0:59c42b44cf60 | 147 | } |
kinga | 0:59c42b44cf60 | 148 | } |
kinga | 0:59c42b44cf60 | 149 | |
kinga | 0:59c42b44cf60 | 150 | // Update our record of the head location and away we go! |
kinga | 0:59c42b44cf60 | 151 | head.x = newHead.x; |
kinga | 0:59c42b44cf60 | 152 | head.y = newHead.y; |
kinga | 0:59c42b44cf60 | 153 | |
kinga | 0:59c42b44cf60 | 154 | // if we've eaten some food, replace the food and grow ourselves! |
kinga | 0:59c42b44cf60 | 155 | if (head.x == food.x && head.y == food.y) |
kinga | 0:59c42b44cf60 | 156 | { |
kinga | 0:59c42b44cf60 | 157 | growing++; |
kinga | 0:59c42b44cf60 | 158 | score++; |
kinga | 0:59c42b44cf60 | 159 | place_food(); |
kinga | 0:59c42b44cf60 | 160 | } |
kinga | 0:59c42b44cf60 | 161 | |
kinga | 0:59c42b44cf60 | 162 | uBit.sleep(SNAKE_FRAME_DELAY); |
kinga | 0:59c42b44cf60 | 163 | } |
kinga | 0:59c42b44cf60 | 164 | } |
kinga | 0:59c42b44cf60 | 165 | |
kinga | 0:59c42b44cf60 | 166 | int main() |
kinga | 0:59c42b44cf60 | 167 | { |
kinga | 0:59c42b44cf60 | 168 | // Initialise the micro:bit runtime. |
kinga | 0:59c42b44cf60 | 169 | uBit.init(); |
kinga | 0:59c42b44cf60 | 170 | |
kinga | 0:59c42b44cf60 | 171 | // Insert your code here! |
kinga | 0:59c42b44cf60 | 172 | uBit.display.scroll("SNAKE v1.0"); |
kinga | 0:59c42b44cf60 | 173 | |
kinga | 0:59c42b44cf60 | 174 | while(1) |
kinga | 0:59c42b44cf60 | 175 | snake(); |
kinga | 0:59c42b44cf60 | 176 | } |
kinga | 0:59c42b44cf60 | 177 |