Witam,
Postanowiłem wrócić do nauki C++ i SFML i próbuję napisać snake'a. Jednak napotkałem problem, z którym nie mogę sobie poradzić. Mianowicie ogon nie chce podążać za głową węża. Siedzę nad tym 3 dzień, przejrzałem sporo materiału w polskim, jak i zagranicznym internecie, a mimo to, wciąż, nie mogę tego ogarnąć. Doprowadza mnie to już do szału. W teorii kod powinien działać, jak należy, w praktyce natomiast, niekoniecznie.
Zamieszczam kod poniżej. Czy ktoś może mi z tym pomóc i wyjaśnić łopatologicznie ??
#include <SFML\Graphics.hpp>
using namespace sf;
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
void respawnFood(RectangleShape& food)
{
float foodSize = 20;
food.setFillColor(Color::Red);
food.setSize({ foodSize, foodSize });
food.setPosition(rand() % 640, rand() % 480);
}
bool isColliding(RectangleShape& snake, RectangleShape& food)
{
if (snake.getGlobalBounds().intersects(food.getGlobalBounds()))
return true;
return false;
}
int main()
{
RenderWindow window(VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT), "SFML");
//window.setFramerateLimit(60);
// MISC
srand(time(NULL));
Clock clock;
Time time;
// SNAKE
enum SnakeDirection { LEFT, RIGHT, UP, DOWN, NONE };
SnakeDirection currentDirection = NONE;
RectangleShape snakeHead;
float snakeSize = 20;
float snakeSpeed = 200.f;
snakeHead.setFillColor(Color::Green);
snakeHead.setSize({ snakeSize, snakeSize });
snakeHead.setPosition(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
std::vector<RectangleShape> snakeBody;
snakeBody.push_back(snakeHead);
// FOOD
RectangleShape food;
respawnFood(food);
// MAIN LOOP
clock.restart();
while (window.isOpen())
{
time = clock.getElapsedTime();
// HANDLE INPUT
Event ev;
while (window.pollEvent(ev))
{
if (ev.type == Event::Closed || ev.type == Event::KeyPressed && ev.key.code == Keyboard::Escape)
window.close();
}
if ((Keyboard::isKeyPressed(Keyboard::D) || Keyboard::isKeyPressed(Keyboard::Right)) && currentDirection != LEFT)
currentDirection = RIGHT;
if ((Keyboard::isKeyPressed(Keyboard::A) || Keyboard::isKeyPressed(Keyboard::Left)) && currentDirection != RIGHT)
currentDirection = LEFT;
if ((Keyboard::isKeyPressed(Keyboard::W) || Keyboard::isKeyPressed(Keyboard::Up)) && currentDirection != DOWN)
currentDirection = UP;
if ((Keyboard::isKeyPressed(Keyboard::S) || Keyboard::isKeyPressed(Keyboard::Down)) && currentDirection != UP)
currentDirection = DOWN;
// END OF INPUT
// UPDATE
if (currentDirection == RIGHT)
snakeHead.move(time.asSeconds() * snakeSpeed, 0);
if (currentDirection == LEFT)
snakeHead.move(-time.asSeconds() * snakeSpeed, 0);
if (currentDirection == UP)
snakeHead.move(0, -time.asSeconds() * snakeSpeed);
if (currentDirection == DOWN)
snakeHead.move(0, time.asSeconds() * snakeSpeed);
// collision check
if (isColliding(snakeHead, food))
{
snakeHead.setFillColor(Color(rand() % 255, rand() % 255, rand() % 255));
snakeBody.push_back(snakeHead);
respawnFood(food);
}
// snake's tail logic
auto endOfSnake = snakeBody.back();
snakeBody.pop_back();
if (currentDirection == RIGHT)
endOfSnake.setPosition(snakeHead.getPosition().x - snakeSize - 3, snakeHead.getPosition().y);
if (currentDirection == LEFT)
endOfSnake.setPosition(snakeHead.getPosition().x + snakeSize + 3, snakeHead.getPosition().y);
if (currentDirection == UP)
endOfSnake.setPosition(snakeHead.getPosition().x, snakeHead.getPosition().y - snakeSize - 3);
if (currentDirection == DOWN)
endOfSnake.setPosition(snakeHead.getPosition().x, snakeHead.getPosition().y + snakeSize + 3);
snakeBody.insert(snakeBody.begin(), endOfSnake);
clock.restart();
// END OF UPDATE
// RENDER
window.clear(Color::Black);
window.draw(snakeHead);
window.draw(food);
for (int i = 0; i < snakeBody.size(); i++)
{
window.draw(snakeBody[i]);
}
window.display();
//END OF RENDER
}
return EXIT_SUCCESS;
}