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

[c++, allegro5] Złe poruszanie przy obrocie obiektu

Ostatnio zmodyfikowano 2013-07-04 14:28
Autor Wiadomość
Rughailon
Temat założony przez niniejszego użytkownika
[c++, allegro5] Złe poruszanie przy obrocie obiektu
» 2013-07-01 20:31:36
Witam. Mam pewien problem, którego nijak rozwiązać nie potrafię.

Mam klase czołgu, w której są wszystkie potrzebne zmienne i funkcje na obracanie.

Tanks.hpp
C/C++
#ifndef TANKS_HPP_INCLUDED
#define TANKS_HPP_INCLUDED

#include "main.h"
#include "input.h"

class cTank {
public:
    int x, y;
    int w, h;
    float v, max_v;
    int strength;
    float angle_tank;
    float v_gun, angle_gun;
   
    ALLEGRO_BITMAP * tank;
    ALLEGRO_BITMAP * gun;
   
    cTank( int, int, int, int, float, int, ALLEGRO_BITMAP *, ALLEGRO_BITMAP * );
   
    bool gun_angle();
    bool go();
};

#endif // TANKS_HPP_INCLUDED
Tanks.cpp
C/C++
#include "Tanks.hpp"

extern CKeyboard key;
extern CMouse mouse;

cTank::cTank( int X, int Y, int W, int H, float MAX_V, int STRENGHT, ALLEGRO_BITMAP * TANK, ALLEGRO_BITMAP * GUN )
    : x( X )
    , y( Y )
    , w( W )
    , h( H )
    , max_v( MAX_V )
    , strength( STRENGHT )
    , tank( TANK )
    , gun( GUN )
{
    v = 0;
    angle_tank = 0;
    v_gun = 0;
    angle_gun = 0;
}

bool cTank::gun_angle() {
    angle_gun = atan2( mouse.getY() - y, mouse.getX() - x );
}

bool cTank::go() {
    if( key.Press( ALLEGRO_KEY_W ) )
         v += 0.1;
   
    if( key.Press( ALLEGRO_KEY_A ) )
         angle_tank -= 0.01;
   
    if( key.Press( ALLEGRO_KEY_D ) )
         angle_tank += 0.01;
   
    if( key.Press( ALLEGRO_KEY_S ) )
         v -= 0.1;
   
    x += v * cos( angle_tank );
    y += v * sin( angle_tank );
    cout << x << " , " << y << endl;
   
}

I teraz jest problem, bo gdy obrócę czołgiem o pewną wartość, to czołg zaczyna sam jechać, a jeśli stoi, to po poruszeniu, za bardzo zmniejsza swoją pozycje na osi x(jedzie nienaturalnie w góre ekranu).
Przeglądałem tematy na tym forum i siedziałem nad kartką, ale nic nie przychodzi mi do głowy. Szereg poprawek także nie pomógł.

I tu jeszcze kod na wyświetlanie grafiki czołgu.
C/C++
//...
//... Pętla główna ...//
al_draw_rotated_bitmap( one.tank, getBmpW( one.tank ) / 2, getBmpH( one.tank ) / 2, one.x, one.y, one.angle_tank, 0 );
//...
P-86753
DejaVu
» 2013-07-02 00:29:31
C/C++
angle_gun = atan2( mouse.getY() - y, mouse.getX() - x );
To jest niepoprawne. Jeżeli Allegro przyjmuje kąty w stopniach to musisz pozamieniać radiany na stopnie.

