1. Hey! Guest! The 34th GMC Jam will take place between August 22nd, 12:00 UTC (Thursday noon) and August 26th, 12:00 UTC (Monday noon). Why not join in! Click here to find out more!
    Dismiss Notice

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

Discussion in 'Programming' started by MilesThatch, May 29, 2019.

  1. MilesThatch

    MilesThatch Member

    Joined:
    Jul 12, 2016
    Posts:
    412
    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?
     
  2. Nux

    Nux Member

    Joined:
    Jul 7, 2016
    Posts:
    371
    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: May 29, 2019
  3. jonjons

    jonjons Member

    Joined:
    May 10, 2017
    Posts:
    293
    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;
        }   
    }
    
     
  4. MilesThatch

    MilesThatch Member

    Joined:
    Jul 12, 2016
    Posts:
    412
    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: May 29, 2019
  5. Nux

    Nux Member

    Joined:
    Jul 7, 2016
    Posts:
    371
    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.
     
  6. jonjons

    jonjons Member

    Joined:
    May 10, 2017
    Posts:
    293
    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();
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice