PROGRAMUL DE STUDIU TEHNOLOGIA INFORMAȚIEI FORMA DE ÎNVĂȚĂMÂNT IF PROIECT DE DIPLOM Ă COORDONATOR ȘTIINȚIFIC CONF. DR. ING. GIANINA GABOR ABSOLVENT… [617331]

UNIVERSITATEA DIN ORADEA
FACULTATEA DE INGINERIE ELECTRICĂ ȘI TEHNOLO –
GIA INFORMAȚIEI
PROGRAMUL DE STUDIU TEHNOLOGIA INFORMAȚIEI
FORMA DE ÎNVĂȚĂMÂNT IF
PROIECT DE DIPLOM Ă
COORDONATOR ȘTIINȚIFIC
CONF. DR. ING. GIANINA GABOR
ABSOLVENT: [anonimizat]
2018

FACULTATEA DE INGINERIE ELECTRICĂ ȘI TEHNOLOGIA INFORMAȚIEI
DEPARTAMENTUL CALCULATOARE ȘI TEHNOLOGIA INFORMAȚIEI
TEMA _____
Lucrare de finalizare a studiilor a student: [anonimizat]:
HERLITSKA ATTILA-LEVENTE
1). Tema lucrării de finalizare a studiilor:
JOC DE ACȚIUNE INTERACTIV IMPLEMENTAT ÎN JA V A
2). Termenul pentru predarea lucrării: 3 iulie 2018
3). Elemente inițiale pentru elaborarea lucrării de finalizare a studiilor: programarea
orientată pe obiecte, JavaFX și MySQL
4). Conținutul lucrării de finalizare a studiilor: Introducrere;Tehnologii utilizate la
implementarea aplicației-JavaFX,modelul model-view-controller(MVC),Apache
Maven,MySQL;Analiza și descrierea contextului aplicației-Analiza jocului video,Pornirea
unui nou joc,Jocul principal,Meniul Game Over;Implemantarea Aplicației- Controlarea
personajului din joc, Armele din joc, Atricolele de prim ajutor din joc, Sistemul de deseanre
din joc, Sistemul de importare al imaginilor, Personajul principal din joc, Personajele zombi
din joc, Implementarea bazei de date, Implmementarea Maven-ului, Implmementarea
JavaFX,Implementarea modelului model-view-controller(MVC); Concluzii; Bibliografie.
5). Material grafic:
6). Locul de documentare pentru elaborarea lucrării: Internet, laborator Calculatoare,
biblioteca universității
7). Data emiterii temei 1 octombrie 2017
Coordonator științific
Conf. dr. ing. Gianina GABOR

UNIVERSITATEA DIN ORADEA
FACULTATEA DE INGINERIE ELECTRICĂ ȘI
TEHNOLOGIA INFORMAȚIEI
PROGRAMUL DE STUDIU TEHNOLOGIA INFORMA ȚIEI
FORMA DE ÎNVĂȚĂMÂNT IF
JOC DE ACȚIUNE INTERAC –
TIV
IMPLEMENTAT ÎN JA V A
COORDONATOR ȘTIINȚIFIC
conf. dr. ing. GIANINA GABOR
ABSOLVENT: [anonimizat]
2018

CUPRINS
INTRODUCERE …………………………………………………………………………………………….. 3
CAPITOLUL I. TEHNOLOGII UTILIZATE LA IMPLEMENTAREA
APLICAȚIEI …………………………………………………………………………………………………………….. 5
I.1 JavaFX ………………………………………………………………………………………………………. 5
I.2 Modelul model-view-controller(MVC) ………………………………………………………… 7
I.3 Apache Maven ……………………………………………………………………………………………. 9
I.4 MySQL ……………………………………………………………………………………………………. 10
CAPITOLUL II. ANALIZA ȘI DESCRIEREA CONTEXTULUI ……………………. 11
II.1 Analiza jocului video ……………………………………………………………………………….. 11
II.2 Pornirea unui nou joc ……………………………………………………………………………… 12
II.3 Jocul principal ………………………………………………………………………………………… 13
II.4 Meniul Game Over …………………………………………………………………………………. 16
CAPITOLUL III. IMPLEMENTAREA APLICAȚIEI ……………………………………. 18
III.1 Controlarea personajului din joc ……………………………………………………………. 18
III.2 Armele din joc ……………………………………………………………………………………….. 18
III.3 Articolele de prim ajutor din joc …………………………………………………………….. 22
III.4 Sistemul de desenare din joc …………………………………………………………………… 23
III.5 Sistemul de importare a imaginilor ………………………………………………………… 27
III.6 Personajul principal din joc …………………………………………………………………… 30
III.7 Personajele tip zombi din joc …………………………………………………………………. 33
III.8 Implementarea bazei de date ………………………………………………………………….. 36
III.9 Implemetarea Maven-ului ……………………………………………………………………… 41
III.10 Implementarea JavaFX ………………………………………………………………………… 41
III.11 Implementarea modelului model-view-controller(MVC) ……………………….. 42
CONCLUZII …………………………………………………………………………………………………. 44
BIBLIOGRAFIE …………………………………………………………………………………………… 45

INTRODUCERE
Jocurile video sunt o formă a divertismentului care au avut un început în anii '70 după
ce tehnologia a început să se dezvolte. Dacă atunci jocurile au fost doar în fază de
experimentare în zilele noastre jocurile video fac parte dintr-o mare industrie. Azi putem zice
că suntem în deceniul cinci al jocurilor video. Cel mai mare pas în industrie l-a reprezentat
realizarea primelor jocuri în totalitate 3D, introducerea conceptului de cloud gaming și
creșterea popularității jocurilor pe tablete și telefoane.
Ultimele două generații de jocuri sunt reprezentate de generația șase și șapte. Cu
generația a șaptea si cu ajutorul unui salt în tehnologie au apărut jocurile de tip Role-Playing
Game (RPG) și First-Person Shooter (FPS). În generația a șaptea din cauza crizei economice
producerea consolelor de jocuri video și a jocurilor a devenit mult mai costisitoare astfel
încât consolele de jocuri și jocurile au devenit mult mai scumpe și pentru o perioadă destul de
îndelungată jocurile de video au fost considerate echipamente de lux. Din aceasta cauză
tipurile de jocuri care au devenit populare înainte de generația a 7-a au început să intre în
declin și au început să crească în popularitate jocuri cu genuri care au fost populare în trecut.
A început de asemenea să crească popularitatea dezvoltatorilor de jocuri independente care au
creat jocuri mai personalizate și astfel noile categorii de jocuri au devenit unice.
Programarea jocurilor video face parte din ingineria programării, un joc video fiind
alcătuit din mai multe părți ce trebuie realizate pentru a avea un produs final complet, care
implică crearea modelelor folosite în joc sau a codului propriu pentru funcționarea corectă a
jocului. În ultimii ani jocurile video care au alocat un buget foarte mare și un timp de
dezvoltare mai îndelungat au fost dezvoltate utilizând limbajul de programare C sau limbajul
C++.
O explicație pentru această decizie o reprezintă faptul că pentru consolele de jocuri
care au de obicei hardware special creat, acesta este diferit fașă de cel al unui computer
desktop. Jocul trebuie programat ținând cont de faptul că memoria și ciclurile de CPU
trebuie utilizate astfel încât jocul să funcționeze folosind resursele în mod optim. O altă
explicație o reprezintă faptul că atât C cât și C++ sunt învățate în școli și universități, sunt
folosite pe piața de IT deci limbajele de programare sunt cunoscute pe scară largă și sunt
folosite și pentru creare/implementare de jocuri. Ultimele versiuni de jocuri utilizează
inclusiv tehnologia C#. [11]
3

Pentru crearea graficii jocurilor video de obicei sunt folosite motoare grafice
proprietare deci create special de fiecare dezvoltator de joc. Dezvoltatorii independenți de
obicei folosesc limbajele de programare care le sunt utile sau sunt disponibile. Pentru
implementarea motorului de joc de obicei se folosesc motoare care sunt disponibile
publicului contra cost sau gratis.
Deși limbajul de programare Java nu este un limbaj de programare foarte popular și
foarte mult folosit în domeniul creării jocurilor video totuși sunt exemple de astfel de jocuri
create, jocuri foarte populare și foarte reușite, cum ar fi: Minecraft, Runescape, Vampire: The
Masquerade – Redemption.
Limbajul de programare Java este un limbaj orientat pe obiecte, deci este capabil să
rezolve probleme similare cu alte limbaje de programare orientate pe obiecte cum ar fi C++
sau C# care sunt mult mai frecvent utilizate în domeniul jocurilor video, de aceea am ales să
implementez un joc în limbajul de programare Java.
Jocul implementat în cadrul proiectului de diplomă are ca tematică lupta dintre un
personaj principal (eroul principal) și un număr mare de adversari (personaje de tip zombi)
pe care trebuie sa îi învingă până la final. Personajele de tip zombi sunt în număr mai mare
decât personajul nostru deci personajul principal este în dezavantaj numeric. Ca să
supraviețuiască este ajutat de un număr de instrumente prezente în joc cu care personajul
principal poate să se apere. Dacă considerăm tematica jocului implementat acesta se
încadrează cu succes în tip ul top down shooter, joc care a fost popular în trecut și care
datorită dezvoltatorilor independenți începe să își regăsească audiența.

4

CAPITOLUL I. TEHNOLOGII UTILIZATE LA
IMPLEMENTAREA APLICA ȚIEI
I.1 JavaFX
JavaFX este un set de pachete grafice și media care permite dezvoltatorilor să
proiecteze, testeze, depaneze si să ruleze aplicații de tip client care pot să funcționeze pe
diferite platforme. Librăria JavaFX este scrisă ca un API (Advanced Programmimg Interface)
Java deci codurile aplicațiilor implementate în JavaF X pot să facă referire la celelalte API-uri
din alte librării Java. De exemplu aplicațiile JavaFX pot să folosească librării API pentru a
folosi capabilitățiile native al sistemului și de a conecta la o aplicație middleware de tip
server.
Apariția aplicației JavaFX poate să fie personalizată cu ajutorul lui Cascading Style
Sheets (CSS).[1]
Cascading Style Sheet (CSS) separă aspectul și stilul de implementare pentru ca
dezvoltatorii să poate concentra pe cod. Se poate folosi JavaFX Scene Builder dacă vrem să
facem designul interfeței și nu vrem să folosim cod. CSS în JavaFX este aplicat nodurilor din
JavaFX scene-graph în care stilurile sunt aplicate similar de la HTML DOM. Stilurile sunt
aplicate prima dată părintelui și apoi copiilor. Codul este scris în așa fel încât numai acele
părți din scene-graph sunt verificate din nou la care trebuie reaplicate stilurile CSS.[2]
JavaFX oferă o anumită flexibilitate pentru crearea Interfeței de utilizator partea pe
care este vâzut de utilizatori poate să fie creat în limbajul de scritping FXML iar partea
logică poate să fie codat în limbajul Java, dar dacă dorim să cream interfața fără codare atunci
putem folosi o funcție al lui JavaFX numit JavaFX SceneBuilder, cum creăm interfața de
utilizator SceneBuilder-ul crează o marcare FXML care poate să fie intergrat întrun
Integrated Development Environment (IDE).
JavaFX este disponibil ca și caracterisitcă integrată în Java SE Runtime Environment
(JRE) și Java Development Kit (JDK ). Pentru că JDK-ul este disponibil în toate platformele
majore de tip desktop aplicațiile JavaFx create în versiunile JDK 7 și versiunile mai noi pot să
ruleze pe toate platforme desktop majore.
Cele mai importante caracteristici al lui JavaFX sunt:
5

