játékfejlesztés.hu
FórumGarázsprojectekCikkekSegédletekJf.hu versenyekKapcsolatokEgyebek
Legaktívabb fórumozók:
Asylum:    5448
FZoli:    4892
Kuz:    4455
gaborlabor:    4449
kicsy:    4304
TPG:    3402
monostoria:    3284
DMG:    3172
HomeGnome:    2919
Matzi:    2520

Pretender:    2498
szeki:    2440
Seeting:    2306
Geri:    2188
Orphy:    1893
Joga:    1791
Bacce:    1783
MaNiAc:    1735
ddbwo:    1625
syam:    1491
(DB) Egy helyi hálózatos játék elkészítése Dark Basic Pro-ban 2006.04.19 15:35




Helyi hálózat (LAN) és FTP protokoll használata DB Pro –ban

Bevezetés

Rengeteg dolog bizonyítja már, hogy a Dark Basic Professional mennyire sokszínű és fejlesztőbarát. Egy régebbi cikkben írtam a program multiplayer lehetőségeiről, de ez főleg az internetes játékra vonatkozott. Most itt az ideje, hogy megismerkedjünk, hogy mire képes a DBP helyi hálózaton (LAN), illetve azt is kielemezzük majd, hogy mik a számottevő különbségek egy internetes és egy LAN-os játék között, amit a programozónak egy „multis” projekt fejlesztése során érdemes ismernie. Sor kerül majd, egy kisebb, 2D-s helyi hálózatos akciójáték elkészítésére is. De mielőtt mindezekbe belevágnánk, ismerkedjünk meg a fejlesztő eszköz FTP-s lehetőségekkel.

Mi is az FTP?

A rövidítés a File Transfer Protokoll-ra (fájl átviteli protokoll) utal, melynek lényege a fájlok és adatállományok két gép közötti átviteli lehetőségének megteremtése. Manapság minden internet szerver rendelkezik ezzel a protokollal. Cégek és magánszemélyek FTP-n tárolják honlapjukat, egyes programozók pedig e protokoll segítségével cserélnek adatot egymás között. Napjainkban mindenki magénak tudhat egy FTP hozzáférést, csak regisztrálnia kell egy ingyenes szolgáltatónál (teszem azt, ATW vagy UW).

Miért van szükségem FTP-re a multiplayer játékomhoz?

Az FTP használatával számtalan lehetőség nyílik meg a DB programozó előtt. Teheti például azt, hogy a kész játéka frissítéseit feltölti egy tárhelyére, a programját meg úgy írja meg, hogy automatikusan észrevegye, hogy van-e frissítés az ftp-n. Ennek a funkciónak az lesz az eredménye, hogy a játék automatikusan fogja magát frissíteni, megspórolva ezzel rengeteg felhasználó idejét és energiáját.

Nézzük meg, hogyan is nézne ki egy ilyen programfrissítő algoritmus (a kód kommentjeinek olvasását erősen ajánlom mindenki figyelmébe ;) ) A következő példaprogramban feltesszük, hogy van egy tárhelyünk, benne egy „patches” mappával. Ebben a mappában további mappák vannak, melyeknek neve egyenlő a letöltendő frissítés verziószámával. Szóval, ha a jelenlegi programunk verziószáma 1.0, akkor nekünk az „1.1” nevű mappába kell belépnünk a frissítésért. Ha létezik ilyen nevű mappa, akkor az azt jelenti, hogy már van ilyen frissítés; ha nem létezik, akkor a fejlesztő még nem adott ki ilyet. Tegyük fel, hogy minden létező frissítés mappában elhelyeztünk egy „patch.exe” nevű fájlt. Ezt kell letöltenünk, és végrehajtanunk:


Rem Auto-Upgrade alprogram:
Auto_Patch:

aktualis_verzio$="1.0"
javitott_verzio$="1.1"
 
Rem A kapcsolódás az FTP CONNECT paranccsal tölténik
Rem Paraméterei: a szolgálatónál regelt tárhelyed webcíme (URL),
Rem felhasználóneve, és jelszava
Ftp connect "http://killertech.atw.hu","user","password"
 
Rem Ellenőrízzük hogy létrejött-e a kapcsolat
Rem A függvény 0-át ad vissza, ha minden simán ment
If get ftp failure()=0
Rem Ha sikerült
goto upgrade
Else
Rem ha nem sikerült, akkor vissza a menübe
goto Menu
Endif
 
