fizyka wzory prawa zadania teoria, chemia teoria zadania wzory, modelarstwo szkutnicze
izometria22.jpg

Pobierz kod Izometria w świecie prostokątnym- część 2
 
RUCH BOHATERA- IZOMETRIA W ŚWIECIE PROSTAOKĄTNYM- CZEŚĆ 2

Jak by tu zacząć… najlepiej to pociągnąć temat już rozpoczęty. Z praktycznego punktu widzenia, to dokończyć model świata 2D przedstawiony w temacie: Izomeria w świecie prostokątnym. Powiedzmy, że chcemy nasz świat ożywić. Zacznijmy od ruchu postaci bohatera gry, sterowanego z klawiatury. Poniżej bohater na tle murów

izometria22.jpg

Niby sprawa prosta. Algorytm wyświetlenia li tylko grafiki można opisać tak:

-wyświetl grunt
-wyświetl zamek
-wyświetl bohatera

Ogólnie tak to powinno przebiegać. Można powiedzieć: programowanie to rzecz prosta, prostsza od piractwa płyty, którą trzeba ..coś tam, coś tam lub utworzenia strony www (czego ja nie umiem i nie chcę umieć). Ale niestety tak nie jest. Bohater świata 2D ma wiele problemów natury istnienia w tymże świecie. Chociażby poniższa sekwencja obrazków wprowadzi w temat.

izometria23.jpg

Jakie to problemy? Jest ich sporo. Wymienię tylko kilka:
-bohater/duszek musi być wyświetlony na tle budowli
-bohater/duszek musi być wyświetlony poza budowlą
- bohater/duszek musi umieć żyć pełnia swojego życia w świecie 2D( chodzić, biegać, polować, zabijać itp.)
- bohater/duszek musi umieć schować się za drzewem lub za nim przejść

A to nie wszystko…a gdzie dźwięk, zdarzenia losowe, przeciwnik, sztuczna inteligencja, w miarę duży świat itp. Jedna osoba szybko gry nie napisze.

Cała treść tego artykułu bazuje na wcześniejszych pomysłach opisanych w Wędrówkach…

1. Jak pokonać podstawowe trudności życia w świecie 2D przedstawione na poprzedniej ilustracji?

Problem wyświetlania obrazu duszka na tle budowli lub za nią, ewentualnie za rośliną lub artefaktem wiąże się za poprawną kolejnością wyświetlania grafik. Jeżeli coś spapramy to będziemy mieć tak jak poniżej ( w demku można to sprawdzić- jest to efekt zamierzony). Ta.. pierwotniak chodzi po dachu świątyni.

izometria25.jpg

Dlaczego tak się stało?

Oczywiście zakładamy, że nasz bohater nie posiada takiej umiejętności. Na dachu znalazł się przypadkiem.. Jak do tego doszło? Odpowiedź jest prosta: duszek bohatera został wyświetlony później niż obraz kościoła. Jeżeli wyświetlimy go wcześniej to budynek go zakryje. Zarówno jak stanie za budynkiem lub przed budynkiem. To nie będzie dobre rozwiązanie. Jak temu zaradzić?
Już odpowiadam: na poziomie edytora światów.

Proszę zanalizować poniższy rysunek

izometria26.jpg

Duszki w pozycji : B5 i C4 wlazły na dach. Zaś duszki C3, D3, E2, F2 oraz F3 są wyświetlone prawidłowo. I znów można zadać pytanie: dlaczego tak się stało? Przecież mechanizm wyświetlania duszka jest taki sam. Odpowiedź jest jedna : musimy opanować głębie. Tak ,tak do tej pory poniżej 10 0000 metrów "zeszło" tylko dwóch ludzi- pod koniec lat pięćdziesiątych, a na orbitę wyleciało prawie czterystu. I to porównanie jest skalą problemu, który nas czeka. Nic tylko siąść i płakać, ewentualnie przesiąść się na C i też płakać… Ale wystarczy tylko zauważyć jedno- to o czym pisałem w Wędrówkach w świecie 2D - głębia może być stowarzyszona z wierszem. Im wyższy numer wiersza tym wcześniej klatka jest wyświetlana. Czyli jeżeli byśmy osadzili kościół tak, aby środek jego obrazu był w kaflu D4 i zarazem głębia kościoła byłaby pobrana z numeru wiersza tego kafla to wszystko, co byłoby na pozycji poniżej wiersza czwartego będzie wyświetlane wcześniej niż obraz kościoła, a to, co powyżej później. Najłatwiej jest to rozwiąza
ć przez wprowadzenie zakazu ruchu- duszek nie może wejść na dach kościoła.
Czyli obraz drogi powinien być tak uzupełniony, aby, na B5 i C4 nie można było postawić duszka- co na poniższym rysunku nie jest uwzględnione- można więc chodzić po dachu

izometria27.jpg

No tak, rysunki przedstawiają wynik zapisu mapy świata gry. Oczywiście organizacja tego zapisu zależy od edytora. Odczyt do silnika gry. Sam odczyt stwarza wiele możliwości rozwiązań. Ja zaproponuję moje, które nie należy traktować jako to jedyne.

