Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

Pisanie gry 2D za pomocą silnika Irrlicht


Rekomendowane odpowiedzi

Opublikowano

Witam ,postanowiłem napisać poradnik jak stworzyć grę w AutoIT za pomocą UDF do

obsługi Irrlicht. Narazie będzie to poradnik do gry 2D(może pokusimy się o 3D kiedyś)

w której omówimy takie zagadnienia jak:

 

-stworzenie okna gry w silniku Irrlicht

-rysowanie bitmap(obrazków)

-transparentność bitmap

-poruszanie postacią

-kolizje

-prosty system podążania moba za postacią

 

Z czego trzy ostatnie przydadzą się Wam do każdej kolejnej gry :)

Jak widać będzie to rozłożony Xanthous...badziewie że głowa mała ale każdy od czegoś

zaczyna a to już może posłużyć Wam za dobry materiał do nauki pisania gier ;)

 

Koniec wstępu czas zacząć:

Tu możecie pobrać wszystko co będzie Wam potrzebne:

http://code.google.com/p/au3irrlicht2/downloads/detail?name=au3Irrlicht2.0.4.zip

 

I Stworzenie okna gry w silniku Irrlicht

 

 

Najpierw deklarujemy include Irrlicht:

#include "au3Irrlicht2.au3"

Kolejnym krokiem jest nadanie szerokości i wysokości okna ,oraz zainicjowanie

silnika. Potem możemy nadać tytuł dla powstałego okna:

$screen_width = 800 ;szerokosc okna
$screen_height = 650 ;wysokosc okna
_IrrStart($IRR_EDT_DIRECT3D9,$screen_width,$screen_height) ;zainicjowanie silnika Irrlicht
_IrrSetWindowCaption( "Jakistytul" ) ;tytul dla okna

 

Jeżeli teraz uruchomimy skrypt mignie nam nasze okno i tyle zobaczymy, aby utrzymać

je przy życiu zastosujemy zwykłą pętlę While:

WHILE _IrrRunning()
WEnd

 

Teraz mamy na głowie brak wypełnienia na którym moglibyśmy rysować. Z pomocą przyjdą

funkcje:

_IrrBeginScene( 0,0,0) - argumenty to natezenie kolorow podstawowych

_Irrendscene() - zakonczenie rysowania sceny

 

Z tego wynika,że pomiędzy tymi funkcjami musi być zawarte wyrysowywanie obrazków :)

Ale to już w kolejnym punkcie , podstawy mamy :)

 

 

 

II, III Rysowanie bitmap(obrazków) i transparentność

 

 

Przed pętlą główną deklarujemy pod postacią zmiennych wczytanie do pamięci programu

tekstur czyli naszej postaci(jako postac.bmp) i naszego moba(jako mob.bmp) który

przyda się później. Zróbcie w paincie 50x50px jakies obrazki i zapiszcie.

Funkcja do zapisania w pamięci programu tekstury:

$jakaszmienna=_IrrGetTexture("sciezka do pliku")

np:

$postac=_IrrGetTexture("postac.bmp");tym sie posluzymy w dalszej czesci

 

Transparentność: inaczejprzezroczystość. Załadowany obrazek w oknie będzie wyglądał

jak jakiś obiekt na tle kolorowej tarczy...więc ustawmy dla koloru tła naszej postaci

przeźroczystość dzięki czemu nie będzie on brany pod uwagę podczas wyrysowywania.

_IrrColorKeyTexture($postac, 255,255,255 )

W ten sposób ustawiliśmy,że

nie będzie brany pod uwagę kolor biały w pliku tekstury $postac. Nastepnie podczas

rysowania wystarczy uzyc argumentu o wlaczeniu kanału alfa(przezroczystości). To

nizej:

 

Wyrysowanie postaci polega na podaniu jej tekstury,wspolrzednych, rozmiarow itp:

_IrrDraw2DImageElement( tekstura, x ,y, 0(?),0(?),szerokosc,wysokosc, kanal
alfa)

Przykład:

_IrrDraw2DImageElement( $postac, 100 ,250, 0,0,50,50, $IRR_use_ALPHA )

W przykładzie zostanie wyrysowana tekstura $postac w pozycji x=100 ,y=250 , o

szerokosci 50 i wysokosci 50 uzywajac kanalu przezroczystosci.

Funkcję tą jak wyżej wspomniałem umieszczamy w pętli między stworzeniem a

zakończeniem rysowania sceny.

 

 

IV Poruszanie postacią

 

Co znaczy poruszać postacią? Logicznie rzecz biorąc jest to zmienianie współrzędnych

obrazka...więc zaczniemy operować na dwóch zmiennych:

$x=100 ; pozycja x postaci
$y=100 ; pozycja y postaci

Teraz zmienimy nieco sposób wyrysowania postaci:

_IrrDraw2DImageElement( $postac, $x ,$y, 0,0,50,50, $IRR_use_ALPHA )

