I need some working timing code.

BlitzMax Forums/BlitzMax Programming/I need some working timing code.

Amon(Posted 2007) [#1]
I have so far implemented Indiepaths Frame timing code and have used the Grey Alien Framework Example Timing code and I get odd results with both.

Using Indiepaths method everything jitters when moving. Removing the timing code solves this.

Using Greys Framework Example, everything jitters also and is moving about too fast. The annoying thing also is that the Logicwrapper and draw are function calls which means messy code. An example would be having 100 variables to track the state of the game ie. intro screen, title screen ect. and have to work it all within one draw function.

I could use the Grey Alien Framework but with the lack of documentaion and only 1 tutorial it becomes a chore to get anything done.

So, i need something that works.

If you have any timing code that you would like to share then please post it here with an example of use.


TartanTangerine (was Indiepath)(Posted 2007) [#2]
I have used the same timing code in iRoids, GEOM, cBubble, Part One and Part Two - all with silky smooth results. Perhaps you could post a snippit of your implementation that we could take a look at and make some suggestions.


tonyg(Posted 2007) [#3]
You could try this which has a simple example and a pointer to a tutorial. It's not as smooth as I'd like *but* is very simple. I tried the fixed frame-rate logic (posted the code somewhere on these forums) but it was too flakey.


Amon(Posted 2007) [#4]
I have used the same timing code in iRoids, GEOM, cBubble, Part One and Part Two - all with silky smooth results. Perhaps you could post a snippit of your implementation that we could take a look at and make some suggestions.


I Know. Which is why I know for a fact that I'm doing something wrong. I'm basin the code from your post which is from quite a while ago.

Is there any chance you can provide the same code but updated for Max 1.24?

@tonyg

I'll check that out, thanks.

:)


Dreamora(Posted 2007) [#5]
You have an AMD dualcore
Any chance you forgot to install the cool'n'quiet drivers?
If so, no chance you get jittery free, you have a CPU timming issue bound to the dynamic stepping technology of AMD


Amon(Posted 2007) [#6]
You have an AMD dualcore
Any chance you forgot to install the cool'n'quiet drivers?


Ahh. I have seen this "cool & Quiet" thing on the driver cd that came with my mobo. I don't think I've ever installed it; don't know why.

I'll install it now and will report back.

:)


HrdNutz(Posted 2007) [#7]
AMD Dual Core has an issue which keeps the 2 cores from cncronizing sometimes. When applications are run, there is a chance that your app thread will bounce between the 2 cores, and if they arent synced, you might have timing issues.

Look up the AMD Dual Core Optimizer - little piece of software ensures that the cores stay in sync.

beyond that, try averaging out your delta times ina buffer to equilize the jitters.


HrdNutz(Posted 2007) [#8]
This is what my timing code roughly looks like:
----------------------------------------------------------



UPDATE_FREQUENCY = 30 ' times per second
update_time = 1000 / UPDATE_FREQUENCY
execution_time += DELTA_TIME

While execution_time >= update_time
Update()
execution_time -= update_time
Wend

et:Float = execution_time
ut:Float = update_time
TWEEN:float = et/ut

' use tweening for motion interpolation
Render()


Grey Alien(Posted 2007) [#9]
mine is very similar except instead of rendering with Tween it passes that fractional value into the update function to be use as a delta value. The While loop normally passes in 1 as a delta value into update, so the tween is the remainder which is used in the final update. This is very accurate and smooth.

However, if your system is jerky (due to background tasks, bottlenecks, bad CPU timing etc) then no timing code in the world will look smooth, sorry.

Amon: that's one tutorial, one getting start doc, 2 FAQs, Common Types listing, Common Code function listing, one example timing demo, one basic title screen, one template, 3 mini-games and also support too ;-) Btw, it shouldn't run too fast (clue: my games don't) there must be something you are are doing wrong in the way you are using it. Mail me the code and I'll check it out.

Also you shouldn't have a single draw or logic function. Each screen should have it's own variables, sprites etc. Each screen then has it's own logic and draw and every object you draw on it should have it's own logic and draw functions. This is the OOP way and is lots easier to work with than one giant logic function and one giant draw function.


HrdNutz(Posted 2007) [#10]
Hi Grey :)

Could you plase elaborate on what you mean by rendering without tweening and passing tween to the update function? I was under the impression that any variants should be kept out of the update loop, so logic ticks at persistant intervals, and time discrepancies are used for rendering to give the 'illusion' of smooth movement.

thanks in advance,
Dima


Grey Alien(Posted 2007) [#11]
HrdNutz; Yeah basically originally I had an update loop running at 200Hz (this was pretty smooth). But then I also had this remainder left over each time and I hadn't really looked into tweening. So I decided to pass the remainder (as a fraction of 1) into the update function on the last iteration each frame - I call it delta. Normally the update function is passed 1. All my counters and so on are floating point and I multiply any changes to them by Delta. This seems to work totally fine, is very smooth and time is never lost.

Also I can turn off VSync and it works too. Quite often the time difference will be 0ms so the update loop won't get called but sometimes it's 1ms and it will get called ONCE but with a fractional delta. This means that my game timing works the same with VSync on or off. Also I can run a slow motion mode.

I even ran sswifts sprite physics demo with this code and it was fine.

I guess an alternative would be to keep the remainder and add it onto the next batch of update loop iterations instead so that only whole numbers are used.


Amon(Posted 2007) [#12]
Also you shouldn't have a single draw or logic function. Each screen should have it's own variables, sprites etc. Each screen then has it's own logic and draw and every object you draw on it should have it's own logic and draw functions. This is the OOP way and is lots easier to work with than one giant logic function and one giant draw function.



I'm not using the framework for this. I'm just using your example timing.bmx file and trying to intergrate it with my code. Example timing has a logicwrapper and draw function. I don't know how to OOP this. I'm not as good a programmer as you, by far.

TBH all I'm interested in is the exampletiming.bmx. I don't know how to make it so that I don't have to have everything in one LogicWrapperFunction or one Draw Function.

An update to the jerkyness is that i installed the Cool & Quite Drivers and I also used what HrdNutz recommended and the jittering has gone, almost.


Grey Alien(Posted 2007) [#13]
Ah I see. Well the LogicWrapper Function can call a number of different logic functions, one for each unique type (or list of types) - that's why it's called a Logic "wrapper" :-) Same for the draw() function.

So like this (code not tested, just an example):

Global MyScreen:TMyScreen 'then load in its graphics
Global Player:TPlayer 'then load in its graphics
 
Type TMyScreen
  Field Background: TImage
  Field Logo: TImage
  Field Logox#
  Field Logoy#
  Field LogoSpeed#

  Method logic()
     'Move the logo round
     Logox:+LogoSpeed*Delta 'Delta is made my my timing code 
  End Method

  Method Draw()
    DrawImage Background,0,0
    DrawImage Logo,logox,logoy
  End Method
End Type

Type TPlayer
  'Fields for player graphics and coords

  Method Logic()
    'whatever
  end method

  Method Draw()
    'draw the player
  End Method
End Type

'Then in the Logic Wrapper you do this
Function LogicWrapper()
  'whatever you want plus...
  MyScreen.Logic()
  Player.Logic()
End Function

'Then in the Draw() you do this
Function Draw()
  'whatever you want plus...
  MyScreen.Draw()
  Player.Draw()
End Function


Does that make sense? It's very neat then, every type handles itself.

Glad to hear those drivers made a big difference. Didn't realise that stepping was such a big issue. How come it only affects BMax and not other games then?

***Could BMax be made more stable for AMD dual core setup (which don't have the drivers installed?*** THAT is a really important question.


Amon(Posted 2007) [#14]
Ahh! That actually makes sense. Thanks. :)

How come it only affects BMax and not other games then?



It wasn't just affecting BMax on my machine. I have a game I bought on Ebay "severennce - Blade Of Darkness", this game jittered to the point of being unplayable up until I installed those drivers.

Pro Evo 6 would jitter also although not as bad. Playing online matches in Evo 6 was impossible. I though it was network lag caused by my cable connection but it all seems to be working fine now.

I didn't think too much of those Cool & Quite Drivers when i first got the system as I didn't know what they were meant to do. Turns out they were very important.

Makes me wish though that i had gone with Intel Chips instead.


Dreamora(Posted 2007) [#15]
The driver issue is not BM bound nor can you do anything against it.

It is caused by calculations and assumptions within windows which end wrong if the driver is missing.
For that reason all that did not disable it and let their AMD64 run at max speed will suffer from the problem.

Its one of the main reasons some have "physical simulation problems" in games like stuff passing through ground, "shooting off" objects as they collide and penetrate and the like.


Amon(Posted 2007) [#16]
Its one of the main reasons some have "physical simulation problems" in games like stuff passing through ground, "shooting off" objects as they collide and penetrate and the like.



Stuff like that occured in my 3impact programs when using Physics. I haven't tried to see if it still occurs though as I'm working on something with the B3DSDK.


Grey Alien(Posted 2007) [#17]
wow that's nuts. Oh well, guess it's gonna screw up my games on quite a few AMDs...


HrdNutz(Posted 2007) [#18]
Hey Grey, thanks for the update regarding your timing. However, i'm not sure I fully understand O.O If you're passing anything but whole deltas to your update loop, doesn't that make it not extirely fixed step? Maybe I'm missing something, i haven't been keeping up with this lately, but i was under the impression that with a fixed step timing the idea is that logic always ticks at set interval, no matter what, and the remainders of time are used to simulate smooth animation in between those updates (during remder time). The idea is that logic time steps never change, not even by a fraction, so theoretically same exact steps of logic can be reproduced exactly, like recording player input and doing a 'replay' playback, or syncronizing network updates.

For my stuff I use low frequency updates, from 15 to 50 times per second. This almost guarantees that there will be several frames per each update, and each of those frames draws an interpolated value, thus appearing super silky smooth. I used to use high frequency updates (200+hz) without tweening, but that results in a few things: if you're not tweening between the updates (but keeping updates at totally fixed intervals) then I noticed that depending on the framerate, if I had more than one, or less than two, updates happening per frame (not a whole number of updates) then stuff could potentially get jerky. Also, high frequency updates may be putting extra stress on CPU, because you're always forcing more updates usualy than the framerate.

But it seems that passing anythng to the update loop other than fixed interval deltas kind of defeats the point of Fixed Time Steps. I may be not understanding something though.


HrdNutz(Posted 2007) [#19]
Here's a simple example of Fixed Step Timing and Motion Interpolation. The code runs at 10hz, and is totally frame rate independent. The better the framerate, the smoother the first ball will move, and it will always update same amount of times per second.

note: thre is no mechanics of trying to equilize jitters, for simplicity of code. Also, this will render alot more frames per each update, as fast as the comp will allow, but it's not forcing more updates than possible framerate and keeping them to a minimum (10 is is a bit low, but is used here for clarity purposes)
Graphics(640, 480, 32)

Global UPDATE_FREQUENCY = 10 ' times per second
Global update_time = 1000 / UPDATE_FREQUENCY
Global t , dt , execution_time = 0

' boucing ball
Global X# , oldX#
Global dirX# = 1

t = MilliSecs()
While Not KeyDown(KEY_ESCAPE)
	dt = MilliSecs() - t
	t = MilliSecs()

	execution_time:+ dt
 
	' fixed interval update loop    		
        While execution_time >= update_time		
		Update()
		execution_time:- update_time
	Wend
	
	' calculate the remainder for motion interpolation
	Local et# = execution_time
	Local ut# = update_time
	Local tween# = et / ut
	
	Render(tween)
Wend

Function Update()
	' time independent speed
	Local Speed# = 150.0 / (1000.0 / Float(update_time)) ' 150.0 pixels per second
	
	' record the old position for tweening
	oldX = X
	
	' move the ball
	X:+ (Speed * dirX)
	
	' reverse directions if ball is out of screen bounds
	If X < 0 Or X > 640 Then dirX = - dirX
End Function

Function Render(tween#)
	Cls
	' interpolate between old and actual positions
	Local tx# = X * tween + OldX * (1.0 - tween)	
		
	' draw bouncing ball with interpolated values
	DrawOval tx - 16 , 50 , 32 , 32
	
	' draw second bouncing ball WITHOUT tweening
	DrawOval X - 16 , 200 , 32 , 32
	
	Flip
End Function
	



Grey Alien(Posted 2007) [#20]
Yeah my code is fixed rate logic not fixed step i.e. it runs at a fixed rate (200HZ). It used to be fixed step before I added the final loop iteration which uses the delta value. This makes sure it moves very smoothly, espcially as in BMax you can draw everything at floating point coords.


Amon(Posted 2007) [#21]
Update.

It appears that there was nothing wrong with either timing method from Grey Alien or from Indiepath.

The Grey Alien Framework and the ExampleTiming that is part of it all work without flaws.

It was an error on my part that was causing the issue.

Apologies to both Indiepath and Grey for not looking further in to this before putting down their timing methods.

:)