Upgrade:
Rem Kiválasztjuk a javítások mappáját
FTP Set dir "patches" : Sync
 
Rem Belépünk a javítás mappájába
FTP Set dir "1.1"
 
Rem Ha nem létezik a mappa, akkor még nem jött ki ilyen patch
Rem Ebben az esetben vissza igyekszünk a menübe
If Get ftp failure()=1 then FTP Disconnect : goto menu
 
Rem Javítás letöltése
Rem [ftp-s fájlnév, hova töltse, töltés sebessége (byte-ban)]
FTP Get file "patch.exe","backup/patch.exe",100
 
Rem Letöltés (ha a letöltés véget ért, a fv. értéke -1 lesz)
while get ftp progress()>-1
Rem Ahányszor végrehajtódik a parancs, annyiszor 100 byte-ot leszedünk
FTP Proceed
Endwhile
 
Rem Miután letöltöttük a csibét, bezárjuk az FTP kapcsolatot
FTP Disconnect
 
Rem Hajtuk végre a patchelést
Execute file "backup/patch.exe","","",0
 
Rem Alprogram vége
Return



Javítások készítésére a ClickTeam (http://www.clickteam.com) Install Creator Pro termékét ajánlom. A trial verzió ingyenesen letölthető.


A régebbi MP cikkben már megtudhattuk, hogy a DBP nem képes arra, hogy az interneten kreált szervereket lássa. Nos, FTP tárhely használatával ez a probléma is kiküszöbölhető. A probléma orvoslásának módja a következő: legyen az FTP szerverünkön egy „servers” nevű mappa és abban kb. 5 szöveges fájl. A szerver létrehozásakor írjuk meg úgy a DBP játékunkat, hogy az, az IP címünket tartalmazó változót kimentse egy fájlba. Ezután csatlakozzon FTP-re és válassza ki a „servers” mappában lévő fájlok közül azt, amelyik éppen üres, és írja felül azzal a fájlal, amibe kimentettük adatainkat. Miután a szerver leállításra kerül, írjuk felül ugyanezt a fájlt egy üressel, jelezve, hogy már nem létezik a szerverünk. A kliensünk feladata már csak az lesz, hogy FTP-ről letölti az öt szöveges fájlt, megnyitja őket, és a tartalmukat – ami jelen esetben 5db IP cím lesz – kiírja a képernyőre. Ha egy fájl üres, akkor a semmit fogja kiírni a képernyőre. Ez az eljárás vizuálisan így nézhet ki:

Helyi Hálózat

Ezzel el is érkeztünk ahhoz a témához, amiről a cikkünk valójában is szól, a Helyi Hálózathoz. A továbbiakban bemutatásra kerülnek majd a kapcsolat tulajdonságai; előnye – hátrányai; az, hogy hogyan hozhatunk létre ilyen fajta kapcsolatot DB Pro-ban; valamint elkészítünk majd egy kis 2D-s multiplayer akciójátékot is :P. Hát akkor csapjunk a lecsóba.

Mit kell tudni a LAN-ról?

Az internethez hasonlóan, a helyi hálózat is TCP/IP protokollt használ, tehát csatlakozásnál mindkettő esetben célszerű egy IP címet megadnunk. Ellentétben az internettel, a „LAN-os kód” írásakor bőkezűen küldözgethetjük a kövér csomagjainkat, hiszen a 100 Mbit/Sec-os kapcsolatunk ezzel könnyedén megbirkózik. Amikor viszont arra kerül a sor a szerver létrehozásakor, hogy meg kell adnunk, hány játékos legyen képes csatlakozni hozzánk, elég megadnunk 4, maximum 8 playert, hiszen helyi hálózaton úgysem leszünk rászorulva ennél nagyobb szerver kapacitásra (kivételek a Lan party-k ;) ).

LAN Dark Basic Pro-ban

DB Pro-ban helyi hálózatotos kapcsolatot a Default Net Game paranccsal hozhatunk létre. A parancs paramétereiben meg kell adnunk a játékunk címét, a játékosunk nevét, hogy hány játékos vehessen részt a játékban, illetve a játék típusát. Mivel ez a parancs egy függvény, így értéket is ad vissza. A visszakapott érték a mi játékos sorszámunk lesz a szerverben. Szóval, ha mi nyitjuk meg a szervert, akkor a kapott érték mindig 1, ha pedig már van szerver a hálózatban, akkor az értékünk értelem szerűen nagyobb lesz 1-nél. Ez a megállapítás arra is jó, hogy eldöntsük, az adott player szerver vagy kliens.

