51
SVEUČILIŠTE U ZAGREBU FAKULTET ORGANIZACIJE I INFORMATIKE V A R A Ţ D I N Bernard Brček Bedeković STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA ZAVRŠNI RAD Varaţdin, 2010.

STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

SVEUČILIŠTE U ZAGREBU

FAKULTET ORGANIZACIJE I INFORMATIKE

V A R A Ţ D I N

Bernard Brček Bedeković

STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA

ZAVRŠNI RAD

Varaţdin, 2010.

Page 2: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

SVEUČILIŠTE U ZAGREBU

FAKULTET ORGANIZACIJE I INFORMATIKE

V A R A Ţ D I N

Bernard Brček Bedeković

Redoviti student

Broj indeksa: 35616/06-R.

Smjer: Informacijski sustavi

Preddiplomski studij

STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA

ZAVRŠNI RAD

Mentor:

Tihomir Orehovački, dipl. inf.

Varaţdin, rujan 2010.

Page 3: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

I

Sadrţaj

1. UVOD ....................................................................................................................................................................... 1

2. POLJA ..................................................................................................................................................................... 3

2.1. JEDNODIMENZIONALNA POLJA ........................................................................................................................... 3 2.1.1. Statično polje ............................................................................................................................................. 3 2.1.2. Dinamično polje ....................................................................................................................................... 4

2.2. VIŠEDIMENZIONALNA POLJA .............................................................................................................................. 6 2.2.1. Statično polje ............................................................................................................................................. 6 2.2.2. Dinamično polje ....................................................................................................................................... 7

2.3. PRIMJENA POLJA U IGRAMA ................................................................................................................................ 8

3. BITVECTOR ........................................................................................................................................................... 9

3.1. KREIRANJE BITVECTORA .................................................................................................................................... 9 3.2. POSTAVLJANJE VRIJEDNOSTI BITOVA U BITVECTORU ......................................................................................... 9 3.3. ČITANJE VRIJEDNOSTI BITA U BITVECTORU ...................................................................................................... 10 3.4. PRIMJENA BITVECTORA U IGRAMA ................................................................................................................... 10

4. BITFIELD ............................................................................................................................................................. 12

4.1. PRIMJENA BITFIELDA U IGRAMA ....................................................................................................................... 12

5. VEZANE LISTE ................................................................................................................................................... 13

5.1. JEDNOSTRUKO VEZANA LISTA .......................................................................................................................... 13 5.2. DVOSTRUKO VEZANA LISTA ............................................................................................................................. 14 5.3. PRIMJENA VEZANIH LISTI U IGRAMA ................................................................................................................. 14

6. STOG ..................................................................................................................................................................... 15

6.1. PRIMJENA STOGA U IGRAMA ............................................................................................................................. 16

7. RED ........................................................................................................................................................................ 18

7.1. PRIMJENA REDA U IGRAMA ............................................................................................................................... 19

8. HASH TABLICE .................................................................................................................................................. 21

8.1. HASH FUNKCIJA................................................................................................................................................ 22 8.2. HASH VRIJEDNOST ............................................................................................................................................ 23 8.3. PRIMJENA HASH TABLICA ................................................................................................................................. 24

8.3.1. Primjena hash tablica u igrama .............................................................................................................. 24

9. REKURZIJA ......................................................................................................................................................... 26

9.1. PRIMJENA REKURZIJE U IGRAMA ...................................................................................................................... 26

10. STABLA ............................................................................................................................................................... 28

10.1. DIJELOVI STABLA ........................................................................................................................................... 28 10.2. VRSTE STABALA ............................................................................................................................................. 30 10.3. BINARNO STABLO ........................................................................................................................................... 30 10.4. BINARNO STABLO PRETRAŢIVANJA ................................................................................................................ 32 10.5. PRIMJENA STABALA U IGRAMA ....................................................................................................................... 33

11. HRPA ................................................................................................................................................................... 36

12. GRAFOVI ............................................................................................................................................................ 39

12.1. VRSTE GRAFOVA............................................................................................................................................ 39 12.1.1. Dvosmjerni graf .................................................................................................................................... 39 12.1.2. Jednosmjerni graf .................................................................................................................................. 40 12.1.3. Težinski graf .......................................................................................................................................... 40

12.2. IMPLEMENTACIJA GRAFA ................................................................................................................................ 41 12.3. PRETRAŢIVANJE GRAFA .................................................................................................................................. 43

12.3.1. Prvo-u-dubinu ........................................................................................................................................ 44 12.3.2. Prvo-u-širinu ......................................................................................................................................... 44

12.4. PRIMJENA GRAFOVA U IGRAMA ...................................................................................................................... 45

Page 4: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

II

13. ZAKLJUČAK...................................................................................................................................................... 46

14. LITERATURA .................................................................................................................................................... 47

Page 5: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

1

1. Uvod

Svaki računalni program se na svojoj najniţoj razini sastoji od podataka i algoritama koji se na

tim podacima izvršavaju. Spomenuti podaci su obično strukturirani na odreĎeni način da bi bili

pogodni izvršavanje pojedinih algoritama nad njima. Upravo ti načini na koji podaci mogu biti

strukturirani će biti navedeni i opisani u ovom završnom radu s naglaskom na upotrebu

spomenutih struktura u jednoj posebnoj vrsti aplikacija – računalnim igrama. TakoĎer će uz ovaj

rad biti napravljena i jedna igra koja će posluţiti kao demonstracija primjene struktura podataka

koje će biti navedene u ovom radu. Naravno nisu sve strukture podataka pogodne za sve igre pa

tako ni prilikom izrade te igre neće biti korištene baš sve u ovom radu navedene strukture. Za

svaku strukturu će biti navedene neke od mogućih primjena, a kod onih struktura koje će se

koristiti u popratnoj igri to će biti posebno istaknuto. Kod nekih struktura osim opisa biti će

navedena i vremenska sloţenost algoritama koji se nad njima izvršavaju kako vi se istaknula

brzina odreĎenog algoritma. Vremenska sloţenost se označava sa velikim slovom O i koristi se

za opisivanje teoretskih performansi algoritama pri čemu se u obzir uzima vremensko trajanje ili

količina memorije koji su algoritmu potrebni prilikom izvoĎenja [Sherrod, 2007, str. 15].

Najmanja vremenska sloţenost iznosi O(1) te se algoritmi koji imaju takvu sloţenost smatraju

vrlo brzima. Pošto svaka struktura podataka moţe biti implementirana na različite načine

vremenska sloţenost se moţe koristiti za usporedbu pojedinih implementacija.

Programski jezik koji je odabran za izradu popratne igre je C++ jer je on jako popularan kad je

riječ o razvoju računalnih igara [Sherrod, 2007, str. 12]. Igra koja dolazi uz ovaj rad je

jednostavan primjer strategije u realnom vremenu. U spomenutoj, igri igraču se daje na

raspolaganje nekoliko vrsta jedinica (tenk, sjedište baze, spremište tenkova) kojima on moţe

upravljati na način da im dijeli naredbe. Pošto se radi o jednostavnom primjeru, igrač moţe

zadati dvije vrste naredbi – idi na lokaciju, koju igrač moţe zadati samo mobilnim jedinicama te

napadni, koju igrač moţe zadati svim jedinicama. Zadate naredbe dodaju se na listu naredbi

svake jedinice koja je implementirana pomoću reda. Igraču i njegovim jedinicama suprotstavit će

se protivničke jedinice kojima upravlja računalo. Protivničke jedinice su po svojim svojstvima i

izgledu jednake igračevima te ih ima u jednakom broju. Pošto je programiranje igre poprilično

zahtjevan posao većina programera za potrebe igre napiše poseban set klasa, funkcija i

algoritama posebno pripremljenih za odreĎeni tip igre. Takav set odnosno biblioteka naziva se

game engine. Za potrebe ovog rada nije izraĎen posebni game engine nego je korišten postojeći.

Zove se DarkGDK. Radi se o besplatnom engine-u otvorenog koda čiji je autor firma The Game

Page 6: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

2

Creators iz Velike Britanije, a za renderiranje virtualnih svjetova koristi DirectX1 9. Cilj izrade

ovog rada i popratne igre je upoznavanje najpoznatijih struktura podataka i načina njihova

korištenja u izradi računalnih igara.

1 DirectX je kolekcija aplikacijskih programskih sučelja (API-ja) za izvršavanje zadaća povezanih s multimedijom,

posebno s programiranjem igara, na operacijskom sustavu Windows. Sastoji se od sljedećih sučelja: Direct3D,

DirectDraw, DirectMusic, DirectPlay, DirectSound itd. Prva verzija, s oznakom 1, izdana je 30. Rujna 1995. godine

a posljednja i aktualna u vrijeme pisanja ovog rada 27. Listopada 2009 i nosi oznaku 11.

Page 7: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

3

2. Polja

Polja su najjednostavniji i najkorišteniji oblik struktura podataka. Polje se moţe zamisliti kao

jedna velika jednodimenzionalna struktura koja sadrţi brojne ćelije a svakoj ćeliji pristupamo

pomoću indeksa [Penton, 2003, str. 40]. Uobičajeno je da prva ćelija u polju ima indeks 0, a

posljednja indeks koji je za jedan manji od veličine polja (npr. kod polja sa 9 elemenata

posljednja ćelija imala bi indeks 8). Polja su linearne strukture podataka jer su ćelije u memoriji

računala smještene jedna za drugom [Kutti i Padhye, 2004, str. 64]. Vrijeme pristupa pojedinoj

ćeliji u polju je vremenske sloţenosti O(1). Bez obzira koliko elemenata ili ćelija polje sadrţi,

vrijeme pristupa će uvijek biti isto. Pošto se svakom elementu polja moţe pristupiti instantno,

polja se još nazivaju i strukture podataka sa nasumičnim pristupom (eng. random-access

structures) [Penton, 2003, str. 41]. Postoje dvije vrste polja: statično i dinamično [Kutti i Padhye,

2004, str. 75].

2.1. Jednodimenzionalna polja

2.1.1. Statično polje

Statičko polje je polje koje se alocira jednom i njegova veličina se ne moţe naknadno promijeniti

[Penton, 2003, str. 43].

Primjer 1. Alokacija statičnog polja

int polje[10];

Da bi kreirali polje od deset elemenata tipa integer moramo uz ime polja staviti uglatu zagradu u

kojoj moramo specificirati broj elemenata koje će to polje sadrţavati. U primjeru 1 polje ima

deset elemenata čiji su valjani indeksi u rasponu od 0 do 9. Devetom elementu polja bi postavili

vrijednost na pet na način koji je prikazan u primjeru 2.

Primjer 2. Postavljanje vrijednosti elemenata u polju

polje[8]=5;

Vaţno je napomenuti da je nakon kreiranja polja elemente polja potrebno postaviti na odreĎenu

vrijednost jer C++ to neće sam napraviti. Naime, ako probamo pristupiti nekom elementu polja