» standard Catan2
P-86784
SeaMonster131
» 2013-07-02 10:47:23
@up: Allegro5 przyjmuje kąt w radianach, wiec nie trzeba niczego zamieniać ;)
P-86791
DejaVu
» 2013-07-02 10:49:04
No to może bitmapa ma puste miejsce z jakiegoś boku i wówczas środek czołgu nie jest po środku tekstury, tylko w innym miejscu przez co uzyskuje się dziwne efekty.
P-86792
Gabes
» 2013-07-02 13:34:15
Napisałem mały testowy program, który chyba lepiej pokaże wszystko, niż kilka linijek które nic ci nie pomogą. 
C/C++
#include <allegro5/allegro.h>
#include <allegro5/allegro_font.h>
#include<allegro5/allegro_image.h>
#include <cmath>
int main()
{
    al_init();
    al_install_keyboard();
    al_install_mouse();
    al_init_font_addon();
    al_init_image_addon();
    ALLEGRO_KEYBOARD_STATE key_state;
    ALLEGRO_MOUSE_STATE mouse_state;
    al_set_new_display_flags( ALLEGRO_FULLSCREEN );
    ALLEGRO_DISPLAY * okno = al_create_display( 800, 600 );
    al_set_window_title( okno, "Tank" );
    ALLEGRO_BITMAP * tank = al_create_bitmap( 40, 80 );
    ALLEGRO_BITMAP * lufa = al_create_bitmap( 10, 60 );
    ALLEGRO_FONT * font8 = al_create_builtin_font();
    al_set_target_bitmap( tank );
    al_clear_to_color( al_map_rgb( 150, 50, 50 ) );
    al_set_target_bitmap( lufa );
    al_clear_to_color( al_map_rgb( 255, 250, 250 ) );
    al_set_target_bitmap( al_get_backbuffer( okno ) );
    float TankX = 400, TankY = 560;
    float SpeedT = 0.04;
    float AngleT = 0.0;
    float AngleL = 0.0;
    while( !al_key_down( & key_state, ALLEGRO_KEY_ESCAPE ) )
    {
        al_clear_to_color( al_map_rgb_f( 0.5, 0.5, 0.5 ) );
        al_get_keyboard_state( & key_state );
        al_get_mouse_state( & mouse_state );
        if( al_key_down( & key_state, ALLEGRO_KEY_D ) ) AngleT += 0.001;
       
        if( al_key_down( & key_state, ALLEGRO_KEY_A ) ) AngleT -= 0.001;
       
        if( al_key_down( & key_state, ALLEGRO_KEY_W ) ) SpeedT += 0.0001;
       
        if( al_key_down( & key_state, ALLEGRO_KEY_S ) ) SpeedT -= 0.0001;
       
        if( al_key_down( & key_state, ALLEGRO_KEY_SPACE ) ) SpeedT = 0.04, TankX = 400, TankY = 300;
       
        TankX += SpeedT * cos( AngleT - ALLEGRO_PI / 2 );
        TankY += SpeedT * sin( AngleT - ALLEGRO_PI / 2 );
        AngleL = atan2( TankY - mouse_state.y, TankX - mouse_state.x ) - ALLEGRO_PI / 2, 0;
        al_draw_rotated_bitmap( tank, al_get_bitmap_width( tank ) / 2, al_get_bitmap_height( tank ) / 2, TankX, TankY, AngleT, 0 );
        al_draw_rotated_bitmap( lufa, al_get_bitmap_width( lufa ) / 2, al_get_bitmap_height( lufa ), TankX, TankY, AngleL, 0 );
        al_draw_textf( font8, al_map_rgb( 255, 255, 0 ), 5, 5, 0,
        "TankX=%3.0f , TankY=%3.0f , AngleL%4.0f , AngleT%4.0f", TankX, TankY, AngleL, AngleT );
        al_flip_display();
    }
    al_destroy_bitmap( tank );
    al_destroy_bitmap( lufa );
    al_destroy_display( okno );
    return 0;
}
Edycja: Poprawiłem kod, niepotrzebnie zamieniałem wcześniej na stopnie, a w funkcji wyświetlającej z powrotem na radiany.
Było tak:
C/C++
TankX += speedT * cos(( angleT * ALLEGRO_PI ) / 180.0 );
TankY += speedT * sin(( angleT * ALLEGRO_PI ) / 180.0 );
al_draw_rotated_bitmap( tank, 40 / 2, 80 / 2, TankX, TankY,( angleT - 90 ) *( ALLEGRO_PI / 180 ), 0 );

P-86801
Rughailon
Temat założony przez niniejszego użytkownika
» 2013-07-04 14:28:18
No niestety nadal nie działa tak, jak powinno. O dziwo przykładowy kod działa, więc podejrzewam, że spieprzyłem coś małego.

No nic. Dziękuje wam bardzo za pomoc. :)

//edit
Już wszystko działa. Seamonster131 rozwiązał problem. :)
Okazało się zmienne x i y w klasie czołgu powinny być we float, a nie w int.
Na dodatek trzeba było usunąć "-ALLEGRO_PI/2" w cos() i sin().
P-86959
« 1 »
  Strona 1 z 1