Kisebb hálózatos játék elkészítése

Készítsünk el egy kisebb kaliberű, 2 dimenziós akciójátékot. Nincs rá szükségünk, hogy nagyon kidíszítsük, a lényeg most a hálózati kód lesz. Lehessen a játékunkban mozogni és lőni, az ellenfél pedig minden mozdulatunkat láthassa. A továbbiakban elkészített játék teszteléséhez nem kell feltétlenül 2 darab számítógép, elég, ha csak kétszer lefuttatjuk a programot. Első lépésként optimalizáljuk a DB-t, majd töltsük be programunkba a háttér, és a játékosokat megjelenítő spriteokat. Miután ez megvolt, töltsük be játékosunk nevét. A nevet egy külső szöveges fájlban tároljuk, hogy ne kelljen minden egyes csatlakozásnál újra megadni:

Rem Betöltés
Sync on : Sync rate 60
Set display mode 800,600,32
Set window on : Set Window Title "Jatekfejlesztes.hu:  Lovoldozos jatek :D"
Disable escapekey
 
Backdrop on : Color backdrop RGB(255,255,255)
Ink RGB(120,15,15),RGB(0,0,0)
 
 
Rem Képek betöltése
Load image "hatter.jpg",5,1 : hatter=5
Load image "player.bmp",2,1 : player=2
Load image "player2.bmp",3,1 : player2=3
Load image "lovo.bmp",6,1 : lovo=6
Load image "tolteny.bmp",7,1 : tolteny=7
 
Rem Adatok (player név) betöltése
Open to read 1,"playername.txt"
 Read string 1,playername$
Close file 1



Ezután jöhet a játék menüje. Legyen benne egy „Mehet”, egy „Opciók”, és egy „Kilépés” menüpont. A „Mehet” gombra kattintva induljon el a játék, az „Opciók”-ban pedig a player nevet tartalmazó fájlt lehessen átírni. Deklaráljunk egy élet változót is. Ha ez nulla, akkor a játékosunk vesztett. A menüpontokat szépen kiszínezzük ha az egér fedi őket.

 Rem Menü Loop
Menu:
 
Rem Élet
Global Elet=1
 
Do
 
Rem Cím kiírása
Set cursor 220,20 : Set text size 40
Print "Jatekfejlesztes.hu" : Set text Size 36
 
 Rem ***** Menü *****
 
  Rem Mehet
  Set cursor 320,160
  Print "Mehet"
 
  Rem Mehet fedése az egérrel
  If mousex()>320 and mousey()>160 and mousex()<400 and mousey()<190
   Set cursor 320,160 : Ink RGB(255,200,200),RGB(0,0,0)
   Print "Mehet" : Ink RGB(120,15,15),RGB(0,0,0)
 
   Rem Játék indítása
   If mouseclick()=1 then goto mehet
 
  Endif
 
  Rem Opciók
  Set cursor 315,260
  Print "Opciok"
 
  Rem Opciók fedése az egérrel
  If mousex()>315 and mousey()>260 and mousex()<415 and mousey()<285
   Set cursor 315,260 : Ink RGB(255,200,200),RGB(0,0,0)
   Print "Opciok" : Ink RGB(120,15,15),RGB(0,0,0)
 
   Rem Ugrás az opciókhoz
   If mouseclick()=1 then goto opciok
 
  Endif
 
  Rem Kilépés
  Set cursor 310,360
  Print "Kilépés"
 
  Rem Opciók fedése az egérrel
  If mousex()>310 and mousey()>360 and mousex()<415 and mousey()<385
   Set cursor 310,360 : Ink RGB(255,200,200),RGB(0,0,0)
   Print "Kilépés" : Ink RGB(120,15,15),RGB(0,0,0)
 
   Rem Kilépés a programból
   If mouseclick()=1 then end
 
 Endif
 
 Rem ****************
 
 Set cursor 750,500 : Set text size 12
 Print "v1.0" : Set text size 36
 
Sync
Loop



Most jöhet az Opciók alprogram. Legyen benne két menüpont: az egyik segítségével átírhassuk a játékosunk nevét tartalmazó fájlt, a másik menüponttal pedig jussunk vissza a főmenübe.

 Opciok:
 
Rem options Loop
Do
 
Rem PlayerName
Set cursor 120,200
Print "Kattints ide a neved megadasahoz!"
 