23 13 0 9 10 66 19

Slika 2.1. Grafički prikaz polja sa 7 elemenata

Page 8: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

4

prije nego to napravimo naići ćemo na čudne vrijednosti koje nemaju smisla i bilo kakav rad s

tim vrijednostima moţe prouzročiti rušenje programa. Prethodno kreirano polje moţemo

popuniti vrijednostima na dva načina koji su prikazani u primjeru 3.

Primjer 3. Popunjavanje polja vrijednostima

int polje[10]={0,0,0,0,0,0,0,0,0,0};

ili

for(int a=0; a<10; a++) {polje[a]=0;}

Nakon što nam alocirano polje više ne treba, potrebno ga je obrisati korištenjem ključne riječi

delete kao što je prikazano u primjeru 4.

Primjer 4. Brisanje polja

delete[] polje;

Uglate zagrade do ključne riječi delete znači da ţelimo obrisati polje. Bez uglatih zagrada

obrisali bi samo prvi element polja. Ukoliko polje kreiramo unutar funkcije nije ga nuţno

obrisati jer će to program napraviti za nas automatski kad se funkcija izvrši do kraja.

2.1.2. Dinamično polje

Dinamično polje je polje čija se veličina tijekom izvoĎenja programa moţe mijenjati po potrebi.

Takvo polje se mora kreirati upotrebom pokazivača a moţe se kreirati na tri načina [Penton,

2003, str. 50]:

Primjer 5. Alokacija dinamičnog polja pomoću funkcije malloc

polje=(int*)malloc(sizeof(int)*10);

Pomoću funkcije malloc alociramo memoriju dovoljno veliku da u nju stane polje ţeljene

veličine. Pošto funkcija malloc vraća pokazivač na alociranu memoriju tipa void, taj pokazivač je

potrebno konvertirati u tip podataka koji će biti spremljeni u polju, u ovoj slučaju je to integer

[Ibid, str. 50]. Ako prilikom alociranja memorije funkcija malloc vrati vrijednost 0 znači da ne

postoji dovoljno slobodne memoriju u računalu za polje te veličine. Prilikom ovakvog načina

alociranja memorije potrebno je navesti jedan parametar koji označava količinu memorije u

bajtovima koju ţelimo alocirati.

Primjer 6. Alokacija dinamičnog polja pomoću funkcije calloc

polje=(int*)calloc(10,sizeof(int));

Page 9: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

5

Funkcija calloc alocira memoriju na isti način kao i funkcija malloc s jednom bitnom razlikom:

nakon alociranja svi elementi polja se postave na vrijednost nula. Prilikom ovakvog načina

alociranja memorije potrebno je navesti dva parametra: prvi označava broj elemenata u polju a

drugi veličinu jednog elementa u bajtovima [Ibid, str. 51].

Primjer 7. Alokacija dinamičnog polja pomoću funkcije new

polje=new int[10];

Funkcija new će alocirati polje zadane veličine te će za svaki element novo alociranog polja

pozvati njegovu konstruktor metodu ako ona postoji [Ibid, str. 52]. Zbog toga je ovakav način

alociranja memorije sporiji od malloc-a i calloc-a. Jedini parametar koji treba navesti u ovom

slučaju označava broj elemenata koje će polje sadrţavati a pokazivač na tu memoriju koji

funkcija new vraća je uvijek istog tipa kao i elementi polja pa ga nije potrebno konvertirati.

Za razliku od statičnih polja koja, ako su alocirana unutar funkcije, program sam obriše iz

memorije nakon što se funkcija izvrši do kraja, dinamička polja moramo obrisati sami. Ukoliko

to ne učinimo prouzrokovati ćemo problem koji se zove memory leak - memorija koju smo

jednom alocirali a više nam ne treba i dalje zauzima mjesto u memoriji jer program ne zna da

nam više ne treba [Ibid, str. 53]. Ako nastavimo alocirati novu memorijsku lokaciju bez da smo

obrisali već alociranu koja nam više ne treba, memorija računala će biti sve punija i punija, a u

jednom trenutku bi moglo i ponestati mjesta u memoriji. Prilikom brisanja dinamički alociranih

polja način brisanja ovisi o načinu na koji smo ih alocirali. Ako je polje alocirano pomoću

funkcije malloc ili calloc treba ga obrisati pomoću funkcije free.

Primjer 8. Brisanje dinamičnog polja pomoću funkcije free

free(polje);

Ako je alocirano pomoću funkcije new, onda ga brišemo isto kao i statično polje, ključnom

riječju delete. Za razliku od funkcije free, delete prije brisanja polja poziva destruktor metodu

svakog elementa polja ukoliko potonji element ima destruktor metodu. Nadalje, ako ţelimo

promijeniti veličinu dinamičkog polja to moţemo napraviti na dva načina koji su prikazani u

primjerima 9 i 10 [Ibid, str. 54].

Primjer 9. Promjena veličine dinamičkog polja pomoću funkcije realloc

polje=(int*)realloc(polje,sizeof(int)*20);

Page 10: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

6

Ako je polje alocirano pomoću funkcija malloc ili calloc veličinu mijenjamo funkcijom realloc.

Funkcija realloc traţi dva parametra: prvi je pokazivač na polje čiju veličinu ţelimo promijeniti

a drugi označava novu veličinu polja. U slučaju da je moguće alocirati novo polje na istom

mjestu u memoriji funkcija realloc će to učiniti te se u tom slučaju pokazivač na polje neće

promijeniti. MeĎutim, ukoliko to nije moguće polje će biti alocirano na drugom mjestu u

memoriji. Konačno, ukoliko u memoriji nema dovoljno mjesta za novo polje realloc će vratiti

nula [Ibid, str. 55].

Ako je polje alocirano pomoću funkcije new, nije mu moguće promijeniti broj elemenata na

jednostavan način. Najprije je potrebno alocirati novo polje sa ţeljenim brojem elemenata, zatim

kopirati podatke iz starog polja u novo te na kraju obrisati staro polje [Ibid, str. 57].

Primjer 10. Kopiranje dinamičnog polja na drugu memorijsku lokaciju

int *polje=new int[10];

int *novo_polje=new int[20];

memcpy( novo_polje, polje, sizeof(int)*10);

delete[] polje;

2.2. Višedimenzionalna polja

Za razliku od jednodimenzionalnih polja koja ubrajamo u linearne strukture podataka,

višedimenzionalna polja pripadaju kompleksnijim strukturama podataka. Kod

jednodimenzionalnih polja, podaci su u memoriji smješteni jedan iza drugog. Razlog tome je

jednostavnost ali i brzina pristupa podacima jer se svakom elementu moţe brţe pristupiti ako mu

se zna adresa u memoriji koju je lako izračunati. MeĎutim kod višedimenzionalnih polja stvar je

malo drugačija. Podaci nisu u memoriji smješteni jedan iza drugoga nego se za smještaj

pojedinog elementa polja računa adresa po odreĎenoj formuli. Ta formula nije kod svakog

programskog jezika ista jer svaki programer koji razvija pojedini programski jezik pokušava naći

jednostavniji i brţi način za izračun adrese elementa polja dok istovremeno treba i pohraniti

podatke u memoriju na način da im se moţe što brţe pristupiti.

Isto kao i u slučaju jednodimenzionalnih polja, C++ nam daje mogućnost da višedimenzionalno

polje deklariramo statički ili dinamički.

2.2.1. Statično polje

Statično polje se deklarira slično kao i jednodimenzionalno polje – veličinu svake pojedine

dimenzije navodimo u uglatim zagradama nakon imena polja [Penton, 2003, str. 112].

Page 11: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

7

Primjer 11. Alokacija dvodimenzionalnog statičnog polja

int polje[2][3];

Primjer 12. Alokacija trodimenzionalnog statičnog polja

int polje[2][3][4];

Isto kao i jednodimenzionalna polja i višedimenzionalna trebaju nakon kreiranja biti postavljena

na početne vrijednosti [Ibid, str. 113].

Primjer 13. Postavljanje višedimenzionalnog statičnog polja na početne vrijednosti

int polje[3][3]={ {1,2,3},

{4,5,6},

{7,8,9} };

Pošto se dvodimenzionalna polja mogu zamisliti kao polja čiji su elementi opet polja svaki red u

polju je definiran kao normalno polje [Ibid, str. 113]. U primjeru 13, kreirano polje ima dvije

dimenzije, a svaka dimenzija po 3 elementa. Broj u prvoj uglatoj zagradi odreĎuje broj

elemenata polja, a broj u drugoj uglatoj zagradi broj elemenata od kojih se sastoji svaki element

polja. Budući da je svaki element polja sastavljen od više drugih elemenata on se moţe

promatrati kao manje polje unutar većeg [Ibid, str. 113].

Ovakvi tipovi polja su najčešći u razvoju igara jer jako rijetko postoji potreba za naknadnim

povećavanjem ili smanjivanjem broja elemenata [Ibid, str. 113].

2.2.2. Dinamično polje

Ponekad ne znamo koliko nam elemenata bude potrebno u nekom trenutku pa je polja potrebno

deklarirati kao dinamička (npr. prilikom učitavanja slika kojima ne znamo unaprijed rezoluciju).

Takvo polje se deklarira, isto kao i dinamičko jednodimenzionalno, pomoću pokazivača. Nakon

što polje jednom deklariramo veličinu mu moţemo odrediti naknadno kada ćemo znati koliko

elemenata nam treba. Prilikom toga mora se uzeti u obzir jedno ograničenje koje govori da, osim

prve, sve dimenzije moraju biti poznate [Lipljin, 2004, str. 170].

Primjer 14. Deklariranje višedimenzionalnog dinamičnog polja

int (*polje)[5];

Primjer 15. Alociranje višedimenzionalnog dinamičnog polja

int (*polje)[5]=new int[2][5];

Page 12: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

8

2.3. Primjena polja u igrama

Kad je riječ o računalnim igrama, memorija treba sadrţavati puno podataka, a još je vaţnije da se

tim podacima moţe brzo pristupiti i da ih se moţe brzo promijeniti. Upravo su zbog toga polja

jako korisna te se jako često koriste u razvoju igara. Najčešće se koriste za spremanje podataka

kojima je potrebno brzo i često pristupanje čak i do nekoliko desetaka puta u sekundi [Penton,

2003, str. 71]. Najčešće su takvi podaci u pitanju kada u igri postoje razni likovi, bilo prijateljski

ili neprijateljski, s kojima je igrač stalno u doticaju.

Primjer 16. Primjer polja

class cEnemy{

public:

int m_iObj;

int m_iHealth;

int m_iAmmo;

int m_iStatus : 3;

int m_iType : 3;

bool m_iStatic;

int m_iTarget;

}

class cResurs{

public:

int m_iObj;

double m_fTime;

float m_fX,m_fY,m_fZ;

int m_iAmount;

int m_iType;

bool m_bCollected;

};

U igri koja dolazi uz ovaj rad polja se koriste na sljedeće načine:

