Ebben a részben 3db, két kisebb és egy nagyobb példa program legfontosabb kódrészletei láthatók Boo nyelven
A példák átnézése segíti megismerni a Boo szintaxisát. Ha ezek alapjén megpróbálunk egy kisebb saját programot írni, rájöhetünk, hogy miért is "csuklóbarát" a nyelv.
A példákból 2 Unity 3D-ben lett megírva, a scripteléshez a Boo nyelvet használva.
Először nézzünk egy kisebb, tisztán Boo példát. Utána a Unityről található egy rövid leírás, majd a két Unity-s példa következik.
Egy egyszerű példa
Ebben a példában egy saját osztály szerepel, amivel a racionális számokkal, szépen, tört alakban tudjuk kezelni.
Először nézzünk rá a teljes kódra:
import System
class Racionalis:
private szamlalo as int
private nevezo as int
private def lnko(a as int, b as int) as int:
if a == 0:
return b
else:
return lnko((b % a), a)
public Szamlalo as int:
get:
return szamlalo
set:
szamlalo = value
public Nevezo as int:
get:
return nevezo
set:
if value != 0:
nevezo = value
public def constructor(sz as int, nev as int):
o as int
szamlalo = sz
if nev != 0:
nevezo = nev
else:
nevezo = 1
o = lnko(szamlalo, nevezo)
szamlalo = (szamlalo / o)
nevezo = (nevezo / o)
public def invert():
if szamlalo == 0:
return
temp as int
temp = szamlalo
szamlalo = nevezo
nevezo = temp
public def equals(other as Racionalis) as bool:
return ((szamlalo * other.nevezo) == (nevezo * other.szamlalo))
public def multx(b as Racionalis):
szamlalo = (szamlalo * b.szamlalo)
nevezo = (nevezo * b.nevezo)
public def mult(b as Racionalis) as Racionalis:
return Racionalis((szamlalo * b.szamlalo), (nevezo * b.nevezo))
public override def ToString() as string:
return ((szamlalo + '/') + nevezo)
a as Racionalis
b as Racionalis
a = Racionalis(1, 2)
b = Racionalis(2, 4)
print a + " " + b
print a.equals(b)
a.multx(b)
b = a.mult(b)
print a
print b
a.Szamlalo = 3
a.Nevezo = 0
print a.Szamlalo
print a.Nevezo
A racionális osztály:
import System
class Racionalis:
private szamlalo as int
private nevezo as int
private def lnko(a as int, b as int) as int:
...
public Szamlalo as int:
...
public Nevezo as int:
...
public def constructor(sz as int, nev as int):
...
public def invert():
...
Külön tároljuk a számlálót és a nevezőt.
Ezen kívül a getter és setter metódusok szerepelnek itt, az osztály konstruktora, továbbá a tört egyszerűsétéséhez használt függvények.
A getter és setter metódusok:
public Szamlalo as int:
get:
return szamlalo
set:
szamlalo = value
public Nevezo as int:
get:
return nevezo
set:
if value != 0:
nevezo = value
A példában a törtek szorzása és egyenlőségvizsgálata szerepel.
public def equals(other as Racionalis) as bool:
return ((szamlalo * other.nevezo) == (nevezo * other.szamlalo))
public def multx(b as Racionalis):
szamlalo = (szamlalo * b.szamlalo)
nevezo = (nevezo * b.nevezo)
public def mult(b as Racionalis) as Racionalis:
return Racionalis((szamlalo * b.szamlalo), (nevezo * b.nevezo))
Valamint a kiíratáshoz, a stringgé konvertáló függvény:
public override def ToString() as string:
return ((szamlalo + '/') + nevezo)
Az osztály használata:
import System
a as Racionalis
b as Racionalis
a = Racionalis(1, 2)
b = Racionalis(2, 4)
print a + " " + b
print a.equals(b)
a.multx(b)
b = a.mult(b)
print a
print b
a.Szamlalo = 3
a.Nevezo = 0
print a.Szamlalo
print a.Nevezo
És a konzolon látható eredmény:
Problem: Something bad happened.
1/2
1/2
True
1/4
1/8
3
4
Unity
A következő példák Unityben lettek megírva, így elengedhetetlen, hogy
röviden ne beszéljünk a Unity-ről.
A Unity3D honlapja, ahol többet olvashatunk róla:
Unity3D honlapja
Az oldalon "Game Engine"-ként szerepel, azonban szerencsésebb
megnevezés a "3D fejlesztő keretrendszer", hiszen nem csak játékok
fejlesztésére alkalmas.
Unity-ben rendkívül könnyen és gyorsan lehet dolgozni. Még az is
elég jól elboldogulhat vele, aki nem programozó, hiszen a Unity
felhasználói felülete igen csak barátságos, rengeteg dolgot ad
készen, továbbá egyedi prefab rendszerrel rendelkezik.
A Unity multiplatform. A 4.0 verzió óta képes fordítani:
- PC
- Mac
- Linux
- Android
- IOS
- Google Native Client
- XBox 360
- PS3
- Wii
- Flash
A felsoroltak közül csak az utolsó 4 fordító a nem ingyenes.
Fontos megjegyezni, hogy a Unityből létezik ingyenes és fizetős Pro
verzió is. 2013 május 21.-től az ingyenes verzióhoz már ingyen adják
a listában szereplő Android és IOS fordítót is.
Unity-t lehet scriptelni C#-ban, JavaScriptben valamint Boo-ban. A legtöbb, Unityvel foglalkozó könyv csak C#-ot használ, a Unity által kínált scriptek többsége pedig JavaScriptben lettek megírva.
A példákban csak a Boo scriptekkel foglalkozunk. Az egyéb, Unity spec. megoldásokról a Unity honlapján olvashatunk bővebben.
Egyszerűbb Unity példa
Nézzünk egy egyszerűbb, Boo-ban scripttelt példát Unity-ben.
A Web Playerre fordított program azonnal ki is próbálható.
A W-A-S-D gombokkal mozgathatjuk a kamerát, és az egér bal gombjával lőhetünk.
Példa1
Megj.:
- Az új Unity, Web Playerre fordítva sajnos Google Chrome-ban nem működik. De Firefox-ban és Internet Explorerben kipróbálható.
- Ha nincsen feltelepítve Unity Weplayer, azt a linkre kattintva először felkínálja.
Ebben a példában csak egy Boo script található, minden egyéb
(prefabok, modellek, egyéb játékelemek) Unityben készültek.
A forrás:
import System
import UnityEngine
import System.Collections
public class Shooter(MonoBehaviour):
public bullet as Rigidbody
public power as single = 1500.0F
public moveSpeed as single = 2.0F
private def Start():
pass
private def Update():
h as single = ((Input.GetAxis('Horizontal') * Time.deltaTime) * moveSpeed)
v as single = ((Input.GetAxis('Vertical') * Time.deltaTime) * moveSpeed)
transform.Translate(h, v, 0)
if Input.GetButtonUp('Fire1'):
instance = (Instantiate(bullet, transform.position, transform.rotation) as Rigidbody)
instance.AddForce((Vector3(0, 0, 1) * power))
Minden, Unity-s Boo script-hez szükséges, hogy a MonoBehaviour-ből származtassuk, ahogy az a példában is látható.
Első olvasásra furcsa lehet, hogy miért public-ként vesszük fel az adattagokat. Ez Unity spec. megoldás, mert így Unity-ből lehet beállítani a kezdőértékeket, és "belekötni" a használt prefabokat.
A példához nem szükséges túl sok magyarázat. Az Update() fv-ben történik a játék logikájának frissítése, ahol is figyeljük az egér mozgását, és kattintásra létrehozunk egy lövedéket: Instantiate(), majd azt elindítjuk az útján.
A játékban szereplő fizikához a Unity által felkínált eszközöket használja a program.
Megj.: A script a játékban szereplő mainCamera-hoz van kötve, de a kód újrafelhasználható, gyakorlatilag bármilyen prefab-re ráköthetjük, és a lövedék (bullet) helyére is bármilyen, RigidBody-t tehetünk.
Erről bővebben a Unity honlapján olvashatunk.
Összetettebb Unity példa
Egy kissé összetetteb példa található itt, Unity-ben, Boo-ban scriptelve.
A Web Playerre fordított program azonnal ki is próbálható.
A W-A-S-D gombokkal mozoghatunk ás SPACE-el ugorhatunk.
A cél bejutni az épületbe, amit csak akkor tehetünk meg, ha felszedtünk 4 elemet.
Példa2
Megj.:
- Az új Unity, Web Playerre fordítva sajnos Google Chrome-ban nem működik. De Firefox-ban és Internet Explorerben kipróbálható.
- Ha nincsen feltelepítve Unity Weplayer, azt a linkre kattintva először felkínálja.
A példában szereplő modellek és textúrák a Unity 3.x Game Development Essentials könyv unity-csomagjából lettek felhasználva, a sziget kézzel lett elkészítve. A karakter mozgásához a Unity által kínált FirstPersonController módosított prefabje biztosítja.
A könyv egy nagyon hasonló példán keresztül mutatja be a Unity-t, C#-ban kódolva. Ez a példa abból indul ki, azonban minden script át lett írva Boo-ra, továbbá egy kissé módosítva lett és ki lett egészítve.
Ebben a példában már több osztály / script szerepel, nézzük ezeket sorra:
Az elemekre kötött PowerCell script:
import System
import UnityEngine
import System.Collections
public class PowerCell(MonoBehaviour):
public rotationSpeed as single = 100.0F
private def Start():
pass
private def Update():
transform.Rotate(Vector3(0, (rotationSpeed * Time.deltaTime), 0))
private def OnTriggerEnter(col as Collider):
if col.gameObject.tag == 'Player':
col.gameObject.SendMessage('CellPickup')
Destroy(gameObject)
Ez a script gondoskodik az elemek körbe forgásáért, valamint
figyelik a playerrel való ütközést. Ekkor üzenetet küldenek
a Player-nek, és gondoskodnak az önmegsemmisítésről.
Az épületre kötött script:
import System
import UnityEngine
import System.Collections
public class TriggerZone(MonoBehaviour):
public lockedSound as AudioClip
private def OnTriggerEnter(col as Collider):
if col.gameObject.tag == 'Player':
if Inventory.charge == 4:
transform.FindChild('door').SendMessage('DoorCheck')
else:
transform.FindChild('door').audio.PlayOneShot(lockedSound)
col.gameObject.SendMessage('HUDon')
A Player-nek az ajtóval történő ütköztetés eredményét figyeli. Ha a játékos már felvette a 4 elemet, akkor beengedi, egyébként pedig nem.
Az épület ajtajára (Outpost.Door) kötött, DoorManager script:
import System
import UnityEngine
import System.Collections
public class DoorManager(MonoBehaviour):
private doorIsOpen = false
private doorTimer as single = 0.0F
public doorOpenTime as single = 3.0F
public doorOpenSound as AudioClip
public doorShutSound as AudioClip
private def Start():
doorTimer = 0.0F
private def Update():
if doorIsOpen:
doorTimer += Time.deltaTime
if doorTimer > doorOpenTime:
Door(doorShutSound, false, 'doorShut')
doorTimer = 0.0F
private def DoorCheck():
if not doorIsOpen:
Door(doorOpenSound, true, 'doorOpen')
private def Door(aClip as AudioClip, openCheck as bool, animName as string):
audio.PlayOneShot(aClip)
doorIsOpen = openCheck
transform.parent.gameObject.animation.Play(animName)
Ez a script felelős az ajtó kinyitásáért és becsukásáért, időzítve.
A játékosra kötött scriptek: ChaarcterMotor, FPSInputController, Inventory, MouseLook.
Az első kettő a Unity által biztosított scriptek. Ezek JavaScriptben vannak megírva.
MouseLook:
import System
import UnityEngine
import System.Collections
[AddComponentMenu('Camera-Control/Mouse Look')]
public class MouseLook(MonoBehaviour):
public enum RotationAxes:
MouseXAndY = 0
MouseX = 1
MouseY = 2
public axes as RotationAxes = RotationAxes.MouseXAndY
public sensitivityX as single = 15.0F
public sensitivityY as single = 15.0F
public minimumX as single = (-360.0F)
public maximumX as single = 360.0F
public minimumY as single = (-60.0F)
public maximumY as single = 60.0F
private rotationY as single = 0.0F
private def Update():
if axes == RotationAxes.MouseXAndY:
rotationX as single = (transform.localEulerAngles.y + (Input.GetAxis('Mouse X') * sensitivityX))
rotationY += (Input.GetAxis('Mouse Y') * sensitivityY)
rotationY = Mathf.Clamp(rotationY, minimumY, maximumY)
transform.localEulerAngles = Vector3(-rotationY, rotationX, 0)
elif axes == RotationAxes.MouseX:
transform.Rotate(0, (Input.GetAxis('Mouse X') * sensitivityX), 0)
else:
rotationY += (Input.GetAxis('Mouse Y') * sensitivityY)
rotationY = Mathf.Clamp(rotationY, minimumY, maximumY)
transform.localEulerAngles = Vector3(-rotationY, transform.localEulerAngles.y, 0)
private def Start():
if rigidbody:
rigidbody.freezeRotation = true
Az egér kezelését végző script.
Az "[AddComponentMenu('Camera-Control/Mouse Look')]" Unity spec. kód. Így könnyebben elérhető és használható lesz a megírt scriptünk.
Inventory:
import System
import UnityEngine
import System.Collections
public class Inventory(MonoBehaviour):
public static charge = 0
public collectSound as AudioClip
// HUD
public hudCharge as (Texture2D)
public chargeHudGUI as GUITexture
private def Start():
charge = 0
private def Update():
pass
private def CellPickup():
AudioSource.PlayClipAtPoint(collectSound, transform.position)
charge += 1
chargeHudGUI.texture = hudCharge[charge]
HUDon()
private def HUDon():
if not chargeHudGUI.enabled:
chargeHudGUI.enabled = true
Az Inventory script az elemek számát figyeli, valamint a felületen megjeleníti az adott töltöttségi szintet.