Java API este o librărie care este alcătuită din clase și interfețe scrise în limbajul
Java
WebView este o componentă care folosește tehnologia WebKitHTML care face
posibilă folosirea paginilor încuibate în JavaFX. A fost instalat ca suport adițional
pentru folosirea unor funcții HTML5- WebSocketuri și WebWorkers
Funcțiile Swing pot fi upgradate cu funcții JavaFX
Grafică 3D care implementează clase pentru crearea diferitelor forme 3D
Canvas API care permite desenarea în mod direct pe o scenă creată de JavaFX
API de printare care permite lucrul direct cu API-ul JavaFX Printing
Model de desfășurare de aplicații independente – pachete ale aplicațiilor
independente au toate resuresele aplicațiilor și o copie privată a runtime-urilor de
la Java și JavaFX, fiind distribuite ca pachete ce pot fi instalate.[1]
Clasa Application din JavaFX furnizează un framework pentru aplicațiile care o
folosesc. Runtime-ul JavaFX are un ciclu care se execută de fiecare dată când o aplicație
folosește clasa Application, din cauza asta nu este o practică bună de a nu folosi JavaFX
după ce toolkit-ul JavaFX a fost închis și a ajuns la finalul ciclului.
Când se crează o aplicație aceasta este creată întrun thread. În thread trebuie s ă fie
inițializate și obiectele JavaFX Scene și Stage. Excepții pot să apară când apar evenimentele,
când sunt executate animațiile sau în orice altă parte al codului, dacă se întâmpla așa ceva
atunci acesta este trimis la interfața numită manipulatorul de excepții.[3]
Clasa Scene este recipientul pentru tot conținutul aflat în scene graph care este o
arboră de structuri de date care are abilitatea de a ști la fiecare pas ce obiecte să fie afișate, ce
părți al ecraneului trebuie reparat și cum trebuie interpretat în cel mai eficient mod . Fundalul
este pus cu ajutorul proprietății fill. Mărimea scenei este inițializat de aplicație la construcție,
dacă nu sunt date mărimi inițiale atunci se vor crea cu mărimile implicite. Mărimile implicite
sunt calculate pe baza mărimilor preferate ale conținuturilor. Dacă numai o singură mărime
este dată atunci celelalte mărimi vor fi calculate pe baza primei mărimi. Aplicația trebuie să
specifice nodul rădăcină pentru grafica de scenă. Dacă se dorește să se creeze obiecte 3D
atunci trebuie utilizate buffere de adâncime și support pentru anti-aliasing.
Un buffer de adâncime este folosit pentru a interpreta pe bază de adâncime întrun mod
corect, pentru a evita lupta de adâncimi. Prin suport pentru anti-aliasing înțelegem acordul de
a permite aplicației de a folosi anti-aliasing care are rolul de a creșterea calității le grafici
acestuia [4].
6

Clasa Stage este nivelul cel mai superior când vorbim despre recepiente JavaFX.
Când vorbim despre recepiente JavaFX ne referim la acele clase cu care putem să modificăm
apariția ferestrei aplicației și a componentelor aflate în fereastră. Etapa primară este
construită de platformă, apoi putem să construim etape adiționale care sunt implementate de
aplicație. Fiecare obiect de tip e tapă trebuie să fie executată întrun thread. Etapa are mai
multe stiluri pe care putem să le aplicăm. O etapă poate să aibă o fereastră proprietar deci
spunem că acesta este părintele, dacă acesta este închis atunci toate descendentele lui vor fi
închise.[5]
I.2 Modelul model-view-controller(MVC)
Modelul MVC este un model arhitectural care este în mare parte utilizat pentru
crearea unor interfețe grafice pentru utilizatori. Premisa principală a modelului este bazată pe
modularitatea și abilitatea de a crea trei aspecte diferite ale interfeței grafice : data (model),
reprezentarea vizuală al datei (view), interfața dintre view și model (controller). Idea
principală este de a avea aceste trei c omponente separate una de cealaltă pentru a avea
independență, de aceea dacă se va face o modificare la una dintre aceste componente celălalte
nu vor fi afectate. Cel mai mare avantaj al acestei model îl reprezintă abilitatea de a reutiliza
logica aplicației când vrem să implementăm o altă aplicație.
În general modelul este implemetat prima dată. Acest model are două sarcini
importante, prima este salvarea stări lor și a doua sarcină este genstionarea abonaților prezente
în model. Starea nu trebuie să fie ceva foarte complex trebuie doar să decidem cum vrem să
depozităm detele. Proprietățile trebuie să fie asociate unor listeneri care sunt grupați întro
listă, proprietățile vor contacta această listă dacă se vor schimba . Codul poate să fie definit
într-o superclasă care apoi poate să fie moștenită de proprietățiile create, deci acesta trebuie
scrisă numai întrun singur loc. Un bun model MVC are grijă de superclasă și abonații
modelului astfel încât cel mai mult efort să fie pus pe codare.
Când modelul de date a fost finalizat de obicei este creat modelul view ca pas
următor. View-ul este componenta care este în direct conexiune cu un model. De obicei
acesta este afișat unor useri prin intermediul unei interfețe de user. Mai pot să facem modele
controller-view care nu ai nimic de a face cu interfețe de utilizatori. Când creăm un view
probleme la care trebuie să gândim este cum să reacționăm când apar schimbări la stări și
cum să afișăm informațiile utilizatorilor.
7

Cu cât mai complex sunt proprietățiile folosite cu atât mai complex editori și mai
complexe view-uri sunt necesare, dar frameworkul știe deja cum trebuie conectate aceste
componente la model și poate să autoconfigureze componenetele bazate pe prorietăți.
Pentru părțile care nu se schimbă când modelul se schimbă ține de responsabilitatea
controller-ului. Acesta trebuie să ajută la navigarea în view și știe cum să răspundă la
schimbările în view.
Viewul nu poate fi modificat și poate fi folosit numai în mod de citire, deci când
dorim/ trebuie să modificăm ceva în view atunci controler-ul răspunde eventul de editare, și
este cel care îl procesează și îl trimite modelului care va face modificările corespunzătoare ale
valorilor. Controler-ul poate fi implementat în diferite moduri, fie prin funcții de callback care
sunt asociate cu diferite editori care sunt utilizate când se schimbă valorile fie prin adăugarea
de ascultători în mod direct în component e care pot fi notificate când valorile se schimbă în
editoare.
Când este posibil cea mai bună metodă ce poate fi utilizată este cea care lasă modelul
să facă validările necesare asupra valorilor astfel încât toate schimbările valorilor sau
schimbări ale procesului de validare să fie făcute doar într-o singură locație. Dar se poate
întâmpla ca acestă metodă să nu poată fi utilizată, de exemplu se poate întâmpla ca o valoare
numerică să fie modificată și vream să o trimitem la controler dar acesta este transmisă printr-
o valoare text deci trebuie creată o altă metodă pentru transformarea valorilor.
În aplicația implementată conceptul MVC este implementat pentru că ajută la
implementarea logicii programului, și mai ajută la distribuirea sarcinilor programului. Ca și la
explicația generală a conceptului programul implementează cele trei aspecte ale acestuia:
modelul, controler-ul și view-ul.[6]
Pentru a implementa aceste aspecte în program au fost create trei pachete diferite care
sunt numite controller, model și view care conțin diferite clase, interfețe sau date de tip enum.
În pachetul controler există o singură clasă numită GameController.java care conține diferite
funcții care controlează evenimentele legate de apăsarea tastelor și cele legate de mouse.
Rolul cel mai important al controler-ului din program este de a face disponibile funcții
care pot fi folosite de diferite clase din model ce pot fi ulterior modificate sau suprascrise deci
clasa poate să decide cum să folosească aceste funcții.
Pachetul model are ca și conținut diferite clase care execută acțiuni diverse. Aceste
clase pot fi ca și clasa Player.java care are funcții care decid ce să se întâmple când se apasă o
tastă sau când mouse-ul este folosit respectiv ca și clasa GameSprite.java care conține funcții
8

care manipulează valori și variabile sau le returnează pentru a lucra cu imagini pe care vor fi
desenate. Cele mai multe clase sunt clase care lucrează cu obiecte.
În pachetul view există clasa GameWindow.java care are un rol important și anume de
a desena imaginile corespunzătoare obiectelor prezente în joc și de a crea și furniza toate
elementele necesare pentru a putea desena toate imaginile obiectelor.
I.3 Apache Maven
Apache Maven este un sistem de build, mangement de proiect are și un container
abstract pentru rularea task-urilor. Acest sistem cuprinde un model care conține un obiect de
tip proiect, un set de standarde, un ciclu de viață al proiectului, un sistem pentru
managementul dependențelor și o logică pentru executatea scopurilor plugin-urilor definite în
diferite puncte ale ciclului de viață al proiectului. Când folosim Maven descriem proiectul cu
un model de tip proiect după care putem aplica o logică transversală dintr-un set de plugin-
uri.
Înainte ca Maven s ă fie folosit într-o scară mai largă de multe ori fieacare proiect în
parte avea un sau mai multe persoane dedicate cu scopul de creare și de mentenanța unor
sisteme build personalizate.
Cu ajutorul lui Maven se pot crea interfețe comune pentru proiecte. Maven
implementeză conceptul de Convention Over Configuration care înseamnă că fără schimbări
în codul sursă, resursele, testele, au o locație predefinită iar proiectul produce un JAR
executabil, deci nu trebuie să predefinim localizarea acestora. Acesta este una dintre cele mai
folositoare caracteristici Maven și anume faptul că putem să folosim convențiile implicite dar
putem opta pentru personalizarea tuturor opțiunilor.
Dar funcția de Convention Over Configuration poate să fie folosit nu numai pentru
ușurarea pentru lucrul cu locațiile, de exemplu pluginurile oferă un set de convenții pentru
compilarea codurilor sursă. Convention Over Configuration are un ciclu de viață bine definit.
Instalarea programului Maven este o procedură relativ simplu. În sistemele de operare
Linux și MAC OSX trebuie descărcat versiunea binară de pe websiteul oficial și trebuie
instalat și ca un ultim pas trebuie pus directorul în calea de comandă.
Instalarea prgramului Maven pe sistemul de operare Windows este similar ca și
instalarea pe sistemele de operare Linux și MAC OSX cu diferența că calea implicit pentru
instalare va fi dat pe partițiunea de disk unde este instalat sistemul de operare iar apoi trebuie
configurat variabila de environment numit PATH.
9

