Gra 2D, część 2 Wyżej, dalej, szybciej poruszanie postacią


Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
Opublikowane na Wrocławski Portal Informatyczny (http://informatyka.wroc.pl)
Strona główna > Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią
Gra 2D, część 2: Wyżej, dalej, szybciej -
poruszanie postacią
05.01.2010 - Marcin Milewski [1]
Trudność
Poprzedni artykuł - tworzenie okna i sprite'y [2]
Następny artykuł - przewijana mapa [3]
W tym artykule zajmiemy się
stworzeniem postaci sterowanej przez gracza. Stworzymy w tym celu model,
według którego bohater będzie się poruszał, aby ostatecznie tchnąć w niego
życie i oddać kontrolę nad nim graczowi.
Artykuł ten bazuje na kodzie stworzonym w poprzedniej części cyklu, o
tworzeniu okna i animacji na sprite'ach [2]. Lekko uaktualnioną wersję zródeł można znalezć
tutaj [4]. Oto efekt, który uzyskamy podczas tego artykułu:
Na początek kilka założeń dotyczących animacji oraz poruszania postacią w grze:
1. Gracz może stać, iść, biec lub skakać - sterowanie będzie się odbywać za pomocą
klawiatury
2. Można sterować ruchem bohatera również podczas skoku
3. Animacja będzie składać się z trzech stanów: stoi, idzie w lewo, idzie w prawo.
Pozostałe stany pozostawiamy jako proste ćwiczenie do wykonania.
Przyjmujemy, że przez pojęcie "gracza" rozumiemy osobę siedzącą przed komputerem, a
postać sterowana w grze to "bohater" czy właśnie "postać".
Animacja bohatera
Jak zaznaczyliśmy we wstępie, nasz bohater będzie mógł znajdować się w jednym z trzech
stanów: idzie w prawo, idzie w lewo lub stoi. Każdemu z tych stanów odpowiada jeden wiersz
1 z 12 2012-12-21 17:02
Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
na teksturze. Oto interesujący nas kawałek tej tekstury [5]:
Aktualne wymiary obrazka to 1024x1024, więc trzeba dokonać stosownego uaktualnienia w
pliku Renderer.cpp w metodzie DrawSprite:
1 // plik Renderer.cpp, metoda DrawSprite
2 const double texture_w = 1024.0;
3 const double texture_h = 1024.0;
4
Musimy także poinformować program, gdzie na teksturze znajdują się poszczególne
animacje. Przypomnijmy, że definiuje się je w pliku SpriteConfig.cpp:
1 SpriteConfig::SpriteConfig() {
2 Insert("player_right",
3 SpriteConfigData(
4 DL::Player, 5, 0.2, 0, 4*32, 32, 32, true));
5
6 Insert("player_left",
7 SpriteConfigData(
8 DL::Player, 5, 0.2, 0, 5*32, 32, 32, true));
9
10 Insert("player_stop",
11 SpriteConfigData(
12 DL::Player, 1, 0.2, 0, 6*32, 32, 32, true));
13 }
14
Natomiast klasę Engine należy poinformować, że nasza tekstura jest teraz w pliku tex.bmp
(przy okazji zmieńmy nazwę zmiennej na bardziej odpowiednią). Ponadto włączamy test
przezroczystości nakazując, aby piksele, które mają współrzędną A (od Alpha) większą niż
0.5 były rysowane jako przezroczyste. Pole m_player klasy App będzie reprezentowało
postać sterowaną przez gracza. Metoda SetSprites przekaże postaci informację o sprite'ach,
które ma wykorzystywać do odpowiednich animacji.
Pokaż/ukryj kod
1 // inicjalizacja OpenGL
2 glClearColor(0, 0, 0, 0);
3 glEnable(GL_DEPTH_TEST);
4 glDepthFunc(GL_LEQUAL);
5 glEnable(GL_TEXTURE_2D);
6 // niewyświetlanie przezroczystych fragmentów sprite'a
2 z 12 2012-12-21 17:02
Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
7 glEnable(GL_ALPHA_TEST);
8 glAlphaFunc(GL_GEQUAL, 0.1);
9
10 const std::string atlas_filename = "data/tex.bmp";
11 Engine& engine = Engine::Get();
12 engine.Load();
13 engine.Renderer()->LoadTexture(atlas_filename);
14 m_player->SetSprites(
15 SpritePtr(new Sprite(engine.SpriteConfig()->
16 Get("player_left"))),
17 SpritePtr(new Sprite(engine.SpriteConfig()->
18 Get("player_right"))),
19 SpritePtr(new Sprite(engine.SpriteConfig()->
20 Get("player_stop"))) );
21
22 // pętla główna (...)
23
Wskaznik na obiekt bohatera dodajemy do klasy App. Należy dołączyć także odpowiedni
nagłówek oraz zainicjować wskaznik bohatera. Deklaracja klasy App wygląda teraz
następująco:
Pokaż/ukryj kod
1 #include
2 #include "Player.h"
3
4 class App {
5 public:
6 explicit App(size_t win_width,
7 size_t win_height,
8 bool fullscreen_mode) :
9 m_window_width(win_width),
10 m_window_height(win_height),
11 m_fullscreen(fullscreen_mode) {
12 // 10-szerokość levelu (na razie 10 kafli, 1 ekran)
13 m_player.reset(new Player(1, 1, 10));
14 }
15
16 void Run();
17
18 private:
19 void Draw();
20 void Update(double dt);
21 void Resize(size_t width, size_t height);
22 void ProcessEvents();
23
24 private:
25 size_t m_window_width; // szerokość okna
26 size_t m_window_height; // wysokość okna
27 bool m_fullscreen; // tryb pełnoekranowy
28 bool is_done;
29 SDL_Surface* m_screen;
30
31 PlayerPtr m_player;
32 };
33
3 z 12 2012-12-21 17:02
Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
Obiekt postaci należy oczywiście aktualizować oraz rysować. Zrobimy to miejscach, gdzie
wcześniej aktualizowane oraz rysowane były przykładowe liczniki, czyli w metodach
odpowiednio Update oraz Draw.
1 void App::Update(double dt) {
2 m_player->Update(dt);
3 }
4
5 void App::Draw() {
6 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
7 glLoadIdentity();
8 // narysuj postać gracza
9 m_player->Draw();
10 SDL_GL_SwapBuffers();
11 }
12
Szczegóły dotyczące klasy Player omówimy za chwilę. Teraz potrzebujemy jeszcze struktury,
pozwalającej nam określić stan, w którym może znajdować się bohater. Zgodnie z
założeniem podajemy tylko 3 stany. W pozostałych stanach będziemy odtwarzali animację
któregoś ze zdefiniowanych stanów. Do opisania stanu definiujemy odpowiednie wyliczenie w
pliku Types.h:
1 namespace PS {
2 enum PlayerState {
3 Stand,
4 GoLeft,
5 GoRight
6 };
7 }
8
Trochę ruchu nikomu jeszcze nie zaszkodziło ;)
Nasz bohater będzie poruszał się w dwuwymiarowym układzie współrzędnych. Mamy zatem
ruch w poziomie oraz w pionie. Do modelowanie tego pierwszego użyjemy ruchu
jednostajnego, czyli prędkość poruszania się będzie stała w dla konkretnego stanu postaci.
Wyróżniamy 3 takie stany:
Stanie -
Chodzenie -
Bieganie - , gdzie jest pewną stałą większą od 1
Pojawia się pytanie: czy taki model wiernie oddaje rzeczywistość? Odpowiedz brzmi: nie, ale
to nie szkodzi. Zauważmy, że czas, w którym ciało przyspiesza (np. moment przejścia od
stanu spoczynku do chodu) jest bardzo krótki. Jego pominięcie zostanie zauważone (o ile w
ogóle) dopiero po dokładnym przyjrzeniu się ruchu postaci. Przypomnijmy zależności między
wartościami, które występują w ruchu jednostajnym:
Inaczej wygląda rzecz, kiedy przyjrzymy się ruchowi w pionie. Gdyby postać poruszała się
4 z 12 2012-12-21 17:02
Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
wyłącznie góra-dół (czyli prędkość pozioma byłaby równa 0), moglibyśmy rozważyć
zaniedbanie przyspieszenia w pionie. Zwróćmy także uwagę, że tor, po którym poruszałby
się bohater, byłby stosunkowo krótki, więc pominięcie przyspieszenia nie byłoby widoczne na
pierwszy rzut oka. Jednak, jak wspomnieliśmy, ruch naszego bohatera odbywa się w dwóch
wymiarach. Kiedy postać wykona skok po skosie, to oczekiwanym torem jego ruchu będzie
parabola. Zwróćmy uwagę, że ruch ten będzie trwał wystarczająco długo, aby zauważyć tor,
po którym porusza się sprite. Dlatego ruch w pionie opiszemy jako połączenie ruchu
jednostajnie opóznionego (wznoszenie się postaci) z ruchem jednostajnie przyspieszonym
(opadanie).
Przypomnijmy wzory wykorzystywane do opisania ruchu jednostajnie
przyspieszonego/opóznionego:
Na poniższej animacji widzimy dwa sposoby poruszania się postaci. Sprite po lewej jest
aktualizowany z wykorzystaniem ruchu jednostajnie przyspieszonego/opóznionego, a sprite
po prawej - ruchu jednostajnego prostoliniowego:
Implementacja poruszania postacią
Po krótkiej powtórce z teorii, nadszedł czas na zajęcie praktyczne, czyli implementację
poruszania postacią. Na postaci sterowanej przez gracza będziemy chcieli wykonywać kilka
czynności:
Zaktualizować jej położenie
Narysować ją
Zmienić jej stan: idz w lewo, idz w prawo, zatrzymaj się, skocz, spada
5 z 12 2012-12-21 17:02
Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
Zanim zobaczymy jak te czynności przekładają się na konkretny kod, określmy sposób w jaki
postać gracza będzie zmieniała swój stan. Na początku każdej klatki bohater będzie spadał
w dół, gdyż jest pod wpływem grawitacji. Następnie będziemy na niego nakładali kolejne
ograniczenia (nie może iść w lewo, nie może skakać, ...). W ten prosty sposób przedstawimy
wszystkie żądane zachowania. Spójrzmy teraz na deklarację klasy Player w pliku Player.h:
Pokaż/ukryj kod
1 #ifndef __PLAYER_H__
2 #define __PLAYER_H__
3
4 #include
5 #include "Sprite.h"
6 #include "Types.h"
7
8 class Player {
9 public:
10 explicit Player(double x, double y, size_t level_width);
11
12 void SetSprites(SpritePtr left, SpritePtr right, SpritePtr stop);
13 void Update(double dt);
14 void Draw() const;
15
16 double GetX() const { return m_x; }
17 double GetY() const { return m_y; }
18 double GetDefaultYVelocity() const {
19 return DefaultYVelocity;
20 }
21 double GetDefaultYAcceleration() const {
22 return DefaultYAcceleration;
23 }
24
25 void Run() { m_running_factor = 2.0; }
26 void StopRunning() { m_running_factor = 1.0; }
27 void GoLeft() { m_vx -= 4.0; m_state=PS::GoLeft; }
28 void GoRight() { m_vx += 4.0; m_state=PS::GoRight;}
29 void StopLeft() { m_vx += 4.0; m_state=PS::Stand; }
30 void StopRight() { m_vx -= 4.0; m_state=PS::Stand; }
31 void ForbidGoingLeft() { m_can_go_left = false; }
32 void ForbidGoingRight() { m_can_go_right = false; }
33 void Fall() { m_vy = 0.0; m_is_on_ground = false;}
34 void Jump(double y_velocity = DefaultYVelocity);
35 void AllowToJump() { m_jump_allowed = true; }
36 void ForbidToJump() { m_jump_allowed = false; }
37 void SetDefaultMoving() { m_is_on_ground = false;
38 m_can_go_right = m_can_go_left=true;
39 }
40 void PlayerOnGround() { m_vy = 0;
41 m_is_on_ground=m_jump_allowed=true;
42 }
43
44 double GetNextXPosition(double dt) const {
45 return m_x + m_vx * dt * m_running_factor;
46 }
47 double GetNextYPosition(double dt) const {
48 return m_y + (m_vy + m_ay * dt) * dt;
49 }
50
51 private:
52
6 z 12 2012-12-21 17:02
Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
53 enum { DefaultYVelocity = 20, DefaultYAcceleration=-60 };
54
55 PS::PlayerState m_state; // stan, w którym znajduje się postać
56 SpritePtr m_left; // animacja - postać idzie w lewo
57 SpritePtr m_right; // animacja - postać idzie w prawo
58 SpritePtr m_stop; // animacja - postać stoi
59 double m_x; // położenie postaci na osi odciętych
60 double m_y; // położenie postaci na osi rzędnych
61 double m_vx; // prędkość na osi OX
62 double m_vy; // prędkość gracza w pionie
63 double m_ay; // przyspieszenie gracza w pionie
64 double m_running_factor; // współczynnik biegania.
65 // >1.0 => biegnie,
66 // <1.0 => spowolnienie
67 bool m_jump_allowed; // czy gracz może skakać
68 // (np. jest na podłożu)
69 size_t m_level_width; // szerokość poziomu (w kaflach)
70 bool m_is_on_ground; // czy postać jest na podłożu
71 bool m_can_go_left; // czy postać może iść w lewo
72 bool m_can_go_right; // czy postać może iść w prawo
73 };
74 typedef boost::shared_ptr PlayerPtr;
75
76 #endif
Nie powinno być wątpliwości co do większości metod oraz pól. Warto jednak zaznaczyć, że
klasa Player powinna zapewniać metody pozwalające nie tylko pobierać jej stan, ale także go
zmieniać. Na przykład metody dotyczące skoku przydadzą się przy reagowaniu na kolizje z
obiektami na planszy (np. żółw, na którego można skoczyć i wybić się w górę). Wartości
stałych DefaultYVelocity oraz DefaultYAcceleration, jak również wartości określające
prędkość i przyspieszenie postaci zostały dobrane drogą eksperymentu. W każdej chwili
można zmienić je na inne, jeżeli uznamy, że bohater porusza się za wolno lub skacze zbyt
nisko.
Wśród mnogości pól i metod zauważamy kilka funkcji odnoszących się jakby do tej samej
funkcjonalności: np. StopLeft oraz ForbidGoingLeft. Pierwsza z nich mówi graczowi, że ruch
w lewo definitywnie się zakończył (np. gracz nie trzyma już dłużej odpowiedniego klawisza),
druga natomiast zabrania w danym momencie poruszania się w lewo - powodem może być
np. ściana, lub przesuwanie jakiegoś elementu.
Mając zdefiniowane funkcje do manipulacji bohaterem, możemy dodać kod, który będzie z
nich korzystał zapewniając tym samym interakcję między graczem z postacią w wirtualnym
świecie. Kod obsługujący wejście znajduje się w metodzie App::ProcessEvents w pliku
App.cpp. Zapewnia on reakcję bohatera na naciśnięcie odpowiednich klawiszy. Obecnie
wygląda on następująco:
Pokaż/ukryj kod
1 void App::ProcessEvents() {
2 if (is_done)
3 return;
4
5 // przyjrzyj zdarzenia
6 SDL_Event event;
7 while (SDL_PollEvent(&event)) {
8 if (event.type == SDL_VIDEORESIZE) {
7 z 12 2012-12-21 17:02
Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
9 Resize(event.resize.w, event.resize.h);
10 } else if (event.type == SDL_QUIT) {
11 is_done = true;
12 break;
13 // naciśnięcie ESC -> wyjście z gry
14 } else if (event.type == SDL_KEYDOWN
15 && event.key.keysym.sym == SDLK_ESCAPE) {
16 is_done = true;
17 break;
18 // klawisz d - bieganie
19 } else if (event.type == SDL_KEYDOWN
20 && event.key.keysym.sym == SDLK_d) {
21 m_player->Run();
22 } else if (event.type == SDL_KEYUP
23 && event.key.keysym.sym == SDLK_d) {
24 m_player->StopRunning();
25 // strzałka w górę - skok
26 } else if (event.type == SDL_KEYDOWN
27 && event.key.keysym.sym == SDLK_UP) {
28 m_player->Jump();
29 // strzałka w lewo - idz w lewo
30 } else if (event.type == SDL_KEYDOWN
31 && event.key.keysym.sym == SDLK_LEFT) {
32 m_player->GoLeft();
33 // strzałka w prawo - idz w prawo
34 } else if (event.type == SDL_KEYDOWN
35 && event.key.keysym.sym == SDLK_RIGHT) {
36 m_player->GoRight();
37 // zwolnienie strzałki w lewo
38 // - zatrzymaj poruszanie w lewą stronę
39 } else if (event.type == SDL_KEYUP
40 && event.key.keysym.sym == SDLK_LEFT) {
41 m_player->StopLeft();
42 // zwolnienie strzałki w prawo
43 // - zatrzymaj poruszanie w prawą stronę
44 } else if (event.type == SDL_KEYUP
45 && event.key.keysym.sym == SDLK_RIGHT) {
46 m_player->StopRight();
47 }
48 }
49 }
50
Przyjrzyjmy się implementacji klasy Player. W konstruktorze ustawiamy początkowy stan
postaci: stoi na pozycji (x, y), porusza się z prędkością [0, 0] oraz przyspieszeniem [0,
DefaultYAcceleration]. Może skakać (zakładamy, że stoi na podłożu), porusza się z normalną
prędkością (nie biegnie - m_running_factor=1.0). Dodatkowo przekazujemy informacje na
temat szerokość poziomu. Te informacje będą potrzebne, aby określić początek i koniec
planszy oraz aby narysować postać na ekranie. W ciele konstruktora ustawiamy domyślny
stan ruchu - prawdopodobnie nadpisując ustawione na liście inicjalizacji pola.
1 #include
2 #include "Player.h"
3 #include "Engine.h"
4
5 Player::Player(double x, double y, size_t level_width)
6 : m_state(PS::Stand),
7 m_x(x),
8 z 12 2012-12-21 17:02
Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
8 m_y(y),
9 m_vx(0.0),
10 m_vy(0),
11 m_ay(DefaultYAcceleration),
12 m_running_factor(1.0),
13 m_jump_allowed(true),
14 m_level_width(level_width),
15 m_is_on_ground(true),
16 m_can_go_left(true),
17 m_can_go_right(true) {
18 SetDefaultMoving();
19 }
20
Metodę SetSprite widzieliśmy już wcześniej. Ustawia ona sprite'y dla poszczególnych
animacji bohatera - idzie w lewo, idzie w prawo, stoi.
1 void Player::SetSprites(SpritePtr left,
2 SpritePtr right,
3 SpritePtr stop) {
4 m_left = left;
5 m_right = right;
6 m_stop = stop;
7 }
8
W metodzie Jump zmieniamy pola obiektu tak, aby możliwy był skok. Nadajemy wartości
prędkości oraz przyspieszeniu w pionie, a także dbamy o to, aby postać nie mogła skoczyć,
jeżeli nie jest to możliwe. W Draw przeliczamy współrzędne postaci w wirtualnym świecie na
współrzędne na ekranie, a następnie rysujemy odpowiedniego sprite'a.
Pokaż/ukryj kod
1 void Player::Jump(double y_velocity) {
2 // wykonaj skok o ile jest taka możliwość
3 if (m_jump_allowed) {
4 m_jump_allowed = false;
5 m_is_on_ground = false;
6 m_vy = y_velocity; // początkowa prędkość
7 m_ay = DefaultYAcceleration; // przyspieszenie
8 }
9 }
10
11 void Player::Draw() const {
12 const double tile_width =
13 Engine::Get().Renderer()->GetTileWidth();
14 const double tile_height =
15 Engine::Get().Renderer()->GetTileHeight();
16
17 // wylicz pozycję gracza na ekranie
18 const double pos_x = m_x * tile_width;
19 const double pos_y = m_y * tile_height;
20
21 switch (m_state) {
22 case PS::Stand:
23 m_stop->DrawCurrentFrame(pos_x, pos_y,
24 tile_width, tile_height);
9 z 12 2012-12-21 17:02
Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
25 break;
26 case PS::GoLeft:
27 m_left->DrawCurrentFrame(pos_x, pos_y,
28 tile_width, tile_height);
29 break;
30 case PS::GoRight:
31 m_right->DrawCurrentFrame(pos_x, pos_y,
32 tile_width, tile_height);
33 break;
34 }
35 }
36
Na koniec najciekawsza z metod klasy Player, metoda Update. W pierwszych liniach
modyfikujemy prędkość oraz położenie zgodnie ze wzorami podanymi w części teoretycznej
tego artykułu. Przy aktualizacji położenia bohatera na osi OX (metoda GetNextXPosition)
zauważmy występujący tam współczynnik m_running_factor odpowiadający za szybsze
poruszanie się postaci (bieganie). Ustalamy również granice na planszy, w których postać
powinna się zmieścić. Nie chcemy, aby wyszła ona za początek lub koniec planszy oraz aby
spadła poniżej poziomu y=1. To ostatnie wymaganie jest tymczasowe, gdyż w przyszłości
bohater będzie poruszał się po podłożu, z którego będzie mógł spaść. W końcowej części,
na postawie prędkości w poziomie, ustalamy w jakim stanie znajduje się postać, po czym
aktualizujemy animację.
Pokaż/ukryj kod
1 void Player::Update(double dt) {
2 // wylicz nową prędkość oraz połóżenie na osi OY
3 if (!m_is_on_ground) {
4 m_y = GetNextYPosition(dt);
5 m_vy += m_ay * dt;
6 }
7
8 // jeżeli poniżej pierwszego kafla, to nie spadaj niżej.
9 // Na razie ustalamy poziom na y=1, aby postać nie uciekała
10 // za ekran
11 if (m_y < 1) {
12 m_y = 1;
13 PlayerOnGround();
14 }
15
16 // wylicz pozycję gracza w poziomie (oś OX).
17 m_x = GetNextXPosition(dt);
18
19 // nie można wyjść poza mapę
20 if (m_x < 0) {
21 m_x = 0; // nie można wyjść za początek mapy
22 } else if (m_x > m_level_width - 1) {
23 // nie można wyjść za prawą krawędz mapy
24 m_x = m_level_width - 1;
25 }
26
27 // ustal stan ruchu gracza na podstawie prędkości
28 if (fabs(m_vx) < 0.01) {
29 m_state = PS::Stand;
30 m_vx = 0;
31 } else if (m_vx > 0.0) {
32 m_state = PS::GoRight;
10 z 12 2012-12-21 17:02
Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
33 } else {
34 m_state = PS::GoLeft;
35 }
36
37 // uaktualnij animację
38 switch (m_state) {
39 case PS::Stand:
40 m_stop->Update(dt);
41 break;
42 case PS::GoLeft:
43 m_left->Update(dt);
44 break;
45 case PS::GoRight:
46 m_right->Update(dt);
47 break;
48 }
49 }
50
Przedstawiona metoda Update i krótkie pomocnicze metody dbają o to, aby bohater poruszał
się w taki sposób jak chce tego gracz. Warto poświęcić chwilę czasu na dokładne
zrozumienie zmiany stanu postaci, gdyż do tego zagadnienia wrócimy w artykule o
wykrywaniu kolizji. Zobaczymy w nim m.in. jak stworzony przez nasz model sprawdza się w
akcji.
Warto dodać informację podczas uruchamiania aplikacji o sposobie sterowania postacią. Oto
uaktualniona zawartość pliku main.cpp:
1 #include "App.h"
2 #include
3
4 int main(int argc, char *argv[]) {
5 std::cout
6 << " strzałki lewo/prawo - poruszanie się postacią\n"
7 << " strzałka do góry - skok\n"
8 << " przytrzymanie klawisza d - bieganie"
9 << std::endl;
10
11 App app(600, 400, false);
12 app.Run();
13 return 0;
14 }
15
A oto efekt końcowy:
11 z 12 2012-12-21 17:02
Gra 2D, część 2: Wyżej, dalej, szybciej - poruszanie postacią http://informatyka.wroc.pl/print/422
Kompletny kod zródłowy do tego artykułu można znalezć pod tym adresem [6]. Dostępna jest
też wersja z projektem w Dev-C++ [7] pod Windows.
Masz pytanie, uwagę? Zauważyłeś błąd? Powiedz o tym na forum [8].
Zadania dla dociekliwych
1. Rozszerz klasę Player o stany skacze, spada oraz biegnie. Taka zmiana wiąże się z
dodaniem nowych animacji oraz zapewnienia odpowiedniego przejścia między stanami
postaci. Czy jest możliwe aby dodać nowy stan bez dodawania nowej animacji?
Przyjrzyj się stanowi biegnie.
2. Ogranicz (częściowo lub całkowicie) możliwość sterowania postacią gdy znajduje się w
powietrzu.
Poprzedni artykuł - tworzenie okna i sprite'y [2] Następny artykuł - przewijana mapa [3]
Adres zródła: http://informatyka.wroc.pl/node/422
Odnośniki:
[1] http://marcindev.blogspot.com/
[2] http://informatyka.wroc.pl/node/387
[3] http://informatyka.wroc.pl/node/474
[4] http://informatyka.wroc.pl/upload/mmi/platf/02_start.zip
[5] http://informatyka.wroc.pl/sites/default/files/user_files/u958/02_tex.png
[6] http://informatyka.wroc.pl/upload/mmi/platf/02_final.zip
[7] http://informatyka.wroc.pl/upload/mmi/platf/02_final_devcpp.zip
[8] http://informatyka.wroc.pl/forum/viewtopic.php?f=55&t=358
12 z 12 2012-12-21 17:02


Wyszukiwarka

Podobne podstrony:
Gra 2D, część 3 Wyświetlanie przewijanej mapy
Gra 2D, część 4 Piszemy Hall of Fame
Gra 2D, część 4 Piszemy Hall of Fame
Gra Memory Owoce (Fruits), częśc 1

więcej podobnych podstron