The Daily Click ::. Forums ::. Klik Coding Help ::. Slowing down time
 

Post Reply  Post Oekaki 
 

Posted By Message

CakeSpear



Registered
  28/01/2004
Points
  112
9th May, 2012 at 09/05/2012 12:19:56 -

Hi
Ive been struggeling for the longest time now with how to correctly slow down time in my game.
Ive tried to keep it simple and get it to work correctly and precisely in a simple scenario 'a falling rock affected by gravity'

...
Ive been following an example wich states that this is how you do it:

ADD GRAVITY
Set SpeedY_ to: SpeedY_ + GravityStrength_ * TimeRatio_

MOVE PLAYER
Set Ypossition to: Ypossition + SpeedY_ * TrimeRatio_

However, doing the math on this produces inaccurate results.
Ive also tried few other methods and solutions, but i cant get it to work and i cant seem to wrap my head around it.

What i want to do is simple enough:
I want a falling Rock affected by gravity, to move the same distance accross 2 frames at 100% speed, as it does across 4 frames at 50% speed.

...
I know this is not an easy question.
Could someone pleace help me slow down time?


 
n/a

Cazra

Crazy?

Registered
  24/07/2002
Points
  4472

Game of the Week WinnerVIP Member
11th May, 2012 at 11/05/2012 04:54:03 -

Put the parts of your game that you want slowed down into one big group. We'll call it "SlowGroup". We'll also have some sort of timer for slowing it down. We'll call this counter "SlowTimer". Then do something like the following outside of that group somewhere.

> Start of level: set SlowTimer = 0.0
> Always: Disable group "SlowGroup", add 0.5 to SlowTimer
> if SlowTimer >= 1.0: subtract 1.0 from SlowTimer, Activate group "SlowGroup"

It'll take some extra work to slow down animations as well, but this will slow down any physics or other game logic going on inside "SlowGroup".

Adjust the amount that is added to SlowTimer in that 2nd event to adjust how much time is slowed down. Adding 0.5 slows time down in "SlowGroup" to 50% normal time. Adding 0.25 slows time down in "SlowGroup" to 25% normal time, and so on.

Edited by Cazra

 
n/a

CakeSpear



Registered
  28/01/2004
Points
  112
13th May, 2012 at 13/05/2012 00:33:32 -

That is a good solution wich will work.

But that method doesnt really slwo anything down, at 50% speed ( above method ) Objects move 'every other frame' raher than 'half speed each frame', wich might look 'laggy' and not as nice.
If i wanted to do something like this i can imaging it would be easier to just alter the FPS durring runtime ( wich is possible in MMF2 ).

 
n/a

Bricnic



Registered
  16/07/2002
Points
  1016

VIP MemberWii OwnerHas Donated, Thank You!
14th May, 2012 at 14/05/2012 09:05:40 -

You need to keep all positions stored in variables, so you don't get integer arithmetic introducing rounding errors. MMF will only store integers for the pixel positions of all objects, but for your purposes, you want to store all positions as floats (or even better doubles, but I'll assume you don't have the developer version).

Store XPosition and YPosition as alterable variables. Make all updates to these variables instead, and then have an "Always" event that sets the actual X and Y of the object to these variables.

Some example pseudo-code:

ADD GRAVITY
Set SpeedY_ to: SpeedY_ + (GravityStrength_ * TimeRatio_)

UPDATE POSITION VARIABLE
Set YPos_ to: YPos_ + (SpeedY_ * TimeRatio_)

UPDATE PLAYER POSITION
Set Yposition to: YPos_

 
n/a

CakeSpear



Registered
  28/01/2004
Points
  112
14th May, 2012 at 14/05/2012 12:29:06 -

I am storing my possitions as decimals in Alterable Values, and i do own Developer.
How do i choose beytween Floats and Doubles in MMF2???

...
That pseudo code is however inaccurate, do the math an see for yourself.

