krzyk Temat założony przez niniejszego użytkownika |
[SFML 2.0] Kolizja (koncepcje) » 2012-12-14 19:01:00 Wielokrotnie przewiją się przez to forum tematy o kolizji więc podzielę się moją koncepcją,niestety niedziała przy szybkiej zmianie pozycji(przeskakuje lub wpada w objekty) i niemam na to żadnego pomysła.
Jeśli ktoś ma inne rozwiązania mógłby się podzielić przykładowym kodem lub algorytmem.
#include <SFML/Graphics.hpp> #include <iostream>
int main() { srand( time( NULL ) ); sf::RenderWindow window( sf::VideoMode( 640, 480 ), "gierka xD" ); sf::Clock clock; sf::RectangleShape rects[ 100 ]; const float qqq = 150.0; for( int y = 0; y < 10; ++y ) { for( int x = 0; x < 10; ++x ) { float px = rand() %( int ) qqq * 10; float py = rand() %( int ) qqq * 10; rects[ x + y * 10 ].setSize( sf::Vector2f( qqq * 0.5, qqq * 0.5 ) ); rects[ x + y * 10 ].setPosition( px, py ); rects[ x + y * 10 ].setFillColor( sf::Color::Green ); } } sf::CircleShape player( 5.0, 10 ); player.setFillColor( sf::Color::Black ); player.setOrigin( sf::Vector2f( player.getRadius(), player.getRadius() ) ); while( 1 ) { bool found = false; sf::Vector2f pp( rand() %( int ) qqq * 10, rand() %( int ) qqq * 10 ); player.setPosition( pp ); for( int q = 0; q < 100; ++q ) { sf::RectangleShape rect = rects[ q ]; sf::FloatRect rbound = rect.getGlobalBounds(); if( rbound.intersects( player.getGlobalBounds() ) ) found = false; else found = true; } if( found ) break; } const float dstep = 1.0; float dirH, dirV; while( window.isOpen() ) { sf::Event event; while( window.pollEvent( event ) ) { if( event.type == sf::Event::Closed ) window.close(); } dirV = dirH = 0.0; if( sf::Keyboard::isKeyPressed( sf::Keyboard::Right ) ) dirH = dstep; else if( sf::Keyboard::isKeyPressed( sf::Keyboard::Left ) ) dirH = - dstep; if( sf::Keyboard::isKeyPressed( sf::Keyboard::Up ) ) dirV = - dstep; else if( sf::Keyboard::isKeyPressed( sf::Keyboard::Down ) ) dirV = dstep; window.clear( sf::Color( 127, 127, 127, 0 ) ); for( int q = 0; q < 100; ++q ) window.draw( rects[ q ] ); int t = clock.getElapsedTime().asMilliseconds(); clock.restart(); sf::Vector2f lastpos( player.getPosition() ); float distance =( 0.2 * t ); sf::Vector2f plpos( player.getPosition().x +( dirH * distance ), player.getPosition().y +( dirV * distance ) ); bool colx = false, coly = false; sf::Vector2f forx( plpos.x, lastpos.y ); sf::Vector2f fory( lastpos.x, plpos.y ); for( int q = 0; q < 100; ++q ) { sf::RectangleShape rect = rects[ q ]; sf::FloatRect rbound = rect.getGlobalBounds(); player.setPosition( forx ); if( rbound.intersects( player.getGlobalBounds() ) ) colx = true; player.setPosition( fory ); if( rbound.intersects( player.getGlobalBounds() ) ) coly = true; if( colx && coly ) break; } sf::Vector2f newpos( lastpos ); if( !colx ) newpos.x = plpos.x; if( !coly ) newpos.y = plpos.y; player.setPosition( newpos ); sf::View view = window.getDefaultView(); view.setCenter( player.getPosition() ); window.setView( view ); window.draw( player ); window.display(); } return 0; } |
|
Mrovqa |
» 2012-12-14 20:23:11 1. Wygodniej jest stworzyć klasę, która obsługuje kolizje. 2. Nie przejmuj się efektem tunnelingu - w dobrych silnikach fizycznych takich jak np. box2d ze względów wydajnościowych (kwantowy czas) też jest ten 'bug'.
@down niewykluczone, jeszcze nie rozpocząłem pisania w tej bibliotece, rzuciłem jedynie okiem na dokumentację ;) |
|
DejaVu |
» 2012-12-14 20:25:11 @up: mijasz się z prawdą :) Box2D posiada flagę czy obiekt jest 'posciskiem' tj. czy jest to obiekt przemieszczający się bardzo szybko. Ta flaga zapobiega efektowi tunnelingu dla szybkich obiektów. |
|
krzyk Temat założony przez niniejszego użytkownika |
» 2012-12-14 21:09:45 @Mrovqa
Klasy będą pózniej,narazie szukam sposobów na kolizję.
Co do tunellingu,wymyśliłem sobie że mogę sprawdzać kolizję lini z objektami gdzie początek to stara pozycja a koniec nowa,wtedy wystarczy znależć pierwsze przecięcie linia/objekt. |
|
DejaVu |
» 2012-12-14 22:13:25 Osobiście to polecałbym pomęczyć się z nauką jakiejś popularnej biblioteki do obsługi kolizji/fizyki, bądź użyciem jakiegoś istniejącego silnika, jeżeli chcesz tworzyć gry. Sam niejednokrotnie pisałem samodzielnie wykrywanie kolizji w grach oraz fizykę i powiem Ci, że żaden bardziej złożony projekt nie został ukończony, ponieważ po ewentualnym napisaniu silnika, kończyła się motywacja wraz z napływem kolejnych problemów do rozwiązania, a po dłuższej przerwie od projektu zachodzi zjawisko 'a może by tak napisać od nowa? Lepiej niż poprzednio?'. Ponadto dokumentacji w domowych produkcjach zazwyczaj się nie robi, a więc bez dużego doświadczenia w pisaniu kodu w sposób czytelny, napotkasz problem "ale po co mi ta funkcja była? jak z niej korzystać?" i zaczniesz wszystko od nowa. |
|
krzyk Temat założony przez niniejszego użytkownika |
» 2012-12-17 11:45:25 @up
"ale po co mi ta funkcja była? jak z niej korzystać?" |
To naszczęście już dawno za mną,piszę samodokumentujący się kod a w przypadku niejednoznaczności trzasnę komentarz.
Najgorsze to niedoprecyzowanie wymagań,ach to planowanie a raczej jego brak;P
Przeanalizawałem pare silników (Newton,ODE,Chipmunk),sprawdziłem pare sposobów.
Najodpowiedniejszą wydawała metoda SAT ale ilość kodu była większa niż przy użyciu Box2D.
Heh,przynajmniej dowiedziałem się na jakiej zasadzie działają silniki fizyki,więc to niebył stracony czas. |
|
« 1 » |