in game timers with blitz3d

Blitz3D Forums/Blitz3D Programming/in game timers with blitz3d

skyfire1(Posted 2005) [#1]
i know how to use timers for 2d games but can anyone tell me how to use timers for 3d games?


Orca(Posted 2005) [#2]
time is time. I don't know exactly what you're trying to do, but it shouldnt really matter.

Are you talking about delta timing?( though, once again, delta timing works the same way regardless..)


Jams(Posted 2005) [#3]
Yes, plese elaborate on your question......


skyfire1(Posted 2005) [#4]
you make a timer using createtimer() right? to keep a 3d game running at a constant rate, do you code something like the example below or do you pick a different method close to the one below?


;set up variables
timer = createtimer(60)

;game loop
frames = waittimer(timer)

for k = 0 to frames
UpdateLogic()
UpdateWorld()
next

;end of game loop




Orca(Posted 2005) [#5]
That's not very efficient, but it will slow down your loop.

You are much better off using delta timing. The whole idea is to track how fast your game is running, and adjust all the in game changes that are dependant on time( usually the movement of your game objects ).

Say you move an object 1 unit per frame. In 1 second:

@ 100 fps, that object will move 100 units.

@ 50 fps, that object will have moved only 50 units.


Delta timing solves that by adjusting the movement to how fast your game is being processed.


So going back to the previous example, lets say we set our delta timer to run at 75 fps. We now have to multiply our movements by a delta factor.

@ 100 fps, the object will now move at ( 75 / 100 ) * 1 units per frame. This comes out to 75 units per second.

@ 50 fps, the object will now move at ( 75 / 50 ) * 1 units per frame. This comes out to 75 units per second.

Despite the fact that the machines are both running the game at different speeds, the in game object has moved the same amount.

You have to update your delta timer each loop so it's aware of how fast your game is running. This is awesome because now your game adjusts itself to increases and drops in framerate. And you're not wasting valuable time in your loop, waiting around idle for a timer to finish.


skyfire1(Posted 2005) [#6]
but what about functions like moveentity()?


Orca(Posted 2005) [#7]
It doesnt matter.

whatever the delta factor is, you multiply it against your movement.

MoveEntity entity, vx * delta, vy * delta, vz * delta

Anything that moves and is going to be affected by time gets multiplied by the delta.


skyfire1(Posted 2005) [#8]
okay.


Storm8191(Posted 2005) [#9]
This may be slightly off-topic, but I've honestly had quite a bit of trouble using Delta Timing. It's not that there are problems with moving things at a constant rate - that's what Delta-timing is good at. The problem is when you want objects to slow down or speed up gradually. Think of an object being tossed up into the air. It goes up, slows down until it turns around, and then speeds up going down.

Delta timing doesn't work so well for this. I've tried multiple equations but haven't found anything that works properly yet. Simply multiplying the change in speed bye delta time doesn't yield proper results, and without doing something, object speeds change more slowly when delta time is a high value.

I'm not sure what to do about it, so if anyone has any good ideas, I'd like to hear them.


skyfire1(Posted 2005) [#10]
i just used delta timing but i had the same problem as storm.


Jeroen(Posted 2005) [#11]
i use frame tweening.


WolRon(Posted 2005) [#12]
In case my Delta-timing example is of any help...
http://home.cmit.net/rwolbeck/programmingtutorial/reference/framelimiter.htm

The problem is when you want objects to slow down or speed up gradually. Think of an object being tossed up into the air. It goes up, slows down until it turns around, and then speeds up going down.
Delta timing doesn't work so well for this. I've tried multiple equations but haven't found anything that works properly yet. Simply multiplying the change in speed bye delta time doesn't yield proper results, and without doing something, object speeds change more slowly when delta time is a high value.

Delta time shouldn't effect this at all. I suspect that you are trying to improperly use it.

For example, if your object would normally move x amount per frame, but it is slowing down, then your code might look like this:
theObjectsYvelocity# = theObjectsYvelocity# * .95   ;slow down 5%
Then you would still have to multiply it by Delta time:
theObjectsYvelocity# = theObjectsYvelocity# * deltaTime#
Don't use Delta Time to adjust your objects speeds. That is not the purpose of it.


skyfire1(Posted 2005) [#13]
ok. i think i get the concept for delta timing now. thanks for the help.


DH(Posted 2005) [#14]
sorry wolron, I have used delta time in the past and found it to be a pain with Blitz.

Simple fact is that blitz millisecs() isnt all that accurate in the first place. Secondly, if your code is running at 1000 fps (meaning virtually 0ms between scan), how are you supposed to use that in getting your deltatime factor?

Delta time has never been smooth for me, and I know I am properly implimenting it. I currently use a way of slowing down the game to a frame rate around 60 fps. In that frame I check to see how long the last render and flip took and simply based the number of logic loops on that (meaning if the render/flip took longer, then I will have more logic loops running to make up for the time difference and vice versa).

This keeps it steady and accurate. Juyst my 2 cents though


WolRon(Posted 2005) [#15]
Simple fact is that blitz millisecs() isnt all that accurate in the first place.
I highly doubt that...

Secondly, if your code is running at 1000 fps (meaning virtually 0ms between scan), how are you supposed to use that in getting your deltatime factor?
If you look at the Delta-timing code on my website, you will see that it deals with that occurence.
If FL\SpeedFactor# <= 0 Then FL\SpeedFactor# = 0.00000000001



DH(Posted 2005) [#16]
If you look at the Delta-timing code on my website, you will see that it deals with that occurence.
If FL\SpeedFactor# <= 0 Then FL\SpeedFactor# = 0.00000000001


It has been stated here many times that Blitz3d floats are not accurate! How can you trust a Blitz3d Float value out 11 decimals and then multiplying that by another minute factor which will result in a virtual 0. And we all know that a virtual 0 over 10,000 scans is still 0!

I'm not saying your delta time is bad, but when you start dealing a ton more in physics libraries you will find that delta time is worthless in Blitz3d.

For small projects, simple games, or FPS games (simple fps games), yes perhaps delta time will prove to be efficient 'enough'. But getting more advanced in game play and the what is going on in your enviroments delta time will merely give you movement 'artifacts'.


WolRon(Posted 2005) [#17]
How can you trust a Blitz3d Float value out 11 decimals and then multiplying that by another minute factor which will result in a virtual 0. And we all know that a virtual 0 over 10,000 scans is still 0!
If you multiply the Delta-time against the CHANGE IN VALUE and not the ACTUAL VALUE, then a net zero result will not matter (the original value stays the same).

For example, instead of doing this:
value# = value# * deltatime#
you would do this:
value# = value# + change# * deltatime#

As far as Blitz floats only being 32 bit, that's a limitation of Blitz floats, not of the Delta-timing code.


aab(Posted 2005) [#18]
Idont often use Deltatime for a few reasons (Ignoring that calculating Accurately inrementing Milliseconds in a Windows operating system possibly em..impossible : calls like GetTickCount() and timeGetTime() are jumpy, and using QueryPerformanceCounter() and QueryPerformanceFrequency() though being effective requies time itself, so by the time ou get the result time with presicion to milliseconds has passed)

Firstly, your involving a multiplication in so many values that that itself is an addition to any slowdown: Although i admit i dont like the look of extra code either, especially where a time related variable has to be passed to so many game procedures (youll never hear a global from me: Im OOP all the way, or as close as i can get).
Secondly, if a game is too slow to play, large choppy movements wont really solve the problem that well: Consider an fps where you turn right,a dn after half a second you get to see where your targeting: Its even less impossible to target than it would be were it running slowly such that a great amount of time would pass to turn around (Not that i would suffer playing like that either).
Sacrafice to the collision-queried positions in larger movements is also a trouble: {Er...by that i mean say you had a 2d blitz game, using ImagesCollide, where images might end up moving too fastly through each other if the frame rate was dropping}: Although that could be resolved by checking collision of objects through their paths or by dividing the lengths into the desired minimum distance intervals to check for collision and working each position out in order - again however more code to work through, more logic, more complication etc.
I desire accurate logic above my expected render-rates though: For example i mainly say, set a limit on the frame rate to 60 fps and render if the fps was high enough and the frame was even not odd {This (*Crappy*) method suffices simple projects} but i never take frames out of logic while letting rendering work at full pace: Not in a game.


WolRon(Posted 2005) [#19]
Secondly, if a game is too slow to play, large choppy movements wont really solve the problem that well: Consider an fps where you turn right,a dn after half a second you get to see where your targeting: Its even less impossible to target than it would be were it running slowly such that a great amount of time would pass to turn around (Not that i would suffer playing like that either).
Sacrafice to the collision-queried positions in larger movements is also a trouble: {Er...by that i mean say you had a 2d blitz game, using ImagesCollide, where images might end up moving too fastly through each other if the frame rate was dropping}:
Both of these scenarios are moot, because a simple addition to your code (such as
If FL\SpeedFactor# > 2.0 Then FL\SpeedFactor# = 2.0
) would prevent both of those scenarios from occuring. Sure, the program will run slower than intended, BUT if the PC is too slow to run the program, then it's TOO SLOW. Delta-time isn't intended to make a slow PC run faster, it's intended to attempt to make a program run more smoothly. But alas, if it's not possible, then it's not possible.

Use delta-time for what it's intended to be used as, not as some kind of speed enhancement code.

but i never take frames out of logic while letting rendering work at full pace:
I don't know why you stated this. Delta-timing doesn't do this.


Storm8191(Posted 2005) [#20]
Wolron, I don't think you quite understand my problem. Take this for example:

;Move the ship
shipxpos# = shipxpos# + (shipxspeed# * delta#)

;Apply friction
shipxspeed# = shipxspeed# * 0.95  


Now, I assume this is how you mean to use delta timing. The problem is, the ship does not slow down at the same rates with different delta times. If the game runs quickly, the speed value will decrease at a fairly fast rate, and the ship will stop in a short distance. However, if the game is running slowly, the delta time will cause the ship to move faster for every loop, but its speed will decrease at the same loop rate (slower in world time). The result is that the ship will stop a much further distance away, and take longer to stop.

I got to looking at this problem further, and it may be solvable if you subtracted away from the speed, instead of multiplying a <1 value. But the problem, as stated, remains. Sometimes this is the more desirable effect you want your game to have.


John Pickford(Posted 2005) [#21]
A slight tangent but strictly speaking friction should be a constant, not proportional to speed. You could probably use 'constant*delta' to replace all your accellerations and actually get more realistic physics.

That doesn't especially help your *specific* problem though. You're changing the speed without regard to the delta. You have no idea how often that speed change will occur so obviously it could go wildly wrong. I'm sure someone with better maths than me can come up with the algorithm to correct this.

I avoid delta timing for the same reasons. I'm just too used to doing things iteratively and it would be easy for me to make a mistake like the above example.

In my game I set a 'framerate' for the logic (40 fps) but leave the game free-running. In each cycle I check the real time and call the logic n times (often 0) depending on how much time has elapsed. So my game can be running with a graphicsl framerate of anywhere between 30-240fps (and it does!) without the logic going astray.

Delta timings *might* be more CPU efficient. I'm not sure. In my system the logic gets called 40 times per second whatever. If I was using delta it might get called 200times on occasion.


Grey Alien(Posted 2005) [#22]
John is right, you can't reduce shipspeed by multiplying by a constant. Acceleration is defined as metres per second per second so you need to modify you constant depending on how much time has elapsed. Just using delta might be too big a value so try delta/10 and see what happens.


Banshee(Posted 2005) [#23]
The problem is when you want objects to slow down or speed up gradually.

I use interupts to apply multiplication and division to delta timing, ie:

interupt=interupt +delta
while interupt=> 5
   gradualAcceleration=gradualAcceleration *1.01
   interupt=interupt-5
wend



John Pickford(Posted 2005) [#24]
I don't understand that at all. Blitz doesn't allow interrupts anyway.


Banshee(Posted 2005) [#25]
@John, it's a software coded interupt/timer.

Imagine the example above where the person (i'm too lazy to read back and see who) executed their logic at 40fps and their 3D world at whatever the computer could run at.

Well this method does the same thing, but only to the specific code encapsulated inside the interupt while{} structure.

In my above code snipper the interupt variable is being increased by the delta time delay, then the while{} structure starts which reduces it by 5 per execution (1000/5=200fps) therefore executing the code inside at a constant rate, yet still maintaining compatability with the delta timing principle.

This method allows the programmer to get all the advantages of delta timing, and overcome its shortcomings by combining it with constant rate mathematics - interestingly, the programmer can make particular tasks faster than others too so in a car race sim you could make your acceleration run at 200fps, but your AI decision making might run on a 10fps interupt.


Mr Snidesmin(Posted 2005) [#26]
Here's a novel idea I just thought of. . . I haven't tried this and I'm not sure if it would work, but what if. . .

1) you set an optimal framerate, say 35 fps

2) each loop you randomly either draw a frame or update the logic.

3) keep track of the frame rate

4) if the framerate exceeds the optimal, then slightly increase the chance of updating logic / decrease chance of rendering and vica versa

5) set limits (probably best based on a mininum # of updates per sec) so that it doesn't become impossible to render or update.

6) use delta timing in your update loop to keep movement consistant.

That way you should be able to run at near enough your optimal frame rate and update as much as is possible at that framerate with no time loss. You would also easily allow the user to adjust their optimal framerate - so a slow computer could use an optimal of say 20 fps etc and the physics would therefore not suffer, and someone with a super fast computer could run as fast as they are able to, without the loss of update accuracy.

I think I'll try this and see if it works. . .


WolRon(Posted 2005) [#27]
Storm8191, as John Pickford pointed out, you are applying delta-time to the ships velocity, but you failed to apply delta-time to the ships frictional coefficient.

So your code should really look something like this:
;Move the ship
shipxpos# = shipxpos# + (shipxspeed# * delta#)

;Apply friction
shipxspeed# = shipxspeed# * (1.0 - ((1.0 - 0.95)* delta#))  
That should be more desirable.


Banshee(Posted 2005) [#28]
shipxspeed# = shipxspeed# * (1.0 - ((1.0 - 0.95)* delta#))


Would actually read as
shipxspeed# = shipxspeed# * (.05* delta#)

I think, which doesnt work. You cannot multiply by a delta - only add or subtract. However as I showed in my example above if you perform the multiplication or division at an interval using a software timer you can effectively use constant fps mathematics and still get all of the advantages of delta timing.


Viperfish(Posted 2005) [#29]
without delta timing.
shipxspeed# = shipxspeed# * 0.95

with delta timing
shipxspeed# = shipxspeed# * (0.95^delta#)

Additions and subtractions are multiplied by your delta.
Multiplications and divisions are raised to the power of your delta.

Works perfectly in my projects.


BlackD(Posted 2005) [#30]
Thanks WolRon - like your page. I'd set the 0 value to 0.000001 as that's the epsilon value Mark uses in GEOM.H for B3D and if it's good enough for Mark, it's good enough for me. ;) But it makes delta very easy to understand for anyone.

And thanks John for clearing up the differences of which syntax to use for delta calculations. I've always been a TIMER person, but have been reminding myself I need to switch to delta sometime soon and I think I'll do it now. :)

+BlackD