1) Sve neprijateljske jedinice će biti smještene u polju tipa cEnemy. Svi podaci o

neprijateljskim jedinicama biti će unaprijed odreĎeni i spremljeni u datoteku

„enemys.dat“. Kada igrač odabere New Game iz glavnog izbornika podaci će iz datoteke

„enemys.dat“ biti učitani i tada će igrač započeti s igrom

2) Na nivou će takoĎer postojati nekoliko točaka na kojima će se pojavljivati odreĎeni

resursi koje će igrač tijekom igre moći pokupiti. One će biti smještene u polju tipa

cResurs, a njihove lokacije će biti nasumično odreĎene prije početka igre. Broj točaka

ovisi o teţini igre koju igrač odabere u glavnom izborniku.

Osim za likove, polja mogu posluţiti za spremanje podataka o nivou koji iz nekog razloga treba

biti interaktivan pa je potrebno pristupati podacima što brţe.

Page 13: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

9

3. Bitvector

Bitvector je posebna vrsta polja koja sluţi za drţanje podataka veličine jednog bita na način da ti

podaci budu što saţetiji i time da zauzimaju što je moguće manje memorije [Penton, 2003, str.

84]. Upotreba bitvectora posebno dolazi do izraţaja kada je potrebno slati podatke preko mreţe

ili prilikom spremanja masivnih virtualnih svjetova na hard disk [Ibid, str. 105]. Najefikasniji

način za kreiranje bitvectora je kreiranje bitvectora one veličine kojom se šalju podaci po

sabirnici računala. Na većini 32 bitnih računala se podaci po sabirnici šalju u djelićima od 32 bita

što odgovara veličini podatka long integer [Ibid, str. 84].

0 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0 0 0 1 1 0 1 1 1 1 0 1 0 0 1 1 0

Slika 3.1 Bitvector sa 32 indeksa, svaki veličine jednog bita

3.1. Kreiranje bitvectora

Pošto je bitvector zapravo posebna vrsta polja kreiramo ga isto kao i dinamičko polje. MeĎutim,

svi elementi moraju biti tipa long integer ako ţelimo da jedan element polja bude velik 32 bita. S

obzirom da bit moţe poprimiti vrijednost 0 ili 1, potrebni su nam samo pozitivni brojevi pa

koristimo tip podatka unsigned long integer. Ukoliko ne ţelimo da elementi polja budu veliki 32

bita moţemo koristiti i druge tipove podataka.

Primjer 17 predstavlja ilustraciju kreiranja bitvector polja veličine jednog elementa odnosno 32

bita.

Primjer 17. Kreiranje bitvectora

unsigned long int* polje=new unsigned long int[1];

Pošto je svaki element velik 32 bita, bitvector polje iz primjera 17 moţe sadrţavati samo broj

bitova koji su višekratnici broja 32 (32, 64, 96 ...). Broj u uglatoj zagradi predstavlja koliko puta

po 32 bita će bitvector polje sadrţavati.

3.2. Postavljanje vrijednosti bitova u bitvectoru

Da bi postavili vrijednost pojedinog bita, prvo moramo znati u kojem elementu polja se taj bit

nalazi te redni broj tog bita u tom elementu. Da bi saznali u kojem elementu se bit nalazi

moramo redni broj bita podijeliti sa veličinom jednog elementa polja u bitovima – u ovom

Page 14: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

10

slučaju to je 32. Da bi saznali koji bit u prethodno odreĎenom elementu odgovara onom

traţenom, koristimo operator % (modulo). Na kraju, kad znamo redni broj bita, njegovu

vrijednost postavljamo na jedan pomoću operatora AND, odnosno na nulu korištenjem OR

operatora [Ibid, str. 91].

Primjerice, ţelimo postaviti vrijednost bita s indeksom 36 na vrijednost 1:

Primjer 18. Postavljanje vrijednosti bita sa indeksom 36 na vrijednost 1

int element=36/32;

int redni_broj=36 % 32;

polje[element]=(polje[element] | (1<<redni_broj));

Primjer 19. Postavljanje vrijednosti bita sa indeksom 36 na vrijednost 0

polje[element]=(polje[element] & (~(1<<redni_broj)));

3.3. Čitanje vrijednosti bita u bitvectoru

Čitanje vrijednosti bita iz primjera 18 je prikazano u primjeru 20.

Primjer 20. Čitanje vrijednosti bita iz bitvectora

bool vrijednost=(polje[element]&(1<<redni_broj)) >> redni_broj;

Slučajevi čitanja i postavljanja vrijednosti u bitvectoru se zasnivaju na binarnim matematičkim

pravilima koja glase [Ibid, str. 91]:

1. X and 1 = X

2. X and 0 = 0

3. X or 1 = 1

4. X or 0 = X

3.4. Primjena bitvectora u igrama

Većina današnjih igara ima quick-save mogućnost odnosno mogućnost da igra sama snimi stanje

u kojem se virtualni svijet nalazi u nekom trenutku tako da igrač ima mogućnost da nakon

prekida igranja ponovo nastavi gdje je stao [Ibid, str. 96]. Da igrač ne bi morao voditi računa o

tome igra to radi za njega. Budući da su virtualni svjetovi ogromni i zauzimaju stotine megabajta

kod simuliranja više stvari odjednom, spremanje potpunog stanja igre u nekom trenutku moglo

bi prouzrokovati duţu stanku u igranju jer je brzina hard diska u usporedbi s RAM memorijom

računala jako mala. Tu na scenu nastupa bitvector koji moţe posluţiti za voĎenje evidencije o

tome koji dijelovi igre su se promijenili od zadnjeg snimanja stanja. U tom slučaju svaka stavka

Page 15: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

11

igre koja se mijenja kroz vrijeme moţe biti predstavljena jednim bitom u bitvectoru. Na taj način

spremanje potpunog stanja igre potrebno je napraviti samo jednom te se kod svakog naknadnog

snimanja spremaju samo promijenjeni podaci.

Primjer 21. Funkcija za pomicanje neprijatelja u igri

Void Enemy_SetPosition(cEnemy *enemy, float x, float y, float

z){

enemy.m_fX=x;

enemy.m_fY=y;

enemy.m_fZ=z;

Bitvector_Set(enemys_bv, enemy.index, 1);

}

Funkcija Enemy_SetPosition iz primjera 21 prilikom svakog pozivanja pomiče neprijatelja na

zadanu poziciju te postavlja odreĎeni bit u bit vektoru na 1. Indeks bita u bitvectoru za svakog

neprijatelja je odreĎen unaprijed i spremljen u indeks varijablu unutar klase cEnemy; Bitvector

enemys_bv kreiran je unaprijed i sadrţi onoliko bitova koliko je neprijatelja u igri.

Svaki put kada bi se pozvala funkcija za quick save za svakog neprijatelja u igri bi se provjerila

vrijednost bita u bitvectoru. Ukoliko bi ta vrijednost bila 1, znači da se od posljednjeg pozivanja

quick save funkcije stanje tog neprijatelja promijenilo te bi novo stanje trebalo ponovo spremiti u

odreĎenu datoteku. Nakon toga vrijednost bita bi se ponovo postavila na 0. Ako bi vrijednost bita

bila nula, stanje tog neprijatelja ne bi bilo potrebno ponovo spremati pošto se nije promijenilo od

zadnjeg pozivanja quick save funkcije.

Page 16: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

12

4. Bitfield

Bitfield je struktura podataka slična bitvectoru kod koje svaki indeks moţe poprimiti više

vrijednosti [Penton, 2003, str. 102]. Kao i bitvector, bitfield je integer varijabla čiju veličinu u

bitovima moţemo sami odrediti i moţe biti deklarirana samo unutar klase ili strukture [Ibid, str.

102].

Primjer 22. Kreiranje bitfielda

class cPlayer{

public:

unsigned m_state : 2; Ovo je bitfiled varijabla veličine 2 bita – moţe poprimiti 4

različite vrijednosti.

};

4.1. Primjena bitfielda u igrama

U slučaju kada pojedine varijable u igri u svakom trenutku mogu zauzimati vrijednosti iz malog

intervala te kada takvih varijabli, postoji mogućnost da programer sam odabere koliko bitova će

C++ koristiti za pojedinu varijablu. Ako za više varijabli programer odabere manji broj bitova

moţe uštedjeti memorijski prostor. Pošto današnja računala dolaze opremljena sa velikim

količinama memorije takva ušteda neće bitno utjecati na performanse računala ili neće utjecati

uopće. No u slučaju da se razvija igra kod koje je potrebno slati velike količine podataka o stanju

virtualnog svijeta i igrača, ušteda koju omogućuje bitfield bi mogla biti od velike vaţnosti. Kod

takvih igara slanje prevelike količine podataka preko interneta bi mogla jako utjecati na

performanse same igre. Primjer takve igre je MMORPG2 (Massive Multiplayer Online Role-

Playing Game).

2 MMORPG je vrsta računalne igre u kojoj je veliki broj igrača u meĎusobnoj interakciji unutar virtualnog svijeta.

Igrač preuzima ulogu virtualnog lika i preuzima kontrolu na njegovim potezima. Glavna razlika izmeĎu ove vrste

igara i ostalih je u velikom brojku igrača koji sudjeluju u MMORPG-u te trajnosti virtualnog svijeta kojim se kreću.

Čak i dok igrač ne igra svijet se razvija i dalje jer je igra stalno pokrenuta na udaljenom serveru koji je obično u

vlasništvu izdavača igre.

Page 17: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

13

5. Vezane liste

Vezana lista je struktura podataka slična polju koja rješava dva najveća problema polja –

elementi se u polje ne mogu ubaciti ili izvaditi iz polja na jednostavan način i njihova veličina je

fiksna. Vezana lista se sastoji od ćelija kao i polje ali se te ćelije nazivaju čvorovi i za razliku od

polja kod kojeg se ćelije nalaze jedna do druge u memoriji i ne sadrţe ništa osim podataka u

polju, čvorovi su razbacani po memoriji i svaki čvor osim podataka sadrţi i adresu odnosno

pokazivač na sljedeći čvor u listi [Penton, 2003, str. 148]. Zbog načina na koji su vezane liste

strukturirane umetanje i brisanje pojedinih čvorova u listi je vrlo jednostavno. Postoje razne

varijacije vezanih listi a u ovom radu će biti spomenute dvije – jednostruko i dvostruko vezane

liste. Liste mogu biti implementirane na dva načina – pomoću polja i pomoću pokazivača, što će

biti prikazano u nastavku ovoga rada.

5.1. Jednostruko vezana lista

Jednostruko vezana lista je najjednostavniji oblik vezane liste kod koje svaki čvor sadrţi samo

podatke i adresu sljedećeg čvora u listi. Slika 5.1. prikazuje grafički prikaz vezane liste sa 3

čvora.

Slika 5.1. Grafički prikaz jednostruko vezane liste sa 3 čvora

Jednostruko vezana lista ima nekoliko prednosti nad poljem [Sherrod, 2007, str. 152]:

moguće je umetati čvorove u listu i brisati čvorove iz bilo kojeg dijela liste vrlo

jednostavno,

moguće je dodavati nove čvorove u listu u nedogled pod uvjetom da ima dovoljno

slobodne memorije u računalu.

Glavni nedostaci su nemogućnost pristupanja pojedinom čvoru preko indeksa i činjenica da je

jedini mogući obilazak čvorova od početka prema kraju.

Podaci Pokazivač na

sljedeći element

Page 18: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

14

5.2. Dvostruko vezana lista

Za razliku od jednostruko vezane liste, kod koje svaki čvor pokazuje na sljedeći čvor u listi,

čvorovi kod dvostruko vezane liste pokazuju na prethodni i na sljedeći čvor u listi [Penton, 2003,

str. 169]. Slika 5.2 prikazuje grafički prikaz dvostruko vezane liste sa 3 čvora.

Slika 5.2 Grafički prikaz dvostruko vezane liste sa 3 čvora

U usporedbi s poljem dvostruko vezana lista ima iste prednosti i nedostatke kao i jednostruko

vezana lista ali i omogućuje obilazak liste od kraja prema početku [Sherrod, 2007, str. 152].

5.3. Primjena vezanih listi u igrama

Glavna primjena vezanih listi u igrama je kod onih stvari koje ne ţelimo imati u ograničenom

broju. Primjerice, u RPG ţanru igre, likovi imaju mogućnost skupljanja raznih oruţja, napitaka,

opreme itd.. koji se dodaju u inventar onim redoslijedom kojim ih likovi skupljaju [Penton, 2003,

str. 177]. Primjer 23 prikazuje odsječak programskog koda koji demonstrira dodavanje novog

predmeta u inventar.

Primjer 23. Dodavanje novog predmeta u inventar

Class cItem{

int m_iType;

LPSTR m_szName;

};

class cPlayer{

list<cItem*> m_inventar;

};

cPlayer g_player;

void AddItem(cItem *item){

g_player.m_inventar.push(item);

}

Podaci Pokazivač na

sljedeći element

Pokazivač na

prethodni element

Page 19: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

15

6. Stog

Stog je apstraktni tip podatka kod kojeg se elementi dodaju i brišu samo s jednog kraja – s vrha.

Zbog toga se stog naziva i LIFO ( eng. Last In First Out) strukturom. Stog se moţe nazvati i

linearnom kolekcijom podatkovnih elemenata u kojoj su elementi poredani po vremenu koje su

proveli u stogu – najnoviji element se uvijek nalazi na vrhu, a najstariji na dnu stoga [Dale, 2003,

str. 196].

Sljedeće su operacije moguće na stogu [S. Childs, 2008, str.175]:

1) Push – dodaje novi element na vrh stoga

2) Pop – vraća element na vrhu stoga i briše ga sa stoga

3) Top - vraća element na vrhu stoga

4) MakeEmpty – kreira prazan stog

5) IsEmpty – vraća 1 ako je stog prazan inače vraća 0

6) IsFull - vraća 1 ako je stog pun tj. ako nije moguće dodati novi element na kraj stoga

(neke implementacije stoga (npr. pomoću polja) imaju unaprijed odreĎen maksimalni

broj elemenata)

Stog se moţe implementirati na više načina: pomoću polja (slika 6.2.), vezane liste (slika 6.1.)

itd.. Kod implementacije pomoću polja moguća je implementacija pomoću statičnog i

dinamičnog polja. Stog implementiran statičnim poljem ima unaprijed definiranu veličinu te

postoji mogućnost da stog bude napunjen do kraja. Nasuprot tome, implementacija pomoću

dinamičkog polja omogućuje naknadno povećanje stoga i u slučaju stog nije moguće napuniti do

kraja [S. Childs, 2008, str.176].

Slika 6.1. Grafički prikaz stoga implementiranog pomoću vezane liste

Vrh stoga Dno stoga

Page 20: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

16

.

6.1. Primjena stoga u igrama

U igrama stog se koristi u izradi izbornika. Svaka igra ima glavni izbornik koji se uglavnom

sastoji od sljedećih opcija: New Game, Load Game, Save Game, Options, Exit. Korisnik prilikom

odabira bilo koje opcije u izborniku otvara novi izbornik tzv. podizbornik koji sadrţi nove

opcije. Npr. odabirom opcije Options obično se otvara podizbornik koji sadrţi sljedeće: Sound,

Video, Controls. Pritiskom na tipku Escape (Esc) korisnik se vraća na prethodni izbornik.

Pomoću stoga ovaj mehanizam navigacije kroz izbornike u igri se implementira na sljedeći

način: svaki put kada korisnik odabere podizbornik iz trenutnog izbornika taj podizbornik se

kreira i stavlja na vrh stoga. Svaki put kada korisnik pritisne tipku Escape, trenutni izbornik se

briše sa vrha stoga te izbornik koji se nakon toga nalazi na vrhu stoga postaje novi trenutni

izbornik.

Primjer 24 prikazuje programski kod, korišten u igri koja dolazi uz rad, za kretanje korisnika

kroz glavni izbornik igre.

Primjer 24. Mehanizam kretanja kroz izbornik implementiran pomoću stoga

struct sMenuItem{

LPSTR m_szText;

DWORD m_dColor;

cMenu *m_pMenu;

sMenuItem(){

m_szText=NULL;

m_pMenu=NULL;

}

};

class cMenu{

public:

int m_iCount;

int m_iLeft;

int m_iTop;

sMenuItem *m_pItems;

cMenu(){}

cMenu(int count){

m_iCount=count;

m_pItems=new sMenuItem[count];

}

14 22 7 39

Dno stoga Vrh stoga

Slika 6.2. Grafički prikaz stoga implementiranog pomoću polja

Page 21: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

17

};

stack<cMenu*> menus1;

stack<cMenu*> menus2;

stack<cMenu*> *menus;

void ProcessMenu(){

if(dbEscapeKey()){

if(menus->size()>1) menus->pop();

}

cMenu *menu=menus->top();

LPSTR text="";

if(dbMouseClick()==0) g_iM=0;

for(int i=0; i<menu->m_iCount; i++){

dbInk(dbRGB(0,255,0),dbRGB(255,255,255));

int x=dbMouseX(), y=dbMouseY();

int width=dbTextWidth(menu->m_pItems[i].m_szText);

int height=dbTextHeight(menu->m_pItems[i].m_szText);

if(x>menu->m_iLeft && x<menu->m_iLeft+width){

if(y>menu->m_iTop+(20*i) && y<menu->m_iTop+(20*i)+height){

dbInk(dbRGB(255,0,0),dbRGB(255,255,255));

if(dbMouseClick()==1 && g_iM==0) {

g_iM=1;

text=menu->m_pItems[i].m_szText;

if(menu->m_pItems[i].m_pMenu){

menus->push(menu->m_pItems[i].m_pMenu);

}

}

}

}

dbText(menu->m_iLeft,menu->m_iTop+(20*i),menu-

>m_pItems[i].m_szText);

}

if(strcmp(text,"Easy")==0){

g_iGO=1; menus->pop(); g_iResourceCount=15;

InitLevel();

}

if(strcmp(text,"Medium")==0){

g_iGO=1; menus->pop(); g_iResourceCount=5;

InitLevel();

}

if(strcmp(text,"Hard")==0){

g_iGO=1; menus->pop(); g_iResourceCount=0;

InitLevel();

}

if(strcmp(text,"Exit")==0) exit(0);

if(strcmp(text,"Resume")==0) g_iGO=1;

if(strcmp(text,"Exit to main menu")==0){g_iGO=0;

menus=&menus1;}

}

Page 22: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

18

7. Red

Red je homogena grupa elemenata na koju se elementi dodaju na jedan kraj koji se naziva

začelje (eng. End ili Rear), a uzimaju na drugom kraju pod nazivom čelo (eng. Front) [N.

Kasiviswanath, 2007, str. 79]. Zbog toga se red takoĎer naziva i FIFO (eng. First in First Out)

strukturom.

Sljedeće operacije su moguće na redu [Dale, 2003, str. 198]:

1) Enqueue – dodavanje novog elementa na kraj reda

2) Dequeue – brisanje elementa s početka reda

3) Front – vraća element na početku reda

4) IsEmpty – vraća 1 ako je red prazan inače vraća 0

5) IsFull – vraća 1 ako je red pun tj. ako nije moguće dodati novi element na kraj reda (neke

implementacije reda (npr. pomoću polja) imaju unaprijed odreĎen maksimalni broj

elemenata)

6) MakeEmpty – kreira prazan red

Red je, kao i stog, moguće implementirati na više različitih načina, primjerice pomoću polja

(slika 7.1.), vezane liste (slika 7.2.) itd.

Slika 7.1. Grafički prikaz reda sa 5 elemenata implementiranog pomoću polja

Čelo Začelje

0 1 2 3 4

Čelo Začelje

7.2. Grafički prikaz reda sa 3 elementa implementiranog pomoću vezane liste

Page 23: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

19

Postoje 4 vrste reda [Sherrod, 2007, str. 173-182]:

1) Obični red kod kojeg se elementi dodaju na jedan kraj a brišu sa drugog (slika 7.1)

2) Dvostruki red kod kojeg se elementi mogu dodati i brisati sa oba kraja

3) Kruţni red kod kojeg se elementi, u slučaju da je red već pun, dodaju na popunjena

mjesta u redu pri čemu se elementi koji su u redu prebrišu s novo dodanim elementima

(slika 7.3)

4) Prioritetni red kod kojeg su elementi poredani po prioritetu

Slika 7.3. Grafički prikaz kruţnog reda [prilagoĎeno prema Penton, 2003, str. 209]

U primjeru igre koja dolazi uz ovaj rad korišten je STL3 red koji je implementiran pomoću reda s

dvostrukim krajem (eng. double-ended queue ili deque).

7.1. Primjena reda u igrama

Redovi imaju najčešću primjenu u RTS (Real time Strategy) igrama odnosno strategijama u

realnom vremenu u kojima igrač raspolaţe raznim borbenim i ne borbenim jedinicama (npr.

tenkovi, vojnici, tvornice) te ima mogućnost nareĎivanja pojedinim jedinicama da nešto rade

3 Programski jezik C++ ima standardni set predloţaka klasa koji su poznati pod nazivom Standard Template Library

(STL). Ta biblioteka klasa se koristi za odrţavanje i ponovno korištenje koda i sastoji se od učinkovito dizajniranih

komponenti i algoritama koji se često mogu vidjeti u kompjuterskom programiranju. Jedan od glavih ciljeva STL-a

je abstrakcija i učinkovitost. To omogućava korištenje STL-a u velikom broju aplikacija. [Allen Sherrod, 2007, str.

11]

1

2

3

4

6

7

8

5

Čelo

Začelje

Stvarna granica

polja

Page 24: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

20