Rem PlayerName fedése az egérrel
If mousex()>120 and mousey()>200 and mousex()<650 and mousey()<225
 Set cursor 120,200 : Ink RGB(255,200,200),RGB(0,0,0)
 Print "Kattints ide a neved megadasahoz!"
 Ink RGB(120,15,15),RGB(0,0,0)
 
 If mouseclick()=1
 Set cursor 120,200
 Input Name$
 
 If file exist("playername.txt")=1 then delete file "playername.txt"
 Open to write 1,"playername.txt"
 Write string 1,Name$
 Close file 1
 
 Goto Menu
 
 Endif
Endif
 
Rem Vissza
Set Cursor 1,500
Print "Vissza"
 
Rem Vissza fedése az egérrel
If mousex()>1 and mousey()>500 and mousex()<100 and mousey()<525
 Set Cursor 1,500 : Ink RGB(255,200,200),RGB(0,0,0)
 Print "Vissza" : Ink RGB(120,15,15),RGB(0,0,0)
 
 If mouseclick()=1 then goto menu
 
Endif
Sync
Loop



            A menüvel nagyjából készen is volnánk, most jöhet maga a játék. Hogy ha a játékos rákattint a mehet gombra, akkor ugorjunk a „mehet” címkére a programunkban, ami a hálózathoz való csatlakozásért felelős. Játékunk ezen részében fog kiderülni, hogy szerver vagy kliens vagyunk. Először jelezzünk a felhasználónak, hogy most egy ideig ne csináljon semmit, majd hívjuk meg a default net game parancsot:

Rem Jelezzünk a fehasználónak
Set text size 24 : Sync
Print "Csatlakozas... varj egy kicsit!" : sync
PlayerSzam=default net game("jf.hu_game",PlayerName$,4,1)



Mint ahogy már fentebb említettem, a parancsból visszakapott érték, a hálózatba belépett játékos száma lesz. Ezt tároljuk el a PlayerSzam változóba! Most pedig kielemezzük, hogy milyen pozíciót töltünk be. Ha számítógépünkön minden jól van beállítva, akkor eme parancs hatására meg kell jelennie egy ilyen windows ablaknak:


Ha ez az ablak nem jelenik meg, akkor ne számítsunk arra, hogy játékunk helyesen fog működni. Ha viszont megjelent az ablak, akkor örülhetünk. :) Hagyjuk üresen a beírás helyét, majd kattintsunk az OK gombra. Ilyenkor a Dark Basic automatikusan szervert keres a hálózatban, és ha nem talál, akkor csinál egyet. Nagyobb LAN Party-k esetében – ahol több szerver is van egyszerre – érdemes beírnunk a mezőbe annak a számítógépnek az IP címét, amelyikhez csatlakozni szeretnénk.

Ha mi vagyunk a szerver, akkor állítsuk a játék ablakának címét „Én vagyok a szerverre”, készítsük el saját magunk sprite-ját, majd ugorjunk a játék központi részére (Main Loop). Érdemes úgy megírnunk a programot, hogy a benne szereplő sprite-ok száma mindig az azt irányító játékos száma legyen. Így sokkal könnyebb lesz majd frissíteni őket. Mivel most úgy néz ki, hogy mi vagyunk a szerver, ezért elég csak a saját magunk megjelenítése a pályán, hiszen még úgy sincs bent rajtunk kívül senki a játékban. Hogy mi történjen akkor, ha játék közben belép valaki, a Main Loop-ban kell megírnunk.

If PlayerSzam=1
 Set window title "En vagyok a szerver! :D"
 
 Rem Háttér elkészítése
 Sprite hatter,0,0,hatter : Size sprite hatter,800,600 : Sync
 
 Rem Önmagunk elkészítése (mi mindig kinézetünk mindig a player kép lesz)
 Sprite PlayerSzam,50,50,player
 
 Rem Mehet a játék
 Goto Main_Loop