Jak widać zmieniliśmy tu tylko tyle ,że za konkretne liczby wstawilismy zmienne odpowiadające pozycji obrazka. Dzięki temu wystarczy napisać jedną funkcję z _IsPressed którą umieścimy w pętli głównej po zakończeniu rysowania aby zacząć sterować postacią :) Ta funkcja sterowania wygląda następująco:

func sterowanie()
if _IsPressed("27")=1 Then $x+=5 ;jesli zostanie nacisniety klawisz strzalki w prawo wtedy wartość $x zwiekszy sie o 5.
if _IsPressed("25")=1 Then $x-=5
if _IsPressed("28")=1 Then $y+=5
if _IsPressed("26")=1 Then $y-=5
EndFunc

Mysle ze komentarz jest zbędny, ponieważ jest to całkowita podstawa ;)

Jeśli nadal niezrozumiałe to pisz w temacie, PW, lub help pod F1 wyjaśni lepiej :)

 

 

 

Dotychczas uzyskany kod(jesli bedzie w folderze postac.bmp i UDF Irrlicht to zadziała :) :

 

 


#include "au3Irrlicht2.au3"
#include "misc.au3"
$screen_width = 800 ;szerokosc okna
$screen_height = 650 ;wysokosc okna
_IrrStart() ;zainicjowanie silnika Irrlicht
_IrrSetWindowCaption( "Jakistytul" ) ;tytul dla okna

$postac=_IrrGetTexture("postac.bmp");
_IrrColorKeyTexture($postac, 255,255,255 )

$x=100 ;pozycja x postaci
$y=100 ;pozycja y postaci


WHILE _IrrRunning()
_IrrBeginScene( 0,0,0) ;rozpoczecie rysowania sceny ,nadanie tła
_IrrDraw2DImageElement( $postac, $x ,$y, 0,0,50,50, $IRR_use_ALPHA )
_Irrendscene() ;koniec rysowania sceny
sterowanie()
Sleep(20)
WEnd

func sterowanie()
if _IsPressed("27")=1 Then $x+=5 ;jesli zostanie nacisniety klawisz strzalki w prawo wtedy wartość $x zwiekszy sie o 5.
if _IsPressed("25")=1 Then $x-=5
if _IsPressed("28")=1 Then $y+=5
if _IsPressed("26")=1 Then $y-=5
EndFunc

 

 

V Kolizje

 

 

 

Tak to największy problem wszystkich początkujących , sam nie dałem kiedyś rady i prosiłem Hfaue zawsze o pomoc - cierpliwy w sumie ... :)

Mamy do wyboru trzy kolizje:

-Kafelkową, gdzie postać porusza się po tablicy zmiennych (co kratka) i przy każdym następnym ruchu sprawdza jaka jest wartość w kafelku do którego zamierzamy się przemieścić.Np: jesli 0 to moze wejsc jesli 1 tzn. ze jest tam jakis obiekt.

Plusy: świetny logiczny pomysł, zajmuje bardzo mało objętości w kodzie i nie jest skomplikowany jeśli zna się tablice zmiennych. Minusem jest brak możliwości wdrożenia lepszej grafiki jeśli chodzi o AutoITowanie.

 

-Strefową , gdzie postać porusza się o dowolność ilość pikseli sprawdzając cały czas czy nie znajduje się w polu kolizji z innym przedmiotem. Plusy: można robić grafikę na wysokim poziomie. Minusy: duża ilość kodu, ogólny bajzel i nieporęczność, właśnie dlatego opiszę tylko ten sposób ;)

 

-Pikselową:

Niedawno na forum jakiś ktoś zrobił grę ,gdzie kolizje były sprawdzane przez różnice w kolorze mapy i postaci na niej stojącej

 

Przejdźmy zatem do obiecanej kolizji strefowej, od razu kod funkcji napisanej pod nią i wyjaśnienie:

 

 

func kolizja($bohater_x,$bohater_y,$szer_bohater,$wys_bohater,$przeszkoda_x,$przeszkoda_y,$szer_przeszkoda,$wys_przeszkoda,$id=0)

if ($bohater_x + $szer_bohater > $przeszkoda_x) And ($bohater_y + $wys_bohater > $przeszkoda_y) And ($bohater_x < $przeszkoda_x + $szer_przeszkoda) And ($bohater_y < $przeszkoda_y + $wys_przeszkoda) Then

if $id=0 then

if $bohater_x>$przeszkoda_x then $x+=5
if $bohater_x<$przeszkoda_x then $x-=5
if $bohater_y>$przeszkoda_y then $y+=5
if $bohater_y<$przeszkoda_y then $y-=5

EndIf
endif

endfunc

 

 

 

Jeżeli postać znajdzie się w polu obiektu wtedy sprawdzi kolejne warunki zależne od id dla kolizji. Dlaczego mowa o jakimś dziwnym id? A no dlatego właśnie by milej było pisać różne interakcje czyli np. bonusy, dodatkowe punkty, zbieranie przedmiotów, przechodzenie na inną mapę itp. bo kolizja to nie samo "nie wchodzenie" na przedmiot. U nas id=0 będzie równe temu ostatniemu i postać jeżeli znajdzie się w polu zostanie z niego "wypchnięta" lub jeśli będzie próbowała wejść będzie stawiała silny opór.Świadczą o tym cztery warunki po "if $id=0 then".

 

