Snake game on nokia N5110 LCD

Dependencies:   mbed

Snake game on nokia N5110 LCD and Keyes Syos Joystick. You control snake using joystick. Start/pause game ba using button on joystick or by pressing p on your keyboard (serial communication). More info on my blog: http://sdizdarevic.com/post/94147065625/frdm-k64f-project

Revision:
0:5bdb67970267
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Snakelib.h	Fri Aug 08 06:44:50 2014 +0000
@@ -0,0 +1,341 @@
+#ifndef E_SNAKE_H
+#define E_SNAKE_H
+#include <cstdlib>
+#include "mbed.h"
+#include "N5110.h"
+#include "Helper.h" 
+class Snakelib
+    {
+        static const bool SnakeTypes [2][6][3][3];
+        static const bool SnakeFood [5][3][3];
+        static const int Pos [2][3][3];
+        short Snake [438][2];
+        static const double Speeds [10];
+        static const unsigned char Points[10];
+        AnalogIn VX, VY;
+        InterruptIn SW;
+        int HScore, Score;
+        int SnakeLen, Speed;
+        int SnakeType, FoodType;
+        int eX, eY, pX, pY, Dir;
+        bool Moved, Pause, Draw, Started;
+        N5110 DISP;
+        DigitalOut ENBL;
+        Ticker TJoy, TMove;
+        Timer Dbnc;
+        Ticker T;
+        void SetBlock (int Block = 0, int X = 1, int Y = 1)
+            {
+                for (int a = 0; a < 3; ++a)
+                    for (int b = 0; b < 3; ++b)
+                        if (Block == 2 && SnakeFood [FoodType][a][b])
+                            DISP.setPixel (X + Pos[0][a][b], Y + Pos[1][a][b]);
+                        else if (Block < 2 && SnakeTypes [Block][SnakeType][a][b])
+                            DISP.setPixel (X + Pos[0][a][b], Y + Pos[1][a][b]);                
+            }
+        int Rand (int Min = 1, int Max = 83)
+            {
+                static bool First = true;
+                if (First) srand (time (NULL)), First = false;
+                while (7)
+                    {
+                        int S = rand () % (Max - Min + 1) + Min;
+                        if (!((S - 1)  % 3)) return S;
+                    }
+            }
+        void GameOver ()
+            {
+ 
+                //FlashB();
+                wait (2);
+                DISP.clear();
+                DISP.setXYAddress (0, 0);
+                DISP.printString ("END!", 29, 0);
+                DISP.printString ("Score: ", 10, 2);
+                char Buff[20];
+                ToString (Buff, Score);
+                DISP.printString (Buff, 50, 2);
+                DISP.printString ("Best: ", 10, 4);
+                ToString (Buff, HScore);
+                DISP.printString (Buff, 50, 4);
+                eX = eY = 0; //
+                Started = false;
+                wait (3);
+                Restart();
+            }
+        void Prekuco()
+            {
+                DISP.clear();
+                DISP.setXYAddress (0, 0);
+                DISP.printString ("Well done!!!!!", 0, 0);
+                DISP.printString ("Congrats", 0, 2);
+                eX = eY = 0;
+                Started = false;
+                wait (3);
+                Restart();
+            }
+        void HitFood ()
+            {
+                if (Snake [0][0] == pX && Snake [0][1] == pY)
+                    {
+                        Score += Points[Speed - 1];
+                        AddSnakeBody();
+                        RandFood(pX, pY);
+                    }
+            }
+        void HitWall()
+            {
+                if (Snake[0][0] + 1 > 83 || Snake[0][0] - 1 < 0 || Snake[0][1] + 1 > 47 || Snake[0][1] - 1 < 0)
+                    {
+                        if (Score > HScore)
+                            HScore = Score;
+                        Started = false;;
+                        GameOver();
+                        return;
+                    }
+            }
+        void HitSelf()
+            {
+                for (int a  = 1; a <= SnakeLen; ++a)
+                    if (Snake[0][0] == Snake[a][0] && Snake[0][1] == Snake[a][1])
+                        {
+                            if (Score > HScore)
+                                HScore = Score;
+                            GameOver();
+                            return;
+                        }
+            }
+        void Start()
+            {
+                Snake[0][0] = Rand(20, 70);
+                Snake[0][1] = Rand(10, 35);
+                RandFood(pX, pY);
+                AddSnakeBody();
+                AddSnakeBody();
+                Refresh();
+            }
+        void FlashB ()
+            {
+                for (int z = 0; z < 5; ++z)
+                    {
+                        DISP.clear();
+                        DISP.setXYAddress (0, 0);
+                        DISP.refresh();
+                        wait (0.5);
+                        DrawWall();
+                        for (int a = 0; a <= SnakeLen; ++a)
+                            SetBlock(a == 0 ? 0 : 1, Snake[a][0], Snake[a][1]);
+                        SetBlock(2, pX, pY);
+                        DISP.refresh();
+                    }
+            }
+        void MoveSnake ()
+            {
+                if (Pause || !Started) return;
+                for (int a = SnakeLen; a >= 1; --a)
+                    {
+                        Snake[a][0] = Snake[a - 1][0];
+                        Snake[a][1] = Snake[a - 1][1];
+                    }
+                Snake[0][0] += eX;
+                Snake[0][1] += eY;
+                Moved = true;  
+                Refresh();
+            }   
+        void AddSnakeBody()
+            {
+                SnakeLen++;
+                int X = 0, Y = 0;
+                if (Dir == 0) X = 3, Y = 0;
+                if (Dir == 1) X = 0, Y = 3;
+                if (Dir == 2) X = -3, Y = 0;
+                if (Dir == 3) X = 0, Y = -3;
+                Snake [SnakeLen][0] = Snake[SnakeLen - 1][0] + X;
+                Snake [SnakeLen][1] = Snake[SnakeLen - 1][1] + Y;
+            }
+        void RandFood(int &X, int &Y)
+            {
+                while (7)
+                    {
+                        int A = Rand(1, 83);
+                        int B = Rand(1, 47);
+                        bool S = false;
+                        for (int I = 0; I <= SnakeLen; ++I)
+                            if (Snake[I][0] == A && Snake[I][1] == B)
+                                S = true;
+                        if (!S) {X = A; Y = B; return;}
+                    }
+            }
+        void DrawWall ()
+            {
+                for (int a = 0; a < 84; ++a)
+                    for (int b = 0; b < 48; ++b)
+                        if (!a || !b || a == 83 || b == 47)
+                            DISP.setPixel (a, b);
+            }
+        void Refresh ()
+            {
+                if (!Draw) return;
+                HitFood();
+                HitWall();
+                HitSelf();
+                DISP.clear();
+                DISP.setXYAddress (0, 0);
+                DrawWall();
+                for (int a = 0; a <= SnakeLen; ++a)
+                    SetBlock(a == 0 ?  0 : 1, Snake[a][0], Snake[a][1]);
+                SetBlock(2, pX, pY);
+                DISP.refresh();
+                if (SnakeLen > 437) Prekuco();            
+            }
+        void Moving () 
+            {
+                if (!Moved) return;
+                double vx = VX, vy = VY;
+                if (vx < 1./3.) 
+                    {
+                        if (Dir == 2) return;
+                        eX = -3; eY = 0;
+                        Dir = 0;
+                        Moved = false;
+                    }
+                else if (vx > 2./3.)
+                    {
+                        if (Dir == 0) return;
+                        eX = 3; eY = 0;
+                        Dir = 2;
+                        Moved = false;
+                    }
+                if (vy < 1./3.) 
+                    {
+                        if (Dir == 1) return;
+                        eX = 0; eY = -3;
+                        Dir = 3;
+                        Moved = false;
+                    }
+                else if (vy > 2./3.)
+                    {
+                        if (Dir == 3) return;
+                        eX = 0; eY = 3;
+                        Dir = 1;
+                        Moved = false;
+                    }
+            }
+        void Pressed () 
+            {
+                if (Dbnc.read()  > .2)
+                    {
+                        if (!Started) 
+                            {
+                                Started = true;
+                                TMove.attach (this, &Snakelib::MoveSnake, Speeds[Speed - 1]);
+                            }
+                        else 
+                            {
+                                Pause = !Pause;
+                                Draw = !Pause;
+                            }
+                    }
+                Dbnc.reset();
+            }
+    public:
+        Snakelib (PinName P1, PinName P2, PinName P3, PinName P4, PinName P5, 
+                    PinName P6, PinName P7, PinName BX, PinName BY, PinName BS) 
+            :   VX (BX), VY (BY), SW (BS), HScore (0), Score (0), SnakeLen (0), Speed (6), SnakeType (0),
+                FoodType (0), eX (3), eY (0), pX(0), pY (0), Dir (2), Moved(false), Pause (false), Draw (true), Started (false),
+                DISP (P1, P2, P3, P4, P5, P6, P7), ENBL (LED_RED)
+            {
+ 
+            }
+        void START()
+            {
+                ENBL = 1;
+                Dbnc.start();
+                SW.mode (PullUp);
+                DISP.init();
+                DISP.setXYAddress (0, 0);
+                DISP.clear();
+                TJoy.attach (this, &Snakelib::Moving, 0.01);
+                DISP.printString ("- SNAKE   -", 0, 0);
+                DISP.printString ("K64F", 0, 3);
+                DISP.printString ("Freescale", 0, 4);
+                wait (2);
+                SW.rise (this, &Snakelib::Pressed);
+                Start();
+                
+                
+            }
+        int SnakeSpeed () const {return Speed;}
+        void SetSnakeSpeed (unsigned char S)
+            {
+                if (S == Speed) return;
+                Speed = S;
+                Speed = Speed < 1 ? 1 : Speed > 10 ? 10 : Speed;
+                TMove.detach();
+                wait_ms (2);
+                TMove.attach (this, &Snakelib::MoveSnake, Speeds[Speed - 1]);
+            }
+        int GetSnakeType () const {return SnakeType + 1;}
+        void SetSnakeType (unsigned char S)
+            {
+                if (S == SnakeType) return;
+                int ST = S < 1 ? 1 : S > 6 ? 6 : S;
+                SnakeType = ST - 1;
+                Refresh();
+            }
+        int GetFoodType () const {return FoodType + 1;}
+        void SetFoodType (unsigned char S)
+            {
+                if (S == FoodType) return;
+                int FT = S < 1 ? 1 : S > 5 ? 5 : S;
+                FoodType = FT - 1;
+                Refresh();
+            }
+        void PauseGame () {Pause = true; Draw = false;}
+        void ResumeGame () {Pause = false; Draw = true;}
+        bool Paused () const {return Pause;}
+        void Restart()
+            {
+                TMove.detach();
+                SnakeLen  = eY = Score = 0;
+                eX = 3;
+                Dir = 2;
+                Started = false;
+                Start();
+            }
+    };
+const bool Snakelib::SnakeTypes [2][6][3][3] = 
+    {
+        {
+            {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
+            {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}},
+            {{0, 1, 0}, {1, 1, 1}, {0, 1, 0}},
+            {{0, 1, 0}, {1, 0, 1}, {0, 1, 0}},
+            {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
+            {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}
+        },
+        {
+            {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}},
+            {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
+            {{0, 1, 0}, {1, 0, 1}, {0, 1, 0}},
+            {{0, 1, 0}, {1, 1, 1}, {0, 1, 0}},
+            {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
+            {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}
+        }
+    };
+const bool Snakelib::SnakeFood [5][3][3] =  
+    {
+        {{1, 0, 1}, {0, 1, 0}, {1, 0, 1}},
+        {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
+        {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}},
+        {{0, 1, 0}, {1, 1, 1}, {0, 1, 0}},
+        {{0, 1, 0}, {1, 0, 1}, {0, 1, 0}}    
+    };
+const int Snakelib::Pos [2][3][3] = 
+    {
+        {{-1, 0, 1}, {-1, 0, 1}, {-1, 0, 1}},
+        {{1, 1, 1}, {0, 0, 0}, {-1, -1, -1}}
+    };
+const double Snakelib::Speeds [10] = {1., .8, .7, .5, .32, .25, .15, .1, .075, .050};
+const unsigned char Snakelib::Points[10] = {1, 1, 1, 2, 3, 4, 5, 6, 8, 10};
+#endif  //E_SNAKE_H