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

[Allegro 4] Przyciski i ruch myszy - problem

Ostatnio zmodyfikowano 2011-11-18 13:08
Autor Wiadomość
mmove2
Temat założony przez niniejszego użytkownika
[Allegro 4] Przyciski i ruch myszy - problem
» 2011-11-18 11:12:32
Witam wszystkich użytkowników forum. Niestety, swoje pierwsze minuty tutaj zaczynam od proszenia o radę.
Napisałem taki kod (wiem, nie jest on piekny, ale powstał tylko po to, aby zobrazować problem).
C/C++
#include <allegro.h>
#include <cmath>
#define PI 3.14159

BITMAP * scrbuf = NULL;
BITMAP * sprite = NULL;
BITMAP * tlo = NULL;

class PLAYER
{
public:
    double x,
    y;
    fixed angle;
};

PLAYER player;

class bullet {
private:
    float damage;
    float x, y;
    float speed, alfa;
    BITMAP * grafika;
public:
    void SetDamage( float d )
    {
        damage = d;
    }
    void SetGrafika( const char * filename )
    {
        grafika = load_bmp( filename, default_palette );
    }
    void ReleaseGrafika()
    {
        destroy_bitmap( grafika );
    }
    float positionx()
    {
        return x;
    }
    float positiony()
    {
        return y;
    }
    void ComputeFly( int mx, int my, int px, int py )
    {
        mx = mouse_x;
        my = mouse_y;
        x = px;
        y = py;
        alfa = atan(( my - y ) /( mx - x ) );
        if( mx < x )
             alfa = alfa - PI;
       
    }
   
    void fly( float speed )
    {
        if( x > 0 && y > 0 && x < SCREEN_W && y < SCREEN_H )
        {
            x += cos( alfa ) * speed;
            y += sin( alfa ) * speed;
            masked_blit( grafika, scrbuf, 0, 0, x, y, grafika->w, grafika->h );
        }
    }
};

class gnat {
private:
    bullet pociski[ 31 ];
    int i, k;
public:
    gnat()
        : i( 29 )
    {
        memset( pociski, 0, 31 * sizeof( bullet ) );
    }
    void animuj()
    {
        for( int j = 29; j >= i; j-- )
        {
            pociski[ j ].fly( 2 );
        }
    }
   
    int strzelaj( int mx, int my )
    {
        pociski[ i ].SetDamage( 10 );
        pociski[ i ].SetGrafika( "bullet.bmp" );
        pociski[ i ].ComputeFly( mx, my, player.x, player.y );
        i--;
        return i;
    }
    void przeladuj()
    {
        i = 29;
        for( int j = 0; j < 29; j++ )
             pociski[ j ].ReleaseGrafika();
       
        memset( pociski, 0, 31 * sizeof( bullet ) );
    }
   
    float dawajx()
    {
        return pociski[ i ].positionx();
    }
    float dawajy()
    {
        return pociski[ i ].positiony();
    }
};

gnat bron;
bool strzal = 0;

