Poruszanie ludzika w wyznaczonym kierunku

0

Pisze sobie taka mala gierkę w allegro 5 i C++
Natknąłem się na pewien problem.
Mianowicie mój ludzik chodzi nie zawsze porusza się w wyznaczonym kierunku.
Mam np. bitmapę z samolotem i ten ludzik powinien poruszać się w kierunku wyznaczanym prze dziób
i nawet porusza się prawidłowo ... póki nim nie skręcisz , gdy skręcisz potrafi się poruszać 'bokiem'.
Przykładowo w kierunku wyznaczonym przez prawe skrzydło.
Nie wiem jak bardziej szczegółowo opisać problem.
Poniżej kod...

 class Gracz
{
private:
double tab_sin[72];
double tab_cos[72];
int lx,ly;
float radian;
double dx,dy;
int x ,y; // pozycja samochodu na ekranie
int kierunek ; // aktualny kierunek samochodu
double v; // prędkość naszego samochodu
float predkosc;
void Draw();
void Poruszanie();
ALLEGRO_BITMAP * samolot ;
public:
~Gracz();// dekonstruktor
Gracz();// konstruktor
void Play();
};
Gracz::Gracz()
{
 samolot = al_load_bitmap("Graphics\\player.png");
 lx = 100;
 ly = 100;
 x =200,y=200; // pozycja samochodu na ekranie
 dx=0,dy=0; // przesunięcie samochodu po osi X i Y
 kierunek = 0; // aktualny kierunek samochodu
 v=0.0; // prędkość naszego samochodu
      for(int i=0; i < 72; i ++)
     {
        tab_sin[i] = sin((M_PI*(i*5))/180);
        tab_cos[i] = cos((M_PI*(i*5))/180);
     }
}
Gracz::~Gracz()
{
al_destroy_bitmap (samolot);
}
void Gracz::Draw()
{
al_draw_rotated_bitmap(samolot, al_get_bitmap_width(samolot)/2, al_get_bitmap_height(samolot)/2, x, y, kierunek, 0);
}
void Gracz::Poruszanie()
{
al_get_keyboard_state(&klawiatura); //odczyt stanu klawiatury

if ( al_key_down(&klawiatura, ALLEGRO_KEY_RIGHT )) kierunek -- ;
if ( al_key_down(&klawiatura, ALLEGRO_KEY_LEFT  )) kierunek ++ ;
if ( al_key_down(&klawiatura, ALLEGRO_KEY_DOWN  )) v-= 0.02;
if ( al_key_down(&klawiatura, ALLEGRO_KEY_UP    )) v+= 0.02;
// Sprawdzamy wszystkie ograniczenia:
if( kierunek > 71) kierunek = 0;
if( kierunek < 0) kierunek = 71;
if( v >1.5) v=1.5;
if( v <-1) v=0;
// Obliczanie prędkości cząstkowych:
dx += v*tab_cos[ kierunek];
dy += v*tab_sin[ kierunek];
// Przemieszczanie naszego samochodu:
if( dx >=1 || dx <= -1) { x += int(dx); dx = dx - (dx); }
if( dy >=1 || dy <= -1) { y += int(dy); dy = dy - (dy); }

}
void Gracz::Play()
{
Poruszanie();
Draw();
}
0

W jakim celu każda instancja gracza posiada osobne pole preliczonych sinusów oraz cosinusów?
Nie wspominając o tym, że ten kod jest strasznie nieczytelny...

0

Ten kod jest nie czytelny bo jest to naklejanka kodów z różnych stron np http://www.easykoder.vot.pl/arty/samochodzik
tzn jeżeli chodzi o kod poruszania i obracania ludka reszta moja...

W jakim celu każda instancja gracza posiada osobne pole preliczonych sinusów oraz cosinusów?

Gracz będzie jeden więc nie widzę problemu.
A pytanie brzmi czemu ludek nie porusza się tak jak bym tego sobie życzył - gdzie leży błąd w kodzie.

0

