Kun tänne on näitä objekti-systeemejä alkanut tulla, niin esittelen sitten omanikin.
Tarkoitukseni ei ola täysin samalla lailla matkia CB:n objektijärjestelmää, niinkuin aiemmat esimerkit, ja esimerkiksi kääntymiseen ei käytetä funktiota Turn vaan Rotate-funktiota, ja koko luokan nimi ei ole Object vaan CSprite. C siinä edessä on lyhennä sanasta Class, mutta voisihan se olla vaikka lyhenne sanasta Chaos, kun kerran se on ohjelmointikielenkin nimi.
Kaiken pohjana on CObject, joka sisältää peruskomennot liikkumiselle, eli: Move( x, y ), Rotate( angle ), Translate( x, y ), SetPosition( x, y ), SetAngle( angle ), CopyPosition( obj As CObject ), CopyAngle( obj As CObject ). Näiden lisäksi se sisältää muutaman itsetutkiskelu funktion: X(), Y(), Angle(), jotka (yllätys, yllätys) palauttavat tiedot objektin x- ja y-sijainnista sekä kulmasta. Se on tässä
Code: Select all
Class CObject
Private Var mPos[2] As Float
Private Var mAngle As Float
Constructor
mPos[0]=0.0
mPos[1]=0.0
mAngle=0.0
EndConstructor
/*Palauttaa objektion X-koordinaatin*/
Public Function X() As Float
Return mPos[0]
EndFunction
/*Palauttaa objektin Y-koordinaatin*/
Public Function Y() As Float
Return mPos[1]
EndFunction
/*Palauttaa objektin kulman*/
Public Function Angle() As Float
Return mAngle
EndFunction
/*Pyörittää objektia. Vastaa CB:n TurnObject-funktiota*/
Function Rotate( Var angle As Float ) As Void
mAngle+=angle
If mAngle>360 Then
mAngle=mAngle-360
ElseIf mAngle<0 Then
mAngle+=360
EndIf
EndFunction
/*Asettaa objektin tiettyyn kulmaan. Vastaa CB:n RotateObject-funktiota*/
Function SetAngle( Var angle As Float ) As Void
mAngle=angle
EndFunction
/*Liikuttaa objektia eteenpäin tai sivulle*/
Public Function Move( Var forward As Float, Var sidestep As Float=0 ) As Void
mPos[0]+= Cos(mAngle)*forward+Sin(mAngle)*sidestep
mPos[1]+= Sin(mAngle)*forward+Cos(mAngle)*sidestep
EndFunction
/*Liikuttaa objektia koordinaattiakseleiden mukaisesti objektin nykyisestä kulmasta välittämättä*/
Public Function Translate( Var x As Float, Var y As Float ) As Void
mPos[0]+=x
mPos[1]+=y
EndFunction
/*Asettaa objektin tiettyihin koordinaatteihin*/
Public Function SetPosition( Var x As Float, Var y As Float ) As Void
mPos[0]=x
mPos[1]=y
EndFunction
Public Function CopyPosition( Var obj As CObject ) As Void
This.mPos[0]=obj.X()
This.mPos[1]=obj.Y()
EndFunction
Public Function CopyAngle( Var obj As CObject ) As Void
This.mAngle=obj.Angle()
EndFunction
EndClass
Tästä luokasta periytetään ensimmäisenä CCamera-luokka, joka toimii kamerana tuleville Spriteillemme. Kamera luokka sisältää siis kaikki CObjektin-funktiot ja lisäksi myös seuraavat funktiot: SetSize( w, h ), InitImage( w, h ), DrawTo(), Draw( x, y ) ja vielä itsetutkiskelua varten Width() ja Height(). Peruskäytössä sinun ei periaatteessa tarvitse kuin luoda kamera muuttuja, ja konstruktori hoitaa loput. Muita funktioita tarvitset luodessasi jaettua ruutua (esimerkki alempana). Tässä itse luokka
Code: Select all
Class CCamera Inherits CObject
Private Var mSize[2] As Integer
Private Var mImage As Image
Constructor
mSize[0]=Screen.Width()
mSize[1]=Screen.Height()
EndConstructor
/*Palauttaa näkymän leveyden*/
Public Function Width() As Integer
Return mSize[0]
EndFunction
/*Palauttaa näkymän korkeuden*/
Public Function Height() As Integer
Return mSize[1]
EndFunction
Public Function SetSize( Var sizeX As Integer, Var sizeY As Integer ) As Void
mSize[0]=sizeX
mSize[1]=sizeY
EndFunction
/*Alustaa kuvamuuttujan, tarpeellinen vain jaetun ruudun toteutuksessa*/
Public Function InitImage(Var sizeX As Integer, Var sizeY As Integer ) As Void
mImage = New Image
mImage.Create sizeX,sizeY
mSize[0]=sizeX
mSize[1]=sizeY
EndFunction
/*Jos olet alustanut kuvan, niin ohjaa piirtokomennot tällä funktiolla
siihen (samalla myös tyhjentää kuvan)*/
Public Function DrawTo() As Void
Screen.SetDrawBuffer mImage
Screen.Box 0,0,mSize[0],mSize[1]
EndFunction
/*Tarvitaan vain jaetussa ruudussa, piirtää näkymän ruudulle*/
Public Function Draw(Var x As Integer, Var y As Integer ) As Void
mImage.Draw x,y
EndFunction
EndClass
Sen jälkeen vielä itse CSprite-luokka, joka on se tärkein osa toiminnallisuutta. Se sisältää sen varsinaisen kuvan piirtämisen, skaalaamisen, läpinäkyvyyden ja pyörittelyn. Funktioita ovat:
- SetMask(r,g,b,a=255), jolla asetetaan maskiväri ENNEN KUVAN LATAUSTA.
- Load(file As String), jolla ladataan kuva
- SetOpacity( alpha ), jolla asetetaan läpinäkyvyys
- ChangeOpacity( alpha ), jolla muutetaan läpinäkyvyyttä
- Zoom( scale ), jolla skaalataan objektia
- SetScale( scale ), jolla asetetaan skaalaus tiettyyn arvoon
- ZoomX( scale ) ja ZoomY( scale ), jolla skaalataan objektia vain toisessa suunnassa
- SetScaleX( scale ) ja SetScaleY( scale ), jolla asetetaan vain tietyn suuntainen skaalaus
- Update(), jolla ei tee yhtään mitään, mutta jonka voi toteuttaa periytetyissä luokissa, eli tämä toimii periaatteessa virtuaalifunktiona
- Draw(), joka piirtää objektin suoraan näytölle. En suosittele käytettäväksi seuraavan funktion olemassa olon takia
- Draw( cam As CCamera ), piirtää objektin kameran kautta. Tämän käyttäminen mahdollistaaa helpon skrollattavuuden
- Opacity(), ScaleX(), ScaleY() ja Img() toimivat jälleen itsetutkiskelu funktioina, joiden palauttaman arvot jokainen voi päätellä
Lisäksi mukana on vielä kaksi luokan ulkopuolista funktiota: UpdateSprites() ja DrawSprites(cam), jotka kutsuvat Update()- ja Draw( cam As CCamera )-funktioita kaikille Pushatuille spriteille. Ja se koodi:
Code: Select all
Class CSprite Inherits CObject
Private Var mScale[2] As Float
Private Var mImage As Image
Constructor
mImage = New Image
mScale[0]=1.0
mScale[1]=1.0
EndConstructor
/*Palauttaa objektin läpinäkyvyyden*/
Public Function Opacity() As Float
Return mImage.GetOpacity()
EndFunction
/*Palauttaa objektin skaalausarvon leveyssuunnassa*/
Public Function ScaleX() As Float
Return mScale[0]
EndFunction
/*Palauttaa objektin skaalausarvon pituussuunnassa*/
Public Function ScaleY() As Float
Return mScale[1]
EndFunction
/*Palauttaa objektin kuvamuuttujan*/
Public Function Img() As Image
Return mImage
EndFunction
/*Asettaa maskin ladattavalle kuvalle. KUTSU ENNEN LATAUSTA!*/
Function SetMask(Var r As Integer, Var g As Integer, Var b As Integer, Var a As Integer=255)
mImage.Mask(r,g,b,a)
EndFunction
/*Lataa objektille kuvamuuttujan*/
Public Function Load( Var file As String ) As Void
mImage.Drop()
mImage.Load(file)
EndFunction
/*Asettaa objektin läpinäkyvyyden*/
Function SetOpacity(Var alpha As Float) As Void
mImage.SetOpacity(alpha)
EndFunction
/*Muuttaa objektin läpinäkyvyyttä tiettyyn suuntaan*/
Function ChangeOpacity( Var alpha As Float ) As Void
Var temp As Float=mImage.GetOpacity()
temp+=alpha
If (temp > 1.0) Then
temp=1.0
ElseIf (temp < 0.0) Then
temp=0.0
EndIf
mImage.SetOpacity(temp)
EndFunction
/*Skaalaa objektia tietyn monikertaiseksi*/
Function Zoom( Var scale As Float ) As Void
mScale[0]=mScale[0]*scale
mScale[1]=mScale[0]*scale
EndFunction
/*Asettaa skaalauksen tarkalleen tiettyyn arvoon*/
Function SetScale( Var scale As Float ) As Void
mScale[0]=scale
mScale[1]=scale
EndFunction
/*Skaalaa objektia leveyssuunnassa*/
Function ZoomX( Var scale As Float ) As Void
mScale[0]*=scale
EndFunction
/*Asettaa leveyssuuntaisen skaalauksen tarkalleen tiettyyn arvoon*/
Function SetScaleX( Var scale As Float ) As Void
mScale[0]=scale
EndFunction
/*Skaalaa objektia pituussuunnassa*/
Function ZoomY( Var scale As Float ) As Void
mScale[1]*=scale
EndFunction
/*Asettaa pituussuuntaisen skaalauksen tarkalleen tiettyyn arvoon*/
Function SetScaleY( Var scale As Float ) As Void
mScale[1]=scale
EndFunction
Public Function Update() As Void
/*Tämä on tyhjä funktio, voit periyttää luokan CSpritestä, ja toteuttaa sille oman update-funktion*/
EndFunction
/*Piirtää objektin*/
Public Function Draw() As Void
mImage.DrawRotated( mPos[0], Screen.Height()-mPos[1], mAngle, mScale[0], mScale[1] )
EndFunction
/*Piirtää objektin kameran mukaan*/
Public Function Draw( Var cam As CCamera ) As Void
Var camW=cam.Width()
Var camH=cam.Height()
Var camX=cam.X()
Var camY=cam.Y()
mImage.DrawRotated( (camW/2)+mPos[0]-camX, (camH/2)-mPos[1]+camY, mAngle, mScale[0], mScale[1] )
EndFunction
EndClass
Function UpdateSprites() As Void
Foreach iObj In CSprite
iObj.Update()
Next
EndFunction
Function DrawSprites( Var cam As CCamera ) As Void
Foreach iObj In CSprite
iObj.Draw(cam)
Next
EndFunction
Näiden jälkeen sitten vielä pari esimerkkiä käytöstä:
Yleistä esimerkkiä:
Code: Select all
Class CCow Inherits CSprite
Private Var mMoveX As Float
Private Var mMoveY As Float
Private Var mRotSpeed As Float
Constructor
This.SetMask(0,0,0)
This.Load("../media/cow.png")
This.SetPosition(Random(-400,400),Random(-400,400))
mMoveX=Random(-100,100)
mMoveY=Random(-100,100)
mRotSpeed=Random(-270,270)
This.SetOpacity(0.7)
EndConstructor
Public Overrided Function Update() As Void
Var dt As Float =Screen.GetFrameTime()
This.Rotate(dt*mRotSpeed)
This.Translate(mMoveX*dt,mMoveY*dt)
If (This.X()>800)|(This.X()< -800) Then
mMoveX= -mMoveX
EndIf
If (This.Y()>800)|(This.Y()< -800) Then
mMoveY= -mMoveY
EndIf
EndFunction
EndClass
Screen.Set 640,480
Screen.ClsColor(128,128,128)
Var camera As CCamera = New CCamera
Var obj As CSprite = New CSprite
obj.SetMask(0,0,0)
obj.Load("../media/guy.bmp")
For i=0 To 255
Var iObj As CSprite = New CCow
Push iObj
Next
Var dt As Float
Var cameraFollow=0
Push obj
Repeat
dt=Screen.GetFrameTime()
obj.Move(80*obj.ScaleX()*dt*(Key.Down(KEY_W)-Key.Down(KEY_S)),40*obj.ScaleX()*dt*(Key.Down(KEY_A)-Key.Down(KEY_D)))
obj.Rotate(180*dt*(Key.Down(KEY_Q)-Key.Down(KEY_E)))
obj.Translate(90*dt*(Key.Down(KEY_RIGHT)-Key.Down(KEY_LEFT)),90*dt*(Key.Down(KEY_UP)-Key.Down(KEY_DOWN)))
camera.Translate(90*dt*(Key.Down(KEY_NUMPAD6)-Key.Down(KEY_NUMPAD4)),90*dt*(Key.Down(KEY_NUMPAD8)-Key.Down(KEY_NUMPAD2)))
If Key.Down(KEY_Z) Then
obj.Zoom(1.0+dt)
ElseIf Key.Down(KEY_X) Then
obj.Zoom(1.0-dt)
ElseIf Key.Hit(KEY_C) Then
obj.SetScale(1.0)
EndIf
If Key.Hit(KEY_SPACE) Then
cameraFollow= Not cameraFollow
EndIf
If Key.Hit(KEY_RETURN) Then
camera.SetPosition(0,0)
EndIf
If cameraFollow Then
camera.CopyPosition(obj)
EndIf
obj.ChangeOpacity(dt*(Key.Down(KEY_2)-Key.Down(KEY_1)))
If Key.Hit(KEY_3) Then
obj.SetOpacity(1.0)
EndIf
UpdateSprites()
DrawSprites(camera)
If Mouse.Hit(0) Then
camera.Translate(Mouse.X()-320,Mouse.Y()-240)
EndIf
Screen.Color(255,255,255,128)
Screen.Box(2,2,380,42)
Screen.Color(255,0,0)
Screen.Line(2,2, 382,2)
Screen.Line(382,2, 382,44)
Screen.Line(382,44, 2,44)
Screen.Line(2,44, 2,2)
Screen.Color(0,0,0)
Screen.Text 4, 1,"Ukko liikkuu WASD:sta ja Q:sta ja E:sta, sekä nuolinäppäimistä"
Screen.Text 4,11,"Z:sta ja X:sta säätää kokoa, C:stä palauttaa oletuksen"
Screen.Text 4,21,"1:sta ja 2:sta muuttaa lapinakyvyytta ja 3:sta palauttaa oletuksen."
Screen.Text 4,31,"Numeronäppäimistöllä tai hiiren klikkauksilla liikuttaa kameraa."
Screen.Color(255,255,255)
Screen.Text 10,50,"FPS: "+Screen.FPS()
Screen.Text 10,60,"DeltaTime: "+dt
Screen.Text 10,70,"Obj.X: "+obj.X()+" | Obj.Y: "+obj.Y()
Screen.Text 10,80,"Scale: "+obj.ScaleX()+" | Angle: "+obj.Angle()
Screen.Text 10,90,"Opacity: "+obj.Opacity()
Screen.Text 10,100,"Cam X: "+camera.X()
Screen.Text 10,110,"Cam Y: "+camera.Y()
Screen.Text 10,120,"Cam Width: "+camera.Width()
Screen.Text 10,130,"Cam Height: "+camera.Height()
Screen.Draw()
Until Key.Hit(KEY_ESCAPE)
Jaettu ruutu:
Code: Select all
Screen.Set(800,600)
Var obj As CSprite = New CSprite
Var cam As CCamera = New CCamera
Var cam2 As CCamera = New CCamera
cam.InitImage(400,600)
Key.Wait()
cam.Rotate(90)
cam2.InitImage(400,600)
cam2.Rotate(90)
obj.SetMask(0,0,0)
obj.Load("../media/guy.bmp")
Repeat
Var dt As Float=Screen.GetFrameTime()
obj.Move 120*dt*(Key.Down (KEY_W)-Key.Down (KEY_S))
obj.Rotate 120*dt*(Key.Down (KEY_A)-Key.Down (KEY_D))
cam.Move 120*dt*(Key.Down (KEY_T)-Key.Down (KEY_G)),120*dt*(Key.Down (KEY_H)-Key.Down (KEY_F))
cam2.Move 120*dt*(Key.Down (KEY_I)-Key.Down (KEY_K)),120*dt*(Key.Down (KEY_L)-Key.Down (KEY_J))
Screen.Color 0,0,0
cam.DrawTo()
obj.Draw cam
cam2.DrawTo()
obj.Draw cam2
Screen.SetDrawBuffer(Null)
cam.Draw 0,0
cam2.Draw 400,0
Screen.Color 255,255,255
Screen.Line(400,0,400,600)
Screen.Draw()
Forever
CTileMap on kehityksessä, mutta seuraavaksi lisännen jonkinlaisen overlap-funktion CSpriteen, jos vain kerkeän. (Olen keskittynyt enemmän Wii-skenen ja DS-skenen seuraamiseen viimepäivinä)
Include-komennosta (jota kannattanee noiden koodien kanssa käyttää) ChaosEditorin yhteydessä: Include etsii tiedostoja aina viimeksi avatusta kansiosta. Jos sinulla on esim kansio A, jossa on kansiot B ja C, ja olet avannut koodin kansiosta B, joka käyttää includea kyseisessä kansiossa sijaitsevaan tiedostoon, ja avaat sen jälkeen koodin kansiosta C ja yrität kääntää B-kansion koodia, niin kääntäjä valittaa, että se ei löydä include-tiedostoa.