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

Snakelib.h

Committer:
sdizdarevic
Date:
2014-08-08
Revision:
0:5bdb67970267

File content as of revision 0:5bdb67970267:

#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