(npr. odu s jednog mjesta na drugo, napadnu neprijateljske jedinice). Te naredbe se skupljaju u

red i onim redom kojim ih je igrač zadao se izvršavaju. Neke od poznatijih igara koje spadaju u

tu kategoriju su: Warcraft, Starcraft i Command & Conquer. U primjeru 25 je prikazan odsječak

programskog koda iz igre koja dolazi uz ovaj rad a sluţi dodavanje naredbi u red koje igrač

izdaje svojim jedinicama.

Primjer 25. Dodavanje naredbi na kraj reda

class cCommand{

public:

int m_iType;

int m_iTarget;

float m_fX, m_fY, m_fZ;

cCommand(){}

~cCommand(){}

};

class cUnit{

public:

int m_iObj;

int m_iObj2;

int m_iHealth;

int m_iAmmo;

int m_iStatus;

int m_iStatic;

int m_iType;

int m_iTemp;

queue<cCommand*> commands;

cUnit(){

m_iTemp=0;

}

~cUnit(){}

};

cCommand *naredba=new cCommand;

naredba->m_iType=0;

naredba->m_fX=dbObjectPositionX(g_iMarker);

naredba->m_fY=dbObjectPositionY(g_iMarker);

naredba->m_fZ=dbObjectPositionZ(g_iMarker);

unit->commands.push(naredba);

Page 25: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

21

8. Hash tablice

Hash tablica je struktura podataka koja omogućuje vrlo brze operacije umetanja elemenata i

traţenja elemenata koji se već nalaze u tablici [Sherrod, 2007, str. 210]. Većina operacija nad

hash tablicom ima sloţenost od O(1) [Ibid, str. 210]. Grafički prikaz hash tablice prikazan je na

slici 8.1.

Slika 8.1. Hash tablica [prilagoĎeno prema Sherrod, 2007, str. 210]

Hash tablice su brze strukture podataka. Čak i kod velikog broja elemenata, potraga za nekim

elementom u tablici moţe biti instantna. Uzrok te brzine leţi u činjenici da su hash tablice

bazirane na strukturi polja. Kada je indeks u polju nekog elementa poznat, traţenje tog elementa

u hash tablici nije ništa drugo nego čitanje elementa iz polja. Obzirom da se hash tablice baziraju

na polju, one takoĎer nasljeĎuju sve prednosti i mane koje polje ima.

Sljedeće činjenice vrijede za hash tablice [Sherrod, 2007, str. 211]:

1) Promjena veličine hash tablice je komplicirana i vremenski zahtjevna

2) Elementi u tablici se ne mogu jednostavno poredati

3) Traţenje elemenata u tablici je vrlo brzo

4) Kopiranje hash tablica je sporo i nuţno je da tablica koja se kopira i tablica u koju se

kopira budu iste veličine

5) Dodavanje novih elemenata u hash tablicu je brzo

Objekt

Objekt

Objekt poslan u hash funkciju

HASH TABLICA

Objekt smješten u

hash tsblicu na

indeks generiran u

hash funkciji

Page 26: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

22

Princip rada hash tablice je sljedeći [Ibid, str. 211]:

svaki objekt koji se ţeli dodati u hash tablicu ima vlastiti ključ,

ključ je oznaka tog objekta koja je pretvorena u indeks u polju hash tablice,

za ključ nekog objekta moţe se upotrijebiti bilo što, pa čak i sam objekt.

8.1. Hash funkcija

Kod koji se koristi za pretvaranje ključa u indeks zove se hash funkcija (slika 8.2.).

Slika 8.2. Grafički prikaz pretvaranja ključa u indeks [prilagoĎeno prema Sherrod, 2007, str. 211]

Učinkovitost hash funkcije je vrlo vaţna. Korištenje loše hash funkcije moţe dovesti do kolizije

u hash tablici. Kolizija se javlja kad hash funkcija pretvori više od jednog ključa u isti indeks

[Sherrod, 2007, str. 215]. Kada doĎe do kolizije programer moţe učiniti jedno od sljedećeg [Ibid,

str. 215]:

1) Ne dodati objekt u hash tablicu

2) Zamijeniti objekt u tablici s onim koji u tablicu treba biti dodan

3) Pronaći novi indeks za objekt koristeći tehniku otvorenog adresiranja (eng. Open

addressing)

4) Napraviti hash tablicu tako da omogućuje smještaj više od jednog objekta na pojedinom

indeksu u tablici

Kolizije koje se dogaĎaju u tablici mogu imati poguban učinak na performanse tablice te stoga

hash funkcija mora biti učinkovita. Nijedna hash funkcija ne moţe garantirati da do kolizija neće

doći, ali kada do njih doĎe, potrebno ih je riješiti jednom od dvije glavne metode [Ibid, str. 215-

217]:

1) Open addressing – ukoliko se dogodi kolizija tijekom umetanja novog objekta u hash

tablicu traţi se nova pozicija za objekt. To se radi sekvencijalnim pretraţivanjem hash

tablice dok se ne pronaĎe prva slobodna pozicija u tablici.

OBJEKT Hash

funkcija

OBJEKT

INDEKS

U POLJU

Page 27: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

23

2) Separate chaining – umjesto traţenja praznog elementa u tablici kod ove metode svaka

ćelija u hash tablici je zapravo vezana lista. Ukoliko i doĎe do kolizije, objekt se

jednostavno doda na kraj vezan liste.

8.2. Hash vrijednost

Hash funkcija je algoritam koji neku vrijednost pretvori u brojčanu i to u onaj broj koji je veći od

0 i manji od zadnjeg indeksa u hash tablici [Smith, 2004, str. 178]. Ta vrijednost se naziva ključ

a on moţe biti string, broj ili nešto treće. Hash vrijednost pojedinog ključa ovisi o veličini hash

tablice. U slučaju da povećamo hash tablicu sve hash vrijednosti koje se nalaze u tablici postat će

nevaljane te će se ponovo morati pretvarati u nove.

Kod pretvaranja brojčane vrijednosti u hash vrijednost, moţe se koristiti operator modulo u

kombinaciji sa veličinom hash tablice kako bi hash vrijednost bila u onom rasponu indeksa koji

postoje u hash tablici.

Primjer 26. Pretvaranje brojčane vrijednosti u hash vrijednost

int hash=key % m_size;

Što je veća hash tablica, to su manje šanse da doĎe do kolizija. Grafički prikaz izračuna hash

funkcije prikazan je na slici 8.3.

Slika 8.3. Primjer hash funkcije na hash tablici sa 23 elementa [prilagoĎeno prema Allen Sherrod, 2007, str.

214]

Osim brojeva, još jedan tip podatka se često sluţi za pretvaranje u hash vrijednosti – riječ je o

stringu. Primjer 27 prikazuje hash funkciju za pretvaranje stringova u hash vrijednosti kod kojeg

dolazi do malo kolizija:

Primjer 27. Pretvaranje stringa u hash vrijednost

unsigned long int StringHash( const char* p_string ){

unsigned long int hash = 0;

112 Hash

funkcija 20

112 % 23

Page 28: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

24

int i;

int length = strlen( p_string );

for( i = 0; i < length; i++ ){

hash += ( (i + 1) * p_string[i] );

}

return hash;

}

Ova metoda se bazira na činjenici da je svaki znak u stringu zapravo cijeli broj izmeĎu 0 i 255

(slika 8.4.).

Slika 8.4. String predstavljen pomoću brojeva

8.3. Primjena hash tablica

Hash tablice imaju mnoge primjene u generalnom računalnom programiranju i u razvoju igara.

Neke od primjena hash tablica su sljedeće [Sherrod, 2007, str 212]:

1) Programi za provjeru pravopisa

2) Sustavi baza podataka

3) Rječnici

4) Telefonski imenici

5) Implementacija tablice simbola u skriptnom jeziku za igre ili u generalnom programiranju

6) Implementacija transpozicijske tablice u igri šaha

7) Lista igrača u MMORPG (Massively Multiplayer Online Role-Playing Game) igri

8) Čuvanje podataka o resursima koje igra koristi

8.3.1. Primjena hash tablica u igrama

Postaje sve uobičajenije da uz igre dolaze i alati koji omogućuju korisnicima da dizajniraju nove

mape ili likove za igru. U tim alatima korisnici imaju mogućnost da resurse (zvukovi, teksture)

koje će igra koristiti navedu po imenu. Kada se hash tablica ne bi koristila, svaki put kada bi

korisnik naveo ime resursa, igra bi morala pretraţiti sve učitane resurse da vidi da li je pojedini

resurs već učitan [Penton, 2003, str. 235]. Pošto većina igara sadrţi velike količine resursa, takvo

pretraţivanje bilo bi jako sporo, što bi loše djelovalo na njihove performanse. Uz upotrebu hash

tablica takva pretraţivanja nisu potrebna jer naziv pojedinog resursa moţe posluţiti kao ključ

[Ibid, str. 235]. U tom slučaju svaki element hash tablice bi sadrţavao dva podatka – ime resursa

P O Z D R A V

80 79 90 68 82 65 86

Page 29: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

25

i pokazivač na adresu u memoriji gdje je resurs pohranjen. Svaki puta kada bi trebalo učitati novi

resurs njegov naziv bi pomoću hash funkcije bio pretvoren u hash vrijednost. Ako bi element u

hash tablici, koji odgovara toj hash vrijednosti bio prazan značilo bi da taj resurs još nije učitan

te bi ga bilo potrebno učitati. Nasuprot tome, ako bi element bio popunjen, ne bi bilo potrebno

ponovo učitavati resurs već bi se adresa već prije učitanog resursa pročitala iz hash tablice.

Primjer 28 prikazuje programski kod potreban za učitavanje resursa i njegovo spremanje u

odgovarajući indeks u hash tablici.

Primjer 28. Programski kod za učitavanje resursa

struct cTableEntry{

LPSTR m_szName;

int m_iIndex;

};

list<cTableEntry*> hash_tablica[32];

unsigned long int StringHash( const char* p_string ){

unsigned long int hash = 0;

int i;

int length = strlen( p_string );

for( i = 0; i < length; i++ ){

hash += ( (i + 1) * p_string[i] );

}

return hash;

}

void Object_SetTexture(int obj, LPSTR tex){

int found=0;

int hash_value=StringHash(tex) % 32;

if(hash_tablica[hash_value].empty()==false){

list<cTableEntry*>::iterator i=hash_tablica[hash_value].begin();

while(i!=hash_tablica[hash_value].end()){

cTableEntry *entry=*i;

if(strcmp(entry->m_szName,tex)==0){

found=entry->m_iIndex;

}

i++;

}

}

if(found==0){

found=free_image();

dbLoadImage(tex,found);

cTableEntry *entry=new cTableEntry();

entry->m_iIndex=found;

entry->m_szName=tex;

hash_tablica[hash_value].push_back(entry);

}

dbTextureObject(obj,found);

}

Page 30: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

26

9. Rekurzija

U računalnom programiranju postoji mogućnost da jedna funkcija pozove sama sebe. Kada bi

