• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GameMaker Using Delta-time to fix Game Makers god awful laptop performance?

MilesThatch

Member
Greetings everyone.

It's been known for quite some time that Game Maker runs like absolute a** on laptops with integrated graphics cards. Anything from intel at that matter. I have few games I had tested it out on and my suspicion lies with with the surfaces being the culprit. All of the game that run slow on my laptop use surfaces. However not all of my games that use surfaces run slow on the laptop. There were exceptions.... if my memory doesn't fail me.

In any case. the entire game slows in proportion so do you think I can use the delta time to proportionally upscale the speed on laptops? I mean that's what delta time is meant for, right? Network and slow hardware compensation?

My idea is to take the delta time measurement of the game running at normal speed on my desktop. And use that value as a reference for calculating how much slower is the game running on a laptop. Then any sort of time or speed values would be scaled up by that factor?
 

Nux

GameMaker Staff
GameMaker Dev.
Sure you can. But be warned that simply scaling speed isn't going to be enough; you're going to have to multiply every rate of change by that delta time factor. For example:
Code:
hsp += acc * dt;
x += hsp * dt;
This is the simplest application. However, it's not very accurate and will cause errors with physics. This is especially apparent if you are using sinusoidal movement, like with springs, because errors in the integration can add up and eventually cause the simulation to explode.

You can get more accurate predictions by looking into the "equations of motion", which is essentially the vanilla movement code everyone uses except more general. Using these will reduce the error, but not remove it completely. I'm sure there are other integration methods you could look into which perform better, but this is probably the "nicest".

Furthermore, not everything can just be multiplied by this time factor. Take exponential decay, for example. You cannot do:
Code:
value *= 0.5 * dt;
and instead have to use something along the lines of:
Code:
value *= pow(0.5, dt);
 
Last edited:

jonjons

Member
Delta time is the global time for the CPU ( i think... ).
Its the time the CPU uses to communicate with the hardware, graphics card, keyboard, etc...

I think its going to require some extra work to use delta time on GM. Other engines only use delta time with an extra lock to 30 fps ( void fixed update LOL ), but they are also more hard to code.

Using delta time in GM the game will also be slow, but it will skip the frames... I think its best to use room speed instead, you will get a slow motion effect instead low fps.
One way to use delta time Its to remake all the timers and skip alarms.

Heres an example using delays with delta time 1/1000000 its one second
Code:
//-------//--DELAYS--//--------


if (stayDown != 0) //--attacks--
{
    stayDown -= delta_time /1000000;
    stayDown = clamp(stayDown, 0, 50);
    if ( stayDown <= 0 )
    {
        stayDown = 0;
    }
}

if (plrAtck_delay2 != 0) //--attacks--
{
    plrAtck_delay2 -= delta_time /1000000;
    plrAtck_delay2 = clamp(plrAtck_delay2, 0, 5);
    if ( plrAtck_delay2 <= 0 )
    {
        plrAtck_delay2 = 0;
    }
}
if (  knockDrag != 0 && ( grounded == 0 || grounded == 2 ) )
{
    knockDrag -= delta_time /1000000;
    hsp = dirDrag * knockDrag;
    knockDrag = clamp(knockDrag, 0, 15);
    if ( knockDrag <= 0 )
    {
        knockDrag = 0;
    }
}


if (invureble != 0)
{
    invureble -= delta_time /1000000;
    invureble = clamp(invureble, 0, 5);
    if ( invureble <= 0 )
    {
        invureble = 0;
    }   
}
 

MilesThatch

Member
I see, thanks @Nux and @jonjons

My original though was to calculate the percentage ratio of the laptop game speed vs what I think normal speed is (speed on my desktop development machine)

so say hypotherically if the normal step speed / delta time is 400203 SI (microseconds) per step and my laptop runs the game at 243562 SI per step, then I would say

Code:
speed_ratio = 243562 / 400203
which gives me a ratio of 0.6085. So my game on the laptop is running at almost half the speed.

so if I move the character by 5 pixels in the actual game, in laptop mode I'd do

Code:
x += 5 / speed_ratio // which is equals to 0.6085
which will move the player by 8.216 pixels instead.
 
Last edited:

Nux

GameMaker Staff
GameMaker Dev.
The usual formula I see to calculate a delta time ratio is:
Code:
dt = (delta_time / 1000000) * 60;
where the default game speed you want to achieve is "60 fps".

EDIT:
I think you can see something along these lines in jonjons code.
 

jonjons

Member
speed_ratio = 243562 / 400203
that could work, but i think it would still make the game run slow, and its very confusing... maybe a more advanced gm user could give you feed back...

theres already a video using delta time, you must be aware ;)

If i was you, i would stick with room speed delta time gave me some problems, plus it must be easier to lower the room speed to 15 fps, and make the player code from there...

but are you sure you cant optimize the code ?
you must already know this, but one way i use to draw multiple shaders its to put them all into one surface, and pass that surface to another and another then only draw the final surface

Post-Draw event
Code:
gpu_set_colorwriteenable(true, true, true, false);

surface_set_target(surf1);
shader_set(shd_pixelate);
shader_set_uniform_f(pixel,512,512,value1,value1);
draw_clear(c_black);
draw_surface(application_surface, 0, 0);
shader_reset();
surface_reset_target();


surface_set_target(surf2);
shader_set(shd_blur);
shader_set_uniform_f(usize,vW,vH,value2);
draw_clear(c_black);
draw_surface(surf1,0,0);
shader_reset();
surface_reset_target();




surface_set_target(surf3);
shader_set(shd_bloom);
shader_set_uniform_f(bloomIntensity, value3);
shader_set_uniform_f(bloomblurSize, value4);
draw_clear(c_black);
draw_surface(surf2,0,0);
shader_reset();
surface_reset_target();



surface_set_target(surf4);
shader_set(sh_hue);
shader_set_uniform_f(pos_uni, value5);
draw_clear(c_black);
draw_surface(surf3,0,0);
shader_reset();
surface_reset_target();


surface_set_target(application_surface);



surface_set_target(surf5);
draw_clear(c_black);
draw_surface(surf4,0,0);
surface_reset_target();
draw_surface_ext(surf5,0,0,1,1,0,c_white,1);

gpu_set_colorwriteenable(true, true, true, true);

if ( gridTG )
{
var camX = camera_get_view_x(view_camera[0]);
var camY = camera_get_view_y(view_camera[0]);
    
    
    depth = -1000;
    gpu_set_blendmode(bm_subtract);
    draw_sprite_tiled_ext(spr_pxGrid, 0, vW, vH, pxGridSZ, pxGridSZ, pxGridCOchange, pxGridAL);
    gpu_set_blendmode(bm_normal);
    
    draw_text(camX,camY+32, " SIZE: " + string(pxGridSZ));
    draw_text(camX,camY+50, "ALPHA: " + string(pxGridAL));
    draw_text(camX,camY+72, "COLOR: " + string(pxGridCOchange));
}



surface_reset_target();
 
Top