#include "SynEngine.hpp" enum PlayerSprite { Empty, Point, Straight, Curved, Back, Head, PointGot, GameOver }; struct SnakePart { sf::Vector2i cellPosition; unsigned direction; }; class Snake : public IBehaviour { private: std::vector snake; unsigned int lenght; SnakePart *head; Timer *timer; Grid *grid; float timeCountdown; float timeResetValue; unsigned TickPerSec; GameConfiguration *config; void Move(); void Grow(); unsigned GetDirection(sf::Vector2i, sf::Vector2i); unsigned GetBackDirection(); sf::Vector2i GetDirectionVector(unsigned); PlayerSprite GetNewSprite(unsigned &); public: Snake(); void Update(); ~Snake(); }; Snake::Snake() { TickPerSec = 4; timeResetValue = 1.0 / (float)TickPerSec; timeCountdown = timeResetValue; lenght = 2; snake.reserve(lenght); for (unsigned i = 0; i < lenght; i++) snake.push_back({ sf::Vector2i(1 - i, 0), 0}); timer = &GameManager::timer; head = &snake[0]; config = GameManager::GetConfig(); grid = &GameManager::GetGrid(); grid -> UpdateCell(snake[0].cellPosition.x, snake[0].cellPosition.y, PlayerSprite::Head, 0); grid -> UpdateCell(snake[1].cellPosition.x, snake[1].cellPosition.y, PlayerSprite::Straight, 0); } void Snake::Move() { sf::Vector2i *backPosition = &snake[lenght - 1].cellPosition; sf::Vector2i *secondPosition = &snake[1].cellPosition; sf::Vector2i headPosition = head -> cellPosition; unsigned direction; unsigned headDirection; PlayerSprite sprite; grid -> UpdateCell(backPosition -> x, -backPosition -> y, PlayerSprite::Empty); headDirection = head -> direction; snake.pop_back(); // Check if the new direction is opposite to the head's direction if((GameManager::GetInputDirection() + 2) % 4 == headDirection) headPosition += GetDirectionVector(headDirection); else { headPosition += GameManager::GetInputVector(); headDirection = GameManager::GetInputDirection(); } snake.insert(snake.begin(), { headPosition, headDirection }); direction = snake[1].direction; sprite = GetNewSprite(direction); grid -> UpdateCell(headPosition.x, -headPosition.y, PlayerSprite::Head, headDirection); grid -> UpdateCell(secondPosition -> x, -secondPosition -> y, sprite, (int)direction); grid -> UpdateCell(backPosition -> x, -backPosition -> y, PlayerSprite::Back, GetBackDirection()); } void Snake::Update() { if(timeCountdown > 0.0) { timeCountdown -= timer -> GetDeltaTime(); return; } Move(); timeCountdown = timeResetValue; } sf::Vector2i Snake::GetDirectionVector(unsigned direction) { switch (direction) { case 0: return sf::Vector2i(1, 0); case 1: return sf::Vector2i(0, -1); case 2: return sf::Vector2i(-1, 0); case 3: return sf::Vector2i(0, 1); default: return sf::Vector2i(1, 0); } } PlayerSprite Snake::GetNewSprite(unsigned &direction) { SnakePart *third = &snake[2]; SnakePart *second = &snake[1]; sf::Vector2i vector = third -> cellPosition - head -> cellPosition; unsigned newDirection = GameManager::GetInputDirection(); // I need to update this. It look so bad if(vector.x != 0 && vector.y != 0) { direction += 2; direction %= 4; if(direction > newDirection) { unsigned temp; temp = direction; direction = newDirection; newDirection = temp; } // 0 - 1 -> 0 // 1 - 2 -> 1 // 2 - 3 -> 2 // 0 - 3 -> 3 if(direction == 0 && newDirection == 3) direction = 3; return PlayerSprite::Curved; } direction = GetDirection(head -> cellPosition, second -> cellPosition); return PlayerSprite::Straight; } unsigned Snake::GetDirection(sf::Vector2i first, sf::Vector2i second) { first -= second; if(first.x > 0) return 0; if(first.y < 0) return 1; if(first.x < 0) return 2; if(first.y > 0) return 3; return 0; } unsigned Snake::GetBackDirection() { return GetDirection(snake[lenght - 2].cellPosition, snake[lenght - 1].cellPosition); } Snake::~Snake() { }