You are on page 1of 28

Prošli put:

Načelni odabir tema


obradio
Saša Mladenović
Prirodoslovno matematički fakultet
Što sada hoće od nas?
 Nakon prijava projekata kroz idućih nekoliko predavanja proći ćemo kroz
osnovne ideje koje mogu biti zajedničke za više projekata.
 Cilj ovog predavanja je pokazati kako programiranje može biti jednostavno i
zabavno, a jedino što preostaje zaista “naučiti” jest interpretirati vlastiti
projekt koristeći osnovne pojmove objektno orijentiranog programiranja.
Elementi objektnog modela

 Osnovni elementi:
• apstrakcija
• enkapsulacija
• modularnost
• nasljeđivanje
• polimorfizam
 Bez jednog od ovih elemenata model se ne može
proglasiti objektno-orijentiranim

3
Elementi objektnog modela

 Dodatni elementi:
• identifikacija tipa (typing)
• konkurentnost
• perzistencija
 Ovi elementi su korisni, ali ne i neophodni elementi
objektnog modela

4
Primjeri
Igra
 Prvi projekt sa liste koju ste popunili je:
“Neka jednostavna igra u GUI (WinForm)”
 Pong je naziv za računalnu igru koju je razvila tvrtka Atari 1972. Ova igra je
pokrenula razvoj industrije računalskih igara.
Cilj: razviti Pong igru
 Osnovne značajke igre:
1. 2D igra (pojednostavljeni stolni tenis)
2. Igra za jednog igrača (lijeva strana predstavlja igrača)
3. Upravlja se pomoću tipkovnice
4. Jednostavna grafika
5. Jedna loptica koja se kreće po x i y osi
6. Dvije palice koje se kreću po y osi
7. Loptica mijenja smjer kada udari u palicu (reket)
8. Kad igrač promaši lopticu igra je završena
9. Obavijesti igrača o tome je li igru dobio ili izgubio
10. Vrati sve parametre na početak, ako želiš ponovo igrati
Što sada?
 Kreirati vlastiti engine ili koristiti postojeći?
 Koje biblioteke i alate koristiti?

• XNA Game Studio?


• Vlastiti jednostavni engine (jer je za početak to dovoljno)
 GameSDK
 2DGL (2D Game Language)

http://www.youtube.com/user/ashh640?feature=watch
Korak 1
 Krećemo od postavljanja razvojnog okruženja
