játék készítése java-banmidra.uni-miskolc.hu/jadox_portlets/documents/document_15012... ·...

64
Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai tanszék Játék készítése Java-ban Szakdolgozat Készítette: Búr Béla N5GIZ2 3860 Encs, Vadvirág út 20. Tervezésvezető: Elek Tibor Informatikai tanszék

Upload: lyduong

Post on 06-Feb-2018

216 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Miskolci Egyetem

Gépészmérnöki és informatikai kar

Automatizálási és kommunikáció-technológiai tanszék

Játék készítése Java-ban

Szakdolgozat

Készítette:

Búr Béla

N5GIZ2

3860 Encs, Vadvirág út 20.

Tervezésvezető:

Elek Tibor

Informatikai tanszék

Page 2: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Tartalom

I. Bevezetés ..................................................................................................... I-1

II. A Java és a játékfejlesztés ........................................................................... II-3

Grafikus csomagok a Java-hoz ........................................................................ II-4

III. Java2D ..................................................................................................... III-5

Mire való a Java2D? ....................................................................................... III-5

A megjelenítés alapjai ..................................................................................... III-5

Geometriai alakzatok ...................................................................................... III-5

Képek ............................................................................................................. III-7

Grafikai elemek megjelenítése ........................................................................ III-8

Szövegek ...................................................................................................... III-12

IV. Swing ...................................................................................................... IV-14

Általános ismeretek ...................................................................................... IV-14

V. Hangfájlok lejátszása a Java-ban, a Java Sound API ................................ V-16

A Java Sound-ról általánosan ........................................................................ V-16

A javax.sound.sampled csomag .................................................................... V-16

VI. Java és az animáció ............................................................................... VI-19

Animációs alapok .......................................................................................... VI-19

Bufferelés és teljes képernyős mód a Javaban ............................................. VI-21

VII. Az elkészült program ismertetése .......................................................... VII-23

A játék rövid bemutatása ............................................................................. VII-23

Az elkészítés során felmerült feladatok ....................................................... VII-24

Felhasznált programok ................................................................................ VII-27

Az osztályok ismertetése ............................................................................. VII-27

GameFrame ............................................................................................. VII-27

GameExecutorThread .............................................................................. VII-28

A játék képernyői ...................................................................................... VII-29

Page 3: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

A játék elemei ........................................................................................... VII-38

A pályát létrehozó és kezelő osztályok: ................................................... VII-48

A Field interfész, és a hozzá tartozó osztályok: ....................................... VII-50

Segédosztályok ........................................................................................ VII-51

A játék folyamatainak leírása ....................................................................... VII-54

Futási szálak ............................................................................................ VII-54

Egy periódus leírása ................................................................................ VII-55

VIII. Összefoglalás ....................................................................................... VIII-57

Page 4: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai
Page 5: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

I-1

I. Bevezetés

A Java napjaink egyik legnépszerűbb programozási nyelve, azonban a

játékfejlesztés kapcsán csak ritkán hallani róla.

A szakdolgozat feladatom kigondolásakor az elsődleges célom Java, a Java2D és

az objektum-orientált programok tervezésének bemutatása volt. Azért

választottam ehhez a játékfejlesztést, mert úgy gondoltam, hogy egy ilyen

összetettebb feladat során rengeteg, máshol is előforduló probléma merülhet fel,

ezért az elkészítés során szerzett tapasztalatokat talán később is hasznosíthatom.

A nyelv az egyre inkább előtérbe kerülő, és véleményem szerint még mindig

rengeteg kiaknázatlan lehetőséget tartalmazó indie játék1 területen ideális

választás lehet, mivel elég absztrakt ahhoz, hogy egyszerűen és gyorsan stabil

kódot írjunk, és elég hatékony ahhoz, hogy egy ilyen projekt szükségleteit

kielégítse.

A játék egy kétdimenziós platformer lesz, ami manapság újra népszerű 8-bites

korszakot fogja megidézni. A játékmenet abból fog állni, hogy egy figurát irányítva

különböző akadályokon és ellenségeken átjutva, platformokon ugrálva kell eljutni a

célig.

A forráskódot úgy szeretném megírni, hogy az egyes feladatok jól elkülönüljenek

egymástól, illetve átlátható, és könnyen bővíthető legyen, ezek mellett a játék

egyes elemeit, a kód átírása, vagy ismerete nélkül is egyszerűen meg lehessen

változtatni.

Az ilyen típusú játékhoz folyamatos animációt, a bemeneti (billentyűzet), kimeneti

(monitor) perifériák kezelését, hangok lejátszását, illetve alapvető grafikai

objektumok megjelenítését kell biztosítani.

A dolgozat első felében a nyelv és a játékfejlesztés sajátosságairól írok, és

bemutatom a felhasznált Java API-kat, amik a JDK2 részei:

A Java2D-t, amivel a játék grafikai elemeit valósítottam meg

A Swing alapjait, ami egy GUI3 felületek létrehozására alkalmas API

A Java Sound API-t, amit a játék hangjainak lejátszásáért felelős

1 Kis, jellemzően független fejlesztőcsapat által készített játék, játékkiadók pénzügyi támogatása

nélkül. 2 Java Development Kit: a nyelv hivatalos fejlesztőcsomagja

3 A Graphical User Interface, vagyis a grafikus felhasználói felület rövidítése.

Page 6: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

I-2

Ezek után a számítógépes játékok mozgókép-megjelenítésének alapproblémáit

írom le, bemutatva a Java által nyújtott megoldásukat.

A szakdolgozat második része a konkrét programról fog szólni: először az

elkészült játékot írom le röviden, majd az elkészítés során felmerült problémákat,

és azok megoldásait ismertetem. A következő fejezetben felvázolom a projekt

osztályainak struktúráját, és a működésüket. A futási szálak, illetve a játék egy

ciklusa alatt történő események leírásával zárom a játék ismertetését, majd az

összefoglalóban összegzem a megszerzett tapasztalatokat.

Page 7: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

II-3

II. A Java és a játékfejlesztés

Sokan gondolják, hogy csak azért nem használják a nyelvet a játékiparban,

mert nem lehet vele elég „gyors” programot írni. Ez az állítás régebben megállta a

helyét, azonban manapság, a folyamatos fejlődés következményeként, a

teljesítményi mutatói egyesek szerint megközelítették/elhagyták az iparban

preferált C/C++ nyelvekét. (Davison, 2005)

Ha ez igaz is, akkor sem kell a közeljövőben jelentős változást várni ilyen téren,

mivel az Java-ra való átállást rengeteg más, külső tényező is gátolja, olyanok,

mint:

Mivel a másik két nyelv sokkal inkább elterjedt az iparágban,

ezekben tanultak meg fejleszteni a legjobb szakemberek. Rengeteg

időbe és pénzbe kerülhet, míg az eddig jól bevált módszereket

újragondolják, és a Javahoz igazítják.

A legtöbb konzol, és az Iphone sem tartalmaz JVM4-et, ezért

konzolos kiadásnál nem tudnák újra használni a PC verzióhoz megírt

kódot, egyszerűbb a C++ verziót átírni.

A játékfejlesztéshez használt két legnépszerűbb API, a DirectX és az

OpenGL csak mérsékelten támogatják a Java-t, emellett az ezeket

használó motorok is a másik két nyelvre lettek írva.

Az elsődleges alkalmazási helye ezen a területen az Android-ra való fejlesztés,

