cpp SFML gra kolizje sprite z rectangleShape

0

hej, mam taką funkcje do sprawdzania kolizji i generalnie dziala dobrze, ale jesli najezdzam postacia na platforme od gory albo od dolu i cala postac nie znajduje sie jakby w szerokości platformy, to przerzuca mi ja na bok zamiast zostawic na platformie. ktos wie jak to naprawić, albo co może powodować ten problem? Tutaj wrzucam link do filmu jak to wygląda --->


void Player::checkCollisions(std::vector<Obstacle> obstacles)
{
	sf::Vector2f playerPos = hitbox.getPosition();

	for (auto& obs : obstacles) {
		sf::FloatRect playerBounds = hitbox.getGlobalBounds();
		sf::FloatRect wallBounds = obs.getObstacle().getGlobalBounds();

		nextPosition = playerBounds;
		nextPosition.left += velocity.x;
		nextPosition.top += velocity.y;

		if (wallBounds.intersects(nextPosition)) {
			//Bottom collision
			if (playerBounds.top < wallBounds.top
				&& playerBounds.top + playerBounds.height < wallBounds.top + wallBounds.height
				&& playerBounds.left < wallBounds.left + wallBounds.width
				&& playerBounds.left + playerBounds.width > wallBounds.left
				)
			{
				this->isPressed = 0;
				velocity.y = 0.f;
				player.setPosition(playerBounds.left, wallBounds.top - playerBounds.height);
				hitbox.setPosition(playerBounds.left, wallBounds.top - playerBounds.height);
			}

			//Top collision
			else if (playerBounds.top > wallBounds.top
				&& playerBounds.top + playerBounds.height > wallBounds.top + wallBounds.height
				&& playerBounds.left < wallBounds.left + wallBounds.width
				&& playerBounds.left + playerBounds.width > wallBounds.left
				)
			{
				velocity.y = 0.f;
				player.setPosition(playerBounds.left, wallBounds.top + wallBounds.height);
				hitbox.setPosition(playerBounds.left, wallBounds.top + wallBounds.height);
			}

			//Right collision
			if (playerBounds.left < wallBounds.left
				&& playerBounds.left + playerBounds.width < wallBounds.left + wallBounds.width
				&& playerBounds.top < wallBounds.top + wallBounds.height
				&& playerBounds.top + playerBounds.height > wallBounds.top
				)
			{
				velocity.x = 0.f;
				player.setPosition(wallBounds.left - playerBounds.width, playerBounds.top);
				hitbox.setPosition(wallBounds.left - playerBounds.width, playerBounds.top);
			}

			//Left collision
			else if (playerBounds.left > wallBounds.left
				&& playerBounds.left + playerBounds.width > wallBounds.left + wallBounds.width
				&& playerBounds.top < wallBounds.top + wallBounds.height
				&& playerBounds.top + playerBounds.height > wallBounds.top
				)
			{
				velocity.x = 0.f;
				player.setPosition(wallBounds.left + wallBounds.width, playerBounds.top);
				hitbox.setPosition(wallBounds.left + wallBounds.width, playerBounds.top);
			}
		}
	}
}

1

Musisz zmienić logike obsługi kolizji - w tej chwili jak sie w odpowiednim miejscu "wbijesz" w platformę, to masz jednocześnie kolizję z górą i bokiem.
Najprostsze co byc może pomoże - zamień if na else if w Right Collision (wtedy oczywiście pojawią się inne przypadki szczególne ;) )

Inny drobiazg który może troszkę pomóc (uprościć te paskudne if-y) - zredukuj gracza do punktu (środka prostokąta) i powiększ odpowiednio bounding box przeszkody - uprościsz sobie wtedy ten problem do kolizji punktu z prostokątem.

0

Może napisz sobie metodę bool IntersectRect(const sf::FloatRect &a,const sf::FloatRect &b)
Zamiast takiej pseudohackerki.

Aczkolwiek wydaje mi się że coś takiego jak SFML musi mieć wbudowane IntersectRect() :D

1

Tak w ogóle, to najlepiej wykrywać kolizję jeszcze zanim nastąpiła.
Teraz nawet na filmiku od Ciebie widać, że prostokąt nachodzi na przeszkodę i się cofa.
Jeśli przed faktycznym wykonaniem ruchu sprawdzisz, czy kolizja nastąpi, to możesz skrócić przesunięcie, tak aby gracz nigdy nie naszedł na przeszkodę.
Wtedy wszystko wygląda gładko, bez przeskoków.

Tip: ruch pionowy i poziomy obsługuj osobno.

1

Zależy co chcesz z tym SFMLem zrobić. Na twoim miejscu spiąłbym SFML z Box2D i nie wymyślał koła na nowo.

0


Nie jestem pewien, w której części gość pokazuje kolizję (filmików jest pare, to dasz radę znaleźć), ale tutaj jest to całkiem przyjemnie wyjaśnione i działa dobrze

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