Snake - klasyczny problem z ogonem

0

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;
}
0

w zyciu napisalem moze parę linijek kodu w C++ ale wydaje mi się że w wektorze masz tylko 1 element i po prostu nie "rozwijasz" snejka tylko aktualizujesz ciągle 1 element. Musisz dodawać ogon do czasu aż snejkSajz < 20

0

w dodatku moze byc przypadek ze foodRespown pojawi Ci się w snakeBody :) i zrób sobie jakiś obiekt Snejk :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1