Teraz najgorsza sprawa: jak to zastosować? A tu właśnie problemik jest taki ,że musimy każdy obiekt z oddzielna wklepywać w pętle główną. Możemy stworzyć system zapisu mapy i będzie problem z głowy co byśmy nie musieli wklepywać każdego obiektu do pętli głównej. Przykład zastosowania:

Tworzymy w paincie obiekt o szerokosci 100 i wysokosci 80. Umieszczamy obrazek na pozycji 200,200 i dodajemy kolizję, oto kod całego programu który to wykorzysta:

 

 

 

#include "au3Irrlicht2.au3"
#include "misc.au3"
$screen_width = 800 ;szerokosc okna
$screen_height = 650 ;wysokosc okna
_IrrStart() ;zainicjowanie silnika Irrlicht
_IrrSetWindowCaption( "Jakistytul" ) ;tytul dla okna

$postac=_IrrGetTexture("postac.bmp");
$przeszkoda=_IrrGetTexture("przeszkoda.bmp");
_IrrColorKeyTexture($postac, 255,255,255 )

$x=100 ;pozycja x postaci
$y=100 ;pozycja y postaci


WHILE _IrrRunning()
_IrrBeginScene( 0,0,0) ;rozpoczecie rysowania sceny ,nadanie tła
_IrrDraw2DImageElement( $postac, $x ,$y, 0,0,50,50, $IRR_use_ALPHA ) ;to nasza postac
_IrrDraw2DImageElement( $przeszkoda, 200 ,200, 0,0,100,80, $IRR_IGNORE_ALPHA ) ; to nasz przedmiot z którym kolidujemy
_Irrendscene() ;koniec rysowania sceny


kolizja($x,$y,50,50,200,200,100,80,0)


sterowanie()
Sleep(1)
WEnd

func sterowanie()
if _IsPressed("27")=1 Then $x+=5 ;jesli zostanie nacisniety klawisz strzalki w prawo wtedy wartość $x zwiekszy sie o 5.
if _IsPressed("25")=1 Then $x-=5
if _IsPressed("28")=1 Then $y+=5
if _IsPressed("26")=1 Then $y-=5
EndFunc


func kolizja($bohater_x,$bohater_y,$szer_bohater,$wys_bohater,$przeszkoda_x,$przeszkoda_y,$szer_przeszkoda,$wys_przeszkoda,$id=0)

if ($bohater_x + $szer_bohater > $przeszkoda_x) And ($bohater_y + $wys_bohater > $przeszkoda_y) And ($bohater_x < $przeszkoda_x + $szer_przeszkoda) And ($bohater_y < $przeszkoda_y + $wys_przeszkoda) Then

if $id=0 then

if $bohater_x>$przeszkoda_x then $x+=5
if $bohater_x<$przeszkoda_x then $x-=5
if $bohater_y>$przeszkoda_y then $y+=5
if $bohater_y<$przeszkoda_y then $y-=5

EndIf
endif

endfunc

 

 

 

 

 

VI Proste AI - podążanie moba za postacią

 

 

Jak już się można domyślić będzie to zwykłe użycie instrukcji warunkowych w pętli głównej programu.

Jeżeli mob będzie bliżej krawędzi lewej ekranu niż bohater wtedy jego wartość x bedzie sie zwiekszala... i tak z trzema pozostałymi kierunkami.

 

Najpierw stworzymy zatem zmienne okreslajace jego pozycje, teksture, przezroczystosc i go wyswietlimy. Potem po wyswietlaniu w petli glownej znajdzie się odniesienie do funkcji której działanie wyżej opisałem. Zatem umieszczamy te dane w kodzie(przyjmijmy ze tekstura to mob.bmp o wymiarach 50x50 z białym tłem):

$xmob=100
$ymob=100
$mob=_irrgettexture("mob.bmp")
_IrrColorKeyTexture($mob, 255,255,255 )

;do petli glownej:
_IrrDraw2DImageElement( $mob, $xmob ,$ymob, 0,0,50,50, $IRR_use_ALPHA )
AImob1()

;funkcja AImob1 przykładowo(można zrobić coś bardziej ambitnego, np. jesli postac jest o 100 pikseli dalej to mob jej "nie widzi"):

func AImob1()

if $xmob<$x then $xmob+=1
if $ymob<$y then $ymob+=1
if $ymob>$y then $ymob-=1
if $xmob>$x then $xmob-=1

endfunc

 

Więc to koniec...

 

Tutaj cały kod tego co napisaliśmy(jak widać niezbyt długi):

 

 

#include "au3Irrlicht2.au3"
#include "misc.au3"
$screen_width = 800 ;szerokosc okna
$screen_height = 650 ;wysokosc okna
_IrrStart() ;zainicjowanie silnika Irrlicht
_IrrSetWindowCaption( "Jakistytul" ) ;tytul dla okna