În Maven proiectele, buildurile, dependențele sunt obiecte care trebuie modelate și
descrise. Aceste obiecte sunt descrise de un fișier tip XML numit Project Object Model. POM
spune Mavenului ce fel de project este și cum trebuie să se facă schimbări la setările implicite
încăt să se producă rezultatele dorite. [7]
I.4 MySQL
MySQL este un sistem de manegment al bazelor de date folosind SQL.
SQL(Strucured Query Language) este cel mai folosit și standardizat folosit la accesarea
bazelor de date. Depinzând de mediul în care lucrăm putem să lucrăm cu SQL direct sau
putem să scriem SQL împreună cu un limbaj de programare.
Bazele de date relaționale din MySQL sunt depozitate în tabele separate mai degrabă
într-o singură locație. Modelele logice ca și bazele de date, tabelele oferă o flexibiliatate la
mediul de programamre aleasă. Putem să creăm regurile de relații între tabelel create de
exemplu relația de unu-la-unu.
MySQL Database Software este un sistem de client/server care este alcătuit dintr-un
SQL Server de multi-threading care suportă diferite backend-uri, diferite programe de client
și librării.[8]
MySQL Workbench este un instrument grafic pentru lucrul cu serverele și bazele de
date MySQL. MySQL Workbench permite crearea conexiunilor la baza de date, administrarea
bazelor de date și migrarea datelor din baza de date.[9]
În cadrul aplicației implementate am utilizat instrumentul grafic MySQL Workbench
pentru că are o interfață de utiliztor ușor de folosit și ușor de înțeles.Prin folosirea MySQL
Workbench putem să creăm conexiuni foarte ușor și este foarte ușor de a o folosi cu alte
programe MySQL, în aplicație împreună cu MySQL Workbench folosim o altă aplicație
numită MySQL Server cu care putem crea serverul nostru și să-l configurăm, și cu ajutorul
aplicației MySQL Workbench putem să lucrăm cu baza de date creat întrun interfață grafică.
10

