Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] [Allegro] Problem z kolizją (znowu... :) )

Ostatnio zmodyfikowano 2012-11-22 18:18
Autor Wiadomość
kubawal
Temat założony przez niniejszego użytkownika
[C++] [Allegro] Problem z kolizją (znowu... :) )
» 2012-11-20 16:04:07
Witam!

Ostatnio napisałem sobie gierkę typu "ludzik ruszany strzałkami"
Wszystko działało, do momentu, gdy dodałem kolizję z obiektem i zamiast skomplikowanego kodu dodałem klasy.
Oto mój kod:

classes.h
C/C++
#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; }

//definicje krawędzi zwracanych przez funkcję Player::Edges()

#define K_1_2 1 //krawędź między rogami 1 i 2
#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;
   
    struct Invalid { Invalid() { } };
   
    Object( string name, int xX = 0, int yY = 0 )
        : X( xX )
        , Y( yY )
    { bmp = load_bmp( name.c_str(), default_palette ); if( !bmp ) throw Invalid(); W = bmp->w; H = bmp->h; }
    virtual ~Object() { destroy_bitmap( bmp ); }
   
    virtual bool collision( Object & o );
};

class Enemy;

class Player
    : public Object
{
    struct Pos // struktura pomocnicza dla funkcji edges()
    {
        int x, y;
        Pos( int xx, int yy )
            : x( xx )
            , y( yy )
        { }
    };
    int edges( Object & o );
public:
    int HP;
    int edge; // krawędź uderzenia
   
    Player( string name = "C:\\grafika\\ludek.bmp", int xX = 300, int yY = 300 )
        : Object( name, xX, yY )
        , HP( 100 )
        , edge( K_NOT )
    { }
   
    bool collision( Object & o );
};

class Enemy
    : public Object
{
public:
    Enemy( string name = "C:\\grafika\\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;
       
    }
   
};

class Buffer
{
    BITMAP * buf;
    int color;
public:
   
    Buffer( int w, int h, int ccolor = makecol( 0, 0, 0 ) )
        : buf( create_bitmap( w, h ) )
        , color( ccolor )
    { clear(); }
    ~Buffer() { destroy_bitmap( buf ); }
   
    void clear() { clear_to_color( buf, color ); }
    enum Copy_type { Normal, Masked };
    void copy( BITMAP * src, int x, int y, Copy_type bt );
    void draw();
};

classes.cpp
C/C++
#include "classes.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;
   
}

//schemat wierzchołków w funkcji edges():
//  1-------2
//  |       |
//  |       |
//  |       |
//  4-------3

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 ); // wierzchołki obiektu
    Pos p1( X, Y ), p2( X + W, Y ), p3( X + W, Y + H ), p4( X, Y + W ); // wierzchołki Playera
   
    if( o1.y == p3.y &&(( p3.x >= o1.x && p3.x <= o2.x ) ||( p4.x >= o1.x && p4.x <= o2.x ) ) )
    //p3 lub p4 koliduje z o na lini o1-o2 lub na jego krawêdziach 1 i 2
         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 ) ) )
    //p4 lub p1 koliduje z o na lini o4-o1 lub na jego krawêdziach 2 i 3
         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 ) ) )
    //p2 lub p3 koliduje z o na lini o4-o1 lub na jego krawêdziach 4 i 1
         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 ) ) )
    //p4 lub p1 koliduje z o na lini o4-o1 lub na jego krawêdziach 2 i 3
         return K_4_1;
   
    return K_NOT;
}


void Buffer::copy( BITMAP * src, int x, int y, Copy_type bt )
{
    switch( bt )
    {
    case Normal:
        blit( src, buf, 0, 0, x, y, src->w, src->h );
        break;
    case Masked:
        masked_blit( src, buf, 0, 0, x, y, src->w, src->h );
        break;
    }
}
void Buffer::draw()
{
    blit( screen, buf, 0, 0, 0, 0, buf->w, buf->h );
    clear();
}

main.cpp
C/C++
#include "classes.h"
#define SILA_ODBICIA 5

Buffer buf( 800, 800, makecol( 255, 255, 255 ) );

void Game();
void Repaint( Player & p, Enemy & e );

