A więc wziąłem się do napisanie tego oto poradnika :D Poradnik jest na temat stworzenia gry, ping-ponga multiplayer używając do tych celów, Game Maker'a, a także 39DLL.
Będą nam potrzebne:
- 39DLL - Do pobrania
- Game Maker PRO - Do kupienia na GMC
- Cierpliwość :D - Rzecz nie do kupienia
Zaczynajmy:
Pierwszą rzeczą którą musi zrobić jest zaimportowanie skryptów 39DLL. Jest to łatwe do zrobienia, klikamy "File" i z menu wybieramy "Merge game...". W okienku które wyskoczy szukamy pliku "DLLScripts.gmk" który znajduje się w folderze z DLL'em. Po zrobieniu tego musimy przygotować sprit'y, potrzebujemy:
- paletki,
- piłki,
- przycisku "join",
- przycisku "host",
- pionowej lini.
Tworzymy pokój i nazywamy go "RMMenu", teraz otwieramy go, klikamy na zakładke "settings", a tam, na dole "Cration Code.". Wpisuje tam taki oto kod:
GML
dllinit(0,true,false) //0 - oznacza ze DLL nazywa sie 39dll.dll i znajduje sie w folderze z gra, pierwsze true oznacza zaladowanie funkcji socketow, a false oznacza nie zaladowanie funkcji plikow</span></span></span></span>
Ten kod służy do inicjacji naszego DLL. Musi być wykonany, po to abyśmy mogli używać jego funkcji. Czyli ta funkcja musi być wykonana jako pierwsza. Oczywiście jeżeli ktoś chce może załadować funkcje do operacji na plikach, ale w tak prostej grze nie jest to potrzebne. Teraz kolejna ważna rzecz, dołączanie do servera. Oto kod który należy wkleić w przycisku "join", w evencie "Mouse"->"Left Released".
GML
ip = get_string("Podaj IP do ktorego chcesz sie polaczyc:", "127.0.0.1"); //Pytamy o IP
global.otherplayer = tcpconnect(ip, 14804, 1); //Laczymy sie z danym serverem pod portem 14804
if(!global.otherplayer) //Jezeli false...
{
show_message("Nie mozna polaczyc z serverem."); //...pokazujemy wiadomosc
exit;//i wychodzimy z akcji
}
else //innaczej
global.host = false; //Zmienna mowi ze nie hostujemy
room_goto(RMGame); //Idziemy grac</span></span></span></span>
Musisz stworzyć pokój "RMGame" gdzie będzie można grać :P Przy okazji stwórz także pokój o nazwie "RMHost", gdzie hoster będzie czekał na gracza. Stwórz obiekt, w którym po kliknięciu lewym przyciskiem myszki przeniesie nas do pokoju o nazwa "RMHost". Teraz utwórz nowy obiekt, które będzie odpowiadał za oczekiwanie hostera na gracza. W tym obiekcie dodaj:
Create
GML
listen = tcplisten(14804, 2, 1); //Nasluchujemy na porcie 14804, na polaczenie. 2 oznacza ilosc graczy
global.host = true; //Zmienna okreslajaca iz hostujemy</span></span></span></span>
Step
GML
sock = tcpaccept(listen, 1); //Akceptujemy polaczenia
if(sock) //Jezeli jakies jest
{
closesocket(listen); //Zamykamy socket na ktorym nasluchujemy
global.otherplayer = sock; //Bedziemy wysylac dane do osoby ktora sie polaczyla
room_goto(RMGame); //Idziemy grac
}
Ewentualnie, można dodać w Draw:
GML
draw_text(0, 0, "Czekam na gracza..."); //Piszemy tekst na pozycji x= 0, y= 0</span></span></span></span>
To wszystko odpawiada za oczekiwanie hostera na gracza, sporo :P
Kolejnym krokiem jest stworzenie obiektu które będzie blokował piłeczke aby za daleko nie wypadła.
Ustaw mu solid, a następnie sprite "pionowej lini". Ten obiekt musi stać w górnej i dolnej stronie pokoju "RMGame".
Czasz na piłeczke, trudna sprawa... <joke> Tak naprawde piłka nie jest taka trudna. Wystarczy odpowiednio wysyłać jej pozycje x i y. W create piłeczki:
GML
if(global.host) //jesli hostujemy
{
direction = random(360); //random direction
speed = 8; //predkosc
setnagle(global.otherplayer, true) //To zapobiega lagom, należy to wstawić przed rozpoczęciem gry, bardzo się opłaca
}
Step:
GML
if(global.host) //Jesli hostujemy...
{
clearbuffer();//...czyscimy bufor, musi odbyc sie przed kazdym wyslaniem wiad.
writebyte(1); //ID wiadomosci, aby gracz, wiedzial co ma odebrac
writeshort(x);//wysylamy X pilki
writeshort(y);//wysylamy Y pilki
sendmessage(global.otherplayer); //Wysylamy, do gracza
}
Do wysyłania możemy użyć także tych funkcji:
GML
writebyte( wartosc );//Wysyla 1 bajt, wartosc pomiedzy 0 a 255
writeshort( wartosc );//Wysyla 2 bajtowa wartosc liczbowa, z przedzialu -32768 a 32767
//Jezeli chcemy wyslac wieksze lub mniejsze liczby uzywamy tych funkcji:
writeint( wartosc );
//Lub
writedouble( wartosc );
writestring( string ); //Wysyla ciag znakow(string)</span>
Kolizje z paletką, i obramowaniem to nic innego jak zwykłe odbicie. A outside room:
GML
x = xstart
y = ystart
Mamy już piłeczke, ale co teraz? Teraz pora na paletki, każdej zawartość będzie inna, po to abyśmy nie sterowali obiema, tylko jedną, a także dla wielu innych rzeczy. Paletka gracza pierwszego, czyli ta którą gra hoster. Jej zawartość:
- Destroy
GML
closesocket(global.otherplayer); //Zamykamy socket
room_goto(RMMenu); //Wracamy do menu</span></span></span></span>
- Step
GML
if(!global.host)exit;
while(1) //Petla while
{
size = receivemessage(global.otherplayer); //Odbieramy wiad.
if(size < 0)break; //Wylamujemy z petli, gdy napotka blad
if(size == 0) //Jezeli nic nie ma :(
{
show_message("Drugi gracz opuscil gre."); //Pokazujemy wiadomosc
instance_destroy(); //Nisczymy sie
break;
}
mid = readbyte(); //Odczytujemy byte
switch(mid) //Switch
{
case 0:
objPlayer2.y = readshort(); //Odbieramy Y drugiego gracza
break;
case 1:
objBall.x = readshort(); //Odbieramy X pilieczki
objBall.y = readshort(); //Odbieramy Y pileczki
break;
}
}
- Strzałka W Góre
GML
if(y > 0 and global.host)
{
y -= 5;
event_user(0);
}
- Strzałka W Dół
GML
if(y + sprite_height < room_height and global.host)
{
y += 5;
event_user(0);
}
Teraz dodaj event User Definied 0 a w nim:
GML
clearbuffer(); //Czyscimy bufor
writebyte(0); //ID wiad. dla ruchu paletki
writeshort(y); //wysylamy pozycje Y
sendmessage(global.otherplayer); //wysylamy</span></span></span></span>
Koniec, jak na razie pierwszej paletki. Przyszła pora na drugą. Jest to prawie to samo, lecz różni się tym, jak już mówiłem wyżej, że sprawdzamy czy jesteśmy hostem, czy nie. No więc nie będe się rozgadywał, bierzmy się do roboty. Kod tej paletki będzie bez komentarzy, ponieważ wszystko w niej to to samo co w pierwszej, a więc wystarczy looknąć wyżej :P
Zaczynajmy, event Destroy:
GML
closesocket(global.otherplayer);
room_goto(RMMenu)
- Step
GML
if(global.host)exit;
while(1)
{
size = receivemessage(global.otherplayer);
if(size < 0)break;
if(size == 0)
{
show_message("Drugi gracz opuscil gre.");
instance_destroy();
break;
}
mid = readbyte();
switch(mid)
{
case 0:
objPlayer1.y = readshort();
break;
case 1:
objBall.x = readshort();
objBall.y = readshort();
break;
}
}
- Strzałka W Góre
GML
if(y > 0 and !global.host)
{
y -= 5;
event_user(0);
}
- Strzałka W Dół
GML
if(y + sprite_height < room_height and !global.host)
{
y += 5;
event_user(0);
}
- User Defined 0
GML
clearbuffer();
writebyte(0);
writeshort(y);
sendmessage(global.otherplayer);
Pamiętaj także, aby w evencie Game End dodać kod:
GML
dllfree()
Obiekt z tym eventem musi byc w kazdym pokoju, ten kod zwolni dll z pamieci naszego komputera :P
Download(GMK+EXE): https://gmclan.org/up5379_4_Pong.html
39DLL(Należy wkleić do folderu z grą): https://gmclan.org/up5379_4_39dll.html
Nie czepiać się tego że większość w poradniku to kod, bo to nie pokazuje wszystkich funkcji tego DLL, tylko te które są potrzebne.
Jeśli będą problemy, proszę pisać, a jeśli znajdziecie błąd u mnie, tutaj w kodzie to także pisać. Wiem, że to mało, no bo to taki mini kurs.
To już koniec, mam nadzieje że coś się nauczycie, o korzystaniu z 39DLL. Jest on znacznie szybszy, wygodniejszy i lepszy niż wbudowany mplay.
Pozdro
Roki