programer u svojem programu napisao takvu funkciju bez mogućnosti da se takvo pozivanje u

odreĎenom trenutku prekine u programu mogla bi nastati beskonačna petlja koja bi se izvršavala

sve dok se nasilno ne prekine. Kada se u takvu beskonačnu petlju doda mogućnost nenasilnog

prekidanja dobije se rekurzija [Sherrod, 2007, str. 74]. Rekurzija ima mnoge korisne primjene u

programiranju i moţe biti ključna u dizajniranju programskog koda. Svrha rekurzivne funkcije je

pronalazak rješenja malog djelića velikog problema i svaki put kada se funkcija rekurzivno

pozove novi dio problema biva riješen [Ibid, str. 74].

Postoje dvije vrste rekurzije [Dale, 2003, str. 400]:

1) Direktna – kada funkcija zove sama sebe

2) Indirektna – kada jedna ili više funkcija poziva funkciju unutar koje su one pozvane

Rekurzija je moćna programerska tehnika, ali programer mora biti oprezan kada je koristi jer

rješenja pomoću rekurzije mogu biti sporija od rješenja pomoću iteracije [Ibid, str. 401].

Primjer 29 prikazuje rekurzivnu funkciju koja sluţi za izračunavanje y potencije broja x.

Primjer 29. Funkcija za izračunavanje y potencije broja x

int power(int x, int y)

{

if(y==0) return 1;

else{

return x*power(x,y-1);

}

}

9.1. Primjena rekurzije u igrama

Ponekad da bi se postigao odreĎeni efekt u igrama je objekte koji sačinjavaju virtualni svijet

potrebo renderirati odreĎenim redoslijedom. Jedan od takvih efekata je transparentnost kod kojeg

je potrebno objekte renderirati od onog najudaljenijeg od igrača do onog najbliţeg. Jedini način

da se odredi takav redoslijed je sortiranje niza objekata po njihovoj udaljenosti od igrača. Budući

da igrač u igri neprestano mijenja svoju poziciju takvo sortiranje je potrebo izvršavati više

desetaka puta u sekundi. Zbog toga je potrebno da algoritam sortiranja bude vrlo brz. Upravo

takav je quick sort algoritam koji se temelji na rekurziji i njegov kod je prikazan u primjeru 30.

Page 31: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

27

Primjer 30. Quick sort algoritam

void q_sort(int array[], int left, int right){

int pivot, l_hold, r_hold;

l_hold = left;

r_hold = right;

pivot = array[left];

while (left < right){

while ((array[right] >= pivot) && (left < right))

right--;

if(left != right){

array[left] = array[right];

left++;

}

while ((array[left] <= pivot) && (left < right))

left++;

if(left != right){

array[right] = array[left];

right--;

}

}

array[left] = pivot;

pivot = left;

left = l_hold;

right = r_hold;

if (left < pivot)

q_sort(array, left, pivot-1);

if (right > pivot) q_sort(array, pivot+1, right);

}

void quickSort(int array[], int array_size){

q_sort(array, 0, array_size - 1);

}

Page 32: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

28

10. Stabla

U računalnoj znanosti, stablo je struktura podataka koja je formirana u neku smislenu formaciju

[Sherrod, 2007, str. 286]. Početni dio stabla naziva se korijen. Iz korijena izlaze čvorovi koji su

posloţeni u hijerarhiju, a meĎusobno su povezani rubovima [Penton, 2003, str. 331]. Rubovi su u

C++-u predstavljeni pokazivačima (ako se radi o implementaciji stabla pomoću pokazivača) koji

pokazuju na druge čvorove u hijerarhiji, slično pokazivačima kod vezanih listi. Rubovi koji

izlaze iz korijena još se nazivaju i grane. Osim pokazivačima, rubovi mogu biti predstavljeni i

indeksima ukoliko se radi o implementaciji stabla pomoću polja. Grafički prikaz strukture

podataka stabla moguće je vidjeti na slici 10.1.

Slika 10.1. Grafički prikaz stabla

10.1. Dijelovi stabla

Vrstu stabla odreĎuju njegovi dijelovi [Sherrod, 2007, str. 287]. Općenito stablo se sastoji od

čvorova i rubova. Rubovi mogu biti bilo koji način povezivanja čvorova – pokazivačima ili

indeksima. Svaki čvor je podstablo sa svojim podacima i rubovima. Veze izmeĎu čvorova su tipa

roditelj-dijete. U općenitom stablo svaki čvor moţe sadrţavati proizvoljan broj čvorova djece.

Dijelovi stabla mogu se vidjeti na slici 10.2.

Korijen

Dijete 1 Dijete 2 Dijete 3

Page 33: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

29

Slika 10.2. Dijelovi stabla [Penton, 2003, str. 331]

U tabeli 10.1. navedeni su termini koji se koriste za opis stabala.

Tabela 10.1. Termini za opis stabala [Ron Penton, 2003, str. 331 i Allen Sherrod, 2007, str. 288]

Termin Opis Primjer (slika 10.2.)

Korijen Najgornji čvor u stablu Čvor A je korijen stabla

Dijete Čvor ispod drugog čvora na istoj grani stabla B je dijete od A

Roditelj Čvor iznad drugog čvora na istoj grani B je roditelj od C

Brat Čvor na istoj razini sa drugim čvorom C je brat od D

List Čvor bez djece C i D su listovi

Razina Opisuje visinu čvora A je na nultoj razini, B na

prvoj, C i D na drugoj

Podstablo Stablo sadrţano unutar drugog stabla B je korijen podstabla stabla A

Ključevi Ključ se koristi kako bi se odredilo na koji

način će se dodati novi čvor u stablo. Ne koriste

sva stabla ključeve, samo neka (npr. binarno

stablo)

Obilazak Obilazak stabla je proces pomicanja kroz

čvorove stabla s ciljem provoĎenja nekog

algoritma na stablu

Stabla se smatraju rekurzivnim strukturama podataka jer je svako dijete u stablu stablo za sebe

[Penton, 2003, str. 332] (slika 10.3.).

a

b

c d

Page 34: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

30

Slika 10.3. Stablo koje demonstrira rekurzivnu prirodu stabala, čvorovi b i c su stabla za sebe [Penton, 2003,

str. 331]

10.2. Vrste stabala

Postoje razne vrste stabala od kojih svaka ima svoju primjenu.

Neka od poznatijih vrsta su [Sherrod, 2007, str. 289]:

Općenito hijerarhijsko stablo

Binarno stablo

Kd - stablo

Crveno - crno stablo

Hrpa

Graf scene

BSP (Binary Space Partitioning) stablo

Quad-stablo (quad-tree)

Oc-stablo (octree)

10.3. Binarno stablo

Binarno stablo je stablo kod kojeg svaki čvor moţe imati najviše 2 čvora kao svoju djecu

[Penton, 2007, str. 360]. Ti čvorovi se obično nazivaju lijevo i desno dijete. Slika 10.4. prikazuje

čvor u binarnom stablu.

a

b c

Page 35: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

31

Slika 10.4. Čvor u binarnom stablu

Sljedeća svojstva su karakteristična za binarna stabla [Penton, 2003, str. 361-362]:

1. Punoća – binarno stablo moţe biti puno. Zbog činjenice da svaki čvor moţe imati najviše

dvoje djece, moguće je napuniti stablo tako da se više ne mogu dodavati novi čvorovi bez

da se poveća visina stabla (slika 10.5.)

2. Gustoća – binarno stablo moţe biti i gusto. Gustoća se postiţe dodavanjem novih čvorova

na najdoljnjoj razini stabla prvo na lijevu stranu odnosno kao lijevo dijete

3. Balansiranost – balansirano binarno stablo je stablo kod kojeg svaki čvor ima otprilike

isti broj čvorova na lijevoj i na desnoj strani

Slika 10.5. Puno binarno stablo

Lijevo dijete Desno dijete

Roditelj

Page 36: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

32

Slika 10.6. Gusto binarno stablo

10.4. Binarno stablo pretraživanja

Binarno stablo pretraţivanja je posebna vrsta binarnog stabla kod kojeg se čvorovi dodaju po

posebnom algoritmu tako da je kasnije pretraţivanje tog stabla vrlo jednostavno i brzo.

Smještaj novog čvora prilikom operacije dodavanja ovisi o ključu. Ukoliko je vrijednost ključa

čvora kojeg ţelimo dodati manja od vrijednosti ključa čvora kojem dodajemo dijete, taj dodani

čvor će postati lijevo dijete, a ako je vrijednost ključa veća onda će postati desno dijete [Kutti i

Padhye, 2004, str. 165]. Slika 10.7. prikazuje dodavanje novog čvora u binarno stablo

pretraţivanja s ključem čija je vrijednost 23.

Slika 10.7. Dodavanje novog čvora u binarno stablo pretraţivanja [Allen Sherrod, 2007, str. 300]

Iz slike se takoĎer vidi da nije potrebno puno usporedbi da bi se našlo mjesto na koje treba

dodati novi čvor. Što je stablo veće, to će biti efikasnije prilikom izvoĎenja raznih algoritama.

40

30 46

23

Page 37: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

33

Primjerice, kod stabla sa milijun čvorova prilikom traţenja mjesta za novi čvor trebalo bi

napraviti najviše 20 usporedbi. Broj usporedbi takoĎer ovisi i o tome da li je stablo balansirano

ili nije. Najgori mogući scenarij kod nebalansiranog stabla je kada su vrijednosti koje se dodaju

već sortirane zbog čega bi svi dodani čvorovi bili smješteni sa samo jedne strane stabla. Kod

takvog stabla pretraţivanje bi bilo isto kao i kod vezane liste – sekvencijalno.

Slika 10.8. Najgori slučaj nebalansiranog stabla

10.5. Primjena stabala u igrama

U razvoju računalnih igara, stabla imaju razne primjene. Sluţe za ubrzavanje renderiranja scene,

ubrzavanje fizike u stvarnom vremenu, ubrzavanje detekcije kolizija, za ubrzavanje svjetlosnih

efekata, itd..

Graf scene je općenita struktura podataka koja se koristi za opis veza izmeĎu objekata u

virtualnim svjetovima [Sherrod, 2007, str. 449]. Veze izmeĎu objekata formiraju hijerarhiju u

kojoj su čvorovi meĎusobno povezani rubovima i mogu predstavljati materijale, odnose izmeĎu

fizičkih podataka, odnose izmeĎu pozicijskih podataka itd. Slika 10.9. prikazuje primjer grafa

scene.

45

36

20

15

Page 38: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

34

Slika 10.9. Graf scene [Sherrod, 2007, str. 449]

Na grafu scene, struktura podataka moţe biti implementirana pomoću grafa ili stabla. Svaki čvor

u stablu moţe imati proizvoljan broj djece, ali samo jednog roditelja. Prema tome, kada je riječ o

implementaciji pomoću stabla, jedina moguća implementacija je pomoću općenitog stabla.