$postac=_IrrGetTexture("postac.bmp");
$przeszkoda=_IrrGetTexture("przeszkoda.bmp");
$mob=_irrgettexture("mob.bmp")

_IrrColorKeyTexture($postac, 255,255,255 )
_IrrColorKeyTexture($mob, 255,255,255 )

$x=100 ;pozycja x postaci
$y=100 ;pozycja y postaci
$xmob=400
$ymob=400




WHILE _IrrRunning()
_IrrBeginScene( 0,0,0) ;rozpoczecie rysowania sceny ,nadanie tła
_IrrDraw2DImageElement( $postac, $x ,$y, 0,0,50,50, $IRR_use_ALPHA ) ;to nasza postac
_IrrDraw2DImageElement( $przeszkoda, 200 ,200, 0,0,100,80, $IRR_IGNORE_ALPHA ) ; to nasz przedmiot z którym kolidujemy
_IrrDraw2DImageElement( $mob, $xmob ,$ymob, 0,0,50,50, $IRR_use_ALPHA )

_Irrendscene() ;koniec rysowania sceny

AImob1()
kolizja($x,$y,50,50,200,200,100,80,0)

sterowanie()
Sleep(1)
WEnd

func sterowanie()
if _IsPressed("27")=1 Then $x+=5 ;jesli zostanie nacisniety klawisz strzalki w prawo wtedy wartość $x zwiekszy sie o 5.
if _IsPressed("25")=1 Then $x-=5
if _IsPressed("28")=1 Then $y+=5
if _IsPressed("26")=1 Then $y-=5
EndFunc


func kolizja($bohater_x,$bohater_y,$szer_bohater,$wys_bohater,$przeszkoda_x,$przeszkoda_y,$szer_przeszkoda,$wys_przeszkoda,$id=0)

if ($bohater_x + $szer_bohater > $przeszkoda_x) And ($bohater_y + $wys_bohater > $przeszkoda_y) And ($bohater_x < $przeszkoda_x + $szer_przeszkoda) And ($bohater_y < $przeszkoda_y + $wys_przeszkoda) Then

if $id=0 then

if $bohater_x>$przeszkoda_x then $x+=5
if $bohater_x<$przeszkoda_x then $x-=5
if $bohater_y>$przeszkoda_y then $y+=5
if $bohater_y<$przeszkoda_y then $y-=5

EndIf
endif

endfunc



func AImob1()

if $xmob<$x then $xmob+=1
if $ymob<$y then $ymob+=1
if $ymob>$y then $ymob-=1
if $xmob>$x then $xmob-=1

endfunc

 

 

 

Oraz download z Irrlichtem, plikiem *.au3 oraz bitmapami:

 

http://speedy.sh/zqvjZ/poradnikirr2d.rar

Skan:

https://www.virustotal.com/file/0f20d9c8cf8d6b46a7ebcd728a76b8f52ac5f7b190d530c74b644aac9437d70a/analysis/1332957334/

 

 

 

 

VII Algorytm odnajdywania drogi

 

 

 

Na wstępie zaznaczam: kod tego algorytmu nie jest mój, w pełni wykonał go Hfaua i to jemu za niego dziękujcie i całujcie sygnet :D

Czym jest ten algorytm nie muszę chyba tłumaczyć ale dla nie wiedzących powiem,że polega on na wyszukaniu drogi z punktu A do punktu B z wykorzystaniem kolizji (tzn. ,że nie przejdzie przez ścianę po prostej linni tylko będzie szukał obejścia jej ).

Przejdźmy do kodu:

 

#include <File.au3>
#include <Array.au3>

;rozmiar mapy
Const $MAP_H = 20;
Const $MAP_W = 20;
Const $Box_size[2] = [200 / $MAP_W, 200 / $MAP_H]

;mapa
Global $map[$MAP_W][$MAP_H];
load_map();ladowanie mapy

;bohater
Global $hero[2];
random_point($hero)

;pozycja startowa
Global $start[2] = [$hero[0], $hero[1]];

;pozycja docelowa
Global $end[2];
random_point($end);losowa wartosc, ale tak, zeby byla dostepna na mapie

;droga z punktu start do punktu end
Global $way[$MAP_H * $MAP_W][2];
Global $way_lenght = 0;

;obliczamy najkrótszą drogę i czas potrzebny na jej przebycie
$cz = TimerInit();
find_way();
$time = Round(TimerDiff($cz), 3);
MsgBox(0, "FindWay", "Czas potrzebny na znalezienie drogi = " & $time & "ms");

;zapisujemy wynik do pliku
$file = FileOpen("wyniki.txt", 9);
FileWrite($file, $time & @CRLF);

;zczytanie wyników i obliczenie sredniego czasu
#include <File.au3>
Global $wyniki[_FileCountLines("wyniki.txt")];
_FileReadToArray("wyniki.txt", $wyniki);
$suma = 0;
For $i = 0 To UBound($wyniki) - 1
$suma += $wyniki[$i];
Next
$srednia = round($suma / UBound($wyniki), 3);
MsgBox(64, "FindWay", "Średni czas dla " & UBound($wyniki) & " wyników na mapie " & $MAP_W & "x" & $MAP_H & " to - " & $srednia);

