cpp SFML gra kolizje sprite z rectangleShape

cpp SFML gra kolizje sprite z rectangleShape
Natalia Pachucka
  • Rejestracja:prawie 3 lata
  • Ostatnio:prawie 3 lata
  • Postów:1
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 --->

Kopiuj

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

KO
zamien if na else bo oba warunki sa spelnione, x klocka jest mniejszy niz x platformy wiec wykona sie jeden if oraz y klocka jest wiekszy niz y platformy sie sie wykona rowniez ten if. A tak poza tym to jest juz w sfml wbudowana funkcja do sprawdzania kolizji: if(klocek.getGlobalBounds().intersect(platforma.getGlobalBounds())) { jakis kod }
BG
  • Rejestracja:prawie 6 lat
  • Ostatnio:4 dni
  • Postów:289
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.

_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:5 dni
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


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 2x, ostatnio: _13th_Dragon
Zobacz pozostały 1 komentarz
_13th_Dragon
Ok, a czym jest to: 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 )
BG
A to są próby sprawdzenia z której strony nastąpiła kolizja (np. z góry czy z boku)
_13th_Dragon
Z których po zrobieniu odpowiedniej metody będzie 4 wywołania, a nie napiętrzone nieczytelne if'y
_13th_Dragon
No właśnie o to ten post.
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:2 minuty
  • Postów:6673
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.


🕹️⌨️🖥️🖱️🎮
edytowany 2x, ostatnio: Spine
M4
  • Rejestracja:prawie 3 lata
  • Ostatnio:prawie 3 lata
  • Postów:2
MrMadMatt
  • Rejestracja:ponad 9 lat
  • Ostatnio:16 dni
  • Postów:373
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.

T3
  • Rejestracja:ponad 4 lata
  • Ostatnio:7 miesięcy
  • Postów:687
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

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.