Function In Type?

Previous topic - Next topic

Amon

I'm trying to convert some Mojo code to GLBasic but having a little difficulty. It seems to work but not as desired. The code is some simple custom Delta Timing code I used in Mojo. Code below:

Code (glbasic) Select


Import mojo

Class DeltaTimer

' Usage...

' 1) Create DeltaTimer object, eg.
' "Local dt:DeltaTimer = New DeltaTimer (60)"
' where 60 is your game's intended frame rate,
' regardless of device frame rate.

' 2) Call dt.UpdateDelta at start of OnUpdate...

' 3) Multiply all speeds by dt.delta...

' 4) That's it.

Field targetfps:Float = 60
Field currentticks:Float
Field lastticks:Float
Field frametime:Float
Field delta:Float

Method New (fps:Float)
targetfps = fps
lastticks = Millisecs
End

Method UpdateDelta ()
currentticks = Millisecs
frametime = currentticks - lastticks
delta = frametime / (1000.0 / targetfps)
lastticks = currentticks
End

End

Class Game Extends App

Global FPS:Int = 60

' Position/speed of example rects...

Field ux:Float = -16 ' Position increased by uncorrected speed
Field dx:Float = -16 ' Position increased by DELTA-CORRECTED speed
Field xs:Float = 4.0 ' Speed

Field dt:DeltaTimer ' A handle for the delta timer (to be created in OnCreate)

Method OnCreate ()
dt = New DeltaTimer ( FPS ) '  Gameplay update rate...
SetUpdateRate FPS ' ... may be different to device/app update rate!
End

Method OnUpdate ()

' ---------------------------------------------------------------------------
' 1) Get new frame delta...
' ---------------------------------------------------------------------------

dt.UpdateDelta

' ---------------------------------------------------------------------------
' 2) Multiply speeds by frame delta...
' ---------------------------------------------------------------------------

ux = ux + xs ' Speed NOT scaled by frame delta, ie. how NOT to do it...
dx = dx + xs * dt.delta ' Speed scaled by frame delta...

' Wrap rects around screen...

If ux > DeviceWidth + 16 Then ux = -16
If dx > DeviceWidth + 16 Then dx = -16

' Change FPS on the fly to see effect...

If KeyHit (KEY_LEFT)
FPS = FPS - 10
If FPS < 10 Then FPS = 10
SetUpdateRate FPS
Endif

If KeyHit (KEY_RIGHT)
FPS = FPS + 10
SetUpdateRate FPS
Endif

If KeyDown (KEY_ENTER)
FPS = 60
SetUpdateRate FPS
Endif

End

Method OnRender ()

Cls 32, 64, 128

DrawText "Time scale factor (Delta): " + dt.delta + " (Frame time: " + dt.frametime + " ms)", 0, 20

SetColor 255, 0, 0
DrawRect ux - 16, 200 - 16, 32, 32
SetColor 255, 255, 255
DrawText "Uncorrected", ux - 16, 200 - 32

SetColor 0, 255, 0
DrawRect dx - 16, 260 - 16, 32, 32
SetColor 255, 255, 255
DrawText "Corrected by delta timing", dx - 16, 260 - 32

DrawText "Use <- and -> plus ENTER to change game update rate (currently " + FPS + " fps)", 0, 60

End

End

Function Main ()
New Game
End


- http://www.amon.co | Dev Tools - BlitzMax - Shiva Unlimited - Unity Pro - Carrara 8 Pro - Hexagon 2.2.5 - Blacksmith 3D Paint - FuturePaint Pro - Bryce 7 Pro.
I'm never wrong at all; I just discover 1000 ways that don't work!

MrTAToad

I'll do all the work for you :

Code (glbasic) Select
// --------------------------------- //
// Project: AppTimer
// Start: Thursday, September 11, 2008
// IDE Version: 5.360

//! This help file contains information for using the AppTiming system, which can be used to give a consistent movement speed
//! independant of the processor speed
//! The original code was for BlitzMax, and was written by JoshK
//! Converted to GLBasic by Nicholas Kingsley
//! You call the routines like :
//! LOCAL blah AS TAppTime
//! blah.Initialise_AppTime()
//! speed=blah.Update_AppTime()

TYPE TAppTime
AppTime_UPS;AppTime_Iterator;AppTime_CurrentTime;AppTime_PauseStart;AppTime_Speed;AppTime_DesiredLoopTime;AppTime_LastUpdateTime
AppTime_LastUPSTime;AppTime_DesiredFrequency%

//! This function initialises the AppTimer system, and must be called first.
//\param frameRate% - This is the frame rate that you want all movement to be based on.  It defaults to 60 FPS, which is the lowest rate that should be used.
//\return Nothing is returned
FUNCTION Initialise%:frameRate%=60
self.AppTime_UPS=0.0
self.AppTime_Iterator=0.0
self.AppTime_CurrentTime=0.0
self.AppTime_PauseStart=0.0
self.AppTime_Speed=1.0
self.AppTime_LastUpdateTime=0.0
self.AppTime_LastUPSTime=0.0
self.AppTime_DesiredLoopTime=1000.0/(frameRate*1.0)
RETURN TRUE
ENDFUNCTION

//! This function updates the timing system.  It needs to be called once per loop.
//\param No parameters are passed
//\return A movement value is returned.  This should be muliplied by the amount you want to move.  If the routine is paused, then 0.0 is returned
FUNCTION Update:
LOCAL time
LOCAL elapsed

IF self.AppTime_PauseStart<>0
RETURN 0.0
ENDIF