Ha kliensek vagyunk, akkor az ablak címkéje „Én meg kliens vagyok!” legyen. Ha be akarunk lépni egy játékba, azt illik közölni a szerverrel, mivel csak így fogja tudni majd menet közben elkészíteni kinézetünket. A szerver játékos száma mindig 1. Addig küldözgetjük az „engedj_be” üzenetet az első számú játékosnak, míg az meg nem kapja, és válaszol az „ok_jöhetsz” üzenettel. Ha megkaptuk ezt a választ, az azt jelenti, hogy a szerver már elkészítette kinézetünket, és tiszta az út a meccsbe belépéshez. Mivel most kliensek vagyunk, nem elég csak saját magunkat elkészíteni, hanem fel kell mérni, hogy hány darab játékos van most éppen játékban, és őket is meg kell jelenítenünk. A szerveren lévő játékosokról a Perform Checklist For Net Players paranccsal készíthetünk listát. A parancs lefutását követően elindítunk egy elöl számlálós ciklust, ami 1-től kezdődik, és addig tart, ahány eleme volt a listánknak, mínusz 1. Azért kell az elemekből kivonnunk egyet, mert az utolsó játékos aki belépett azok mi vagyunk, és önmagunkat nem készíthetjük el kétszer.

Else
 
 Set window title "En meg kliens vagyok!"
 
 Rem Háttér elkészítése
 Sprite hatter,0,0,hatter : Size sprite hatter,800,600 : Sync
 
 Rem Játszási szándékunk közlése a szerverrel
 Get net message
 While kliens_ok=0
  Send net message string 1,"engedj_be"
  If net message string$()="ok_johetsz" then kliens_ok=1
  Get net message
 Endwhile
 
 Rem Önmagunk elkészítése
 Sprite PlayerSzam,600,50,player
 
 Rem A Többiek elkészítése
 Perform checklist for net players
 For i=1 to checklist quantity()-1
 
  Rem A többiek kinézete player2 kép lesz
  Sprite i,100,50,player2
 
 Next i
 
 Rem Mehet a játék
 Goto Main_Loop
 
Endif



Mindezek után, jöhet a fő programtörzs, a Main Loop. Itt hívjuk majd meg a különböző funkciókért felelős alprogramjainkat. Szükségünk lesz egy mozgató, lövő, adatcserét közlő, aktív játékosokat ellenőrző, és egy pontszám-kezelő alprogramra.

Rem Main Loop
Main_Loop:
Do
 
Gosub Mozgatas
Gosub Loves
Gosub Adatcsere
Gosub Player_kezeles
Gosub Elet_kezeles
 
Sync
Loop



A mozgatásért felelős programrészben lehessen mozogni a kurzor segítségével, legyenek korlátok, hogy ne lehessen kimenni a pályáról, és legyen egy alapszintű gravitáció. A játékos pozícióit a program tárolja el változókba, hogy később el lehessen azokat küldeni. Az Irany$ változó pedig arra szolgál majd, hogy a később kilőtt golyó irányát meghatározza.

Mozgatas:
If upkey()=1 then dec yPoz,2
If downkey()=1 then inc yPoz,2
If leftkey()=1 then dec xPoz,2 : Irany$="balra"
If rightkey()=1 then inc xPoz,2 : Irany$="jobbra"
 
Rem Gravitáció
If yPoz<500 then Inc yPoz,1
 
Rem Korlátok
If xPoz<1 then xPoz=1
If xPoz>700 then xPoz=700
If yPoz<1 then yPoz=1
If yPoz>500 then yPoz=500
 
Sprite PlayerSzam,xPoz,yPoz,player
 
Return



Ezután jöhet a lövésért felelős alprogram. A controll billentyű lenyomására egy kis időre változzon meg játékosunk animációja lövőre ( :) ), majd készítsük el a kilőtt golyót. Ha a golyót megjelenítő sprite létezik, akkor mozgassuk azt a megadott irányba, mindaddig, amíg nem ütközik a fallal. A töltény pozícióját is változókba tároljuk, hogy később tovább lehessen küldeni őket. Valamint hozzunk létre egy „lo” nevű változót, melynek értéke mindig 1 lesz, ha lövés van folyamatban, különben 0.

Loves:
 
If controlkey()=1
 
 Rem Várakozás a gomb felemeléséig
 While controlkey()=1
  Sync
 Endwhile
 
 Rem Lövö animáció
 Sprite PlayerSzam,xPoz,yPoz,lovo : Sync : Sleep 500
 Sprite tolteny,xPoz+50,yPoz+50,tolteny
 
 Rem Tölrény pozíciója
 tx=xPoz+50 : ty=yPoz+50
 
 Rem Töltény iránya
 TIrany$=irany$
 
Endif
 
Rem Töltény irányítása
If Sprite exist(tolteny)=1
 
Rem Ha lövés van
lo=1
 
If Tirany$="jobbra" then inc tx,5
If Tirany$="balra" then dec tx,4
 
