Budapesti Műszaki és Gazdaságtudományi Egyetem Villamosmérnöki és Informatikai Kar Automatizálási és Alkalmazott Informatikai Tanszék
Herber Máté
WINDOWS PHONE ALAPÚ JÁTÉK MOTORJÁNAK KÉSZÍTÉSE
KONZULENS
Albert István BUDAPEST, 2011
Tartalomjegyzék Tartalomjegyzék ............................................................................................................. 2 Összefoglaló ..................................................................................................................... 5 Abstract............................................................................................................................ 6 1 Bevezetés ....................................................................................................................... 7 2 A fejlesztés során megismert technológiák ................................................................ 8 2.1 Windows Phone 7 platform .................................................................................... 8 2.1.1 Történeti áttekintés .......................................................................................... 8 2.1.2 Architektúra ..................................................................................................... 8 2.1.3 Fejlesztőkörnyezet ......................................................................................... 10 2.2 .NET keretrendszer ............................................................................................... 11 2.2.1 Története ........................................................................................................ 11 2.2.2 Alkalmazás-végrehajtási modell .................................................................... 12 2.2.3 C# nyelv ......................................................................................................... 13 2.3 XNA keretrendszer és alternatívái ........................................................................ 14 2.3.1 DirectX........................................................................................................... 14 2.3.2 Felügyelt kódú DirectX programozói interfészek ......................................... 14 2.3.3 Az XNA keretrendszer................................................................................... 15 2.4 Silverlight.............................................................................................................. 16 2.4.1 XAML nyelv .................................................................................................. 17 2.4.2 Elrendezések .................................................................................................. 18 2.5 WCF szolgáltatások .............................................................................................. 20 2.5.1 Címek ............................................................................................................. 21 2.5.2 Szerződések ................................................................................................... 21 2.5.3 Kötések .......................................................................................................... 22 2.6 Windows Azure .................................................................................................... 24 2.6.1 Számítási felhő............................................................................................... 24 2.6.2 Azure Services Platform ................................................................................ 27 3 Játékmotorok Windows Phone 7 Platformra .......................................................... 29 3.1 TileMap IDE (tIDE) .............................................................................................. 29 3.1.1 xTile ............................................................................................................... 29 3.2 Farseer Physics Engine ......................................................................................... 30
3.3 Engine Nine .......................................................................................................... 31 3.4 FlatRedBall ........................................................................................................... 33 3.5 SunBurn Engine .................................................................................................... 33 3.6 ScriptTD................................................................................................................ 34 3.7 Összefoglalás ........................................................................................................ 35 4 VortexTD .................................................................................................................... 37 4.1 Tower Defense játékok ......................................................................................... 37 4.2 A játék tulajdonságai ............................................................................................ 38 4.3 A játék entitásainak tervezése ............................................................................... 39 4.3.1 Élőlények ....................................................................................................... 39 4.3.2 Tornyok és lövedékek .................................................................................... 40 4.3.3 Az út struktúrája............................................................................................. 43 4.4 Osztályhierarchia és folyamatok tervezése ........................................................... 43 4.4.1 Kapcsolat a grafikai motorral ........................................................................ 43 4.4.2 A játék felkonfigurálása ................................................................................. 45 4.4.3 Osztályok tervezése ....................................................................................... 45 4.4.4 Általános működés ......................................................................................... 57 4.4.5 Pályaszerkesztő, pályaletöltés ........................................................................ 61 4.5 Implementáció ...................................................................................................... 61 4.5.1 Az élőlények lépése ....................................................................................... 62 4.5.2 Tornyok műveletei ......................................................................................... 63 4.5.3 TickCounter időzítő működése ...................................................................... 66 4.5.4 Ütközések keresése új torony készítésénél .................................................... 67 4.5.5 Pálya betöltése XML fájlból .......................................................................... 69 4.5.6 Pályaszerkesztő és pályaletöltés kiszolgálása WCF szolgáltatással .............. 69 4.5.7 Pályaszerkesztő .............................................................................................. 71 4.5.8 A játék felkészítése a pályák letöltésére ........................................................ 74 5 Tesztelés, teljesítménymérés ..................................................................................... 76 6 Értékelés ..................................................................................................................... 77 6.1 Továbbfejlesztési lehetőségek .............................................................................. 78 Köszönetnyilvánítás ...................................................................................................... 79 Irodalomjegyzék............................................................................................................ 80
HALLGATÓI NYILATKOZAT Alulírott Herber Máté, szigorló hallgató kijelentem, hogy ezt a szakdolgozatot meg nem engedett segítség nélkül, saját magam készítettem, csak a megadott forrásokat (szakirodalom, eszközök stb.) használtam fel. Minden olyan részt, melyet szó szerint, vagy azonos értelemben, de átfogalmazva más forrásból átvettem, egyértelműen, a forrás megadásával megjelöltem. Hozzájárulok, hogy a jelen munkám alapadatait (szerző(k), cím, angol és magyar nyelvű tartalmi kivonat, készítés éve, konzulens(ek) neve) a BME VIK nyilvánosan hozzáférhető elektronikus formában, a munka teljes szövegét pedig az egyetem belső hálózatán keresztül (vagy autentikált felhasználók számára) közzétegye. Kijelentem, hogy a benyújtott munka és annak elektronikus verziója megegyezik. Dékáni engedéllyel titkosított diplomatervek esetén a dolgozat szövege csak 3 év eltelte után válik hozzáférhetővé. Kelt: Budapest, 2011. 12. 08.
..................................................................... Herber Máté
Összefoglaló Napjaink mobiltelefonjaira egyre inkább tekintünk többfunkciós szoftver platformként, mint csupán telefonálásra alkalmas eszközként. Az utóbbi években rendkívüli népszerűségnek örvendő okostelefonok nagymértékben felgyorsították a mobil szoftverfejlesztést. Egy felmérés [1] alapján az App Store 1 -ban megtalálható 500.000 alkalmazás mintegy 16 százaléka a játék szekcióban kerül feltöltésre, amely így a legtöbb alkalmazást számláló kategória. Ebből következik, hogy a játékfejlesztésben – mobil platformokra – hatalmas piaci potenciál van, ám a folyamatosan növekvő felhasználói igényeket egyre nehezebb kielégíteni. Szakdolgozatomban ezen feladat egy részének próbálok megfelelni. Egy hallgatótársammal közösen készített játék logikai motorját készítem el, míg ő a grafikai megvalósításért felelős. Valamint feladatom még a rendelkezésemre bocsátott webes felületbe integrálni az általam készített pályaszerkesztő modult, amely lehetővé teszi a játékosoknak a játék bővítését, így hozzájárul a jobb felhasználói élményhez. A játékhoz készített pályák egy felhőszolgáltatás tárába kerülnek, majd egy felhőben futó alkalmazás szolgálja ki a játékosok telefonját az új tartalommal. A dolgozat első felében ismertetem az általam használt technológiákat, valamint a tervezés során felmerült alternatívákat járom körül. A második részben foglalkozom részletesen az általam elkészített játéklogika ismertetésével, illetve a hozzá tartozó pályaszerkesztő modul bemutatásával. Mind a két rész két elkülöníthető egységre bontható, hisz a játék és a pályaszerkesztő elkészítéséhez különböző technológiákat kell felhasználnom, és implementációban is nagyban különböznek. A munkám hozzájárul, hogy a közös végtermék egy Tower Defense 2 típusú játék legyen Windows Phone 7 platformra, amelyhez tartozó webes szolgáltatás segítségével a játékosok különféle szolgáltatásokat kapnak, mely tovább növeli a játékélményt. Szakdolgozatom végén számos továbbfejlesztési, illetve javítási javaslatot teszek.
1
Egy online, alkalmazásokat árusító bolt, melyet az Apple fejlesztett ki.
2
A valós idejű játékok egy műfaja, melyben a térképet átszelő ellenségeket kell megállítani, azáltal, hogy lövéseket kapnak, ha elhaladnak a játékos tornyai mellett.
Abstract In our days mobile phones are more considered to be a complex software platform than a device simply for telephony. In recent years the extraordinary popularity of smartphones has greatly accelerated mobile software development. According to a survey [1] games come out at 16 percent of all 500,000 applications that have been uploaded to Apple Store1, so thus games is the category with the most applications. It follows that game development – to mobile platforms – has a huge market potential, while it is becoming more and more difficult to satisfy the continuously increasing user requirements. In my thesis I am trying to meet a part of these requirements. I develop the logical engine of a game made in conjunction with my fellow student, who is responsible for the graphics. My other task is to integrate a self-made map editor module into the given web frontend, which allows the user to extend the game, thus contributing to a better user experience. The maps made for the game are stored in a cloud service, and then an application hosted in the cloud serves the client mobile phones with content. In the first half of the dissertation I review the technology used, and examine the alternatives encountered in the design phase. In the second half I deal in detail with the description of the game logic and presentation of the map editor module. Both main chapters can be divided into two distinct parts, since creating the game required a different technology than building the map editor, and implementations differ greatly from each other as well. My work contributes to the final common product being a Tower Defense2 game for Windows Phone 7 platform, with a web frontend to which the players receive various services, which further enhances the gaming experience. At the end of my thesis I suggest several options for further development and correction.
1
An online shop to download applications developed by Apple.
2
Subgenre of real time strategy games, where player tries to stop enemy creatures from crossing a map by getting shot when they pass player’s towers.
1 Bevezetés Szakdolgozatom kettős célt szolgál. Az elsődleges cél, hogy megtervezzem és elkészítsem egy Windows Phone 7 platformon futó játék logikai motorját, valamint webes támogatást a hozzá kapcsolódó tartalmakhoz. A másodlagos cél természetesen az ezt megelőző kutatómunka, amellyel elmélyedhetek a felhasználandó technológiák mélységeiben, hogy megfelelő színvonalú alkalmazás születhessen. A bevezetés után a platform nyújtotta szolgáltatásokat fogom bemutatni, különös tekintettel a játék készítése során használt komponensekre, illetve a második részben a pályaszerkesztő fejlesztéséhez nélkülözhetetlen technológiákra. Arról, amivel nem ennek a feladatnak a kapcsán foglalkoztam először részletesen, például .NET keretrendszer, vagy nem volt feladatom részletesen megismerni, például XNA keretrendszer, csak egy pár összefoglaló mondatot írok, míg néhány részfunkcióra részletesebben kitérek. A
következő
részben
bemutatok
pár
általam
előzetesen
megvizsgált
játékfejlesztői komponenst, ezeket teszem mérlegre, így megfelelően megindokolhatom, hogy miért nem használom végül egyik komponenst sem a megvalósítás során. A leghangsúlyosabb rész két részből áll, egyik során bemutatom a játék tervezése során előkerülő problémákat, és a megoldást rájuk, végül ismertetem a kész tervet. A második részben az implementációval foglalkozom, a különféle tervezett elemek konkrét megvalósításának részletei kerülnek tárgyalásra. Végül ismertetem a pályaszerkesztő létrehozásának folyamatát, mely elkülönül egy webes modul létrehozására, valamint a felhővel fenntartott kapcsolat kiépítésére mind a mobil, mind a webes felületen. Legvégül összegzem a feladatot, és a tapasztalataimat, ezenkívül felsorolok még rengeteg lehetséges tennivalót, melyekkel igazán felhasználóbaráttá és élvezhetővé válhat a játék.
7
2 A fejlesztés során megismert technológiák 2.1 Windows Phone 7 platform 2.1.1 Történeti áttekintés A Windows Phone 7 mobil operációs rendszer a Windows Mobile termékvonalat váltotta le az okostelefonok piacán, és egyúttal a vállalati szféra helyett a fogyasztói piacot célozta meg. A fejlesztés 2008-ban kezdődött, és már 2010 októberében megjelent. 2011 februárjában a Nokia és a Microsoft vezetői bejelentették, hogy a Nokia jövőben készülő okostelefonjainak elsődleges operációs rendszere a Windows Phone 7 lesz. 2011 októberében megjelent a Mango kódnevű frissítés, mely rengeteg újdonságot hozott, valamint orvosolta a platform korábbi számos hiányosságát.
2.1.2 Architektúra A rendszer a Windows CE hetes verziójú kernelére [2] épül. Az 1996 óta fejlesztett kemény valósidejű rendszert rengeteg beágyazott rendszerben alkalmazzák sikerrel, így nem csoda, hogy a Windows Phone 7 alapjául szolgálhat. Az
operációs
rendszert
futtató
eszközök
számára
szigorú
hardver
követelményeket írtak elő, így minden Windows Phone 7-et futtató telefon garantáltan jó minőségű felhasználói élményt biztosít. Elvárás többek között a négy érintési pontot és 480x800 felbontást támogató kijelző, ARM architektúrájú processzor, DirectX9 kompatibilis videokártya, 256 MB memória, stb. Továbbá minden készüléknek rendelkeznie kell iránytűvel, fényérzékelővel, gyorsulásmérővel, A-GPS vevővel valamint 5 megapixeles kamerával. Az előírás segítségével a fejlesztő biztos lehet abban, hogy támaszkodhat ezen eszközökre az alkalmazásának futtatása során. Az egyes hardverelemeket közvetlenül a kernel kezeli. A kernel feletti réteg három különálló részre tagolódik. Az alkalmazásmodell felelős az alkalmazásokkal kapcsolatos műveletek elvégzéséért, mint például az izolációs tárak kialakítása, a frissítés valamint az alkalmazás jogosultságok kezelése. A felhasználói felületmodell felel a grafikus felületek összeállításáért, Direct3D támogatásért, munkamenetek kezeléséért. A harmadik blokk feladata a felhő integráció megvalósítása, melynek használatával számos közösségi szolgáltatást tudunk igénybe 8
venni. Ilyenek például a Windows Live szolgáltatásai, az Xbox LIVE közösségi játékcsatorna, a Bing kereső, stb.
1. ábra - Windows Phone 7 Architektúra
A legfelső réteg alapja természetesen a .NET keretrendszer virtuális gépe a CLR, mely fordítja és futtatja a beépített .NET komponensekre épülő felhasználói alkalmazásokat [3]. A rendszer három különböző technológiát támogat az alkalmazásfejlesztéshez. A Silverlightban készült alkalmazások natív megjelenést kapnak az operációs rendszeren belül, valamint az alapkinézethez hasonlító vezérlőket használhat a fejlesztő, ezáltal a keretrendszer tökéletes felhasználói programok készítésére. Az XNA keretrendszer használatával komplex játékokat készíthetünk, támogatja mind a 2D, mind a 3D megjelenítést, valamint párhuzamos hangeffektek lejátszását, melyek fokozzák a felhasználói élményt. Az új HTML szabvány, a HTML5 felhasználásával platformfüggetlen alkalmazásokat tudunk készíteni, melyet bármelyik HTML5 kompatibilis böngészőben tudunk élvezni. A Mango frissítés már tartalmazza
9
az Internet Explorer böngésző kilences verzióját, mely segítségével lejátszhatók a HTML5 alkalmazások. A Windows 8 új, érintőképernyőkre optimalizált felületére is HTML5 nyelven lehet alkalmazásokat fejleszteni. A rendszerben megtalálható .NET keretrendszer a desktop 3.5 verziójú keretrendszerhez hasonlít leginkább, néhány komponenstől eltekintve, de megtalálható a négyes keretrendszer néhány eleme is, például az opcionális paraméterek lehetősége. Természetesen a Silverlight és XNA keretrendszerben megtalálhatjuk a desktop környezetben, illetve Xbox rendszeren megismert osztálykönyvtárak jelentős részét. Végül rendelkezésre állnak telefon specifikus könyvtárak, melyek segítségével tudjuk vezérelni a szenzorokat és a kamerát, továbbá launcherek és chooserek [4], melyek segítségével a telefon OS bizonyos szolgáltatásait programozottan érhetjük el, illetve a legújabb verzióban a többfeladatosságot támogató komponens.
2.1.3 Fejlesztőkörnyezet A Windows Phone 7 rendszerhez használt fejlesztőkörnyezet első változata 2010 márciusában debütált, azóta folyamatosan fejlesztik. A Mango frissítés megjelenésével természetesen a fejlesztőeszköznek is megjelent a legújabb változata, mely tartalmazza a Mango újításait. Az SDK a Visual Studio 2010 integrált fejlesztőkörnyezetre épül, azt vértezi
fel
a
telefonra
történő
fejlesztéshez
szükséges
eszközökkel
és
osztálykönyvtárakkal. A Windows Phone fejlesztői csomag tartalmazza a telefon által használt compact framework binárisait, mely megteremti a programozási platform alapját. Tartalmazza továbbá a Silverlight SDK legújabb verzióját, mely segítségével elérhetjük a WP7 specifikus Silverlight vezérlőket és a Metro elvnek megfelelő letisztult felületeket tudunk létrehozni. Külön komponensként letölthető egy Silverlight Toolkitnevű eszközkészlet, amely rengeteg kitesztelt komponenst biztosít az alapértelmezettek mellé. Telepítésre kerül az XNA Game Studio, valamint az XNA keretrendszer könyvtárai, amelyeket a nagy teljesítményű vagy komplex játékok fejlesztésére használhatunk. Természetesen mindkét fejlesztőeszköz létrehozza a saját projekt- és fájlsablonjait, ez lehetővé teszi az alkalmazások létrehozását. A SilverLight felületek létrehozásához segítségül kapjuk az Expression Blend vektorgrafikus programot, ennek segítségével rendkívül komplex, animált felületeket tervezhetünk, támogatja a dizájn nézetet, minden funkciót a rendelkezésre bocsát, hogy minél kevesebb XAML kódot kelljen kézzel megírnunk. Ezzel a szolgáltatáslistával 10
egyértelműen elsősorban a grafikus tervezőket veszik célba, akiknek ez által nem szükséges mély .NET vagy C# tapasztalattal rendelkezni a felület létrehozásához. A legfontosabb fejlesztőeszköz a telefonhoz a Windows Phone Emulator, mely egy Windows Phone 7 alapú komplett rendszert virtualizál. Használatával lehetőség nyílik a létrehozott alkalmazás tesztelésére, hibakeresésére. Gyakorlatilag majdnem minden funkciót támogat, amit az igazi készülék is, még több érintési pontot is kiválthatunk több egér, meg egy szoftver segítségével. Természetesen regisztráció után lehetőség nyílik egy Windows Phone 7 alapú telefonon is a fejlesztői alkalmazások kipróbálására, tesztelésére. Külön kellemes meglepetés, hogy a készüléken is működik a valós idejű hibakeresés.
2.2 .NET keretrendszer A .NET egy szoftver keretrendszer rengeteg osztálykönyvtárral, melyet igénybe vehet minden .NET kompatibilis nyelvet használó fejlesztő. Elsősorban Microsoft Windows operációs rendszeren fut, bár léteznek a .NET egy részhalmazát megvalósító platformfüggetlen megoldások is. A rendszert arra tervezték, hogy az új Windows operációs rendszerre írt alkalmazások felhasználják a keretrendszer osztályait, így rendkívül gyorsan fejleszthetők komplex vékony és vastagkliens alkalmazások. A keretrendszerre írt programok egy CLR nevű virtuális gépben futnak, amely olyan fontos szolgáltatásokat nyújt, mint memória- és kivételkezelés.
2.2.1 Története A keretrendszer fejlesztése az 1990-es évek végén kezdődött, majd 2000 vége felé megjelent az első bétaverzió, majd 2002-ben megjelent a végleges változat is, mely már tartalmazta a keretrendszer alapjait, azonban még nagyon instabil volt. Egy évvel később megjelent az első nagy frissítés, a .NET 1.1, amely rengeteg hibajavítást tartalmazott, és bevezette a Compact Framework változatot is, melyet mobil és beágyazott rendszerekben használnak. Az első igazán használható változat a 2005-ben megjelent .NET 2.0, ekkor kezdett a keretrendszer széles körben alkalmazottá válni. Rengeteg újítást hozott, kezdve a generikus osztályokkal, SQL támogatással, rengeteg ASP.NET és WinForms
11
fejlesztéssel egészen az új nyelvi elemekig, mint a Nullable 3 típusok, Névtelen metódusok és típusok valamint iterátorok. A Windows Vista korai megjelenésével egyidőben megjelent a keretrendszer 3.0-ás verziója, mely gyakorlatilag négy új, különálló komponenst tartalmazott a keretrendszer előző verziójához, ezek a WPF, WCF, WF és Windows CardSpace. Megjelenésekor a komponensek számos hiányossággal és hibával küzdöttek, valamint nem készültek hozzájuk megfelelő fejlesztőeszközök, így a használatuk rendkívül nehézkes volt. Ezt orvosolandó egy évvel később megjelent a 3.5-ik változat, mely javította az előző verzió gyermekbetegségeit, és kibővítette a BCL-t a LINQ technológiával. Megjelent a Visual Studio legújabb, 2008-as változata is, mely támogatta a keretrendszerben megjelent új komponensek kényelmes használatát. 2010-ben adták ki a keretrendszer negyedik verzióját, ahol az összes .NET komponens verzióját konzisztensen 4-re állították. Megjelent a párhuzamos LINQ támogatás (Parallel LINQ), valamint a Task Parallel Library, amely osztálykönyvtár segítségével feladatok párhuzamos végrehajtásának szervezésére kapunk hatékony eszközöket. Megjelent pár új nyelvi elem, mint a dynamic kulcsszó, nevesített és opcionális paraméterek. Valószínűleg a Windows 8 operációs rendszerrel egyidőben fog megjelenni a keretrendszer következő változata, melynek fejlesztői bétaverziója már elérhető. Támogatja nyelvi szinten az aszinkron operációkat, rengeteg újítást tartalmaz mind a WPF, mind az ASP.NET komponens, az utóbbinak főleg a HTML5 támogatása lesz nagymértékben javítva, ugyanis úgy néz ki, hogy ezzel a technológiával lehet majd Metro stílusú alkalmazásokat létrehozni az újszerű Windows 8 felületre.
2.2.2 Alkalmazás-végrehajtási modell Az adott nyelven íródott forráskódot, az adott nyelvű, .NET keretrendszerrel kompatibilis fordító egy köztes nyelvre fordítja, ezen az absztrakciós szinten eltűnnek a nyelvek közötti különbségek, bármely nyelvi megvalósítás kis eltéréssel ugyanolyan köztes kódra fordul. Ezután az osztálybetöltő betölti az általunk készített logika köztes nyelvi reprezentációját valamint az általunk hivatkozott .NET osztálykönyvtárak kódját a JIT fordító számára. A JIT fordító pontosan az első használat előtt fogja lefordítani a még lefordítatlan köztes nyelvi forrásfájlokat, majd a lefordított, immár natív kód végrehajtásra kerül. Ha a továbbiakban nem lefordított kódot hív az alkalmazás, a
3
Típusok kiterjesztése, így a megszokott értékükön kívül null értéket is felvehetnek.
12
vezérlés visszakerül a JIT fordítóra, amely lefordítja a megfelelő kódrészletet. A futtatókörnyezet gondoskodik a folyamatos biztonsági ellenőrzésről. A folyamat [5] vizuálisan az alábbi ábrán látható. Megbízható előfeldolgozott kód esetén
Osztálykönyvtárak (IL & Metaadat)
Forráskód
Osztály betöltő EXE/DLL (IL & Metaadat)
Fordító
Menedzselt natív kód JIT fordító
Lefordítatlan metódushívás esetén Biztonsági ellenőrzés
Végrehajtás
Futtatókörnyezet
2. ábra - Alkalmazás végrehajtás folyamata
2.2.3 C# nyelv A .NET nyelvek közül messze a legelterjedtebb a C#, melyet rengeteg, már létező nyelv figyelembe vételével alkottak meg. Így sikerült létrehozni egy nyelvet, amelynek a szintaktikája olyan tiszta, mint a Java-é, egyszerű, akár a Visual Basic, valamint szolgáltatja a C++ rugalmasságát. A továbbiakban felsorolom a nyelv főbb funkcióit:
Akár a többi felügyelt nyelvben, itt sem szükséges mutatókkal dolgozni (bár van rá lehetőség), a memóriát szemétgyűjtő szabadítja fel, így nincs szükség delete kulcsszóra sem.
Formális szintaktika a következő logikai egységeknek: osztály, interfész, struktúra, felsorolás, delegát.
C++-ból megszokott operátor-túlterhelés.
Attribútumok támogatása, mellyel pontosíthatjuk az attribútummal ellátott elem viselkedését.
Támogatja a generikus osztályokat.
Rendelkezésre állnak névtelen delegátok vagy típusok közvetlenül beékelve a használat helyére.
Nagymértékben leegyszerűsített delegát/eseménymodell. 13
Parciális osztályok támogatása, mellyel elkülöníthetjük a generált kódot az általunk készítettől.
Erősen típusos lekérdezések megfogalmazása LINQ nyelven többféle típusú adatra.
Kiegészítő metódussal kiterjeszthető egy zárt osztály működése.
Lambda kifejezés szintaktikailag átláthatóvá teszi a delegátok használatát.
Objektumlétrehozással
egyidőben
lehetőség
van
a
tulajdonságok
inicializálására.
Opcionális paraméterek, illetve nevezett paraméterek támogatása.
A dynamic kulcsszó segítségével futási időben kérdezhetjük le az objektumok tagváltozóit vagy metódusait. Mivel a C# alapvetően típusos nyelv, használata csak indokolt esetben ajánlott.
2.3 XNA keretrendszer és alternatívái 2.3.1 DirectX A Windows 95 előtti időkben a játékfejlesztőknek alacsony szintű kódot kellett írniuk, hogy közvetlen kommunikáljanak a hang- illetve videokártyával, ebből aztán rengeteg probléma adódott, hisz különböző gyártók különböző módon kezelhették a megszakításokat, vagy I/O műveleteket, így ami működött az egyik rendszeren, nem feltétlenül működött a másikon. Windows 95-ben nem volt már lehetőség arra, hogy alacsony szinten programozzák a hardvert a játékfejlesztők, így megjelent a DirectX első verziója, amely lehetővé tette, hogy egy játék változatlanul fusson minden DirectX kompatibilis videokártyán, melynek a hardver specifikus felületét elrejti a HAL driver, így a DirectX hívások felé egy jól meghatározott interfészt mutat. Megjelent továbbá egy emulációs réteg is, mellyel egy jelen nem lévő hardvert lehet virtualizálni, így, bár a szoftveres emuláció sokkal lassabb, mégis céleszköz nélkül futtathatunk bizonyos játékokat [7].
2.3.2 Felügyelt kódú DirectX programozói interfészek 2.3.2.1 Managed DirectX A Microsoft által 2002-ben kifejlesztett Managed DirectX tekinthető az XNA elődjének. Segítségével egy felügyelt DirectX programozói interfészt kapunk, mely
14
nagymértékben
leegyszerűsíti
az
eredeti
API-t,
valamint
objektumorientált
tulajdonságokkal ruházza fel. Fejlesztését már leállították, átadta a helyét az XNA platformnak, a grafikai interfészek közül a Direct3D 9 az utolsó támogatott verziója. 2.3.2.2 SlimDX Az egyik legtöbb szolgáltatást nyújtó DirectX interfész a .NET nyelvekhez. Támogatja a .NET negyedik verzióját, a 64 bites architektúrát valamint a DirectX 10. és 11. verzióját is. Sebessége megközelíti a natív változatét, és a mérések alapján gyorsabb, mint az XNA. További előnye, hogy a projekt nyílt forráskódú, így a kevés példakód ellenére is használható. 2.3.2.3 SharpDX A SlimDX-hez hasonló nyílt forráskódú szoftver, melynek különlegessége, hogy kódgenerátor segítségével készül a natív C++ forrásfájlokból. Ennek kivitelezéséhez a szerző egy okos algoritmust készített, hogy megfelelően kerüljenek fordításra a függvényhívások. A szerző saját mérései szerint [6] ez a leggyorsabb felügyelt API a DirectX-hez. A későbbi verziókban várható egy, az alacsony szintű API-ra épülő, XNAhoz hasonló magasabb szintű keretrendszer (ANX).
2.3.3 Az XNA keretrendszer Microsoft XNA lett a cég játékfejlesztést támogató eszközeinek összefoglaló neve. 2004-ben jelentették be az Xbox New Architecture kódnevű terméket, amelynek elsődleges célpontja a jövőben megjelenő Xbox 360 platform volt, ám a 2006 évi első megjelenéskor már a nyílt forráskódú világban nagy népszerűségnek örvendő rekurzív mozaikszóként mutatták be a rövidítés feloldását: XNA is Not an Acronym. Az XNA eszközkészlet tagja maga a keretrendszer is, mely lehetővé teszi, hogy a felhasználásával készült játékok változtatás nélkül, vagy minimális változtatással futhassanak minden XNA-t támogató rendszeren [7]. Jelenleg támogatják a keretrendszert a Windows család XP-vel kezdődő tagjai, illetve az Xbox 360 és Windows Phone 7 platformok. Hogy a platformfüggetlenséget elérhetővé tegye, a keretrendszer egy játékra optimalizált futtató környezetben (CLR) fut, így felügyelt futási környezetet biztosít a játékok számára. Ezenkívül rengeteg, játékokban gyakran
15
használt, kiterjeszthető osztálykönyvtárat bocsát rendelkezésre, így elősegíti a kód újrahasznosítását a célplatformok közötti migrálás esetén. Windows operációs rendszerek esetén a keretrendszer alapja a .NET 2.0, míg Xbox 360 és Windows Phone 7 platformok esetén egy kompakt .NET 2.0 keretrendszer. Bár elvileg a keretrendszer bármely .NET kompatibilis nyelven programozható, az eddigi fejlesztőkörnyezetek kizárólag a C# nyelvet támogatták. A Windows Phone 7 Mango-val megjelenő fejlesztői környezet azonban a C# mellett már VB.NET támogatással érkezett. Az XNA a megjelenítéshez a natív Direct3D 9-edik verzióját használja, bár a külső programozói interfész nem teljesen egyezik a natív változatéval, legtöbb esetben megtalálható a hiányzó natív hívás XNA-s megfelelője.
2.4 Silverlight A piacvezető Adobe Flash technológiához hasonlóan a Silverlight egy gazdag böngészőalkalmazások
futtatására
alkalmas
keretrendszer.
A
futtatókörnyezet
böngészőbeépülő formájában érhető el Windows és Mac OS X operációs rendszerek alatt, bár nem minden böngésző támogatott. Míg a korábbi verziók a streamelt médiára fektették a hangsúlyt, a későbbi verziók támogatják a különböző grafikus vezérlőket, animációt és multimédiás tartalmakat is, illetve a CLI-t megvalósító nyelveket. Ennek köszönhetően a Silverlight a Windows Phone 7 egyik natív alkalmazásfejlesztő platformja.
Elkészítésénél a már létező WPF technológiát vették a fejlesztők alapul. Ennek megfelelően a felhasználói felület egy XML-hez hasonló, úgynevezett XAML leíró nyelven kerül definiálásra. A mögöttes logika egy Silverlightra optimalizált .NET keretrendszerre épül, mely a hagyományos keretrendszernek csupán egy részhalmazát tartalmazza. Moonlight néven készül a nyílt forráskódú implementációja az első két változatnak. A Novel és a Microsoft egyezségéből adódóan a Mono fejlesztőcsapata támogatást kap a Silverlight fejlesztőitől, hozzáférhetnek az eredeti BCL programozói interfészhez és a különféle tesztmodulokhoz [8]. Annak ellenére, hogy készül a Moonlight projekt, sokan azon a véleményen vannak, hogy sosem valósul meg a
16
különféle platformok teljes támogatása, így a Silverlight sosem lesz olyan népszerű, mint a konkurens Flash technológia. Silverlight alkalmazások fejlesztésére két eszköz is rendelkezésre áll. A Visual Studio 2010 fejlesztőkörnyezet támogatja a Silverlight felületek készítését grafikus szerkesztéssel, illetve XAML szerkesztéssel, illetve a mögöttes kód szerkesztését, hatékony kódkiegészítés, verziókezelés, hibakeresés szolgáltatásokkal. Az Expression Blend ezzel szemben elsősorban a felület igényes kialakításának érdekében bocsát rendelkezésre rengeteg Visual Studio-ból hiányzó eszközt. Segítségével vizuálisan készíthetünk el bonyolult gradienseket vagy akár animációkat is, melyet Visual Studioban csak XAML kód írásával tudunk kényelmesen megtenni. Készíthetünk alkalmazásprototípusokat is a SketchFlow technológia segítségével. Megtalálható ugyan XAML és kódszerkesztő is, de hiányzik a Visual Studio rengeteg szolgáltatása.
2.4.1 XAML nyelv Az XAML egy jelölőnyelv, amely segítségével .NET objektumokat tudunk példányosítani és inicializálni. Bár számos problémakörben használható, eredetileg a WPF részeként alkották meg. Feladata, hogy segítségével egyszerűen tudjanak a fejlesztők tartalomban gazdag, interaktív felületeket leírni. Koncepcióját tekintve az XAML szerepe nagyon hasonló a weblapok XHTML nézetéhez. Mindkét esetben címkékkel definiálhatjuk a nézeten megjelenő vezérlőket, melyek végül a kész nézetet szolgáltatják, illetve a címkék attribútumait használva állíthatjuk be az egyes vezérlők különféle tulajdonságait. Nevet is adhatunk az egyes objektumoknak, hogy később hivatkozni tudjunk rájuk, ám név nélkül is állhatnak, ha később az elemeket nem szeretnénk név alapján elérni. XHTML esetén JavaScript kóddal, míg XAML esetén C#, esetleg más .NET kompatibilis nyelvű kóddal tudjuk manipulálni. Természetesen az XAML kifejezőereje nagyobb, mint az XHTML-é, számos nyelvi funkciót meg lehet valósítani XAML leírás segítségével. Minden leírás elején meg kell adnunk, hogy milyen névtereket alkalmazunk, hisz így tudjuk elkülöníteni és az interpreter számára definiálni az osztályainkat. A tulajdonságoknak a címke attribútumok segítségével adhatunk értéket, ám előfordulhat, hogy egy tulajdonság összetett típust vár értékként, ekkor az adott címkén belül egy gyerek címkével hozhatjuk létre az összetett objektumot. A címke pontokkal elválasztva tartalmazza a tartalmazó osztály valamint a beállítani kívánt tulajdonság nevét. A tulajdonságoknak nemcsak konkrét értéket lehet adni, hanem adatkötéssel 17
összeköthetjük egy másik objektum tulajdonságával. Ehhez arra van szükség, hogy a tulajdonság, amihez kötünk, egy úgynevezett függőségi tulajdonság legyen, a hozzá kötött tulajdonság pedig változása esetén kiváltsa az érték változását jelző eseményt a saját nevével, így a kötés másik oldalán értesülhetünk róla [9]. A kötésnek három módja van, azaz választhatunk, hogy egyirányú, kétirányú kötésre, vagy esetleg egyszeri kötésre van szükségünk. Az eseményekre a szokásos elven tudunk feliratkozni, azaz az esemény tulajdonságnak megadunk egy megfelelő fejlécű delegátot, melyet általában a XAML állományhoz tartozó C# forrásfájlban tudunk megvalósítani. Az MVVM architektúrában 4 általában nem kívánunk feliratkozni közvetlen eseményekre, így elkerülhető, hogy a nézet kódjában kezeljük le azt. Helyette egy parancs tulajdonsághoz köthetjük az általunk létrehozott nézetmodell parancskezelő függvényét, amely majd kiváltódik az esemény kapcsán.
2.4.2 Elrendezések A Silverlight szerencsére örökölte a WPF-től az újgenerációs elrendezésmodellt a régi koordináta alapú megközelítés helyett. Ebben a környezetben általában igaz, hogy az elrendezéspaneleken kívül minden vezérlő pontosan egy elemet tartalmazhat, így például egy ablakon is egy elem helyezkedhet csak el. Azonban a konténerek segítségével elérhető, hogy több vezérlőt helyezzünk el az „ablakon”, ám ténylegesen ezen vezérlők szülője a konténer, így egy szinttel lejjebb kerültek a logikai fában. Ezzel a módszerrel nem sérül, hogy az ablak csak egy elemet tartalmazhat, ez az elem a konténer.
3. ábra - A Panel osztály hierarchiája [9]
4
A Model View ViewModel architektúra az MVC útódja, elsődleges szempontja az egyes
komponensek közötti kapcsolat lazítása, valamint egy adathalmaz többféle nézetének támogatása.
18
Az konténerek határozzák meg a gyerek elemeik elrendezését attól függően, hogy mi a típusuk. Minden konténer a System.Windows.Controls.Panel osztályból származik, ami felruházza egy háttértulajdonsággal, melynek megadható, hogy milyen ecsettel legyen a konténer háttere kifestve. Ezen kívül kap egy gyűjteményt, melyben az általa tartalmazott elemek kerülnek tárolásra. Önmagában a Panel osztály még nem elég az elemek elrendezésére, de megfelelő alap a leszármazott osztályoknak, amik tartalmazzák az elrendezést megvalósító logikát. A System.Windows.Controls névtérben található néhány megvalósítás, ám az ambiciózusabbak saját elrendező panelt is készíthetnek. 1. táblázat - Alapértelmezett elrendezés panelek [9]
Név
Leírás
StackPanel
A benne elhelyezett elemeket vízszintes vagy függőleges sorba helyezi. Leginkább
komplex
oldalak
kisebb
szekcióinak
elrendezésére
használják. WrapPanel
A benne elhelyezett elemeket vízszintes vagy függőleges sorba helyezi, ám ha eléri a rendelkezésre álló szélesség, vagy magasság határát, nem nyújtózkodik, hanem új sort, vagy oszlopot kezd. Így gyakorlatilag sortörést alkalmaz a vezérlőkön. Ez a konténer a Silverlight eszközkészletben érhető el.
DockPanel
A panel kerületén tudjuk elhelyezni a gyerek elemeket. Csatolt tulajdonság segítségével választhatunk a négyféle, felső, jobb, alsó, bal oldal közül. Egy oldalra több elemet is tehetünk. Ha a LastChildFill tulajdonságot igazra állítjuk, akkor az utolsó elem kitölti a rendelkezésre álló helyet, így „középső” elemnek is tekinthető. Ez a konténer is a Silverlight eszközkészletben található meg.
19
A leguniverzálisabb konténer. Sorokat és oszlopokat definiálhatunk
Grid
benne,
amelyeknek
viszonyított
megadhatjuk
nagyságát.
A
benne
abszolút
illetve
elhelyezett
egymáshoz
elemek
csatolt
tulajdonságai alapján határozzuk meg, hogy hányadik sor hányadik oszlopában helyezkedjenek el, illetve hogy mennyi sort és oszlopot foglaljanak el. A WrapPanel és Canvas kivételével minden konténer funkcionalitását tartalmazza. A régi időkből megszokott módon működő konténer, ahol abszolút
Canvas
koordinátát adhatunk meg az elemeknek. Ez a legegyszerűbb, ám a legkevésbé rugalmas megoldás, így használata nem javasolt. Természetesen a konténerek egymásba is ágyazhatók, így rendkívül komplex felületek hozhatók létre.
2.5 WCF szolgáltatások A WCF (Windows Communication Foundation)
egy szoftverfejlesztő
eszközkészlet, amely segítségével szolgáltatásokat tudunk létrehozni, majd telepíteni Windows környezetben. Elméletben mindenki tud szolgáltatásokat létrehozni a WCF keretrendszer nélkül is, de a gyakorlatban a Microsoft által létrehozott ipari szabványokat megvalósító, több protokollt támogató megoldás olyannyira leegyszerűsíti az implementációt, ezáltal felgyorsítva a fejlesztési folyamatot, hogy kár lenne figyelmen kívül hagyni. A szolgáltatás egy bizonyos funkciót megvalósító egység, amely publikálás után bárki
által
használható.
Az
objektumorientált,
illetve
komponensorientált
programozáshoz hasonlóan a szolgáltatásorientált programozásban is egy alkalmazás logikailag összefüggő csoportba helyezi az általa használt szolgáltatásokat, ezek felhasználásával végzi el a komplex feladatát. A szolgáltatások lehetnek helyiek vagy távoliak, készülhetnek különböző gyártók által, eltérő technológiákkal, mivel azonban a kliens és szolgáltatás között csak laza kapcsolat van, ezek a különbségek elfedhetők. A kliensek a szolgáltatással üzenetek formájában kommunikálnak, a WCF esetében ezek általában SOAP üzenetek. A kommunikáció sosem történik közvetlenül, a kliens mindig egy úgynevezett proxy
20
objektumon keresztül hív, melynek a metódusai megegyeznek a szolgáltatáséval, leszámítva néhány proxykezelő metódust. A WCF szolgáltatások három alapfogalomra építenek [10]:
Cím: Megmutatja, hogy hova címezzük az üzeneteket.
Szerződés: Leírja, hogy mit garantál a szolgáltatás, tartalmazza a szolgáltatás funkcióit, melyet a kliens használhat.
Kötés: Tartalmazza, hogy az üzenetküldés pontosan hogyan, milyen paraméterekkel és milyen csatornán megy végbe.
4. ábra - WCF végpontok tulajdonságai
2.5.1 Címek A szolgáltatás címe két fontos paramétert határoz meg, a szolgáltatás helyét és az átviteli protokollt. A hely tartalmazza a célgép vagy hálózat nevét, a kommunikációs portot, csővezetéket vagy üzenetsort, illetve egy opcionális elérési utat vagy URI-t. A támogatott átviteli sémák:
HTTP/HTTPS (http)
TCP (net.tcp)
IPC (net.pipe)
Peer Network (net.p2p)
MSMQ (net.msmq)
Service bus (sb)
2.5.2 Szerződések A
WCF-ben
minden
szolgáltatás
publikál
egy
szerződést,
amely
platformfüggetlen szabványos leírása annak, hogy mit csinál a szolgáltatás. Négyféle szerződés van, mely meghatározza a szolgáltatás működését:
21
2. táblázat – Szerződések [10]
Szerződés
Leírás
Service Contract
Megadja, hogy a kliens milyen operációkat tud hívni a
(Szolgáltatás szerződés)
szolgáltatáson.
Data Contract
Definiálja a szerződés ki- és bemeneti adatainak lehetséges
(Adat szerződés)
típusait. A beépített típusokhoz a WCF tartalmaz megfelelő szerződést, de lehetőség van a saját típusokhoz is megfelelő adat szerződés létrehozására.
Error Contract
Leírja a szolgáltatás által kiváltott kivételeket, valamint
(Hiba szerződés)
hogy a szolgáltatás hogyan kezeli, illetve milyen módon tudatja a klienssel ezeket a hibákat.
Message Contract
Lehetővé
teszi,
hogy
a
szolgáltatások
közvetlenül
(Üzenet szerződés)
üzenetekkel kommunikáljanak. Az üzenet szerződések lehetnek típusosak vagy típus nélküliek, és akkor használatosak, ha az egyik kommunikáló fél kötött üzenetformátumot használ. Általában azonban nem ez a helyzet a WCF esetében, így ez a szerződés kerülendő, hisz használata esetén le kell mondanunk a szolgáltatás és adat szerződések által leírt sorosított osztályok képében történő automatikus üzenetkezelésről.
2.5.3 Kötések Egy kommunikáció leírásához rengeteg paraméter meghatározására van szükségünk. Az üzenetküldés lehet szinkron vagy aszinkron, egyirányú vagy kétirányú, az üzenetek kézbesítése történhet közvetlenül vagy üzenetsorokon keresztül, stb. Ezen paraméterek permutációi rengetegféle kommunikációt eredményezhetnek, azonban sok esetben a tulajdonságok csoportjai egymással logikailag összefüggenek, így az egyik meghatározása implikálja a többi változását. Hogy megkönnyítse a paramétercsoportok meghatározását, a WCF úgynevezett kötéseket definiál, melyek összefogják és definiálják a kommunikációhoz szükséges aspektusokat az általános szkenáriókban.
22
A WCF öt darab sűrűn használt kötést definiál, ezek tucatnyi konfigurálható tulajdonságot adnak a szolgáltatás készítőjének kezébe. Természetesen, ha egyik kötés sem illeszthető a felvetődött problémára, akkor egyedi kötést készíthetünk, vagy specializálhatunk már meglévő kötéseket.
BasicHttpBinding: Arra tervezték, hogy a szolgáltatást szabványos ASMX webszolgáltatásként publikáljuk, így a régi kliensek tudnak kommunikálni az új szolgáltatásokkal. Természetesen, ha kliens oldalon használjuk, elérhetjük, hogy az új WCF kliensek kommunikálni tudjanak régi ASMX webszolgáltatásokkal.
NetTcpBinding: TCP kapcsolatot használ a szolgáltatás és kliens közötti kommunikációhoz,
amely
biztosítja
a
megbízható
kapcsolatot,
tranzakciókezelést és a biztonságos adatátvitelt. WCF kliens és WCF szolgáltatás közötti kommunikációra optimalizálták, így szükséges, hogy mindkét fél a WCF-et használja.
NetNamedPipeBinding5: IPC kötés, amely névvel ellátott csővezetékeket használ a kommunikációra. Ez a legbiztonságosabb kötés, hisz nem fogad hívásokat a gép belső határán kívülről. Rendelkezik a TCP kötés számos tulajdonságával, valamint nagyobb teljesítményű is, hisz az IPC sokkal egyszerűbb protokoll, mint a TCP.
WSHttpBinding: HTTP vagy HTTPS protokollt használ az átvitelre, és a TCP
kötéshez
hasonló
tulajdonságokkal
rendelkezik.
Elsődleges
felhasználása az interneten keresztül kommunikáló WS-* szabványokat használó szolgáltatások és kliensek együttműködésének lehetővé tétele.
NetMsmqBinding: MSMQ-t használ adatátvitelre, ami lehetővé teszi az üzenetsorokon alapuló, nem kapcsolatorientált hívásokat.
Az alábbi folyamatábra segít választani az öt leggyakrabban használt kötés közül az aktuális igényeknek megfelelően.
5
Ez az elnevezés inkonzisztens a többi kötés nevével, hisz a konvenció az átviteli protokollt
tartalmazza a névben, nem pedig az átviteli mechanizmust. Helyesen NetSocketBinding lenne a neve [10].
23
5. ábra - A kötésválasztás folyamata [10]
2.6 Windows Azure 2.6.1 Számítási felhő A számítási felhő egy napjainkban rendkívül népszerű marketing kifejezés arra a technológiára, amely számítási, szoftver, adathozzáférési és tárolási szolgáltatásokat nyújt olyan módon, hogy a végfelhasználó nem ismeri a szolgáltatások fizikai helyét, sem pontos konfigurációját. Ez a tudatlanság egyben a felhőszolgáltatások legnagyobb hátránya, hisz a felhasználó a szolgáltató kezébe helyezi az adatait, amely bizalmat feltételez a szolgáltató iránt. Így felhasználóként utána kell járnunk a felhőszolgáltatást kínáló cég hátterének. 2.6.1.1 Felépítése A felhőszolgáltatásban a legalsó szinten helyezkedik el egy szerver réteg, mely számítógép hardverekből, valamint a felhőszolgáltatás működtetéséhez nélkülözhetetlen szoftverekből áll. Ez tartalmazza többek között a többmagos processzorokat, felhőspecifikus operációs rendszereket. A felhőszolgáltatások definíció szerint nagymértékben testre szabhatók a felhasználói igények szerint. Felhőszolgáltatásnak az alábbi kombinálható szolgáltatásokat tekintjük [11]:
Files as a Service [FaaS]: Lehetőséget biztosít a felhasználóknak, hogy különböző típusú adatot tároljanak egy nagymértékben skálázható, hierarchikus fájlrendszerben, majd ezeket bárhol le tudják tölteni. Ez az 24
egyik legrégebbi felhőszolgáltatás, néhány máig népszerű alkalmazás ezt nyújtja, pl.: Dropbox, Amazon S3, Microsoft Live SkyDrive.
Data Storage as a Service [DaaS]: Nagy mértékben hasonlít a FaaS szolgáltatásra, ám a név implikálja, hogy strukturált adattárolást kapunk, amelyet egy relációs adatbázis valósít meg, melyben hatékonyan tudunk lekérdezni, indexelni, illesztéseket végrehajtani, stb. Napjainkban is létezik pár felhőszolgáltatás, amely szolgáltatja ezt a funkciót, pl.: Microsoft SQL Azure, Amazon SimpleDB, Google App Engine DataStore, stb.
Software as a Service [SaaS]: Szoftvercsomagokat tesz elérhetővé a felhasználók számára interneten keresztül, akik előfizetéssel
vagy
használattal arányos fizetési modellel tudják igénybe venni őket. Érdemes megemlíteni néhány ilyen módon elérhető terméket: Microsoft Office Live, Microsoft Exchange Online, Microsoft SharePoint Online, stb.
Software plus Services [S+S]: A Microsoft által megalkotott kifejezés azon hagyományos szoftverekre, melyet a Microsoft vagy egy Microsoft partner cég hosztol. A partnerek hiteles Microsoft virtuális alkalmazásokat bocsáthatnak a felhasználók rendelkezésére. A legjobb példa erre az együttműködésre az Amazon E2C, mely Windows Server 2003 szerveren SQL Server 2005 technológiát ajánl a felhasználóknak, ahol az adattárolást az Amazon saját Elastic Block Storage technológiája oldja meg. A virtuális gépek képfájljait, valamint EBS pillanatképeket S3 tárba mentik.
Infrastructure as a Service [IaaS]: A jól megszokott adatközpontok szolgáltatásait nyújtja, a nagymértékben skálázható számítási kapacitással, memóriával és tárhellyel, valamint tipikusan internetkapcsolattal. Itt is általában két árazási modellt használnak, az előfizetés alapút és a használattal arányos árazásút. Természetesen ez a technológia is elérhető a piacon, legjobb példa rá az Amazon Web Services, GoGrid vagy Flexiscale.
Communication as a Service [CaaS]: Szolgáltatásorientált üzenetküldő lehetőséget biztosít. A szolgáltatás konfigurálható, megbízható, biztonságos, dinamikusan felügyelhető, a folyamatban lévő adatátvitelek izoláltak, garantált sávszélességgel és válaszidővel rendelkezik, valamint eleget tesz az SLA követelményeinek. Leggyakrabban egy SaaS, S+S vagy IaaS szolgáltatás részeként jelenik meg.
25
Monitoring
as
a
Service
[MaaS]:
Lehetőséget
biztosít
a
többi
felhőszolgáltatás monitorozására, értesítést küld az extrém hálózati terheltségről, hibákról. Sokszor tartalmaz ellenőrző komponenst, mely az SLA
teljesülését,
vagy
a
használat
utáni
számlázás
pontosságát
monitorozza. Rendszerint a többi felhőszolgáltatással együtt van jelen a rendszerben.
Platform as a Service [PaaS]: A platformszolgáltatás általában legalább három elemből tevődik össze: o Tool as a Service [TaaS]: Fejlesztőeszközöket illetve nyelveket nyújt a fejlesztőknek, hogy elkészítsék saját felhőalkalmazásukat. Ilyenek többek között a Microsoft Visual Studio (C#, VB, IronRuby, stb.), Eclipse (Java, stb.), Windows Azure Tools (Website, WCF Service, stb.), Google App Engine (Python alapú WebApp és Django keretrendszerek). o Virtualizált alkalmazás futtatókörnyezet, amely lehetővé teszi az egyedi felhőalkalmazások futtatását, tipikusan IaaS feletti SaaS szolgáltatásként. Az Amazon esetében többféle platform közül választhatunk, ilyenek a 32 vagy 64 bites Linux disztribúciók, a Windows 2003 szerver SQL Server 2005-tel vagy Oracle adatbázissal, illetve a 64 bites OpenSolaris. A Windows Azure egy Windows 2008 szerveren fut egy speciális Microsoft HyperV
hypervisor
felett.
A
Google
App
Engine
Python
futtatókörnyezetet nyújt. o FaaS szolgáltatás, melynek feladata a futó alkalmazások állapotának mentése és visszaállítása. Ilyenek a már fent említett technológiák: Amazon EBS, SimpleDB, S3, Google BigTable vagy Windows Azure Storage Services táblák és blobok.
Everything as a Service [EaaS, XaaS, aaS]: A felhőszolgáltatások egy részhalmaza, melynek segítségével újrahasznosítható, finomhangolható alkalmazásokat hívhatunk, melyek összességében teljesen lefedik egy üzleti probléma megoldását.
26
2.6.2 Azure Services Platform Az előző pontban felsorolt szolgáltatások közül a Windows Azure platform számos szolgáltatást nyújt. Ezek közül ismertetem azokat, melyek előkerültek a szakdolgozatom kapcsán [12].
Azure Platform Components Compute
Storage
AppFabric
SQL Azure
Content Delivery Network
Virtual Network
Azure Market Place
6. ábra - Azure platform komponensek
Azure Compute: Rugalmasan skálázható számítási kapacitást biztosít különféle feladatok elvégzésére. Három csomagból választhatunk, az egyikben webalkalmazást hosztolhatunk IIS 6 webszerverben, a másikban szolgáltatásokat
futtathatunk
az
IIS
szerverben,
többnyire
a
webalkalmazások háttérszolgáltatásait. Végül igényelhetünk komplett virtuális gépeket, amelyek teljes számítási kapacitásukkal rendelkezésünkre állnak. Természetesen az Azure gondoskodik a terheléseloszlásról és a
6
Internet Information Services – Windows operációs rendszeren futó internet alapú
szolgáltatások gyűjtőneve. Egyik szolgáltatása a második legnépszerűbb webkiszolgáló.
27
nagymértékű rendelkezésre állásról, így robosztus szolgáltatásokat tudunk készíteni.
Azure Storage: Lehetőséget biztosít a felhasználó számára bináris adatok tárolására. Ha a bináris tároláson kívül további strukturáltságot szeretnénk, használhatjuk a táblákat. Az előző pontok egyikében említett üzenetsor alapú kommunikációjú szolgáltatások üzenetsorait is tárolhatjuk. Végül lehetőségünk nyílik NTFS fájlrendszerű virtuális meghajtókat is fel-, illetve letölteni. Előnye a társzolgáltatásnak, hogy az adatunkat redundánsan tárolják, minden adatról 3 redundáns replika készül, valamint új szolgáltatásként garantálják a földrajzi redundanciát is, tehát az adataink egymástól több száz kilométerre fekvő szervereken is megtalálhatók, így esetleges természeti katasztrófák esetén sem kell adatvesztéstől tartanunk. Az alkalmazásainkból REST vagy menedzselt programozói interfészen keresztül is elérhetjük az adatainkat, jelentősen megkönnyítve ezzel a fejlesztők munkáját.
SQL Azure: Egy nagy rendelkezésre állású, nagymértékben skálázható SQL adatbázis, aminek a használata néhány kivételtől eltekintve megegyezik a szokásos szervereken futó SQL Server használatával. A relációs adatbázisban a szokott módon, T-SQL nyelven fogalmazhatunk meg komplex kéréseket, illesztéseket. Könnyen hozhatunk létre és módosíthatunk táblákat, indexeket, tárolt eljárásokat, funkciókat és triggereket. Alkalmazásfejlesztőként természetesen rendelkezésünkre áll a menedzselt ADO.NET adathozzáférés, ezenkívül kapunk natív ODBC interfészt, továbbá támogatást PHP-hez és JDBC-hez. Az SQL Azure Reporting eszköz segítségével részletes jelentéseket készíthetünk az adatbázisunkról, az SQL Azure Data Sync eszköz segítségével pedig szinkronizálhatjuk az adatbázist esetleges helyi adatbázisszerveren hosztolt adatbázissal. Természetesen az adatok duplikálása itt sem hiányzik, így adatvesztéstől sem kell tartanunk.
28
3 Játékmotorok Windows Phone 7 Platformra Az játékunk témájának kiválasztása valamint a főbb paraméterek megtervezése után, még mielőtt rátértem a játék implementációjára, megvizsgáltam az esetlegesen elérhető játékfejlesztő komponenseket, hátha fel tudom használni valamelyik néhány funkcióját, hogy megkönnyítsem a logikai motor elkészítését. A következőkben röviden áttekintem a megvizsgált komponensek lehetőségeit.
3.1 TileMap IDE (tIDE) Az első komponens, amit megvizsgáltam, egy csempe alapú grafikai motor. Gyakorlatilag csak a pálya grafikai megvalósításával foglalkozik, segítségével kis komplexitású 2D-s térképek hozhatók létre. Előnye, hogy ingyenes, nyílt forráskódú. Támogat különböző, már létező csempe alapú pályát leíró fájlformátumot (Tiled TMX, Mappy FMP, Fixel), valamint két saját formátumot is bevezet, az egyik XML alapú, a másik egy bináris formátum tbin kiterjesztéssel [13]. Szolgáltatások [13]:
Könnyen kezelhető pályaszerkesztő modul rajzolóeszközzel, mellyel elkészíthető a pálya arculata.
Többszintű
csempézés
támogatása,
rétegek
megjelenítésének
konfigurálhatósága. Parallax7 megjelenítés támogatása.
Automatikus csempeváltás, animált csempék.
Különböző méretű csempék, több csempelap támogatása.
Statisztika a réteg- és csempehasználatról.
Beépülő modulokkal kiterjeszthető.
3.1.1 xTile Egy XNA alapú csempepálya-renderelő motor. Támogatja az XNA által támogatott összes platformot. Segítségével a szerkesztővel létrehozott rétegek Parallax
7
Objektumok helyzetének változása különböző szögekből. Játékfejlesztés esetében azt a hatást
nevezik így, amikor a háttér sokkal lassabban mozog, mint a rajta elhelyezkedő tartalom. Ilyen például a Windows Phone 7 Panoráma vezérlő.
29
megjeleníthetők, így nem szükséges minden képkockára új képet rajzolnunk. Saját tulajdonságokat definiálhatunk pálya, réteg, lap vagy csempe szinten. A tIDE pályaformátumait kezeli az XNA Content Pipeline, ahol automatikus validáció és előfeldolgozás történik. Saját XNA Content Processor-t adhatunk meg a csempék feldolgozására. Absztrakt megjelenítő eszköz kerül definiálásra, így az abból történő leszármazás biztosítja a platformbővíthetőséget.
3.2 Farseer Physics Engine A Farseer egy rendkívül funkciógazdag kétdimenziós fizikai motor, melynek fejlesztése folyamatos és széles körben elterjedt. Legnagyobb előnye, hogy nyílt forráskódú szoftver létére a kereskedelmi szoftverekkel összemérhető szolgáltatásokat nyújt. Az osztálykönyvtár a Box2D fizikai motor XNA-s változatára épül, további funkciókkal kiegészítve azt [14]. A motor, bár XNA platformokhoz készült, alapértelmezetten nem támogatta a Windows Phone 7 rendszert, ám megjelenése után hamar megjelent egy WP7-tel kompatibilis változat. További pozitívum, hogy a fejlesztők készítettek egy demóalkalmazást, melynek segítségével a telefonon élő környezetben ismerhetjük meg a motor lehetőségeit.
7. ábra - Ütközésdetektálás, stabil halmozás
A rengeteg funkció közül kiemelek egy pár fontosat a teljesség igénye nélkül [14]:
Valós idejű ütközésdetektálás, lehetőség ütközési csoportok létrehozására.
Ütközési callback függvények: kezdet, vég, feloldás előtt, feloldás után.
Konvex poligonok, körök.
Dinamikus fa adatszerkezetű széles fázisú ütközésdetektálás.
30
Gyors AABB8 széles fázisú ütközéskeresés.
Érintkezés, súrlódás, kompenzáció modellezése.
Lineáris idejű stabil halmozás.
Különféle típusú csuklós illesztések.
Gravitáció és egyéb erőtér generátorok.
Konkáv polinom feldarabolására, konvex burok keresésére szolgáló és egyéb algoritmusok.
3.3 Engine Nine Az Engine Nine egy XNA alapú háromdimenziós játékgrafikai motor, mely a Windows, Xbox és Windows Phone 7 platformokon kívül rendhagyó módon a Silverlight 5 alapú böngészőalkalmazásokat is támogatja. Viszonylag fiatal, nyílt forráskódú projekt, ám fejlesztése eddig folyamatos. A szolgáltatások listája igen impozáns [15], bár sok helyen csak az XNA feletti egy logikai szinttel magasabb megvalósításról beszélünk.
Grafikus szolgáltatások o Irányított, pont, vagy spot fényforrásból érkező, közvetlen és indirekt fény kezelése. o Árnyék mappelés. o Részletezettség szintjeinek hangolása. o Rugalmas részecske effektek. o Textúrázott téglalapok. o Primitívek: téglatest, gömb, teás kancsó, koordinátatengely, nyíl, pont, vonal, négyzetrács. o Skybox.
Anyagok o Alap XNA anyagok. o Normál mappelés. o Környezeti mappelés. o Futási idejű textúraillesztés darabokból. o Átlátszóság.
8
Axis-aligned bounding box – Ütközésdetektálási módszer, amikor az objektumokat a
koordinátatengelyekkel párhuzamos oldalú téglatestekbe foglaljuk, majd azok metszetét vizsgáljuk.
31
8. ábra - Anyagtulajdonság normál mappelése
Útófeldolgozás o Kiterjeszthető utófeldolgozó keretrendszer. o Dinamikus tartományú fényeffekt. o Mélységélesség állítás, elmosás, körkörös elmosás.
Jelenet Menedzsment o Fa adatstruktúrájú jelenet menedzsment. o Terep-megvilágítás és –kiválasztás. o Modellkiválasztás.
Animációk o Csontvázak animálása. o Automatikus animáció átmenet. o Egyéni animáció irányítás. o Xbox avatárok teljes támogatása. o Merev és burkolt modellek animációjának támogatása. o Gördülékeny átmenetrendszer. o 2D-s Sprite animációk.
Megjelenés o A jelenetek és tartalom egy XML állományban leírható. o A tartalom fordítása közben az XML bináris formátumra fordul. o Gyors betöltés, kis terjesztési méret.
32
3.4 FlatRedBall A FlatRedBall egy ingyenes, de nem nyílt forráskódú játékmotor XNA, Silverlight vagy Managed DirectX platformokra. Az eddig felsoroltak közül leginkább az Engine Nine-ra hasonlít, ám amíg az szigorú értelemben véve csak grafikai motor, addig ez komplett játékmotor. Bár vannak beépített fizikai modelljei, integrálható bele a fent említett Farseer fizikai motor, így összetett fizikai szimulációt is képes kezelni. A fejlesztést segítendő, rengeteg szerkesztőeszközt kapunk, melyekkel a különböző játékelemeket megkomponálhatjuk. További jó referencia, hogy számos színvonalas játék használja alapjaként. Az eddig megismert grafikai elemek közül tartalmazza a két és háromdimenziós megjelenítési lehetőséget, részecskerendszereket, ütközésdetektáló algoritmust, Textúra animációt, lehetőség van utófeldolgozásra, a háromdimenziós alakzatok térbeli mozgásának leírására, megvilágítás beállítására, egyéni shaderek definiálására. Ezenkívül rendelkezik A* útkereső algoritmusimplementációval, teljes zene és hangeffekt-támogatással. A Farseer fizikai motoron kívül további olyan beépülőkkel is együttműködik, mint a mesterséges intelligencia szerkesztő, részecskeszerkesztő, görberajzoló vagy csempeszerkesztő [16]. Ezen szolgáltatások ötvözésével nagyon robosztus játékfejlesztő készletet kapunk, ám ennek az ára a komplexitáson is látszik, a sokféle szerkesztő működését nehéz elsajátítani, a programozói interfész viszonylag bonyolult. Szerencsére rendelkezésre áll megfelelő mennyiségű példaprogram és leírás.
3.5 SunBurn Engine A
Synapse
Gaming
által
fejlesztett
SunBurn játékmotor az első, és eddig egyetlen kereskedelmi
játékfejlesztő
termékcsalád
Windows Phone 7-re, ez meg is látszik a szolgáltatások listáján, terméktámogatáson. A cég honlapjáról letölthető néhány összetett példa, melyek
segítségével
bemutatják
a
motor
képességeit, valamint a forráskódot is mellékelik, így a komponensek használatát is megismerhetjük [17]. Természetesen több neves játékfejlesztő cég illetve színvonalas játék használja a motort, ez jó referencia a cégnek. 33
Mivel ez az első befejezett, komoly szolgáltatásokat nyújtó 3D-s játékmotor a piacon, amely támogatja a Windows Phone 7 platformot, aki színvonalas játékot készít a segítségével, az komoly előnyre, és profitra tehet szert. Három különböző csomagban érhető el a terméklicensz 150$-tól 1000$-ig terjedően, így mindenki megtalálhatja saját igényeinek megfelelő funkciókészletet. Alapvetően a 250$-ért hozzáférhető Professional Edition tartalmaz minden fontos szolgáltatást. A demók is előrevetítik, hogy rendkívül színvonalas játékok készíthetők a motor segítségével a telefon hardverére is. A szolgáltatások között sok megtalálható az előző pontokban felsorolt nyílt forráskódú megoldások valamelyikében, ellenben egy keretrendszeren belül, megfelelően optimalizálva a SunBurn személyében érhető el először [17]. Grafikai szolgáltatásai közül kiemelkedő a fény és árnyék kezelésére irányuló technikák jelenléte és gyorsasága, valós idejű megvilágítás- és árnyékszámolás, fénymappelés, anyagtulajdonságokat figyelembe vevő direkt és indirekt megvilágítás megjelenítése. Textúrák esetén elérhető a fejlett renderelési technika darabokból, utófeldolgozás,
különböző
minták
összeolvasztása,
részletek
szintezettsége,
modellanyagoknál különféle mappelési technikák, egyéni Direct3D shaderek. A jelenetszerkesztőben minden entitás szkriptelhető, az események kódja C# alapú, a jelenetben helyezhetőek el hangforrások, melyek folyamatos vagy egyszeri hangot adnak. Megtalálható továbbá számos, az előbbiekben meg nem említett, nem kiemelkedő funkció, melyekkel együtt véleményem szerint a SunBurn motor jelenleg a legjobb játékfejlesztő eszköz a Windows Phone 7 platformra.
3.6 ScriptTD A ScriptTD kissé kilóg a sorból a többi játékmotorhoz képest, hisz sajnos jóval később kezdődött a projekt, mint ahogy elkezdtem implementálni a szakdolgozatban kiválasztott Tower Defense játékot. Ez nem vette el a kedvemet, hogy megvizsgáljam a lehetőségeit, sőt, ez esetben kódszinten is megnéztem egy-két dolgot, hisz nyílt szoftver lévén lehetőségem nyílt rá. A motor célja, hogy a programozáshoz nem értő, ám lelkes, játékot készíteni akaró egyének saját Tower Defense játékot hozhassanak létre az előre definiált tartalmak
(hangok,
ábrák,
paraméterek,
stb.)
34
lecserélésével.
Természetesen
kiterjeszthető a motor saját elemekkel tetszés szerint, így nagymértékben testre szabható. A játék minden elemét XML dokumentumként adhatjuk meg, ahol egy meghatározott séma alapján definiálhatjuk az objektum tulajdonságait [18]. Részletesen beállíthatjuk, ezáltal a játék menüjének minden elemét, az egyes pályák kinézetét és paramétereit, az ellenséges lények tulajdonságait, a megengedett tornyok listáját, ezek legnagyobb fejlesztésének mértékét, a lényhullámok számát és tulajdonságait. A játék különböző hangeffektjeit is mindenhol felüldefiniálhatjuk. Ha a játék objektumait is ki szeretnénk terjeszteni, programozásra van szükség, az egyes objektumtípusok interfészeit megvalósítva saját típusokat tudunk létrehozni például tornyokból. Erre a motor készítője mutat is egy példát egy blogbejegyzésben. Ezeken felül egy részletes, háromnegyed órás demóvideó is található a projekt weboldalán. Összességében a ScriptTD egy nagymértékben kiterjeszthető TD játékmotor, azonban az alapvető működési elemeket nem lehet benne megváltoztatni, így bár egy pár megvalósítást szívesen átemelnék a későbbiekben a saját projektembe, alapvetően eltér a két TD koncepciója.
3.7 Összefoglalás Az előző pár pontban összefoglaltam néhány játékmotor legfontosabb tulajdonságát, végeredményként megállapítható, hogy általában különböző szegleteit fedik le a játékfejlesztésnek, még fiatal a platform, így a nyílt forráskódú megoldások még nem elég kiforrottak, vagy nem készült el még minden funkciójuk. A csak fizikai, vagy grafikai szolgáltatásokat nyújtó csomagokat, mint a Farseer és Engine Nine egyből elvetettem, hisz feladatom egy Tower Defense játék logikai motorjának elkészítése, mely nem tartalmaz grafikai megvalósítást, illetve mivel egy egyszerű kétdimenziós, felülnézeti játékról van szó, fizikai modellre sem lesz szükségem. A FlatRedBall és SunBurn motorok támogatják a kétdimenziós fejlesztést is, valamint jelenetszerkesztővel és szkript motorral is rendelkeznek, tehát lehetőségem lett volna az egyiket a játék alapjául választani. Erről azért mondtam le végül, mert a játék egyszerű logikája és felépítése nem kívánja meg a jelenet alapú kezelést, így ez csak felesleges nehezítése lett volna a fejlesztésnek, ezenkívül a SunBurn motor nem ingyenes, és egy játék elkészítése nem hozta volna vissza a befektetett pénzt. A tIDE csempe alapú játékfelület nem biztosította a megfelelő rugalmasságot, így sok 35
mindenről le kellett volna mondanunk a betervezett funkciókból és működésből. Végül a ScriptTD motor még nem volt jelen, mikor elkezdtük a projektet, ám valószínűleg erre sem esett volna a választás, hisz alapvető tulajdonsága, hogy egy szabad térben, cellákon mozognak az ellenséges lények, akiket a tornyainkkal irányíthatunk, míg a mi koncepciónk szerint a lények egy meghatározott úton közlekednek, melyek azonban tetszőleges alakúak lehetnek, nincsenek cellákhoz kötve. Ennek ellenére a megvalósítás pár elemét a mi projektünkben is implementálhatónak tartom a későbbiekben. Így végül a sok eszköz megvizsgálása után arra a döntésre jutottam, hogy tisztán C# nyelven saját magam alakítom ki a játék modelljét, mert a játékmotorok vagy nem fedték le az igényeinket, vagy az általunk tervezett játék komplexitásához mérten felesleges és nagymértékű többletmunkát okoztak volna.
36
4 VortexTD A szakdolgozat gyakorlati feladatának egy Windows Phone 7-re készülő XNA alapú játékot választottunk. Konzulensünk szabad kezet adott a játék típusának kiválasztásához, így szabadjára engedhettük a fantáziánkat. Végül figyelembe véve egy érintőképernyős telefon kijelzőjének és irányíthatóságának korlátait, a desktop világban méltán népszerű Tower Defense típusú játékra esett a választás. Miután egyeztettünk konzulensünkkel, és rábólintott a választásra, a következő feladatunk az volt, hogy jól meghatározott, egymástól különálló feladatokra bontsuk a fejlesztést, méghozzá olyan módon, hogy a feladatok mennyisége megfelelő legyen. Játék lévén a felosztás magától ajánlotta magát, így végül az én feladatom a projekt során a játék modelljének és logikai motorjának elkészítése, míg társam a grafikai megvalósításért volt felelős beleértve a felhasználói input kezeléstét, menük megjelenítését, hangok kiváltása, stb. A játékhoz készítendő weboldalból az én feladatom egy pályaszerkesztő modul létrehozása, valamint a weboldal és az adattár, illetve a telefon és az adattár közötti kommunikáció kezelése.
4.1 Tower Defense játékok A Tower Defense (továbbiakban TD) stílus a valósidejű stratégiai játékok alfaja. A játékos célja, hogy az általa építhető tornyokkal megakadályozza, hogy az ellenséges lények átszeljék a pályát, vagy megtegyék a számukra kijelölt utat. Ezen a ponton rögtön kétféle TD-t különböztetünk meg, az egyik változatban az ellenségek egy bizonyos ponton jelennek meg, majd egy bizonyos pont felé tartanak egy cellákból álló pályán, ám az üres cellákon tetszőlegesen közlekedhetnek, így az általunk elhelyezett tornyok vagy tereptárgyak tudják az útjukat befolyásolni. A második, általunk választott változatban az ellenségek egy megadott útszakaszon masíroznak végig, ám ez az útszakasz tetszőleges alakú lehet. A második esetben a tornyokat az út mentén helyezhetjük el. A játékos által letehető tornyok általában különböző mennyiségű pénzbe kerülnek, és különféle képességekkel rendelkeznek a lények feltartóztatásának, illetve eliminálásának céljából. A hullámokban érkező lénycsapatok szintén változatos tulajdonságokkal rendelkeznek, amelyek ellenállóbbá vagy sebezhetetlenné teszik őket 37
bizonyos tornyok által. Minden ellenség feltartóztatásáért pénzt és pontot kap a játékos, ezek általában arányosak egymással, azonban minden lény átengedése után csökken a játékos életpontjainak száma. A lények hullámai egyre erősebbek, így egyre több, különböző képességű torony építése szükséges az életben maradáshoz. A tornyok képességeit általában pár szintig fejleszteni lehet. A játék akkor ér véget, ha a játékos életpontjai elfogynak, illetve ha kivédi az összes ellenséges hullámot. A játékok első változatai már C64 és Atari gépeken is léteztek, valamint olyan PC-s stratégiai játékokhoz léteztek TD pályák, mint StarCraft, Age of Empires 2, vagy Warcraft 3, ám jelenlegi ismertségükre és népszerűségükre a webes Flash alapú játékok megjelenésével tettek szert. Ennek az úttörője a 2007-ben megjelent Flash Element TD, mellyel 3 hónap leforgása alatt több, mint 140 millióan játszottak [19]. Mára a gyűjtőoldalakon száznál is több különböző tematikájú webes TD található.
4.2 A játék tulajdonságai Miután kiválasztottuk a típust, még rengeteg dolgunk volt, mielőtt nekiláthattunk a tervezésnek és implementációnak. Meg kellett egyeznünk a játékunk elemeiről, funkcióiról, működéséről, hogy elkezdhessük az önálló munkát. Első lépésként kipróbáltunk számtalan TD-t, hogy ötleteket gyűjtsünk. Minden esetben felírtuk, ha egy ötlet megtetszett egy játékban, így később el tudtuk dönteni, hogy végül milyen szolgáltatáshalmazt emeljünk be a munkánkba. Végül fontos volt számunkra, hogy a játék ne legyen túl komplex, kezelhető maradjon egy telefonon, így megnéztünk jónéhány videót különböző érintőképernyős telefonokra írt Tower Defensekről. A játékunknak a VortexTD nevet adtuk, ennek megfelelően a játék színhelyét a modern jövőbe helyeztük. Ezután megegyeztünk a játék kulcselemeiről:
Több pályát fog támogatni, melyek közül a játékos kedvére válogathat.
Egy pályán belül tetszőleges számú, előre definiált ellenséges hullám érkezhet egymás után, melyek egyenként konfigurálhatók.
A játékos a likvidált lények után pénzt és pontot kap.
A hely szűkössége miatt a játékos 5 torony közül választhat, ám további fejlesztésekkel összesen 7 különböző funkciójú torony készíthető.
Háromféle élőlény lehet a pályán, amelyek különböző karakterisztikával rendelkeznek.
38
A tornyok megfelelő pénzösszeg fejében fejleszthetők, így bizonyos tulajdonságaik erősebbek lesznek.
Minden torony saját magára jellemző vizualizált lövedéket lő.
A játék támogatja a többnyelvűséget, a hangeffektek ki-bekapcsolhatók.
A játék egy szünet gombbal tetszés szerint megállítható és elindítható.
A játékos a játék weboldalán regisztrálhat, majd belépés után pályákat készíthet a játékhoz, melyet aztán a játékból le tud tölteni.
A játékos a játék főmenüjében elérheti a játékosok által létrehozott pályákat, majd ha kiválaszt egyet, letöltheti a telefonra. Természetesen ehhez a szolgáltatáshoz élő internetkapcsolatra van szükség.
A megvizsgált TD-kben fellelt jó ötletek átemelése mellett törekedtünk arra is, hogy a kész játék ne csak egy legyen a sok közül, hanem egyéni és új dolgokat is bevezessünk. Így a később ismertetendő tornyok közül néhánynak általunk kitalált speciális funkciója van, mely nagyban emeli a játékélményt. Ezen kívül nagy hangsúlyt szerettünk
volna
fordítani
a
játék
elrendezésére
és
irányíthatóságának
ergonomikusságára. Miután megegyeztünk az alapvető összetevőkről, megterveztük a játékelemek alaptulajdonságait, majd külön utakon terveztük meg azok grafikai, illetve pontos modellreprezentációját. Az egyes elemcsoportok tervét külön tárgyalom.
4.3 A játék entitásainak tervezése 4.3.1 Élőlények Három lénytípust definiáltunk, melyek az ajánlásunk szerint erősségben, sebességben, értékben és az egyes tornyokhoz való viszonyukban is eltérnek egymástól. Természetesen egy egyéni pályán ezeket a tulajdonságokat felül lehet bírálni, vagy át lehet rendezni az arányokat.
39
3. táblázat - Élőlények tulajdonságai
Név
Tulajdonságok A leglassabb élőlénytípus, cserébe extra páncélt kapott, így jobban ellenáll a lövéseknek. A Gépágyú és Sár torony
Láva élőlény
fejleszthető Láva lények ellen, a fejlesztés után a Láva élőlények tőlük bónuszsebzést szenvednek el. A Plazma típusú Térítő torony (lásd később) Plazma élőlénnyé változtatja. Közepes sebességű és páncélú élőlény. Szintén a Gépágyú és a Sár tornyok fejleszthetők ellene bónuszsebzésért. A Láva típusú
Plazma élőlény
Térítő torony Láva élőlénnyé változtatja. Viszonylag gyenge védelemmel, ám rendkívüli sebességgel rendelkezik. Egyik torony sem bír ellene bónuszsebzéssel, ami
Elektromos élőlény különösen nehéz ellenféllé teszi. Azonban a Láva illetve Plazma típusú Térítő tornyok a típusuknak megfelelő élőlénnyé változtatják. Az élőlények létrehozását a terveim szerint egy hullámgeneráló osztály végzi. Ezt lehet majd felparaméterezni a gyártandó élőlények tulajdonságaival, majd gyárként fog működni, ezen kívül időzítő is fog benne számolni, hogy a megadott időközönként hozzon létre egy új lényt, így egyből a hullámok kezeléséért is felelős lesz.
4.3.2 Tornyok és lövedékek A legnehezebb, egyben legtöbb kreativitást igénylő tervezési feladat a tornyok funkcióinak kitalálása. Mivel a képernyőn a rendelkezésre álló hely erősen korlátozott, néhány alap tornyot többféle toronnyá tudunk majd építés után fejleszteni.
40
4. táblázat - Tornyok tulajdonságai
Név
Tulajdonságok Egy célpontú, gyorsan tüzelő, kis hatótávú és kis sebzésű torony. Ennek megfelelően olcsó, és fejlesztésével mind a hatótáv, mind a sebzés, mind a tüzelési sebesség nő. Speciális fejlesztése, hogy
Gépágyú torony
Plazma vagy Láva típusúvá változtatható, így valamelyik lénytípus ellen kifejezetten hatásossá válik. Önmagában cselekvésre képtelen torony, belőle fejleszthető ki a Hóvihar vagy a Térítő torony. Természetesen az ára tartalmazza a belőle fejleszthető tornyokét is, így ingyen fejleszthető tovább.
Harmónia torony Több célpontja lehet, a hatótávolságán belül célpontjainak sebességét lassítja. Sebzése nincs. Hatótávolsága, lassító hatása, valamint célpontjainak maximális száma fejleszthető. Hóvihar torony Több célpontú, sebzés nélküli torony. Célzott ellenfeleit a típusának megfelelő élőlénnyé változtatja. Két típusa lehet, Láva és Plazma, melyet a torony közepén elhelyezkedő karika színe Térítő torony
mutat.
Hatótávolsága
valamint
célpontjainak
a
száma
fejleszthető. A Sár torony egy célpont felé robbanó töltetet indít, amely a becsapódás helyén nagy sebzést okoz a célpontnak, valamint egy kisebb robbanást is előidéz, melynek következtében a közelben Sár torony
elhelyezkedő
egységek
a
robbanás
távolságukkal
fordítottan arányos
epicentrumától
sebzést
vett
szenvednek el.
Hatékony torony, így az ára viszonylag magas. Fejlesztése a Gépágyú toronyhoz hasonlóan a tüzelési sebességre és hatótávra, illetve a sebzésre hat. Ugyancsak a Gépágyúhoz hasonlóan Láva és Plazma típusú Sár toronnyá fejleszthető, így az azonos típusú lényekkel szemben bónuszsebzést kap.
41
A Harmónia toronyhoz hasonlóan cselekvésképtelen, ellenben ingyen fejleszthető Lézer vagy Sólyom toronnyá, hisz az ára tartalmazza e tornyokét. Mivel a belőle fejlesztett tornyok a Tüzér torony
legerősebbek a játékban, a Tüzér torony ára a legmagasabb. Folyamatos lézersugarakkal sebzi egyszerre több célpontját. Sebzése jelentős, mely a fejlesztésekkel még tovább növekszik. Hatósugara valamint célpontjainak száma szintén nő.
Lézer torony Extrém hatótávval és tűzerővel rendelkezik, egyetlen célpontját erős tűz alatt tartja. Fejlesztésével további sebzést kap, valamint a lövések is sűrűbbé válnak. Sólyom torony A legkomplexebb működésű torony. Nincs semmi hatása a pályán elhaladó lényekre, önmagában nem csinál semmit, azonban Misztikus torony
a
telefon
multitouch
képességeit
kihasználva
összeköthető néhány másik toronnyal (kivéve egy másik Misztikus
toronnyal),
és
felerősíti
azok
képességeit.
Fejlesztésével növelhetjük a kapcsolatainak maximális számát. Egy toronnyal alkotott kapcsolatát bármikor megszakíthatjuk, és helyette új kapcsolatot hozhatunk létre. Hatása az egyes tornyokra:
Gépágyú: tüzelési sebesség növelése
Hóvihar: lassító hatás növelése
Térítő: hatótávolság növelése
Sár: a robbanás sebzésének növelése
Lézer: lézer sebzésének növelése
Sólyom: hatótávolság növelése
A lövedékeknek három csoportja van, minden torony rá jellemző lövedéket lő.
A diszkrét lövedék megadott időközönként hagyja el a torony csövét, majd a célpont felé repül. Ha eléri a célpontot, megsemmisül, és a célpont lény a lövedék által hordozott sebzést megkapja.
A lövedék intelligens, tehát
amennyiben a célpont megsemmisül a célba érése előtt, akkor a lövedék új 42
célpontot keres, ha talál, átpártol, ha nem, akkor sebzés nélkül megsemmisül.
A folytonos lövedék egy sávban vizualizálódik a torony és célpont között, és folyamatosan sebzi áldozatát.
A hullám lövedék az őt kibocsátó torony középpontjából indul, majd kör alakban kiterjed a torony hatótávolságáig, miután túljutott a hullám a hatótávolságon, új hullám indul a középpontból. Hatása rendszerint több célpontra hat egyszerre.
4.3.3 Az út struktúrája Az általam tervezett út tetszőlegesen hosszú szakaszokból áll. Elméletileg így lehetőség van szinte teljesen görbe út létrehozására is, ha a szakaszok megfelelően rövidek. Az útdarabok össze vannak fűzve, és a feladatuk, hogy irányítsák a rajtuk haladó élőlényeket. Egy élőlény minden pillanatban egy szakaszon mozog, vagyis minden pillanatban pontosan egy útszakasszal áll logikai kapcsolatban, amikor eléri egy útszakasz szélét, akkor a vezérlés átkerül a következő útszakaszra, és a következő lépésben már annak az irányában halad. Létrehozásakor egy lény megkapja, hogy melyik útszakaszon indul, ez meghatározza az egész pályáját. Amikor egy ellenség eléri az útjának a végét, eseményt küld a szabadulásáról, és a játékos megkapja a megfelelő szankciókat, ő pedig lekerül a pályáról, majd megsemmisül. Amennyiben egy ellenség megsemmisül, szintén egy esemény kíséretében eltűnik a pályáról. A játék támogatni fogja a diszjunkt utak létrehozását, így két különböző hullámnak beállítható, hogy melyik úton induljon el és haladjon végig.
4.4 Osztályhierarchia és folyamatok tervezése 4.4.1 Kapcsolat a grafikai motorral A
munka
oroszlánrésze
az
előző
feladatban
kigondolt
entitások
megvalósításának megtervezése volt. Mivel a játékunk egy logikai és egy grafikai modulból fog állni, ezért első feladatom volt egy olyan objektum megtervezése, amelyet a grafikai motor API-ként használhat, így teljes mértékben elrejthetem a játék belső működését a grafikai megvalósítás elől, ami lehetővé teszi majd a későbbiekben az esetleges változtatásokat anélkül, hogy a külső felület megváltozna, így nem kell folyamatosan egyeztetni a másik fejlesztővel, illetve nem kell újraírni már megírt 43
kódrészleteket. Hogy mire használhatja a grafika a játékmotort, egy use case diagramon tekintettem át.
9. ábra – Logikai motor Use case diagramja
Az esetek két csoportra bonhatók, a játék indítása előtti műveletekre és az indítás utániakra. Például pályát letölteni csak a játék menüjében lehet, ám ezt is a logikai motor végzi, valamint ő szolgáltatja az elérhető pályák listáját is a grafikai objektumnak. Indítás után a felhasználó számára szeretnénk adatokat közölni, így szükség van a játék állapotának lekérdezésére, mint például a tornyok és lövedékeik helyzete, utak és élőlények pozíciója, fejlesztési lehetőségek, stb. Szükség van továbbá arra, hogy a játékos befolyásolni tudja a játék menetét, így tudjon tornyokat lerakni, azokat fejleszteni, illetve eladni, tudjon új lényhullámokat küldeni. A legfontosabb használati eset azonban a játék léptetése, vagyis ahogy a játéklogika számára tudósítjuk az idő változását, így kiváltjuk, hogy a benne lévő minden objektum frissítse az állapotát az eltelt időnek megfelelően. Az időváltozás diszkrét csomagokban érkezik,
44
ám fel kell készíteni a motort arra, hogy a két frissítés között esetlegesen bekövetkezendő eseményeket észlelje, hatásukat érvényesítse. További probléma, hogy a fejlesztő nem számíthat fix időközönkénti frissítésre, előfordulhatnak akadások, amikor egy-egy nagyobb „időbeli ugrást” lát a játék logikája, ezt is megfelelően kezelnie kell. Végül úgy döntöttem, hogy lesz egy játékkezelő, kvázi homlokzat osztályom, mely publikálja a grafikai motor részére a szükséges funkciókat.
4.4.2 A játék felkonfigurálása A játékban rengeteg objektumnak kell megadnunk kezdeti paramétereket, ráadásul ezek a paraméterek dinamikusan változhatnak a játék során, például új pálya betöltésével. Azt elkerülendő, hogy a kódban mindenhol különböző beágyazott értékek legyenek, terveztem egy inicializáló objektumot, mely kezeli az egyes beállítások tárolását illetve betöltését, és a beállítások segítségével létrehozza az általuk leírt objektumokat, hogy átadja a játékkezelőnek őket használatra. Kezeli a pályák betöltését és a játék objektumaiba töltését, az élőlényhullámok létrehozását, valamint a tornyok paramétereinek és
fejlesztéseinek objektumba töltését,
melyet
a
játékkezelő
felhasználhat tornyok építésére.
4.4.3 Osztályok tervezése Meg kellett terveznem a játék entitásainak pontosabb működését, hogy az implementáció gördülékenyen menjen. Ehhez egyrészt meg kellett alkotnom az egyes osztályok tulajdonságainak halmazát, amely lefedi az elvárt működést, másrészt el kellett döntenem, hogy az egyes objektumok hogyan közvetítik az állapotváltozásaikat a többiek felé, azaz hogyan értesítik őket, ha szükséges. Az általam készített objektummodellt UML osztálydiagramok formájában fogom ismertetni, ám mivel az egész struktúra nem fér el egy oldalon, több részletre vágom, ahol az logikailag megengedhető.
Sajnos még így sem fér el megfelelő formázással egy diagram,
úgyhogy sajnos a hierarchiát nem tudom megfelelően vizualizálni. 4.4.3.1 GameObject Az osztályok tervezésénél elsődleges szempont volt, hogy megfeleljek az előzőleg felállított specifikációnak. Mivel a játék megfelelő elemeit minden esetben meg kell jeleníteni, ezért előbb vázoltam egy közös ősosztályt, melyben a kirajzoláshoz kapcsolódó minimális entitást, az orientációt vettem fel.
45
10. ábra - Legfőbb játékelemek osztálydiagramja
46
A tervezés során végig, így most is azon az alapján az elv alapján dolgoztam, hogy az ősosztály ne tartalmazzon olyan funkcionalitást, melyet nem használ minden leszármazottja, ezért például a GameObject osztály nem valósítja meg az ICanStep interfészt, mert a RoadNode osztály nem változtatja az állapotát az időben. 4.4.3.2 ICanStep Néhány entitás folyamatosan változtatja az állapotát az időben, az eltelt időt a grafikai motor kéri le az OS-től, majd továbbítja a játékobjektum felé. Ezt az eltelt időmennyiséget felhasználva kell megadnom, hogy mi lesz az objektumok új helyzete. Erre a célra egy ICanStep nevű interfészt vezettem be, mely egyetlen metódust tartalmaz, a léptetést. Minden későbbi osztály, amely megvalósítja az interfészt, szükségszerűen megvalósítja a lépésfüggvényt is, ahol előállíthatja az idő változását figyelembe véve az aktuális, új állapotát. 4.4.3.3 Creature Az élőlényeknek három típusát terveztük, a konkrét típust egy felsorolás adja meg. Nem volt szükség rá, hogy leszármazás szintjén kezeljem külön az élőlényeket, hisz paramétereiken kívül nem térnek el, azonos funkciókat valósítanak meg. Mint már említettem, egy lény mindig egy adott útszakaszhoz tartozik, azon araszol az idő változásával és saját sebességével arányos mértékben, majd ha eléri a szakasz végét, útszakaszt vált. Az objektumok közötti kommunikációt nagyrészt események segítségével oldottam meg, így ha egy élőlény meghal vagy kiszabadul, egy-egy esemény váltódik ki, ilyen módon mindenki értesülhet a történtekről, akinek kezelnie kell. A lény továbbá kezeli a lövedékek által kiváltott eseményeket, amelyek általában a sebzését, lassítását, stb. váltják ki. 4.4.3.4 RoadNode, Road Az útszakasz név kissé csalóka, hisz az útszakasz objektumok lényegében egy koordinátát tartalmaznak, és láncba fűzésük határozza meg a teljes utat. Ezt azért terveztem így, hogy ne kelljen letárolni egyik pontot sem kétszer. Ezáltal az útszakaszokat a legelső pontjuk alapján azonosítom, és mindig két objektum határoz meg egy tényleges szakaszt, amin egy élőlény mozog. Ezt segítendő van egy NextNode valamint egy Direction nevű tulajdonsága, mely megadja a pont által kijelölt szakasz jellemzőit.
47
Az út gyakorlatilag egy tároló osztály, mely felelős az általa megkapott pontokból út építéséért és tárolásáért, valamint a rajta masírozó élőlények tárolásáért és léptetéséért, ezenkívül eltávolítja a játékból a megsemmisült vagy eltávozott lényeket. 4.4.3.5 Tower A tornyok a játék legösszetettebb objektumai. A fenti diagramon a tornyok ősosztálya található, ami elég kevés dolgot valósít meg, mivel a tornyok nagyban különböznek, nem szerettem volna redundáns funkciókat felvenni. Minden toronynak van hatótávolsága, bár már ezt sem használja ki mindegyik. Természetesen játékobjektumnak számítanak, valamint léptethetők is, bár torony szinten a lépés absztrakt függvény, ebből következik, hogy a torony osztály is az. A torony el tudja dönteni egy pályán lévő pontról, hogy milyen messze van, illetve hogy hatótávon belül van-e. Ezenkívül megtudható róla, hogy frissíthető-e, továbbá el is tudjuk adni. 4.4.3.6 Connection, ModifierProxy A Misztikus torony tervezett lehetőségeinek megvalósítására egy tornyok közötti kapcsolatot megvalósító osztályt terveztem. Ennek működési elve a következő: minden kapcsolat objektum két egymással összeköthető tornyot köt össze. Jelenleg a kettő közül pontosan az egyiknek Misztikus toronynak kell lennie. Minden torony tartalmaz egy úgynevezett módosító objektumot, mely pontosan az egyik tulajdonságára van állítva, így annak az értékét szűri többszörözéssel, vagy konkrét érték beállításával. Ezt a módosító objektumot állítja be a kapcsolat a torony típusától függően. Ha egy torony nincs kapcsolatban egy másikkal, a módosító objektuma az alapértelmezett módosító lesz, amely az eredeti értéket adja vissza. Erre a megoldásra azért van szükség, hogy a kapcsolat elvesztésével az érték tulajdonságok az eredetire visszaállhassanak, ne kelljen állapotmentést és visszaállítást csinálni. 4.4.3.7 Player A játéknak egyetlen játékosa van, így egyetlen játékos objektum van példányosítva, melyet azonban ismernie kell a játék jó néhány objektumának, hisz a mezőit változtatni kell a játék során. A játékos rendelkezik életpontokkal, mely az élőlények szabadulásakor csökken, pénzzel, ami növekszik minden lény likvidálásakor, illetve csökken, ha a játékos tornyot vagy fejlesztést vesz. Rendelkezik továbbá pontszámmal, amely a játék végén kiírásra kerül.
48
4.4.3.8 CreatureWaveHandler, TickCounter
11. ábra - Élőlényhullám generátor, Időzítő
Az élőlények indításáért egy külön osztály fog felelni, melynek objektumai a pálya adataiból kerülnek inicializálásra. Feladata, hogy megfelelő időközönként gyártson egy új lényt a paraméterei alapján egészen addig, míg a gyártott lények száma el nem éri a megadott maximális számot, majd hozzáadja a játékban lévő tornyok listájához, ennek
alapján azok kiválaszthatják következő áldozatukat. Ezzel
párhuzamosan természetesen a tornyok feliratkoznak az új élőlények által publikált halál és menekülés eseményekre, hogy az események bekövetkezése esetén a tornyok elfelejthessék az eltűnt lényeket. Ahhoz, hogy a lénygyártó objektum időzíteni tudja a lények készítését, meg kell valósítania az ICanStep interfészt, ám ennyi nem elég, hisz ha minden lépésben létrehozna egy lényt, szinte egy pillanat alatt az összes lény létrejönne. Ennek a problémának az orvosolására terveztem az általam szemléletesen ütésszámlálónak
nevezett
osztályt,
mely
megvalósítja
a
megfelelő
időintervallumonkénti eseménygenerálást. Paraméterként megkapja, hogy a nulladik időpillanatban az esemény bekövetkezzen-e, hogy hányszor kell bekövetkeznie (negatív szám esetén végtelenszer bekövetkezik), valamint a periódusidőt másodpercekben. Miután az objektum elkészült, a CounterOccurences metódusnak megadható, hogy mennyi idő telt el, illetve hogy engedélyezve van-e a számláló (a számlálás szüneteltethető a paraméter állításával). Mivel több bekövetkezés is időszerű lehetett az adott idősávban, a visszatérési érték egy másodpercekből álló lista, mely tartalmazza, hogy hány bekövetkezés volt és milyen időpillanatokban. Ezzel a megoldással elkerülhető, hogy a játék beakadása alkalmával elmaradjon az időszerű események bekövetkezése. A lények létrehozása esetében figyeltem arra, hogy megadható legyen nekik egy időtartam, ami azt reprezentálja, hogy valójában hány másodperce lett a lény 49
létrehozva a motor szerint, és ha ez nullától eltérő szám, akkor a lények automatikusan megfelelő távolságot „tesznek” meg a nekik kijelölt úton, mintha valóban abban az időpillanatban készültek volna. Ezt az időzítő objektumot használom fel a modell további két helyén, a diszkrét lövedékek létrehozásának sűrűségét szabályozza, valamint a hullámlövedékek sugarának nagyságát állítja. 4.4.3.9 Konkrét tornyok Mivel a tornyok működése nagymértékben eltér egymástól az absztrakt tornyon kívül, külön-külön is tárgyalom őket.
Néhány sokszor előforduló tulajdonságot és
metódust elemzek, mielőtt rátérnék a csak egyes tornyokra jellemző dolgokra. Annak az oka, hogy ezek a tulajdonságok vagy metódusok nem egy ősosztályba kerültek az, hogy ezek nem minden toronyban, csak a legtöbbjükben szükségesek. A tornyok legtöbbje tartalmaz egy lövedékgyár objektumot, mely minden toronyhoz specifikusan a saját lövedékéhez tartozó gyártót tartalmazza. Ezt használja a torony lövedékek készítéséhez. Szintén sok torony tartalmaz egy ismert valamint egy célzott élőlénylistát, melyben az általuk a világban ismert és az általuk lőtt lényeket tartják számon. Minden élőlényeket célzó torony tartalmaz egy kiválasztási stratégiát, ami meghatározza, hogy az általa ismert élőlények közül melyiket célozza meg, ha éppen nincs megfelelő számú célpontja. Az absztrakt stratégiát megvalósító konkrét stratégiákat akár játék közben is cserélhetjük. Például a legközelebbi élőlényt célozhatja egy torony.
12. ábra - A legközelebbi élőlényeket célzó stratégia
Minden fejleszthető torony tartalmazza a lehetséges fejlesztéseinek listáját, valamint a grafikus interfész számára kiajánl egy referenciát a következő fejlesztésre. Ha nincs több fejlesztés, null referenciát ad.
50
A legtöbb torony tartalmazza a lövési tulajdonságait, ezek különféle paraméterek, mint lövési sebesség, sebzés, hatótávolság, stb. Mivel jelentésük és használatuk egyértelmű, külön nem térek ki rájuk. Általában a lövedékgyártás felparaméterezésére szolgál. Amely tornyok számon tartják az élőlényeket a pályán, elfelejtik őket, mihelyt azok eltűnnek a pályáról, erről egy eseménykezelő gondoskodik a már említett módon. Néhány torony hangot fog adni, ha lő, így szükség van egy esemény kiváltására, amikor a lövedék megszületik. Az élőlényeket célzó tornyok rendelkeznek egy metódussal, mely a célpontok frissítéséért felelős. Minden frissítés szakaszban megvizsgálja, hogy a toronynak van-e a kapacitásának megfelelő célpontja éppen (ha egy torony elkezd lőni egy célpontot, nem keres újat, míg az előző vagy meg nem hal, vagy ki nem megy a hatóköréből), amennyiben nincs, a lényválasztási stratégiája segítségével választ egy, esetleg több lényt az általa ismert, de be nem célzott élőlények közül. Természetesen minden torony megvalósítja az ICanStep interfészt, és minden lépésben meghatározott lépéseket végez, például újraszámolja a célpontjait, vagy lépteti az általa létrehozott lövedékeket. Minden torony eladható, valamint a legtöbb torony fejleszthető, mindkét műveletet a torony maga végzi. Az első esetben kiváltódik az ősosztály eladást jelző eseménye, melyet a tornyot létrehozó játékkezelő objektum megfelelően lekezel. A második esetben a torony a paramétereit a megvásárolt fejlesztés szerint megváltoztatja, ez a folyamat irreverzibilis. A fejlesztést külön osztályok hajtják végre, ezekről később még szó esik. Természetesen az összes torony nem fér el egy diagramon, így külön kezelem őket. A három torony, melynek a képen látható a vázlata, hasonló működésű, mint azt a közös metódusok és mezők bizonyítják. A közös bennük, hogy adott időnként szokásos puskalövedéket lőnek, melyek a lények felé repülnek, majd egy idő után becsapódnak. Ehhez szükségük van a már megemlített Időzítő osztály egy példányára, ami ütemezi a golyók készítését. A Tüzér toronyból származó Sólyom torony paramétereitől eltekintve gyakorlatilag megegyezik a Gépágyú toronnyal, ennek ellenére nem tartottam célszerűnek az összeolvasztásukat, hisz logikailag két különböző egység, mely a grafikai oldalon meg is mutatkozik. Bővíthetőség szempontjából is ez az út látszott célravezetőnek. Az egyetlen észlelhető különbség a paramétereken kívül az, hogy a Gépágyú tornyot lehetősége lesz a játékosnak kétféle típusúvá fejleszteni, Láva 51
típusúként a Láva, Plazma típusúként a Plazma élőlényekre megnövekedett sebzést generál.
Természetesen
a
Plazma
vagy
Láva
élőlények
sebzést
osztó
eseménykezelőjében fel kell ismerni a lény típusának megfelelő lövedéket.
13. ábra - Gépágyú, Sár, Sólyom torony
A Sár torony, bár ő is repülő lövedékeket lő, komplexebb működéssel bír, hisz a lövedéke becsapódáskor robban, így sebzi a körülötte elhelyezkedő élőlényeket. Ezt a működést teljesen általánosra terveztem, megadható a robbanás sugara, az 52
epicentrumában a robbanás mértéke valamint egy valós számok halmazából valós számok halmazába képző tetszőleges függvény, mely megadja, hogy a robbanástól való távolságnak milyen függvénye legyen az elszenvedett sebződés. Ezt kezdetben egy lineáris függvényként szeretném implementálni. A Gépágyú toronyhoz hasonlóan a Sár torony is fejleszthető ugyanarra a két típusra, és ezáltal többletsebzést okoz a megfelelő ellenfeleknek. Ennek megvalósítása ugyanúgy történik, mint a Gépágyú torony esetében. A következő diagramon újabb két, egymáshoz működésben hasonlító torony szerepel. A két torony legszembetűnőbb vonása, hogy mindketten a Harmónia toronyból építhetők, illetve hogy mindketten hullámlövedéket lőnek.
14. ábra - Hóvihar és Térítő torony
53
A lövés úgy valósul meg, hogy ha van a tornyok hatósugarán belül ellenséges élőlény, akkor létrejön egy hullámlövedék, és egészen addig nem jön létre új, míg van célpont. A lövedék maga végzi el a hullámzást a már említett időzítő objektum egy példányának segítségével. Mindkét torony rendelkezik az élőlényekben definiált módosító effektusokkal. A Térítő toronynak két fajtája lehet, a Láva Térítő torony egy nem láva típusú élőlényt változtatat lávává, a Plazma Térítő torony analóg módon a nem plazma lényeket téríti plazmává. Ezt olyan módon szeretném megvalósítani, hogy a térítő által célzott élőlény típusát ideiglenesen megváltoztatom, majd ha a lény elhagyja a torony hatótávolságát, a torony automatikusan visszaállítja a lény eredeti típusát. A lassító Hóvihar torony működését nagyon hasonlóra terveztem, mint a Térítő toronyét. Amikor a lassító torony hatósugarába ér legalább egy élőlény, akkor lassító hullámlövedéket indít a torony, mely lassítja a torony összes célpontját. Az új célpontokra a torony egy lassító effektet helyez, melyet a torony aktuális paraméterei határoznak meg, ezáltal az adott élőlény sebessége lelassul. Ha az ellenség kiér a torony hatóköréből, a torony leveszi a felhelyezett lassítást, így visszaáll az alapsebesség. Két, az eddigiektől eltérő működésű torony maradt hátra. A Misztikus torony nincs kapcsolatban a pályán haladó élőlényekkel, a többi tornyot erősíti a velük létrehozott kapcsolatokkal, mivel azonban ezt a módosítást maga a kapcsolat objektum hatja végre, ezért a Misztikus toronyban mindössze a kapcsolatok maximális számát kell meghatározni, ami majd a fejlesztések során tud növekedni. A kapcsolat osztály gondoskodik róla, hogy csak kompatibilis tornyokat lehessen összekötni, jelen esetben az egyik torony Misztikus, a másik nem. Végül a Lézer torony az egyetlen a játékban, mely folyamatosan sebző lövedékkel rendelkezik. Nem szükséges időnként új lövedéket létrehoznia, így időzítőre sincs szüksége. Abban az esetben hoz létre egy lézersugarat, ha új célpontot választ. Ez a lövedék folyamatosan közölni fogja a célpont élőlénnyel a két jelentés között eltelt idő alatt bekövetkezett sebzést. Ezen kívül a működése megegyezik a hagyományos lövedékeket használó társaival. A Lézer torony a Sólyom párja, mindketten a Tüzér torony leszármazottai.
54
15. ábra - Misztikus és Lézer torony
Ha szemfüles az olvasó, észrevehette, hogy sem a Harmónia, sem a Tüzér torony nem rendelkezik fejlesztési lehetőséggel annak ellenére, hogy önmagukban nem képesek semmit csinálni. Mivel ezek a tornyok csak azért jönnek létre, hogy azután egy másik típusú toronyra változtassuk őket, ezért úgy terveztem, hogy a Harmónia és Tüzér tornyok törlésre kerülnek, és helyükre automatikusan egy új, a játékos által kiválasztott torony kerül. Ezt a toronycserét az összes tornyot összefogó játékkezelő objektum teszi meg.
55
4.4.3.10 TowerUpdate A tornyokhoz kapcsolódó fejlesztéseket külön objektumok reprezentálják. Minden torony saját fejlesztési osztállyal rendelkezik, melyek a közös absztrakt TowerUpdate osztályból származnak. Erre azért van szükség, mert minden torony esetén különbözni fog, hogy mely paramétereinek értéke fog változni egy fejlesztés következtében. A fejlesztés objektumok a paraméterüket az inicializálás során kapják meg, majd a tornyok saját statikus listájába kerülnek, ahol tárolódik a lehetséges fejlesztések sorozata az adott toronyra. Ezt a listát, valamint a jelenlegi szintjét ismeri a torony, így képes eldönteni, hogy van-e még fejlesztése, ha van, akkor melyik az. A tényleges fejlesztést vagy változtatást a fejlesztés objektum végzi, melynek lesz egy ApplyUpdate metódusa, amely bemenetként vár egy típusának megfelelő tornyot, majd az értékeit beállítja a fejlesztés saját paramétereit és a régi tulajdonságokat felhasználva. Természetesen a fejlesztések is pénzbe kerülnek, így a fejlesztett torony levonja a játékos pénzéből a fejlesztés árát. 4.4.3.11 Bullet, IBulletFactory A lövedékek szerepe, hogy szállítsák a tornyok által leadott információkat az élőlények felé, így egyfajta hordozó közegnek is tekinthetők. A korábban említettekkel összhangban a lövedékeknek három típusa van, ezt az általános Bullet osztályból leszármazó, három különböző funkcionalitást megvalósító osztály reprezentálja. Ezekből származnak le a konkrét tornyokhoz tartozó konkrét lövedéktípusok, melyek azonban általában már nem tesznek hozzá a szülő funkcionalitásához, kivéve a Sár torony robbanó töltényét, mely további speciális funkcionalitással rendelkezik. Minden lövedék az időben változik, tehát léptethető. A lépés kezelése mozgásból, sebzésértékek kiosztásából, animálásból állhat. Általános lövedék szinten van definiálva sebesség, sebzés és pozíció, ám ezen tulajdonságok jelentése eltér a különböző lövedékfajták esetében. A folytonos lövedék, melyet jelenleg csak a Lézer torony használ, két pont között húzódik. Ezenkívül minden lépésben folyamatos sebzést ad le a célpont lénynek egy sebzés esemény segítségével. A hullámlövedék két típusa a Hóvihar és Térítő lövedék. Funkciójuk nem a lények sebzése, csupán a vizualizáció a játékos számára. A módosító tulajdonságok beállítását a már említett módon a lövedék létrehozása előtt a torony végzi el. A tulajdonságok eltávolítását a lényekről szintén a torony végzi, amikor észreveszi, hogy 56
kívül kerültek a hatósugarából. A hullámlövedék animációjához szintén az időzítő osztályt fogom alkalmazni. A diszkrét lövedék a legösszetettebb, hisz effektív mozgást végez, majd célba éréskor sebzés kíséretében megsemmisül. A gazdatornyok bizonyos időnként létrehoznak egy lövedéket, melyek ezután a célpontjuk irányába haladnak a megadott sebességgel. Ezt a mozgást az élőlényéhez hasonlóan oldottam meg. Amint a lövedék eléri a célpont élőlényt, kiváltja a sebzés eseményt, majd kiváltja a saját felrobbanásáról szóló eseményt is, melyet az őt létrehozó torony lekezel, így a lövedék megsemmisül. Így a lépést kezelő függvény vagy mozgatja a lövedéket a cél felé, vagy elvégzi a felrobbanásával járó teendőket. Ha egy lövedék célpontja időközben meghal, lehetőség van útközben célpontot változtatni. Ehhez a letárolt toronytól kérhetünk le egy új célpontot a már megismert stratégiákat használva. A célpontváltoztatás természetesen irányváltoztatással jár. Ha nincs a forrástoronynak lehetséges célpontja, akkor az úton lévő lövedék megsemmisül. A Sár torony ezeken felüli extra funkcionalitással bír, így a lövedéke is speciális tulajdonságokkal rendelkezik. Amennyiben a lövedék eléri a célpontot, egy robbanás esemény is bekövetkezik, amit a lövedék maga kezel. Minden élőlénynek kiosztja a robbanásból származó sebzést, akik csak a becsapódás helyétől megfelelően kicsi távolságban helyezkednek el. A lövedékek gyártása az Abstract Factory 9 mintát követi, azaz egy általános gyártóosztályból származik minden lövedék saját gyártója, mely a megkapott paraméterekkel inicializál egy típusának megfelelő lövedéket. Természetesen a Sár torony lövedékének gyártója plusz paraméterekkel is rendelkezik az alap gyártóhoz képest.
4.4.4 Általános működés Miután megterveztem a játék objektumait, elkészítettem egy tervet az alapvető működésről is. A kulcsfontosságú folyamatokat külön is elemzem. 4.4.4.1 Játék inicializálása A játék grafikai motorja példányosítja a GameHandler játékkezelő osztályt. Ez vezérli az egyes komponenseket, valamit fogadja és kezeli a grafikai motor kéréseit. Az
9
Tervezési minta, ahol egy absztrakt gyártó osztályból származó osztály gyártja az absztrakt
osztályból származó osztályok objektumait.
57
objektum konstruktorában a már mezőként létrejött Player objektum a Reset metódus segítségével állítja be magát a kezdeti értékekre. Ezután létrejön a játék különböző objektumainak beállításait tartalmazó objektum. Ennek a konstruktorában kerül majd létrehozásra a konstans értékekkel feltöltött ElementData objektum, mely a különböző típusú tornyok beállításait tartalmazza. Ezeket az objektumokat használom majd később a tornyok létrehozásánál. Ezután kitöltöm szintén konstans értékekből létrehozott TowerUpdate objektumokkal a tornyok fejlesztéseit tartalmazó statikus tömböket. Végül betöltöm a programcsomagban alapértelmezetten megtalálható valamint a tárban lévő pályákat egy LevelData objektumokat tartalmazó listába. Ezek tartalmazzák magát a pálya leírását, valamint az összes élőlényhullám minden tulajdonságát. Az elérhető pályákat a telefonos adatbázisban szeretném tárolni.
16. ábra - Kezdeti értékek beállítása
58
4.4.4.2 A játékobjektumok léptetése A legfontosabb folyamat a játékban a különböző időben változó elemek állapotának frissítése. Ezt a műveletet a játékkezelő objektum végzi.
17. ábra - Játékelemek léptetése
A szekvencia diagramon látható, hogy a kezelő osztály sorban végighívja az általa ismert léptethető objektumokat, majd azok elvégzik saját állapotuk frissítését és visszatérnek. Gyakorlatilag ez a ciklus ismétlődik az egész játékon keresztül, néha egyegy felhasználói beavatkozás feldolgozását két iteráció közé iktatva, így minden automatikus állapotváltozás itt következik be. A GameInitializer típusú objektum léptetése hozza létre az új lényhullám-generátor objektumot, ha elérkezett a következő hullám ideje. Ezt követően a terv szerint minden torony objektum kerül léptetésre, ezt a diagramon egy általános típusú toronnyal jeleztem. Ezt követően a torony lépteti az általa létrehozott lövedékeket, majd kiválasztja a következő célpontjait, ha még nem telt be a kapacitása, végül új lövedékeket hoz létre, amennyiben szükséges. A lövedékek lépése több összetevőből állhat, ezt már nem szerepeltetem az ábrán, ám erről a 59
folyamatról még következik egy elemzés a következő pontban. A lövedékek mozoghatnak a célpont irányába, animálódhatnak, valamint sebzést küldhetnek a célpont élőlénynek. A tornyok, és ezáltal a lövedékek léptetése után következik az utak léptetése, mely gyakorlatilag az utak által nyilvántartott lények léptetését, valamint az előző körben eltűnt lények törlését jelenti. Az élőlények lépésük során az aktuális útszakaszon haladnak, ha elérik az út végét, megmenekülnek. Végül a játékkezelő lépteti a pályán haladó minden lényhullám-generátorát, mely bizonyos időnként egy új élőlényt indít, majd ezt megismerteti a pálya tornyaival, és elhelyezi a megfelelő úton. 4.4.4.3 Torony tölténygenerálás, élőlény sebzése Ez a folyamat része az előző léptetésfolyamatnak, ám egy konkrét példán részletesen is bemutatom a lövöldözés tervezett folyamatát. A Sár torony lövésének folyamata a legbonyolultabb, így megfelelően mutatja be a többi eset nagy hányadát is.
18. ábra - A Sár torony robbanó lövése
A szekvencia diagramon a különböző alternatív esetekre is megpróbáltam kitérni. Látható, hogy a torony lépteti az első lövedékét, amely nem robban fel, csak mozog a 60
célpont irányába. A torony második lövedéke elérte célpontját, így át is adja neki a lövedékben található sebzést, ám a célpont ettől nem hal meg. Ezután a lövedék felrobban, így a közelben elhelyezkedő élőlények sebződnek, és az ábrán látható módon, ha az egyik meghal, akkor értesítést kap minden lövedék, akinek ő volt a célpontja, minden torony, aki ismerte valamint az út, amin haladt. Végül a lövedéket létrehozó torony értesítést kap a lövedék megszűnéséről.
4.4.5 Pályaszerkesztő, pályaletöltés A pályaszerkesztő tervezésénél elsősorban a funkcionalitásra helyeztem a hangsúlyt, így ideiglenesen lemondtam az MVVM architektúra nyújtotta előnyökről. A weboldalba integrált modul egyszerű működéssel fog bírni, a felhasználó bejelentkezés után hozzáfér egy vezérlőhöz, melyen megtalálható a játék pályájának egy másolata, ahol bal egérkattintásokkal tud új útelemeket létrehozni, jobb egérkattintással pedig befejezheti művét. Ezenkívül meg kell adnia a pályához szükséges egyéb adatokat, mint például a pálya nevét, a játékos életpontjainak számát és a lényhullámok adatait. A lényhullámokat egy listában fogjuk látni, melyhez fel tudunk venni új lényt is, illetve a lista alatt az aktuálisan kijelölt hullám paramétereit tudjuk meghatározni. Ezek az értékek adatkötés segítségével egyből beállítódnak a modellben. Miután a szerkesztő a mentés gombra nyom, a megalkotott modellből elkészül a pályát leíró XML állomány, majd ez feltöltésre kerül az Azure blobtárába, végül az Azure SQL-es adatbázisban található, pályákat tartalmazó táblában is létrejön egy új rekord a pálya adataival. A folyamat közben a felhasználó egy töltőképernyőt lát, így meg tudja állapítani, hogy mikor fejeződik be a művelet. Mind a telefon, mind a Silverlight modul Azure-ban futó WCF szolgáltatást fog használni a funkciók elérésére. A telefonon a pályák listáját a főmenüben található Pályák letöltése feliratú gomb megnyomásával tölthetjük be, majd kiválasztás után a telefon tárába töltődik.
4.5 Implementáció A tervezés során kellőképpen részletes modellt készítettem, így nekiláthattam a különböző funkcionalitások megvalósításához.
Társammal közös verziókezelőt
alkalmaztunk a későbbi tesztelés megkönnyítése végett, de próbáltuk minél jobban elkülöníteni a két kódot, így én egy teljesen különálló osztálykönyvtáron dolgoztam, ami újrafelhasználható állományba fordul. A következőkben szeretném bemutatni a megvalósítás néhány kulcs-, illetve nem triviális elemét, elkerülve hogy az ismertetés 61
átcsapjon kódfelsorolásba, vagy untassa az olvasót. Igyekszem olyan sorrendben haladni, ahogy implementálást végrehajtottam, így egy logikai sorrend is felfedezhető. Ha egy osztály vagy metódus előzetes tárgyalás nélkül kerül elő, akkor már a tervnek megfelelően implementáltnak feltételezhető.
4.5.1 Az élőlények lépése Az élőlény osztályban az egyetlen nehézséget a léptetés megvalósítása jelentette, így ezt a metódust elemzem. A metódus egy valós számként megkapja az eltelt másodpercek számát, ezt használom fel a lépés hosszának meghatározásához. Kiszámolom a következő útszakasz kezdete és az élőlény pozíciója közötti távolságot, ezt kell megtennie a lénynek, mielőtt átváltana egy másik útszakaszra. float distance = Vector2.Distance(_currentStartPoint.NextNode.Position, Actua lPosition);
Ezután meghatározom, hogy a lény milyen hosszú utat tett meg az eltelt idő alatt, ehhez felhasználom a megkapott időt, az élőlény sebességét, valamint az esetleges sebességmódosító értéket. var stepPath = (float) (_speed*time*SpeedMultiplier);
A Módosítók hatását az alábbi módon, a LINQ Aggregate metódusával, adom össze: private double SpeedMultiplier { get { if (_slowChanged) { _speedMul = _slowEffects.Aggregate
, double>(1, (current, slowEffect) => current * slowEffect.Value); _slowChanged = false; } return _speedMul; } }
A következő lépésben három lehetőség van:
Ha az élőlény eléri az útszakasz végét, és nincs több útszakasz, akkor kiváltja a menekülést jelző eseményt.
Ha az élőlény eléri az útszakasz végét, és van további útszakasz, akkor levonja a lépéséből a kiszámolt távolságot, majd kiszámolja a következő útszakasz végéig tartó utat, és átlép a következő útszakaszra, beállítja az új irányát, végül újrakezdi a lépést.
62
Ha már nincs elég lépés az útszakasz végéig, megteszi az általa megtehető utat az útszakasz irányában.
while (distance <= stepPath) { if (_currentStartPoint.NextNode == null) { InvokeCreatureEscaped(new DiedEventDelegateArgs {DiedCreature = this}); return; } stepPath = stepPath - distance; _currentStartPoint = _currentStartPoint.NextNode; ActualPosition = _currentStartPoint.Position; if (_currentStartPoint.NextNode != null) distance = Vector2.Distance(_currentStartPoint.NextNode.Position, ActualPosition); else distance = -1; if (distance > stepPath) SetOrientation(_currentStartPoint.Orientation); } ActualPosition = ActualPosition + stepPath * _currentStartPoint.DirectionVector;
19. ábra - Az élőlények követik az út vonalát
4.5.2 Tornyok műveletei A tornyok bonyolultabb működésű metódusait elemzem, azonban ez mindegyik toronyban kisebb eltérésekkel ugyanúgy alakul, így elég lesz, ha a Gépágyú tornyon keresztül mutatom be a komplex funkciókat. A Gépágyú torony eladása, a többihez hasonlóan, a következőképpen alakul. Minden, a torony által ismert élőlény eseményeiről leiratkozik a torony. Ezután törlődik az összes torony által tárolt élőlény referenciája, majd az általa kilőtt lövedékek referenciája is. foreach (Creature knownCreature in _knownCreatures) { knownCreature.CreatureDied -= DiedEvent; knownCreature.CreatureEscaped -= DiedEvent; if (!TargetCreatures.Contains(knownCreature)) continue; TargetCreatures.Remove(knownCreature); } _knownCreatures.Clear(); FiredBullets.Clear();
63
Végül a játékos pénzmennyiségéhez hozzáadódik a torony aktuális értéke, mely a vételi árának valamint fejlesztési árának fele. Egy eseménnyel jelzem a GameHandler objektum felé, hogy erre a toronyra nincs már szükség, és az törli a nyilvántartásából. Legvégül a toronyhoz fűződő összes kapcsolat törlésre kerül. Player.Money += ActualPrice; InvokeSoldEvent(new SoldEventDelegateArgs {SoldTower = this}); foreach (Connection connection in Connections) { _toDelete.Add(connection); } foreach (Connection connection in _toDelete) { connection.Remove(); } _toDelete.Clear();
A GameHandler osztályban: private void SellMiniGunTower(object sender, SoldEventDelegateArgs args) { MiniGunTowers.Remove(args.SoldTower as MiniGunTower); }
A Connections osztályban: internal void Remove() { _source.Connections.Remove(this); _target.Connections.Remove(this); }
A kapcsolatok kimásolására a törlés előtt azért van szükség, mert a foreach cikluson belül nem lehet törölni abból a gyűjteményből, amin iterálunk. A következő összetett metódus a torony léptetése, melyben a korábbi szekvenciadiagramon látott három funkció valósul meg. Először a korábban elkészített lövedékek kerülnek léptetésre, majd a léptetés során felrobbant lövedékeket töröljük a nyilvántartásból. foreach (Bullet firedBullet in FiredBullets) { firedBullet.Step(time); } foreach (Bullet bullet in _bulletExploded) { FiredBullets.Remove(bullet); } _bulletExploded.Clear();
A lövedékek léptetése után megvizsgáljuk, hogy szükség van-e új célpontra, ha igen, megpróbálunk keresni egyet. Első lépés, hogy a célpontok közül eltávolítom azokat az élőlényeket, akik eltávolodtak a torony hatósugarából.
64
foreach ( Creature targetCreature in TargetCreatures.Where(targetCreature => (!InRange(targetCreature.ActualPosition)))) { _deleteCreatures.Add(targetCreature); } _deleteCreatures.ForEach(d => TargetCreatures.Remove(d)); _deleteCreatures.Clear();
Ezután kiválogatom a hatótávolságon belüli lényeket, majd közülük a torony lényválasztásai stratégiájával választok élőlényt. _targetStrategy.RecountTargets( _knownCreatures.Where(targetCreature => (InRange(targetCreature.ActualPos ition))), TargetCreatures, 1 - TargetCreatures.Count, Position);
A NearestStrategy osztályban: public void RecountTargets(IEnumerable inRangeNotTarget, List target, int missing, Vector2 towerPos) { target.AddRange( (from c in inRangeNotTarget where !target.Contains(c) orderby (Vector2.Distance(c.ActualPosition, towerPos)) select c).Take(missing)); }
20. ábra - A torony a legközelebbi célpontot lövi
Látható, hogy egyetlen LINQ kifejezés segítségével kérem le a tömbből a nekem megfelelő
élőlényeket.
Aggódtam,
hogy
a
megoldás
nem
optimális,
hisz
maximumkiválasztás helyett rendezést használ, de a méréseim alapján különbség nincs, vagy elhanyagolható. Először is megszűröm a listát a where feltétellel, hogy csak a már eddig nem célzott élőlényeket válassza ki célpontnak, majd az ilyen lényeket sorba állítom a toronytól vett távolságuk alapján, majd visszaadok annyit, amennyi a maximális kapacitáshoz hiányzik, vagy kevesebbet, ha nincs elég. Ezeket a torony innentől célzottnak veszi, belekerülnek a célpontjait tartalmazó listába.
65
Végül az új lövedékek generálása következik, melyet egy TickCounter objektum vezérel. Létrehoz a bekövetkezéseknek megfelelő számú új lövedéket a torony lövedékgyárával, majd a torony típusától illetve a célpont lény típusától függően kerül a lövedék sebzése növelésre. A torony feliratkozik az élőlény pályáról való eltűnését és a lövedékének felrobbanását jelző eseményekre. Az utóbbi eseményre a célpont élőlényt is feliratkoztatja. Végül eltárolja a kilőtt lövedéket a listájában, hogy a későbbi lépések alkalmával tudja a lövedéket léptetni. List<double> occurences = Counter.CounterOccurences(time, TargetCreatures.Count > 0); if (occurences == null) return; foreach ( DiscreteBullet bullet in occurences.Select(occurence => _bulletFactory.CreateBullet( BulletSpeed, BaseDamage, occurence, this)) .OfType()) { if ((Type == MiniGunType.Lava) && (TargetCreatures[0].Type == Creature.CreatureType.Lava)) bullet.Damage *= PreferenceMultiplier; if ((Type == MiniGunType.Plasma) && (TargetCreatures[0].Type == Creature.CreatureType.Plasma)) bullet.Damage *= PreferenceMultiplier; TargetCreatures[0].CreatureDied += bullet.CreatureDiedEvent; TargetCreatures[0].CreatureEscaped += bullet.CreatureDiedEvent; bullet.ExplodedEvent += BulletExplodedEvent; bullet.ExplodedEvent += TargetCreatures[0].BulletExplodedEvent; FiredBullets.Add(bullet); }
Amikor egy golyó új célpontot választ, mert a régi megsemmisült, szinte ugyanez a folyamat játszódik le.
4.5.3 TickCounter időzítő működése A játékban a különböző események időzítésében nagy szerepe van a TickCounter osztálynak, korábban már láthattuk a felhasználásának módjait. Egyetlen komplex metódusa van, a CounterOccurences, mely előállítja a bekövetkezett események időbélyegeit. A metódus visszatérési értéke egy bekövetkezéseket tartalmazó lista, amiben az értékek az eltelt időben bekövetkezett események relatív időpillanatai. Például ha egy másodperc alatt három bekövetkezést generál az időzítő, az értékek 0, 0.33, 0.66 lesznek. Kezdetben beállítható, hogy a számláló a 0. időpillanatban generáljon eseményt vagy ne, ezt kezelem a függvény elején. Ezután, ha a számláló már leszámolt, azaz már
66
megtörtént az eredetileg beállított megfelelő számú esemény bekövetkezése, akkor kiváltódik egy esemény, mely jelzi a felhasználónak, hogy a számláló lejárt. if (_count == 0) { OnCountDownEvent(new CountDownDelegateArgs {Owner = _owner}); return occurences; }
Amennyiben még nem járt le a számláló, az eltelt idő, az előző iterációban elmentett maradék idő (amely nem tesz ki egy periódust) és a periódusidő segítségével kiszámolom, hogy az adott idő alatt hány bekövetkezés volt, valamint az új maradék időt. Felhasználom az eltárolt szülőobjektum módosító objektumát, ha létezik, hogy módosítani tudjam a periódusidőt. Erre azért van szükség, mert a Misztikus torony gyorsabb tüzelést tud biztosítani a Gépágyú toronynak, tehát amikor a Gépágyú létrehozza az időzítőjét, beállítja magát az időzítő tulajdonos tulajdonságában, így az időzítő használni tudja a torony módosító objektumát a lövés gyorsításának érdekében. Természetesen a többi esetben az alapértelmezett módosítót használom, mely nem változtat a működésen. int i = -1; double temp while (temp { i++; temp += } Remaining =
= 0; <= time + Remaining)
Modifier.ModifyValue(Period); time + Remaining - i * Modifier.ModifyValue(Period);
Végül előállítom az eredménylistát. for (int j = 0; j < i; j++) { occurences.Add((i - j - 1) * Modifier.ModifyValue(Period) + Remaining); ... return occurences; }
4.5.4 Ütközések keresése új torony készítésénél Feladatom volt még az is, hogy eldöntsem, hogy egy új torony elhelyezhető-e egy koordinátán anélkül, hogy ütközne egy másik toronnyal illetve egy útszakasszal. Ezt a vizsgálatot a GameHandler objektum végzi, a metódust a felhasználói felület hívja folyamatosan, miközben a játékos egy új tornyot akar letenni. Ennek eldöntéséhez a metódus paraméterül kapja az eldöntendő koordinátát, a tornyok sugarát valamint az út szélességét. Az ütközés keresése két lépésből áll, az egyikben az útszakaszokkal történő metszést vizsgálom, a másikban a már lent lévő tornyokkal történő metszést.
67
if (Vector2.DistanceSquared(towerCentre, road.RoadNodes[i].Position) <= (towerRadius + roadWidth / 2) * (towerRadius + roadWidth / 2)) return false; float u = ((towerCentre.X - road.RoadNodes[i].Position.X) * (road.RoadNodes[i + 1].Position.X - road.RoadNodes[i].Position.X) + (towerCentre.Y - road.RoadNodes[i].Position.Y) * (road.RoadNodes[i + 1].Position.Y road.RoadNodes[i].Position.Y)) / Vector2.DistanceSquared(road.RoadNodes[i + 1].Position, road.RoadNodes[i].Position); if ((u < 0) || (u > 1)) continue; Vector2 nv = road.RoadNodes[i].Position + u * (road.RoadNodes[i + 1].Position - road.RoadNodes[i].Position); if (Vector2.DistanceSquared(nv, towerCentre) <= (towerRadius + roadWidth / 2) * (towerRadius + roadWidth / 2)) return false;
21. ábra - Piros kör jelzi az ütközést
Az első esetben kiszámolom a vizsgálandó pont távolságát minden szakasztól egy koordinátageometriai képlet segítségével [20], és megvizsgálom, hogy ez a távolság nagyobb-e, mint a torony sugarának és a félútvastagságnak az összege. Amennyiben nem, akkor a torony metszeni fogja az utat. Ezenkívül, mivel lekerekített végű utakat használunk, minden csomópontban megvizsgálom, hogy a létrehozandó torony nem metszi-e az adott csomópontban lévő félútvastagságú sugarú kört. MiniGunTowers.Any( miniGunTower => Vector2.DistanceSquared(towerCentre, miniGunTower.Position) <= 4 * to werRadius * towerRadius)) return false;
A második esetben minden, a pályán elhelyezett torony esetében megvizsgálom, hogy a középpontja milyen távol van a létrehozandó torony középpontjától, ennek a távolságnak két toronysugárnál nagyobbnak kell lennie. Igazából
a
távolság-összehasonlítások
helyett
összehasonlításokat végzek a teljesítmény optimalizálásáért.
68
távolságnégyzet-
4.5.5 Pálya betöltése XML fájlból Kezdetben
a
teszteléshez
bedrótozott
pályát
alkalmaztam,
később
implementáltam a pálya XML-ből való beolvasását támogató metódust. A fájlstreamet két helyről nyithatjuk meg, megadható egy, az alkalmazás binárisában lévő, erőforrásként tárolt XML, valamint az alkalmazás saját tárterületén (IsolatedStorage) elhelyezkedő állomány. Előbbiben helyezkednek el az alapértelmezett pályák, míg utóbbi helyre az internetről letöltött pályák kerülnek. A pályát leíró szöveget egy XDocument objektumba töltöm, majd LINQ lekérdezések segítségével a saját LevelData objektumomba töltöm a kinyert adatokat. Felolvasási hiba esetén az adott pálya nem kerül betöltésre. A teljes XML feldolgozó kódot, úgy vélem, felesleges lenne kiemelni, helyette egy példát mutatok az útszakasz-koordináták kinyerésére. foreach (IEnumerable roads in nodes.Select( xElement => (from q in xElement.Descendants("Node") select new Vector2((float)q.Element("X"), (float)q.Element("Y"))))) data.RoadNodes.Add(new List(roads));
4.5.6 Pályaszerkesztő és pályaletöltés kiszolgálása WCF szolgáltatással Mielőtt elkészítettem a pályaletöltés támogatását mind a webes, mind a telefonos oldalon szükség volt egy WCF szolgáltatásra, melyet a két kliens használni tud. Erre azért volt szükség, mert sem a webes Silverlight, sem a Windows Phone 7-en elérhető .NET keretrendszer nem támogatja a Windows Azure szolgáltatások elérését direkt módon. A tervezés során ezt a részt nem dolgoztam ki részletesen, ezért itt gondoltam át, hogy milyen szolgáltatásokat fog használni a két kliens. Végül úgy találtam, hogy három funkcionalitást kell megvalósítanom:
XML mentése Azure Blob tárba, egyidejűleg a pálya adatainak mentése az Azure SQL táblába, mely a pályaadatokat tartalmazza. [Silverlight pályaszerkeztő modul]
Elérhető pályanevek lekérése. [VortexTD]
Kiválasztott pálya leíró XML állományának letöltése. [VortexTD]
A WCF szolgáltatás is az Azure webszolgáltatás mellett egy IIS7 szerveren fut.
69
4.5.6.1 Az elkészült pálya tárolása A pályák állományát az Azure Blob Storage nevű tárban helyeztem el, ez a technológia alkalmas bináris állományok viszonylag olcsó tárolására. Az Azure SDK feltelepítésével gazdag .NET támogatást kapunk, így csak használnom kellett a beépített metódusokat. Természetesen előbb azonosítanom kellett magam az Azure előfizetésben, amit a tanszék bocsátott a rendelkezésünkre a szakdolgozathoz, majd kaptam egy connectionstringet, ezt felhasználva tudtam a szolgáltatással kommunikálni. CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting("BlobConnection"); CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); CloudBlobContainer blobContainer = blobClient.GetContainerReference("vortextdstore"); blobContainer.CreateIfNotExist(); BlobContainerPermissions containerPermission = blobContainer.GetPermissions(); containerPermission.PublicAccess = BlobContainerPublicAccessType.Container; blobContainer.SetPermissions(containerPermission); string fileName = string.Format("{0}_{1}.xml", userName, DateTime.Now.ToString(„MM-dd-yyyy-hh-mm-ss”)); CloudBlockBlob blob = blobContainer.GetBlockBlobReference(fileName); blob.Properties.ContentType = „text/xml”; blob.UploadText(xml);
Második lépésként az Azure-ben létrehozott adatbázisunk egyik táblájába szúrok be rekordot, ehhez létrehoztam egy Linq2Sql DataContext objektumot. Ennek mikéntje megegyezik a szokásos adatbázisszerverek esetén megszokott módszerrel. Majd a DataContext objektumba beszúrok egy új elemet, végül véglegesítem a változásokat. using (var dc = new MapDataContext()) { var mapData = new map { email = email, creator = userName, date = date, description = null, // TODO if we will be in a good mood :) mapname = name, URL = blob.Uri.AbsoluteUri, image = null // TODO change to image }; dc.maps.InsertOnSubmit(mapData); dc.SubmitChanges(); }
A kódban maradt kommentek is árulkodnak róla, hogy idő hiányában a pályának jelenleg nem lehet képet és leírást megadni, így azt az adatbázisban sem tárolom, ennek ellenére úgy lett kialakítva a tábla, hogy támogassa ezeket az adatokat, hiszen ez a funkció tervbe van véve a későbbiekben. 70
4.5.6.2 Pályanevek lekérése az adatbázisból Miután bármelyik felhasználó a pályaszerkesztővel készített pályáját eltárolta az Azure-ben, a többi felhasználónak lehetősége nyílik a telefonon letölteni azt. Ennek a műveletnek az első lépése, hogy a készülék letölti az adatbázisból az elérhető pályák listáját. Természetesen ezt egy szolgáltatás művelet segítségével teszi, mely műveletet az előzővel összefogva egy szolgáltatásban implementáltam. A kérés teljesítéséhez egy Linq2Sql lekérdezést fogalmazok meg, mely gyakorlatilag az előbb látott táblamezők közül választja ki a szükséges mezőket, jelenleg a pályacímeket, valamint a pályák letöltési címét adom vissza a kliensnek. using (var dataContext = new MapDataContext()) { IQueryable<string[]> queryResult = from maps in dataContext.maps select new[] {maps.mapname, maps.URL}; result = queryResult.ToArray(); }
4.5.6.3 Kiválasztott pálya letöltése A kliens visszaküldi a szolgáltatásnak a letölteni kívánt pálya címét, majd a szolgáltatásban létrehozok egy webklienst, amely szöveges formátumban letölti a megadott cím tartalmát. Mivel a kliens által megadott cím mindig egy XML állományra fog mutatni, ezért a letöltött szöveg is egy XML-t fog tartalmazni, ezt kapja vissza a kliens. using (var client = new WebClient()) { string result = client.DownloadString(mapUrl); return result; }
4.5.7 Pályaszerkesztő A pályaszerkesztő Silverlight vezérlő elkészítése két lépésből állt. Első lépésben Expression Blend segítségével létrehoztam a felhasználói felületet. Nem töltöttem sok időt azzal, hogy ergonomikussá és kényelmessé tegyem, így a kész modul inkább tekinthető prototípusnak, mint kész terméknek. Ennek ellenére természetesen szem előtt tartottam, hogy funkcionálisan teljes legyen a szerkesztő, és gyakorlott kézzel teljes értékű pályát lehessen készíteni a segítségével.
71
A pályaszerkesztő felépítése a következő:
22. ábra - Pályaszerkesztő felépítése
1. Gombok, melyek segítségével új lényhullámot adhatunk a listához, illetve a kijelölt hullámot törölhetjük. A Save gomb megnyomása után a létrehozott pálya feltöltésre kerül a tárba, adatai pedig az adatbázisba. 2. Megadhatjuk a pálya nevét valamint a játékos kezdő életpontjainak számát. Jelenleg ez a két paraméter származik a pályát leíró állományból. 3. A rajzoló felületen készíthetjük el a pálya útjait. Bal egérgombnyomások esetén létrejön egy új csomópont, majd a megfelelő számú csomópont létrehozása után jobb egérgombbal tudjuk véglegesíteni az utat. Több utat is elhelyezhetünk, majd a hullám StartNodeId tulajdonságával határozhatjuk meg, hogy hányadik úton haladjon az adott hullám (nullától számozva). 4. A lista segítségével tudunk váltogatni a lerakott utak között.
72
5. A kiválasztott út csomópontjainak koordinátáit láthatjuk. 6. A lényhullámok hozzáadása után itt jelenik meg az új hullám ikonja és sorszáma. 7. A mezők segítségével tudjuk megadni a hullámok paramétereit, hibaellenőrzést nem tartalmaz. A gyors kitölthetőség kedvéért tabulátor segítségével tudunk lépegetni a mezők között, és a mező tartalma alapértelmezetten kijelölődik, hogy csak felül kelljen írni. A felületet a Silverlightban használatos XAML nyelven írtam le. Az egyes felületi elemekhez adatkötéssel rendeltem hozzá a mögöttes logikában általam implementált hullámokat és utakat tartalmazó listákat. A listáknak saját adatsablonokat készítettem. Például a hullámokat tartalmazó listák elemei egy StackPanel-ből és benne elhelyezett szövegmezőből illetve képből állnak. A szöveg és a kép az értékét adatkötés felhasználásával kapja. <StackPanel Margin="5,0">
4.5.8 A játék felkészítése a pályák letöltésére Legutolsó lépésként fel kellett készítenem a játékot arra, hogy le tudja tölteni a weboldalon elkészített játékokat, az ehhez tartozó szolgáltatásokról már volt szó. Így gyakorlatilag két metódust kellett szolgáltatnom a felhasználói felületnek, mellyel a pályalistát és egy konkrét pályát le tud tölteni. Mindkét esetben aszinkron szolgáltatáshívás történik. 74
Az egyik esetben egy sztringekből álló listát adok vissza azon pályanevekkel, melyek a helyi telefonon nem elérhetők, az Azure tárban azonban igen, így elkerülöm, hogy egy játékos ugyanazt a pályát többször töltse le. A telefonon megtalálható pályákat a telefonon Mango frissítés óta jelenlévő SQL CE alapú adatbázisban tárolom. Az ebben található pályalistával szűröm a szolgáltatás által meghatározott elérhető pályaneveket: List<Map> queryResult = null; if (dbContext.DatabaseExists()) queryResult = (from map in dbContext.Maps select map).ToList(); List<string[]> toDelete = queryResult != null ? (from map in queryResult from s in e.Result where map.MapName == s[0] select s).ToList() : new List<string[]>(); OnMapNamesObtained(new MapNamesObtainedHandlerArgs {Names = e.Result.Except(toDelete).ToList(), HasError = false});
Ahogy a kódból is látszik, eseménnyel értesítem a felhasználói felületet az operáció befejeződéséről. A pályaletöltés esetében a kapott XML sztringet először kiírom az alkalmazás tárhelyére, majd a már ismertetett módon beolvastatom egy pályát reprezentáló objektumba, végül hozzáadom az elérhető pályák listájához. A telefonon lévő adatbázisba is elmentem, így legközelebb már tudni fogom, hogy ez a pálya már megtalálható a telefonon. A művelet végén ismét eseményt váltok ki. using (IsolatedStorageFile userStoreForApplication = IsolatedStorageFile.GetUserStoreForApplication()) using (IsolatedStorageFileStream isoStream = userStoreForApplication.CreateFile(filename)) using (var sw = new StreamWriter(isoStream)) sw.Write(map); using (var dbContext = new MapDataContext(MapDataContext.DbConnectionString)) { dbContext.Maps.InsertOnSubmit(new Map {FileName = filename, IsDefault = false, MapName = mapName}); dbContext.SubmitChanges(); }
24. ábra - Látható, hogy a tartalom letöltése közben a felhasználó várakozik
75
5 Tesztelés, teljesítménymérés A játék motorját egy osztálykönyvtárként fejlesztettem, így mentes volt minden felület általi kötöttségektől. Ennek következtében már a fejlesztés elején lehetőségem nyílt egy egyszerű konzolos alkalmazást írni, mely szimulál egy játékot, azaz rak le általam megadott helyre tornyokat, indít lényhullámokat, majd megadott sebességgel „futtatja” az időt. Ez az alkalmazás sok segítséget nyújtott, még mielőtt tudtam volna a felhasználói felületet integrálva tesztelni, hisz sok objektumnak megvalósítottam a ToString metódusát, így figyelemmel tudtam követni, hogy mi történik, illetve láthattam, ha valamelyik objektum nem úgy viselkedik, ahogy elvártam. Később már a grafikai felülettel teszteltem a játékmotor funkcióit, melyet társam bocsátott rendelkezésemre. Rengeteg jól észrevehető, illetve kevésbé észrevehető hiba adódott. Felkértünk ismerősöket is, hogy próbálják ki a játékot, figyelmeztessenek, ha találnak valami rendellenességet, illetve értékeljék a játék kinézetét, irányíthatóságát. Ennek következtében néhányszor megváltozott a felület, valamint az irányítható objektumok megnőttek vagy éppen lecsökkentek. A pályaszerkesztő tesztelése szintén kézzel történt, létrehoztam néhány egyszerű pályát, majd végigkövettem az útját egészen a telefon táráig. Az előforduló hibákat javítottam, bár tisztában vagyok vele, hogy a beviteli mezők ellenőrzése további feladat lenne, hisz jelenleg könnyű korrupt adattal feltölteni egy pálya objektumot, mely a játék összeomlásához vezethet. A fenti konzolos alkalmazás lehetőséget adott arra, hogy a JetBrains dotTrace profilozó alkalmazással is megvizsgáljam a kódomat, mind memória, mind pedig teljesítmény szempontjából (mostanra megjelent egy profilozó alkalmazás, mely támogatja a Windows Phone 7 alkalmazásokat). A memóriahasználattal nem akadtak gondok, sosem mértem beragadó objektumokat, melyek nem semmisülnek meg, így nagyjából konstans volt minden típusú objektum száma a futás közben. A teljesítménymérést követően fény derült néhány kódrészletre, melyek a szűk keresztmetszetet jelentették, vagyis a futási idő nagy százalékát generálták. Ilyen volt például a legközelebbi lény kiválasztását végző metódus, így ezt számtalanszor átírtam. Végül úgy éreztem, hogy mindent megtettem, hogy a maximumot hozzam ki a motorból. 76
6 Értékelés Amikor az ember egy nagy lélegzetvételű munka végére ér, szükségszerűen összegzi az eredményeket és tapasztalatokat, hogy a következő hasonló problémát jobban, hatékonyabban tudja megvalósítani. A szakdolgozatom során rengeteg kurrens technológiával ismerkedtem meg, mindegyikben megpróbáltam a lehetőségekhez mérten minél jobban elmerülni. Szerencsés, hogy ezt egy ilyen ösztönző feladat kapcsán tehettem meg, mint egy játék logikájának és támogatásának fejlesztése. Bár a C# nyelv nem volt teljesen új számomra, a projekt során mégis új mélységeiben ismertem meg, gondolok itt főleg a LINQ kifejezések használatára, valamint a WCF szolgáltatások használatának mikéntjére. Megismerkedtem a Windows Phone 7 rendszer fejlesztőeszközeivel, a telefon tulajdonságaival. Belekóstoltam a Windows Azure felhőszolgáltatás használatába, valamint a rendelkezésre álló fejlesztőeszközök lehetőségeivel bővítettem a tudásomat. Végül, de nem utolsó sorban megismerkedtem az XNA játékmodelljével, hogy hogyan változik a játék által befogott virtuális világ az idő múlásával. Igyekeztem eleget tenni a feladatom kiírásának, mind az alkalmazás fejlesztése közben, mind ezen szakdolgozat írásakor, remélem, hogy az általam implementált funkciók lefedik a feladatkiírásban megfogalmazott igényeket. Arra törekedtem, hogy a szakdolgozatomban világos és valamelyest érdekes előadásmódban tolmácsoljam az alkalmazásfejlesztés
folyamatának
lényeges
elemeit.
Igyekeztem
megfelelően
kiválasztani a hangsúlyosabb vagy nehezebben érthető részleteket mind a tervezést, mind az implementálást bemutató részben, hisz természetesen nem volt lehetőségem a teljes alkalmazásmodellt vagy forráskódot lefedni. Megpróbáltam az általam bemutatott részeket megfelelő illusztrációkkal illetve programrészletekkel ellátni, esetleg kiegészíteni a magyarázatot. A feladat kezdetén megismerkedtem a később felhasználandó technológiákkal, ezeket bemutattam a dolgozatomban. Következő lépésben megvizsgáltam, hogy milyen játékfejlesztői lehetőségek léteznek a platformon. Végeredményben elkészítettem a Tower Defense játék motorját, melyet kiegészítve hallgatótársam grafikai felületével, egy teljes értékű Windows Phone 7 játékot alkottunk. A játékhoz készített Silverlight alapú webalkalmazáshoz fejlesztettem egy pályaszerkesztő modult, valamint egy ezt
77
kiszolgáló, WCF keretrendszerre épülő szolgáltatást. A pályaszerkesztő segítségével néhány tesztpályát is készítettem. A fejlesztés során rengeteg hasznos tudásra tettem szert játékfejlesztés, mobil alkalmazásfejlesztés, C# programozás, valamint Microsoft technológiák használata terén.
6.1 Továbbfejlesztési lehetőségek A játék tervezésekor rengeteg funkciót szerettünk volna elkészíteni, melyet sajnos az idő rövidsége miatt idáig nem tudtunk implementálni. A jelenlegi megoldások között is található néhány átdolgozandó elem, ezeket próbálom összeszedni.
Játékmodell fejlesztése, tervezési minták használata, kód-újrahasznosítás, játékelemek közötti kommunikáció újratervezése.
Pályatervező
modul
teljes
újratervezése,
ergonomikus
kialakítás,
felhasználói bevitel validálása, interaktív segítség, robosztus hibakezelés.
NLog vagy más naplózó osztálykönyvtár használata a fejlesztés támogatásához.
Minden
konstans
adat
XML
konfigurációs
állományból
kerüljön
felolvasásra.
Játéktartalom gyártása, egyensúlyozása a megfelelő játékélmény érdekében.
Játék állapotmentésének és visszaállításának támogatása.
Bemutató pálya kezdő játékosoknak.
Létrehozott pályákhoz címkék rendelése, letöltések számolása, tetszik gomb megjelenítése.
Lokális és globális toplista, hogy a játékosok összemérhessék tudásukat.
Elért, különleges eredmények listázása, tárolása (Achievement), például: Last Hope – ölj meg egy lényt az utolsó 30 pixelen.
Visszajátszási lehetőség, visszajátszások feltöltése a weboldalra.
Animációk, hangeffektek fejlesztése, skinnelhetőség.
További nyelvi fájlok létrehozása.
Tornyok képességeinek fejlesztése, több szerep a több érintési pontot kezelő kijelzőnek.
Publikálás a MarketPlace-be.
78
Köszönetnyilvánítás Ezúton szeretnék köszönetet mondani konzulensemnek, Albert Istvánnak és az AAIT tanszéknek, hogy a teljes fejlesztési ciklus alatt rendelkezésünkre bocsátottak egy Windows
Phone
7
operációs
rendszert
futtató
okostelefont
a
fejlesztés
megkönnyítésének érdekében, valamint lehetőséget kaptunk, hogy használhassuk egy Windows
Azure
előfizetés
néhány
komponensét,
felhőszolgáltatásokat.
79
így
megismerhettük
a
Irodalomjegyzék [1] Apple App Store Metrics http://148apps.biz/app-store-metrics/?mpage=catcount (2011. november) [2] Windows Embedded Compact 7 http://msdn.microsoft.com/en-US/library/gg154201.aspx (2011. november) [3] Windows Phone 7 Architecture http://msdn.microsoft.com/library/ff402531.aspx#AppPlat_Overview_Runtime (2011. november) [4] Nick Randolph, Christopher Fairbairn: Windows® Phone 7 Application Development (ISBN: 978-0-470-89166-7) [5] Andrew Troelsen: Pro C# 2010 and the .NET 4 Platform (ISBN: 978-1-4302-2549-2) [6] Benchmarking .NET Direct3D 11 APIs http://code4k.blogspot.com/2011/03/benchmarking-cnet-direct3d-11-apis-vs.html (2010. november) [7] Chad Carter: Microsoft® XNA™ Unleashed (ISBN: 0-672-32964-6) [8] Microsoft Silverlight http://en.wikipedia.org/wiki/Microsoft_Silverlight (2011. november) [9] Matthew MacDonald:Pro Silverlight 4 in C# (ISBN: 978-1-4302-2529-2979-7) [10] Juval Löwy: Programming WCF Services (ISBN: 978-0-596-80548-7) [11] Roger Jennings: Cloud Computing with the Windows® Azure™ Platform (ISBN: 978-0-470-50638-7) [12] Microsoft Azure features http://www.microsoft.com/windowsazure/features/ (2011. november) [13] tIDE project website http://tide.codeplex.com (2011. november) [14] Farseer Physics Engine http://farseerphysics.codeplex.com (2011. november) [15] Engine Nine features http://nine.codeplex.com (2011. november)
80
[16] FlatRedBall Engine comparison http://www.flatredball.com/frb/docs/index.php?title=FlatRedBall_Features (2011. november) [17] SunBurn Engine 2.0 http://www.synapsegaming.com/products/sunburn/engine/ (2011. november) [18] ScriptTD Game XML editing http://scripttd.codeplex.com/wikipage?title=Updating the Script XML (2011. november) [19] Tower Defense Games http://en.wikipedia.org/wiki/Tower_defense (2011. november) [20] Minimum distance between point and line http://paulbourke.net/geometry/pointline/ (2011. november)
81