time=GETTIMERALL()

IF self.AppTime_LastUpdateTime=0.0
self.AppTime_Speed=1.0
self.AppTime_LastUPSTime=time
ELSE
elapsed=time-self.AppTime_LastUpdateTime
IF elapsed=0.0
elapsed=1.0
SLEEP 1
INC time,1.0
ENDIF

self.AppTime_Speed=elapsed/self.AppTime_DesiredLoopTime
ENDIF
self.AppTime_LastUpdateTime=time
self.AppTime_CurrentTime=time

INC self.AppTime_Iterator,1.0 // Its a float as it can go very large...

IF self.AppTime_CurrentTime-self.AppTime_LastUPSTime>=1000.0
self.AppTime_UPS=self.AppTime_Iterator/((self.AppTime_CurrentTime-self.AppTime_LastUPSTime)/1000)
self.AppTime_LastUPSTime=self.AppTime_CurrentTime
self.AppTime_Iterator=0
ENDIF

RETURN self.AppTime_Speed
ENDFUNCTION

//! This function is used when your program is paused or not.  If it is, then the step speed is still updated
//\param pause% - If this is TRUE, then your program is paused.  If FALSE, then it isn't
//\return Nothing is returned
FUNCTION Pause%:DoPause%
LOCAL elapsed

IF DoPause%=TRUE
IF self.AppTime_PauseStart=0.0
self.AppTime_PauseStart=GETTIMERALL()
self.AppTime_UPS=0
self.AppTime_Speed=0
ENDIF
ELSE
IF self.AppTime_PauseStart<>0.0
IF self.AppTime_LastUpdateTime<>0.0
elapsed=GETTIMERALL()-self.AppTime_PauseStart
INC self.AppTime_LastUpdateTime,elapsed
ENDIF

self.AppTime_PauseStart=0.0
self.Update()
ENDIF
ENDIF
ENDFUNCTION

//!  This function returns the updates per second, and is an approximation
//\param No parameters are passed
//\return Updates per second
FUNCTION UPS:
RETURN self.AppTime_UPS
ENDFUNCTION
ENDTYPE

Amon

#2
Thank You! I'll check out your code but it wasn't necassary at all to do all the work :)

I'm going to post my code so far as I've understood it from the docs when reading on types. I don't have the functions in a type, instead I passed the function by reference as in the docs.

This is plainly for my own learning of GLBasic so if it is all wrong please point out where it's noobing.

I do appreciate you converting the code though but before I read it I need to understand where I'm going wrong with my attempt, for learning purposes.

edit: Removed code; posting this mornings update.

I have it all compiling fine but what I'd like to do now is seperate the logic from the drawing by having the Draw function in the main loop and the Logic updating itself independant of the main loop.

Possible? Yes it is but first I must find all the ways that don't work in order to find what does and to do that I must code and learn. :) Help though would be appreciated.

Code (glbasic) Select

SETCURRENTDIR("Media")

GLOBAL BlueShip% = 0
LOADSPRITE "BlueShip.png", BlueShip
GLOBAL sx#, sy#
GETSPRITESIZE BlueShip, sx, sy

GLOBAL dw%, dh%
GETDESKTOPSIZE dw,dh

GLOBAL ESCAPEGAME% = 0

?IF WIN32
?DEFINE SCREENRES
?DEFINE STARTPOS
?ENDIF

?IF SCREENRES
LOCAL dww = 800, dwh = 600
SETSCREEN dww, dwh, 0
?ENDIF

?IF STARTPOS
GLOBAL BShipX# = (800.0 / 2.0) - sx / 2.0
GLOBAL BShipY# = 500.0
?ENDIF

GLOBAL dt AS DeltaTimer
dt.InitDelta()
dt.SetDeltaFPS(60.0)


REPEAT
dt.UpdateDelta()
CLEARSCREEN
Draw()
SHOWSCREEN
UNTIL ESCAPEGAME = 1

END


TYPE DeltaTimer
targetfps#
currentticks#
lastticks#
frametime#
delta#

FUNCTION InitDelta :
self.targetfps = 0.0
self.currentticks = 0.0
self.lastticks = 0.0
self.frametime = 0.0
self.delta = 0.0
RETURN TRUE
ENDFUNCTION

FUNCTION SetDeltaFPS : fps#
self.targetfps = fps
self.lastticks = GETTIMERALL()
RETURN fps
ENDFUNCTION

FUNCTION UpdateDelta :
self.currentticks = GETTIMERALL()
self.frametime = self.currentticks - self.lastticks
self.delta = self.frametime / (1000.0 / self.targetfps)
self.lastticks = self.currentticks
Logic()
RETURN TRUE
ENDFUNCTION

ENDTYPE

FUNCTION Logic:
IF KEY(203) AND NOT KEY(205) THEN BShipX = BShipX - 3.0 * dt.delta
IF KEY(205) AND NOT KEY(203) THEN BShipX = BShipX + 3.0 * dt.delta
ENDFUNCTION

FUNCTION Draw:
IF KEY(01) THEN ESCAPEGAME = 1
ALPHAMODE -1
DRAWSPRITE 0, BShipX, BShipY
ALPHAMODE 0
ENDFUNCTION
- http://www.amon.co | Dev Tools - BlitzMax - Shiva Unlimited - Unity Pro - Carrara 8 Pro - Hexagon 2.2.5 - Blacksmith 3D Paint - FuturePaint Pro - Bryce 7 Pro.
I'm never wrong at all; I just discover 1000 ways that don't work!