GML Time Rewind Feature Tutorial

Discussion in 'Tutorials' started by matharoo, Jul 19, 2019.

  1. matharoo

    matharoo Udemy Instructor

    Joined:
    Jul 9, 2016
    Posts:
    892
    GM Version: GMS2, works with GMS1 too
    Target Platform: All

    Summary:

    A friend of mine was making a game and needed help with implementing a time rewind feature, so I quickly cooked up some code for him. Works like a charm, so I thought I'd share it here.

    Tutorial:

    Basically, we have a DS list that stores the data for each step inside it, which we can use to rewind the time. In this example, the DS list is inside the player object, and stores its x, y and health in an array, then pushes it to the list.

    I recommend you do this in a controller object, and store the data of all the instances in the list, for a proper time rewind.

    Of course, this code isn't perfect and was written in a couple minutes, so if you wanna improve on it or point out a mistake, I'd appreciate it.

    Create event:
    Code:
    td = ds_list_create(); // List that stores data for each step
    td_rewind = 0; // How much to rewind
    
    max_seconds = 3; // Max time you can rewind
    
    The td_rewind variable will be used to go back from the last element in the list. So it'll be a negative value, with its minimum value being -list_size.

    Step event:
    Code:
    var rewind_key = keyboard_check(ord("R"));
    
    // Basic movement, move only if the rewind key is not pressed
    if (!rewind_key) {
       x += keyboard_check(vk_right) - keyboard_check(vk_left);
       y += keyboard_check(vk_down) - keyboard_check(vk_up);
    }
    
    // Add current step's data to the list as an array
    if (!rewind_key)  // Not being rewinded
       ds_list_add(td, [x, y, health]); // <- You gotta store as much data as you can, to make the reverse realistic
    
    // Delete first element if it goes past the max time
    if (ds_list_size(td) > 60 * max_seconds) { // max_seconds is 3
       ds_list_delete(td, 0);
    }
    
    // Now to rewind
    var size = ds_list_size(td);
    
    if (rewind_key && size + td_rewind > 0) { // Second condition makes sure that we don't go past the list size
       td_rewind--; // Go back
    
       // Reapply data from list
       var arr = td[| size + td_rewind];
       x = arr[0];
       y = arr[1];
       health = arr[2];
    }
    // Reset rewind
    else if (!rewind_key) {
       td_rewind = 0;
    }
    Clean up event:
    Code:
    ds_list_destroy(td);
    Hope it helps anyone out there!
     
    SilentxxBunny and Toque like this.
  2. Mert

    Mert Member

    Joined:
    Jul 20, 2016
    Posts:
    358
    And if you do it slooowly, you'll get an awesome Prince of Persia effect.
    Beautiful tutorial
     
    Filkata and matharoo like this.
  3. Edwin

    Edwin Member

    Joined:
    Jul 15, 2018
    Posts:
    406
    Can't apply this in GM'S 1.4
     
  4. chamaeleon

    chamaeleon Member

    Joined:
    Jun 21, 2016
    Posts:
    931
    Show some initiative and create a local variable array that you populate and store instead. Or create a script that that takes those arguments as arguments and return the array.
     
    matharoo likes this.

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