3D program 4 sorban!

Akkor lássunk is hozzá a programozáshoz! Indítsuk el a DB-t, és írjuk be az alábbi programot:

make object cube 1,5

do

yrotate object 1,object angle y(1)+2

loop

Futtassuk! [F5]

Az eredmény egy forgó kocka. Most nézzük, hogy működik a program!

1. sor: Egy 3 dimenziós objektumot készítünk, jelen esetben egy kockát. (Ha a súgóban megnézzük, láthatjuk, hogy többféle objektumot tudunk készíteni: téglatest, gömb, kúp, stb.) Az objektum sorszáma 1-es lesz, a mérete 5 (tehát 5*5*5-ös).

2. és 4. sor: A do és a loop egy végtelen ciklust egedményeznek. A közöttük található programsorok folyamatosan ismétlődnek.

3. sor: Az yrotate object a megadott számú objektumot a megadott szögre fordítja el az y tengey körül. A szöget úgy számítjuk ki, hogy lekérjük az objektumunk y szögét, és hozzáadunk 2-t.

Tipp: állítsuk a kurzort egy parancsra vagy függvényre, és nyomjunk F1-et! Ekkor a súgó megmutatja a paramétereit, meg azt, hogy mit csinál.

Nekünk azonban nem tetszik ez a program, mert olyan lassú. Hogy gyorsítsunk rajta, meg kell ismerkednünk a Sync paranccsal. Alapállásban a DB frissíti a képet. Ha lassan dolgozik, akkor nem szabad rábízni ezt a fontos feladatot... Két dolgot tehetünk:

1, Megadjuk hogy hányszor frissítse a képet. Ezt a Sync Rate paranccsal tehetjük meg:

pl.: sync rate 100

60 fps-nél ne várjunk többet. (az fps itt a frame/sec rövidítése, nem a first person shooteré :) )

2, Mi mondjuk meg, hogy mikor frissítsen:

sync on <- vele beállíthatjuk a kézi képfrissítést: csak sync-re frissít a program

sync <- vele frissítjük a képet

Tehát:

sync rate 100

make object cube 1,5

do

 yrotate object 1,object angle y(1)+2

loop

vagy:

sync on

make object cube 1,5

do

 sync

 yrotate object 1,object angle y(1)+2

loop

Most az 1. változat tűnik gyorsabbnak.

Na, ezzel is megvagyunk. Csináljuk látványosabbra ezt a programot! Színezgessük a hátteret! A háttér neve a DarkBasicben: backdrop. A backdropot színezhetjük, textúrázhatjuk (ezt lásd később). Alapból kék színű. Érdemes tudni róla, hogy folyamatosan frissül, tehát ha kiírunk valamit rá, az a következő frissítéskor eltűnik.

set display mode 800,600,16

make object cube 1,5

sync on

sync rate 60

do

 sync

`Mivel az 'a' változó

`kezdőértéke 0, ezért a mod változó értéke 2 lesz (lásd 4. if kezdetű sor)

`Ha mod=2, akkor az a-t növeljük egészen addig, amíg 255 nem lesz. Ekkor

`a mod 1 lesz, és az 'a' változó értékét csökkenteni kezdjük. Egészen addig,

`amíg 0 nem lesz. Ekkor kezdődik az egész előről.

 if mod=1 then a=a-1

 if mod=2 then a=a+1

 if a=255 then mod=1

 if a=0 then mod=2

`Színezzük az (1-es) objektumot.

`Aztán a hátteret az ellentétes színnel.

`Az rgb paranccsal adhatunk meg színt.

 color object 1,rgb(a,a,a)

 color backdrop rgb(255-a,255-a,255-a)

`Elforgatjuk két tengely körül is az 1-es objektumot

 yrotate object 1,object angle y(1)+2

 xrotate object 1,object angle x(1)+2

`A szövegkiíratás helyét a 0,0 2D koordinátákra állítjuk.

 set cursor 0,0

`A screen fps() függvény az fps-t adja vissza (remélem logikus...)

`Kombináljuk printtel, és így kiírja az fps-t.

 print "FPS: ";screen fps()

loop

Magyarázat:

- A programban vannak megjegyzések, amik ` jellel kezdődnek [AltGr-7]. Ne keverjétek össze a normál aposztróffal [Shift-1]!

- A set display mode 800*600-ra és 16 bitre állítja a felbontást és színmélységet. (Alapból 640*480*16)

- Az RGB() értékei 0 és 255 között változhatnak.

- A printnél egyszerre két tipusú adatot használunk: (csak itt lehet ilyet)

1,string (szöveg)

2,egész szám (screen FPS())

Remélem minden érthető. Akkor most nézzük a kamera kezelését!

Változtassuk meg a kocka méretét! Azt tapasztaljuk, hogy megnövelt méret esetén is ugyanakkora a képernyőn. Ha még nagyobbra állítjuk, eltűnik a kocka.  Ez azért van, mert új objektum készítésekor a DB a kamerát úgy állítja be, hogy az objektum beleférjen a képbe (autocam). Tegyük szabadon mozgathatóvá a kamerát! Ehhez először meg kell ismerkedni a beviteli eszközök kezelésével.

Egér kezelése:

A mouseclick() függvény értéke adja meg, hogy melyik gomb volt lenyomva. Íme egy példaprogram:

do

if mouseclick()=1 then print "Bal gomb"

if mouseclick()=2 then print "Jobb gomb"

if mouseclick()=3 then print "Mindkét gomb"

loop

A hide mouse parancs elrejti, a show mouse parancs megjeleníti az egeret.

Az egér elmozdulását képpontokban a mousemovex() és a mousemovey() függvények adják meg:

do

cls

set cursor 0,0

print "X elmozdulás: ";mousemovex();" Y elmozdulás: ";mousemovey()

loop

A billentyűzet főbb gombjait a controlkey(), shiftkey(), spacekey(), stb. függvényekkel kezelhetjük.

Visszatérve a kamera kezelésére, itt a kamera használatát bemutató program:

autocam off : sync on : hide mouse

randomize timer()

for i=1 to 200

 make object cube i,5

 position object i,rnd(1000),rnd(1000),rnd(1000)

next i

position camera 500,500,500

do

szogx=wrapvalue(szogx+mousemovex())

szogy=wrapvalue(szogy+mousemovey())

rotate camera szogy,szogx,0

if mouseclick()=1 then move camera 5

if mouseclick()=2 then move camera -5

sync

loop

Magyarázat:

1. sor: az autocam off parancs kikapcsolja a DB-nek azt a tulajdonságát, hogy egy objektum létrehozásakor ráfókuszáljon a kamera. Ez azért lesz fontos, mert sok objektummal lesz dolgunk. A sorban található másik két parancs már ismert.

2. sor: a véletlenszám-generátor kezdőértékét az órához állítja. Ez azért kell, mert a program minden induláskor ugyanazokat a "véletlen" értékeket generálná.

3. sor: ciklus eleje

4. sor: 200 kocka legyártása

5. sor: 200 kocka véletlenszerű elhelyezése. Az RND() függvénybe írt szám a véletlenül generált szám legmagasabb értéke, tehát itt 0 és 1000 között lesznek a számok. És 3 ilyen szám kell, mivel 3D-ben 3 koordináta van. (Ezeknek semmi közük a képernyő 2D-s koordinátáihoz! Azokból még mindig 2 van!)

6. sor: ciklus vége

7. sor: a kamerát berakjuk az egész kellős közepébe. Mivel 1 kamera van, nem kell kameraszám. De ha csinálunk egy másikat (csak DBpro-ban lehet) akkor kell.

8. sor: főciklus eleje

9. sor: az egér elmozdulását hozzáadjuk a szögX változóhoz. De mivel a szög 0 és 359 között lehet csak, ezért lekerekítjük a wrapvalue függvénnyel. (A wrapvalue az esetleges -10 -ből 350-et, 370-ből 10-et csinál)

10. sor: ugyanez az egér y koordinátájával

11. sor: kamera elforgatása: a szogx és a szogy fel van cserélve.

12. sor: Ha bal gombot nyomunk, előre megy a kamera

13. sor: Ha jobb gombot nyomunk, hátra

14. sor: Képfrissítés

15. sor: Főciklus vége

Ennyi. Vállalkozó szelleműek kombinálhatják az előző programmal! Azonban nem ártana, hogyha megállna a kamera, ha objektumhoz ér. Azt nem tudjuk vizsgálni, hogy egy kamera ütközik-e, de azt igen, hogy két objektum ütközik-e. Úgy kell tehát megoldani, hogy egy objektumot irányítunk, aminek eltároljuk a koordinátáit. Ha ütközik, visszaállítjuk a régi koordinátákat.

Ütközést az object collision(obj1,obj2) függvénnyel vizsgálhatjuk. "Egyet ad vissza, ha két megadott 3D objektum átfedésben van egymással. Ha a második bemenő paraméter nulla, a visszatérési éték annak az objektumnak a száma, mellyel az első objektum átfedésben van. A paramétereknek egész értékeknek kell lenniük." - idézet a súgóból.

autocam off : sync on : sync rate 60 : hide mouse

randomize timer

for i=1 to 100

 make object cube i,15

 position object i,rnd(1000),0,rnd(1000)

next i

make object plain 101,0,0

do

opx=object position x(101)

opz=object position z(101)

position camera opx,0,opz

szogx=wrapvalue(szogx+mousemovex())

rotate object 101,0,szogx,0

set camera to object orientation 101

if upkey()=1 then move object 101,5

if downkey()=1 then move object 101,-5

if object collision(101,0)<>0 then position object 101,opx,0,opz

sync

loop

A program eleje hasonlít az előzőre. 100 objektumot gyártunk. 3D-ben az y koordináta a magasság, azt most békén hagyjuk. Csinálunk egy 101-edik objektumot, őt fogjuk irányítani.

Fő ciklus:

Először is az opx és opz változókban eltároljuk az objektum koordinátáit. Ezután a helyére berakjuk a kamerát. Ezek után kiszámoljuk a szöget, elforgatjuk az objektumot. A set camera to object orientation parancs az újdonság, ahogy a neve is mondja, az objektumhoz állítja a kamera szögét. A fel és le nyíl nyomására mozgatjuk az objektumot. Ha ilyenkor ütközik, visszaállítjuk a régi helyére.

Ennyi! Ha ütközünk, megáll...

Ezzel véget is ért ennek a  rovatnak a tartalma. Következő hónapban tovább ismerkedünk a 3D objektumokkal - na meg a kamerával, egy picit foglalkozunk a mátrixokkal, és összebarátkozunk a spriteokkal, ami most nem az üdítőt jelenti! :-)

Várkonyi Tibor - vtibor3@freemail.hu