BSP (Binary Space Partitioning) stablo je struktura podataka kod koje se uzima set poligona koji

predstavljaju pojedini nivo igre te se od njih napravi odreĎena hijerarhija kako bi procesiranje

scene tijekom igre bilo brţe [Sherrod, 2007, str. 460]. U BSP stablu čvorovi djeca se obično

nazivaju prednji i straţnji čvor. BSP rekurzivno rascjepljuje virtualnu scenu na dva dijela.

Odabere se neka ravnina te se svaki poligon u nivou testira da se vidi s koje strane ravnine se

nalazi. Ako se poligon nalazi samo sa jedne strane, onda se on stavlja na jednu polovicu scene.

MeĎutim, ako se poligon nalazi s obje strane ravnine, on se prepolovi tako da se jedan njegov dio

nalazi s jedne, a drugi dio s druge strane ravnine [Ibid, str. 461]. Postupak se ponavlja sve dok se

neki odreĎeni uvjet ne ispuni (npr. dok se ne dosegne odreĎeni broj poligona u čvoru). Mnoge

popularne igre koriste BSP stabla za poboljšanje performansi. Neke od njih su Quake 4 i Doom

3.

Quad stablo je struktura podataka kod koje se virtualna scena dijeli na četiri jednaka dijela te se

zatim rekurzivno svaki taj dio dijeli na nova četiri jednaka dijela [Ibid, str. 466]. Taj postupak se

nastavlja sve dok se ne zadovolji neki uvjet. Svaki taj dio predstavlja jedan čvor u stablu te se

prilikom svakog dijeljenja odreĎuje koji se sve poligoni nalaze u kojem dijelu.

Root

World

pos World

pos

Texture

1 Texture

2

Object

1 Object

2 Object

3 Object

4

Page 39: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

35

Slika 10.10. Quad stablo [Sherrod, 2007, str. 467]

Quad stabla se takoĎer mogu koristiti za kreiranje terena kod kojeg čvorovi sadrţe nekoliko

verzija virtualnog svijeta. [Ibid, str. 470]. Verzije se meĎusobno razlikuju po količini detalja

odnosno broju poligona. Koja verzija virtualnog svijeta u pojedinom čvoru će se renderirati ovisi

o udaljenosti čvora od igrača. Što je čvor udaljeniji od igrača to su i detalji u njemu manje

vidljivi igraču pa nije potrebno renderirati najdetaljniju verziju. Na taj način se smanjuje broj

poligona koji se trebaju renderirati te time performanse igre postaju bolje.

Page 40: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

36

11. Hrpa

Hrpa je posebna vrsta binarnog stabla kod kojeg je vrijednost u svakom čvoru veća ili manja od

vrijednosti u čvorovima svoje djece [Penton, 2003, str. 410]. U slučaju da je veći radi se o max

hrpi, a u slučaju da je manju radi se o min hrpi. Primjer max hrpe nalazi se na slici 11.1.

Slika 11.1. Max hrpa

Postoje tri glavne karakteristike hrpe:

1) Hrpa je binarno stablo,

2) Hrpa je kompletna struktura podataka (čvorovi su potpuno napunjeni od lijeve strane

prema desnoj),

3) Vrijednost u svakom čvoru hrpe je veća ili jednaka od vrijednosti u čvorovima njegove

djece ako se radi o max hrpi, odnosno manja ili jednaka ukoliko se radi o min hrpi.

Prethodno nabrojane karakteristike ili pravila mora zadovoljavati svako stablo da bi se moglo

nazvati hrpom.

Hrpa je slabo sortirano binarno stablo jer iako su vrijednosti čvorova djeca svakog čvora manja

ili veća od vrijednosti svojeg roditelja, ta djeca nisu posloţena po nekom odreĎenom redoslijedu

[Sherrod, 2007, str. 329]. Usprkos tome, svrha strukture podataka hrpe je omogućavanje brzog

dodavanja novih čvorova. Prilikom dodavanja novog čvora, taj čvor se smješta na dno hrpe

(slika 11.2.). Nakon toga čvor se miče gore kroz hrpu dok se ne naĎe odgovarajuće mjesto tako

da sva pravila hrpe budu zadovoljena.

90

79 82

55 50 69 75

Page 41: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

37

Slika 11.2. Dodavanje novog čvora u hrpu [Allen Sherrod, 2007, str. 330]

U slučaju brisanja čvorova uvijek se briše onaj čvor koji je na vrhu hrpe odnosno u korijenu.

Prilikom brisanja najgornjeg čvora u hrpi ostaje rupa koja se popunjava najdoljnjim čvorom u

hrpi koji se zatim miče dolje kroz hrpu dok mu se ne naĎe odgovarajuće mjesto u hrpi kako bi se

zadovoljila sva pravila hrpe [Sherrod, 2007, str. 330] (slika 11.3.).

Slika 11.3. Brisanje čvora sa hrpe [prilagoĎeno prema Sherrod, 2007, str. 330]

100

50 40

15 35 27 13

Korijen Prije brisanja

čvora sa

vrijednošću 100

50

35 40

15 13 27

Korijen Nakon brisanja

čvora sa

vrijednošću 100

100

50 40

15 35 27 13

Korijen

Dodani

čvor

Page 42: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

38

Zbog toga što se najveća vrijednost uvijek nalazi u korijenu hrpa se moţe koristiti i kao

prioritetni red. Dokazano je da je hrpa najbrţa implementacija prioritetnog reda [Penton, 2003,

str. 416]. Tabela 11.1. prikazuje broj usporedbi potreban za ubacivanje i brisanje čvora iz

prioritetnog reda za dvije različite implementacije.

Tabela 11.1. Broj usporedbi prilikom brisanja i dodavanja čvorova u prioritetni red implementiran pomoću

vezane liste i hrpe

Broj čvorova Ubacivanje Brisanje Zbroj

lista hrpa lista hrpa lista hrpa

7 7 3 0 6 7 9

15 15 4 0 8 15 12

31 31 5 0 10 31 15

63 63 6 0 12 63 18

127 127 7 0 14 127 21

Hrpe nemaju nikakvu direktnu primjenu u igrama, ali zato implementacija prioritetnog reda

pomoću hrpe ima. Naime, u igrama je najvaţnije da se pojedini algoritam izvrši što brţe a hrpa je

najbrţa implementacija prioritetnog reda. U RTS (Real Time Strategy) igrama poput Warcrafta

ili Starcrafta, igrač ima mogućnost gradnje tvornica kojima zatim ima mogućnost zadavanja

gradnje nekih jedinica [Penton, 2003, str. 429]. Pošto su neke jedinice igraču vaţnije od drugih,

svakoj se jedinici moţe dodijeliti prioritet te će tako, ukoliko igrač tvornici zada gradnju više

različitih jedinica, tvornica uvijek prvo graditi onu jedinicu koja je najvaţnija odnosno onu koja

se nalazi na početku prioritetnog reda.

Page 43: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

39

12. Grafovi

Ako uzmemo stablo, kod kojeg svaki čvor pokazuje samo na svoju djecu, i dodamo mogućnost

da svaki čvor pokazuje na bilo koji drugi čvor, dobijemo graf [Penton, 2003, str. 482]. Dakle graf

je struktura podataka bazirana na čvorovima kod koje svaki čvor moţe pokazivati na bilo koji

drugi čvor. Slika 12.1. prikazuje primjer grafa.

Slika 12.1. Graf

Stablo i graf su slične strukture podataka [Ibid, str. 482]:

1) Imaju čvorove u kojima su smješteni objekti,

2) Imaju rubove, ali se oni nazivaju lukovi,

3) Imaju čvorove koji su meĎusobno povezani te

4) Omogućuju obilazak čvorova koji se koristi kod raznih algoritama

Glavna razlika izmeĎu stabla i grafa je u tome što čvorovi u stablu mogu imati samo jednog

roditelja, dok čvorovi grafa mogu imati proizvoljan broj roditelja.

12.1. Vrste Grafova

Postoji puno različitih vrsta grafova. U ovom radu će biti opisani tri najpoznatije vrste:

dvosmjerni, jednosmjerni, te teţinski graf [Ibid, str. 483].

12.1.1. Dvosmjerni graf

Ovo je najjednostavniji oblik grafa kod kojeg svaki luk pokazuje na dva čvora [Ibid, str. 483].

Slika 12.2. prikazuje primjer dvosmjernog grafa.

1

2

3

4

5

Page 44: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

40

Slika 12.2. Dvosmjerni graf

12.1.2. Jednosmjerni graf

Kod ove vrste grafa, svaki luk pokazuje na samo jedan čvor [Ibid, str. 483]. Slika 12.3. prikazuje

primjer jednosmjernog grafa.

Slika 12.3. Jednosmjerni graf

12.1.3. Težinski graf

Na teţinskom grafu svaki luk ima dodijeljenu teţinu [Ibid, str. 484]. Primjer teţinskog grafa

nalazi se na slici 12.4.

1

2

3

4

1

2

3

4

Page 45: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

41

Slika 12.4. Teţinski graf [Ron Penton, 2003, str. 484]

Slika prikazuje kartu SAD-a na kojoj je 6 gradova prikazano pomoću čvorova a lukovi izmeĎu

njih imaju dodijeljene teţine gdje svaka teţina predstavlja udaljenost izmeĎu 2 čvora koja

pojedini luk povezuje.

12.2. Implementacija grafa

Graf je moguće implementirati na nekoliko različitih načina [Penton, str. 486-491]:

1) Adjacency tablice – kod ove metode koriste se dvodimenzionalna polja. Slika 12.5.

prikazuje adjacency tablicu za sliku 12.4. Da bi preko tablice saznali teţinu izmeĎu dva

različita grada treba naći stupac na x osi gdje se nalazi prvi grad i red na y osi u kojem se

nalazi drugi grad – ćelija u tablici gdje se stupac i redak sijeku predstavlja teţinu izmeĎu

ta dva grada.

New

York

Atl

anta

Den

ver

Sea

tlle

Dal

las

Lo

s

Ang

eles

New York 850 1800

Atlanta 850 800

Denver 1800 1350 1050

Seatlle 1350

Dallas 800

Los Angeles 1050

Slika 12.5. Adjacency tablica za primjer na slici 12.4. [Ron Penton, 2003, str. 487]

Page 46: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

42

2) Smjerne tablice – kod ove metode se takoĎer koriste dvodimenzionalna polja, a

pretpostavka je da postoji odreĎeni broj lukova koji mogu izlaziti iz svakog čvora te da ni

jedan čvor nema više lukova od tog broja. Slika 12.6. prikazuje primjer grafa i

pripadajuće smjerne tablice. Način na koji radi ova tablica je sljedeći:

a. na x osi su navedeni svi mogući smjerovi koje pojedini luk iz svakog čvore moţe

imati,

b. na y osi su navedeni čvorovi,

c. u svakom stupcu za svaki čvor je navedena teţina pojedinog luka,

d. ukoliko teţina nije navedena znači da taj luk u dotičnom čvoru ne postoji.

