fizyka wzory prawa zadania teoria, chemia teoria zadania wzory, modelarstwo szkutnicze

 
omega

Pobierz kod POCHODNIA

 
Jak zrobić pochodnię lub efekt ognia w grze 2D?


 
Powiedzmy , że chcielibyśmy zrobić coś takiego:
tworzenie gier: robimy pochodnię w grze 2D 1

 
Jak się zastanowić to okazuje się, że nie jest to takie trudne.

Co będzie nam potrzebne?

a)obraz tła, które przyciemnimy w kodzi eprogramu aby udawało noc

tworzenie gier: robimy pochodnię w grze 2D 2

b)obraz ognia i drzewca pochodni

tworzenie gier: robimy pochodnię w grze 2D 3

tworzenie gier: robimy pochodnię w grze 2D 4

c) obraz promienia światła- może to trochę dziwić, ale da się taki pomysł wykorzystać

tworzenie gier: robimy pochodnię w grze 2D 5

Bardzo ważne aby tło promienia światła i tło ognia było czarne. Pytanie dlaczego? A to tylko dlatego, że wykorzystamy operacje AND nakładania bitów tła świata, obrazu promienia światła i obrazu płomieni.(poniżej odpowiednia instrukcja)

Image.Draw(Round(x),Round(y),0,0.5,0.5,1,1,OmegaColor(200,200,100,255),Round(AnimPos),bmSrcAdd);

Ale po kolei...

1 Tworzymy klasę pochodni.

Przyjmiemy, że pochodnia to drzewce na którym pali się ogień, a ogień rzuca promienie światła. Jak by nie było, tak to wygląda w rzeczywistości. Jako, że pochodnię można przenosić to również zasymulujemy jej ruch wzdłuż osi X. Klasa pochodni może wyglądać jak poniżej:


 



//*****POCHODNIA*******************
TPochodnia=class(TSprite)
private
//poniższe dane można odczytać w dowolnym edytorze grafiki np. MSPaint
czubek:array[0..1]of TPoint;// będą współrzędne ognia
swiatlo,
plomien:TPlomien;
protected
dVx,
dVy:single;// zmienne przyrostu położenia
constructor Create(const AParent: TOmegaSprite;
const ImageListItem: TImageListItem;
const ImageListItemPlomien: TImageListItem;
const ImageListItemSwiatlo: TImageListItem
);virtual;
procedure Move(const MoveCount: Single); override;
destructor Destroy;
end;
//*********************************

 

Proszę zauważyć , że do ciała klasy TPochodnia podpiąłem dwie zmienne żyjące na innej klasie:
swiatlo i plomien:TPlomien;

Snop światło i płomień zachowują się w pewnym sensie tak samo- snop światła zależny jest od płomienia...Więc dlaczego by nie zrobić jednej klasy na oba obiekty? Klasa ta ma postać


 


TPlomien=class(TSimpleAnimSprite)
private
procedure Draw;override;
protected
constructor Create(const AParent: TOmegaSprite;
const ImageListItem: TImageListItem
);virtual;

end;

 


Efekt półprzezroczystego płomienia jak i efekt strumienia światła uzyskamy jeśli podmienimy standardową funkcję rysującą Draw klasy bazowej TsimpleAnimSprite. Napiszemy ją jak poniżej


 


procedure TPlomien.Draw;
begin
inherited Draw;//<-- jak to się włączy to można zobaczyć różnicę- z czego się zrezygnowało
//światło
Image.Draw(Round(x),Round(y),0,0.5,0.5,1,1,OmegaColor(200,200,100,255),Round(AnimPos),bmSrcAdd);
end;

 


Funkcja nie jest trudna do zrozumienia, jedynie może zastanowić fakt, ze użyłem Round(AnimPos) dla strumienia światła. Przecież nie ma tu animacji klatek. Zrobiłem to tylko dla tego, że oba obiekty są do siebie podobne. Dla płomienia klatki się zmieniają a dla strumienia nie, AnimPos wynosi 0. Oczywiście można zrobić strumień na klasie bazowej TSprite- i to by było najwłaściwsze rozwiązanie. W tej chwili można powiedzieć, że uzyskaliśmy fajny efekt ognia i światła jaki on daje...i to przy pomocy jednej linijki kodu. DELPHI może rzucić na kolana; wiele razy mi to robi :

Co dalej?
Należy teraz zająć się drzewcem pochodni. Utworzymy je przy pomocy tego konstruktora


 


constructor Create(const AParent: TOmegaSprite;
const ImageListItem: TImageListItem;// przechowa obraz klatek drzewca
const ImageListItemPlomien: TImageListItem;// przechowa obraz klatek plomieni
const ImageListItemSwiatlo: TimageListItem// przechowa obraz światła
);virtual;

 