Chyba zauważyłem w czym rzecz :
Mianowicie w funkcji wyświetlającej bitmapę podaję źle obliczony kąt obrotu w prawo podany radianach.
Pomóżcie je obliczyć w sposób prawidłowy...

2

Dlaczego wartosci stalych nie traktujesz jako stale?
Dlaczego funkcja pobierajaca stan klawiatury cos oblicza?
Dlaczego wczytujesz ten obrazek pierdyliard razy?
Dlaczego uzywasz magicznych liczb w kodzie?
Dlaczego nie inicjalizujesz wszystkich pol klasy?
Dlaczego to az tak brzydko wyglada?

0

Nie mam pojęcia co w starym kodzie było nie tak ale napisałem go od nowa i działa idealnie.
Wszystko napisałem w oparciu o :

Mas zjakaś zmienną, która reprezentuje kąt obrotu bohatera. Na strzałi lewo i prawo odejmujesz bądź dodajesz do tej zmiennej stałą wartość - to chyba jest jasne.

Teraz najważniejsza część: na wcisnięcie strzałki do przodu do pozycji x dodaj wartość szybkosc_ruchucos(kat_obrotu), do y dodaj (badź odejmij - zalezy jak przyjałeś oś y) szybkosc_ruchusin(kat_obrotu).
szybkosc_ruchu to stała, która oznacza o ile pikseli postac poruszy się zakładając, że porusza się pod kątem 0, 90, 180 lub 270 stopni.

Pozycję x i y najlepeij przechowywać jako float lub double i dopiero przy rysowaniu postaci rzutować na int (ruch dzięki temu jest dokładniejszy, uzyskujemy efekt, że jeśli psotać ma sie ruszyć o 2.25 piksela w lewo, to będzie poruszać się ciągle o 2, a za czwartym razem poruszy się o 3, by wyrównac różnicę).
Upewnij się też, że nie mieszasz stopni z radianami (obrot masz w stopniach, czy radianach, bo wbudowany sin i cos prawie na pewno działa na radianach).

ŹRÓDŁO : http://forum.programuj.com/viewtopic.php?p=50241
Oto mój kod:

 
class Gracz
{
private:
ALLEGRO_BITMAP * samolot ;
float kat_obrotu;
float szybkosc_ruchu;
void Draw();
void Poruszanie();
float lx,ly;
public:
~Gracz();// dekonstruktor
Gracz();// konstruktor
void Play();
};
Gracz::Gracz()
{
 samolot = al_load_bitmap("Graphics\\player.png");
 lx = 100;
 ly = 100;
 kat_obrotu = 0;
 szybkosc_ruchu = 0;
}
Gracz::~Gracz()
{
al_destroy_bitmap (samolot);
}
void Gracz::Draw()
{
al_draw_rotated_bitmap(samolot, al_get_bitmap_width(samolot)/2, al_get_bitmap_height(samolot)/2, (int)lx, (int)ly, kat_obrotu, NULL);
}
void Gracz::Poruszanie()
{
al_get_keyboard_state(&klawiatura); //odczyt stanu klawiatury

if ( al_key_down(&klawiatura, ALLEGRO_KEY_RIGHT ))kat_obrotu = kat_obrotu + 0.01;
if ( al_key_down(&klawiatura, ALLEGRO_KEY_LEFT  ))kat_obrotu = kat_obrotu - 0.01;
if ( al_key_down(&klawiatura, ALLEGRO_KEY_DOWN  ))szybkosc_ruchu = szybkosc_ruchu - 0.02;
if ( al_key_down(&klawiatura, ALLEGRO_KEY_UP    ))szybkosc_ruchu = szybkosc_ruchu + 0.02;
if(szybkosc_ruchu > 1.0)szybkosc_ruchu = 1.0;
if(szybkosc_ruchu < 0 )szybkosc_ruchu  = 0.0;
lx = lx + szybkosc_ruchu*cos(kat_obrotu);
ly = ly + szybkosc_ruchu*sin(kat_obrotu);
}
void Gracz::Play()
{
Poruszanie();
Draw();
}

@n0name_l możesz sprawdzić ten kod czy czegoś nie przeoczyłem ...:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1