Sprite tolteny,tx,ty,tolteny
 
Rem Ütközések
If ty<1 then delete sprite tolteny
If tx<1 then delete sprite tolteny
If ty>550 then delete sprite tolteny
If tx>750 then delete sprite tolteny
 
Else
Lo=0
Endif
 
Return



Most jöhet játékunk legfőbb része, az adatcsere. Ebben a részben kapni és küldeni fogunk adatokkal teli csomagokat. Ha egy csomag várólistán van (fogadásra várakozik), azt a net message exists() függvénnyel tudhatjuk meg, melynek értéke 1 lesz ha van várakozó csomag. Egy csomagot a get net message paranccsal tudunk fogadni. Most készülő játékunk írása során nem lesz szükségünk a net message type() függvényre (amely a fogadott csomag típusát adja vissza), mivel játékunkban mindig szöveges (string) típusú csomagokat fogunk használni. Az üzenet-kapó algoritmusban nem csak a játékosok pozícióját tartalmazó csomagokat kell lekezelnünk, hanem a fentebb említett „engedj_be” típusúakat is. Addig hajtjuk végre az üzenet kezelő algoritmust, amíg van nem fogadott üzenet.

 Adatcsere:
Rem ***** Adatcsere *****
 
Rem Üzenet kapás
Get net message
While net message exists()=1
 
Rem Letárolás
uzenet$=net message string$()
kitol=net message player from()



Miután letároltuk az üzenet szövegét és azt hogy ki küldte (player szám), megkezdhetjük az üzenetek feldolgozását. Ha egy player be akar lépni akkor üzenetet küld a szervernek. Ennél fogva ha ilyen fajta üzenet érkezik hozzánk, akkor mi vagyunk a szerver.

  Rem ***** Feldolgozás *****
 
  Rem Ha egy kliens be akar lépni a szerverünkbe
  If uzenet$="engedj_be"
 
   Rem Player elkészítése
   Sprite kitol,600,50,player2
 
   Rem Visszajelzés a kliensnek
   Send net message string kitol,"ok_johetsz"
 
  Endif



Ha egy klienst lelövünk akkor kiesik a játékból. Ezt úgy tudjuk megoldani, hogy ha a kliens ütközik a tölténnyel, akkor üzenetet küld a szervernek, majd az kilépteti a játékost a hálózatból és válaszol.

   Rem Ha egy kliens kiesett a játékból
  If uzenet$="vegem_van"
   Send net message string kitol,"ok_bye"
   Free net player kitol
  Endif



Most következzen a csomagok feldolgozása. A mi játékunkban, mivel kénytelenek vagyunk összefűzni az értékeket egy szöveges változóba, valahogy meg kell különböztetni, hogy melyik számpár melyik értékhez tartozik.  Az adatcsomagokban tárolt értékek „*” jellel lesznek elválasztva egymástól. El kell küldenünk az x és y pozíciónkat, azt hogy van-e lövés folyamatban, és a töltény x és y pozícióját. Hogy a fogadó játékos tudja, hogy most adatcsomag érkezett, az elküldendő szöveges változónk elé teszünk egy „p” karaktert. Egy ilyen csomag tehát valahogy így nézhet ki:

p128*485*1*16*345”

Az üzenet szétbontását a következő képpen végezzük: A csomagban található karaktereket sorra vesszük, amíg az üzenet el nem fogy. Egy string típusú változóból karaktert a mid$() függvénnyel csalhatunk ki. A függvénynek meg kell adnunk a kívánt string változó nevét, és azt hogy hanyadik karakterére vagyunk kíváncsi. A „Talalat” változó értéke mindig egyel nő, ha a karakterek nézegetése és pakolgatása során „*” jelhez érkezünk. Alapértelmezetten 1-re állítjuk az értékét. Eme változó arra szolgál, hogy elválassza egymástól a feltöltendő változókat. A vizsgált karaktereket egyenként pakolgatjuk a változókba.

 Rem Ha csomag jön
  If Left$(uzenet$,1)="p"
    Talalat=1
 
    Rem Csomag szétbontása
    Rem Ciklus 1-től az üzenet végéig
    For p=1 to len(uzenet$)
 
     Rem Ha egy érték már meglett
     If mid$(uzenet$,p)="*" then inc Talalat
 
      Rem xPoz
      If talalat=1 and mid$(uzenet$,i)<>"*"
       OtherX$=OtherX$+mid$(uzenet$,p)
      Endif
 
      Rem yPoz
      If talalat=2 and mid$(uzenet$,i)<>"*"
       OtherY$=OtherY$+mid$(uzenet$,p)
      Endif
 
      Rem Van-e lövés folyamatban
      If talalat=3 and mid$(uzenet$,i)<>"*"
       OtherLoves$=OtherLoves$+mid$(uzenet$,p)
      Endif
 
      Rem ToltenyX
      If talalat=4 and mid$(uzenet$,i)<>"*"
       OtherTX$=OtherTX$+mid$(uzenet$,p)
      Endif
 
      Rem ToltenyY
      If talalat=2 and mid$(uzenet$,i)<>"*"
       OtherTY$=OtherTY$+mid$(uzenet$,p)
      Endif
 
   Next p



