A Boo programozási nyelv

Példa programok

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:

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.:


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.:

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.