Berux Temat założony przez niniejszego użytkownika |
[C++] Algorytm na wykrywanie kolizji - prostokąty » 2013-06-04 19:39:03 Witam. Wiem, że tych tematów jest bardzo dużo, ale nie mogę znaleźć żadnego dobrego algorytmu na wykrywanie kolizji. Tylko nie odsyłajcie mnie do google, bo tam już byłem :P. Z góry dzięki. PS Wcześniej korzystałem z tego algorytmu(Easykodera): bool kolizja( int x1, int y1, int s1, int w1, int x2, int y2, int s2, int w2 ) { if( x2 <= x1 + s1 && x2 > x1 && y2 >= y1 && y2 <= y1 + w1 ) return true; else if( x2 <= x1 + s1 && x2 > x1 && y2 + w2 >= y1 && y2 + w2 <= y1 + w1 ) return true; else if( x2 + s2 <= x1 + s1 && x2 + s2 > x1 && y2 >= y1 && y2 <= y1 + w1 ) return true; else if( x2 + s2 <= x1 + s1 && x2 + s2 > x1 && y2 + w2 >= y1 && y2 + w2 <= y1 + w1 ) return true; else return false; };
Nie działa on jednak prawidłowo. |
|
wojownik266 |
» 2013-06-04 19:44:45 Bardzo prosty kod kolizji który stosowałem w sfml 1.6 bool kolizja( float & x, float & y, float & x1, float & y1 ) { if( abs( x - x1 ) > 20 || abs( y - y1 ) > 20 ) return false; else return true; }
|
|
Berux Temat założony przez niniejszego użytkownika |
» 2013-06-04 19:49:36 Nie chce coś u mnie zadziałać :(. Może coś mam w kodzie źle:
#include <cmath> #include <SFML/Graphics.hpp> #include <windows.h>
class OBIEKT { public: float x; float y; int w; int h; sf::Texture textura; sf::Sprite grafika; };
inline void ladowanieTextury( sf::Texture & tekstura, std::string sciezka ) { tekstura.loadFromFile( sciezka ); }
bool kolizja( float & x, float & y, float & x1, float & y1 ) { if( abs( x - x1 ) > 20 || abs( y - y1 ) > 20 ) return false; else return true; }
int main() { bool czyStrzelac = false; bool wyswietlicWroga = true; sf::RenderWindow okno; okno.create( sf::VideoMode( 800, 600, 32 ), "First game's Michał Tomczyk" ); OBIEKT stickman, wrog, luk, strzala; ladowanieTextury( stickman.textura, "stickman.png" ); ladowanieTextury( wrog.textura, "wrog.png" ); ladowanieTextury( luk.textura, "luk.png" ); ladowanieTextury( strzala.textura, "strzala.png" ); ( stickman.grafika ).setTexture( stickman.textura ); ( wrog.grafika ).setTexture( wrog.textura ); ( luk.grafika ).setTexture( luk.textura ); ( strzala.grafika ).setTexture( strzala.textura ); stickman.w = 113; stickman.h = 203; stickman.x = 0; stickman.y =( 600 - stickman.h ); wrog.w = 113; wrog.h = 203; wrog.x =( 800 - wrog.w ); wrog.y =( 600 - wrog.h ); luk.w = 32; luk.h = 72; luk.x = stickman.w; luk.y =( stickman.y +( 102 - luk.h / 2 ) ); strzala.w = 32; strzala.h = 15; strzala.x = stickman.w; strzala.y =( stickman.y +( 102 - luk.h / 2 + 32 ) ); ( stickman.grafika ).setPosition( stickman.x, stickman.y ); ( wrog.grafika ).setPosition( wrog.x, wrog.y ); ( luk.grafika ).setPosition( luk.x, luk.y ); ( strzala.grafika ).setPosition( strzala.x, strzala.y ); while( okno.isOpen() ) { sf::Event zdarzenie; while( okno.pollEvent( zdarzenie ) ) { if( zdarzenie.type == sf::Event::Closed ||( zdarzenie.type == sf::Event::KeyPressed && zdarzenie.key.code == sf::Keyboard::Escape ) ) { okno.close(); } if( sf::Keyboard::isKeyPressed( sf::Keyboard::Up ) ) { ( stickman.grafika ).move( 0, - 3 ); stickman.x += 0; stickman.y -= 3; ( luk.grafika ).move( 0, - 3 ); luk.x += 0; luk.y -= 3; ( strzala.grafika ).move( 0, - 3 ); strzala.x += 0; strzala.y -= 3; } if( sf::Keyboard::isKeyPressed( sf::Keyboard::Down ) ) { ( stickman.grafika ).move( 0, 3 ); stickman.x += 0; stickman.y += 3; ( luk.grafika ).move( 0, 3 ); luk.x += 0; luk.y += 3; ( strzala.grafika ).move( 0, 3 ); strzala.x += 0; strzala.y += 3; } if( sf::Keyboard::isKeyPressed( sf::Keyboard::Left ) ) { ( stickman.grafika ).move( - 3, 0 ); stickman.x -= 3; stickman.y += 0; ( luk.grafika ).move( - 3, 0 ); luk.x -= 3; luk.y += 0; ( strzala.grafika ).move( - 3, 0 ); strzala.x -= 3; strzala.y += 0; } if( sf::Keyboard::isKeyPressed( sf::Keyboard::Right ) ) { ( stickman.grafika ).move( 3, 0 ); stickman.x += 3; stickman.y += 0; ( luk.grafika ).move( 3, 0 ); luk.x += 3; luk.y += 0; ( strzala.grafika ).move( 3, 0 ); strzala.x += 3; strzala.y += 0; } if( zdarzenie.type == sf::Event::KeyPressed && zdarzenie.key.code ==( sf::Keyboard::Space ) ) { strzala.x = stickman.w; strzala.y =( stickman.y +( 102 - luk.h / 2 + 32 ) ); ( strzala.grafika ).setPosition( strzala.x, strzala.y ); czyStrzelac = true; } } if( czyStrzelac ) { ( strzala.grafika ).move( 600, 0 ); czyStrzelac = false; } if( kolizja( strzala.x, strzala.y, wrog.x, wrog.y ) ) { wyswietlicWroga = false; } okno.clear( sf::Color( 0, 128, 0 ) ); okno.draw( stickman.grafika ); if( wyswietlicWroga ) { okno.draw( wrog.grafika ); } okno.draw( luk.grafika ); okno.draw( strzala.grafika ); okno.display(); } return 0; }
/edit: Czy ta wartość dwadzieścia to szerokość/wysokość któregoś obiektu? |
|
RazzorFlame |
» 2013-06-04 20:04:48 Kod wojownika266 sprawdza czy odległość od pozycji jest mniejsza niż 20 (od każdej z 2 osi w 2D). Nie sprawdzi się to gdy masz inne rozmiary/wielkości obiektów. Pomyśl. Kolizja zachodzi gdy: - prawy bok ob. A >= lewy bok ob. B - lewy bok ob. A <= prawy bok ob. B - dolny bok ob. A >= górny bok ob. B - górny bok ob. A <= dolny bok ob. B W pierwszych dwóch warunkach bierzemy pod uwagę oś X. Do obliczenia pozycji prawego boku używamy wzoru: "prawyBok = X+W" gdzie W to szerokość. Do lewego używamy samego X. W trzecim i czwartym warunku bierzemy pod uwagę oś Y. Analogicznie jak u góry tylko wzór na dolny bok: "dolnyBok = Y+H" gdzie H to wysokość. Do górnego boku bierzemy same Y. Oczywiście zadziała to jeżeli X i Y wskazują na prawy górny róg danego obiektu. Jeśli nie to wyznaczamy X i Y prawego górnego rogu i działamy tak jak u góry. Jeśli chcesz wykryć z którego boku nastąpiła kolizja to musisz jeszcze troche pomyśleć (podpowiedź. sprawdzaj który bok jest najbardziej zagłębiony w boku przeciwnym innego obiektu). Licze że po tych informacjach, znając instrukcje warunkowe dasz sobie rade :) |
|
Berux Temat założony przez niniejszego użytkownika |
» 2013-06-04 20:10:24 Dzięki za odpowiedź. Jeszcze nad tym pomyślę. Aha, mam jeszcze jedno pytanie, mianowicie czy nie prościej byłoby mi wykryć kolizję na mapie kafelkowej? |
|
DejaVu |
» 2013-06-04 20:36:04 |
|
Berux Temat założony przez niniejszego użytkownika |
» 2013-06-04 20:56:00 Popróbowałem z tym algorytmem, do którego dałeś linki, ale coś mi nie wychodzi :( Kolizja zachodzi, ale nie zostaje wykryta przez funkcję. if( kolizja( strzala.x, strzala.y, strzala.w, strzala.h, wrog.x, wrog.y, wrog.w, wrog.h ) ) { return 0; }
Mimo, że kolizja zachodzi, program się nie zamyka. |
|
pekfos |
» 2013-06-04 21:00:52 Pokaż kod funkcji kolizja(). |
|
« 1 » 2 |