CAPITOLUL II. ANALIZA ȘI DESCRIEREA CONTEXTULUI
II.1 Analiza jocului video
Pentru a începe proiectarea și implementarea jocului video primul lucru care trebuie
făcut este de a analiza conceptul jocului video și de a stabilit în ce tip de joc se încadrează
acesta.
Conceptul jocului video îl reprezintă faptul că exită un personaj principal în joc și mai
mulți inamici numiți zombi, iar personajul principal trebuie să aibă abilitatea de a omorî
inamicii din joc. După stabilirea acestui concept principal după care trebuie creat jocul,
trebuie decis cum poate jucătorul/ personalul principal să omoare inamicii din joc. Astfel am
decis ca jucătorul/personajul principal să omoare inamicii cu arme de diverse categorii care
trag gloanțe dar am introdus și o armă care nu trage gloanțe.
Pentru că am decis ca inamicii să fie prezenți întrun număr mult mai mare decât
personajul principal din joc pentru ca jocul să nu devină prea greoi au fost introduse și
articole de prim ajutor care să-l ajute pe personajul principal. Luând aceste concepte în
considerare trebuia ales în ce mod să fie realizat/implementat jocul ținând cont și faptul că
jocul final trebuie să aibă un design relativ simplu și am ales ca modalitate de implementare
genul Shoot`em Up.
Genul Shoot`em Up face parte din genul de jocuri de shoot-eri și sunt jocuri de
acțiune. Aceste jocuri sunt de obicei văzute din perspectiva de sus în jos sau din perspectivă
laterală, iar jucătorii trebuie să utilizeze arme de foc pentru a acționa de la distanță.
Scopul jucătorului /personajului principal este de a utiliza arme de foc de la distanță
cât mai rapid posibil astfel încât toți inamicii care îl pun pe jucător în pericol să fie anihilați.
În anumite jocuri personajul principal poate să aibă o bară de viață pentru a putea contracara
mai multe lovituri de la inamic sau această opțiune poate să lipsească caz în care o singură
lovitură este suficientă pentru ca jucătorul/personajul principal să piardă jocul.
De obicei inamicii din joc sunt prezenți într-un număr mare și pot să se comporte în
diferite moduri care depind de tipul de inamic. Aceste Shoot`em Up-uri mai pot fi
caracterizate prin diverse modalități în care se pot mișca jucătorii în cadrul jocului. Un fixed
shooter este caracterizat prin faptul că jucătorul poate să se miște pe o singură axă
direcțională iar inamici se pot mișca doar într-o singură direcție iar nivelele sunt alcătuite
numai dintrun singur ecran.
11

Un rail shooter este caracterizat prin faptul că jucătorul poate să miște pe mai multe
direcții dar este limitat pentru că jucătorul trebuie să respecte o rută predefinită. Mai există și
scrolling shooter care pot fi de tip vertical sau horizontal shooteri , categorisiți în funcție de
direcția pe care poate să meargă jucătorul și anume de jos în sus sau de la stânga la dreapta.
Ultima categorie de shooter este mutidirectional shooter care este caracterizat prin
mișcarea de 360 de grade adică jucătorul are abilitatea de a se mișca unde dorește și abilitatea
de rotire în fiecare direcție. Jocul creat/implementat în cadrul proiectului de diplomă face
parte în această categorie de jocuri. [10]
După deciderea genului din care jocul care va fi implementat face parte, am
considerat că este necesar să fie implementat și un sistem de ceas care arată cât timp a trecut
de la începerea unui nou joc precum și un sistem de numărare a inanimcilor uciși. Aceste
sisteme au fost implementate pentru a arăta jucătorului că a fost făcut progres în joc.
Ultimul pas a fost reprezentat de decizia de a implementa un sistem de highscore care
să memoreze scorul jucătorului aceste informații fiind cât timp a trect și numărul de inamici
uciși, pentru a arăta care sunt cei mai buni jucători care au jucat acest joc. Pentru a
implementa această funcție am decis că trebuie folosită o bază de date pentru că aceste date
trebuie păstrate și atunci când jocul nu este în rulare.
II.2 Pornirea unui nou joc
Când pornim jocul apare ecranul jocului cu o fereastră în interiorul căreia o să fie
meniul principal al jocului, în acestă fereastră apare numele jocului care este ‘ Zombie
Hunter’ și un buton verde în care scrie START GAME, fereastra fiind meniul principal al
jocului.
Pentru a începe un joc nou trebuie dat click dreapta în interiorul butonului START
GAME și se va începe un joc nou. Meniul principal a fost creat într-o manieră stilistică
minimalistă pentru ca jucătorii să poată să înțeleagă clar cum se inițializează un joc nou.
12

Fig. II.1. Meniul principal
II.3 Jocul principal
Principala țintă a jocului este de a supraviețui cât mai mult și de a omorî cât mai mulți
inamici din joc, inamici care sunt numiți zombi. Pentru că aceste două lucruri sunt importante
pentru joc ele sunt afișate în mod constant în joc.
Timpul supraviețiut este reprezentat printr-un ceas afișat în colțul stâng sus, iar
numărul de zombi omorâți este reprezentat prin afișarea textului ‘ Zombies killed:’ urmat de
numărul de zombi omorâți și este afișat tot în colțul stâng lângă ceas.
Fig. II.2. Ceasul și numărul de personaje zombi omorâți
Jucătorul este reprezentat în joc prin personajul principal pe care îl controlează. Acest
personaj este reprezentat în joc printr-un militar.
Personajul poate să fie controlat prin tastatură cu tastele W, A, S, D, apăsând aceste
taste personajul va începe să miște se miște în direcția tastei apăsate – adică sus, jos, stânga
sau dreapta. Personajul mai poate fi controlat prin mișcarea și apăsarea butonului stâng al
mouse-ului. Prin mișcarea mouseului personajul va mișca spre direcția cursorului mouseului
și dacă apăsăm butonul stâng al mouseului atunci personajul va ataca.
13

Fig. II.3. Personajul principal din joc
Personajul din joc are atașată o bară de viață care reprezintă câte atacuri poate
personajul să susțină. Aceasta este reprezentată printr-un dreptunghi de culoare verde
poziționat în colțul dreapta sus al ecranului. Dacă personajul a fost atacat cu succes de zombi
atunci va pierde din viața lui totală. Dacă viața personjului principal ajunge la zero atunci
jocul a luat sfârșit.
Fig. II.4. Bara de viață a personajului
Inamicul din joc este reprezentat prin zombi. Personajele zombi din joc au un scop
numai în cadrul jocului, și scopul acestora este de a ataca personajul principal.
Când personajele zombi apar în joc, vor începe să fugă spre personajul principal și
când sunt în aproprierea personajului atunci vor începe să-l atace. Zombi nu vor înceta să-l
urmărească pe personajul principal și să-l atace decât în momentul în care au fost omorâți.
Fig. II.5. Zombi din joc
14

Pentru ca personajul principal să se poată apăra în momentul în care este atacat, pe jos
sunt plasate diferite arme cu care personajul poate să atace. Pentru a ridica aceste arme
trebuie numai să facem o coliziune cu acestea. Armele sunt reprezentate pe margine printr-o
strălucire de culoarea albastră pentru a putea fi identificate mai ușor. Pentru a ataca cu o armă
jucătorul/personajul principal trebuie să apese butonul stâng al mouse-ului. Sunt patru tipuri
de arme în joc și fiecare este un pic diferită față de alta.
Fig.II.6. Armă prezentă în joc
În joc există sistemul recuperare a vieții personajului principal. Aceasta poate să fie
realizată prin folosirea unor articole de prim ajutor. Ca și armele utilizate în joca, articole de
prim ajutor sunt pe jos și pot fi ridicate ca și armele. Există patru tipuri de articole de prim
ajutor ce pot fi utilizate fiecare recuperând un procent diferit din viață.
Articolele de primul ajutor sunt reprezentate în joc având pe margine o strălucire de
culoarea verde pentru a putea fi diferențiate de alte elemente din joc.
Dacă vream să folosim un articol de prim ajutor atunci trebuie să apasăm butonul
stâng al mouse-ului și atunci viața fi recuperată.
Fig.II.7. Articol de prim ajutor din joc
Când facem coliziune cu armele sau articolele de prim ajutor pentru a le ridica atunci
aceste vor fi puse într-un inventar care este reprezentat prin dreptunghiuri albe implementate
partea de jos a colțului stâng, în acest inventar pot să fie prezente numai patru arme sau
articole de prim ajutor în același timp.
15

Prin intermediul inventarului putem să schimbăm tipul de armă sau articol de prim
ajutor pe care dorim să îl folosim. Pentru schimbare trebuie apăsate tastele 1, 2, 3, 4 pe
tastatură, fiecare tastă reprezentând o poziție din inventar.
Fig.II.8. Inventarul din joc
II.4 Meniul Game Over
Când viața personajului va fi redusă la zero atunci jocul a luat sfârșit, caz în care pe
ecran apare meniul de game over, implementat într-un dreptungi alb care conține titlul Game
Over. În acest meniu vor fi afișate primii 20 de jucători cu numele lor, cât timp au
supraviețuit și câși zombi au omorât.
Dacă timpul supraviețuit sau numărul de zombi se situează undeva în topul celor 20
de jucători afișați atunci jocul va cere jucătorului curent să introducă numele. Trebuie
introdus numele la poziția unde a ajuns jucătorul pe tabelă și când apăsam tasta enter atunci
datele vor fi memorate în tabel și se va începe un joc nou.
Dacă s-a ajuns la ecranul de game over dar rezultatele nu sunt suficiente pentru a face
parte din top 20 și nu este necesară introducerea de date în tabelă, putem să începem un nou
joc prin apăsarea butonului de Play Again.
16

Fig.II.9. Meniul de Game Over
17

CAPITOLUL III. IMPLEMENTAREA APLICAȚIEI
III.1 Controlarea personajului din joc
Mișcarea personajului principal din joc este făcută de jucătorul care utilizează
aplicația. Utilizatorul poate interacționa în cadrul jocului prin intermediul tastaturii sau al
mouse-ului. Pentru mișcarea personajului principal pe nivel persoana care jocă jocul
(jucătorul) trebuie să utilizeze tastele W, A, S, D care îi permit mișcarea personajul pe
direcțiile sus, jos, stânga sau dreapta poziționarea tastelor fiind dependentă de tipul tastaturii.
Dacă personajul nostru are arme la dispoziția atunci poate să atace zombi pe nivelul
pe care este. Personajul va ataca cu arma care este selectată, iar pentru a realiza această
acțiune trebuie să apese butonul stâng al mouse-ului.
Când apăsăm una dintre tastele W,A,S,D sau butonul stâng al mouse-ului pot fi
parcurse succesiuni diferite de evenimente. Am creat o interfață numită
GameEventHandler.java în care sunt declarate metodele corespunzătoare pentru apăsarea
tastelor de la tastatură și pentru apăsarea butoanelor de mouse. Interfața recunoaște
evenimentele ce apar și le transmite clasei care va implementa interfața. Această interfață
implementată utilizează clasa GameController.java care detectează tastele apăsate al tastaturii
și butoanele apăsate al mouse-ului, date ce sunt stocate și trimise mai departe printr-o metodă
care va fi aplicată în fiecare ciclu.
Metoda către care sunt transferate informațiile este GameRoom.java și are rolul de a
transfera informațiile primite de la GameController.java tuturor obiectelor prezente în joc în
momentul aplicării metodei, metodă care se va aplica la fiecare ciclu.
După ce fiecare obiect din joc primește informațiile referitoarela tastele și butoanele
apăsate, fiecare obiect în parte decide ce acțiune trebuie să realizeze în funcție de
informațiile primite. În cazul aplicației implementate numai personajul principal din joc va
acționa în funcție de tastele apăsate și își poate modifica poziția proprie pe baza tastei
apăsate. La apăsarea butonului stâng al mouse-ului și în funcție de arma curent selectată
personajul principal poate ataca inamicii/zombi.
III.2 Armele din joc
Pentru a înfrânge inamicii/zombi personajul principal are nevoie de arme. Aceste
arme sunt dispersate în diferite locații pe nivel, iar pentru a putea fi folosite trebuie să fie
18

strânse și selectate de personajul principal. Pentru implementarea acestor arme a fost creat un
package separat în care sunt puse toate clasele necesare pentru a lucra cu obiectele
implementate ca arme în joc. În cadrul jocului există implementate patru tipuri de arme care
sunt: PISTOL, HANDGUN, SHOTGUN, KNIFE.
Fig. III.1. Cele patru tipuri de arme din joc
Pentru implementarea acestor categorii de arme am creat în package un enum numit
WeaponType.java în care se enumerează aceste categorii. Fiecare armă din joc are un număr
de proprietăți generale prin care se diferențiază față de celelalte și anume: name, damage,
durability și attackDelay.
Name descrie numele armei care va fi utilizată/afișată în joc, damage descrie cât de
mult este afectată viața unui zombi când este atacat de armă, durability descrie cât de durabilă
este arma, dacă valoarea acestui parametru scade până la valoarea zero atunci arma va fi
distrusă și nu mai poate să fie folosită. AttackDelay este proprietatea care descrie cât de des
poate fi utilizată/se poate ataca cu arma selectată în momentul atacului.
Pentru a implementa aceste proprietăți am creat o clasă nouă numită
WeaponProprierties.java, în cadrul căreia se vor seta proprietățile conform tipurilor de arme
menționate anterior.
Secvența de mai jos reprezintă descrierea unui arme din joc în cazul nostru handgun-
ul:
public class WeaponProperties {
private String name;
private int damage;
private int durability;
private int attackDelay;
private WeaponType weaponType;
public WeaponProperties(WeaponType weaponType) {
switch (weaponType) {
case HANDGUN:
damage = 1;
durability = 15;
name = "Handgun";
attackDelay = 40;
this.weaponType = weaponType;
19

break;
Analizând tipurile de arme inserate putem să observăm faptul că trei din cele patru
arme sunt arme care trag gloanțe iar unul nu, aceasta fiind o distincție importantă din punct
de vedere al mecanismelor jocului, pentru că un cuțit nu poate să tragă gloanțe. Din acest
motiv am creat trei clase diferite pentru a lucra cu armele: WeaponItem.java,
BallisticWeaponItem.java, MeleeWeaponItem.java.
BallisticWeaponItem.java a fost creată pentru a gestiona armele care trag gloanțe. În
această clasă armelor care trag gloanțe le sunt asociate proprietățile generale ale armele dar
există și o metodă unică care permite crearea unui glonț când se atacă cu arma. Glonțul este
creat în fața personajului și va începe să se miște în acea direcție.
Glonțul este reprezentat ca un obiect în joc de clasa Bullet.java , în cadrul clasei
existând două metode importante: un eveniment de coliziune în care se verifică coliziuna cu
un alt obiect caz în care zombi va fi lovit și va pierde din viața totală o valoare egală cu cea
conținută în proprietatea damage și un eveniment eveniment care va fi aplicat la fiecare ciclu
și care va determina mișcarea glonțului în direcția corectă.
Secvența de mai jos prezintă modalitatea de implementare a glonțului din joc:
public Bullet(double x, double y, GameSprite sprite, double
damage) {
super(x, y, sprite);
this.damage = damage;
this.setSpeed(50);
getSprite().setAnimationSpeed(2);
}
@Override
public void stepEvent() {
super.stepEvent();
move();
}
@Override
public void collisionEvent(GameObject other) {
if (other instanceof Damagable && other.isSolid()) {
((Damagable) other).damage(damage);
destroy();
}
}
@Override
public void drawEvent() {
}
20

MelleWeaponItem.java a fost creată pentru a gestiona arma care nu trage gloanțe. Ca
și în cazul clasei BalisticWeaponItem.java și clasa MeleeWeaponItem.java are toate
proprietățiile generale ale armelor dar și câteva metode specifice importante. O metodă
importantă este un eveniment care va fi apelat la fiecare ciclu și va decide dacă personajul
care atacă este la o distanță acceptabilă de zombi. Distanța este calculată pe baza imaginilor
obiectelor prezente în joc. O altă metodă importantă este metoda care se va aplica în
momentul care zombi a fost lovit. Metoda resetează toate variabilele asociate cu arma curentă
cum ar fi resetarea proprietății attackDelay.
O altă metodă importantă care va fi aplicată atunci când se va face coliziunea cu un
zombi zombi determină scaderea proprietății de durabilitate/durability adică se va scădea din
durabilitatea totală a armei la fiecare coliziune cu zombi valoarea conținută în proprietatea
damage.
Secvența de cod de mai jos arată calcularea distanței:
@Override
public double getAttackRange() {
if (inventory.getCurrentItem() instanceof
MeleeWeaponItem) {
return ((MeleeWeaponItem) inventory.getCur
rentItem()).getAttackRange();
} else {
return -1;
}
}
Iar secvența de mai jos arată modalitatea de obținere a distanței :
public MeleeWeaponItem(WeaponProperties properties) {
super(properties);
switch (getProperties().getWeaponType()) {
case KNIFE:
attackRange = GameSpriteFactory. PLAYER_RADIUS;
break;
case FLASHLIGHT:
attackRange = GameSpriteFactory. PLAYER_RADIUS;
default:
break;
}
}
21

WeaponItem.java este o clasă pe care clasele MeleeWeaponItem.java și
BallisticWeaponItem.java o extind. Acestă clasă are rolul de a asocia armele din joc cu
proprietățiile corespunzătoare pe baza tipului de armă MeleeWeaponItem sau
BallisiticWeaponItem . Alte roluri importante ale clasei sunt lucrul cu proprietatea durability
adică de reducere a valorii acestuia dacă a fost făcut un atac cu o armă și celălalt rol
important este lucrul cu proprietatea attackDelay, acesta va inițializa o valoare care va fi
incrementată și verificată la fiecare ciclu. Dacă se atinge valoarea curespunzătoarea armei
atunci se poate ataca cu arma curentă și dacă se atacă din nou clasa va reseta această valoare
și ciclul poate reîncepe.
Pentru a reprezenta armele când sunt pe nivel pentru a putea fi ridicate și utilizate de
personajul principal din joc este creată o clasă numită WeaponObject.java care realizează
inițializarea obiectelor cu proprietățiile generale ale armelor și setează imaginea
corespunzătoare armei.
III.3 Articolele de prim ajutor din joc
În joc pentru că inamicul este prezent întrun număr mai mare decăt personajul și de
aceia este prea ușor de a pierde în joc. Considerând acest fapt trebuie introdus o mecanică de
joc prin care personajul principal din joc să își poată recăpăta o parte din viața pierdută.
Implementarea acestora a fost realizată prin crearea unui enum numit HealthType.java în care
am implementat patru tipuri de articole: SURVIVALBAR, HOTDOG, MEAT și RATIONS, și
sunt folosite de celelalte clase pentru a crea aceste articole diferite. Articolele sunt plasate pe
nivel ca și armele și trebuie ridicate/selectate în mod identic cu armele.
Fig.III.2. Cele patru articole de prim ajutor din joc
Ca și armele și aceste articole de prim ajutor au proprietăți ca tipurile să fie unice,
astfel ele sunt caracterizate de următoarele proprietăți: name și heathRegained. Proprietatea
name descrie numele care va fi arătat în joc, iar healthRegained arată nivelul/cantitatea care
va fi adaugată la viața curentă a personajului.
22

Aceste proprietăți sunt folosite de două clase diferite HealthObject.java și
HealthItem.java, fiecare dintre aceste clase folosesc aceste proprietăți pentru a inițializa
articolele. Clasa HeatlhObject.java extinde clasa GameObject.java deci această clasă este
folosită pentru a plasa articole pe nivel, iar HealthItem.java va fi folosită când acestea sunt
folosite de personaj fiind vorba de armele curente.
III.4 Sistemul de desenare din joc
Într-un joc o parte importantă care este întotdeaunea judecată este estetica lui. De
aceea dacă un joc este din punct de vedere al esteticii minimalist, dezvoltatorii încearcă să
pună efort în partea de estetică. Proiectul se bazează pe modelul model-view-controller, deci
desenarea se va face în view, de accea am creat un pachet numit view în care sunt două clase.
Am implementat o interfață numit GameView.java în care au fost declarate metode care vor
desena diferite părți din joc.
Clasa în care se vor implementa aceste metode este GameWindow.java pentru că
această clasă implementează GameView.java. La baza implementării claselor a stat faptul că
trebuie desenate mai multe tipuri de elemente în joc, astfel în clasa GameWindow.java au fost
create clase private care sunt derivate dintr-o clasă abstractă Drawable care descrie unde va fi
desenat. Toate celelalte clase vor extinde această clasă abstractă, astfel clasa SpriteToDraw
care are rolul de a desena imaginile corespunzătoare obiectelor la locațiile corespunzătoare
iar clasa TextToDraw are rolul de a afișa textele necesare la locul corespunzător cu un font
specific ales. Clasa RectangleToDraw are rolul de a desena dreptunghiuri la locurile
specificate cu o lățime și lungime determinate, cu o culoare din cele 3 posibil: roșu, verde,
albastru fiecare dintre aceste culori fiind reprezentate în clasă.
Sistemul de desenare este creată în așa fel încât va desena fiecare element diferit în
diverse faze ale execuției, în acest fel putând controla mai bine când și cum vor fi desenate
elementele. Pentru acest lucru au fost create metode diferite în GameView.java care vor fi
implementate în GameWindow.java și două clase distincte: PreDrawEvent și PostDrawEvent.
Metoda PreDrawEvent are rolul de a desena fundalul în cadrul jocului și va inițializa
imaginea aleasă a fundalului, aceste imagini vor fi plasate pe toate cele patru colțuri ale
ecranului iar apoi va fi plasat pe toată supratața ecranului prin plasarea în mod treptat pe
părțiile de sus, jos, stânga și dreapta a fiecărui nivel.
Metoda PostDrawEvent este metoda care se va aplica după metoda PreDrawEvent,
rolul acestei metode fiind de a prelua toate obiectele care trebuie desenate și de a selecta un
23

element de desen pe baza dacă trebuie implementată imaginea obiectelor din joc. Dacă
trebuie inserat numai text sau trebuie desenate dreptunghiuri metoda le va desena cu
proprietățiile adecvate. Pe lângă aceste roluri metoda mai are două metode mai importante
una de a desena inventarul personajului și de cel de-al doilea de a desena bara de viață a
personajului.
Inventarul personajului este un mecanism de joc foarte important pentru că în acest
inventar se vor memora armele sau articolele de prim ajutor pe care personajul din joc le-a
selectat/ridicat de pe nivel. Când personajul selectează/ridică un obiect atunci în clasa
personajului din joc Player.java se vor face verificări dacă obiectul ridicat/selectat este de tip
armă sau articol de prim ajutor și va fi creat un nou obiect de acel tip. Clasa Player.java
conține și metode care lucrează cu inventarul: addItem care adaugă obiectul în inventar sau
metoda switchToItem care în momentul în care personajul schimba arma sau articolul de prim
ajutor în inventar care indică ce imagini trebuie schimbate și modifică indexul care indică ce
elemente sunt selectate în momentul curent.
Fig. III.3. Inventarul din joc
Pentru a lucra cu inventarul a fost creată o clasă abstractă numită InventoryItem.java
care a fost extinsă de clasele WeaponItem.java și de HealthItem.java.
Personajul are patru locuri în inventar, pentru a schimba între arme sau articole de
prim ajutor trebuie apăsate tastele 1, 2, 3 sau 4 pe tastatură. Dacă una dintre aceste taste este
apăsată atunci se va aplica metoda switchToItem și indexul curent va fi schimbat în funcție de
codul tastatei apăsate.
Secvența de cod de mai jos reprezintă implementarea invetarului:
private String name;
private GameSprite sprite;
public InventoryItem(String name, GameSprite sprite) {
24

this.name = name;
this.sprite = sprite;
sprite.setDepth(-100); // the inventory item sprite is always
on top
}
public String getName() {
return name;
}
public GameSprite getSprite() {
return sprite;
}
public abstract void stepEvent();
Pentru desenarea inventarului cu ajutorul metodei RectangleToDraw se vor
implementate patru dreptungiuri de culoare albă cu o opacitate predefinită. Dacă o armă sau
un articol de prim ajutor este selectat pe poziția inventarului atunci pe dreptunghiul ales
opacitatea va fi schimbată pentru a indica că acea poziție este selectată în momentul curent.
Când se selectează/ridică o armă sau articole de prim ajutor și este inserată în inventar
se va desena în dreptunghi cu ajutorul metodei SpriteToDraw o imagine care va reprezenta
obiectul selectat/ridicat în funcție de tip element inserat – armă sau un articol de prim ajutor.
Cu ajutorul metodei TextToDraw vor fi desenate proprietățiile armei sau articolului de prim
care pot fi: numele armei/articolului de prim ajutor, durabilitatea în cazul armelor sau durata
de timp care va fi adaugată la viața curentă a personajului în cazul articolelor de prim ajutor.
Bara de viață este desenată utilizând o metodă numită drawHealth. Această metodă
desenează bara de viață prin metoda RectangleToDraw prin care sunt implementate două
dreptunghiuri, unul care va avea o opacitate mare și altul care va fi desenat peste primul
dreptungi, culoarea acestuia din urmă fiind verde când viața personajului este la valoarea
maximă deci 100 iar când personajul pierde din viață atunci mărimea dreptungiului scade și
culoarea se transformă din verde spre roșu cu cât scade viața curentă a personajului. Cu
ajutorul lui TextToDraw va fi afișată valoare curentă a vieții curente a personajului.
Fig.III.4. Bara de viață din joc
25

Clasa GameWindows.java este utilizată doar pentru a desena componentele
programului iar metodele PreDrawEvent și PostDrawEvent vor fi suprascrise în clasa
GameRoom.java. ca se poată fi specifica unde și când să deseneze în funcție de faza în care
este jocul: faza Game, faza Main_Menu sau faza Game_over.
Dacă jocul este în faza Game atunci clasa va aplica metoda DrawEvent pe care fiecare
obiect din joc o are și pentru fiecare obiect din joc va aplica o metodă care are rolul de a
semnala că trebuie desenate imaginiile corespunzătoare obiectului, se mai inserează numărul
de personaje zombi care au fost învinse și cât timp a trecut de la începerea jocului.
Dacă jocul este în faza Main_menu atunci se va desena fundalul și se va aplica
metoda DrawMainMenu care va desena meniul principal prin implementarea a două
dreptunghiuri prin metoda RectangleToDraw și desenarea unui buton cu titlul de Start Game
prin metoda DrawButtons.
Un buton este creat prin clasa abstractă GameButton care are rolul de a iniția o altă
fază a jocului dacă se va da un click în interiorul lui. Dacă este faza Main_menu atunci
trebuie inițializată faza de Game, iar dacă viața jucătorului este redusă la 0 atunci se va
inițializa faza Game_over iar dacă se va da click pe butonul Play Again și trebuie
reinițializată faza Game.
Secvența de cod de mai jos reprezină implementarea butonului din joc:
private boolean mouseOnButton = false;
private String text;
private double x;
private double y;
private double width;
private double height;
public GameButton(String text, double x, double y, double
width, double height) {
this.text = text;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void mouseInside() {
if (!mouseOnButton) {
mouseOnButton = true;
}
}
public void mouseOutside() {
if (mouseOnButton) {
mouseOnButton = false;
26

}
}
abstract public void mousePressed();
public boolean isMouseOnButton() {
return mouseOnButton;
}
public String getText() {
return text;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y; }
Metoda DrawButtons este similară ca mod de funcționare cu DrawMainMenu unde
prin intermediul metodei RectangleToDraw va fi desenat un dreptunghi și cu ajutorul metodei
TextToDraw va fi afișat în buton textul Star Game sau Play Again, în funcție de faza în care
se află jocul în acel moment.
III.5 Sistemul de importare a imaginilor
Fiecare obiect din joc are o imagine care trebuie desenată, iar fiecare dintre aceste
imagini trebuie importată. Lucrurile care trebuie luat în considerare: trebuie memorată calea
fiecărui folder sau imagine în parte și trebuie luat în considerare faptul că este o șansă ca
anumite animații să fie prezente în joc. Aceste imagini au fost deja create și pot fi folosite de
oricine. Astfel de imagini au fost folosite pentru reprezentarea personajului principal [12],
inamicilor din joc[13], armelor din joc[14], articolelor de prim ajutor[15] și al glonțului[16].
27

Pentru acest lucru am creat clasa GameSpriteFactory.java iar ideea pe care se bazează
metodele de implementare a imaginilor este metoda factory pattern.
Metoda factory pattern consideră că se va utiliza un obiect pentru crearea altor
obiecte fără a se preciza cu exactitate din ce clasă va fi creat obiectul, realizat prin creare de
metode factory care sunt interfețe implementate de clasele derivate sau metode create în clasa
de bază și suprascrise opțional în clasa derivată. Deși clasa GameSpriteFactory.java nu
funcționează cu exactitate ca și un factory sunt preluate idei din aceasta.
În clasă au fost create PlayerMotion și ZombieMotion, 2 enum-uri care sunt folosite la
căutarea fișierelor țintă a imaginilor. Deoarece personajul din joc are cele mai multe imagini
ce trebuie găsite și afișate care se bazează pe armele din joc folosite și mișcările posibile ale
personajul din joc, am creat o clasă separată cu o metodă pentru a căuta imaginile în fișierele
corespunzătoare.
Această metodă verifică obiectul deținut de personajul din joc și ce tip de mișcare
utilizează în acel moment, respectiv tipul de armă folosit de personaj. Pentru a găsi calea
corectă a imaginilor a fost creat o formă generală a căii în care mișcarea, tipul armei și
numărul imaginii au fost înlocuite cu variabilele &mtn, &wpn, și &num. În metodă sunt
verificate mișcarea și tipul de armă și dacă acestea sunt prezente atunci se va afișa imaginea
care va fi de tip clasă GameSprite.java.
Dacă nu există această imagine atunci se va înlocui &wpn cu numele al armei și
&mtn cu mișcarea și se va înlocui &num cu un număr crescător pâna la momentul în care nu
mai sunt imagini de importat în fișier. Aceste imagini vor fi inserate într-o listă numită
imageURL și pe baza căilor create cu ajutorul metodei se vor desena imaginiile.
Pentru importarea și desenarea imaginilor asociate personajelor zombi se folosește o
metodă asemănătoare celei folosite pentru personajul principal cu diferența că înlocuirea se
va face pe baza enum-ului ZombieMotion, se va înlocui variabila chosenMotion cu numele
mișcării personajului zombi și ca și la personajul principal se va plasa calea creată într-o listă
numită iamgeURL și se va afișa toate imaginile care au călile puse în imageURL.
Pentru imaginile armelor/articolelor de prim ajutor, respectiv a celor care vor fi afișate
în inventar, imaginea glonțului și imaginile ce sunt incluse în fundal sunt folosite același
metode dar pentru că sunt mai puține imagini putem să dăm calea imaginilor pentru fiecare
armă sau articol de prim ajutor în parte depinzând de tipurile acestora sau putem da glonțului
și imaginilor din fundal doar calea necesară pentru a găsi imaginea dorită.
Secvența de cod de mai jos arată importarea imaginiilor personajului principal din joc:
28

public static GameSprite getPlayerSprite(PlayerMotion motion,
WeaponType weapon) {
PlayerSpriteSearchKey key = new PlayerSpriteSearchKey(motion,
weapon);
if (playerSprites.containsKey(key)) {
GameSprite sprite = playerSprites.get(key);
if (motion == PlayerMotion. ATTACK) {
sprite.restartAnimation();
}
return sprite;
} else {
int i = 0;
String playerSpritePath =
PLAYER_SPRITE_PATH .replace("&wpn",
weapon.name().toLowerCase()).replace("&mtn",
motion.name().toLowerCase());
URL imageUrl = GameSpriteFactory. class.getResource(play
erSpritePath.replace("&num", String. valueOf(i)));
System.out.println(imageUrl.toString());
List<String> imageUrls = new ArrayList<>();
while (imageUrl != null) {
imageUrls.add(imageUrl.toString());
imageUrl =
GameSpriteFactory. class.getResource(play
erSpritePath.replace("&num", String. valueOf(++i)));
}
GameSprite sprite = new GameSprite(imageUrls,
PLAYER_RADIUS);
playerSprites.put(key, sprite);
allSprites.add(sprite);
sprite.setScale(0.3);
if (motion == PlayerMotion. ATTACK) {
sprite.setRepeatable( false);
}
return sprite;
}
}
Clasa conține trei variabile importante: ZOMBIE_RADIUS, PLAYER_RADIUS și
BULLET_RADIUS care sunt importante la verificarea coliziunii dintre obiectele din joc,
aceste valori sunt calculate pe baza dimensiunii imaginilor, variabile fiind folosite pentru o
verificarea mai exactă a distanței de atac.
29

Toate metodele din clasă crează imagini de tip GameSprite care sunt din clasa
GameSprite.java, clasă responsabilă pentru setarea proprietățiilor imaginilor și a mai multor
roluri.
Un rol foarte important al clasei este de a calcula viteza la care animațiile trebuie să
fie executate, astfel la fiecare ciclu al procesorului trebuie calculat pe baza vitezei implicite și
a mărimii imagini trebuie decis dacă imaginile sunt de genul celor care trebuie repetate caz în
care trebuie redesenate animațiile.
Secvența de cod de mai jos arată executarea animațiilor:
public void stepEvent() {
if (step == animationSpeed && (repeatable ||
currentImage != images.size() – 1)) {
currentImage = (currentImage + 1) %
(images.size());
}
step = (step + 1) % (animationSpeed + 1);
}
Un alt rol important este de a calcula dimensiunea boundingCircleRadius .
BoundingCircleRadius este un cerc invisibil care acoperă imaginea și este calcualată de clasă
pe baza dimensiunii imaginii. BoundingCircleRadius este folosit pentru a detecta dacă două
obiecte din joc sunt în coliziune. Două obiecte din joc sunt în coliziune dacă cercurile
obiectelor se acoperă una peste cealaltă. Dacă folosim aceste cercuri atunci putem să facem o
verificare de coliziune mai precisă.
III.6 Personajul principal din joc
Personajul principal din joc este implementat prin clasa Player.java. Clasa are multe
roluri de implementat pentru că este un catalizator pentru multe evenimente din joc. Clasa
extinde clasa GameObject.java și implementează interfețele Damagable și DamageInflicter.
Interfețele Damagable și DamageInflicter au fost create pentru a decide în momentul
atacului cine este atacat și cine atacă. Interfața Damagable are metode pentru a prelua viața
obiectului și cât va pierde din viața lui totală.
Interfața DamageInflicter are metode pentru a prelua informația referitoare la distanța
minimă la care se poate ataca cu arma și o metodă determină obiectele aflate la distanța
minimă.
30

Fig.III.5. Personajul principal din joc
Inventarul și conținutul curent al acestuia (arma și/sau articol de prim ajutor) depind
de interacțiunile personajului din joc, deci aceste sunt interconectate, fiind important să existe
metode pentru gesionarea lui în cadrul clasei personajului.
Am creat o clasă internă numită PlayerInventory folosită pentru a lucra cu inventarul
personajului, clasă care conține mai multe metode. O metodă importantă getCurrentItem care
returnează indexul curent al inventarului care este de tip InventoryItem. O altă metodă
addItem verifică tot inventarul și dacă găsește o poziție care este null atunci poziția aceea va
fi setată cu arma sau articolul de prim ajutor.
O altă metodă importantă removeItemsWithZeroDurability verifică totalitatea
inventarului și dacă durabilitatea armelor a ajuns la zero iar atunci pentru poziția unde se află
acestă armă se va asocia o valoare null. O altă metodă importantă numită switchToItem are
rolul de a schimba arma sau articolul de prim ajutor curent și dacă este o armă care a fost
schimbată atunci se va adăuga imaginea corespunzătoare. Schimbarea armei curentă se face
prin verificarea tipului armei. Ultima metodă importantă a clasei este metoda de desenare a
inventarului care este definită în interfața GameView și suprascrisă în clasa
GameWindow.java .
În afara clasei interior create sunt metode și anumite evenimente care trebuie aplicate
la fiecare ciclu – un set de imagini care au fost deja desenate, sau trebuie resetate imaginile
pentru arma curentă pentru a nu se repeta animațiile. Metoda removeWithZeroDurability este
o metodă care trebuie aplicată în fiecare ciclu. Jocul se va termina dacă viața personjului din
joc va fi redusă la zero deci verificarea trebuie facută la fiecare ciclu pentru ca jocul să poată
fi oprit în orice moment.
Dacă s-a constatat că viața are valoarea zero atunci se va aplica metoda
initGameOver. Metoda initGameOver este o metodă declarată în clasa GameRoom.java care
31

inițializează meniul Game Over, după care setează faza de joc la GAME_OVER se preia
valoarea timpului supraviețuit și se face conexiunea cu baza de date în care se află valorile
care descriu tabela highscore. În această metodă se va face compararea valorilor obținute de
jucătorul curent cu toate celelalte valori obținute de alți jucători pentru a decide dacă
rezultatele obținute trebuie să fie incluse în tabelă. Dacă rezultatul este pozitiv atunci dacă
sunt rezultate care nu mai sunt bune pentru tabelă acestea trebuie șterse din baza de date.
Secvența de cod de mai jos reprezintă implementarea personajului din joc:
public PlayerInventory() {
inventory = new ArrayList<>(INVENTORY_SIZE);
inventory.add(WeaponItem. createWeaponItem(new
WeaponProper ties(WeaponType.KNIFE)));
for (int i = 1; i < INVENTORY_SIZE; i++) {
inventory.add(null);
}
switchToItem(currentItemIndex);
}
public InventoryItem getCurrentItem() {
if (inventory.get(currentItemIndex) == null) {
return defaultWeapon;
} else {
return inventory.get(currentItemIndex);
}
}
public boolean addItem(InventoryItem item) {
boolean inventoryNotFull = false;
for (int i = 0; i < inventory.size(); i++) {
if (inventory.get(i) == null) {
inventory.set(i, item);
inventoryNotFull = true;
if (i == currentItemIndex) {
switchToItem(i);
}
break;
}
}
return inventoryNotFull;
}
Clasa mai lucrează cu coliziunea obiectelor, care depinde de tipul obiectului cu care se
face coliziunea – armă sau articol de prim ajutor. În cazul realizării coliziunii trebuie creat un
nou weaponObject sau healthObject și trebuie verificate proprietățile acestuia.
32

O altă metoda inAttackRangeEvent este o metodă suprascrisă a interfeței
DamageInflicter și este utilizată în această clasă pentru a adăuga toate obiectele care sunt
Damagable și sunt la distanță minimă față de arma curentă pentru a ataca și de a se înregistra
ca atac.
Metoda getAttackRange este o metodă care este suprascrisă și returnează distanța
minimă la care se poate ataca cu arma selectată, dar aceasta se va aplica numai dacă arma
curentă este o armă de tip MeleeWeaponItem.
Pentru că personajul din joc trebuie să urmărească poziția mouse-ului acesta trebuie să
fie calculată. Calculul acesteia se va realiza cu ajutorul metodei calcAngleBasedOnMouse
care face calcule pe baza poziției curente a mouse-ului și returnează poziția acestuia în
radiani.
III.7 Personajele tip zombi din joc
Personajele zombi sunt inamicii din joc și fiecare personaj zombi are două mari
roluri: de a urmări personajul principal din joc și de a ataca personajul dacă sunt la o distanță
mică.
Clasa Zombie.java extinde clasa GameObject.java și implementează interfețele
Damagable și DamageInflicter. Am creat o metodă numită calcAngleBasedOnPlayerPos care
se bazează pe calcAngleBasedOnMouse care va fi folosită pentru identificarea poziției
personajului și anume se va calcula unghiul personajului folosind coordonatele curente,
valoarea fiind ulterior convertită în radiani.
Se suprascrie metoda inAttackRangeEvent care a fost creată în interfața
DamageInflicter și se verifică dacă personajul din joc este la distanța ncesară pentru a fi
atacată iar în caz afirmativ personajul va pierde din viața totală o valoare corespunzătoare
predefinită.
O altă metodă suprascrisă care aparține interfeței DamageInflicter este
getAttackRange care returnează distanța pentru a fi folosită în clasă. Metoda suprascrisă
damage este o metodă care aparține interfeței Damagable care va fi folosită când un zombi
va fi atacat, iar dacă acest lucru se întâmplă atunci din viața unui zombi se va scădea o
valoare prestabilită corespunzătoare.
33

Fig.III.6. personaje zombi din joc
În joc dacă a fost omorât un zombi la un moment dat, trebuie creat altul în locul său.
Acest lucru se poate realiza prin crearea unei metode numită spawnZombie, rolul acestei
metode fiind de a crea zombi.
Această metodă este asociat cu dificultatea jocului, pentru că cu cât crește durata
jocului curent cu atât vor fi create mai multe personaje de tip zombi, care sunt implementate
în poziții aleatoare în joc. Există însă un număr maxim de personaje zombi care pot fi
prezenți în joc în același timp acest număr fiind 50. La crearea unui nou personaj zombi,
numărul total al acestora va fi mărit iar când este omorât un personaj zombi atunci numărul
lor total trebuie micșorat.
Cu cât durează mai mult jocul noile personaje de tip zombi create vor fi mai
puternice, astfel vor avea o viteză mai mare de deplasare iar valoarea cu care se diminuează
viața personajului principal este mai mare după un atac reușit.
Secvența de cod de mai jos prezintă implementarea unui personaj de tip zombi din
joc:
public Zombie(double x, double y, double attackDamage, double speed) {
super(x, y,
GameSpriteFactory. getZombieSprite(ZombieMotion.RUN));
this.motion = ZombieMotion. RUN;
this.attackDamage = attackDamage;
setSpeed(speed);
getSprite().setAnimationSpeed(1);
zombieCount++;
}
public Zombie(double x, double y, GameSprite sprite) {
super(x, y, sprite);
this.attackDamage = 1.0;
}
34

Multe dintre aceste metode trebuie verificate la fiecare ciclu și aplicate, astla fel
fiecare ciclu trebuie verificate coordonatele curente ale personajului principal și trebuie
transmise coordonatele sale metodei calcAngleBasedOnPlayerPos .
Pe baza acestora se va decide dacă zombi poate să se miște spre poziția
jucătorului/personajului principal. Prin utilizarea metodei nextPosCollision, metodă a clasei
GameObject se verifică dacă următoarele coordonate vor fi în coliziune. Metoda isInRoom
care este declarată în GameRoom.java va verifica dacă noile poziții la care trebuie să se miște
personajul zombi sunt încă în terenul de joc, în caz afirmativ se va utiliza metoda move
declarată în clasa GameObject.java.
Un alt element care trebuie verificat și aplicat în fiecare ciclu se referă mișcarea
curentă a personajelor de tip zombi iar pe baza distanței dintre zombi și personaj se determină
dacă este la o distanță care să îi permită să ataca personajul. Acest lucru este important pentru
că pe baza acestor mișcări și distanțe se va decide care imagini să fie desenate.
Secvența de cod de mai jos reprezintă implementarea zombiilor din joc:
@Override
public void stepEvent() {
super.stepEvent();
if (health > 0) {
double playerX = getRoom().getPlayerX();
double playerY = getRoom().getPlayerY();
double angle = calcAngleBasedOnPlayerPos(playerX,
play erY);
setAngle(angle);
setDirection(angle);
if (!nextPosCollision() &&
getRoom().isInRoom(getNextX(), get NextY(), this)) {
move();
}
if (playerInAttackRange && !
motion.equals(ZombieMotion. ATTACK)) {
motion = ZombieMotion. ATTACK;
setSprite(GameSpriteFactory. getZombieSprite(Zombie
Motion.ATTACK));
} else if (!playerInAttackRange && motion.equals(Zombie
Motion.ATTACK)) {
motion = ZombieMotion. RUN;
setSprite(GameSpriteFactory. getZombieSprite(Zombie
Motion.RUN));
}
} else {
35

motion = ZombieMotion. DEATH;
setSprite(GameSpriteFactory. getZombieSprite(Zombie
Motion.DEATH));
setSolid(false);
if (!newZombiesSpawned) {
zombiesKilled++;
zombieCount–;
if (zombieCount < MAX_ZOMBIE_COUNT) {
newZombiesSpawned = true;
spawnZombies();
}
}
}
playerInAttackRange = false;
attackDelayCounter++;
}
Mai trebuie verificat dacă un zombi a fost ucis, în caza afirmativ este necesară
schimbarea mișcării la DEATH și este necesară și schimbarea corespunzătoare a imaginii
III.8 Implementarea bazei de date
Implementarea bazei de date este un proces mai lung pentru că trebuie implementată
partea de server dar și trebuie implementat și partea de utilizator astfel încât
programul/aplicația să se poată conecta la această bază de date. Pentru a lucra cu o bază de
date locală trebuie creată una și pentru acest lucru am utilizat aplicația MySQL Server .
Când vream să creăm o baza de dată local, acesta trebuie configurat prima dată,
primul pas este de a decide ce fel de tip de server vrem realizăm și tipul de conexiune pe care
dorim să îl realizăm. În cazul aplicației implementate serverul este de tip development adică
nu o să fie o mașină pură care va lucra numai cu serverul, din considerente de a consuma cât
mai puțină memorie, iar conexiunea este de tip TC/IP la numărul de port 3306.
Următorul pas a fost creare unei parole pentru contul de root, în cazul nostru parola
aleasă este root1234. Pasul final al configurări serverul MySQL este de a decide dacă vream
ca serverul să fie creat ca un serviciu Microsoft. Dacă alegem această opțiune atunci serverul
poate să ruleze în fundal întotdeauna în momentul în care sistemul este pornit, dar dacă vrem
să terminăm executarea serverului atunci putem să căutăm serviciile Microsoft prezente pe
sistem și se poate termina executarea sa.
La implementarea jocului am decis să aleg varianta ca un serviciu Microsoft cu
numele de MySQL57. Ca și încheiere al configurări trebuie ales ce fel de cont vrem să avem
36

un cont standard sau vrem un cont care să aibe funcțiuni mai avansate, și mai trebuie ales un
sistem de securitate care care să fie asociat contului nostru, acest sistem poate să fie cu funcții
standard sau cu funcții mai avansate. În cazul nostru sa ales un cont standard cu un sistem de
securitate standard pentru că funcțiile acestora sunt de ajuns.
MySQL Workbench este un instrument grafic pe care îl putem folosi pentru lucrul cu
bazele de date, în MySQL Workbench putem crea conexiuni prin care putem să ne conectăm
la bazele de date.
Fig 3.1. Conexiunile realizate în MySQL Workbench
A fost realizată o conexiune numită GameConnection care aparține contului cu nume
root la adresa de 127.0.0.1 cu portul TCP/IP de 3306. Când dorim să ne contectăm la baza de
date prin această conexiune trebuie introdusă parola root1234, deoarece conexiunea este
asociată cu baza de date care are aceeași parolă.
După logare putem să începem lucrul cu bazele de date. A fost creată o schemă numită
highscore_schema, iar în această schemă a fost creată o tabelă numită highscore.
În tabelă au fost create patru coloane care sunt: idhighscore care va conține cheia
primară a tabelei care este de tip int(11) și are proprietatea de a se autoincrementa,
player_name de tip varchar (45), coloană în care va fi memorat numele jucătorului, time de
tip longtext, coloana în care va fi memorat timpul care jucătorul a supraviețuit și
zombies_killed de tip int(11) coloană în care va fi memorat numărul de zombii omorâte de
jucător.
37

Fig 3.2. Tabela highscore
La început când nimeni nu a jucat jocul, tabela este vidă deci trebuie introduse valori.
Am realizat acest lucru cu ajutorul SQL-ului prin intermediul instrucțiunii INSERT INTO au
fost introduse 20 de elemente în tabelă.
Din punct de vedere al utilizatorului/programului pentru ca acesta să recunoască și să
facă conexiunea dintre baza de date și conexiunile dintre obiectele din program și elementele
din baza de date, trebuie creat un folder nou numit META-INF în folderul de resurse folosite
de program și trebuie creat un nou fișier xml numit persistance.xml.
În persistance.xml trebuie specificat care clasă din program să fie asociată cu tabela
din baza de date folosită. Mai trebuie să specificat și portul prin intermediul căruia se va face
conexiunea. În cazul aplicației implementate portul este 3306 iar numele schemei în care se
va căuta tabela este highscore_schema, și mai trebuie să adăugăm numele de utilizator și
parola.
Persistanța este dată de un framework numit hibernate, care o să facă asocierea dintre
datele din tabel și cele din program. Prin persistență vorbim de acele date care sunt viabile
mai mult decât metodele pe care le-au creat, deci hibernate o să utilizeze Java Persistance
API(JPA).
38

Fig 3.3. Fișierul persistance.xml
După ce a fost creat fișierul persistance.xml a fost creat un nou pachet numit
persistance în care sunt create/conținute clasele care vor lucra cu baza de date. Clasa
Highscore.java este clasa care va reprezenta tabela highscore din baza de date, deci această
clasă va fi folosită de un framework pentru a determina metodele clasei.
Pentru implementare am folosit anotații, adică trebuie să dăm numele tabelei cu care
vrem să lucrăm în cazul nostru highscore și trebuie să dăm numele coloanelor cu care o să
lucrăm, astfel prin intermediul acestei clasei vom crea entiăți. Clasa DBConnection.java este
clasa care o să facă conexiunea la baza noastră de date.
Deoarece datele sunt folosite prin entități conexiunea trebuie să fie făcută prin aceste
entități, iar lucrul cu entitățiile sunt realizate prin entityManageri. Un entityManager este o
instanță a persitenței care va crea/distruge instanțe de entități și va identifica/interoga prin
intermediul cheile acestora.
Metoda creată getEntityManager are rolul de a crea acești entityManageri prin
folosirea unui entityManagerFactory, un entityManagerFactory fiind o instanță care va crea
acești entityManageri. Metoda creată close are rolul de a vizualiza toate entitățile de tip
entityManager create și de a verifica dacă acestea sunt deschise iar în caz afirmativ toate
aceste entități trebuie închise.
A mai fost creată o clasă numită DBConnectionException care extinde subclasa
Exception. Această clasă a fost creată pentru a gestiona excepțiile care ar putea apărea pe
39

parcursul execuției programului. Această clasă are metode prin intermediul cărora se vor
putea afișa mesaje și trata excepții.
Probabil cea mai important clasă creată este clasa HighscoreDAO.java , prin
intermediul acestei clase putând fi implementate metodele care vor lucra cu datele din bazele
din date. Metoda insertNewHighscore care extinde clasa DBConnectionException are rolul
de insera valori noi în baza de date. Această metodă are un entityManager care va fi preluat
de la clasa DBConnection.java și pe baza acestuia va fi creat un nou entityTransaction. Un
entityTransaction este o instanță a persistenței care este folosită pentru a controla tranzacțiile
a enityManagerilor cu date locale.
În metoda noastră după crearea tranzacției trebuie inițializate și informațiile pe care
le primește de la tabela highscore trebuie persistate adică datele trebuie menținute după
execuția procesului iar la final trebuie finalizate aceste informații, iar la finalul tuturor
tranzacțiilor trebuie închis entityManagerul.
Metoda getHighscores care extinde clasa DBConnectionException are rolul de a afișa
informațiile aflate în baza de date. În metodă o să folosim un entityManager care va fi preluat
din DBConnection. După crearea acestui entityManager am implementat un query folosind
createQuery cu instrucțiunea SELECT h FROM Highscore h care va inspecta toate
elementele din tabelă, iar tabela va fi asociată cu clasa Highscore.java și va trimite rezultate
pentru afișat, iar la finalul execuției entityManager trebuie închis.
Metoda deleteHighscore extinde clasa DBConnectionException și are rolul de a
șterge elementele din tabelă. În metodă vom folosi un entityManager care va fi preluat din
DBConnection și pe baza căruia va fi creat un entityTransaction, iar pe baza id-urilor din
clasa Highscore vor fi căutate elementele și vor fi șterse din baza de date, toate modificările
realizate fiind finalizate. La finalul execuției toate entitățile de tip entityManager trebuie
închise.
Ultima metodă creată closeEntityManager care extinde clasa
DBConnectionException și are rolul de a închide toate entitățile de tip entityManager după
finalizarea execuțiilor necesare. Această metodă creată este folosită de celălalte metode
pentru a închide toate elementele de tip entityManager.
Toate aceste clase s unt inserate în clasa GameRoom.java. Pentru că tabela din baza de
date trebuie afișată numai pe ecranul Game Over toate clasele vor fi conținute în metoda
initGameOver.
Metoda getHighscore este utilizată de fiecare dată când se va aplica initGameOver, iar
metoda deleteHighscore trebuie să fie aplicată numai dacă rezultatele obținute din sesiunea
40

de joc sunt mai mari decât ultimele 20 de rezultate obținute anterior de alți jucători iar
rezultatele care nu mai sunt în top 20 trebuie șterse.
Metoda insertNewHighscore e folosită în cadrul metodei playAgainPressed adică în
momentul în care noile rezultate trebuie inserate după ce a fost apăsat butonul Play Again sau
dacă a fost apăsată tasta Enter după ce a fost introdus numele jucătorului.
III.9 Implemetarea Maven-ului
Pentru a putea folosi Apache Maven nu este suficient să instalăm programul, dacă
dorim să îl utilizăm cu succes trebuie creată și o variabilă PATH de tip mediu. În cazul
aplicației implementate am ales calea C:\Users\Admin\apache-maven-3.5.0-bin\apache-
maven-3.5.0, și am creat fișierul POM.xml.
Un mare avantaj al Apache Maven îl reprezintă managementul ușor al depedențelor.
În Apache Maven nu este necesară căutarea și inserarea fiecărei biblioteci în parte pentru
fiecare dependență. Deci și în aplicația implementată trebuie să inserăm anumite dependențe
cum ar fi hibernate-core, hibernate-entitymanager și mysql-connector-java .
Hibernate-core este folosită în aplicație pentru a furniza funcționalitățiile de bază al
hibernatului. Hibernate-entitymanager este folosită în aplicație pentru a furniza
funcționalitățiile asociate cu persistența și cu asocierea datelor din program cu cele din baza
de date.
Mysql-connector-java este utilizată în aplicația implementată pentru a furniza driver-
ul care va implementa Java Database Connectivity (JDBC) API.
În POM.xml trebuie inserate numai aceste definiții anterior menționate iar Apache
Maven va descărca toate resursele necesare.
III.10 Implementarea JavaFX
Pentru implementarea metodelor lui JavaFX am creat o clas ă numită MainApp.java.
Această clasă este cea care realizează inițializarea aplicației deci va utiliza metodele JavaFX
pentru a desena elementele din joc.
Clasa MainApp.java extinde clasa Aplication deci va genera un framework pentru
toate celelalte metode al lui JavaFX. În cadrul clasei am creat un Stage numit primaryStage
care permite lucrul cu fereastra. Cu ajutorul Stage-ului în joc a fost creat un Scene, a fost
41

setat titlul ferestrei cu numele de ”Zombie Hunter” și a fost setată lungimea și lățimea
ferestrei la 1028 X 768 pixeli.
Pentru a folosi Stage-ul și pentru a utiliza și crea o scenă / Scene datorită folosirii
modelului MVC(Model-View-Controller) în această clasă trebuie create următoarele: un
GameController, un GameWindow și un GameRoom.
Un GameWindow este necesar deoarece cu ajutorul clasei GameWindow.java sunt
desenate elementele din joc, acesta lucru fiind realizat prin crearea unui canvas în clasă al
cărui dimensiune va fi egal cu dimensiunea ferestrei create, iar prin intermediul acestui
canvas putem desena imaginile prezente în joc, în final toate elementele din canvas fiind
asociate unei scene/ Scene create. Acestă scenă/ Scene creată va conține toate elementele
desenate/implementate în canvas dar mai are un rol foarte important și anume detectarea
tastelor apăsate și eliberate, detectarea mișcării, apăsarea și eliberarea butoanelor de mouse,
astfel încât pot fi verificate tastele și butoanele care sunt apăsate.
Un GameRoom este necesar pentru că această clasă are rolul de a lucra cu obiectele
create și se referă la aplicarea metodelor de apăsare a tastelor pe tastatură sau apăsarea
butoanelor de mouse sau legat de JavaFX prin aplicarea metodelor de desenare a imaginilor
pentru fiecare obiect creat.
Un GameController este necesar pentru că aici sunt declarate metodele folosite de
celelalte clase utilizate sau legate de JavaFX aici luându-se deciziile legate de desenare.
Deciziile legate de realiza sau nu a desenului trebuie luate aici, deoarece aceste metode
trebuie aplicate la fiecare ciclu fiind necesară verificarea lor frecventă pentru o funcționare
corectă.
III.11 Implementarea modelului model-view-controller(MVC)
Modelul model-view-controller(MVC) st ă la baza implementării aplicației. Pentru a
implementa acest model au fost create trei pachete cu numele de model, controller și view.
Fiecare pachet are mai multe clase sau interfețe implementate în funcție de pachetul în care se
află.
Pentru implementarea modelului a fost creat pachetul numit model, care conține
interfețe și clase care lucrează cu obiectele prezente în joc dar care conțien șii clase create
care lucrează cu imaginile din joc. Ca interfețe există Damagable.java sau
DamageInflicter.java care conțin metode pe care celelalte clase din pachet le vor folosi pentru
implementarea acestor interfețe.
42

Clasele utilizate sunt Player. java și Zombie.java care au funcțiile lor proprii cu care
lucrează dar care pot să salveze datele și să transmită datele cu care lucrează, acesta fiind cel
mai important lucru pe care clasele din model trebuie să le realizeze.
Cea mai importantă clasă din pachetul model este clasa GameRoom.java, rolul acestei
clase fiind de a crea obiectele din joc și de a folosi datele luate de la celelalte clase pentru a le
folosi în funcțiile lui având și rolul de a aplica diferite operații asupra tuturor obiectelor
prezente în joc în mometul aplicării acestor operații.
Deci rolul pachetului model este de a salva date și de a permite celorlalte clase de a
lucra cu datele lui.
Pentru implementarea controllerului a fost creat un pachet numit controller în care se
află o singură clasă numită GameController.java . Fiind controllerul aplicației acesta conține
diferite funcții declarate în interiorul său pe care ulterior celelalte clase din alte pachete le pot
folosi și pot decide modul în care să folosească aceste funcții. Și ceastă clasă poate să
folosească datele claselor din pachetul model, și decide care dintre aceste date trebuie
actualizate.
Pentru implementarea modelului view a fost creat un pachet numit view. În acest
pachet este creată interfață GameView.java în care sunt declarate funcții, pe care clasa
GameWindow.java o va folosi după ce va implementa interfața GameView.java. Funcțiile
clasei GameWindow.java au rolul de a desena elementele din aplicație, clasa va cere ca
desenarea să fie efectuată dar controllerul va fi cel care va decide dacă va fi permis acest
lucru.
În caz afirmativ clasa GameWindow.java va desena aceste elemente, deci rolul
modelului view este de a desena elementele aplicației.
43

CONCLUZII
În legătură cu aplicația creată am realizat o aplicație care este un joc de tipul
Shoot`em Up subtip multidirectional shooter care a respectat cerin țele de bază pentru a putea
fi inclus în categoria menționată. Astfel este implementată posibilitatea de mișcare în patru
direcții: sus, jos, stânga, dreapta, precum și posibilitatea de rotire 360 de grade și perspectiva
de sus în jos.
Prin proiectarea și implementarea acestei aplicații am realizat un joc simplu care să fie
în același timp distractiv dar care să poată fi utilizat cu succes atât de o persoană pasionată de
jocuri dar și de alte persoane care de obicei nu sunt fani ai jocurilor video.
Pe parcursul elaborării aplicației am realizat cât de complexă poate fi implementarea
unui joc video chiar dacă partea grafică în cazul aplicației mele este mai simplă. Pe lângă
noțiunile de programare utilizate am aflat că într-un joc video sunt multe mecanisme care
sunt într-o strânsă relație una cu cealaltă, și am mai învățat și descoperit elemente noi despre
subiecte despre aveam cunoștințe anterioare dar pe care le-am aprofundat – JavaFX sau
MySQL.
Pe parcursul elaborării aplicației am realizat cum poate să fie folosit limbajul de
programare Java pentru crearea jocurilor video. Deși nu este o alegere populară pentru
crearea jocurilor video prin crearea acestei aplicație am aflat că Java are multe funcționalități
similare cu C++ sau C# ce pot fi utilizate cu succes pentru a putea crea jocuri video.
Pe parcursul elaborării aplicației am create mai multe versiunui ale acesteia și am
ajuns la versiunea finală. Aceste schimbări au fost realizate deoarece odată cu evoluția
aplicației anumite elemente au devenit nerelevante. Prin intermediul acestor schimbări am
învățat cum să planific o aplicație pe mai multe etape și am văzut cum poate o aplicație să se
schimbe cu timpul și să evolueze.
Pe viitor doresc să dezvolt această aplicație prin introducerea unor noi varietăți de
zombi care răspund în mod diferit la acțiunile jucătorului/personajului principal, eventual pot
realiza implementarea unor noi tipuri de arme și este posibilă și implementarea unor noi
articole de prim ajutor.
44