Slika 12.6. Graf i njegova smjerna tablica [Ron Penton, 2003, str. 488]

3) Vezani grafovi opće namjene:

a. Dvosmjerni graf - kod ove metode struktura grafa se sastoji od dva dijela – prvi

dio predstavlja čvorove u grafu koji se mogu drţati u polju ili vezanoj listi, a

drugi dio predstavlja lukove koji isto tako mogu biti u polju ili u vezanoj listi.

Čvorovi grafa sluţe za drţanje podataka o pojedinom čvoru, a lukovi sadrţavaju

dva pokazivača na čvorove koje povezuju.

Page 47: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

43

Slika 12.7. Dvosmjerni vezani graf

b. Jednosmjerni graf – Ovo je najčešći i najbrţi oblik vezanog grafa. Struktura grafa

se sastoji od čvorova koji mogu biti u polju ili vezanoj listi. Svaki čvor u grafu

osim podataka o samom čvoru sadrţi i vezanu listu lukova koji izlaze iz njega.

Svaki luk pokazuje na samo jedan čvor.

Slika 12.8. Jednosmjerni vezani graf

12.3. Pretraživanje grafa

Pretraţivanje grafa se provodi kako bi se saznalo do kojih čvorova moţemo doći iz početnog

čvora slijedeći lukove [Sherrod, 2007, str. 357].

Postoje dva načina pretraţivanja grafa [Ibid, str. 358]: prvo-u-dubinu i prvo-u-širinu.

C

1

2

3

A

B

1

2

3

A

B

C

ČVOROVI

A

C

1

2

3

B

1

2

3

ČVOROVI

A

B

C

LUKOVI

Page 48: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

44

12.3.1. Prvo-u-dubinu

Pretraţivanje prvo-u-dubinu je algoritam koji koristi stog kako bi se kretao od početnog čvora do

završnog ukoliko je to moguće, ili dok se ne obiĎu svi čvorovi, a završni čvor nije pronaĎen

[Sherrod, 2007, str. 359].

Algoritam se sastoji od sljedećih koraka [Ibid, str. 358]:

1) Izabrati početni čvor i označiti ga kao trenutni

2) Staviti trenutni čvor na stog i označiti ga da je provjeren

3) Ako je trenutni čvor ujedno i završni onda stati inače nastaviti

4) Posjetiti prvi čvor koji je povezan s trenutnim čvorom a da još nije provjeren i označiti ga

kao trenutni čvor

5) Ponavljati korake od 2. do 4. sve dok algoritam ne provjeri sve čvorove na jednom putu

6) Ako završni čvor nije naĎen, maknuti trenutni čvor sa stoga i posjetiti sljedeći

neprovjereni čvor s kojim je trenutni čvor povezan

7) Ponavljati korake od 2. do 6. sve dok se svi čvorovi ne provjere, što znači da završni čvor

nije pronaĎen, ili dok se ne pronaĎe završni čvor

Ukoliko se pronaĎe završni čvor, čvorovi koji se nalaze na stogu nakon završetka algoritma

predstavljaju čvorove koji tvore put od početnog čvora do završnog.

12.3.2. Prvo-u-širinu

Pretraţivanje prvo-u-širinu je algoritam koji koristi red kako bi se kretao od početnog čvora do

završnog ukoliko je to moguće [Sherrod, 2007, str. 367].

Algoritam ima sljedeće korake [Ibid, str. 367]:

1) Staviti početni čvor na kraj reda i onda započeti petlju koja će se ponavljati sve dok je

red pun

2) Unutar petlje izvaditi čvor s početka reda i označiti ga kao trenutni čvor

3) Staviti sve neprovjerene čvorove koji su povezani sa trenutnim čvorom na kraj reda i

označiti ih kao provjerene

4) Ako više nema neprovjerenih čvorova koji su povezani s trenutnim provjeriti da li je

trenutni čvor završni

5) Ako je završni čvor pronaĎen, algoritam se završava

6) Ako završni čvor nije pronaĎen, ponoviti korake od 2. do 5.

Pretraţivanje prvo-u-širinu je korisno ako traţimo najkraći mogući put izmeĎu dva čvora na

grafu.

Page 49: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

45

12.4. Primjena grafova u igrama

Jedna od najvaţnijih stvari u igrama je umjetna inteligencija. Bez obzira da li se radi od

dvodimenzionalnoj ili trodimenzionalnoj igri umjetna inteligencija je u igrama prisutna od

njezinih početaka. Jedna od najvaţnijih stvari što se tiče umjetne inteligencije je pronaći put kroz

virtualni svijet od točke A do točke B. Jedan od jako popularnih algoritama koji sluţe upravo

tomu je A* (A-star) algoritam [Sherrod, 2007, str. 391].

A* algoritam se izvodi na teţinskom grafu [Ibid, str. 391]. U virtualnom svijetu područja u koja

mogu zalaziti virtualni likovi su predstavljena čvorovima. Ti čvorovi su meĎusobno povezani

lukovima koji tvore putove koji govore igri kako iz jednog područja virtualnog svijeta doći u

drugo. Slika 13.9. prikazuje pogled odozgora na virtualni svijet u kojem čvorovi odreĎuju kako

iz jednog područja doći u drugo.

Slika 12.9. Pogled na virtualni svijet u kojem čvorovi definiraju putove iz jednog područja u drugo

Teţine na pojedinom čvoru mogu označavati razne stvari koje su drugačije od igre do igre.

Primjerice, mogu označavati „trošak“ puta do odreĎenog čvora [Ibid, str. 392]. Primjer toga bila

bi igra u kojem kompjuterski likovi imaju mogućnost voţnje kroz virtualni svijet. U tom slučaju,

teţine pojedinih čvorova mogle bi se odrediti prema tipu terena na kojem se pojedini čvor nalazi.

Čvorovi koji se nalaze na cesti imali bi najmanji trošak, dok bi oni koji se nalaze na travi ili blatu

imali veći trošak [Ibid, str. 392].

Page 50: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

46

13. Zaključak

U računalnom programiranju i razvoju igara postoji mnogo različitih struktura podataka. Temelj

svakog programiranja leţi u učinkovitom korištenju spomenutih struktura i algoritama koji se

izvode nad njima. U ovom radu su navedene i opisane najpoznatije strukture podataka i načini na

koji se mogu iskoristiti prilikom razvoja igara. Pošto svaka igra započinje glavnim izbornikom i

igra koja dolazi uz ovaj rad ima svoj izbornik. On je baziran na stogu koji je opisan u sedmom

poglavlju. Budući da se radi o RTS ţanru igre u kojem je jedna od osnovnih stvari zadavanje

naredbi jedinicama, tako i igra uz ovaj rad dolazi s tom mogućnošću koja je implementirana

pomoću strukture podataka red, a opisana u osmom poglavlju ovog rada. Osim zadavanja

naredbi potrebno je i pristupati raznim podacima koji postoje o svakoj jedinice ali i ostalim

dijelovima igre. Da se performanse igre ne bi pogoršale takvim podacima je potrebno pristupati

brzo. Upravo tomu sluţe polja čija je najbolja namjena čuvanje podataka kojima se treba brzo i

često pristupati. Polja su opisana u drugom poglavlju. U četvrtom poglavlju je opisana bitvector

struktura uz pomoć koje je izvedena quick save funkcija, a čija je namjena da igraču omogući

spremanje stanja igre odnosno virtualnog svijeta u nekom odreĎenom trenutku, prekine s igrom

te nastavi kasnije. Jedan od vaţnijih aspekata svake igre svakako je i manipulacija resursima

kojima igra raspolaţe. Zbog ograničene veličine računalne memorije vaţno je da se pojedini

resurs ne učita u memoriju više od jedanput. Pošto današnje igre obiluju resursima, sekvencijalno

pretraţivanje već učitanih resursa sa ciljem provjeravanja li odreĎeni resurs već postoji, bilo bi

presporo. U takvim situacijama potrebno je to pretraţivanje ubrzati. Prateća igra ovom radu

koristi hash tablicu kao metodu ubrzavanja pretraţivanja već učitanih resursa što je opisano u

devetom poglavlju. Osim struktura podataka koje su korištene u popratnoj igri u samom radu sa

navedene još neke koje imaju primjene u računalnim igrama. To su stabla te grafovi koji se često

koriste u umjetnoj inteligenciji. Naravno nijedna od tih struktura ne mora se koristiti upravo

tako. Neke strukture su pogodnije za jedan tip igre a druge za drugi. Na programeru je da odluči

koja struktura podataka će za njegovu igru biti najkorisnija. U igrama je najbitnija brzina

izvoĎenja pojedinih algoritama nad podacima pa programer prilikom odabira pojedinih struktura

mora obratiti pozornost i na različite implementacije pojedinih struktura i način na koji će ih

koristiti. Ponekad je sporija varijanta neke strukture korisnija ako se algoritmi nad njome rijetko

izvršavaju te ako je jednostavna za implementirati. U tom slučaju programer moţe ţrtvovati

brzinu zbog jednostavnosti.

Page 51: STRUKTURE PODATAKA U RAZVOJU RAČUNALNIH IGARA · sveuČiliŠte u zagrebu fakultet organizacije i informatike v a r a Ţ d i n bernard brček bedeković strukture podataka u razvoju

47

14. Literatura

1) Ammeraal, L. (1996). Algorithms and Data Structures in C++, Wiley

2) Brownsey, K. (2000). The Essence of Data Structures Using C++ (1. izdanje), Pearson

Education Limited

3) Conger, D., Little R. (2006). Creating Games in C++: a step-by-step guide, New Riders

4) Dale, N. (2003). C++ Data Structures (3. izdanje), Jones and Barttlett Publishers

5) Kasiviswanath, N. (2007). Data Structures Using C++, Laxmi Publications LTD

6) Keogh J. E., Davidson K. (2004). Dana Structures Demystified, McGraw-Hill

7) Kutti N. S., Padhye P. Y. (2004). Data Structures in C++, Prentice-Hall

8) Lipljin, N. (2004). Programiranje/1, TIVA Varaţdin

9) Llopis, N. (2003). C++ for Game Programmers, Cengage Learning

10) Penton, R. (2003). Data Structures for Game Programmers, Premier Press

11) S. Childs, J. (2008). C++ Classes and Data Structures, Prentice Hall

12) Sahni, S. (2004). Data Structures, Algorithms, And Applications In C++.

Silicon Press

13) Sedgewick, R. (2002). Algorithms in C++, Parts 1-5: Fundamentals, Data

Structures, Sorting, Searching, and Graph Algorithms. Third Edition,

Addison Wesley Professional

14) Sherrod, A. (2007). Data Structures and Algorithms for Game Programmers, Charles

River Media

15) Smith, P. (2004). Applied Dana Structures with C++, Jones and Bartlett Publishers, Inc.

16) Weiss, M. A. (2006). Data Structures and Algorithm Analysis in C++. Third

Edition, Addison Wesley