Time reversal in a constant-running scene

Welcome to our brand new Clickteam Community Hub! We hope you will enjoy using the new features, which we will be further expanding in the coming months.

A few features including Passport are unavailable initially whilst we monitor stability of the new platform, we hope to bring these online very soon. Small issues will crop up following the import from our old system, including some message formatting, translation accuracy and other things.

Thank you for your patience whilst we've worked on this and we look forward to more exciting community developments soon!

Clickteam.
  • Good morning,

    I'm working on a title that has a 2D runner-scene (I.E. Canabalt). My game doesn't feature loss, only progression, but for this scene I want to implement a penalty for collisions that warps you back to a waypoint. I could just do a fade out, but I thought it would be way cooler to actually retrace the player's steps in fast motion (it would also fit with the theme of the game). Has anyone done this that would be willing to help me along with some ideas?

    One of the things I love about Fusion is the ability to simply run into walls, try crazy stuff, and figure things out (1200 hours in, and loving it!), but another thing I love is the community. You have all unknowingly helped me for over two years now, showing me tips and tricks. I thought I would turn to you guys for any ideas.

    I have one idea, but have never attempted anything like it before.

    By using some kind of pathfinding I could just have the animations reverse as the game drags the player back via any convenient route, but that wouldn't quite be as spiffy as using the *actual* path the player made.

    Thank you all!

  • Hi! So what you want is simply to track the last positions the player had? Not so difficult! Just add the player position to an array / list / string either always or at a certain interval. I would use a 2D number array for best performance.

    Example with number array:

    * Always
    - Array: Write value XPos of player to XY: (Interval, 0)
    - Array: Write value YPos of player to XY: (Interval, 1)

    'Interval' must be a simple counter that adds 1 each interval.
    When the player reaches a checkpoint you reset the array and the Interval counter.

    If positions are the only thing you need to store, then that's all you need to do for that.

    To backtrack the positions, simply read the array backwards and set the player's position to X = ValueAtXY( "Array", Interval, 0 ) and Y = ValueAtXY( "Array", Interval, 1 ).

    Hopefully this was what you wanted :)

    Edited 3 times, last by Popcorn: I had the write events wrong! (December 13, 2016 at 10:33 AM).

  • Make sure to also store the players current animation and frame, in that array as well, that way it plays back the proper animations when reversing instead of just the animation currently playing when he hits the wall.

    Fusion Veteran Since 2005. Example Projects: Please login to see this link.

  • The more objects and complexity to have to your scene, the more you'd need a robust system. I've actually created exactly that in MMF2, but its not an easy task. If your game is like canabalt and has all objects either on a deterministic generation based on a single seed, or does not dynamically create new instances or destroy old instances, its much easier to implement a time rewind, because you can simply store the variables for each object and rewind them, or even just calculate where their 'backwards movement' would be.

    When you have objects being created and destroyed however, you need to combine a dual system of storing the variables for your objects as well as tracking the instances of objects. For example, I store an array of 1000 max objects * 1000 frames to record into the past * 16 variables stored per object * 4 bytes per integer, for a 1000*1000*16*4 = 64 megabyte array, then I have a deque storing arrays of actions executed each frame to be read in reverse in string format, for example "destroy object 14", so when object 14 is destroyed, that string is pushed to the deque and object 14's ID is released, when read in reverse its popped off and a new object instantiated with ID 14 reserved and retrieves its variables from the array. The deque covers state based changes and other frame properties and another queue leases out the indexes. And the whole thing encompasses many thousands of lines of code in MMF2 and Lua and C

    My point being that this can be a very difficult task if you want it to work in a fully fleshed out manner, so if you plan ahead with your project and do a very simple game with a simple rewind feature, you could make it work way easier. If you have the same objects with none being randomly created/destroyed, you could simply say that an object moving left at +1 speed in reverse moves at -1 speed, and if you have only a single triggered protocol per object, say a bin on top of a building in canabalt, that the player can only interact with once by running into it, you simply store the timestamp of when the player hits it, then when rewinding calculate based off that point, so you could have slightly more


    So I heavily suggest that you try to structure your game in a way that you can calculate where objects were in the past without needing to store it. If you have a single variable "player distance from start", and instead of randomly generating obstacles, you use a pseudo-random deterministic formula for when obstacles appear (for example, "a*X+b mod c", where a,b&c are constant numbers and X is your input variable), then you can calculate the positions of any objects based on the distance input. Its enormously easier to do this when you have deterministic scenes, and a running game like canabalt is a great candidate for that. If you combine it with what I said above about a timestamp, your overall state pseudocode would look like this:

    If X >= timestamp:
    >position = position_of_object_after_being_hit_by_player(x - timestamp)
    If X < timestamp:
    >position = deterministic_position_of_object(x)
    If player hits object:
    >timestamp = X

    make one protocol for figuring out where objects should be deterministically, one for where they should be after the player hits them (spinning away into the air or whatever), bam, games made that much easier to code. You wouldn't need to record the position of objects

    Edited 2 times, last by Pixelthief (December 15, 2016 at 5:30 PM).

  • PixelThief, holy mackerel! That sounds like an excellent recommendation for a Canabalt type of game, I consider myself fortunate to have read that.

    For this particular model (it is one scene in a game that normally operates as a simple platformer) I will not require a rock solid foundation for object generation and destruction, as the scene is just a minute or two long and will cover a relatively short, static, distance (It's a game that ops for small, meaningful moments). No procedural content here, but it is clear that your system would work marvelously for such a scene.

    Thank you for the excellent response.

  • Guys, the originally proposed idea (with the animation addition) by Popcorn and PlasmaVoid worked very well in my simple scene, for any who are attempting this.

    Tweaking the speed at which the array updates, and doubly so in reverse, smoothed it out. It even fits with my theme of fragmentation.

    Thank you all very much!

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!