Snake vs Block Game to be run upon K64F.

Dependencies:   mbed

Revision:
51:387249f9b333
Parent:
50:3cf9a94a264e
Child:
52:c2faa96cf293
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GameEngine/SnakevsBlock/SnakevsBlock.cpp	Fri Apr 26 18:30:25 2019 +0000
@@ -0,0 +1,295 @@
+#include "SnakevsBlock.h"
+
+SnakevsBlock::SnakevsBlock()
+{
+
+}
+
+SnakevsBlock::~SnakevsBlock()
+{
+
+}
+
+void SnakevsBlock::init()
+{
+    //The level initialisation and all the other initial information passing will be done here
+    level = 1;
+    garbage = 0; //this is to allow the user to change the position of reference for motion control by saving the absolute angle.
+    foodbuff = 0; //this makes the food fall at diffrent times when a particular level starts.
+    send_block_number = 0;
+    blockgap = 300;
+    blockbuff = -50;
+    for(int i=0; i<=14; i++)  {b[i] = 1;} //makes all the snake beads move by default.
+    SnakevsBlock::object_initialisations();
+}
+
+void SnakevsBlock::reset()
+{
+    //This prepares the game for the next level by reseting certain variables.
+    foodbuff = 0;
+    for(int i=0; i<=2; i++)  {
+        food_pos[i].x = 0;
+        food_pos[i].y = 0;
+    }
+    if(blockgap >= 50) {blockgap -= 40;}  //to make progressive levels harder by making the blocks drop more frequently.
+    SnakevsBlock::object_initialisations();
+}
+
+void SnakevsBlock::object_initialisations()
+{
+    _l.init(); //length calc object initialisation.
+    _s.init(); //snake object initialisation.
+    _f.init(); //food 1 object initialisation.
+    _ff.init(); //food 2 object initialisation.
+    _fff.init(); //food 3 object initialisation.
+    _b.init(); //block object initialisation.
+}
+
+void SnakevsBlock::read_input(Gamepad &pad, FXOS8700CQ &device, int g_mode)
+{
+    device.get_values();
+    angle = -device.get_roll_angle();
+    //if button A is pressed then reset that particular position to center
+    if (pad.check_event(Gamepad::A_PRESSED) == true)  {
+        garbage = angle;
+    }
+    device.get_values();
+    angle = -device.get_roll_angle() - garbage;
+    if(g_mode == 1)  { //this condition returns the relevant working directions if we select joystick in StartScreen.
+        _d = pad.get_direction(); //Obtains Direction pushed towards on Joystick.
+        _mag = pad.get_mag(); //Obtains Magnitude of Joystick.
+    }
+    else if(g_mode == 2)  { //this condition returns the relevant working directions if we select motion control in StartScreen.
+        if (angle >= 8) {
+            _d = E;
+        }
+        else if (angle <= -8) {
+            _d = W;
+        }
+        else {
+            _d = CENTRE;
+        }
+    }
+    device.get_values();
+    //printf("%d",gm);
+    //printf("%f",angle);
+    //printf("%f",device.get_roll_angle());
+}
+
+void SnakevsBlock::draw(N5110 &lcd, Gamepad &pad)   {
+    _length = _l._getLength();
+    _s.draw(pad, lcd, _length, level); //Draws the Snake.     //Make these snake buffs relative to the snake drops which in turn relate to the game speed
+    if(foodbuff >= 0)  {
+        _f.draw(lcd, blockbuff); //Draws the first food.
+    }
+    if(foodbuff >= 50)  {
+        _ff.draw(lcd, blockbuff); //Draws the second food.
+    }
+    if(foodbuff >= 80) {
+        _fff.draw(lcd, blockbuff); //Draws the third food.
+    }
+    foodbuff +=1;
+    if(foodbuff >= 8) {
+        _b.draw(lcd, _length);
+    }
+    if(foodbuff == 8) {
+        blockbuff = -10;
+    }
+    //Code to print length on game screen.
+    _l.print_length_on_screen(lcd);
+} 
+
+int SnakevsBlock::update(N5110 &lcd, Gamepad &pad, SDFileSystem &sd) //Updates objects on screen.
+{
+    send_block_number = 0;  //this is for the game to decide wether to remember the number on the block for the current itteration.
+                            //we dont need to remember if it has already gone past the screen.
+    CheckSnakeFoodCollision(pad); //Function checks for when the snake collides with it's food.
+    CheckSnakeBlockCollision(pad); //Function checks for when the snake collides with any of the blocks.
+    CheckSnakeBlockSidesCollision(pad); //Function checks for when the snake collides with any of the blocks' sides.
+    _s.update(_d, b); //_d is the direction of joystick and b controls the motion of a section of the snake relative to obstruction
+    _f.update();
+    _ff.update();
+    _fff.update(); 
+    _b.update(blocknum, blockgap, srn, send_block_number);
+    blockbuff++;
+    if(blockbuff >= blockgap)  {  //this makes blockbuff reset every time the new set of blocks appear.
+        blockbuff = -11;
+    }
+    //_statset.read(sd); //to read the currently stored value.
+    if(_length == 0)  {
+        _wl.GameOver(lcd,pad);
+    }
+    if((pad.check_event(Gamepad::BACK_PRESSED))||(_length == 0)){ //Waits for Back button to be pressed.
+        back = 1;
+        SnakevsBlock::init();
+    }
+    else {
+        back = 0;
+    }
+    printf("%d\n",_length);
+    if(_length >= 20)  {
+        level = _wl.LevelComplete(lcd, pad, level);
+        _Setstats.write(level, sd);
+        SnakevsBlock::reset();
+    }
+    return back;
+}
+
+void SnakevsBlock::get_pos()
+{
+    //printf("player pos = %f %f \n", player_pos.x, player_pos.y); //top left of player sprite
+    // 81.000000 0.000000 top right
+    // 0.000000 0.000000 is top left
+    // 81.000000 45.000000 bottom right
+    snakex = _s.get_pos().x; //this could be snake_pos[0].x or simply snake_pos[0] to represent both x&y but as it is used the most, it improves readability. 
+    snakey = _s.get_pos().y; //this could be snake_pos[0].y or simply snake_pos[0] to represent both x&y but as it is used the most, it improves readability.
+    //printf("snakexy in GAME = %d %d \n", snakex, snakey);
+    //Obtains all required coordinates.
+    food_pos[0] = _f.get_pos();
+    food_pos[1] = _ff.get_pos();
+    food_pos[2] = _fff.get_pos();
+    //obtains origin cordinates of block.
+    b_pos = _b.get_pos();
+    //this saves the positions of each snake beed (the first to the last) in a single array. Element[0] is the top beed and soo on.
+    snake_pos[0] = _s.get_pos(); //gets the position of the top beed and saves in array.
+    snake_pos[1] = _s.get_pos_before1(); //gets the position of the second beed and saves in array.
+    snake_pos[2] = _s.get_pos_before2(); //gets the position of the third beed and saves in array.
+    snake_pos[3] = _s.get_pos_before3(); //gets the position of the fourth beed and saves in array.
+    snake_pos[4] = _s.get_pos_before4(); //gets the position of the fifth beed and saves in array.
+    snake_pos[5] = _s.get_pos_before5(); //gets the position of the sixth beed and saves in array.
+    snake_pos[6] = _s.get_pos_before6(); //gets the position of the seventh beed and saves in array.
+    snake_pos[7] = _s.get_pos_before7(); //gets the position of the eight beed and saves in array.
+    snake_pos[8] = _s.get_pos_before8(); //gets the position of the ninth beed and saves in array.
+    snake_pos[9] = _s.get_pos_before9(); //gets the position of the last beed and saves in array.
+}   
+    
+
+void SnakevsBlock::CheckSnakeFoodCollision(Gamepad &pad)    {
+    //If statements check if the snake sprite has collided with any
+    //of the three food sprites, if so then the food location is reset and
+    //length of the snake is increased using the length variable.
+    for(int y=0; y<=2; y++)  {    //this loop automatically detects each combination of collision in the y postion
+        for(int x=0; x<=2; x++)  {    //this loop automatically detects each combination of collision in the x postion
+            for(int food_sr=0; food_sr<=2; food_sr++)  {    //this loop automatically detects which food we are interacting with.
+                if (
+                    ((snakey + y == food_pos[food_sr].y) ||
+                    (snakey + y == food_pos[food_sr].y + 1) ||
+                    (snakey + y == food_pos[food_sr].y + 2)) &&
+                    ((snakex + x == food_pos[food_sr].x) ||
+                    (snakex + x == food_pos[food_sr].x + 1) ||
+                    (snakex + x == food_pos[food_sr].x + 2))
+                ) {
+                    //printf("snake feast working \n");
+                    //audio feedback
+                    pad.tone(786.0,0.1);
+                    food_pos[food_sr].x = (rand() % 82);  //this makes the food pop up at a random, unspecified location in the x axis.
+                    food_pos[food_sr].y = -3;
+                    _l.PlusLength();
+                }
+            }
+        }
+    }
+    _f.set_pos(food_pos[0]);
+    _ff.set_pos(food_pos[1]);
+    _fff.set_pos(food_pos[2]);
+}
+    
+void SnakevsBlock::CheckSnakeBlockCollision(Gamepad &pad)  {
+    //Obtains the numbers inside the block.
+    b_number = _b.get_number();
+    //If statements check if the snake sprite has collided with any
+    //of the blocks which are a maximum of 5, if so then the snake length reduces and the block number reduces
+    //the block has to move slower and come down after every 2/3 iterations(dependent on the snake size.(think about this)
+    for(int block=0; block<=83; block+=1)  {    //this loop automatically detects for each section of block and each combination of collision
+        if (((snakey == b_pos.y + 11)||(snakey == b_pos.y + 10)||(snakey == b_pos.y + 9)) && (snakex + 1 == b_pos.x + block))  {
+            //the or for the block's y position is due to the fact the exact y co-ordinate might not be collided if the snake's length has increased in the same itteration.
+            //printf("snake collision working \n");
+            //audio feedback
+            if(blocknum > 0)  {b_pos.y = 0;}  //change this to speed y = 0 when length = 10.
+            srn = CheckBlock(block);  //this tells us which of the 5 blocks we are colliding with
+            blocknum = b_number[srn];
+            if((_length>=10)&&(b_number[srn]>0)) { //this makes the block stop moving down if it's length is more than 10 and still collides.
+                velocity = 0;
+            }
+            else {
+                velocity = 1;
+            }
+            ImplementCollision(pad);
+            SnakevsBlock::_set_velocity();
+        }
+    }
+}
+ 
+void SnakevsBlock::_set_velocity()  {
+    _b.velocity.y = velocity;
+    _f.velocity.y = velocity;
+    _ff.velocity.y = velocity;
+    _fff.velocity.y = velocity;
+}
+ 
+int SnakevsBlock::CheckBlock(int block)  {
+    int srn;
+    if((block>=0)&&(block<=18))  {srn = 0;}
+    if((block>=19)&&(block<=34))  {srn = 1;}
+    if((block>=35)&&(block<=50))  {srn = 2;}
+    if((block>=51)&&(block<=66))  {srn = 3;}
+    if((block>=67)&&(block<=83))  {srn = 4;}
+    return srn;
+}
+    
+void SnakevsBlock::ImplementCollision(Gamepad &pad)  {
+    send_block_number = 1;
+    if(blocknum > 0)  {  // to make sure that snake doesn't decrease in _length if number on the block is less than 1;
+        _l.MinusLength();
+        pad.tone(1000.0,0.1);
+        wait(0.04);
+    }
+    blocknum-=1;
+}
+
+void SnakevsBlock::CheckSnakeBlockSidesCollision(Gamepad &pad)
+{
+    //If statements check if the snake sprite has collided with any
+    //of the blocks' sides and then stop the snake moving in x axis
+    int length = _length;
+    if(_length>=10) {length = 10;} //to stop the snake length virtually at 10 when it goes past it.
+    
+    for(int i=0; i<=9; i++)  {
+        b[i] = 1;
+    }
+    for(int i=0; i<=9; i++)  { //i checks for all possible collisions with the snake respective to it's length.
+        for(int b_y_combination=0; b_y_combination<=10; b_y_combination++)  {
+            if (
+                (snake_pos[i].y == b_pos.y + b_y_combination) ||
+                (snake_pos[i].y + 1 == b_pos.y + b_y_combination) ||
+                (snake_pos[i].y + 2 == b_pos.y + b_y_combination))  {
+                for(int b_x_combination=2; b_x_combination<=82; b_x_combination+=16)  {
+                    //For West side of walls 
+                    if(
+                        ((snake_pos[i].x == b_pos.x + b_x_combination+2) ||  //W
+                        (snake_pos[i].x + 1 == b_x_combination+2))&&(_d != E)&&(length > i) //W
+                        ) {
+                        //code makes sure that the colliding part doesn't move in x axis.
+                        for(int snake_beed_num=0; snake_beed_num<=10; snake_beed_num++)  {
+                            if(length == snake_beed_num + i)  {
+                                b[snake_beed_num - 1] = 0;
+                            }
+                        }
+                    }
+                    //for East side of walls
+                    else if (
+                        ((snake_pos[i].x + 1 == b_x_combination) ||  //E
+                        (snake_pos[i].x + 2 == b_x_combination))&&(_d != W)&&(length > i) //E
+                    ) {
+                        //code makes sure that the colliding part doesn't move in x axis.
+                        for(int snake_beed_num=0; snake_beed_num<=10; snake_beed_num++)  {
+                            if(length == snake_beed_num + i)  {
+                                b[snake_beed_num - 1] = 0;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file