GameMaker Increasing the FPS with room speed but keeping the in-game speed

Hello everyone.

I'm in the middle of a conundrum. I've been working on this game for 5 years now, soon to be 6 years and for some reason when starting the
development I decided that the room speed 40 was a good pick for the game.

I later learned that this isn't a very optimal room speed. In order to use Vsync for example, I should have picked 30 or 60 FPS.

Unfortunately it's not as easy as just changing the room_speed in each room, and like I mentioned before, this is an almost 6 year old project
which means there is quite a few lines of code to go through.

So here's my question:

Does anyone have some hints and tricks on how to go through the process? Has anyone else been in the same situation?
Or, in order to fix this, will I have to go through all my code and increase alarms as well as decreasing speeds of all kinds?
Which will be a tedious and soul crushing process...

I'm not sure what to do here and all help will be very appreciated!
 

GMWolf

aka fel666
It depends on how you coded your game.
If you coded everything with speeds and acceleration you have to go in and change all those values. Acceleration is hard because you'll have to find new values that give you similar results.

Ideally you would have gone with either delta timing, or have used variable such as jump height etc to calculate acceleration, jump speed etc.
 
It depends on how you coded your game.
If you coded everything with speeds and acceleration you have to go in and change all those values. Acceleration is hard because you'll have to find new values that give you similar results.

Ideally you would have gone with either delta timing, or have used variable such as jump height etc to calculate acceleration, jump speed etc.
I feared as much. It shouldn't be too difficult to change the values, i'm more worries about how time consuming it might be.

Delta timing? That is new to me. I'm guessing you're talking about: https://docs.yoyogames.com/source/dadiospice/002_reference/date and time/delta_time.html
If I decide to back and change everything, perhaps adding that to the code might be ideal?
 

O.Stogden

Member

Like I said here, it'd be easier to use a division to basically lower your speeds as though it was playing at 40FPS, even though it was at 60. Or use Delta Timing.

Delta Timing can cause issues if your framerate is not stable however. But hopefully you've optimized your game to hold at a decent framerate.

DT will basically make constant adjustments based on what the *current* FPS is, against what the *target* FPS is. It essentially does what my dividing would do, but it handles it dynamically, but because of that, it can produce odd results if the FPS is going up and down constantly, and if your game has any lag spikes at some point, it can really mess things up, although there's probably ways to prevent that.

In terms of how much time you need to spend, it'll be identical for both really. You'll either be dividing/multiplying by a fixed number, or dividing/multiplying by Delta Time.
 

rytan451

Member
I can at least do some of the math for you.

If a speed was (beforehand) 3 pixels per frame at 40 FPS, that's 120 pixels per second. At 30 FPS, that's 4 pixels per frame; at 60 FPS, that's 2 pixels per frame.

If your acceleration was 9 pixels per frame squared (gravity = 9) at 40 FPS, that's 14400 pixels per second squared. At 30 FPS, that's 16 pixels per frame squared (gravity = 16). At 60 FPS, that's 4 pixels per frame squared (gravity = 4).

In short, converting speed means multiplying speed values by old_fps / new_fps, whereas converting acceleration means multiplying by sqr(old_fps) / sqr(new_fps).

If you want, you can just set up a few global variables that hold the scaling factors and just multiply your speeds and accelerations by them as needed. For example, if you have a hspd variable (to maintain more control over the instance) then instead of going x += hspd in a step event, you would go x += hspd * SPEED_SCALING.

Though rewriting for delta time is optimal, that's often just too much work. Oftentimes it's impossible. Perhaps consider using delta time in your next project, but it would be a great deal of work to rewrite for delta time.
 

GMWolf

aka fel666
Delta Timing can cause issues if your framerate is not stable however. But hopefully you've optimized your game to hold at a decent framerate.
You can just keep your delta time value constant. The game will slow down like without delta timing, but you can easily change the dt value of you change room speed.

It's not practical to do in GM, but what I like to do is simulate the world in fixed steps, and determine how many steps I need to simulate each frame.
You get great stability at the cost of a little performance.
 

Mert

Member
I used the function below in some of my projects

GML:
function dt(val) {
    var delta = (delta_time / 1000000) * fps;
    return delta;
}
Code:
//Move the character.
//Move 4 pixels right side..
obj_player.x += dt(4);
 
I can at least do some of the math for you.