;wypisanie drogi w konsoli
For $i = 0 To $way_lenght - 1
ConsoleWrite($way[$i][0] & ", " & $way[$i][1] & @CRLF)
Next

$hGUI = GUICreate("Find Way", 200, 200);
$lStart = GUICtrlCreateLabel("", $start[0] * $Box_size[0], $start[1] * $Box_size[1], $Box_size[0], $Box_size[1]);
GUICtrlSetBkColor(-1, 0xFF0000);
$lEnd = GUICtrlCreateLabel("", $end[0] * $Box_size[0], $end[1] * $Box_size[1], $Box_size[0], $Box_size[1]);
GUICtrlSetBkColor(-1, 0x00FF00);
$lHero = GUICtrlCreateLabel("", $hero[0] * $Box_size[0], $hero[1] * $Box_size[1], $Box_size[0], $Box_size[1]);
GUICtrlSetBkColor(-1, 0x0000FF);
;tworzymy sciany
For $y = 0 To $MAP_H - 1
For $x = 0 To $MAP_W - 1
If ($map[$x][$y] = 0) Then
GUICtrlCreateLabel("", $x * $Box_size[0], $y * $Box_size[1], $Box_size[0], $Box_size[1]);
GUICtrlSetBkColor(-1, 0x000000);
EndIf
Next
Next
GUISetState();

;wiadomosc o drodze
MsgBox(64, "Find Way", "Bohater (czerwony) przemieszcza się z punktu czerwonego (" & $start[0] & ", " & $start[1] & ") do punktu zielonego (" & $end[0] & ", " & $end[1] & ")")

;przejscie drogi
$way_index = 0
While $hero[0] <> $end[0] Or $hero[1] <> $end[1]
Sleep(333);
$hero[0] = $way[$way_index][0];
$hero[1] = $way[$way_index][1];
$way_index += 1;
GUICtrlSetPos($lHero, $hero[0] * $Box_size[0], $hero[1] * $Box_size[1]);
WEnd
Sleep(1000);

Func load_map()
$file = FileOpen("map.txt", 0);

For $y = 0 To $MAP_H - 1
For $x = 0 To $MAP_W - 1
$map[$x][$y] = FileRead($file, 1);
Next
Next

FileClose($file);
EndFunc ;==>load_map

Func random_point(ByRef $p)
Do
$p[0] = Random(0, $MAP_W - 1, 1);
$p[1] = Random(0, $MAP_H - 1, 1);
Until $map[$p[0]][$p[1]] = 1
EndFunc ;==>random_point

Func find_way()
;najpierw torzymy sobie mapę pomocniczą
Local $t[$MAP_W][$MAP_H];

;wypełnienie mapy wartosciami pustego pola (-1)
Const $UNSEEN_FIELD = -1;
For $y = 0 To $MAP_H - 1
For $x = 0 To $MAP_W - 1
$t[$x][$y] = $UNSEEN_FIELD;
Next
Next

;stworzenie kolejki
Local $q[$MAP_W * $MAP_H][2];maksymalny mozliwy rozmiar[0]->X [1]->Y
$p = 0;aktualnie sprawdzany punkt w kolejce
$new = 0;index nowo dodawanego punktu

;rozpatrywane strony (mozliwosc poruszania sie tylko dół, prawo, lewo, góra)
Local $dir[4][2] = [[0, 1],[1, 0],[-1, 0],[0, -1]];dół prawo, lewo góra

;punkt aktualnie rozpatrywany
Local $v[2];
;punkt pomocniczy
Local $w[2];

;dodanie punktu startowego do kolejki
$q[$new][0] = $start[0];
$q[$new][1] = $start[1];
$new += 1;

;przypisanie wartosci 0 pierwszemu polu
$t[$start[0]][$start[1]] = 0

;wypelnianie mapy
While $p < $new

;przypisanie nowego punktu do rozpatrywania
$v[0] = $q[$p][0];
$v[1] = $q[$p][1];
$p += 1;

;sprawdzanie punktow okrazajacych go
For $i = 0 To 3
;nowy punkt (sprawdzamy czy moze byc dodany do kolejki)
$w[0] = $v[0] + $dir[$i][0];
$w[1] = $v[1] + $dir[$i][1];

;jesli wykracza poza mape to rozpatrujemy kolejny punkt
If Not isOnMap($w) Then ContinueLoop;

;jesli jeszcze nie odwiedzilismy tego pola i jest ono dostepne do chodzenia
If ($t[$w[0]][$w[1]] = -1 And $map[$w[0]][$w[1]] = 1) Then

;wartosc kolejnego pola jest rowne wartosc pola poprzedniego + 1
$t[$w[0]][$w[1]] = $t[$v[0]][$v[1]] + 1;