BIBLIOGRAFIE
[1] https://docs.oracle.com/javase/8/javafx/get-started-tutorial/jfx- overview.htm#JFXST784 ,
consultat la 6.10.2017 & 22.02.2018
[2] https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-
files/cssref.html#introscenegraph , consultat la 10.10.2017
[3] https://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html , consultat
la 20.10.2017
[4] https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Scene.html consultat la
03.11.2017
[5] https://docs.oracle.com/javase/8/javafx/api/javafx/stage/Stage.html , consultat la
10.11.2017
[6] https://en.wikibooks.org/wiki/Computer_Science_Design_Patterns/Model
%E2%80%93view%E2%80%93controller , consultat la 20.11.2017
[7] http://books.sonatype.com/mvnref-book/pdf/mvnref-pdf.pdf , consultat la 25.11.2017
[8] https://dev.mysql.com/doc/refman/5.7/en/what-is-mysql.html , consultat la 05.12.2017
[9] https://dev.mysql.com/doc/workbench/en/wb-intro.html , consultat la 08.12.2017
[10] https://en.wikipedia.org/wiki/Shoot_%27em_up , consultat la 20.02.2018
[11] http://www.escapistmagazine.com/articles/view/video-games/columns/experienced-
points/12729-The-Language-For-Programming-Games-Needs-to-Change , consultat la
15.01.2018
45