Postać ciała konstruktora wygląda jak poniżej:



 


constructor TPochodnia.Create(const AParent: TOmegaSprite;
const ImageListItem: TImageListItem;
const ImageListItemPlomien: TImageListItem;
const ImageListItemSwiatlo: TImageListItem);
begin
//rób drzewce pochodni
inherited Create(AParent);
Image := ImageListItem;
ImageIndex:=0;
width:=Image.TileWidth;
height:=Image.TileHeight;
x:=200;
y:=250;
z:=1;
//przyjmij wartość przesunięcia ruchu w osi X
dVx:=40;
//gdy nachylony w prawo
czubek[0].x:=22;
czubek[0].y:=12;
//gdy nachylony w lewo
czubek[1].x :=12;
czubek[1].y :=10;
//rób światło
Swiatlo:=TPlomien.Create(AParent,ImageListItemSwiatlo);
Swiatlo.z:=z+1;
//rób płomień pochodni
Plomien:=TPlomien.Create(AParent,ImageListItemPlomien);
Plomien.z:=z+1;
end;

 


Konstruktor pochodni wywołamy jak poniżej (pamiętając aby w sekcji var
projektu formatki zdefiniować zmienną: Pochodnia:TPochodnia;)


 

procedure TForm1.OmegaScreen1Init(Sender: TObject);
begin
//twórz pochodnie,
// W liście obrazów pod indeksem 1 jest drzewce pochodni, pod indeksem 2 jest płomień,
// pod indeksem 3 jest obraz światła
Pochodnia:=TPochodnia.Create(OmegaSprite1,OmegaImageList1.ImageList.Items[1],
OmegaImageList1.ImageList.Items[2],OmegaImageList1.ImageList.Items[3]);
OmegaTimer1.Enabled:=true;
end;

 

Jak widać za jednym pociągnięciem utworzyły się trzy obiekty: drzewce, ogień i światło.
Na tej zasadzie można tak utworzyć kilka pochodni stosując wywołanie tej procedury w pętli.

Muszę jeszcze wspomnieć o tym aby zadbać aby te trzy obiekty się nie rozjeżdżały,
na przykład bohater naszej gry wziął do ręki pochodnię z nią wędruje.
Pilnujemy tego ruchu w tej procedurze:



 


procedure TPochodnia.Move(const MoveCount: Single);
begin
inherited Move(MoveCount);
//uaktualnij położenie drzewca
X:= X+MoveCount*dVx;
if x<0 thenbegin
x:=0; //wyrównaj do lewej krawędzi ekranu
dVx:=40; //zrób na przesuwanie w prawo
ImageIndex:=0;//zmień klatkę drzewca- nachylona w prawo
end;
if x>800 thenbegin
x:=800; //wyrównaj do prawej krawędzi ekranu
dVx:=-40;//zrob na przesuwanie w prawo
ImageIndex:=1;//zmien klatkę drzewca- nachylona w lewo
end;
//uaktualnij położenie płomienia
Plomien.x:=x+czubek[ImageIndex].x-Plomien.width div 2;
Plomien.y:=y+czubek[ImageIndex].y-Plomien.Height;
//a teraz swiatla
Swiatlo.x:=Plomien.x-Swiatlo.width div 2;
Swiatlo.y:=Plomien.y;
end;

 

W tym fragmencie kodu wyjaśni się pewien chwyt jaki zastosowałem. Otóż mogło
budzić zastanowienie dlaczego wprowadziłem taką zmienną :
czubek:array[0..1]of Tpoint?
i to w dodatku jako tablica. Sprawa jest prosta zmienna ta przechowuje współrzędne zaczepienia
płomienia w zależności od nachylenia drzewca. Dodatkowo przełączanie indeksu w tej
tablicy nie załatwiam jakimś tam specjalnym indeksem ale wykorzystuje indeks zmiany klatki
obrazu. Co widać poniżej


 
Plomien.x:=x+czubek[ImageIndex].x-Plomien.width div 2;
Plomien.y:=y+czubek[ImageIndex].y-Plomien.Height;

 

Efekt nocy uzyskamy w najprostszy sposób


 

//udawaj noc
OmegaImageList1.ImageList.Items[0].Draw(75,200,0,0,0,1,1,OmegaColor(50,75,70,255),0);

 

W rzeczywistej planszy świata gry należy obsłużyć taką zmianę koloru dla
każdego (lub wybranych) pola ewentualni całego ekranu.
Pozostałych procedur nie będę tłumaczyć, są one w miarę proste wystarczy przeglądnąć
kod programu. Mam nadzieję, że tym artykułem przybliżyłem zalety komponentu OMEGI
no i oczywiście kompilatora DELPHI

Koniec

Alkomat- wirtualny test

Alkomat- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
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