Ez a cikk azt mutatja be, hogyan lehet kódolni egy karakter sprite-ot, amely képes a kép hátterén sétálni a Golang, az Image csomag és a Fyne GUI eszközkészlet segítségével.
Nemrég követtem a Frank's Laboratory néhány érdekes oktatóanyagát a játékok JavaScriptben való kódolásával kapcsolatban. Úgy döntöttem, hogy az egyik egyszerű játékát Golangban kódolom a Fyne grafikus felhasználói felület eszköztárával ebben a cikkben JavaScript helyett.
Az itt bemutatott kód felépítése is némileg el fog térni a Frank's Laboratory eredetiétől, mivel a Golang a JavaScripttől eltérően működik.
Csakúgy, mint az oktatóvideójában, nem fogunk teljes játékot építeni. Egy karaktert mozgathat a háttérképen a billentyűzet nyílbillentyűivel. Ennek ellenére ez egy valódi játék kezdete lehet.
A játék eszközei
Alább láthatja a projektben használt kétjátékos elemeket.
Starwars hátteret és Chewbaccát, más néven Chewbaccát tartalmazó sprite lapot fogunk használni. – Chewie. Az ezekre az eszközökre mutató eredeti linkek megtalálhatók a Frank’s Laboratory oktatóanyagának YouTube-oldalán.
Miután letöltötte őket, ezeket a PNG-képes játékelemeket el kell helyezni egy ./assets
nevű mappába a Go kódot futtató mappa alatt.
Az általunk használt Golang-csomagok
- Fyne: A Fyne GUI Toolkit kezdőlapja itt található. Ha többet szeretne megtudni Fyne-ről, akkor korábbi cikkeim is érdekesek lehetnek, amelyeket itt és itt találtok.
- Kép: A szabványos könyvtárból származó alapképcsomag dokumentációja itt található.
- Idő: Ez egy szabványos Golang-könyvtár. Az Időcsomag dokumentációját itt találja.
A kódex áttekintése
A játékos és játék modellek
Az 1–16. sorban definiáljuk a Player
struktúrát.
A x
és y
mezők a játékos pozíciójára utalnak a játékban.
Az width
és height
a sprite lapon lévő egyes sprite méretei.
A frameX
és frameY
változók a sprite pozícióra vonatkoznak a sprite lapon x, illetve y irányban.
A cyclesX
mező a sprite-ok számát számolja X irányban a sprite lapon. Ezek a sprite-ok ismételten körbefutnak az elejétől a végéig, amikor a játékos sétál.
A upY
, downY
, leftY
, rightY
változók azokra a sprite-sorokra vonatkoznak, amelyek megfelelnek a játékos karakterének orientációjának.
A speed
változó az az összeg, amely hozzáadódik a játékos x vagy y pozíciójához.
A xMov
és yMov
mezők a játék során bizonyos billentyűk lenyomásával kerülnek beállításra.
A 18–24. sorban definiáljuk a Game
struktúrát.
A canvasWidth
és canvasHeight
mezők a háttér méretére vonatkoznak.
A fps
konstans a másodpercenkénti képkockákra vonatkozik, amelyekben a játékot futtatni szeretnénk.
Végül a then
az időmérésre szolgál – erről később.
PNG fájlok betöltése
A fenti kód betölti azokat a PNG-képeket, amelyeket játékeszközként használunk.
Az „ebben a cikkben” szereplő kódból lett adaptálva. Megváltoztattam, hogy kifejezetten PNG-képekkel működjön, és image.Image
típusú képet adjon vissza.
Lényegében megnyit egy PNG-képet tartalmazó fájlt, majd dekódolja azt. Ezen lépések mindegyikéhez van néhány alapvető hibakezelés.
A fájl bezárása késleltetett, így mindig megtörténik, amikor a program elhagyja a funkciót – függetlenül attól, hogy történtek-e hibák vagy sem.
Az eszközök, a modellek és a Fyne alkalmazás beállítása
Hozzon létre egy Fyne alkalmazást a főablak „Játék” címmel.
A PNG fájlok betöltése a fent definiált load()
függvény használatával.
Tudja meg, hány óra van most Unix ezredmásodperces stílusban – ez egy int64 szám. Mentse el now
néven.
Hozzon létre egy játékstruktúrát néhány releváns változó tárolására. Állítsa a szélességet 800-ra és a magasságot 500-ra. A fps
vagy képkocka/másodperc értéke 10. A then
mező jobbra now
van beállítva.
Végül a margin
mezőt 4-re állítjuk. Ezzel biztosítjuk, hogy lejátszónk ne érintse meg a háttérszegélyt.
Ezután kiszámítjuk a fpsInterval
értéket a fps
változó segítségével. Ezt a változót a játékhurokban fogják használni – erről később.
Ha ez megtörtént, létrehozunk egy Player struktúrát néhány fontos változóval. A játékos kezdőpozíciója a (100, 200)
pozícióban lesz, a (0, 0)
pedig az ablak bal felső sarkában lesz.
Minden játékos sprite mérete 40px
x 72px
lesz. A kezdő frameX
és frameY
is 0
lesz. A sprite lapsorok, amelyek a felfelé mutató nyílra, lefelé mutató nyílra, bal tömb és jobbra nyíl vannak leképezve em> billentyűk 4, 3, 0 és 1 lesznek. A sebesség 9
-ra van állítva. A xMov
és yMov
változás a x
és y
pozícióban egyaránt 0
.
Hozzon létre egy Fyne vásznat img
néven, és helyezze el a háttérképet. Ezután állítsa be a vászon méretét a háttér eredeti méretére.
Most hozzon létre egy üres képet sprite
néven, amely ugyanolyan méretű, mint a háttér a sprite rajzolásához, és helyezze egy Fyne vászonba. Ennek neve playerImg
.
Létrehozunk egy spriteSize
nevű változót is, amelyet később használunk. Ez a változó megtartja az egyjátékos sprite méretét.
Ezután adja hozzá a háttérvászon img
és a sprite vásznat playerImg
egy c
nevű Fyne-tárolóhoz. Ez a tároló az MaxLayout
elrendezés szerint rendezi a vásznakat. Ennek eredményeként mindkét vászon a maximális méretre lesz állítva. Erről az elrendezésről "itt" olvashat bővebben.
Ezután az w
ablak tartalmát a c
tárolóra állítjuk.
A legfontosabb eseményeket és a játékhurkot az alábbiakban tárgyaljuk.
Az w
ablak a képernyő közepén jelenik meg. Végül azt mondják, hogy mutasd meg és futtasd.
A legfontosabb események meghatározása
Itt a négy lehetséges kulcseseményt valósítjuk meg. Tekintettel arra, hogy a játékos karakterét a háttér egy részén négy irányba kell mozgatnia, meg kell valósítanunk ezeket a lehetőségeket.
Először csatolunk egy Fyne kulcs eseménykezelőt az w
ablak vásznához az Canvas().SetOnTypedKey()
függvények segítségével.
Mind a négy esetről egy switch utasítás gondoskodik. "Itt" megtalálja az egyes billentyűzetbillentyűk összes definícióját.
Minden egyes lehetőségnél ellenőrizzük, hogy a játékos karakter pozíciója bizonyos határokon belül van-e. Itt ne felejtsük el feltüntetni az game.margin
értéket, ha alkalmazható.
A mozgás irányától függően az player.xMov
vagy player.yMov
player.speed
pozitív vagy negatív értékre van állítva. Ezenkívül a megfelelő sprite-sort a player.frameY
beállításával választja ki az adott sorindexhez.
A játékhurok
Ez a játékhurok. A program ezen része egy végtelen ciklust tartalmaz.
A ciklus minden iterációjához 1 ezredmásodperces szünet tartozik. Ez adott esetben hosszabb szünetre módosítható, ha szükséges.
Ezután megkapjuk a megfelelő időt now
és átalakítjuk int64
Unix ezredmásodpercekre. Használjuk arra, hogy megtudjuk, mennyi idő telt el elapsed
a legutóbbi game.then
beállítás óta.
Ha a elapsed
értékkel rendelkező idő nagyobb, mint a fpsInterval
, akkor belépünk a tényleges játékmechanika ágba. Csak akkor lépünk be ebbe az ágba, ha fpsInterval
elhaladt, hogy elérjük a megfelelő játéksebességet.
Ezután a game.then
-et now
-re állítjuk.
Ahhoz, hogy egy sprite-ot kinyerhessünk a sprite-lapról, szükségünk lesz egy spriteDP
kiindulási pontra és egy sr
nevű téglalapra, amelynek mérete spriteSize
, amely lefedi az adott sprite-ot.
Ahhoz, hogy ezt a sprite-ot a háttér tetejére helyezzük, hasonlóképpen szükségünk van egy dp
referenciapontra a játékos számára – a lejátszó x és y koordinátái alapján – és egy téglalapra, ahová a sprite-ot meg kell rajzolni. Ez a téglalap is spriteSize
méretű.
Most először töröljük a sprite
képet image.Transparent
kitöltésével. Ha ez megtörtént, átvihetjük az adott sprite-ot a playerSprites
sprite lapról a sprite
képre, és ebből a canvas.NewRasterFromImage()
segítségével új rasztert készíthetünk.
A játékhurok utolsó részében meghatározzuk a játékos x
és y
koordinátáit, valamint a player.frameX
értéket a következő ciklushoz, ha akár a player.xMov
, akár a player.yMov
értéke nem nulla. Ezenkívül a player.frameX
módosításával a sorban lévő sprite-ek között is körbejárunk.
Ha a mozgás nulla volt, akkor a player.frameX
nullára lesz állítva, ami az első sprite a sorban. Ez a szellem egyben a karakter álló helyzetét is képviseli.
Végül a c
tároló frissül, hogy a képek frissüljenek az ablakban.
A teljes kód
Hivatkozások
Sau Sheong „Képekkel való munka a Go-ban”
„The Go image/draw csomag”, Nigel Tao