;dodajemy punkt do kolejki
$q[$new][0] = $w[0];
$q[$new][1] = $w[1];
$new += 1;
EndIf

If ($w[0] = $end[0] And $w[1] = $end[1]) Then
ExitLoop 2;wychodzimy z pętli i idziemy tworzyć sciezke
EndIf
Next
WEnd

;tworzymy sciezke
While $w[0] <> $start[0] Or $w[1] <> $start[1]
;tworzymy kolejny element drogi
$way[$way_lenght][0] = $w[0];
$way[$way_lenght][1] = $w[1];
$way_lenght += 1;

;sprawdzamy punkty dookoła
For $i = 0 To 3
;nowe punkty pomocnicze
$v[0] = $w[0] + $dir[$i][0];
$v[1] = $w[1] + $dir[$i][1];

;jesli wykracza poza mape to sprawdzamy kolejny punkt
If Not isOnMap($v) Then ContinueLoop

;jesli jest o jeden wieksze niz wartosc punktu obok
If ($t[$v[0]][$v[1]] = $t[$w[0]][$w[1]] - 1) Then
;rozpatrujemy ten punkt
$w[0] = $v[0];
$w[1] = $v[1];

ExitLoop;wychodzimy z pętli
EndIf
Next
WEnd

;odwracamy tablicę
$j = $way_lenght - 1;
Local $tmp[2];
For $i = 0 To ($way_lenght - 1) / 2
$tmp[0] = $way[$i][0];
$tmp[1] = $way[$i][1];
$way[$i][0] = $way[$j][0];
$way[$i][1] = $way[$j][1];
$way[$j][0] = $tmp[0];
$way[$j][1] = $tmp[1];
$j-=1;
Next
EndFunc ;==>find_way

Func isOnMap($w)
If $w[0] >= 0 And $w[0] < $MAP_W Then
If $w[1] >= 0 And $w[1] < $MAP_H Then
Return True;
EndIf
EndIf

Return False;
EndFunc ;==>isOnMap[/spoiler]

 

 

Teraz kod dla mapy która musimy zapisać w folderze tym co skrypt, w formacie .txt pod nazwą "map" ,oczywiście bez cudzysłowia .

0000000000000000000001111111111111111110010011001111001100100100110011110011001001111111111111111110010011001111001100100100110011110011001001111111111111111110010011001111001100100100110011110011001001111111111111111110010011001111001100100100110011110011001001111111111111111110010011001111001100100100110011110011001001111111111111111110010011001111001100100111111111111111111000000000000000000000

 

Świetnie wytłumaczone w komentarzach :)

Brawa i podziękowania dla Hfauy jeszcze raz :)

Jak na AutoIT działa świetnie :)

 

 

 

Jeśli macie jakieś sugestie to piszcie staram się coś dodać/zmodyfikować/wyjaśnić :)

Opublikowano

na razie jest spoko.

ciekawi mnie rozwiązanie kolizji, bo nadal nie jestem pewny jak powinno się na nie reagować (w przypadku gdy trafimy na miejsce na ktore nie powinnismy moc wejść)[nie jestem pewny czy to jest poprawne]. Czy podczas jej wystąpienie w ogóle się nie poruszyć, czy wyliczyć z której strony jest kolizja i "przylgnąć" do ściany, czy znaleźć najbliższe miejsce bez kolizji, czy jakoś całkiem inaczej...

 

btw.

próbowałem znaleźć sposób na wyeliminowanie odstępy przy przytrzymaniu klawisza przed pierwszym, a drugim jego sczytaniem, jednak nie mogłem nic takiego wykminić. Windowshookeq też nie działa tak jak byłoby najlepiej. Zna ktoś jakiś sposób na to? (Nie mam zamiaru nic pisać w au3, tak z ciekawości ;p)

Opublikowano

@UP możesz wyjaśnić jaki odstęp przy przytrzymaniu klawisza? :P

Nie bardzo rozumiem :P

 

Dodany system kolizji +przykład

Opublikowano

pamiętasz ze swojej gry Xuanhtus (lol, nie wiem jak to się pisze) postać na chwile przystawała (po wciśnięciu klawisza), a potem chodziła już płynnie.

tak samo jak w notatniku przytrzymasz np litere R to po pierwszym jej napisaniu będzie mała przerwa. windows ma taki delay. o to chodzi.

 

 

 

@2down.

u mnie właśnie jest przy każdym

Opublikowano

@Sopel tutaj zastosowałem największe zło _IsPressed() i nie ma tego opóźnienia :)

@Jack gra jest w silniku Irrlicht, nie jest to GUI AutoITa, a okno tworzy się przez funkcje w bibliotekach silnika czyli z użyciem DLLCall bodajże, skopiuj stestuj i zobaczysz :)

Opublikowano

można by było się odwołać do user32.dll ale to będzie to samo co ispressed

może z hookiem?

 

#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>

Global $hHook, $hStub_KeyProc, $buffer = ""
global $i = 0
_Main()

Func _Main()
OnAutoItExitRegister("Cleanup")

Local $hmod

$hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam")
$hmod = _WinAPI_GetModuleHandle(0)
$hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($hStub_KeyProc), $hmod)
Run("notepad.exe")
WinWait("[CLASS:Notepad]")
WinActivate("[CLASS:Notepad]")

While 1
	Sleep(1)
WEnd
EndFunc   ;==>_Main

Func _KeyProc($nCode, $wParam, $lParam)
$tKEYHOOKS = DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam)
$f = DllStructGetData($tKEYHOOKS, "vkCode")
if $i = $f Then
$i = 0
Else
	ConsoleWrite($f & @CRLF)
$i = $f
EndIf
Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc   ;=
Func Cleanup()
_WinAPI_UnhookWindowsHookEx($hHook)
DllCallbackFree($hStub_KeyProc)
EndFunc   ;==>Cleanup

funkcje _KeyProc posprzątałem tam gdzie consolewrite to tam ify($f to numerek guzika), wrzuć do swojej gierki i sprawdź albo skompiluj jako konsole program

Opublikowano

@Sopel trochę dziwne, zaraz wstawie dokonczony tut i powiesz jak sciagniesz to co w tym tucie napisane jak działa

@Jack zaraz sprawdze czy tak się to ominie chociaż nie widzę tu różnicy między _IsPressed a tym wyżej. Wydaje mi się ,że ta przerwa jest narzucona przez sterowniki klawiatury :P

Opublikowano

@up

oczywiście że system filtruje keypress

porównaj

wciśnięty guzik przy maxymalnych ustawieniach w panelu sterowania

http://screenshooter.net/2977083/ojjrohx

a teraz

while
send(1)
wend

http://screenshooter.net/2977083/dgbrktm

sprawdzałem na skrypcie który podałem wyżej, tylko maly edit

 

$tCur = _Date_Time_GetSystemTime()
	ConsoleWrite(_Date_Time_SystemTimeToDateTimeStr($tCur) & "  " & $f & @CRLF)
$i = $f

więc jeżeli chodzi o te zacinanie, to hook powinien dobrze się sprawować zarejestrował 42 kliknięcia na sekunde(kto normalny tyle wyciągnie?)

Różnica między hookiem a ispressed jest taka,

w twoim kodzie ispressed jest w while

a w hook nie, nie trzeba się go pytać co sekunde czy coś było kliknięte, samo powie

przy czym też miej procko jebne

@edit

a zaraz obczaje sobie ten kodzik

Opublikowano

Arkeus pobierz download i wtedy sprawdź, mi działa (standardowa odzywka każdego programisty... :P )

Sopel dziwne z tym Twoim zatrzymywaniem postaci ;P

Rozumiem przy Hotkeyach , ale przy Ispressed? Pobierałeś i srawdziałeś? :)

 

PS: kogo można prosić o zdjęcie ciążących %?:P

Opublikowano

musiałbyś binarke wrzucić bo nie działa mi irr.

zresztą, próbwałem na przykładzie ispressed (mój tetris), hotkeyset (xuanthus), winhook (zrobiłem przykład).

za każdym razem jest delay

Opublikowano

sopelek, nie rozumiem twojego delay, bo mi zapierdala aż miło :/

sopel, użyj tej funkcji

_IrrReadKeyEvent()

zrobiłem testa z hookiem, nie nadaje sie na auto

@up2

zaraz kogoś zapytam(jeżeli nie poradziłeś sobie)

+ poprosiłbym o jakąś dokumentacje jeżeli można

 

dodajcie sobie gdzieś

 

if $bohater_x >= 800 then $x = 0
if $bohater_x < 0 then $x = 800
if $bohater_y >= 650 then $y = 0
if $bohater_y < 0 then $y = 650

lepiej się ucieka xD

@edit

edytuj irrstart na

_IrrStart($IRR_EDT_DIRECT3D9,$screen_width,$screen_height)

w innym przypadku default się ustawi, czyli 800x600

; Syntax.........: _IrrStart($i_DeviceType=$IRR_EDT_DIRECT3D9, $i_ScreenWidth=800, $i_ScreenHeight=600, $i_BitsPerPixel=$IRR_BITS_PER_PIXEL_32, $b_FullScreen=$IRR_WINDOWED, $b_Shadows=$IRR_NO_SHADOWS, $b_InputCapture=$IRR_IGNORE_EVENTS, $b_VSync=$IRR_VERTICAL_SYNC_OFF)

@arkeus

ściągnij directx sdk,najnowsze stery

 

@down

pisze sobie giere i byłem zmuszony aby znaleźć to :D

Opublikowano

@Jack

Przed inicjacją silnika masz zmienne $screen_width i $screen_height i to one odpowiadaja jak widac za rozmiar okna , dokumentację zaraz wygrzebię i dodam link , moment ;)

http://speedy.sh/XauyJ/au3Irr2.chm

 

EDIT: fakt , mój błąd z defaultem ;p Normalnie mam zawsze

