Snake

Dependencies:   microbit

Fork of microbit_snake by Mohammad Khan

A Snake Game with animation, score and continuous play

Steps:

  • Switch On.
  • Snake animation plays.
  • Game starts.
  • Press buttons to move the snake left, right, up and down.
  • Food appears as a dot on the display.
  • Try eating the food by manoeuvring Snake to run over it.
  • Snake grows as it eats food.
  • As it grows it becomes hard to avoid snake biting itself.
  • Game Over.
  • Snake is flashed and then score is scrolled.
  • Game restarts after replaying animation.

Controls:

  • Left Button (A)
    • If snake moving UP/DOWN moves snake to LEFT.
    • If snake moving LEFT moves snake to DOWN.
    • If snake moving RIGHT moves snake to UP.
  • Right Button (B)
    • If snake moving UP/DOWN moves snake to RIGHT.
    • If snake moving LEFT moves snake to UP.
    • If snake moving RIGHT moves snake to DOWN.

How it looks:

https://www.youtube.com/watch?v=unEs3NOvIKA

Binary to play with

/media/uploads/mazimkhan/microbit_snake_nrf51_microbit.hex

Committer:
mazimkhan
Date:
Sun Apr 10 19:20:49 2016 +0000
Revision:
2:38060465e019
Parent:
0:af1bb8b895c7
Child:
3:a0200bceae4b
Removed printfs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mazimkhan 0:af1bb8b895c7 1 /*
mazimkhan 0:af1bb8b895c7 2 The MIT License (MIT)
mazimkhan 0:af1bb8b895c7 3 Copyright (c) 2016 British Broadcasting Corporation.
mazimkhan 0:af1bb8b895c7 4 This software is provided by Lancaster University by arrangement with the BBC.
mazimkhan 0:af1bb8b895c7 5 Permission is hereby granted, free of charge, to any person obtaining a
mazimkhan 0:af1bb8b895c7 6 copy of this software and associated documentation files (the "Software"),
mazimkhan 0:af1bb8b895c7 7 to deal in the Software without restriction, including without limitation
mazimkhan 0:af1bb8b895c7 8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
mazimkhan 0:af1bb8b895c7 9 and/or sell copies of the Software, and to permit persons to whom the
mazimkhan 0:af1bb8b895c7 10 Software is furnished to do so, subject to the following conditions:
mazimkhan 0:af1bb8b895c7 11 The above copyright notice and this permission notice shall be included in
mazimkhan 0:af1bb8b895c7 12 all copies or substantial portions of the Software.
mazimkhan 0:af1bb8b895c7 13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
mazimkhan 0:af1bb8b895c7 14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
mazimkhan 0:af1bb8b895c7 15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
mazimkhan 0:af1bb8b895c7 16 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
mazimkhan 0:af1bb8b895c7 17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
mazimkhan 0:af1bb8b895c7 18 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
mazimkhan 0:af1bb8b895c7 19 DEALINGS IN THE SOFTWARE.
mazimkhan 0:af1bb8b895c7 20 */
mazimkhan 0:af1bb8b895c7 21
mazimkhan 0:af1bb8b895c7 22 #include "MicroBit.h"
mazimkhan 0:af1bb8b895c7 23 #include "DigitalOut.h"
mazimkhan 0:af1bb8b895c7 24
mazimkhan 0:af1bb8b895c7 25 #define SNAKE_HEAD_PIXEL_BRIGHTNESS 25
mazimkhan 0:af1bb8b895c7 26 #define SNAKE_REST_PIXEL_BRIGHTNESS 15
mazimkhan 0:af1bb8b895c7 27 #define SNAKE_FOOD_PIXEL_BRIGHTNESS 255
mazimkhan 0:af1bb8b895c7 28
mazimkhan 0:af1bb8b895c7 29 template <class T> class Node{
mazimkhan 0:af1bb8b895c7 30 public:
mazimkhan 0:af1bb8b895c7 31 Node(T data): d(data), next(NULL), prev(NULL) {}
mazimkhan 0:af1bb8b895c7 32
mazimkhan 0:af1bb8b895c7 33 Node * getNext(){
mazimkhan 0:af1bb8b895c7 34 return next;
mazimkhan 0:af1bb8b895c7 35 }
mazimkhan 0:af1bb8b895c7 36 Node * getPrev(){
mazimkhan 0:af1bb8b895c7 37 return prev;
mazimkhan 0:af1bb8b895c7 38 }
mazimkhan 0:af1bb8b895c7 39 void detach () {
mazimkhan 0:af1bb8b895c7 40 if (prev){
mazimkhan 0:af1bb8b895c7 41 prev->next = next;
mazimkhan 0:af1bb8b895c7 42 }
mazimkhan 0:af1bb8b895c7 43 if (next){
mazimkhan 0:af1bb8b895c7 44 next->prev = prev;
mazimkhan 0:af1bb8b895c7 45 }
mazimkhan 0:af1bb8b895c7 46
mazimkhan 0:af1bb8b895c7 47 next = NULL;
mazimkhan 0:af1bb8b895c7 48 prev = NULL;
mazimkhan 0:af1bb8b895c7 49 }
mazimkhan 0:af1bb8b895c7 50 void append(Node * node) {
mazimkhan 0:af1bb8b895c7 51 Node * n = this;
mazimkhan 0:af1bb8b895c7 52 while (n->getNext()){
mazimkhan 0:af1bb8b895c7 53 n = n->getNext();
mazimkhan 0:af1bb8b895c7 54 }
mazimkhan 0:af1bb8b895c7 55 n->next = node;
mazimkhan 0:af1bb8b895c7 56 if (node){
mazimkhan 0:af1bb8b895c7 57 node->prev = n;
mazimkhan 0:af1bb8b895c7 58 }
mazimkhan 0:af1bb8b895c7 59 }
mazimkhan 0:af1bb8b895c7 60 public:
mazimkhan 0:af1bb8b895c7 61 T d;
mazimkhan 0:af1bb8b895c7 62 private:
mazimkhan 0:af1bb8b895c7 63 Node * next;
mazimkhan 0:af1bb8b895c7 64 Node * prev;
mazimkhan 0:af1bb8b895c7 65 };
mazimkhan 0:af1bb8b895c7 66
mazimkhan 0:af1bb8b895c7 67 template <class T> class List {
mazimkhan 0:af1bb8b895c7 68 public:
mazimkhan 0:af1bb8b895c7 69 List(): head(NULL), tail(NULL){
mazimkhan 0:af1bb8b895c7 70 }
mazimkhan 0:af1bb8b895c7 71 void prepend(Node<T> * node){
mazimkhan 0:af1bb8b895c7 72 if (node){
mazimkhan 0:af1bb8b895c7 73 if (head == NULL && tail == NULL) {
mazimkhan 0:af1bb8b895c7 74 head = tail = node;
mazimkhan 0:af1bb8b895c7 75 } else {
mazimkhan 0:af1bb8b895c7 76 node->append(head);
mazimkhan 0:af1bb8b895c7 77 head = node;
mazimkhan 0:af1bb8b895c7 78 }
mazimkhan 0:af1bb8b895c7 79 }
mazimkhan 0:af1bb8b895c7 80 }
mazimkhan 0:af1bb8b895c7 81 Node<T> * removeTail(){
mazimkhan 0:af1bb8b895c7 82 Node<T> * node = tail;
mazimkhan 0:af1bb8b895c7 83 if (tail) {
mazimkhan 0:af1bb8b895c7 84 tail = tail->getPrev();
mazimkhan 0:af1bb8b895c7 85 node->detach();
mazimkhan 0:af1bb8b895c7 86 }
mazimkhan 0:af1bb8b895c7 87 return node;
mazimkhan 0:af1bb8b895c7 88 }
mazimkhan 0:af1bb8b895c7 89 Node<T> * getHead(){
mazimkhan 0:af1bb8b895c7 90 return head;
mazimkhan 0:af1bb8b895c7 91 }
mazimkhan 0:af1bb8b895c7 92 Node<T> * getTail(){
mazimkhan 0:af1bb8b895c7 93 return tail;
mazimkhan 0:af1bb8b895c7 94 }
mazimkhan 0:af1bb8b895c7 95 void cleanup(){
mazimkhan 0:af1bb8b895c7 96 Node<T> * node = tail;
mazimkhan 0:af1bb8b895c7 97 while(node){
mazimkhan 0:af1bb8b895c7 98 Node<T> * temp = node;
mazimkhan 0:af1bb8b895c7 99 node = node->getPrev();
mazimkhan 0:af1bb8b895c7 100
mazimkhan 0:af1bb8b895c7 101 temp->detach();
mazimkhan 0:af1bb8b895c7 102 delete temp;
mazimkhan 0:af1bb8b895c7 103 }
mazimkhan 0:af1bb8b895c7 104 head = tail = NULL;
mazimkhan 0:af1bb8b895c7 105 }
mazimkhan 0:af1bb8b895c7 106 private:
mazimkhan 0:af1bb8b895c7 107 Node<T> * head;
mazimkhan 0:af1bb8b895c7 108 Node<T> * tail;
mazimkhan 0:af1bb8b895c7 109 };
mazimkhan 0:af1bb8b895c7 110
mazimkhan 0:af1bb8b895c7 111 class Dimension
mazimkhan 0:af1bb8b895c7 112 {
mazimkhan 0:af1bb8b895c7 113 public:
mazimkhan 0:af1bb8b895c7 114 Dimension (int start, int end) {
mazimkhan 0:af1bb8b895c7 115 this->start = start;
mazimkhan 0:af1bb8b895c7 116 this->end = end;
mazimkhan 0:af1bb8b895c7 117 this->cur = start;
mazimkhan 0:af1bb8b895c7 118 }
mazimkhan 0:af1bb8b895c7 119
mazimkhan 0:af1bb8b895c7 120 Dimension (int start, int end, int cur) {
mazimkhan 0:af1bb8b895c7 121 this->start = start;
mazimkhan 0:af1bb8b895c7 122 this->end = end;
mazimkhan 0:af1bb8b895c7 123 this->cur = cur;
mazimkhan 0:af1bb8b895c7 124 }
mazimkhan 0:af1bb8b895c7 125
mazimkhan 0:af1bb8b895c7 126 void operator ++(int){
mazimkhan 0:af1bb8b895c7 127 cur++;
mazimkhan 0:af1bb8b895c7 128 if (cur > end){
mazimkhan 0:af1bb8b895c7 129 cur = start;
mazimkhan 0:af1bb8b895c7 130 }
mazimkhan 0:af1bb8b895c7 131 }
mazimkhan 0:af1bb8b895c7 132
mazimkhan 0:af1bb8b895c7 133 void operator --(int){
mazimkhan 0:af1bb8b895c7 134 cur--;
mazimkhan 0:af1bb8b895c7 135 if (cur < start){
mazimkhan 0:af1bb8b895c7 136 cur = end;
mazimkhan 0:af1bb8b895c7 137 }
mazimkhan 0:af1bb8b895c7 138 }
mazimkhan 0:af1bb8b895c7 139
mazimkhan 0:af1bb8b895c7 140 int operator -(int i){
mazimkhan 0:af1bb8b895c7 141 int r = cur - i;
mazimkhan 0:af1bb8b895c7 142 if (r < start){
mazimkhan 0:af1bb8b895c7 143 r = end;
mazimkhan 0:af1bb8b895c7 144 }
mazimkhan 0:af1bb8b895c7 145 return r;
mazimkhan 0:af1bb8b895c7 146 }
mazimkhan 0:af1bb8b895c7 147
mazimkhan 0:af1bb8b895c7 148 operator int(){
mazimkhan 0:af1bb8b895c7 149 return cur;
mazimkhan 0:af1bb8b895c7 150 }
mazimkhan 0:af1bb8b895c7 151 private:
mazimkhan 0:af1bb8b895c7 152 int start;
mazimkhan 0:af1bb8b895c7 153 int end;
mazimkhan 0:af1bb8b895c7 154 int cur;
mazimkhan 0:af1bb8b895c7 155 };
mazimkhan 0:af1bb8b895c7 156
mazimkhan 0:af1bb8b895c7 157
mazimkhan 0:af1bb8b895c7 158 class SnakeBone {
mazimkhan 0:af1bb8b895c7 159 public:
mazimkhan 0:af1bb8b895c7 160 SnakeBone(int startx, int endx, int curx, int starty, int endy, int cury):
mazimkhan 0:af1bb8b895c7 161 x(startx, endx, curx), y(starty, endy, cury)
mazimkhan 0:af1bb8b895c7 162 {
mazimkhan 0:af1bb8b895c7 163 }
mazimkhan 0:af1bb8b895c7 164
mazimkhan 0:af1bb8b895c7 165 Dimension getX(){
mazimkhan 0:af1bb8b895c7 166 return x;
mazimkhan 0:af1bb8b895c7 167 }
mazimkhan 0:af1bb8b895c7 168
mazimkhan 0:af1bb8b895c7 169 Dimension getY(){
mazimkhan 0:af1bb8b895c7 170 return y;
mazimkhan 0:af1bb8b895c7 171 }
mazimkhan 0:af1bb8b895c7 172
mazimkhan 0:af1bb8b895c7 173 private:
mazimkhan 0:af1bb8b895c7 174 Dimension x;
mazimkhan 0:af1bb8b895c7 175 Dimension y;
mazimkhan 0:af1bb8b895c7 176 };
mazimkhan 0:af1bb8b895c7 177
mazimkhan 0:af1bb8b895c7 178
mazimkhan 0:af1bb8b895c7 179 class Snake {
mazimkhan 0:af1bb8b895c7 180 public:
mazimkhan 0:af1bb8b895c7 181 enum Direction {
mazimkhan 0:af1bb8b895c7 182 UP,
mazimkhan 0:af1bb8b895c7 183 DOWN,
mazimkhan 0:af1bb8b895c7 184 LEFT,
mazimkhan 0:af1bb8b895c7 185 RIGHT
mazimkhan 0:af1bb8b895c7 186 };
mazimkhan 0:af1bb8b895c7 187
mazimkhan 0:af1bb8b895c7 188 Snake (): d(UP){
mazimkhan 0:af1bb8b895c7 189 bones.prepend(new Node<SnakeBone>(SnakeBone(0, 4, 2, 0, 4, 2)));
mazimkhan 0:af1bb8b895c7 190 }
mazimkhan 0:af1bb8b895c7 191
mazimkhan 0:af1bb8b895c7 192 Node<SnakeBone> * getHead(){
mazimkhan 0:af1bb8b895c7 193 return bones.getHead();
mazimkhan 0:af1bb8b895c7 194 }
mazimkhan 0:af1bb8b895c7 195 Dimension getHeadX(){
mazimkhan 0:af1bb8b895c7 196 return _getNodeX(bones.getHead());
mazimkhan 0:af1bb8b895c7 197 }
mazimkhan 0:af1bb8b895c7 198 Dimension getHeadY(){
mazimkhan 0:af1bb8b895c7 199 return _getNodeY(bones.getHead());
mazimkhan 0:af1bb8b895c7 200 }
mazimkhan 0:af1bb8b895c7 201 Dimension getTailX(){
mazimkhan 0:af1bb8b895c7 202 return _getNodeX(bones.getTail());
mazimkhan 0:af1bb8b895c7 203 }
mazimkhan 0:af1bb8b895c7 204 Dimension getTailY(){
mazimkhan 0:af1bb8b895c7 205 return _getNodeY(bones.getTail());
mazimkhan 0:af1bb8b895c7 206 }
mazimkhan 0:af1bb8b895c7 207
mazimkhan 0:af1bb8b895c7 208 void grow(){
mazimkhan 0:af1bb8b895c7 209 // Find next position to place new head
mazimkhan 0:af1bb8b895c7 210 Dimension nextX = getHeadX();
mazimkhan 0:af1bb8b895c7 211 Dimension nextY = getHeadY();
mazimkhan 0:af1bb8b895c7 212
mazimkhan 0:af1bb8b895c7 213 switch (d){
mazimkhan 0:af1bb8b895c7 214 case UP: {
mazimkhan 0:af1bb8b895c7 215 nextY--;
mazimkhan 0:af1bb8b895c7 216 }
mazimkhan 0:af1bb8b895c7 217 break;
mazimkhan 0:af1bb8b895c7 218 case DOWN: {
mazimkhan 0:af1bb8b895c7 219 nextY++;
mazimkhan 0:af1bb8b895c7 220 }
mazimkhan 0:af1bb8b895c7 221 break;
mazimkhan 0:af1bb8b895c7 222 case LEFT: {
mazimkhan 0:af1bb8b895c7 223 nextX--;
mazimkhan 0:af1bb8b895c7 224 }
mazimkhan 0:af1bb8b895c7 225 break;
mazimkhan 0:af1bb8b895c7 226 case RIGHT: {
mazimkhan 0:af1bb8b895c7 227 nextX++;
mazimkhan 0:af1bb8b895c7 228 }
mazimkhan 0:af1bb8b895c7 229 break;
mazimkhan 0:af1bb8b895c7 230 }
mazimkhan 0:af1bb8b895c7 231
mazimkhan 0:af1bb8b895c7 232 // New bone at head
mazimkhan 0:af1bb8b895c7 233 bones.prepend(new Node<SnakeBone>(SnakeBone(0, 4, nextX, 0, 4, nextY)));
mazimkhan 0:af1bb8b895c7 234 }
mazimkhan 0:af1bb8b895c7 235
mazimkhan 0:af1bb8b895c7 236 void reduce(){
mazimkhan 0:af1bb8b895c7 237 Node<SnakeBone> * tail = bones.removeTail();
mazimkhan 0:af1bb8b895c7 238 if (tail){
mazimkhan 0:af1bb8b895c7 239 delete tail;
mazimkhan 0:af1bb8b895c7 240 }
mazimkhan 0:af1bb8b895c7 241 }
mazimkhan 0:af1bb8b895c7 242
mazimkhan 0:af1bb8b895c7 243 void left(){
mazimkhan 0:af1bb8b895c7 244 switch (d){
mazimkhan 0:af1bb8b895c7 245 case UP:
mazimkhan 0:af1bb8b895c7 246 case DOWN: {
mazimkhan 0:af1bb8b895c7 247 d = LEFT;
mazimkhan 0:af1bb8b895c7 248 }
mazimkhan 0:af1bb8b895c7 249 break;
mazimkhan 0:af1bb8b895c7 250 case LEFT: {
mazimkhan 0:af1bb8b895c7 251 d = DOWN;
mazimkhan 0:af1bb8b895c7 252 }
mazimkhan 0:af1bb8b895c7 253 break;
mazimkhan 0:af1bb8b895c7 254 case RIGHT: {
mazimkhan 0:af1bb8b895c7 255 d = UP;
mazimkhan 0:af1bb8b895c7 256 }
mazimkhan 0:af1bb8b895c7 257 break;
mazimkhan 0:af1bb8b895c7 258 }
mazimkhan 0:af1bb8b895c7 259 }
mazimkhan 0:af1bb8b895c7 260
mazimkhan 0:af1bb8b895c7 261 void right(){
mazimkhan 0:af1bb8b895c7 262 switch (d){
mazimkhan 0:af1bb8b895c7 263 case UP:
mazimkhan 0:af1bb8b895c7 264 case DOWN: {
mazimkhan 0:af1bb8b895c7 265 d = RIGHT;
mazimkhan 0:af1bb8b895c7 266 }
mazimkhan 0:af1bb8b895c7 267 break;
mazimkhan 0:af1bb8b895c7 268 case LEFT: {
mazimkhan 0:af1bb8b895c7 269 d = UP;
mazimkhan 0:af1bb8b895c7 270 }
mazimkhan 0:af1bb8b895c7 271 break;
mazimkhan 0:af1bb8b895c7 272 case RIGHT: {
mazimkhan 0:af1bb8b895c7 273 d = DOWN;
mazimkhan 0:af1bb8b895c7 274 }
mazimkhan 0:af1bb8b895c7 275 break;
mazimkhan 0:af1bb8b895c7 276 }
mazimkhan 0:af1bb8b895c7 277 }
mazimkhan 0:af1bb8b895c7 278
mazimkhan 0:af1bb8b895c7 279 void reset(){
mazimkhan 0:af1bb8b895c7 280 bones.cleanup();
mazimkhan 0:af1bb8b895c7 281 bones.prepend(new Node<SnakeBone>(SnakeBone(0, 4, 2, 0, 4, 2)));
mazimkhan 0:af1bb8b895c7 282 d = UP;
mazimkhan 0:af1bb8b895c7 283 }
mazimkhan 0:af1bb8b895c7 284
mazimkhan 0:af1bb8b895c7 285 Direction getDirection(){
mazimkhan 0:af1bb8b895c7 286 return d;
mazimkhan 0:af1bb8b895c7 287 }
mazimkhan 0:af1bb8b895c7 288
mazimkhan 0:af1bb8b895c7 289 private:
mazimkhan 0:af1bb8b895c7 290 Dimension _getNodeX(Node<SnakeBone> * node){
mazimkhan 0:af1bb8b895c7 291 if (node){
mazimkhan 0:af1bb8b895c7 292 return node->d.getX();
mazimkhan 0:af1bb8b895c7 293 }
mazimkhan 0:af1bb8b895c7 294 return Dimension(-1, -1, -1);
mazimkhan 0:af1bb8b895c7 295 }
mazimkhan 0:af1bb8b895c7 296
mazimkhan 0:af1bb8b895c7 297 Dimension _getNodeY(Node<SnakeBone> * node){
mazimkhan 0:af1bb8b895c7 298 if (node){
mazimkhan 0:af1bb8b895c7 299 return node->d.getY();
mazimkhan 0:af1bb8b895c7 300 }
mazimkhan 0:af1bb8b895c7 301 return Dimension(-1, -1, -1);
mazimkhan 0:af1bb8b895c7 302 }
mazimkhan 0:af1bb8b895c7 303
mazimkhan 0:af1bb8b895c7 304 List<SnakeBone> bones;
mazimkhan 0:af1bb8b895c7 305 Direction d;
mazimkhan 0:af1bb8b895c7 306 };
mazimkhan 0:af1bb8b895c7 307
mazimkhan 0:af1bb8b895c7 308 class Game {
mazimkhan 0:af1bb8b895c7 309 public:
mazimkhan 0:af1bb8b895c7 310 Game(MicroBit & ubit): uBit(ubit), foodx(-1), foody(-1), image(5,5),
mazimkhan 0:af1bb8b895c7 311 buttonPressed(false) {
mazimkhan 0:af1bb8b895c7 312 uBit.display.setDisplayMode(DISPLAY_MODE_GREYSCALE);
mazimkhan 0:af1bb8b895c7 313 uBit.display.print(image);
mazimkhan 0:af1bb8b895c7 314 }
mazimkhan 0:af1bb8b895c7 315
mazimkhan 0:af1bb8b895c7 316 void left(){
mazimkhan 0:af1bb8b895c7 317 if (!buttonPressed){
mazimkhan 0:af1bb8b895c7 318 buttonPressed = true;
mazimkhan 0:af1bb8b895c7 319 snake.left();
mazimkhan 0:af1bb8b895c7 320 }
mazimkhan 0:af1bb8b895c7 321 }
mazimkhan 0:af1bb8b895c7 322
mazimkhan 0:af1bb8b895c7 323 void right(){
mazimkhan 0:af1bb8b895c7 324 if (!buttonPressed){
mazimkhan 0:af1bb8b895c7 325 buttonPressed = true;
mazimkhan 0:af1bb8b895c7 326 snake.right();
mazimkhan 0:af1bb8b895c7 327 }
mazimkhan 0:af1bb8b895c7 328 }
mazimkhan 0:af1bb8b895c7 329
mazimkhan 0:af1bb8b895c7 330 bool move(){
mazimkhan 0:af1bb8b895c7 331 // Display food
mazimkhan 0:af1bb8b895c7 332 if (foodx != -1 && foody != -1){
mazimkhan 0:af1bb8b895c7 333 image.setPixelValue(foodx, foody, 255);
mazimkhan 0:af1bb8b895c7 334 uBit.display.print(image);
mazimkhan 0:af1bb8b895c7 335 }
mazimkhan 0:af1bb8b895c7 336
mazimkhan 0:af1bb8b895c7 337 snake.grow();
mazimkhan 0:af1bb8b895c7 338
mazimkhan 0:af1bb8b895c7 339 Dimension nextX = snake.getHeadX();
mazimkhan 0:af1bb8b895c7 340 Dimension nextY = snake.getHeadY();
mazimkhan 0:af1bb8b895c7 341
mazimkhan 0:af1bb8b895c7 342 // Check snake bite
mazimkhan 0:af1bb8b895c7 343 if (image.getPixelValue(nextX, nextY) == 15){
mazimkhan 0:af1bb8b895c7 344 // Game Over
mazimkhan 0:af1bb8b895c7 345 return false;
mazimkhan 0:af1bb8b895c7 346 }
mazimkhan 0:af1bb8b895c7 347
mazimkhan 0:af1bb8b895c7 348 // check if we grew by eating.
mazimkhan 0:af1bb8b895c7 349 if (nextX == foodx && nextY == foody){
mazimkhan 0:af1bb8b895c7 350 // food gone
mazimkhan 0:af1bb8b895c7 351 foodx = -1;
mazimkhan 0:af1bb8b895c7 352 foody = -1;
mazimkhan 0:af1bb8b895c7 353
mazimkhan 0:af1bb8b895c7 354 // Since we have grown to the head. no need to delete tail.
mazimkhan 0:af1bb8b895c7 355 } else {
mazimkhan 0:af1bb8b895c7 356 // Switch off end.
mazimkhan 0:af1bb8b895c7 357 int endx = snake.getTailX();
mazimkhan 0:af1bb8b895c7 358 int endy = snake.getTailY();
mazimkhan 0:af1bb8b895c7 359 if (endx != -1 && endy != -1){
mazimkhan 0:af1bb8b895c7 360 image.setPixelValue(endx, endy, 0);
mazimkhan 0:af1bb8b895c7 361 }
mazimkhan 0:af1bb8b895c7 362 snake.reduce();
mazimkhan 0:af1bb8b895c7 363 }
mazimkhan 0:af1bb8b895c7 364
mazimkhan 0:af1bb8b895c7 365 // Turn On head.
mazimkhan 0:af1bb8b895c7 366 image.setPixelValue(nextX, nextY, 15);
mazimkhan 0:af1bb8b895c7 367 uBit.display.print(image);
mazimkhan 0:af1bb8b895c7 368 buttonPressed = false;
mazimkhan 0:af1bb8b895c7 369 return true;
mazimkhan 0:af1bb8b895c7 370 }
mazimkhan 0:af1bb8b895c7 371
mazimkhan 0:af1bb8b895c7 372 bool isGoodFood(int x, int y){
mazimkhan 0:af1bb8b895c7 373 bool ret = image.getPixelValue(x, y) == 0;
mazimkhan 0:af1bb8b895c7 374
mazimkhan 0:af1bb8b895c7 375 // also don't accept food in the direction of movement
mazimkhan 0:af1bb8b895c7 376 if (ret){
mazimkhan 0:af1bb8b895c7 377 switch(snake.getDirection()){
mazimkhan 0:af1bb8b895c7 378 case Snake::UP:
mazimkhan 0:af1bb8b895c7 379 case Snake::DOWN: {
mazimkhan 0:af1bb8b895c7 380 ret = x != snake.getHeadX();
mazimkhan 0:af1bb8b895c7 381 }
mazimkhan 0:af1bb8b895c7 382 break;
mazimkhan 0:af1bb8b895c7 383 case Snake::LEFT:
mazimkhan 0:af1bb8b895c7 384 case Snake::RIGHT: {
mazimkhan 0:af1bb8b895c7 385 ret = y != snake.getHeadY();
mazimkhan 0:af1bb8b895c7 386 }
mazimkhan 0:af1bb8b895c7 387 break;
mazimkhan 0:af1bb8b895c7 388 }
mazimkhan 0:af1bb8b895c7 389 }
mazimkhan 0:af1bb8b895c7 390 return ret;
mazimkhan 0:af1bb8b895c7 391 }
mazimkhan 0:af1bb8b895c7 392
mazimkhan 0:af1bb8b895c7 393 void play(){
mazimkhan 0:af1bb8b895c7 394 while (true) {
mazimkhan 0:af1bb8b895c7 395 if (!move()){
mazimkhan 0:af1bb8b895c7 396 showGameOver();
mazimkhan 0:af1bb8b895c7 397 break;
mazimkhan 0:af1bb8b895c7 398 }
mazimkhan 0:af1bb8b895c7 399
mazimkhan 0:af1bb8b895c7 400 // Put food
mazimkhan 0:af1bb8b895c7 401 if (foodx == -1 && foody == -1){
mazimkhan 0:af1bb8b895c7 402 while (true){
mazimkhan 0:af1bb8b895c7 403 int x = uBit.random(4);
mazimkhan 0:af1bb8b895c7 404 int y = uBit.random(4);
mazimkhan 0:af1bb8b895c7 405
mazimkhan 0:af1bb8b895c7 406 if (isGoodFood(x, y)){
mazimkhan 0:af1bb8b895c7 407 foodx = x;
mazimkhan 0:af1bb8b895c7 408 foody = y;
mazimkhan 0:af1bb8b895c7 409 break;
mazimkhan 0:af1bb8b895c7 410 }
mazimkhan 0:af1bb8b895c7 411 }
mazimkhan 0:af1bb8b895c7 412 }
mazimkhan 0:af1bb8b895c7 413 uBit.sleep(500);
mazimkhan 0:af1bb8b895c7 414 }
mazimkhan 0:af1bb8b895c7 415 }
mazimkhan 0:af1bb8b895c7 416 void showGameOver(){
mazimkhan 0:af1bb8b895c7 417 // switch off food
mazimkhan 0:af1bb8b895c7 418 if (foodx != -1 && foody != -1){
mazimkhan 0:af1bb8b895c7 419 image.setPixelValue(foodx, foody, 0);
mazimkhan 0:af1bb8b895c7 420 uBit.display.print(image);
mazimkhan 0:af1bb8b895c7 421 }
mazimkhan 0:af1bb8b895c7 422
mazimkhan 0:af1bb8b895c7 423 // change brightness to 255 as pixels with custom brightness
mazimkhan 0:af1bb8b895c7 424 // are not affected by display.setBrightness(). Possible Bug!!!
mazimkhan 0:af1bb8b895c7 425 Node<SnakeBone> * bone = snake.getHead();
mazimkhan 0:af1bb8b895c7 426 while (bone){
mazimkhan 0:af1bb8b895c7 427 image.setPixelValue(bone->d.getX(), bone->d.getY(), 255);
mazimkhan 0:af1bb8b895c7 428 bone = bone->getNext();
mazimkhan 0:af1bb8b895c7 429 }
mazimkhan 0:af1bb8b895c7 430 // Flash snake
mazimkhan 0:af1bb8b895c7 431 uBit.display.print(image);
mazimkhan 0:af1bb8b895c7 432 bool toggle = false;
mazimkhan 0:af1bb8b895c7 433 for (int i = 0; i < 10; i++, toggle = !toggle){
mazimkhan 0:af1bb8b895c7 434 if (toggle)
mazimkhan 0:af1bb8b895c7 435 uBit.display.setBrightness(255);
mazimkhan 0:af1bb8b895c7 436 else
mazimkhan 0:af1bb8b895c7 437 uBit.display.setBrightness(15);
mazimkhan 0:af1bb8b895c7 438 uBit.sleep(500);
mazimkhan 0:af1bb8b895c7 439 }
mazimkhan 0:af1bb8b895c7 440 }
mazimkhan 0:af1bb8b895c7 441
mazimkhan 0:af1bb8b895c7 442 void reset(){
mazimkhan 0:af1bb8b895c7 443 // cleanup snake and state
mazimkhan 0:af1bb8b895c7 444 snake.reset();
mazimkhan 0:af1bb8b895c7 445
mazimkhan 0:af1bb8b895c7 446 foodx = -1;
mazimkhan 0:af1bb8b895c7 447 foody = -1;
mazimkhan 0:af1bb8b895c7 448 image = MicroBitImage(5, 5);
mazimkhan 0:af1bb8b895c7 449 uBit.display.setDisplayMode(DISPLAY_MODE_GREYSCALE);
mazimkhan 0:af1bb8b895c7 450 uBit.display.print(image);
mazimkhan 0:af1bb8b895c7 451 }
mazimkhan 0:af1bb8b895c7 452
mazimkhan 0:af1bb8b895c7 453
mazimkhan 0:af1bb8b895c7 454 private:
mazimkhan 0:af1bb8b895c7 455 MicroBit & uBit;
mazimkhan 0:af1bb8b895c7 456 int foodx;
mazimkhan 0:af1bb8b895c7 457 int foody;
mazimkhan 0:af1bb8b895c7 458 Snake snake;
mazimkhan 0:af1bb8b895c7 459 MicroBitImage image;
mazimkhan 0:af1bb8b895c7 460
mazimkhan 0:af1bb8b895c7 461 // Sync button press and movement. Don't let quick button presses
mazimkhan 0:af1bb8b895c7 462 // change snake direction twice/thrice/... before moving. As a
mazimkhan 0:af1bb8b895c7 463 // double press can reverse the snake on its own and Game Over!!!
mazimkhan 0:af1bb8b895c7 464 bool buttonPressed;
mazimkhan 0:af1bb8b895c7 465 };
mazimkhan 0:af1bb8b895c7 466
mazimkhan 0:af1bb8b895c7 467
mazimkhan 0:af1bb8b895c7 468 MicroBit uBit;
mazimkhan 0:af1bb8b895c7 469 Game game(uBit);
mazimkhan 0:af1bb8b895c7 470
mazimkhan 0:af1bb8b895c7 471
mazimkhan 0:af1bb8b895c7 472 void onButtonA(MicroBitEvent){
mazimkhan 0:af1bb8b895c7 473 game.left();
mazimkhan 0:af1bb8b895c7 474 }
mazimkhan 0:af1bb8b895c7 475
mazimkhan 0:af1bb8b895c7 476 void onButtonB(MicroBitEvent){
mazimkhan 0:af1bb8b895c7 477 game.right();
mazimkhan 0:af1bb8b895c7 478 }
mazimkhan 0:af1bb8b895c7 479
mazimkhan 0:af1bb8b895c7 480 int main()
mazimkhan 0:af1bb8b895c7 481 {
mazimkhan 0:af1bb8b895c7 482 // Initialise the micro:bit runtime.
mazimkhan 0:af1bb8b895c7 483 uBit.init();
mazimkhan 0:af1bb8b895c7 484
mazimkhan 0:af1bb8b895c7 485 uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, onButtonA);
mazimkhan 0:af1bb8b895c7 486 uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonB);
mazimkhan 0:af1bb8b895c7 487
mazimkhan 0:af1bb8b895c7 488 // Continous play
mazimkhan 0:af1bb8b895c7 489 while (true)
mazimkhan 0:af1bb8b895c7 490 {
mazimkhan 0:af1bb8b895c7 491 game.play();
mazimkhan 0:af1bb8b895c7 492
mazimkhan 0:af1bb8b895c7 493 uBit.display.print(MicroBitImage(5,5));
mazimkhan 0:af1bb8b895c7 494 uBit.display.setBrightness(255);
mazimkhan 0:af1bb8b895c7 495 uBit.display.scroll("URBITTEN"); // don't mind spaces in a scrolling display.
mazimkhan 0:af1bb8b895c7 496
mazimkhan 0:af1bb8b895c7 497 game.reset();
mazimkhan 0:af1bb8b895c7 498 }
mazimkhan 0:af1bb8b895c7 499 }