1000 * 1.25 = 1250

is not the same as

1000 * 1.125 = 1125
1125 * 1.125 = 1265,625

 
n/a

DeadmanDines

Best Article Writer

Registered
  27/04/2006
Points
  4758
14th May, 2012 at 14/05/2012 14:15:00 -

Remember to test it in practice. I don't mean testing the arithmetic, I mean make a little man that walks around and slows down / speeds up as you change the time ratio and watch how his motion looks to your eye.

Or just borrow the new example I made from here (http://community.clickteam.com/showthread.php?t=46829&p=524503&viewfull=1#post524503 ).

Basically, although *eventually* the gravity seems to fall out of kilter when you process it in Excel, it's almost unnoticeable in a simple platform game, because each time you land, your vertical inertia is reset to zero. So the player's on-screen velocity never gets to be high enough to see any problems. Otherwise, you may end up chasing decimal points.

In essence, it happens like this, because I can't upload a spreadsheet from here:


At 50% Gravity 1px per frame At 100%
Inertia Position Inertia Position
-5 1000 -5 1000
-4.5 997.75
-4 995.75 -4 996
-3.5 994
-3 992.5 -3 993
-2.5 991.25
-2 990.25 -2 991
-1.5 989.5
-1 989 -1 990
-0.5 988.75
0 988.75 0 990
0.5 989
1 989.5 1 991
1.5 990.25
2 991.25 2 993
2.5 992.5
3 994 3 996
3.5 995.75
4 997.75 4 1000
4.5 1000
5 1002.5 5 1005
5.5 1005.25
6 1008.25 6 1011


At gravity of 1px per frame, after 11 frames, the player's Y position is about 3px out. Bearing in mind that I usually use gravity at much less than 1px, it gives quite a lot of room for error.

You could apply inertia once every N frames, but I suspect that wouldn't fix the problem. If you see in the calcs above, the problem isn't the inertia in itself, because the inertias line up quite nicely. The percentage problem arises when the inertia is added into the position.

Let's look at the 2nd frame, where at 100% inertia is -4 and position 996px.
The maths behind that was Inertia = Inertia + 1 * 1.0; Position = Position + Inertia * 1.0.

But the corresponding frame at 50% has inertia -4 but position 995.75px.
The maths is as follows, using resolved numbers for clarity:
Inertia = -5 + 1 * 0.5 = -5 + 0.5 = -4.5;
Position = 1000 + -4.5 * 0.5 = 1000 + -2.25 = 997.75px;
Inertia = -4.5 + 1 * 0.5 = -4.5 + 0.5 = -4.0;
Position = 997.75 + -4 * 0.5 = 997.75 + -2 = 995.75px;

Wrong-diddly-wrong, because we apply two lots of 50% instead of one lot of 100%.

That's the tricky bit.

 
191 / 9999 * 7 + 191 * 7

CakeSpear



Registered
  28/01/2004
Points
  112
14th May, 2012 at 14/05/2012 15:28:30 -

Dines, you confuse me with the name Intertia. Im guessing that Intertia is what i call MoveX_ and MoveY_ in my Applications ( current movement speed in pixels ).
I have tried theese methods in practice in my applications wich have lead to the same problems as i find when doing the math on paper.

Look at this example, TimeRatio is at 1 ( 100% game speed )

Frame1
Gravity: 0 + (1 * 1) = 1
Position: 0 + 1 = 1

Frame2
Gravity: 1 + (1 * 1) = 2
Position: 1 + 2 = 3



Think about it, if TimeRatio is at 0.25 ( 50& game speed )

Frame1
Gravity: 0 + (1 * 0.25) = 0.25 ( Gravity is only increased the first frame of every 4 Frames )
Position: 0 + 0.25 = 0.25

Frame2
Gravity: 0.25
Position: 0.25 + 0.25 = 0.5

Frame3
Gravity: 0.25
Position: 0.5 + 0.25 = 0.75

Frame4
Gravity: 0.25
Position: 0.75 + 0.25 = 1

Frame5
Gravity: 0.25 + (1 * 0.25) = 0.5 ( Gravity is only increased the first frame of every 4 Frames )
Position: 1 + 0.5 = 1.5

Frame6
Gravity: 0.5
Position: 1.5 + 0.5 = 2

Frame7
Gravity: 0.5
Position: 2 + 0.5 = 2.5

Frame8
Gravity: 0.5
Position: 2.5 + 0.5 = 3

...
I have actually created the solution i just posted above, the only problem im having at the moment is that TimeRation can only be 0.1 or 0.2 or 0.5 But im working on it.
Also using this method you wont have a 'smooth' accelleration from Frame1 to Frame4, Frame5 to Frame8 and so on, but you rather get a constant accelleration.

When i started with this i realy hoped for a simple solution for slowing down time using TimeRatio.
I still hope there is a simple solution to all this, but it has proven to be quite the challenge.

 
n/a

DeadmanDines

Best Article Writer

Registered
  27/04/2006
Points
  4758
14th May, 2012 at 14/05/2012 17:17:10 -

Yeah, inertia just means movement speed.

For your tests in applications, make sure you're testing it on the actual motion of an object, not just looking at the values in counters. If you make a Mario clone with bullet time, does Mario noticeably fall along a different curve during bullet time than he does at normal time?

For instance, my Tortoise example has this mathematical inconsistency in it, but no one would notice unless they audited the maths by hand like you have. To the naked eye, there's no real difference.

 
191 / 9999 * 7 + 191 * 7

CakeSpear



Registered
  28/01/2004
Points
  112
14th May, 2012 at 14/05/2012 21:40:13 -

I understnd what your saying Dines, that if it works in your particular game and the inaccuracy of the method is minimal and hard to notice, then its OK and the inconsistency dont matter much.

But it just happens to be that i am not creating any particular game as of yet, i am creating a 'Game Engine'.
What this means is that out of this Game Engine i will be able to creat many different games wich again might have very different mechanics. For example one game might have the Player moving at lighning speed acoross a huge game area.

Because of this i am very reluctant to use any inacurate method, since the inacuracy will then be present in all game created of the engine.

 
n/a

DeadmanDines

Best Article Writer

Registered
  27/04/2006
Points
  4758
14th May, 2012 at 14/05/2012 23:01:49 -

Ah, I understand your need for accuracy much better now

There is still one method I'd like to try - if it works, I'll let you know.

 
191 / 9999 * 7 + 191 * 7

CakeSpear



Registered
  28/01/2004
Points
  112
14th May, 2012 at 14/05/2012 23:06:05 -

Much appreciated Dines!
Ill continue working towards a solution myself, if im succsessfull l give you a shout as well

 
n/a

DeadmanDines

Best Article Writer

Registered
  27/04/2006
Points
  4758
15th May, 2012 at 15/05/2012 12:02:09 -

How does this sound:

Speed			   0	px/s

Gravity 50 px/s/s
Position 1000 px
FPS 100 fps
T 50%
Length of one frame 0.01 seconds
Base FPS 50 fps

Inertia Position Inertia Position
Start 0 1000 0 1000
0.5 1000.005
1 1000.015 1 1000.02
1.5 1000.03
2 1000.05 2 1000.06
2.5 1000.075
3 1000.105 3 1000.12
3.5 1000.14
4 1000.18 4 1000.2
4.5 1000.225
5 1000.275 5 1000.3
5.5 1000.33
6 1000.39 6 1000.42
6.5 1000.455
7 1000.525 7 1000.56
7.5 1000.6
8 1000.68 8 1000.72
8.5 1000.765
9 1000.855 9 1000.9
9.5 1000.95
10 1001.05 10 1001.1
10.5 1001.155
11 1001.265 11 1001.32
11.5 1001.38
12 1001.5 12 1001.56
12.5 1001.625
13 1001.755 13 1001.82
13.5 1001.89
14 1002.03 14 1002.1
14.5 1002.175
15 1002.325 15 1002.4


Speeds are applied by the length of 1 frame, rather than the ratio of time.
So at 50% speed, a normally 50fps game will use 100fps to show one second.
So 1 frame represents 0.01 seconds of game time at 50% speed.
So speeds are recorded in pixels per second (acceleration like gravity at pixels per second per second) and multiplied by the number of seconds that each frame represents.

So a speed of 1px/s at 50% time travels a distance of 1px * 0.01 seconds per frame = 0.01 px per frame

That seems to be fairly accurate - it's sometimes 0.1px out, but it seems to auto-correct over time.

EDIT: No it doesn't But now I really do know what the solution is, I just need to set it out programatically.

Edited by DeadmanDines

 
191 / 9999 * 7 + 191 * 7

Jenswa

Possibly Insane

Registered
  26/08/2002
Points
  2722
16th May, 2012 at 16/05/2012 20:41:28 -


Originally Posted by CakeSpear
I am storing my possitions as decimals in Alterable Values, and i do own Developer.
How do i choose beytween Floats and Doubles in MMF2???

...
That pseudo code is however inaccurate, do the math an see for yourself.

1000 * 1.25 = 1250

is not the same as

1000 * 1.125 = 1125
1125 * 1.125 = 1265,625



Math notice from the teacher:

100*1.25 isn't the same as 100*1.125*1.125

Because 1.125*1.25 = 1.265625

And this isn't a rounding error, this is the mathematical difference between a linear and exponential function.

If you want to multiply by 1.25 in two steps, you need to have the squareroot of 1.25, which is something about: 1.1180 with 4 decimals, this way your trick will work.

Because 100.125 is approximately 100*1.1180*1.11.80 (because of only using 4 decimals instead of the entire series of digits).

It's just like the rent on savings.

If you want to use *1.25 for your movement for the lapse of 1 second, you should use the squareroot for 0.5 seconds instead of simply dividing 1.25 by 2. So if you want to split *1.25 up into 10 little steps, you don't do 1.25/10 = 0,125 (because that certainly only would get smaller), you need to take the tenth root of 1.25. In common computer code it's this: 1.25^(1/10) and if you need 20 steps, you use 1.25^(1/20).

However I am not sure if this is what you want. You probably want something like increasing the number of pixels falling every second because this way you can use a division by 2 for 2 steps or division by 10 for 10 steps. But of course if you use a division by 2 or 10 you should add 1/10 or 1/2 of the pixels to add for falling.

I am hoping I am writing some piece of text which is readable and understandable.

One last recommendation is on article on the timestep called: fix your timestep
It's written in C++ but the coding principles should be easy to follow:
http://gafferongames.com/game-physics/fix-your-timestep/

Happy coding!

 
Image jenswa.neocities.org

DeadmanDines

Best Article Writer

Registered
  27/04/2006
Points
  4758
17th May, 2012 at 17/05/2012 12:45:59 -

So from your link (the 'previous' page of the article about RK4 integration), the RK4 system is applied by essentially always creating 4 additional frames to sniff out the curve being applied by the current acceleration?

So if we say in pseudocode:

Frame starts
Bob's Y position is 100px
Bob is flying upwards with a velocity of 150px/s/s
Gravity pulls Bob at a rate of 50px/s/s
--- RK4 checks this at the start of the frame,
--- RK4 checks it after 50% of delta time
--- RK4 checks it after 50% of delta time from previous check
--- RK4 checks it at end of frame
--- RK4 does its magic to work out the weighted average acceleration based on the 4 samples
Move the player's position accordingly

Is that the... 'thrust'... of it?

Edited by DeadmanDines

 
191 / 9999 * 7 + 191 * 7
   

Post Reply



 



Advertisement

Worth A Click