Letárolás után lecsippentjük a változókból a bennük maradt „p”, illetve „*” karaktereket:

OtherX$=Right$(OtherX$,Len(OtherX$)-1)
OtherY$=Right$(OtherY$,Len(OtherY$)-1)
OtherLoves$=Right$(OtherLoves$,Len(OtherLoves$)-1)
OtherTX$=Right$(OtherTX$,Len(OtherTX$)-1)
OtherTY$=Right$(OtherTY$,3)



Majd pedig frissítjük a sprite-ok pozícióit a kapott adatokkal (át kell konvertálni a stringeket egész számmá a val() függvény segítségével). Ha lövés van akkor pozícionáljuk a töltény sprite-ot (amelynek száma az üzenet küldőjének száma+”tolteny” változó értéke), ha nincs lövés, akkor töröljük a töltény sprite-ot (feltéve ha létezik):

   Rem Player frissítése
   If val(OtherLoves$)=1
    Sprite tolteny+kitol,val(OtherTX$),val(OtherTY$),tolteny
   Else
    If sprite exist(tolteny+kitol) then Delete sprite tolteny+kitol
   Endif



Frissítjük az ellenfél sprite-ját (aminek száma maga a player száma):

   Sprite kitol,val(OtherX$),val(OtherY$),player2



Ha az ellenfél lő, és a töltény ütközik velünk, akkor kitöröljük a töltény sprite-ját és levonunk az életünkből egyet. Ez azt jelenti, hogy kiestünk a játékból. Ennek a folyamatnak az eredményével egy másik alprogram fog foglalkozni majd.

   Rem Töltény ütközése a playerrel
   If val(OtherLoves$)=1
    If sprite collision(PlayerSzam,tolteny+kitol)=1
     Sprite PlayerSzam,50,50,player
     Delete sprite tolteny+kitol
     Dec Elet
    Endif
   Endif



Redukáljuk az értékeket tartalmazó változókat, hogy aztán a következő pakolásnál tiszta lappal indulhassunk:

   Rem Változók redukálása
   OtherX$=""
   OtherY$=""
   OtherLoves$=""
   OtherTX$=""
   OtherTY$=""
 
  Endif
  Rem Feldolgozás vége



Lekérjük a következő feldolgozásra váró üzenetet, és lezárjuk az üzenet fogadó ciklust:

Get net message
 
Endwhile



Ugyanennek az alprogramnak a feladata még, saját adataink elküldése a többi játékosnak. Ha a Send net message string parancshoz első értéknek 0-át adunk meg, az azt jelenti, hogy a szerveren játszó összes játékosnak el szeretnénk küldeni a csomagunkat.

Rem Üzenet küldés
 
Rem Csomag elkészítése
Csomag$="p"+str$(xPoz)+"*"+str$(yPoz)+"*"+str$(lo)+"*"+str$(tx)+"*"+str$(ty)
Send net message string 0,Csomag$
 
Rem *********************
Return



Szükségünk van egy olyan alprogramra is, amely azt ellenőrzi, hogy lépett-e ki játékos a meccsből az utóbbi időben. Ha talál kilépett játékost, akkor törli a sprite-ját. A kilépett játékos számát a net player destroyed() függvény adja vissza:

Player_kezeles:
 
Rem Ha az egyik player kilép
kilepett=net player destroyed()
If kilepett>0
 If sprite exist(kilepett) then delete sprite kilepett
Endif
 
Return



Ellenőriznünk kell továbbá a saját meghalásunkat is. Egy „vegem_van” üzenetet küldünk a többieknek, ha ez életünk kevesebb lesz mint 1. Ha megkaptuk a válaszüzenetet, az azt jelenti, hogy a többiek már kitöröltek minket a játékból, tehát mi is töröljük őket és a terepet. Ezek után nincs más hátra, mint előre, lépjünk vissza a menübe ;) .

