Finished timeline data structures!



The ActionTimeline + suite of actions/utilities library is complete. Along the way, I found various expected and unexpected edge cases. I came up with solutions to all problems I could think of, with ~650 lines of test code to ensure it works as expected. Integrating the library into the actual game should bring out more bugs if there are any. There are also many performance improvements that could be made later, if they show up as bottlenecks in the profiler.

Maintaining A Minimal Timeline

It is important for the library to keep the timeline minimal, so that the “can*” states are always correct. These states will eventually propagate to the UI, indicating to the user what is currently possible:

  • canUndo
  • canRedo
  • canRewind
  • canUnwind

One of the first major edge cases to handle was executing actions that only mutated state of paused entities. An example of this is when the player is paused, but rewinds time and then moves around. After they do this, they should be able to unwind time (forward time travel). This originally didn’t work, so I had to make things smart about when the timeline was updated/overwritten with new indices. Now, the timeline isn’t touched when state mutations happen only to paused entities.

Another, more serious edge case, was when an entity was paused (or played) later on in the timeline. There would be all kinds of bugs that could happen with those objects skipping (or using incorrect) timeline elements and getting out of sync with reality. To fix all of this strange logic for good, I implemented a virtual history erase by storing the minimum action index at the point of erasure. That means whenever a paused state is changed on an entity, all of its previous actions won’t affect it anymore. There is no other way to decrease the minimum value, outside of undo/redo. The timeline is also pruned whenever paused states are changed, which keeps the can* functions updated. That means the timeline always shrinks with paused states changing, and will never increase in size with this type of game logic.

Next Steps

  • Time Stuff
    • Integrate new library into game, using the new Action interface
    • Setup keyboard controls (Z/X/C/V)
    • Create UI controls (related to potentially re-designing the UI as well)
    • Add time mechanics: Pausers, players, paused areas, playing areas, and initial time states for entities (more layers are needed)
    • Make levels that use the new time mechanics
  • Future
    • Finish rotators
    • Finish remaining mechanics/logic/edge cases
    • Make a road-map for the rest (polish for release)