HookTimer: How reliable is it? And velocity movement.
Displaying 1-10 of 10 total.
1
Please enter a numerical value for the importance of this sticky.
Enter 0 to unsticky.
blues_zodiakos

I know that under default settings, hooktimer is supposed to be called 100 times a second. How reliable is this? If the game itself is running slowly, will hooktimer still be called reliably at 100 times a second, or does it have a lower priority? I'm trying to have an entity move at say, 4 pixels per second across the screen (pretty slow, but that's just an example), and I want to have a reliable, easy way of maintaining exactly how many pixels per frame that is. I can't rely on frame throttling, because I want my game to render at the max fps possible on the target computer, while still looking the same on any computer running it. I know this has come up before, but I still can't wrap my brain around it. Is it simply:

PixelsMovemedThisFrame = PixelVelocityPerSecond / FramesPerSecond

1 = 60 / 60 (makes sense)
4 = 240 / 60 (fps if throttled to exactly 60... a velocity of 240 would yield a movement of 4 pixels per frame, speedy)
8 = 240 / 30 (maybe this works)

So here's the problem, and I'm sure it's related to decimals and floats. How do I manage the problem if the pixel velocity is below the fps?

1 = 1 / 60 (actually .016 etc., but verge rounds up, so the entity will ALWAYS move at least 1 pixel a frame)

This could be a problem. The end result, I think, is that all objects would move at a minum of (fps) pixels per frame - and that could be all the way up to who knows how many! If the fps was sufficiently high enough, objects would zip by so fast it would be impossible to see them.

Does anyone know an easy way to solve this? Or am I just completely confuzzled?

Posted on 2005-01-15 13:29:38 (last edited on 2005-01-15 17:04:45)

RageCage


//pixels per second
int pps=16;


if( pps *(timer-timeStamp) /100 >= 1 ){
moveDist=pps *(timer-timeStamp) /100;
timeStamp=timer;
}


It would seem like that should work, unless what you say about the 1/100==1 thing is true... if so you might have to pull something like:


//pixels per second
int pps=16;

if( pps *(timer-timeStamp) /100 == 1 && pps *(timer-timeStamp) %100 != 0)
return;

if( pps *(timer-timeStamp) /100 >= 1 )
moveDist=pps *(timer-timeStamp) /100;
timeStamp=timer;
}


although I question how well that'd work....

Posted on 2005-01-16 10:47:58 (last edited on 2005-01-16 10:49:33)

Omni

1. Verge Integers always round down to zero. Even if the result would be greater than 0.5, it would still round down to zero. All decimal data is discarded.

2. Perhaps you should use fixed point.

3. HookTimer is reliable, because it always calls a function a set number of seconds. You can essentially make your own HookTimer procedures in code using just the 'timer' variable. You keep track of how many centisecs has passed, and then you call the function enough times to catch up.

while (timer - lasttime > 0)

Call Function
lasttime++


It's almost that simple. The only problem is when you time a function that just can't be completed in less than a centisec, in which case lasttime will never catch up to timer, and a HookTimer version would also fall behind and start to do bad stuff. That's why you don't put graphics or anything potentially time consuming in HookTimer.

But, as long as the function can be completed in a 1/100th second time window, then HookTimer will always reliably call it, because it works by simple looping, essentially. There's no way it shouldn't be able to catch up unless you're doing something wacky like per-pixel.

4. Now, my own explanation of moving an entity 4 pixels. Keep in mind I haven't read RageCage's math (reading someone else's math code is kinda hard for me to follow :) ) so I'll just try to summarize what I would do.



1 You want to move an entity 4 pixels in a second.
2 That means in 100 centisecs, the entity moves, 4 pixels. Of course.
3 So, 100 must equal 4 pixels, or technically 4 pixels per 100 centisecs, or, simplified, 1 pixel per 25 centisecs, or whatever.



Try this.

Pseudo-code

define real X position of the entity real_x
define time to move per second. pixel_per_sec = 4

int global variable seconds_counted

void MoveMyEntity()
while (timer - lasttime > 0)
seconds_counted++
if (seconds_counted == 100 / pixel_per_sec)
//IE, the correct number of centisecs have passed, in this case 100/pixel_per_sec = 25
seconds_counted = 0
real_x++
lasttime++


HookTimer(Move_My_Entity)


And I think that would essentially do it. EDIT: RageCage's first example also looks good and probably simpler :)



5. Also, try taking a look at this.
http://www.verge-rpg.com/files/detail.php?id=577
It's the framethrotlling code I made a while back. It allows you to set the functions to be called, and then lets you set a Max FPS and a frameskip that WILL be maintained.

For example, in the demo the starting settings rotate a picture of Interference's font at exactly 6 degrees a second at 60 FPS. So, every second the font makes a complete revolution, since 6 degrees * 60 frames = 360 degrees per second. That's not the same as pixel velocity, but you could make it work, and it's an interesting alternative to HookTimer since it also lets you potentially do neat things like cut down the FPS for ZSNES-style slow motion :)

Posted on 2005-01-16 11:59:47 (last edited on 2005-01-18 07:56:38)

Omni

Side note: the framethrottle version 2 has a glitch where setting the Frameskipping above 1 will cut down on the number of times process function is called. This is false, it should only skip the render instructions. I have a patched version of this, but I'll have to upload it later tonight.

Posted on 2005-01-16 12:23:51

blues_zodiakos

Frame throttleing and skipping isn't a problem, my old particle system (zps, pretensious name) did it. I would really rather my new particle system do nothing of the sort, however, that way anyone who decides to use it will have the freedom to choose their own method of throttling/skipping, or choose to not do it at all. Regardless, I want the particles to move the same speed on every computer, as it will make creating particle systems MUCH easier.

I was kind of tired when I wrote the initial post, so here's my problem. Say I set a particle (a single pixel, in this example) to move at a velocity of 4 pixels a second (orientation isn't important). The only thing my engine really needs to know is, given the current fps, and the velocity of the pixel, how far does it need to move the pixel in THIS frame. Everything else is easy as pie.