• Forma je veličine 640x480
• Osnovni element u igrama je “Sprite” (2D slika ili animacija integrirana u
širu scenu)
 Kako to definirati?
 Preuzmite GameSDK sa stranica kolegija.
 Proučite što bi Vam moglo trebati od dostupnih metoda.
 Kod za igru pohranjujete u BGL.cs (Basic Game Language C#)
Sprite
public struct Sprite public Sprite(string images, int p1, int p2, int w, int h)
{ {
public string image; bmp = new Bitmap(images);
public Bitmap bmp; image = images;
public int x, y, width, height; x = p1;
public bool show; y = p2;
width = w;
public Sprite(string images, int p1, int p2 height = h;
) show = true;
{ }
bmp = new Bitmap(images); }
image = images;
x = p1;
y = p2;
width = bmp.Width;
height = bmp.Height;
show = true;
}

39-55
Pomaci loptice
setTitle("Ping-Pong!"); // postavi naziv prozora

// definiramo moguće pomake loptice


left = true; // pomičemo lopticu lijevo
up = true; // pomičemo lopticu gore
Učitavanje Sprite-a
public void loadSprite(string file, int spriteNum, int x, int y)
{
spriteCount++;
sprites[spriteNum] = new Sprite(file, x, y);
}

public void loadSprite(string file, int spriteNum)


{
spriteCount++;
sprites[spriteNum] = new Sprite(file, 0, 0);
}

Polje spriteova
Za razmišljanje:
Što je ovo? Kako to da imamo isti naziv metode?
Kako se naziva ova pojava u OOP-u?

266-283
Inicijalizacija
 Sve do sada navedeno spada u inicijalizaciju igre.
public void Init() Što je ovo?
{

// definiramo moguće pomake loptice
left = true; // pomičemo lopticu lijevo
up = true; // pomičemo lopticu gore

//Učitavanje resursa i razina


setTitle("Ping-Pong!"); // postavi naziv prozora

loadSprite("ball.bmp", 1, 320-12, 240-12); // učitaj sprite


/ sa identifikatorom na određenu koordinatu
loadSprite("paddle.bmp", 2, 20, 240-(136/2));
loadSprite("paddle.bmp", 3, 620-35, 240-(136/2));

80-90
Problem prozirnosti
 Loptica koju koristimo je drukčija od originala. Naša je loptica okrugla. Sada
postoji problem prozirnosti dijela bitmape oko loptice (crna boja).
91 setImageColorKey(1, Color.Black); // učini nevidljivom za zadani sprite
//navedenu boju

316 public void setImageColorKey(int spriteNum, Color col)


{
sprites[spriteNum].bmp.MakeTransparent(col);
}

Bitmap Class
System.Drawing Namespace
Nedostaje još pozadina
 Na isti način kao i do sada učitava se još jedna bitmapa.
93 setBackgroundImage("Pozadina.bmp"); // postavi zadanu bitmapu u pozadinu

public void setBackgroundImage(string backgroundImage) 247-259


{
this.BackgroundImage = new Bitmap(backgroundImage);
}

public void setBackgroundImageLayout(string layout)


{
if (layout.ToLower() == "none") this.BackgroundImageLayout = ImageLayout.None;
if (layout.ToLower() == "tile") this.BackgroundImageLayout = ImageLayout.Tile;
if (layout.ToLower() == "stretch") this.BackgroundImageLayout = ImageLayout.Stretch;
if (layout.ToLower() == "center") this.BackgroundImageLayout = ImageLayout.Center;
if (layout.ToLower() == "zoom") this.BackgroundImageLayout = ImageLayout.Zoom;
}
Ima li još nešto?
 Inicijalizacija je važna jer u igri postavlja cjelokupno okruženje.
 Postavlja se pitanje kako ćemo igri udahnuti život?
• Osvježiti stanje igre (Update)
 Sada imamo “grubi nacrt igre”
Kako upravljamo reketom?
 Pretpostavimo neka igrač upravlja strelicama prema gore i dolje kako bi
pomicao reket u zadanom smjeru.
 Ono što nam treba je registrirati pritisak korisnika na tipku
 Ima li još ograničenja?
• Smijemo doći samo do ruba svijeta, inače ćemo “pasti”!
• Kako je postavljen koordinatni sustav?
 Za koliko pomičemo reket?
if(isKeyPressed(Keys.Up) && spriteY(2)>0)
{
moveSprite(2, spriteX(2), spriteY(2)-5);
}
if(isKeyPressed(Keys.Down) && spriteY(2)<(480-163))
{
moveSprite(2, spriteX(2), spriteY(2)+5);
}

101-111
A što je s lopticom?
 Loptica se kreće u četiri osnovna smjera:lijevo, gore, desno i dolje
 Koliko nam varijabli treba za određivanje smjera ako pretpostavimo da se
radi o logičkim varijablama?
 Kako ćemo naznačiti da se loptica kreće ukoso?
// ponašanje loptice
if(left) moveSprite(1, spriteX(1) - 5, spriteY(1));
if(up) moveSprite(1, spriteX(1), spriteY(1) - 5);
if(left == false) moveSprite(1, spriteX(1) + 5, spriteY(1));
if(!up) moveSprite(1, spriteX(1), spriteY(1) + 5);

public void moveSprite(int spriteNum, int x, int y)


{
sprites[spriteNum].x = x;
sprites[spriteNum].y = y;
}
113-117
Loptica i svijet
 Isto kao i kod reketa, treba odrediti kada je loptica došla do “kraja svijeta”.
 Postavlja se pitanje: Što je “kraj” i kako onda reagirati?

// Detekcija sudara sa rubom svijeta

if(up && spriteY(1) < 1) up = false;


if(!up && spriteY(1) > 425) up = true;

121-124
 Iza 09.12.
Loptica i reket
 Ovo je složenija zadaća, ali logički bi mogli reći:
1. Ako se loptica kreće ulijevo (prema nama) i
2. ako smo detektirali sudar između reketa i loptice
 onda se loptica više ne treba kretati u lijevo nego u suprotnu
stranu
 Bilo bi lijepo pronaći odgovarajući zvuk udarca i odsvirati ga

// Detekcija sudara sa reketom

if ( left && spriteCollision(1, 2)) // metoda iz 2D game language


{
playSound(1);
left = false; // ako loptica ide u lijevo i udari u reket
// tada se više ne treba kretati u lijevo
}

128-133
Kako detektirati koliziju?
 Najjednostavnije je zamisliti kako su svi spriteovi pravokutnici i onda tražiti
sijeku li se ili ne.

public bool spriteCollision(int spriteNum1, int spriteNum2)


{
Rectangle sp1 = new Rectangle(sprites[spriteNum1].x, sprites[spriteNum1].y,
sprites[spriteNum1].width, sprites[spriteNum1].height);
Rectangle sp2 = new Rectangle(sprites[spriteNum2].x, sprites[spriteNum2].y,
sprites[spriteNum2].width, sprites[spriteNum2].height);
Collision = Rectangle.Intersect(sp1, sp2);

if (!Collision.IsEmpty)
{
return true; Rectangle Structure
} Namespace: System.Drawing
else Method: Intersect(Rectangle, Rectangle)
{
return false;
}

} 478-493
Što sa drugim reketom?
 Ako je loptica udarila u igračev reket, promijenili smo joj smjer gibanja.
 Sada treba ispitati: Je li loptica udarila u drugi reket?
// detekcija sudara s drugim reketom
if ( !left && spriteCollision(1, 3)) // metoda iz 2D game language
{
playSound(2);
left = true; // ako loptica ne ide u lijevo i udari u reket
// tada se treba opet kretati u lijevo
}

135-141
Kako se kreće drugi reket?
1. Trebamo detektirati poziciju loptice u odnosu na reket računala
2. Ako se loptica kreće prema reketu ( ne u lijevo) tada trebamo prilagoditi y
koordinatu reketa y koordinati loptice (tako radi i čovjek)
3. Broj piksela za koji ćemo pomaknuti reket emulira reflekse čovjeka dok igra
Kako se kreće drugi reket?
 Loptica je učitana prva u polju spriteova, pa je njezina oznaka 1 (zadržali
smo neku logiku označavanja)
 Drugi po redu učitali smo reket igrača, a treći po redu reket računala
 Ovo nam je važno za razumijevanje koda koji definira kretanje drugog reketa
// Kretanje drugog reketa (UI)

if(spriteY(1) < spriteY(3) + 15 && spriteY(3) > 1 && left == false)


// želimo postaviti centar reketa
{
moveSprite(3, spriteX(3), spriteY(3) - 7);
}

if(spriteY(1) > spriteY(3) - 15 && spriteY(3) < (480-163) && left == false)
// želimo postaviti centar reketa
{
moveSprite(3, spriteX(3), spriteY(3) + 7);
}

144-154
Detekcija kraja igre
 Za ovako jednostavnu igru nećemo uvoditi brojač već ćemo smatrati da se
igra samo dok loptica ne “ispadne” sa stola.
 Sada imamo relativno jednostavan zadatak.
Detekcija kraja igre

 Nadam se da vam je na primjeru ove igre postalo vidljivo kako


programiranje ne mora uvijek biti “ozbiljan” posao i da se u njemu može
itekako uživati.
 Isto tako se nadam kako ćete uvidjeti kako za programiranje igara trebate
imati jako puno znanja iz različitih područja te se nadam da ćete idući put
kad budete igrali neku igru razmišljati i o njenom programskom modelu
Idući put
Pregled mogućnosti PMF GameSDK-a
Hanojski toranj

You might also like