If a speed was (beforehand) 3 pixels per frame at 40 FPS, that's 120 pixels per second. At 30 FPS, that's 4 pixels per frame; at 60 FPS, that's 2 pixels per frame.

If your acceleration was 9 pixels per frame squared (gravity = 9) at 40 FPS, that's 14400 pixels per second squared. At 30 FPS, that's 16 pixels per frame squared (gravity = 16). At 60 FPS, that's 4 pixels per frame squared (gravity = 4).

In short, converting speed means multiplying speed values by old_fps / new_fps, whereas converting acceleration means multiplying by sqr(old_fps) / sqr(new_fps).

If you want, you can just set up a few global variables that hold the scaling factors and just multiply your speeds and accelerations by them as needed. For example, if you have a hspd variable (to maintain more control over the instance) then instead of going x += hspd in a step event, you would go x += hspd * SPEED_SCALING.

Though rewriting for delta time is optimal, that's often just too much work. Oftentimes it's impossible. Perhaps consider using delta time in your next project, but it would be a great deal of work to rewrite for delta time.
Really cool for you to help out with the math!

I tried inplementing the values provided and for the basic movement of the characters it actually worked great.

But I have to make sure. In what other scenarios should the acceleration formula sqr(old_fps) / sqr(new_fps) be applied? Is it for all accelerations?
An easy example, let's say I have something fade out and in the step event I have this:
image_alpha -= 0.2;

Should I then change that to image_alpha -= 0.2 * sqr(old_fps) / sqr(new_fps);

or will image_alpha -= 0.2 * old_fps/new_fps; suffice
 

rytan451

Member
If you're changing things linearly (like, reducing alpha by 0.2 every frame), then use the velocity factor. That's old_fps / new_fps. If you're changing things quadratically (the speed of change is increasing or decreasing at a constant rate) then use the acceleration formula.

A third scenario: if you're multiplying a value every step (so, multiplying speed by 0.9). At 40 FPS, that's multiplying 0.9^40 per second. At 30 FPS, you'd want to multiply 0.9^40 per second as well, so that's 0.9^(4/3). At 60FPS, that's 0.9^(2/3). That means, instead of variable *= old_multiplier, you'd use variable *= pow(old_multiplier, new_fps / old_fps). This only applies to things that happen every step, of course.
 

RayFlower

Member
Going through and decoupling my game's performance from the framerate and just wanted to say thanks for the info.

What I'm using is deltatime, and I've converted @rytan451's formulas to work for it
GML:
//speed/linear values:         old_fps / new_fps                                        --> _deltatime
//converting acceleration:     sqr(old_fps) / sqr(new_fps)                                --> sqr(_deltatime)
//lerping / multiplying:         variable *= pow(old_multiplier, new_fps / old_fps)        --> variable *= pow(old_multiplier, 1 / _deltatime)


// examples for fps values
hsp += move_speed_inc * sqr(old_fps) / sqr(new_fps)
x += hspeed * (old_fps / new_fps)
camera.x = lerp(camera.x, x, pow(0.9, new_fps / old_fps))

// examples for deltatime
var _deltatime = (delta_time / 1000000) * room_speed;
hsp += move_speed_inc * sqr(_deltatime) // acceleration/speed values, gravity
x += hspeed * _deltatime // linear/constant values, timers, etc
camera.x = lerp(camera.x, x, pow(0.9, 1 / _deltatime)) // lerping, multiplication, etc
Just thought I'd share it here for anyone else that wants to use deltatime or account for variable framerates and need to convert their whole project to it.

After testing it, the normal deltatime works much better for velocity, movement speed and gravity, rather than using the squared values. I tried a bunch of tests on my player movement, running the same room at 30fps (rather than 60), altering player speed to 50% (while still rendering 60 frames). Regular deltatime converted properly, whereas squared deltatime overshot/undershot the values by almost twice the amount. That being the case means I don't understand what the acceleration formula from @rytan451 is used for. Do you have more examples?

Edit:
... testing more of it out and apparently lerping doesn't work this way (as I had previously thought..), found this post to help with lerps instead: https://www.reddit.com/r/gamemaker/comments/cwc44r
Also, the formula for that you used is actually backwards. It should be variable *= pow(old_multiplier, old_fps / new_fps). Or using deltatime as I am, pow(old_multiplier, _deltatime)
 
Last edited:
Top