[12] https://opengameart.org/content/animated-top-down-survivor-player , consultat la
12.11.2017
[13]https://opengameart.org/content/top-down-animated-zombie-set , consultat la 12.11.2017
[14] https://opengameart.org/content/weapon-inventory-graphics , consultat la 12.11.2017
[15] https://opengameart.org/content/food-items , consultat la 12.11.2017
[16] https://opengameart.org/content/pistol-32×26-bullet-12×3 , consultat la 12.11.2017
46

DECLARAȚIE DE AUTENTICITATE A
LUCRĂRII DE FINALIZARE A STUDIILOR
Titlul lucrării: Joc de acțiune interactiv implementat în java
Autorul lucrării: HERLITSKA ATTILA-LEVENTE
Lucrarea de finalizare a studiilor este elaborată în vederea susținerii
examenului de finalizare a studiilor organizat de către Facultatea de Inginerie
Electrică și Tehnologia Informației din cadrul Universității din Oradea, sesiunea
iulie a anului universitar 2017-2018.
Prin prezenta, subsemnatul Herlitska Attila-Levente , CNP:
1940909055064 , declar pe proprie răspundere că această lucrare a fost scrisă de
către mine, fără nici un ajutor neautorizat și că nici o parte a lucrării nu conține
aplicații sau studii de caz publicate de alți autori.
Declar, de asemenea, că în lucrare nu există idei, tabele, grafice, hărți sau
alte surse folosite fără respectarea legii române și a convențiilor internaționale
privind drepturile de autor.
Oradea,
……07.2018 Semnătura
47

Similar Posts