_IrrStart( $IRR_EDT_OPENGL, $screen_width, $screen_height, $IRR_BITS_PER_PIXEL_32, _
$IRR_WINDOWED, $IRR_NO_SHADOWS, $IRR_IGNORE_EVENTS, $IRR_VERTICAL_SYNC_ON )

i usunałem z przekonania ,że zbędne cienie itp. dzięki za wychwycenie błędu ;)

  • 4 tygodnie później...
Opublikowano

@up

przykład kolizji

#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <misc.au3>
$Form1 = GUICreate("Form1", 382, 228, 192, 124)
$y1 = 24
$x1 =24
$y2 =80
$x2 =64
$wys = 36
$szer = 17
$xs = 0
$ys = 0
$Label1 = GUICtrlCreateLabel("kamera", $x1,$y1,$wys,$szer)
GUICtrlSetBkColor(-1, 0xFF0000)
$Label2 = GUICtrlCreateLabel("mob", $x2,$y2,$wys,$szer)
GUICtrlSetBkColor(-1, 0x00FF00)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
AdlibRegister("move", 10)
func move()
if _IsPressed("25") then left()
if _IsPressed("26") then up()
if _IsPressed("27") then right()
if _IsPressed("28") then down()
if GetCollision($x1+$xs, $x1+$wys+$xs,$y1,$y1+$szer,$x2,$x2+$wys,$y2,$y2+$szer) then $xs = 0
if GetCollision($x1,$x1+$wys,$y1+$ys,$y1+$szer+$ys,$x2,$x2+$wys,$y2,$y2+$szer) then $ys = 0
 $x1 += $xs
 $y1 += $ys
 GUICtrlSetPos($Label1, $x1, $y1)
$ys = 0
$xs = 0
EndFunc
func left()
$xs = -1
EndFunc
func right()
$xs = 1
EndFunc
func up()
$ys = -1
EndFunc
func down()
$ys = 1
EndFunc

func GetCollision($1X1, $1X2, $1Y1, $1Y2, $2X1, $2X2, $2Y1, $2Y2)
if (($1X2 > $2X1) and ($1Y2>$2Y1) and ($1X1<$2X2) and ($1Y1<$2Y2)) then
return true

   Else
 return False
 endif

endfunc

func mob()
if($x1 < $x2) Then
$xz = 1
if GetCollision($x1, $x1+$wys+3,$y1,$y1+$szer,$x2,$x2+$wys,$y2,$y2+$szer) then $xz = 0
$x2 -= $xz
guictrlsetpos($Label2,$x2,$y2)
EndIf
if($x1 > $x2) Then
$xz = 1
if GetCollision($x1, $x1+$wys,$y1,$y1+$szer,$x2,$x2+$wys+3,$y2,$y2+$szer) then $xz = 0
$x2 += $xz
guictrlsetpos($Label2,$x2,$y2)
EndIf
if($y1 < $y2) Then
$yz = 1
if GetCollision($x1, $x1+$wys,$y1,$y1+$szer+3,$x2,$x2+$wys,$y2,$y2+$szer) then $yz = 0
$y2 -= $yz
guictrlsetpos($Label2,$x2,$y2)
EndIf
if($y1 > $y2) Then
$yz = 1
if GetCollision($x1, $x1+$wys,$y1,$y1+$szer,$x2,$x2+$wys,$y2,$y2+$szer+3) then $yz = 0
$y2 += $yz
guictrlsetpos($Label2,$x2,$y2)
EndIf





EndFunc
AdlibRegister("mob", 50)
Do
until guigetmsg() = -3

  • 4 tygodnie później...
Opublikowano

Ok a nadanie własnego tła ?

 

I chcąc robić kolizje tak aby dało się jeździć np po ulicy nie po chodniku w mojej grze rowerem to musze każdą linie osobno opisac czy moge na mape naniesc linie i zapisac do osobnego pliku i dolaczyc jako kolizje ?

Opublikowano
I chcąc robić kolizje tak aby dało się jeździć np po ulicy nie po chodniku w mojej grze rowerem to musze każdą linie osobno opisac czy moge na mape naniesc linie i zapisac do osobnego pliku i dolaczyc jako kolizje ?

mało ważne jak to zrobisz. Wystarczy, że w jakiś sposób będziesz miał zapisane te wartości

Opublikowano

A tło ? ;d

 

lol to jest port irrlichta do autoit'a? ;o nie lepiej użyć c++ ?

;)

Oczywiście że lepiej ale nie w przypadku tego co ja chce robić zajeło by to za dużo czasu, zabawy a w Autoit w 15 minut masz to zrobione a więc pytanie - Poco w c++ ?

Opublikowano

Do samego 2D nie warto używać Irrlichta, wystarczy prosty ClanLib, SDL, XenonCore, Allegro <--- C++ :)

C++ jest szybsze i ogólnie ocieka zajebistością :) AutoIT według mnie do gier się nie nada ;) Ale kto co woli :>

Opublikowano

Nie powiedziałem że nie jest lecz ja planuje coś na zasadzie gry a w rzeczywistości ma to być projekt 1 razowy a więc poco się męczyć ? :D

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...