ELEC2645 (2019/20) / Mbed 2 deprecated ELEC2645_Project_ll16j23s

Dependencies:   mbed ll16j23s_test_docs

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SnakeBody.cpp Source File

SnakeBody.cpp

00001 #include "SnakeBody.h"
00002 
00003 SnakeBody::SnakeBody()
00004 {
00005     head_x = 42;
00006     head_y = 24;
00007     _length = 4;
00008     _length_increase = 4;
00009     _angle = -1.0;
00010     _move_state = 0;
00011     _d = 0;
00012 }
00013 
00014 SnakeBody::~SnakeBody()
00015 {
00016 //destructor
00017 }
00018 
00019 void SnakeBody::init()
00020 {
00021     body_x.clear();
00022     body_x.push_back(42);
00023     body_y.clear();
00024     body_y.push_back(24);
00025 }
00026 
00027 void SnakeBody::update_direction()
00028 {
00029 
00030     if ((head_x % 2) + (head_y % 2) == 0) {   // only allows changing movement when the snake is cell-aligned (ie x and y are even)
00031         // partition 360 into segments and check which segment the angle is in
00032         printf("D: %d\n", _d);
00033         if (_angle < 0.0f) {          //check for -1.0 angle
00034             _d = 0;
00035         } else if (_angle < 45.0f) {  //North quadrant
00036             _d = 1;
00037         } else if (_angle < 135.0f) { //East quadrant
00038             _d = 2;
00039         } else if (_angle < 225.0f) { //South quadrant
00040             _d = 3;
00041         } else if (_angle < 315.0f) { //West quadrant
00042             _d = 4;
00043         } else {                      //NW half - quadrant
00044             _d = 1;
00045         }
00046     }
00047 };
00048 
00049 void SnakeBody::update_position()
00050 {
00051 
00052     Direction _fsm[5] = {
00053         {0,  0, {0,1,2,3,4}},  // Centred
00054         {0, -1, {1,1,2,1,4}},  // North, will not go to centre or south
00055         {1,  0, {2,1,2,3,2}},  // East, will not go to centre or west
00056         {0,  1, {3,3,2,3,4}},  // South, will not go to centre or north
00057         {-1, 0, {4,1,4,3,4}}   // West, will not go to centre or east
00058     };
00059 
00060     _move_state = _fsm[_move_state].nextState[_d]; // adjusts fsm state based on direction
00061     //printf("State: %d\n", _move_state);
00062 
00063     head_x += _fsm[_move_state].delta_x; // increments x value based on fsm state value
00064     head_y += _fsm[_move_state].delta_y; // increments y value based on fsm state value
00065 
00066     head_x = ((head_x % 84) + 84) % 84; // wraps x back to within range 0-83
00067     head_y = ((head_y % 48) + 48) % 48; // wraps y back to within range 0-47
00068 
00069     //printf("head_x: %d\n", head_x);
00070     //printf("head_y: %d\n", head_y);
00071 };
00072 
00073 void SnakeBody::snake_movement(Gamepad &pad)
00074 {
00075 
00076     _angle = pad.get_angle(); //finds joystick angle
00077     //printf("Angle: %f\n", _angle);
00078     update_direction(); //converts angle into a integer direction
00079     update_position();  //takes integer direction and feeds it into FSM to move snake in correct direction
00080     update_body();      //feeds head coords into body vectors and remove old ones
00081 }
00082 
00083 void SnakeBody::update_body()
00084 {
00085     if ((head_x % 2) + (head_y % 2) == 0) {        //only updates body when cell aligned
00086         body_x.insert(body_x.begin(), head_x);    //sets first array element to head coordinates
00087         body_y.insert(body_y.begin(), head_y);
00088 
00089         body_x.erase(body_x.begin() + _length, body_x.end()); //erases all elements from position after tail (ie [_length])
00090         body_y.erase(body_y.begin() + _length, body_y.end()); //up to end of vector
00091     }
00092     if(_length_increase > 0) { //converts length increase into length, one unit at a time
00093         _length++;
00094         _length_increase--;
00095         //printf("L increase: %d\n", _length_increase);
00096     }
00097 }
00098 
00099 
00100 void SnakeBody::draw_body(N5110 &lcd)
00101 {
00102     lcd.drawRect(head_x, head_y, 2, 2, FILL_BLACK); //draws square at head (so new head coords displayed even when not cell-aligned) 
00103     for(int i = 0; i < _length - 3; i++) { //iterates across vector to draw sqaures at every position
00104         lcd.drawRect(body_x[i], body_y[i], 2, 2, FILL_BLACK);
00105     }
00106 }
00107 
00108 void SnakeBody::snake_snake_collision(Gamepad &pad, bool &_death)
00109 {
00110     if (_move_state > 0) { //if body has started to move
00111         for(int i = 3; i < _length - 3; i++) { //only checks from 3rd cell onwards since head can't collide with very start of body
00112             if (head_x == body_x[i] && head_y == body_y[i]) { //checks if head coord is the same as any of the body coords
00113                 //printf("S-S Collison \n");
00114                 _move_state = 0;
00115                 _death = true;
00116             }
00117         }
00118     }
00119 }
00120 
00121 void SnakeBody::add_length(int increase) {
00122     _length_increase += increase;
00123 }
00124 
00125 void SnakeBody::run(Gamepad &pad, N5110 &lcd, bool &_death)
00126 {
00127     snake_movement(pad);
00128     draw_body(lcd);
00129     snake_snake_collision(pad, _death);
00130     //printf("Body running!");
00131 }
00132 
00133 void SnakeBody::reset()
00134 {
00135     head_x = 42;
00136     head_y = 24;
00137     for(int i = 1; i < body_y.size(); i++) { 
00138         body_y.at(i) = 50; //moves all body coordinates off-screen
00139     }
00140     _length = 4;
00141     _length_increase = 4;
00142     _move_state = 0;
00143 }