int main()
{
    allegro_init();
    install_keyboard();
    set_color_depth( 32 );
    set_gfx_mode( GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0 );
    install_mouse();
    sprite = create_bitmap( 64, 64 );
    BITMAP * gracz = NULL;
    BITMAP * naboj = NULL;
    gracz = load_bmp( "gracz.bmp", default_palette );
    tlo = load_bmp( "Background.bmp", default_palette );
   
    scrbuf = create_bitmap( SCREEN_W, SCREEN_H );
    clear_to_color( sprite, makecol( 255, 0, 255 ) );
    blit( tlo, scrbuf, 0, 0, 0, 0, tlo->w, tlo->h );
    masked_blit( gracz, sprite, 0, 0, 0, 0, 64, 64 );
   
    blit( tlo, screen, 0, 0, 0, 0, tlo->w, tlo->h );
   
    show_mouse( screen );
    unscare_mouse();
   
    player.x = SCREEN_W / 2;
    player.y = SCREEN_H / 2;
    player.angle = 0;
   
    mouse_b = 0;
    int pestki = 29;
   
    while( !key[ KEY_ESC ] )
    {
       
        blit( tlo, scrbuf, 0, 0, 0, 0, tlo->w, tlo->h );
       
        player.angle = - fixatan2( ftofix( player.x - mouse_x ), ftofix( player.y - mouse_y ) );
       
        if( key[ KEY_LEFT ] )
             player.x = player.x - 1;
       
        if( key[ KEY_RIGHT ] )
             player.x = player.x + 1;
       
        if( key[ KEY_UP ] )
             player.y = player.y - 1;
       
        if( key[ KEY_DOWN ] )
             player.y = player.y + 1;
       
        if( mouse_b & 1 )
        {
            pestki = bron.strzelaj( mouse_x, mouse_y );
            show_mouse( screen );
            if( pestki == 0 )
                 bron.przeladuj();
           
            strzal = 1;
            mouse_b = 0;
        }
        if( strzal )
        {
            bron.animuj();
        }
        textprintf_ex( scrbuf, font, 10, 10, makecol( 255, 100, 200 ), - 1, "Gracz: x: %d, y: %d",( int ) player.x,( int ) player.y );
        textprintf_ex( scrbuf, font, 600, 10, makecol( 255, 100, 200 ), - 1, "Cel: x: %d, y: %d", mouse_x, mouse_y );
        textprintf_ex( scrbuf, font, 600, 30, makecol( 255, 100, 200 ), - 1, "Naboje: %d", pestki );
       
        rotate_sprite( scrbuf, sprite, player.x - sprite->w / 2, player.y - sprite->h / 2, player.angle );
        blit( scrbuf, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H );
    }
   
    destroy_bitmap( scrbuf );
    destroy_bitmap( sprite );
    destroy_bitmap( gracz );
    destroy_bitmap( tlo );
    destroy_bitmap( naboj );
    allegro_exit();
   
    return 0;
}
END_OF_MAIN();

W programie gracz wystrzeliwuje pociski kliknięciami lewego przycisku myszy.  A co jest problemem? Otóż gdy lewy przycisk myszy wciśniemy, ale go nie zwolnimy, to przy każdym ruchu myszką wystrzeliwane są wszystkie pociski na raz, powstaje taki "wężyk" na ekranie i dopóki nie zwolni się lewego przycisku myszy, to mamy śmiech nie strzelanie.
Czym jest to spowodowane? Czy pole mouse_b zawiera też informacje o ruchu myszy (wygląda na to, że tak)? Co zrobić, aby po wciśnięciu lewego przycisku myszy strzały pojawiały sie w cyklicznych odstępach, np. co pół sekundy?
Tak, wstawiałem do programu timer, ale nic to nie dało.

Dziękuję za poświęcony czas i proszę o radę :)

Kod źródłowy oraz bitmapy użyte w programie są tutaj: http://www.sendspace.com/file/64wdcx
P-44267
DejaVu
» 2011-11-18 12:00:26
C/C++
int strzelaj( int mx, int my )
{
    pociski[ i ].SetDamage( 10 );
    pociski[ i ].SetGrafika( "bullet.bmp" );
    pociski[ i ].ComputeFly( mx, my, player.x, player.y );
    i--;
    return i;
}
Musisz w tej metodzie dać jakiegoś timeouta żeby nie dało się dodawać nowego pocisku co klatkę. Np.
C/C++
int strzelaj( int mx, int my )
{
    if( m_czekaj > 0 )
         return;
   
    pociski[ i ].SetDamage( 10 );
    pociski[ i ].SetGrafika( "bullet.bmp" );
    pociski[ i ].ComputeFly( mx, my, player.x, player.y );
    i--;
    m_czekaj = 10;
    return i;
}
W metodzie aktualizującej położenie dopisać:
C/C++
void fly( float speed )
{
    //...
    if( m_czekaj > 0 )
         --m_czekaj;
   
}
W konstruktorze:
C/C++
m_czekaj = 0;
P-44268
mmove2
Temat założony przez niniejszego użytkownika
» 2011-11-18 13:08:46
Dziękuję za pomoc. Pomogło!
W klasie bullet dodałem publiczne pole m_czekaj, w konstruktorze tejże klasy zainicjalizowałem to zerem. Resztę zrobiłem zgodnie z podpowiedzią, a jako wartość interwału czasowego pomiędzy kolejnymi pociskami eksperymentalnie dobrałem 100 zamiast 10.

Pozdrawiam i dobrego weekendu życze! :)
P-44269
« 1 »
  Strona 1 z 1