ELEC2645 (2019/20) / Mbed 2 deprecated ELEC2645_Project_ll16j23s

Dependencies:   mbed ll16j23s_test_docs

SnakeBody/SnakeBody.cpp

Committer:
JoeShotton
Date:
2020-05-26
Revision:
10:a2d643b3c782
Parent:
9:0571880085cc
Child:
13:7b7ec5db56b2

File content as of revision 10:a2d643b3c782:

#include "SnakeBody.h"

SnakeBody::SnakeBody()
{
    _x_head = 42;
    _y_head = 24;
    _length = 4;
    _length_increase = 4;
    _angle = -1.0;
    _move_state = 0;
    _d = 0;
}

SnakeBody::~SnakeBody()
{
//destructor
}

void SnakeBody::init()
{
    _body_x.clear();
    _body_x.push_back(42);
    _body_y.clear();
    _body_y.push_back(24);
}

void SnakeBody::update_direction()
{

    if ((_x_head % 2) + (_y_head % 2) == 0) {   // only allows changing movement when the snake is cell-aligned (ie x and y are even)
        // partition 360 into segments and check which segment the angle is in
        printf("D: %d\n", _d);
        if (_angle < 0.0f) {          //check for -1.0 angle
            _d = 0;
        } else if (_angle < 45.0f) {  //North quadrant
            _d = 1;
        } else if (_angle < 135.0f) { //East quadrant
            _d = 2;
        } else if (_angle < 225.0f) { //South quadrant
            _d = 3;
        } else if (_angle < 315.0f) { //West quadrant
            _d = 4;
        } else {                      //NW half - quadrant
            _d = 1;
        }
    }
};

void SnakeBody::update_position()
{

    Direction _fsm[5] = {
        {0,  0, {0,1,2,3,4}},  // Centred
        {0, -1, {1,1,2,1,4}},  // North, will not go to centre or south
        {1,  0, {2,1,2,3,2}},  // East, will not go to centre or west
        {0,  1, {3,3,2,3,4}},  // South, will not go to centre or north
        {-1, 0, {4,1,4,3,4}}   // West, will not go to centre or east
    };

    _move_state = _fsm[_move_state].nextState[_d]; // adjusts fsm state based on direction
    //printf("State: %d\n", _move_state);

    _x_head += _fsm[_move_state].delta_x; // increments x value based on fsm state value
    _y_head += _fsm[_move_state].delta_y; // increments y value based on fsm state value

    _x_head = ((_x_head % 84) + 84) % 84; // wraps x back to within range 0-83
    _y_head = ((_y_head % 48) + 48) % 48; // wraps y back to within range 0-47

    //printf("x_head: %d\n", _x_head);
    //printf("y_head: %d\n", _y_head);
};

void SnakeBody::snake_movement(Gamepad &pad)
{

    _angle = pad.get_angle(); //finds joystick angle
    //printf("Angle: %f\n", _angle);
    update_direction(); //converts angle into a integer direction
    update_position();  //takes integer direction and feeds it into FSM to move snake in correct direction
    update_body();      //feeds head coords into body vectors and remove old ones
}

void SnakeBody::update_body()
{
    if ((_x_head % 2) + (_y_head % 2) == 0) {        //only updates body when cell aligned
        _body_x.insert(_body_x.begin(), _x_head);    //sets first array element to head coordinates
        _body_y.insert(_body_y.begin(), _y_head);

        _body_x.erase(_body_x.begin() + _length, _body_x.end()); //erases all elements from position after tail (ie [_length])
        _body_y.erase(_body_y.begin() + _length, _body_y.end()); //up to end of vector
    }
    if(_length_increase > 0) { //converts length increase into length, one unit at a time
        _length++;
        _length_increase--;
    }
}


void SnakeBody::draw_body(N5110 &lcd)
{
    lcd.drawRect(_x_head,_y_head,2,2,FILL_BLACK); //draws square at head (so new head coords displayed even when not cell-aligned) 
    for(int i = 0; i < _length - 3; i++) { //iterates across vector to draw sqaures at every position
        lcd.drawRect(_body_x[i],_body_y[i],2,2,FILL_BLACK);
    }
}

void SnakeBody::snake_snake_collision(Gamepad &pad, bool &_death)
{
    if (_move_state > 0) { //if body has started to move
        for(int i = 3; i < _length - 3; i++) { //only checks from 3rd cell onwards since head can't collide with very start of body
            if (_x_head == _body_x[i] && _y_head == _body_y[i]) { //checks if head coord is the same as any of the body coords
                //printf("S-S Collison \n");
                _move_state = 0;
                _death = true;
            }
        }
    }
}

void SnakeBody::add_length(int increase) {
    _length_increase += increase;
}

void SnakeBody::run(Gamepad &pad, N5110 &lcd, bool &_death)
{
    snake_movement(pad);
    draw_body(lcd);
    snake_snake_collision(pad, _death);
    //printf("Body running!");
}

void SnakeBody::reset()
{
    _x_head = 42;
    _y_head = 24;
    for(int i = 3; i < _body_y.size(); i++) {
        _body_y.at(i) = 50;
    }
    _length = 4;
    _length_increase = 4;
    _move_state = 0;
}