int main( void )
{
    allegro_init();
    install_keyboard();
   
    set_gfx_mode( GFX_AUTODETECT_WINDOWED, 800, 800, 0, 0 );
    set_color_depth( 8 );
    set_palette( default_palette );
    clear_to_color( screen, makecol( 0, 255, 255 ) );
   
    Game();
   
    allegro_exit();
    return 0;
}
END_OF_MAIN();

void Game() try
{
   
   
    Player player( "C:\\grafika\\ludek.bmp" );
    Enemy enemy( "C:\\grafika\\przeszkoda.bmp" );
   
    clear_to_color( screen, makecol( 0, 255, 255 ) );
   
   
    while( !key[ KEY_ESC ] )
    {
       
        if( !player.collision( enemy ) )
        {
            if( key[ KEY_UP ] ) player.Y--;
           
            if( key[ KEY_DOWN ] ) player.Y++;
           
            if( key[ KEY_LEFT ] ) player.X--;
           
            if( key[ KEY_RIGHT ] ) player.X++;
           
        }
        else // kolidujemy z wrogiem
        {
            switch( player.edge ) // odbijamy go
            {
            case K_1_2:
                player.Y -= SILA_ODBICIA;
                break;
            case K_2_3:
                player.X += SILA_ODBICIA;
                break;
            case K_3_4:
                player.Y += SILA_ODBICIA;
                break;
            case K_4_1:
                player.X -= SILA_ODBICIA;
            default: // nieznany przypadek, b³¹d
                allegro_message( "Niespodziawany błąd w funkcji Player::colission(): niezdefiniowana krawędź uderzenia" );
            }
            player.HP -= 10;
        }
       
        Repaint( player, enemy );
       
    }
   
   
}
catch( Object::Invalid oi )
{
   
    allegro_message( "Wystąpił błąd ładowania bitmap \"ludek.bmp\" i \"przeszkoda.bmp\"" );
    return;
}

void Repaint( Player & p, Enemy & e )
{
   
    buf.copy( p.bmp, p.X, p.Y, Buffer::Masked );
    buf.copy( e.bmp, e.X, e.Y, Buffer::Masked );
   
    buf.draw();
    buf.clear();
}

Gdy próbuje ją uruchomić, występuje błąd czasu wykonania ("Wystąpił problem z aplikacją allegro.exe..." itd.)
Wiecie, co się dzieje?

Pozdrawiam
kubawal
P-69606
DejaVu
» 2012-11-20 17:31:57
Szukaj ewentualnej przyczyny problemu w miejscach, gdzie wczytujesz bitmapy (może jakieś wczytanie się nie powiodło) oraz w miejscach, gdzie możesz wykroczyć poza tablice (jeżeli w kodzie masz takie).
P-69613
RazzorFlame
» 2012-11-20 18:34:27
"C:\\grafika\\ludek.bmp"
Nie lepiej podawać ścieżkę w taki sposób?
"C:/grafika/ludek.bmp"
P-69622
kubawal
Temat założony przez niniejszego użytkownika
» 2012-11-21 16:15:35
W kodzie nie używam tablic poza key.

Problem z wczytaniem bitmap zostałby zgłoszony
if( !bmp ) throw Invalid();
 
Chyba, że widzicie jakieś potencjalne problemy w klasach Object, Player, Enemy a szczególnie w Buffer ?
P-69647
krzyk
» 2012-11-21 16:31:51
set_color_depth chyba powinno być przed set_gfx_mode.
Sprawdzaj też czy set_gfx_mode wogóle zadziałało.
P-69648
kubawal
Temat założony przez niniejszego użytkownika
» 2012-11-21 16:56:58
Znam już źródło problemu:

C/C++
Buffer( int w, int h, int ccolor = makecol( 0, 0, 0 ) )
    : buf( create_bitmap( w, h ) ) // tu się psuje
    , color( ccolor )
 

Jednak ciągle nie wiem, jak to naprawić.
P-69649
krzyk
» 2012-11-21 17:05:35
Używasz create_bitmap przed zainicjowaniem allegro.
P-69652
kubawal
Temat założony przez niniejszego użytkownika
» 2012-11-22 18:18:46
OK, dzięki. Temat zamknięty.
P-69699
« 1 »
  Strona 1 z 1