kubawal Temat założony przez niniejszego użytkownika |
[C++, allegro] Ludek zacina się po kolizji z przeszkodą » 2012-09-07 21:27:50 Witam oto kod: #include <allegro.h>
inline int randint( int max ) { return rand() % max; } inline int randint( int min, int max ) { return randint( max - min ) + min; }
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; }; END_OF_FUNCTION();
void Game();
int main( void ) { allegro_init(); install_keyboard(); set_color_depth( 16 ); set_gfx_mode( GFX_AUTODETECT_WINDOWED, 600, 600, 0, 0 ); set_palette( default_palette ); clear_to_color( screen, makecol( 255, 0, 255 ) ); Game(); allegro_exit(); return 0; } END_OF_MAIN();
void Game() { BITMAP * bufor = NULL; BITMAP * przeszkoda = NULL, * ludek = NULL; int ludekX = 300, ludekY = 300; int przeszkodaX, przeszkodaY; bufor = create_bitmap( 600, 600 ); ludek = load_bmp( "C:\\lib\\ludek.bmp", default_palette ); przeszkoda = load_bmp( "C:\\lib\\przeszkoda.bmp", default_palette ); if( !ludek || !przeszkoda || !bufor ) { set_gfx_mode( GFX_TEXT, 0, 0, 0, 0 ); textout_ex( screen, font, "Nie udało się załadować bitmap", 0, 0, makecol( 0, 0, 0 ), 0 ); rest( 5000 ); } przeszkodaX = randint( 0, 600 - przeszkoda->w ); przeszkodaY = randint( 0, 600 - przeszkoda->h ); while( !key[ KEY_ESC ] ) { clear_to_color( screen, makecol( 255, 0, 255 ) ); if( !kolizja( ludekX, ludekY, ludek->w, ludek->h, przeszkodaX, przeszkodaY, przeszkoda->w, przeszkoda->h ) ) { if( key[ KEY_UP ] ) ludekX++; if( key[ KEY_DOWN ] ) ludekX--; if( key[ KEY_RIGHT ] ) ludekY++; if( key[ KEY_RIGHT ] ) ludekY--; } masked_blit( ludek, bufor, 0, 0, ludekX, ludekY, 800, 800 ); masked_blit( przeszkoda, bufor, 0, 0, przeszkodaX, przeszkodaY, 800, 800 ); blit( bufor, screen, 0, 0, 0, 0, 800, 800 ); rest( 20 ); } destroy_bitmap( ludek ); destroy_bitmap( przeszkoda ); destroy_bitmap( bufor ); } END_OF_FUNCTION();
Problem jest taki, że ludek po wjechaniu na przeszkodę zacina się. Wiem że to skutek tego, że gdy koliduje z przeszkodą, nie zbiera zdarzeń z klawiatury. Aby móc go np. cofnąć muszę znać, z którego boku przeszkody(przeszkoda to zwykły kwadrat) uderzyłem. No i właśnie nie wiem jak to zrobić. Proszę o pomoc. |
|
diego997 |
» 2012-09-08 12:23:15 Wiesz kiedyś sam miałem z tym problem pewnie są inne rozwiązania co do kolizji ale znam tylko jedno. Masz dwie klasy Player i Enemy w klasie Enemy dodatkowo trzymasz zmienną: która przyjmuje wartości załóżmy od 1 do 4 (kwadrat ma 4 boki) Spójrz na screen poniżej powinno się nieco rozjaśnić, tzn powinieneś załapać sens jak nie to pytaj :D Chyba że ktoś widzi jakieś przeciwskazania co do tego sposobu to niech napisze :) Screen: http://imageshack.us/photo/my-images/840/screenlal.png/Podczas sprawdzania kolizji najpierw wykrywane są te linie jeżeli edge = 1 to znaczy że klocek jest po lewej stronie i kiedy faktycznie dojdzie miedzy nimi do kolizji to wiadomo że z lewej strony :D |
|
RazzorFlame |
» 2012-09-08 14:43:14 A może dlatego że kiedy wjedzie w przeszkode to już z niej nie wyjdzie :)
Edit: diego a gdyby był 5 kątny hmm? Wiem że wszystko da się zrobić ale takie rozwiązanie moim zdaniem jest bardzo ciężkie do napisania. Już chyba lepiej by było trzymać w vectorze linie (2 punkty na 1 linie ofc).
Edit x2: LooooooooooooooooL ja sie pomyliłem i myślałem że akwes nade mną napisał WTF xd |
|
diego997 |
» 2012-09-08 15:28:44 @Razzor masz racje to jest "dobre" rozwiązanie tylko w przypadku czworokąta ;p Gdybym miał inną figurę to nie wiem. Wykrywanie kolizji to jedna sprawa a odpowiednie zareagowanie to druga ;p |
|
kubawal Temat założony przez niniejszego użytkownika |
» 2012-09-10 10:28:05 Dzięki Diego! Zrobiłem to tak: Są zmienne opisujące pozycje wszystkich wierzchołków obiektu o nazwach: o1, o2, o3, o4. Są też zmienne opisujące pozycje wierzchołków bitmapy ludka o nazwach: p1, p2, p3, p4. I teraz sprawdzam czy: p3 lub p4 nie koliduje z linią o1-o2, p4 lub p1 z linią o2-o3, p1 lub p2 z linią o3-o4, p3 lub p4 z linią o4-o1. Oto kod: Kolizje.h: #include <allegro.h> #include <string>
using namespace std;
inline int randint( int max ) { return rand() % max; }
inline int randint( int min, int max ) { return randint( max - min ) + min; }
#define K_1_2 1 #define K_2_3 2 #define K_3_4 3 #define K_4_1 4 #define K_NOT 0
bool kolizja( int x1, int y1, int s1, int w1, int x2, int y2, int s2, int w2 );
class Object { public: int X, Y; int W, H; BITMAP * bmp; Object( string name, int xX = 0, int yY = 0 ) : bmp( load_bmp( name.c_str(), default_palette ) ) , X( xX ) , Y( yY ) , W( bmp->w ) , H( bmp->h ) { } virtual bool collision( Object & o ); };
class Enemy;
class Player : public Object { struct Pos { int x, y; Pos( int xx, int yy ) : x( xx ) , y( yy ) { } }; int edges( Object & o ); public: int HP; int edge; Player( string name = "ludek.bmp", int xX = 300, int yY = 300 ) : Object( name, xX, yY ) , HP( 100 ) , edge( 0 ) { } bool collision( Object & o ); };
class Enemy : public Object { Enemy( string name = "przeszkoda.bmp", int xX = - 1, int yY = - 1 ) : Object( name ) { if( xX = - 1 ) X = randint( 0, 600 - W ); else X = xX; if( yY = - 1 ) Y = randint( 0, 600 - H ); else Y = yY; } };
Kolizje.cpp: #include "kolizje.h"
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; };
bool Object::collision( Object & o ) { if( kolizja( X, Y, W, H, o.X, o.Y, o.W, o.H ) || kolizja( o.X, o.Y, o.W, o.H, X, Y, W, H ) ) return true; else return false; }
bool Player::collision( Object & o ) { if( Object::collision( o ) ) { edge = edges( o ); return true; } else return false; }
int Player::edges( Object & o ) { Pos o1( o.X, o.Y ), o2( o.X + o.W, o.Y ), o3( o.X + o.W, o.Y + o.H ), o4( o.X, o.Y + o.W ); Pos p1( X, Y ), p2( X + W, Y ), p3( X + W, Y + H ), p4( X, Y + W ); if( o1.y == p3.y &&(( p3.x >= o1.x && p3.x <= o2.x ) ||( p4.x >= o1.x && p4.x <= o2.x ) ) ) return K_1_2; if( o2.x == p2.x &&(( p1.y >= o2.y && p1.y <= o3.y ) ||( p4.y >= o2.y && p4.y <= o3.y ) ) ) return K_2_3; if( o3.y == p1.y &&(( p1.x >= o3.x && p1.x <= o4.x ) ||( p2.x >= o3.x && p2.x <= o4.x ) ) ) return K_3_4; if( o4.x == p2.x &&(( p2.y >= o4.y && p2.y <= o1.y ) ||( p3.y >= o4.y && p3.y <= o1.y ) ) ) return K_4_1; return K_NOT; }
Czy to jest dobrze? |
|
« 1 » |