2. Głębia bohatera: (to nie temat dla humanistów)


Problem należy rozpatrzyć pod kontem kolejności wyświetlania grafiki. Problem jest prosty do rozwiązania gdyby nie było możliwości chodzenia za przeszkodą ( szerzej opisałem to w Wędrówkach..) Jeżeli chcemy chodzić za drzewem lub budynkiem to musimy znać kolumnę i wiersz przebywania duszka w świecie 2D i na tej podstawie wyliczyć głębie. Można też ją odczytać, co będzie rozwiązaniem mniej czasochłonnym. Głębia jest znana dla każdego kafla warstwy- patrz kod tworzenia warstw. Jeżeli chodzi o duszka to, obsługuje to ta oto procedura

procedure TPraduch.Pozycja(const aX,aY:single;const ADW,ADH:integer);
var
k,w:integer;
begin
fkolumna:=Round(ax-RogSwiata.x+Image.TileWidth div 2) div ADW;
fWiersz :=Round(ay-RogSwiata.y+Image.TileHeight-16) div ADH;
fidKafla:=fKolumna+fWiersz*DaneMApy.XCount;
k:=Round(ax+Image.TileWidth div 2)div ADW;
w:=Round(ay+Image.TileHeight-16)div ADH;
z:=SwiatProstokatnyWarstwy[1,k,w].z+1;
end;

Jak widać określam dwa razy położenie duszka. FKolumna i Wiersz to połeżenie obowiązujące w całej mapie- świecie a k i w to poleżenie warstwach widocznych na ekranie. Może to dziwić , ale tak jest zorganizowany mój model gigantycznego świata. Odczytana wartość

z:=SwiatProstokatnyWarstwy[1,k,w].z+1;

Zwiększam o jeden a to tylko dla tego, aby można było stanąć na tle budynku lub drzewa

izometria29.jpg

Wspomniana procedura musi być ciągle wywoływana w czasie ruchu duszka czy to sterowanego z klawiatury czy też automatycznie

procedure TPraduch.Move(const MoveCount:single);
begin
DeltaSeconds:=MoveCount;
inherited Move(MoveCount);
Pozycja(x,y,DaneMApy.W1Kosc,DAneMapy.H1Kosc);
end;

Dla duszka poruszanego z klawiatury , czyli bohatera którym aktualnie gramy wystarczy nam znajomość pozycji w warstwach widocznych. Automat musi znać jedną i drugą pozycję. Na razie nie robię zabezpieczenia przed wyliczeniem k, w wykraczającym poza tablicę SwiatProstokatnyWarstwy bo omawianym przykładzie nie występuje żaden automatyczny duszek. Może będzie to w następnej części…

3. Sterowanie bohaterem i animacja ruchu

W świecie izometrycznym możemy poruszać się w kierunkach od 0 do 360 stopni. Należy zadbać o odpowiedni obrót duszka. Jako że obraz duszka wyświetlany jest w kolejnych klatkach animacji ruchu dla danego kierunku zdecydowałem się na 8 kierunków ruchu

izometria210.jpg

W załączonym kodzie skręcanie odbywa się przy pomocy klawiszy kursora strzałka w lewo lub prawo. Naprzód to strzałka w górę, do tyłu to strzałka w dół. Oprogramowanie ruchu nie jest rudne należy tylko odpowiednio przerzucać indeksy klatek do obranego kierunku ruchu

Poniżej fragment kodu z unit pierwotniak;