I was wrong earlier, I tried it and verge rounds down. So, any time a pixel is supposed to move less than 1 pixel a frame (if the current fps is 60, and I want to move the pixel at a velocity of 59 pixels a second), the division will cause the pixel to move absolutely nowhere, because the pixels per frame would always be zero. Bump the velocity up to 60, however, and away it goes. What this means is that, with these calculations, and integer math, the faster the computer (thus the higher the framerate), the more pixels will just sit there and do nothing (and the rest will probably be too fast to ever see).

I'm definitely going to have to figure out a fixed point solution to this. It's not that it's difficult, its that I hate doing it. It makes me want to stab things with a dull spork until they bleed. Profusely.

Posted on 2005-01-16 20:23:01

Omni

Nasty.



All right, new strategy.

Object moves 4 pixels in 100 centisecs. Thus, the most basic movement unit is 1 pixel per 25 seconds, or just 1 out of 25.



Immediate conversion solution: create the pixel increments using factors of 25.

Example.




int real_pixel_x
int incrementing_pixel25



void Initialize()
incrementing_pixel25 = real_pixel_x * 25;


void Process()
while(timer-lasttime)
incremeting_pixel25++

real_pixel_x = incrementing_pixel25/25

lasttime++




This should work perfectly. Every second, incrementing pixel will increase by 100, which, when multiplied by the factor of 1 pixel/25 centisecs, or 100 * 1 / 25, equals 4. By expanding real_pixel_x to be on a (*25) scale using incrementing_pixel25, you ensure that incrementing_pixel is always incremented, and thus we don't have to worry about losing data using decimal incremetation. You can't guarantee that your machine will get 60 frames per second, but HookTimer certainly will be called 100 times a second, which means this object will move definitely at 4 pixels a second.

Is that understandable?

Posted on 2005-01-16 21:15:04

blues_zodiakos

Ooh, that's good. That's EXACTLY what I needed. It's sort of like what zaratustra was doing in his 4Four demo (which I tried to study because it had the same problem solved), but in .25 increments instead of 100. I looked at that demo a while ago but I still couldn't figure out exactly what it was doing. Maybe I'm older now or something.

However, your code makes perfect sense. Thank you!

Posted on 2005-01-17 13:08:07

Omni

No problem.

Posted on 2005-01-17 16:24:49

Gayo

It's worth noting that whenever I use hooktimer to handle sprite movement, people who know more about coding than I do yell at me. Since the entity has a fixed movement rate, its position can be expressed as a linear function of time, so a less cpu-intensive method might be to hookrender the movement or just put it in a loop, and have it check how much time has elapsed since the last logic cycle and update positions accordingly. This is a huge pain when you have to worry about acceleration, as I found out when working on my ill-fated Zelda clone, but for ordinary VERGE-like movement it's easy peasy.

Posted on 2005-01-20 19:43:33

Omni

I just realized. If you want, you can HookTimer the above code in my post as well. It works whether you HookTimer or HookRetrace it, since it always just calculates position based on the amount of time that has passed.

Posted on 2005-01-23 16:44:13


Displaying 1-10 of 10 total.
1
 
Newest messages

Ben McGraw's lovingly crafted this website from scratch for years.
It's a lot prettier this go around because of Jon Wofford.
Verge-rpg.com is a member of the lunarnet irc network, and would like to take this opportunity to remind you that regardless how babies taste, it is wrong to eat them.