Elet_kezeles:
 
Rem Ha a player meghal, kiesik a játékból
If Elet<1
 While kiesett=0
  send net message string 0,"vegem_van"
  Get net message
  If net message string$()="ok_bye"
 
  Rem Sprite-ok törlése
  Delete sprite hatter
  Delete sprite PlayerSzam
  Rem Többi player sprite-jának törlése
   For i=1 to 4
    If sprite exist(i) then delete sprite i
   Next i
 
  Rem Ugrás a menüre
  goto Menu
 
  Endif
 Endwhile
Endif
Return



Ötletek, és egyéb trükkök

-Ha azt szeretnénk, hogy játékunk ne engedjen be régebbi verziószámmal rendelkező klienst a szerverünkbe, akkor érdemes minden program frissítés során módosítani a játék forráskódjában a default net game parancs paramétereit. A játék címéhez mindig csatoljuk az adott verziószámot is. Ezzel azt érjük el, hogy a kliens azt fogja hinni, hogy a szerver ami fut a hálózaton egy másik játékot szolgál ki.

-A fentebb elkészített játék „adatcsere” alprogramja nem csak helyi hálózaton, hanem internetes kapcsolat esetén is használható. Internetes kapcsolat és LAN között Dark Basic-ben csak a csatlakozás módjában van különbség (na és persze a csomagok súlyában :P ).

-Néhány könnyebben megvalósítható ötlet multiplayer játékok megvalósítására DBP –hoz: 2D-s vagy 3D-s autós gyorsulási verseny; egy 2D-s GTA klón (DeathMatch-ben :D ); online társasjátékok...

Végszó

A cikk írása során igyekeztem minél érthetőbb és lényegre törőbb lenni. Igaz, kicsit hosszabbra sikerült a cikk, mint amilyennek terveztem, de így legalább volt lehetőségem kitérni minden fontos részletre is. Az elkészített játék forráskódját, egy EXE fájlt, és minden egyéb fájlt mellékeltem, amit lentebb lehet majd letölteni. A példaprogram teszteléséhez a szerver létrehozása után újra futtasd le a programot! Ahányszor fut a játék egy időben, annyi játékos vesz részt a meccsben. Remélem sokaknak tetszik ez a kis iromány, és hasznát lelik majd benne a későbbi játékfejlesztői pályájuk során! :)

Üdvözlettel:

Seeting

Technical Director of Syntax Entertainment

Értékelés: 8.50

Új hozzászólás
Seeting          2006.08.27 15:34
Dehogynem.
peti634          2006.06.03 14:42
grta jó cik, FTP-be nem lehet feltölteni filét?
Seeting          2006.05.31 06:34
Ha én vagyok a szerver, akkor a játszmagazda neve Seeting.
A send net message integer-el pedig az a probléma, hogy nem lehet összefűzni, mint a stringet.
Asylum          2006.05.02 01:46
Yo cikk, végre ilyen is van Amugy miért nem send net message integer t használsz a pozicio küldésére? A stringes konvertálos nálam nem mindig ad pontos értéket
Ja és ha kliens vagyok akkor mi az hogy "...vagy a játszmagazda nevét" a csatlakozó ablakban tehát nem muszáj IP -t beirn8i hanem ööö ha mondjuk én vok a server akkor mit? Na jol megfogalmaztam.
Seeting          2006.04.20 02:08
Köszi!
Én még ilyen problémával nem találkoztam, de netes játékra minden képpen ajánlom én is a külön server perogi elkészítését...
sloth          2006.04.19 23:57
gratula, nagyon jó cikk!

csak egy gondom van vele: nekem annak idején mikor próbálgattam ez a " hogy a szerveren játszó összes játékosnak el szeretnénk küldeni a csomagunkat." nem igazán müködött. Vagyis a játékosok dirktbe nem tudták egymásnak küldeni a poziciójukat, nem látták egymást, csak a szervert. A megoldás az volt mindenki küldte a servernek, az meg átpasszolta mindenkinek. Ami igazábol nem gond, csak a szervert terheli kicsit pluszban, mert az átmenő csomagokat is kezelni kell. Vagyis célszerü egy külön server .exe -t csinálni, és nem beintegrálni a kliensbe.
Neked ilyen gondod nem volt ?