//wartosci odpowiadaja skrajnym indeksą klatek zachowań
tabPierwotny:array[0..33,0..1]of byte=
((0,7),//stoj {0}
(8,15),//pauza {1}
(16,23),//IDŹ {2}
(24,31),//
(32,39),//
(40,47),//
(48,55),//
(56,63),//
(64,71),//
(72,79),//
(80,87),//BIEG {10}

Jest to tablica która przechowuje indeks początkowy i końcowy klatki animacji dla danego stanu życiowej aktywności duszka. Przykładowo poniższe wartości liczbowe

(16,23),//IDŹ {2}
(24,31),//
(32,39),//

odpowiadają:
(16,23) - klatki ruchu idź na północ od numeru 16,17,18…23
(24,31) - klatki ruchu idź na północny wschód od numeru 24,25,…31
(32,39) - klatki ruchu idź na wschód od numeru 32,32,…39

I tak dalej. W tej tablicy są przechowywane indeksy biegu, mówienia itp. Może jedynie zdziwić, to że

(136,143),
(0,8),//Mów {18}
(9,17),

Dane- indeksy ponownie maleją. Otóż duszek złożony jest z dwóch plików graficznych. Ich nazwy odpowiadają nazwom z zasobów oil i są zapisane do tablicy

tabGrafikiPierwotny:array[0..1]of string=
(
('pierwotny000'),//grafa- stoj, pauza, idź, bieg
('pierwotny001') //grafa- mow,okrzyk
);


Procedura procedure tPierwotny.Akcja; obsługuje zmianę obrazów zachowań. Zawiera ona taka procedurę ZmienObraz(tabGrafikiPierwotny[1]); to tu następuje zmiana indeksu ładowanego obrazu z zasobów OmegaImageList zaś same klatki animacji zmieniam tu:

procedure tPierwotny.Zachowanie;
//ustal granice klatek zachowań
begin
case Stan of
stStop :begin TabZachowan0:=tabPierwotny[0,0] ;
TabZachowanK:=tabPierwotny[0,1];end;
stPauza :begin TabZachowan0:=tabPierwotny[1,0] ;
TabZachowanK:=tabPierwotny[1,1];end;
stIdz :begin TabZachowan0:=tabPierwotny[2+ord(Kierunek),0] ;
TabZachowanK:=tabPierwotny[2+ord(Kierunek),1];end;
stBieg :begin TabZachowan0:=tabPierwotny[10+ord(Kierunek),0];
TabZachowanK:=tabPierwotny[10+ord(Kierunek),1];end;
stMow :begin TabZachowan0:=tabPierwotny[18+ord(Kierunek),0];
TabZachowanK:=tabPierwotny[18+ord(Kierunek),1];end;
stOkrzyk:begin TabZachowan0:=tabPierwotny[26+ord(Kierunek),0];
TabZachowanK:=tabPierwotny[26+ord(Kierunek),1];end;
end;
inherited Zachowanie;//ta linia wywołuje metodę ojca
end;

a to metoda ojca

procedure TPraduch.Zachowanie;
begin
if ImageIndex>fTabZachowanK then ImageIndex:=fTabZachowan0;
if ImageIndexthen ImageIndex:=fTabZachowanK;
end;


Teraz jedynie należy w zegarze gry oprogramować reakcję duszka bohatera na wciśnięty klawisz. Są to te linie kodu

TPierwotny(PraLista.Items[idAktywnyDuszek]).Klawiszologia;
RuchWSwiecieWzgledemBohatera(TPierwotny(PraLista.Items[idAktywnyDuszek]). skokX,TPierwotny(PraLista.Items[idAktywnyDuszek]).skokY);


Gdyby to był automat należałoby wykorzystać procedury

OmegaSprite1.Collision;
OmegaSprite1.Dead;
OmegaSprite1.Move(OmegaTimer1.DeltaSecs);

Dokładnie na tych samych zasadach co opisałem w ruchu borostwora w Wędrówkach…

Klawiszologia zachowań omawianego duszka:
- klawisze strzałek- idź
- Lewy Shift + strzałka w górę - bieg
- klawisz M (wciśnięty)- mów
- klawisz O (wciśnięty)- okrzyk


4. Kolizja ruchu

Polega na stwierdzeniu czy można w danej klatce postawić duszka. W tym przykładzie stwierdzenie wystąpienia 1 (jedynki) lub końca świata oznacza zakaz ruchu

if (PMapa(Lista.Items[1])^[idKafla].RGBA.zakazWstepu=1)
or
KoniecSwiata(aX,aY) then

Całość kodu znajduje się w function tPierwotny.Kolizja(aX,aY:single):boolean; należy jedynie ta funkcje uruchamiać w momencie wciskania klawiszy ruchu i stwierdzić czy można postawić duszka w nowej pozycji. Jak nie to wyskakujemy z akcji ruchu


procedure tPierwotny.Akcja;
begin
//bieg
if(oisUp in fOmegaInput.keyboard.States) and (oisButton1{Lewy Shift} in fOmegaInput.keyboard.States)
then begin
skokX:=dv*1.5*tabWersor[ord(Kierunek),0];
skokY:=dv*1.125*tabWersor[ord(Kierunek),1];
if Kolizja(X+skokX,Y+skokY) then exit;
dXAnimacji:=dXAnimacji+deltaSeconds;
if dXAnimacji>deltaSeconds*3.5 then begin
ImageIndex:=ImageIndex+1;dXAnimacji:=0;
Stan:=stBieg;
Zachowanie;
end;
exit;
end;
//idz na przod



I to by było na tyle w tej części

Do prawidłowego działania przykładu wymagane są te pliki

swiat_512x384.mue2D
teren_rosliny.oil
swiatynie.oil
zamki.oil
pierwotny001.oil
D3DX81AB.DLL
MPPSDK.DLL

 
Układ okresowy- kod qr
Układ okresowy

Układ okresowy pierwiastków- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Alkomat- wirtualny test kod qr
Alkomat- wirtualny test

Alkomat- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Znaki drogowe- kod qr
Znaki drogowe

Znaki drogowe, test ABCD- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Poziomica kod qr
Poziomica i klinometr

Poziomica, klinometr- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Światłomierz fotograficzny kod qr
Światłomierz fotograficzny

Światłomierz fotograficzny- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Taklarz- olinowanie stałe kod qr
Olinowanie stałe- kalkulator średnic

Olinowanie stałe- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
przepis na gogfry

Przepis na gofry

zobacz
przepis na bitą śmietanę

Przepis na bitą śmietanę

zobacz