ennek egyszerű az oka: ez a platformon alkalmazott elsődleges nyelv. (Ismeretlen,

Why is'nt Java more widely used for game development)

Az előbb említett hátrányok a független, és az anyagi szempontokat

másodlagosként kezelő projektnél nem olyan lényegesek, fontosabb a gyorsan

megírt, mégis stabil és átlátható kód, emellett az itt szintén kevésbé fontos

hatékonyság sem feltétlenül rosszabb, mint más nyelveknél. Ilyen független

projekt volt például a Minecraft, ami Markus Persson nevéhez fűződik: ez a kiadás

után nem sokkal hatalmas siker lett, és ma már kapható Xbox 360-ra, Android-ra

és iOS-re is (Ismeretlen, Minecraft Wikipédia oldala) .

4 Java Virtual Machine: Java Virtuális Gép, fő feladata a kód futtatása az adott platformon

Page 8: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

II-4

Grafikus csomagok a Java-hoz

Manapság a számítógépes játékok körében a két legnépszerűbb API az OpenGL

és a DirectX, amik 2D és 3D grafika megjelenítésére szolgálnak, hardveres

gyorsítás segítségével. Míg a DirectX a Microsoft cég csomagja, és a cég

termékeihez lett írva, addig az OpenGL platformfüggetlen, és a legtöbb platformon

létezik rá megvalósítás. Az általam használt Java2D mellett a játékkészítők

körében népszerűek az alábbi API-k:

Java OpenGL: Az OpenGL egyik Java implementációja, ami a legtöbb

OpenGL funkciót elérhetővé teszi a JNI5-n keresztül. (Ismeretlen, Java

OpenGL Wikipédia oldala)

LightWeight Java Gaming Libraly: Az LWJGL egy Java

játékfejlesztőknek készített csomag, ami nagy teljesítményű,

platformfüggetlen könyvtárak használatát teszi elérhetővé 3D játékok

készítéséhez. Segítségével lehetőség van olyan eszközöket kezelni, mint a

gamepad, a joystick-ok, vagy a kormány. A csomagot alapnak szánták

összetettebb könyvtárak, és játékmotorok létrehozásához. (Ismeretlen,

LWJGL weboldal)

Java3D: A Java3D egy az Oracle által fejlesztett, 3 dimenziós grafika

kezelésére írt API, ami platformtól függően használja a JOGL-t, az

OpenGL-t és a Direct3D-t.

A felsorolt csomagok nyílt forráskódúak, és BSD licenc alatt terjesztik őket.

5 Java Native Interface: egy keretrendszer, ami lehetővé teszi a Java és más alacsonyabb szintű

programozási nyelvek, mint a C vagy a C++ együttműködését.

Page 9: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

III-5

III. Java2D

Mire való a Java2D?

A Java2D nevű API kétdimenziós grafika kezelésére használatos osztályok

gyűjteménye, amely lehetővé teszi az alakzat, a szöveg, kép és egyéb grafikai

elemek megjelenítését. Segítségével felhasználói felületek, rajzprogramok, vagy

bármilyen más grafikai elemeket megjelenítő programok készíthetőek.

A megjelenítés alapjai

A Java2D objektumok az „user space” (~felhasználói terület) nevű

koordinátarendszerben definiálhatóak, ennek az értékeit tárolják. A megjelenítő

eszközök közti különbségek „user space” szinten nem számítanak, láthatatlanok a

program számára. A megjelenítés során a renderelő rutinok a user space

koordinátákat „device space” (~eszköz koordinátarendszer) koordinátákká

alakítják: a device space a megjelenítő eszköz saját koordinátarendszere: ez az

eszköz lehet egy ablak a képernyőn, a monitor, de akár a nyomtató, vagy

bármilyen más kimenet. Az alapértelmezett transzformációnál (így a monitorra

rajzolásnál is) a 0,0 koordináta a bal felső sarok, és az x, y koordináta pedig

jobbra, illetve lefelé növekszik. Általánosan integer változókkal definiálják az

értékeket, de lehetővé tették a double, vagy float használatát is erre a célra. Egy

elem akkor kerül megjelenítésre, amikor egy paint vagy update metódus hívódik

fel a megfelelő Graphics osztályú kontextussal. Ez egy absztrakt típus, a Java2D

által használt implementációja a Graphics2D, ami hozzáférést biztosít az API

kiterjesztett grafikai és renderelő lehetőségeihez.

Geometriai alakzatok

A Java2D API széles választékot nyújt megjeleníthető geometriai elemekből,

emellett lehetőség van a kombinálásuk által saját alakzatok létrehozására. Ezek a

java.awt.geom csomagban találhatóak. Definiálásukhoz elengedhetetlen

következők ismerete:

Page 10: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

III-6

Point2D: egy koordinátát reprezentáló osztály. Ez a fogalom nem egyezik

meg a pixellel: egy pontnak nincs kiterjedése és színe, ezért nem lehet

renderelni.

Shape: interfész: egy olyan geometriai alakzatot definiál, aminek van

körvonala és területe.

Ez utóbbit implementálják az alapvető alakzatok:

Line2D: egy vonal adatait tárolja. A koordinátáit double-ként kapja meg. A

végpontok metódusok segítségével módosíthatóak.

QuadCurve2D: exponenciális görbe. Legegyszerűbben 3 pont segítségével

határozható meg.

CubicCurve2D: ezt a görbét egy harmadfokú egyenlet írja le, beállítható 4

pont segítségével.

Rectangle2D: egy négyzet. Deklarálásánál a bal felső sarkának

koordinátáját, a szélességét, és a magasságát kell megadni.

RoundRectangle2D: lekerekített sarkú négyzet. A négyzet adatai mellett a

sarokszögek szélességét és magasságát is meg kell adni a definiálásánál.

Arc2D: Egy ív rajzolására alkalmas, ami egy ellipszis részlete. Leírható egy

befoglaló négyzettel, a kezdő szöggel, az ív hosszúságával és a lezárással.

Lezárás típusok:

o Open: csak a szög ívét rajzolja meg.

o Chord: a szög 2 végét összeköti.

o Pie: a szög 2 végét a középponttal köti össze.

RoundRectangle2D: lekerekített sarkú négyzet.

Ellipse2D: ellipszis.

QuadCurve2D: négyzetes görbe. Két pont és egy kontroll-pont definiálja.

CubicCurve2D: Két végpont és két kontrollpont segítségével definiált

görbe.

A felsorolt osztályok absztraktak, viszont mindegyik tartalmaz Float és Double

nevű belső osztályt, amik a leszármazottjaik, és példányosíthatóak.

Összetettebb alakzatokat a következő osztályok segítségével lehet létrehozni:

GeneralPath: egy útvonal, amit vonalakkal és görbékkel lehet definiálni.

Page 11: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

III-7

Area: Shape objektumokból kiindulva definiál új alakzatokat, olyan

műveletekkel, mint a kivonás, a metszet vagy az unió.

Képek

A Java2D-ben a képek adatait általában négyzet alakú kétdimenziós pixel-tömbök

írják le. Az egyes pixeleknek a színe van letárolva, pozíciójukat pedig a tömbben

való elhelyezkedésük adja meg. A közös absztrakt ősosztályuk az Image, aminek

a leggyakrabban használt leszármazottja a BufferedImage: ennek két fontos

mezője van:

Az egyik egy ColorModel osztályú objektum, ami azt adja meg, hogy a

pixeladatokból hogyan képződjenek a színek.

A másik pedig a Raster osztály egy példánya, ami a következő feladatokat

látja el:

o a kép négyzetes koordinátáit tárolja

o karbantartja a képadatokat a memóriában

o lehetőséget biztosít több részkép készítésére egy képadatokat

tartalmazó bufferből

o metódusokat nyújt meghatározott pixelek közvetlen eléréséhez

A képek beolvasásának legegyszerűbb módja az ImageIO osztály read

metódusának használata: paramétere lehet InpustStream, File vagy URL.

Visszatérési értéke egy BufferedImage. Kezeli a GIF, PNG, JPEG, BMP és WBMP

formátumokat, és leszármaztatható, ezáltal újabb típusok kezelését is meg lehet

valósítani.

Működése: az ImageIO értelmezi a fájl formátumát, majd dekódolja

BufferedImage-é, amit már a Java közvetlenül is használhat.

Az API lehetőséget nyújt beépített szűrők alkalmazására: ezek ősosztálya a

BufferedImageOp. Ha egy ilyet megkap a Graphics2D objektum a rajzoló

metódusnál, akkor az eredeti kép helyett egy, az eredeti képre alkalmazott

algoritmus eredményeként kapott képet jeleníthetünk meg. Néhány fontosabb

szűrő osztály:

Page 12: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

III-8

RescaleOp: a kép színrendszerének megfelelően lehet a pixelek színét

változtatni, tónusokat erősíteni, vagy esetleg átlátszóságot állítani (ARGB

színrendszer esetében).

ConvoleOp: élesíteni és elmosni lehet vele.

AffineTransformOp: pixelek pozícióját változtatja Affine transzformációk

segítségével.

Grafikai elemek megjelenítése

Az API által definiált geometriai elemek megjelenítése egy Graphics2D

objektumon történik, aminek az ehhez kapcsolódó metódusait 2 részre lehet

osztani:

Megjelenítő metódusok: paraméterként egy Shape, Image vagy String objektumot

kapnak, amit az előzőleg beállított megjelenítési attribútumok alapján renderelnek:

draw: egy alakzat körvonalának megjelenítése.

fill: alakzat megjelenítése a határvonalain belül eső területek

beszínezésével.

drawString: Egy String-ként megadott szöveg megjelenítése. A font

attribútum felhasználásával a String elemet alakzatokká konvertálja, amikre

a fill metódust hívja meg. Erről bővebben a „Szövegek” részben.

drawImage: kép megjelenítése. Mivel a kép nem tartalmaz UserSpace

koordinátákat, ezért a bal-felső sarok koordinátáját meg kell kapnia.

Megkaphat egy ImageObserver paramétert is, ami a kép betöltésekor jelez

az alkalmazásnak, azonban ez a BufferedImage esetében nem szükséges:

itt az értéke lehet null.

Az 1:1-es leképzés mellett olyan műveleteket is el lehet végezni, mint a

nyújtás, a vágás vagy a szűrés. Paraméterként, a forrás (kép) és cél (user

space) koordináták megadásával meg lehet megadni, hogy a Graphics

saját koordinátarendszerében hol jelenjen meg az adott képrészlet. Ez a

metódus kaphatja meg paraméterként a BufferedImageOp egy példányát.

Megjelenítést módosítók: a megjelenítő metódusok viselkedését lehet velük

beállítani. Ezek közül néhány fontosabb:

Page 13: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

III-9

setStroke: a rajzolási körvonalak vastagságát, csatlakozásuk módját állítja

be. Paraméterként egy Stroke interfészt implementáló osztályt vár. Az

egyik leggyakrabban használt ilyen a BasicStroke nevű, amivel a

következő tulajdonságokat lehet beállítani:

o width: vonalvastagság

o join: szakaszok csatlakozásainak megjelenítése. 3 konstans értéket

vehet fel:

1. ábra – Csatlakozási típusok

A JOIN_MITER beállításhoz tartozhat egy miterlimit nevű

paraméter, ami azt adja meg, hogy mekkora az a maximum szög,

aminél még nem vágja le a sarkakat. Az értéknél nagyobb szögekre

a JOIN_BEVEL megjelenítés érvényes.

o cap: szakaszok lezárása:

2. ábra – Lezárási típusok

o dash: a vonal szaggatási mintája. Egy float tömbbel adhatjuk meg,

ami az egyes szakaszok és szakaszközök hosszúságát jelzi.

3. ábra – a tömb értékei: 5f,10f,15f,25f,35f,45f.

A dash_phase-el ezt a szaggatást eltolhatjuk:

4. ábra - Az előző szaggatás 15f értékű eltolása. Ugyanaz jelenik meg, mint ha 0 eltolással ezt a tömböt adtuk volna meg: 15,25f,35f,45f,5f,10f.

Az interfész fontos metódusa a createStrokedShape nevű metódust, ami

egy alakzatot kap paraméterként, és a Stroke által készített körvonalának

körvonalát adja vissza egy másik alakzatként. Ha az eredményt kitöltjük a

Page 14: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

III-10

rajzolás színével, a megjelenített kép ugyanaz lesz, mint ha beállítanánk a

Stroke-ot és utána meghívnánk a draw-t az eredeti alakzatra.

setPaint: Egy Paint interfészt implementáló osztályt vár paraméterként. Ez

határozza meg, hogy a kitöltő (fill) műveletek során a belső pixeleket milyen

színre állítsa. Néhány alapvető implementáció:

o Color: az összes érintett pixelt a megadott színre állítja. Egy kör

kitöltése sárga színnel egy sárga színű kört eredményez.

o GradientPaint: két különböző színű pont közötti egyenletes

színátmenettel tölt ki.

o TexturePaint: egy kép és egy négyzet segítségével ismétlődő mintát

generál. A négyzet a teljes kép egy előfordulását határozza meg,

ehhez lesz igazítva a többi ismétlődése

setComposite: a rajzolóműveleteknél a legenerált képpontadatokat

forrásként, a már kirajzolt képpontokat pedig célként értelmezve az

általános megfeleltetés az, hogy a forráspixelek felülírják a célt, de a

kompozíciók megengednek másféle megfeleltetést is: megkapják a forrás

és a kirajzolt pixelek adatait, amikből olyan képpontokat generál, amikben

ezek hatással vannak egymásra. Egy Composite interfészt implementáló

osztályt vár paraméterként, aminek az egyik leggyakrabban használt

implementációja az AlphaComposite nevű, ami a megjelenítendő elemet

áttetszővé tudja tenni.

setTransform: beállítja a transzformációs attribútumot, amivel mozgatni,

nyújtani, nyírni lehet az objektumokat megjelenítés során. Egy

AffineTransform osztályú objektumot vár, ami Affine transzformációt ír le:

ez olyan átalakítás, aminek során a párhuzamos vonalak párhuzamosak

maradnak.

A transzformációt létre lehet hozni osztályszintű gyártó metódusokkal,

melyek olyan példányt adnak vissza, aminek csak az egyik paramétere van

beállítva.

Az összetettebb transzformációk megadásánál a többi attribútumot is be

kell állítani, vagy az osztály konstruktorában megadni őket.

Népszerűbb osztályszintű gyártó metódusok:

Page 15: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

III-11

o getRotateInstance: forgatási transzformációt ad vissza, ami

paraméterként a forgási szöget várja.

o getScaleInstance: nyújtási transzformáció, ami a nyújtási arányt

várja.

o getShearInstance: vágási transzformáció, aminek módját 2 double

határozza meg.

o getTranslateInstance: mozgatási transzformáció: az x és y

tengelyen való eltolást várja paraméterként.

A létrejött transzformációkat a concatenate nevű metódussal tudjuk

összefűzni.

setClip: egy alakzat, vagy 4 pont segítségével beállítja a rajzolási

célterületet.

clip: az aktuális célterületet úgy módosítja, hogy az megegyezzen a

paraméterként kapott területtel való metszetével.

setFont: a beállított Font objektum határozza meg hogyan jelennek meg a

string szövegek a képernyőn. A metódus és az osztály részletesebb leírása

a „Szövegek” fejezetben található.

setRenderingHint: a renderelési folyamat működését a Graphics2D egy

RenderingHints objektumban tárolja. A kívánt beállításokat 2 módon

adhatjuk meg:

o létrehozhatunk egy RenderingHints objektumot, amit a metódusnak

átadva lecseréli az aktuális objektumot

o a metódus megkaphat kulcs-érték párt is, amivel az aktuális

objektumnak csak a kívánt paramétereit változtatja

Az osztálynak azért Hints, vagyis tanácsok a neve, mert nem feltétlenül

fognak életbe lépni a kívánt változtatások. Ha valamelyiknek nem

lehetséges a megvalósítása, azt ignorálja a JVM. A leggyakrabban beállított

paraméterek:

KEY_ANTIALIASING: az élsimítást lehet vele ki- és bekapcsolni, ami az

alakzatok határán kialakuló „fűrészfogas” részt simítja árnyalással és az

elrendezések módosításával.

Page 16: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

III-12

5. ábra - VALUE_ANTIALIAS_ON 6. ábra - VALUE_ANTIALIAS_OFF

KEY_DITHERING: ha be van kapcsolva, akkor a színábrázolási korlátokat,

a pixelek átcsoportosításával és a pixelsűrűség változtatásával

kompenzálja a renderelő, a látás sajátosságait kihasználva.

KEY_INTERPOLATION: a képekre alkalmazott affine transzformációs

torzítások szabályait adja meg.

Szövegek

A szövegek megjelenítésének legkézenfekvőbb módja a Graphics osztály

drawString metódusa, ami a paraméterként kapott szöveget az előzőleg beállított

betűtípus attribútum alapján képzi a megjelenítendő alakzatokat, aminek a neve

font és a Font osztály, vagy annak egy leszármazottjának példánya.

Azokat az alakzatokat, amikből a kész alakzatokat képzi, glyph-eknek hívja a Java

dokumentáció. Egy karakter állhat több ilyenből is (pl. ékezetes karakterek), de

néhány esetben több karakter jelenik meg egy glyph-ként (pl. a „fi” szó helyett ϕ).

A Font osztály értelmezhető ilyen elemek gyűjteményeként. Az egyes glyph-ek

ugyanolyan tulajdonságokkal egy betűtípust (pl. Arial félkövér dőlt) alkotnak, az

egyes betűtípusok csoportja pedig betűtípus-családot (pl. Arial).

A betűtípusokhoz 3 attribútum tartozik:

Logikai név: egy rendszeren belüli betűtípushoz tartozik. Ilyen például az

„Arial félkövér dőlt”. A getName metódus segítségével lehet lekérdezni.

Betűtípus család név: a tipográfiai jellemzőket adja meg. Az előző példában

szereplő Font betűtípus családja az „Arial”. A getFontFamilyName adja

vissza.

Betűtípus név (font face name): azonosítja a betűtípust a rendszeren belül.

Gyakran megegyezik a logikai névvel. Ezt kell használni a betűtípusra való

hivatkozáskor. A getFontName metódussal lehet lekérdezni.

Az objektumról további információkat lehet megtudni a getAttributes által

visszaadott Map-ből.

Page 17: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

III-13

Az megjelenítés során fontos lépés a mérés: az ebből kapott információk

szükségesek a későbbi Text műveleteknél is, mint például az írásjelek

pozícionálása, vagy a kijelölés. A glyph-ek alakja, mérete és pozíciója sokszor

környezetfüggő: például a kézírásos betűtípusoknál számít az, hogy milyen

betűhöz kapcsolódnak, ettől függően többféle kép tartozhat ugyanahhoz a

betűhöz.

A Java-ban a szövegek a memóriában találhatóak logikai sorrendben rendezve:

aszerint, hogy melyik karaktert írjuk és olvassuk. Ez nem mindig egyezik a vizuális

rendezéssel: függ az aktuális nyelv szabályaitól.

Ha nem „monospaced” betűtípussal dolgozunk, akkor a karaktereknek különböző

szélességük lehet, tehát az elhelyezés során számít az is hogy milyen karakterek

szerepelnek a szövegben, nem csak az, hogy mennyi.

Szerepelhetnek egymás mellett különböző betűtípusok és stílusok, ebben az

esetben ugyanannak a karakternek is lehet többféle kiterjedése, tehát a

rendezésnél figyelembe kell venni a típusokat is. A TextLayout osztály ezt elvégzi

a programozó helyett, de lehetőség van saját rendezésre is.

Egy összefüggő többsoros szöveg kiíratását a megadott szélességű területre a

LineBreakMeasurer osztály segítségével tehetjük meg. A megjelenítendő

szöveget, és annak attribútumait tárolhatja az AttributedString osztály, amin az

AttributedCharacterItarator használatával megy végig, majd az egyes sorokat

TextLayout objektumként adja vissza, ami megváltoztathatatlan, stílussal

rendelkező karakteradatokat tartalmaz. (Ismeretlen, Oracle Java dokumentációk)

Page 18: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

IV-14

IV. Swing

Általános ismeretek

Amikor az első Java verziót kiadták, a felhasználói felületek létrehozásához

nyújtott funkciók meglehetősen szűkösek voltak. Az erre a feladatra hivatott

Abstract Windows Toolkit (röviden: AWT) minden elemet támogatott, amit egy

HTML-formba be lehet építeni, és ezek mellé néhány fontosabb objektumot,

viszont komplexebb felületek létrehozása nehézkes volt a használatával. Erősen

függött a futtatókörnyezet ablakozó rendszerétől, ezért a hordozhatósággal járó

előnyök mellett nem lehetett egységes megjelenítést elérni.

Ezen problémák megoldását az 1997-ben a Java Foundation Classes részeként

kifejlesztett Swing megjelenésével orvosolták, amiben már olyan összetettebb

komponensek is szerepeltek, mint a táblázat vagy a lapfülek.

Létrehozásukat az tette lehetővé, hogy az új API pehelysúlyú komponenseket

használ, vagyis csak kis mértékben függ a futtatókörnyezet ablakozó rendszerétől.

Az egész Java-ban lett írva, és csak saját objektumokkal dolgozik, tehát az

vezérlésüket is teljes körűen birtokolja. A Java2 megjelenésével a JDK része lett a

csomag.

A Swing model-view-controller nevű architektúra szerint építi fel a

komponenseit.

Ebben a model az elem értékeiről tartalmaz információkat. Például egy csúszkánál

tartalmazhatja a kurzor aktuális értékét, a minimum és maximum értékeket, illetve

a léptetés „durvaságát”, azaz hogy milyen pontossággal lehet állítani az értéket. A

model adatai mindig függetlenek attól, hogy a komponens hogy jelenik meg a

képernyőn.

A view azt adja meg, hogy a komponens hogyan jelenjen meg. Az megjelenítés

módját különféle LookAndFeel objektumokkal lehet beállítani. A népszerűbb

operációs rendszerek design-jának megfelelő osztályok a csomag részei.

A controller azt adja meg, hogy a komponens hogyan reagál a külső

eseményekre. Ilyen esemény például egy egérkattintás, vagy egy másik

komponens értékének beállítása.

Page 19: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

IV-15

Egy swing felület általános működtetéséhez több szálat kell alkalmazni. Ezek 3

csoportba sorolhatóak:

indító szál: a Swing programokban az indító szál dolga általában az

inicializálást végző Runnable objektum létrehozása, és annak felíratása az

eseménykezelőre.

eseménykezelő szál: az eseménykezelő kódot futtatja. A felhasználói felület

változásait ebben a szálban érdemes intézni a konkurenciaprobléma

elkerülése érdekében.

egyéb háttér-szálak: ha egy Swing programnak hosszú futási idejű feladatot

kell elvégeznie, nem célszerű az eseménykezelő szálban megtennie,

hiszen az események sorban dolgozódnak fel. Új szálat indítva a feladat

elvégzésére, pedig a felhasználói felület módosítása okozhat konkurencia

problémát. Ezért hozták létre egy SwingWorker osztályt, amely egy

háttérszálban végzi el a kívánt feladatot, de lehetőséget ad a felhasználói

felület módosítására, amelyet az eseménykezelő szálban végez el.

Page 20: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

V-16

V. Hangfájlok lejátszása a Java-ban, a

Java Sound API

A Java Sound-ról általánosan

Az elkészítendő játék hangjainak lejátszásához a Java Sound API-t választottam.

Ez egy alacsonyszintű API, ami a hang bemeneteket és kimeneteket vezérli. A

hozzá tartozó csomagok:

javax.sound.sampled: ebben a digitális felvételek lejátszásához,

felvételéhez és keveréséhez szükséges osztályok vannak. Ezek azok az

adattípusok, amik a hanghullámokból bizonyos időközönként vett diszkrét

értékű mintákból állnak. A játékban ezt a csomagot használtam.

javax.sound.midi: a MIDI-khez tartozó műveleteket biztosítja. A MIDI adatok

nem magát a hangot írják le, hanem a létrehozásához szükséges

eseményeket. Ilyen például a számítógépre kötött MIDI eszköz egy

billentyűjének lenyomása.

javax.sound.sampled.spi, javax.sound.midi.spi: ezek új audio és MIDI

eszközök készítésére alkalmasak, melyeket a Java Sound API

kiegészítéseként lehet használni. Olyanokat, mint egy MIDI szintetizátor,

egy saját fájlformátumot feldolgozó osztály, vagy egy konverter.

A javax.sound.sampled csomag

A fő feladata az, hogy az audió anyag bájtjait a rendszerből- és a rendszerbe

mozgassa. Ez magában foglalja az audio be- és kimenetek nyitását, és a bufferek

menedzselését.

Az API megkülönbözteti egymástól az adat- és a fájlformátum fogalmakat. Az

adatformátumot egy AudioFormat objektum adja meg, ami a következő

attribútumokat kezeli:

kódolás (általában PCM)

csatornák száma (1: monó, 2: sztereó)

mintaszám (egy csatornára egy másodperc alatt küldött minták száma)

Page 21: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

V-17

egy mintában a bitek száma

keret nagyság

keret nagysága byte-okban

byte rendezés

A fájlformátumok az audio fájl struktúráját adják meg. Ez egy AudioFileFormat

objektumban van tárolva, és a következőket tartalmazza:

fájl típus (pl.: WAV)

fájl hossza bájtokban

az audio adatok hossza, keretekben megadva

az adatokhoz tartozó AudioFormat objektum

Az adatok olvasására különböző fájlformátumokból az AudioSystem osztály ad

lehetőséget. Az adatokból lehetséges AudioInputStream objektum készítése, ami

az InputStream leszármazottja: azzal egészíti ki, hogy kezeli az adatformátumhoz

kapcsolódó adatokat.

Az API-ban az audioeszközöket a Mixer objektum képviseli. Ez lehet például egy

hangkártya elérhető szolgáltatásainak együttese, vagy egy beépített mikrofon.

Ennek a feladata a ki- és bemeneti adatfolyamok kezelése.

A különféle csatornák a Line, (vonal) interfészt implementálják. A csatorna lehet

egy Mixer, de egy port (pl. fülhallgató kimenet), vagy akár egy adatfolyam is. Az

interfész biztosítja a következő műveleteket:

a csatornán áthaladó adat kezelése, manipulálása

nyitott és zárt státusz kezelése

események kezelése: esemény a nyitás és a zárás, de az egyes

implementációk más típusúakat is kezelnek. Amikor egy esemény

generálódik, azt elküldi az összes olyan objektumnak, ami fel van íratkozva

a vonal eseményfigyelőjére.

A Line interfésznek van egy belső osztálya: Line.Info . Ez arra szolgál, hogy

információkat adjon vissza az aktuális objektumról. Az implementáló osztályok ezt

leszármaztathatják, hogy specifikus információkat is tároljon.

Az audióeszközök felderítésére a legegyszerűbb mód az AudioSystem

használata: lekérdezi az elérhető Mixer objektumokat, amiken Line-okat biztosít,

emellett konvertálni tud az audió formátumok között, illetve a fájlokat audió

adatfolyammá alakítja.

A Mixer objektumok információinak lekérdezése a getMixerInfo() nevű statikus

metódussal történik. Ha ezek közül megtalálta a program a megfelelőt. a

getMixer(Mixer.Info info) metódussal lekérhetjük hozzá a Mixer objektumot.

Page 22: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

V-18

Az egyes Line implementációk eléréséhez az AudioSystem.getLine metódusát,

illetve az egyes Mixer-ek getSourceLineInfo, és getTargetLineInfo metódusát

érdemes használni, amiket Line.Info alapján keres.

A hangok lejátszásához két Line implementáció van:

Clip: ez az összes hangadatot egyszerre kapja meg. Akkor érdemes használni, ha

azokat be lehet tölteni a memóriába, és nem valós időben játszunk le.

Az alapértelmezett kimeneten egy Clip-et az AudioSystem.getClip metódussal

kapunk meg. Ez egy magasabb szintű metódus, ami a getMixer-t és a getLine-t is

használja.

Lejátszás előtt először le kell foglalni a vonalat az open metódus segítségével.

A lejátszás kezdeti pozíciójának beállításához a setFramePosition illetve, a

setMicroSecondPosition metódusokat lehet használni. A setLoopPoints-al azt

a részletet lehet beállítani, amit ismételni szeretnénk.

A lejátszás a start és a stop metódussal lehet indítani, illetve leállítani.

A SourceDataLine folyamatos írásra lett kialakítva. Akkor érdemes használni, ha

a hang nem fér el a memóriában egyben, vagy lejátszás során még nincs meg az

összes adat (pl. telefonbeszélgetés). Az open metódusnál itt meg lehet adni egy

AudioFormat objektumot, és egy buffer méretet. Ha ilyeneket nem kap, akkor a

rendszer alapértelmezett értékekkel fog dolgozni. A start felhívása után lehet

meghívni a write metódust, amivel az adatokat byte tömb formátumban

elhelyezhetjük a bufferben, amit a lehető leghamarabb elkezd üríteni. Ha nagyobb

adatot akarunk elküldeni, mint amekkorát a buffer tartani képes, akkor a metódus

addig nem tér vissza, amíg annyi adatot ki nem ürített (lejátszás), hogy az utolsó

byte is beleférjen. Ez egy bevett gyakorlat a lejátszás kivárására.

A drain metódus addig várakoztat, amíg a buffert ki nem üríti.

Page 23: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VI-19

VI. Java és az animáció

Animációs alapok

A célként kitűzött platformjátéknál mozgóképre van szükség, amit a játéktér

folyamatos újrarajzolásával állít elő a program. Az animáció folyamatosságának

egyik mérőszáma a másodpercenkénti újrarajzolások száma, vagyis az FPS

(Frame Per Seconds). Ahhoz hogy az emberi szem folyamatosnak lássa a

mozgást, ennek a mérőszámnak körülbelül 10 felett kell lennie, tehát 10-szer kell

mindent újrarajzolni egy másodperc alatt. Egy bizonyos mértékig minél nagyobb

ez a szám, annál gördülékenyebbnek látszik az animáció, viszont egy szint fölé

már fölösleges emelni, mivel már a szem nem érzékeli a különbséget, illetve a

monitor frissítési kapacitása is határos.

Ha a játéktér újrarajzolásánál a folyamat az elemeket egymás után rajzolja ki a

képernyőre, a képet vibrálni láthatjuk. Ez azért van, mert a ciklus során

folyamatosan jelennek meg az objektumok, amint az összes elem látható, törölni

kell őket, majd egy másik képet megjelenítenie, tehát az egész periódusnak csak

a legvégén láthatjuk a kívánt képet. Ez egy jól ismert probléma, amit flickering-

nek hívnak. A megoldása az, ha a folyamat a rajzolás során már a végleges képet

jeleníti meg. Erre a legkézenfekvőbb módszer a dupla buffer-es renderelés,

melynek többféle kivitelezése lehetséges:

Szoftveres megvalósítás: a rajzoló műveletek a számítógép

memóriájában tárolják az eredményüket. Amikor minden rajzoló művelet

befejeződött, a program jellegétől függően az egész területet, vagy csak a

változásokat átmásolja a VRAM6-ba, aztán megjeleníti. A megjelenítés alatt

lévő buffert első-, a rajzolás alatt lévőt pedig háttérbuffernek nevezik.

A dupla bufferelés több memóriát és számítási időt igényel, mint az egyszerű

renderelés, ezeket a műveleteket kell még az eredetiek mellett elvégezni:

o memória allokálása a háttérbuffernek

o másolás a VRAM-ba (blitting)

6 A videokártya memóriája.

Page 24: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VI-20

o várás a szinkronizálásra

Page flipping: Itt mindkét buffer a VRAM-ban van, de értelemszerűen a

képernyőn egyszerre csak az egyik buffer jelenik meg, eközben a másik

rajzolódik. Ezt úgy lehet megvalósítani, hogy folyamatosan cserélgetik a

megjelenítendő adatok kezdő pointerét a videó memóriában.

Ez a módszer sokkal gyorsabb, mint az előző, mivel kihagyja a blitting-nek

nevezett műveletet.

Dupla bufferes megvalósításnál előjöhet egy másik gyakori hiba, az ún. tearing,

vagyis könnyezés. Ez akkor adódik, amikor a monitor frissítési frekvenciája nincs

összehangolva a megjelenítési periódussal: amikor a monitor frissíti a képernyőt,

még nem fejeződött be az új kép rajzolása, egyszerre látszik az előző és az új kép

is.

7. ábra - Tearing

A két periódus összehangolása a VSync.

Egy olyan szabállyal meg lehet oldani, ami nem engedi újrarajzolni a képet, amíg

az meg nem jelent a monitoron.

A duplabufferes renderelésnél ez addig számít jó megoldásnak, amíg az eredeti

FPS szám a frissítési frekvencia felett van, egyébként az FPS csak olyan diszkrét

értékeket vehet fel, amik a frekvencia és egy pozitív egész szám hányadosai.

A diszkrét FPS-számot el lehet kerülni tripla bufferelés alkalmazásával:

Page 25: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VI-21

Tripla bufferelés: A dupla bufferelésnél a programnak várnia kell, hogy az

elkészült rajz átmásolódjon a memóriába, vagy kicserélődjön a pointer

(page flipping), mielőtt elkezdené az új rajzolást. Ezt itt úgy küszöbölték ki,

hogy a 2 háttérbuffert alkalmaznak, ezért az új kép rajzolása rögtön

elkezdődhet, amint kész az előző. Így a szoftver és a videokártya

egymástól függetlenül végezhetik a műveleteket. (Ismeretlen, How VSync

works, and why people loathe it)

Bufferelés és teljes képernyős mód a Javaban

A J2SE 1.4 egyik újdonsága, hogy lehetőséget nyújt a programozónak, hogy

megkerülje az ablakozó rendszert, és közvetlenül a képernyőre rajzoljon. Ehhez

teljes képernyős módra kell váltani, így át lehet venni az irányítást a megjelenítő

eszköz felett.

A megjelenítő eszközt egy GraphicsDevice objektum kezeli. Az elérhető

eszközök listáját a GraphicsEnvironment getScreenDevices(), az aktuálisat pedig

a getDefaultScreenDevice() metódusával kapjuk meg. A GraphicsEnvironment

osztály a platformon elérhető megjelenítő eszközöket és betűtípusokat tárolja.

Azt, hogy engedélyezett-e a teljes képernyős mód, az

isFullScreenModeSupported() metódus mondja meg. A

setFullScreenWindow(Window) metódus, a paraméterül kapott ablakot teljes

képernyősre állítja. Ha a teljes képernyős mód nem támogatott, akkor átméretezi

úgy, hogy kitöltse az egész képernyőt. Ha a paraméter null, visszatér az eredeti

üzemmódba.

A DisplayMode objektumok kezelik az eszköz következő információit: felbontás,

színmélység, frissítési frekvencia. Az elérhető megjelenítési módokat a

GraphicsDevice getDisplayModes() metódusa adja vissza egy tömbként. A

beállításnál ennek a tömbnek az értékeiből lehet választani.

Teljes képernyős módban nem szükséges figyelni az operációs rendszer által kért

újrarajzoló műveleteket, ezek helyett érdemes egy saját ciklust írni ezekre. Ezt

aktív renderelésnek hívják, és sok fölösleges számítást lehet vele elkerülni.

Page 26: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VI-22

Teljes képernyős módban közvetlenül a VRAM-ot is lehet használni, ami

lehetőséget nyújt a Page-flipping megvalósításához. A különböző bufferelési

stratégiák kivitelezését a BufferStrategy használatával érdemes elvégezni. Ennek

a megjelenítés a feladata, tekintet nélkül a tárolók számára, vagy a megjelenítési

technikára. Két legfontosabb metódusa a getDrawGraphics, ami visszaadja a

rajzolási területet, és a show, ami megjeleníti azt a képernyőn.

A bufferelési lehetőségeket a BufferCapabilities osztály objektumai tárolják.

Olyan metódusokkal lehet vizsgálni őket, mint:

isPageFliping: visszatérési értéke true, ha a hardveres page-flipping

elérhető.

isFullScreenRequied: ha true, akkor a page-flipping használatához

szükséges a teljes képernyős mód.

getFlipContents: azt adja meg, hogy a bufferek közötti váltás hogyan

történik.

Az elérhetőeket GraphicsConfiguration példány getBufferCapabilities() metódus

adja vissza. Ez egy megjelenítő eszköz beállításait tárolja. Egy GraphicsDevice

objektumhoz tartozhat több ilyen beállítás is.

Page 27: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-23

VII. Az elkészült program ismertetése

A játék rövid bemutatása

8. ábra – Egy kép a játékból

Az elkészített játékban, mint ahogy a bevezetésben is említettem: egy kis figurát

(lila dinoszaurusz) irányítva, a különböző akadályokon és ellenségeken

átjutva/átugrálva kell eljutni a célig.

A pálya statikus, nem mozdítható elemei a blokkok, ezekből épülnek fel a

platformok, de egy ilyen blokk a célt jelző fekete négyzet is.

A blokkokon járnak, és ezeknek ütköznek neki a szereplők (a játékos, és az

ellenfelek).

A szereplőkre hat a gravitációs erő, illetve a pályabeállításoktól függően a szél.

Az alapvető mozgástípusok a futás, az állás és az ugrás.

A játékosnak kezdéskor 3 élete van: ezeket az ellenfelekkel való érintkezések

során veszíti el. Lehetőség van az ellenfél kiiktatására: ehhez rá kell ugrani.

A képernyő jobb alsó sarkából lehet leolvasni a fennmaradó életek számát.

Ha a játékos elérte a célt, az ENTER billentyűvel lehet a következő szintre lépni.

Page 28: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-24

A futást a nyilakkal irányíthatjuk, az ugrás pedig a SPACE billentyű lenyomásakor

történik. Ha a billentyűket a SHIFT-el együtt nyomja meg a felhasználó, az

gyorsabb futást és nagyobb ugrást eredményez.

Az elkészítés során felmerült feladatok

Ebben a fejezetben a játék megvalósításához kapcsolódó követelményeket, és

azoknak azt a kivitelezését mutatom be, ami a folyamatos újraírások után már a

végleges verzióban szerepel.

A játék legyen képes grafikai elemeket megjeleníteni és pozícionálni.

A játék elemei képként jelennek meg. A beolvasásukhoz, és az ehhez hasonló

feladatokhoz készült egy fájlkezelő osztály, aminek az egyik metódusa a kép

elérési útvonalát megkapva, BufferedImage osztályú objektumot ad vissza. Ezek

a képek vannak megjelenítve a játék ablakában. A pozícionáláshoz a Graphics

draw metódusánál megadható paraméterek szolgálnak, amiket a programban két

szám összege határoz meg: az abszolút pozíció, amit egy külön osztályban

tároltam, illetve az eltolás, amit a későbbiekben ismertetek. A képek

átméretezésére is szükség volt, amit szintén a draw metódus paramétereivel

végeztem el. A szélesség és magasságértékek a pozíciót tároló osztályba

kerültek.

A játék szereplői változtassák a pozíciójukat.

A pozíció állításához a szereplőkhöz tartozik egy függőleges és vízszintes irányú

sebességérték, amit egy metódus hozzáad a pozíciók értékéhez.

A folyamatos mozgáshoz mozgóképet kellett megjeleníti: ehhez egy végtelen

ciklus beállítja az összes szereplő pozícióját a sebesség alapján, majd újrarajzolja

őket. Ennek pontos leírása az „A játék folyamatainak leírása” c. részben

olvasható.

A szereplők ütközzenek a pályaelemekkel, ne tudjanak rajtuk átmenni.

Az ütközések kezeléséhez listázni kellett az ütköztethető elemeket. A játék egy

szintjének blokkjait egy kétdimenziós tömb tárolja, a szereplőket pedig egy lista.

Ahhoz hogy a szereplők nekiütközhessenek a blokkoknak, minden periódusban

meg kell vizsgálni, hogy valamelyik szereplő érintkezik-e valamelyik blokkal. A

Page 29: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-25

blokkok tömbjét tartalmazó objektumnak vannak olyan metódusai, amik egy

szereplőt megkapva paraméterként, annak pozíciója alapján visszaadják a

legközelebb balra, jobbra, felül illetve alul lévő elemeket. Ezek építenek a blokkok

tömbbeli elhelyezkedésére, emiatt a blokkok elhelyezésük utáni mozgatása nem

lehetséges.

Azt, hogy ütköznek-e az így kapott blokkokkal, a szereplők ősosztályában definiált

metódusok adják meg, ahogy az ütközés során történő viselkedést is. A

leszármaztatásukkal értem el, hogy a különböző osztályba tartozóak különböző

módon viselkedjenek.

A szereplőket mozgassák külső erőhatások.

A külső mozgató elemek, mint a gravitáció egy közös interfészt implementálnak. A

játék egy periódusa alatt az összes ilyen mező mozgató metódusa meghívódik az

összes szereplőre.

Az ugrás megvalósítása az eddig felvázolt rendszerben a felfelé mutató sebesség

állítását jelenti. Ha 10-re van állítva, akkor a játékos az első periódusban 10

egységgel feljebb kerül, a másodikban már csak 9-el a gravitációs mező hatása

miatt, és így tovább, amíg el nem kezd lefelé gyorsulni. Az ugrás csak akkor

lehetséges, ha a szereplő a földön van, ezért ezt a tulajdonságot egy boolean

értékben tárolom, aminek az alsó blokkal való ütközések vizsgálatakor változik az

értéke.

Az ellenfelek változtassák a mozgásuk irányát.

Egyes ellenfelek mozgását az ősosztályok különböző események hatására

felhívódó metódusok irányítják.

A játékos és az ellenfél ütközése legyen vizsgálva, és lekezelve.

Az ütközés az összes periódusban vizsgálva van a szereplők pozíciója és mérete

alapján. Az ütközések során, ha a játékos felülről esik rá az ellenfélre, akkor az

meghal, egyébként a játékos életeinek száma csökken. Arra, hogy megállapítsuk

az egymáshoz viszonyított elhelyezkedést, a szereplők koordináta állítása előtt

eltárolódik az eredeti érték. A játékos akkor iktatja ki az ellenfelet, ha érintkezéskor

az előző, legalacsonyabban lévő Y koordinátája magasabban volt, mint az ellenfél

legmagasabban lévő Y koordinátája.

Page 30: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-26

A megjelenített játéktér mozogjon együtt a játékossal.

Az elemek kirajzolása során pozícióértékekhez hozzáadok egy függőleges és egy

vízszintes eltolás értéket, ami attól függ, hogy hol áll a játékos.

A játék nyelve legyen állítható.

A játék során megjelenő szövegeket a ResourceBoundle használata helyett

kísérletezés céljából egy általam írt osztály kezeli. Ez ugyanúgy kulcs-érték

párokkal dolgozik, amiket az egyes szövegfájlokból olvas be HashMap-ekbe.

A hangok lejátszása ne szakítsa meg a játékmenetet.

Mivel a játékciklus, és a billentyűzetesemények figyelője sem várhatja meg, amíg

egy hang lejátszódik, minden egyes effekt lejátszása külön szálon történik.

Legyen lehetőség teljes képernyős mód használatára.

A teljes képernyő módhoz az előző fejezetben leírt módszert alkalmazom.

A játék futásakor a kép ne vibráljon.

A vibrálás eltűntetését a JFrame bufferelési módjának beállításával értem el.

A játék tartalmazzon menüt, ahol be lehet állítani a nyelvet, a teljes

képernyős módot, és ki lehet kapcsolni a hangokat.

A játék menüjét saját elemekből építettem fel. Ezeknek kétféle típusa van:

o Alap menüelem: egy négyzet rajta szöveggel.

o Választási opciókkal rendelkező menüelem: az alap négyzet és

szöveg mellett más menüelemeket is tartalmaz, amiket aktív

állapotban megjelenít. A játékhoz tartozó beállításokat ilyen

menüelemekkel lehet állítani: egy opció választása után a

beállításokért felelős segédosztály elvégzi a hozzá tartozó

műveleteket.

A játék legyen gyors.

A gyorsaság növelését az egyes részfeladatok optimalizálásával értem el. Az

újraírások során vizsgáltam a metódusok futási idejét, és a legkedvezőbb értékhez

Page 31: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-27

tartozó megoldást alkalmaztam. Nagyon kis időtartamokat kellett vizsgálni, ezért a

System.currentTimeInMillis() nem minden esetben ad elég pontos információt,

helyette a System.nanoTime()- ot alkalmaztam. A mérésre alkalmazott módszer:

1. egy long változóba eltároltam a System.nanoTime() értékét

2. a program elvégezte a metódust

3. A System.nanoTime() aktuális értékéből kivontam a változó értékét, így az

eredménye egyenlő a metódus futási idejével nanoszekundumokban.

Felhasznált programok

A kód megírásához az Eclipse fejlesztőkörnyezetet választottam. A projekt

változásainak kezelését eleinte nem terveztem, azonban a sorozatos refaktorálás

során felmerülő új hibák miatt szükségességét éreztem valamilyen verziókezelő

rendszer használatának: az SVN-re esett a választásom, amihez a TortoiseSVN-t

és az Eclipse letölthető Subversive nevű plugin-jét telepítettem fel. A kód a Java

Development Kit 7u17-hez igazodik, a felhasznált képek pedig Photoshop-al

készültek.

Az osztályok ismertetése

A működés teljes megértéséhez szükséges, az osztályhierarchia és az egyes

osztályok ismerete. Ebben a fejezetben a fontosabb tudnivalókat írom le róluk.

GameFrame

9. ábra - GameFrame

A projekt egyetlen futtatható osztálya, ami egy JFrame-ből van leszármaztatva.

Itt, és az összes később leírt olyan osztálynál, ahol szerepel a singleton()

metódus, a singleton tervezési mintát alkalmaztam. Ez azt jelenti, hogy az

osztálynak csak egyetlen példányosított objektuma lehet. Emiatt a konstruktora

Page 32: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-28

private módosítót kapott. Ez itt csak egy statikus blokkban van felhívva, ahol a

SINGLETON nevű tagot példányosítja, amit a singleton() metódus ad vissza. Ezt a

kialakítást azért választottam, mert azt feltételeztem, hogy egy JVM egyszerre

csak egy játékot fog futtatni, így kihasználhatom a mintának azt az előnyét, hogy

nem kell minden GameFrame objektummal kapcsolatban lévő osztálynak

referenciát tárolnia, elég, ha a GameFrame.singleton() metódust felhívja.

A konstruktor a játékhoz olyan jellemzőket állít be, mint az átméretezhetőség

letiltása, a fókusz kérése, vagy az ignoreRepaint paraméter igaz-ra állítása,

aminek hatására figyelmen kívül hagyja az operációs rendszertől érkező

újrarajzolási kéréseket.

A main metódus beolvassa a szövegfájlokból a beállításokat

(SettingsUtility.singleton().readSettingsFromFiles()), és felhívja a

GameExecutorThread.singleton().startGame(); metódust.

GameExecutorThread

10. ábra - GameExecutorThread

Ez az osztály tartalmazza az aktuális képernyő (játék, főmenü, vagy beállítások)

adatainak frissítéséért, és a megjelenítésért felelős periódust. Implementálja a

Runnable interfészt: a fenn említett metódus létrehoz egy futtatási szálat az

osztályból (animator), majd elindítja azt.

Fontosabb adattagjai:

Page 33: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-29

content: a játék egy képernyője

strategy: a GameFrame osztály getBufferStrategy álltal visszaadott

objektumának kell lennie

Fontosabb metódusai:

run(): ebben a metódusban található a képernyő adatainak frissítéséért, és

megjelenítéséért felelős periódus, ami a program futása során

folyamatosan ismétlődik. A pontos működését az „Egy periódus leírása”

című fejezetben írom le.

pause() és start(): ezek a metódusok megállítják, illetve elindítják a ciklus

ismétlődését.

setContent(): a képernyőt váltja. Ez a content értékének változtatása

mellett a következő feladatokat látja el:

o a GameFrame KeyListener-jét az új content-re állítja.

o a content-nek felhívja az initialize metódusát.

A játék képernyői

A játékban háromféle képernyő van, amik az AbstractEngine osztály

leszármazottjai.

11. ábra – Az AbstractEngine osztályhoz tartozó hierarchia

Page 34: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-30

AbstractEngine

12. ábra - AbstractEngine

Fontosabb metódusai:

render(): a paraméterként kapott Graphics2D objektumra rajzolja a

képernyő elemeit

update(): a megjelenítendő elemek adatainak frissítése

keyTyped(KeyEvent), keyPressed(KeyEvent), keyReleased(KeyEvent):

absztrakt metódusok, a billentyűzetesemények kezelésére. Az osztály

implementálja a KeyListener interfészt

initialize(): a képernyő inicializálása/újrainicializálása

nextEngine és previousEngine getter és setter-ek: a képernyők közötti

navigálásokat oldják meg. A getNextEngine metódusban a következő

képernyő previousEngine-je megkapja az aktuális képernyőt, ha az

isReturnAble metódus true-t ad vissza. A returnToPreviousEngine az előző

képernyőre ugrik vissza.

A játék indításakor az MainMenuEngine az első képernyő, ami az

AbstractMenuEngine-ből származik. Az AbstractMenuEngine egy

MenuContainer osztályú tagjának kezeléséért felelős. A MenuContainer osztály

legfontosabb adattagja egy MenuElement-ekből álló lista.

Page 35: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-31

MenuElement

13. ábra - MenuElement

Fontosabb adattagjai:

selected: azt tárolja, hogy ki van-e választva a menüelem.

14. ábra – A játék menüje

key: az azonosítást, és a felirat kiválasztását szolgálja. A konstruktor a

játék szövegeit kezelő osztály (TextHandler) segítségével megkeresi a

kulcshoz tartozó aktuális szöveget, aminek az értékét a text mező kapja

meg.

text: a menü felirata

background: fix szélességű és magasságú (konstansok) négyzet, a

szöveg háttere.

Page 36: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-32

Fontosabb metódusai:

drawElement(Graphics2D) a paraméterként kapott objektum színét, és

betűtípusát megfelelő értékekre állítva megjeleníti a téglalapot, kirajzolja a

szöveget (drawString), majd visszaállítja az eredeti értékeket.

MenuContainer

15. ábra - MenuContainer

Fontosabb adattagjai:

menuElements: az osztály feladata az ebben a listában lévő menüelemek

kezelése.

Fontosabb metódusai:

addMenuElement(MenuElement): a listához hozzáadja a paraméterként

kapott elemet, majd az yPos értékét növeli az elem magasságának és az

elemek közti távolságnak (ELEMENT_SPACE) az összegével.

addMenuElement(String): egy MenuElement osztályú objektumot hoz

létre, az xPos, yPos és a paraméterként kapott kulcs értékének

segítségével, amire meghívja az addMenuElement(MenuElement element)

metódust.

Page 37: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-33

addMenuElementWithOptions(String): az előző metódushoz hasonló a

működése azzal a különbséggel, hogy a MenuElement-ből származó

MenuElementWithOptions objektumot hoz létre.

drawMenu(Graphics2D): a lista összes elemére meghívja a

drawElement(g2d) metódust.

cursorUp() és cursorDown() metódusok: A listában lévő aktív elemet lehet

a segítségükkel kiválasztani.

index és key getter és setter metódusok: a listában kiválasztott elem

sorszámát, illetve annak kulcsát adják vissza/állítják be.

AbstractMenuEngine

16. ábra - AbstractMenuEngine

Fontos adattagjai:

container: a képernyő ezt az elemet kezeli és jeleníti meg

Fontosabb metódusai:

createContainer(): absztrakt metódus. Visszetérési értéke egy

MenuContainer elem, ennek az értékét kapja meg az initialize metódusban

a container változó. Azt a célt szolgálja, hogy a különböző leszármazott

osztályokban változtatható legyen, az elem inicializálásnak módja.

keyPressed(): felhívja a navigationActions nevű absztrakt metódust, aztán

kezeli a fel- (actionForUp(MenuElement))le-

Page 38: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-34

(actionForDown(MenuElement)) nyíl, illetve az

Enter(actionForEnter(MenuElement)) billentyűk lenyomását. Az említett

metódusok a kiválasztott menüelemet kapják meg paraméterként. A nyilak

hatására az alapértelmezett metódus, a container-ben való kiválasztás.

render: törli a megjelenítendő területet, majd feketére színezi, és

megjeleníti a container elemet.

Az update() metódus itt üres, mivel csak a felhasználói interakcióra kell pozíciókat

változtatni. Az isReturnable() metódus false-t ad vissza azért, hogy ne lehessen

egy ilyen típusú képernyőre visszalépni.

MainMenuEngine:

17. ábra – MainMenuEngine

Ez a képernyő a játék főmenüje.

Fontosabb metódusai:

createContainer(): a főmenü elemeihez tartozó kulcsokból készíti a

container elemeit. Amennyiben a játék még tart7, a lista tartalmazni fogja az

oda való visszalépést.

actionForEnter(MenuElement): a kiválasztott elem kulcsát megvizsgálva

beállítja a következő képernyőt, vagy kilép a játékból.

MenuElementWithOptions

A „Beállítások” képernyőt az OptionMenuEngine valósítja meg, ami általános

MenuElement elemek mellett MenuElementWithOptions osztályúakat is

7 GameEngine.singleton() != null && !GameEngine.singleton().isGameOver() &&

GameEngine.singleton().isReturnAble() feltétel

Page 39: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-35

tartalmaz. Ez utóbbi arra a célra lett tervezve, hogy a játék beállításait jelenítse,

illetve változtassa meg.

18. ábra - MenuElementWithOptions

Fontosabb adattagjai:

container: az elem kulcsához tartozó választási lehetőségeket tartalmazza.

active: állapotjelző

Fontosabb metódusai:

createContainer: a SettingsUtility osztályból lekéri az elem kulcsához

tartozó további kulcsokat egy listában, amik alapján feltölti a container

elemet, ezek után ugyanennek az osztálynak a segítségével lekérdezi, és

beállítja az éppen aktív elemet.

drawElement(Graphics2D):az alap MenuElement rajzolása mellett aktív

állapot esetén a container drawMenu(Graphics2D) metódusát is meghívja.

setActive(): abban az esetben, ha épp most válik inaktívvá az elem,

meghívja a setOption() metódust, ami a

SettingsUtility.setSettings(String,String) segítségével elvégzi a kívánt

beállítást.

Page 40: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-36

OptionsMenuEngine

19. ábra - OptionsMenuEngine

Fontosabb metódusai:

createcontainer(): MenuElementWithOptions objektumokat is elhelyez a

container-ben.

Billentyűzetleütést kezelő metódusai:

actionForEnter(MenuElement): ha a kiválasztott elem

OptionsMenuElement, akkor azt aktívvá teszi (setActive(true)).

actionForUp(MenuElement), actionForDown(MenuElement): ha az

éppen kiválasztott elem egy MenuElementWithOptions és az állapota aktív,

akkor azon belül léptetnek, egyébként az ősosztály metódusát hívják fel.

navigationActions(KeyEvent): ha az eseményt az Escape billentyű

lenyomása okozta, és a kiválasztott elem MenuElementWithOptions és

aktív, akkor inaktívvá teszi, egyébként visszalép az előző menübe.

Page 41: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-37

GameEngine

20. ábra - GameEngine

Ez a játék képernyője.

Fontosabb adattagjai:

gameActors: a játékban aktívan résztvevő szereplőket tárolja: az

ellenfeleket és a játékost

map: az aktuális pálya, az összes elérhető pálya neve a mapNames[]

tömbben van tárolva

level: az aktuális szint

player: a játékos

Page 42: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-38

hud: a játék közbeni információk megjelenítéséért felelős objektum8

backGround: a játék háttere

Fontosabb metódusai:

drawObjects(Graphics2D): A felsorolt adattagok megjelenítését végzi:

Részletes működése az „Egy periódus leírása” részben található.

update(): a szereplők pozíciójának frissítését végzi. Részletes leírása az

„Egy periódus leírása” részben található.

render(Graphics2D): a paraméterre meghívja a clearRect metódust a

terület törléséhez, majd ha a játék még tart, meghívja a

drawObjects(Graphics2D)-t, egyébként a paintGameOver(Graphics2D)-

t, ami kiírja a képernyőre, hogy vége a játéknak.

keyPressed(KeyEvent): az Escape billentyű hatására, vagy ha vége a

játéknak visszalép az előző képernyőre. Ha a játékos továbbléphet a

következő szintre (canPlayerExit()), akkor az ENTER billentyű hatására

megteszi azt(setNextLevel()). Ezen vizsgálatok utána átadja az eseményt

a player objektumnak.

keyReleased(KeyEvent): a player eseménykezelőjének továbbítja a

paramétert.

A játék elemei

A szereplők és pályaelemek ősosztálya az AbstractGameElement. Ennek két

mezője van: egy a pozíció tárolására, egy pedig azt mutatja, hogy éppen látható-e

az elem. A pozíciót az ElementPosition nevű osztály, és annak leszármazottjai

kezelik. Ezek azért kerültek külön osztályba, hogy a koordinátaadatok jellege ne

játsszon szerepet az AbstractGameElement-hez tartozó hierarchia kialakítása

során.

8 A HUD itt a Heads Up Display rövidítése: a kifejezést a játékképernyőn általában áttetszően vagy

kis ikonokkal kijelzett adatok összességére használják.

Page 43: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-39

21. ábra – ElementPosition, MovingElementPosition, MovingElementPositionWithDirection

ElementPosition

Az ElementPosition az x, y koordináták, a szélesség és a magasság

attribútumokat kezeli.

Fontosabb metódusai:

interSectedWith(ElementPosition),

intersectedWithRectangle(int,int,int,int): ezek a metódusok azt adják

vissza, hogy a paraméterekhez tartozó négyzettel, vagy pozícióval

érintkezik-e az objektum.

MovingElementPosition

A MovingElementPosition függőleges és vízszintes sebességadatokkal egészíti

ki az ősét.

Fontosabb metódusai:

move():a sebességadatokat hozzáadja a koordinátákhoz

MovingElementPositionWithDirection

A MovingElementPositionsWithDirection minden koordinátaállításnál letárolja

az előző értéket. Ezek ütközésdetektálásnál, az egymáshoz viszonyított pozíciók

megállapításához vannak felhasználva.

Page 44: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-40

AbstractGameElement

22. ábra - AbstractGameElement

Fontosabb metódusai:

drawToGraphics(Graphics2D,int,int), a képernyőre való rajzolást

valósítja meg, a két int paraméterrel való eltolással.

getType(): az elem típusára vonatkozó String-et ad vissza (pl. a játékos

objektumára visszaadva az értéke: „PLAYER”).

createPosition(int, int, int, int) a konstruktorban van felhívva. Visszatérési

értékét kapja a position objektum.

az koordinátákat kezelő metódusok a position objektum azonos nevű

metódusait hívják fel.

Page 45: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-41

23. ábra – Az AbstractGameElement-hez tartozó hierarchia

ImageGameElement

24. ábra - ImageGameElement

Azoknak a játékelemeknek, amik egy képet jelenítenek meg, ez az ősosztályuk.

Mivel az egyes osztályok azonos típusú elemeket jelölnek, az image lehetséges

értékei osztályszintű elemekben van tárolva.

Fontosabb metódusai:

drawToGraphics(Graphics2D): a Graphics2d osztály drawImage

metódusának az image objektumot, illetve a position x, y, width és height

koordinátáit adja át.

Page 46: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-42

AbstractBlockElement

25. ábra - AbstractBlockElement

A pálya statikus az AbstractBlockElement leszármazottjai.

Fontosabb adattagjai:

destroyable: azt tárolja, hogy a játékos el tudja-e tűntetni a blokkot

collosionEnabled: ha az értéke true, nekiütközhetnek a szereplők.

Fontosabb metódusai:

destroy():az isVisible és a collosionEnabled értékét false-ra állatja, ezálltal

eltűnteti a blokkot.

SimpleBlock, StoneBlock, ExitDoor

Ezek már nem absztrakt osztályok. A megjelenített képben, és az említett két

boolean értékében különböznek:

26. ábra – SimpleBlock, StoneBlock, ExitDoor

Page 47: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-43

A pályaelemek táblázata

SimpleBlock StoneBlock ExitDoor

Megjelenített kép:

destroyable true false false

collosionEnabled true true false

Actor

A játék résztvevői ennek osztálynak leszármazottjai.

27. ábra - Actor

Page 48: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-44

Status belső osztály:

Fontosabb adattagjai:

direction: a mozgás irányát adja meg: ez a Direction nevű enum típus.

Lehetséges értékei: bal, jobb.

movementType: a mozgás típusát adja meg: ez a MovementType enum.

Lehetséges értékei: állás, futás, ugrás

Ezeknek az összes lehetséges kombinációja el van tárolva osztályszintű

változókban, emellett egy külön státusz a halott, amikor a mozgás iránya, és

típusa is null.

Fontosabb adattagjai:

onGround: értéke akkor true, ha a szereplő talajon jár. Az olyan műveletek

felhívásánál fontos a vizsgálata, mint az ugrás, vagy a gravitációs

gyorsulás.

isDead: a státusz beállításánál, illetve az egymással való ütközés

kezelésénél fontos.

jumpPower: az ugrás nagyságát határozza meg (a kezdeti felfelé mutató

sebesség). Az ugrást kivitelező metódusok alapértelmezetten erre az

értékre állítják a felfelé mutató sebességet.

Fontosabb metódusai:

createPosition(): MovingElementPositionWithDirection objektumot ad

vissza. Az osztály ennek a metódusait is implementálja.

setStatus: a status értékeit állítja be a sebességek alapján, majd beállítja

az ahhoz tartozó képet.

animate(Image[]): feladata a szereplő képeinek folyamatos cserélgetése a

megadott időközönként (ANIMATION_LENGTH).

checkAndSetOnGroundFromBlock(AbstractBlockElement),

sideCollosion(AbstractBlockElement),

upCollosion(AbstractBlockElement): ezek kezelik a blokkokkal való

ütközést. Ebben az osztályban található az alapértelmezett viselkedés, ami

egy adott irányú ütközés során megállítja az irányba történő mozgást.

Page 49: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-45

Az Actor-ból származtatott osztályok betöltésük során egy statikus blokkban

inicializálják státuszokhoz tartozó képeket, majd azokat egy HashMap-ben

(imageForStatusAssignment) tárolják.

RedEnemy, GreenEney, YellowEnemy

28. ábra – RedEnemy, GreenEnemy, YellowEnemy

Mivel az ellenfeleket nem a játékos irányítja, viselkedésüket az egyes események

hatására felhívott metódusok felülírásával lehet beállítani.

Az ellenfelek táblázata

RedEnemy GreenEnemy YellowEnemy

Kép

Viselkedés:

Oldalirányú ütközésnél

véletlenszerűen felugrik

vagy megfordul.

Oldalirányú ütközésnél a

sebességet ellentétes

előjelűvé állítja

A játékost

követi.

Felülírt

metódusok:

sideCollosion

(AbstractBlockElement)

sideCollosion

(AbstractBlockElement) update()

Page 50: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-46

Player

29. ábra -Player

Fontosabb adattagjai:

lives: életek száma

running: ha az értéke true, akkor a játékos gyorsabban fut és nagyobbat

ugrik

Fontosabb metódusai:

keyPressed(KeyEvent): a bal és jobb irány lenyomására beállítja a

megfelelő irányú sebességet, a Space-re felhívja az ugrás metódust, a

Shift-re pedig az isRunning változó értékét true-ra változtatja.

Page 51: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-47

keyReleased(KeyEvent): visszaállítja az eredeti értékeket.

die(): csökkenti az életek számát, majd elvégzi az ehhez tartozó

metódusokat

upCollosionAdditonalActions(AbstractBlockElement): az ősosztályban

implementált viselkedés mellett az eltűntethető blokkokat eltűnteti.

HeadsUpDisplay

30. ábra - HeadsUpDisplay

Ennek az osztálynak az a feladata, hogy a felhasználót tájékoztassa az aktuális

eseményekről. A működése annyiból áll, hogy a játékos életeinek számát jelzi úgy,

hogy a playerHeadImage képet annyiszor jelenít meg egymás mellett, ahány

élete van, illetve ha a játékos érintkezik a pálya ExitDoor elemével, akkor kiírja,

hogy az ENTER lenyomásával továbbléphet a következő szintre.

Page 52: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-48

A pályát létrehozó és kezelő osztályok:

GameMapLevel

31. ábra - GameMapLevel

Ez egy szintet tárol a játékban, vagyis egy játékteret.

Fontosabb adattagjai:

screenBlocks: a pálya elemeinek tömbje, amit egy szöveges fájlból olvas

be.

A beolvasás során, ami a konstruktorban történik, végighalad rajta sorról

sorra, és az abban lévő kód alapján elhelyez a pályaelemek tömbje, vagy a

szereplők listája között egy elemet (ez utóbbit aztán átadja a GameEngine-

nek, és nem használja tovább).

Page 53: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-49

exitDoor: a szint kijárata

Fontosabb metódusok:

getNearestBlockLeft(Actor), getNearestBlockRight(Actor),

getLowestRoffOverActor(Actor), getHighestGroundUnderActor(Actor):

Ezek a metódusok az Actor osztályú objektum pozíciója alapján a hozzá

képest legközelebbi balra, jobbra fölötte és alatta lévő elemet adják vissza.

getScreenBlockAt(int,int,boolean): visszaadja az adott koordinátánál lévő

blokkot. Mivel épít az elemek tömbben lévő pozíciójára, a blokkok

mozgatása helytelen működéshez vezet.

GameMap

A GameMapLevel-ek szervezéséért felelős.

32. ábra - GameMap

Ez konstruktorában egy könyvtár nevét kapja meg paraméterként, amiben kell,

hogy legyen egy fieldList.txt, illetve egy levelList.txt fájl. Előbbiben a pályához

tartozó szintek leírását tartalmazó további szöveges fájlok nevei, vannak,

utóbbiban pedig a pálya gravitációs mezők melletti hatásainak a neve és

erőssége.

Page 54: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-50

CollosionDetection

33. ábra - CollosionDetection

Ez az osztály kezeli a játék során fellépő ütközéseket.

Fontosabb metódusai:

collosionDetection(Actor): feladata a szereplő ütköztető metódusainak

felhívása a megfelelő pályaelemmel.

checkActorContact(Actor,Actor):két szereplő ütközését vizsgálja.

Lehetséges visszatérési eredményei:

o 0, ha a két paraméter megegyezik, valamelyik „halott”, vagy nem

érintkeznek.

o 1, ha az első ráesett/ugrott a másodikra. Ez a feltétel akkor igaz, ha

az előző legalacsonyabb pozíciója (getPreviousYMax() )

magasabban van, mint a második legmagasabb pozíciója.

o -1 minden egyéb esetben.

A Field interfész, és a hozzá tartozó osztályok:

34. ábra – GravityField, Wind

Ezek a szereplők pozícióját befolyásolják: a doMove(Actor) metódus a

paraméterként kapott szereplő pozícióját módosítja.

Page 55: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-51

GravityField

A gravitációs gyorsulást szimulálja: ha az actor a levegőben van, és a függőleges,

lefelé történő gyorsulása nem érte még el a határértéket, akkor azt növeli.

Wind

A függőleges pozíciót változtatja, ezzel azt a hatást keltve, mint ha az objektumot

elfújná a szél.

Segédosztályok

A játék során felmerülő általános feladatok elvégzésére a game.utility csomagban

lévő segédosztályok hivatottak.

SettingsUtility

35. ábra - SettingsUtility

Ez az osztály kezeli a játék beállításait.

Fontosabb adattagjai:

options: HashMapben tárolja a lehetséges beállításokat (kulcsok), és azok

opcióit (értékek).

Page 56: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-52

settings: a SettingsHolder nevű HashMap-ből leszármaztatt belső osztály

egy példánya. Erre az osztályra azért volt szükség, hogy az értékek

felvitelekor elvégezze a megfelelő beállításokat:

ResourceUtility

36. ábra - ResourceUtility

A fájlok kezeléséért felelős.

Fontsabb metódusai:

Szerepelnek benne különböző getter metódusok, melyek a fájlokhoz tartozó

útvonalakat adják vissza.

readKeysAndValues(File,String): a paraméterként kapott fájl alapján

olyan HashMap-et hoz létre, ami a fájlban található kulcs-érték párokat

String-ként tartalmazza.

readKeysAndArrayListValues(File,String,String): A fájl tartalma alapján

egy String kulcsokat és String listát tartalmazó HashMap-et ad vissza.

Page 57: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-53

TextHandler:

37. ábra - TextHandler

A játék szövegeit kezeli. A megjelenítendő szövegek a két HashMap

attribútumban vannak hozzárendelve a megfelelő kulcshoz. A reinitialize(String)

metódus újraolvassa a kapott kulcshoz tartozó szövegfájlokat.

SoundUtility

38. ábra - SoundUtility

Az osztály a hangok lejátszásáért felelős. A Sound enum típus kétféle hangot

tárol, amiket a play() metódussal lehet lejátszani. A SoundThread run() metódusa

a konstruktorban kapott Sound attribútumot játssza le.

Fontosabb metódusai:

Page 58: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-54

playSound(Sound) abban az esetben, ha a soundOn értéke true, elindítja

a paraméter alapján példányosított SoundThread szálat.

DisplayUtility

39. ábra - DisplayUtility

Feladata a megjelenítési adatok kezelése.

Fontosabb metódusai:

setFullScreenDisplayMode(GraphicsDevice) a GameFrame-et teljes

képernyős módra állítja, majd megpróbálja beállítani a legelőnyösebb

BufferStrategy objektumot, és üzemmódot (amit a két DisplayMode

elemeket tartalmazó tömbből választ ki). A beállításhoz meg kell állítani a

GameExecutorThread fő periódusát.

A játék folyamatainak leírása

Futási szálak

A futás közben a következő szálak végzik a játékkal kapcsolatos műveleteket:

Indításkor az inicializáló szál előkészíti a futást: meghívja a GameFrame

konstruktorát, beolvassa a beállításokat, majd elindítja a

GameExecutorThread-hez tartozó szálat.

Az eseménykezelő szál, figyeli a billentyűzetleütéseket, és ennek

megfelelően hívja fel a metódusokat. Az AbstractEngine implementálja a

KeyListener interfészt. A képernyők eseménykezelése a GameFrame-hez

van rendelve.

Page 59: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-55

A GameExecutorThread-hez tartozó animator változó az objektumból

Thread-et készít, amit a startGame metódusban indít el. Ez a szál felelős a

játék adatainak frissítéséért és a megjelenítésért. Az „Egy periódus

leírása” című részben részletesen le van írva a működése.

Minden egyes hang lejátszásához külön szál jön létre.

Egy periódus leírása

A GameExecutorThread egy periódusa a következő műveletekből áll:

1. Lekéri az aktuális rendszeridőt a System.nanoTime()-al.

2. Frissíti a képernyő adatait: content.update(): ez csak játék képernyő

esetén végez feladatot, ilyenkor ha még tart a játék, az összes

szereplőn elvégzi a következő műveleteket:

o pozíciók állítása a sebesség alapján

o a játékossal való interakció vizsgálata: ha ütköznek, akkor attól

függően, hogy milyen az egymáshoz viszonyított pozíciójuk, az

ellenfél meghal, a játékos felugrik, és lejátszódik az ehhez

kapcsolódó hang, vagy a játékos hal meg.

o elvégzi a pályához tartozó mezők műveleteit

o megvizsgálja a pályaelemekkel való ütközéseket, és elvégzi az

ezekhez kapcsolódó műveleteket

3. A strategy attribútumon megjeleníti a képernyő elemeit, ami

GameFrame esetén a következő feladatokból áll:

o Megrajzolja a hátteret.

o Beállítja a pályaelemek és szereplők eltolásának értékét a

játékos pozíciója alapján.

o Megrajzolja a pályaelemeket.

o Megrajzolja a szereplőket.

o Felrajzolja a hud-ot.

Ezután meghívja a Toolkit.getDefaultToolkit().sync() metódust. Ez

azért fontos, mert az ablakozó rendszer várakoztatási sorba teheti az

újrarajzolási kérelmeket.

Page 60: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VII-56

4. A System.nanoTime() metódus által visszaadott értékből kiszámolja,

hogy meddig tartott ezeket a műveleteket elvégezni.

5. Ha az alapértelmezett periódus tovább tartott az alapértelmezett

periódusidőnél, és a két időtartam különbsége meghaladja az

overSleepTime értékét, a futtató szálnak várakoznia kell. Ha többet vár,

mint a különbség értéke, akkor az overSleepTime értékét beállítja a

többlet értékére.

6. Ha a periódus tovább tartott a beállított értéknél, akkor újra felhívja a

képernyő frissítési metódusát, hogy a következőként megjelenített kép

szinkronba kerüljön az elvárt működéssel.

7. Utolsó lépésként felhívja a switchContent() nevű metódust, ami, ha az

aktuális képernyő getNextContent() metódusa nem null-t ad vissza,

akkor az általa visszaadott értékkel felhívja a

setContent(AbstractEngine) metódust.

Page 61: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Játék készítése Java-ban

VIII-57

VIII. Összefoglalás

A szakdolgozat elkészítése során megismerkedtem a Java és a játékfejlesztés

kapcsolatával, majd a Java2D és a JavaSound API-kal. Utánanéztem az ilyen

jellegű játékoknál jelentkező leggyakoribb animációs problémáknak, és azok

megoldási lehetőségeinek. Megterveztem és megvalósítottam egy platformjátékot,

amiben szerepelnek az előzetesen felállított követelmények. A kivitelezés során

rengeteget segítettek a különböző játékfejlesztéssel kapcsolatos internetes

fórumok, amiken az egyes részfeladatok megoldásait kerestem.

Az elkészült játékon még lehetne fejleszteni:

Az ütközésdetektálás gyorsabb lenne, ha a pályán az egymás mellett lévő

blokkokat nagyobb téglalapokká csoportosítaná a program, hogy ne kelljen

mindegyiket külön vizsgálni. Az ezt megvalósító algoritmust még nem

implementáltam.

A játéktér elemeinek mozgatása hibás működéshez vezet, ennek

elkerüléséhez a blokk kereső metódusokat kell átírni.

A hátteret a program minden periódusban újrarajzolja, ami a periódus

időintervallumaihoz képest hosszú ideig tart. Ennek a javítására még

keresem a megoldást, amit talán a JPane rétegezés használata jelent majd.

A folyamatosan felmerülő problémák miatt olykor az osztályok hierarchiáján is

változtatni kellet, ez nagyban megnövelte a fejlesztési időt. Egy hasonló program

megvalósítása most már sokkal kevesebb ideig tartana, mivel a tervezésnél

felhasználnám az eddigi tapasztalataimat, de a megszerzett tudás hasznos lehet

más típusú grafikus alkalmazás készítésekor is.

Page 62: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai
Page 63: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Summary

During making of my thesis, I gained a good understanding of the relationship

between Java, the game industry, Java2D and the Java Sound API. I experienced

some of the animation problems with these type of games, and the possible

solutions. I planned and made the game, which implements in advance the

established requirements. During the execution I learned a lot from Internet

Forums about the Java Game Development, where I tried find some solutions for

the problems.

There are still some things to do with the game:

The collosion detection would be faster, if the program used containing

rectangles for the blocks. I have not made the algorythm for this feature yet.

The moving of the map elements cause invalid behaviour. The solution

would be the rewriting of the block finding methods.

The background is painted in every period, and it takes quite a long time

compared to the other operations. Maybe I should use some kind of JPane

layers for fixing this.

Because of the arising problems I had to rewrite the hirerarchy of the classes

many times, which increased the development time. Developing the same kind of

program would be faster for me in the future, because of my experience gained,

and the knowledge will be useful during any graphics application development in

the future.

Page 64: Játék készítése Java-banmidra.uni-miskolc.hu/JaDoX_Portlets/documents/document_15012... · Miskolci Egyetem Gépészmérnöki és informatikai kar Automatizálási és kommunikáció-technológiai

Irodalomjegyzék

Brian Cole, R. E. (2002). Java Swing, 2nd Edition. O'Reilly.

Davison, A. (2005). Killer Game Programming in Java. O'Reilly.

Ismeretlen. (dátum nélk.). Minecraft Wikipédia oldala. Letöltés dátuma: 2013.

április 10, forrás: Wikipédia: http://hu.wikipedia.org/wiki/Minecraft

Ismeretlen. (dátum nélk.). Oracle Java dokumentációk. Letöltés dátuma: 2013.

április 8, forrás: Oracle: http://docs.oracle.com/javase/

Ismeretlen. (dátum nélk.). Why is'nt Java more widely used for game development.

Letöltés dátuma: 2013. április 10, forrás: Programmers:

http://programmers.stackexchange.com/questions/55104/why-isnt-java-more-

widely-used-for-game-development