Sponsored By

Braid Style Rewind System 03

Third post for the rewind system.

Derek Dittmer, Blogger

February 18, 2013

5 Min Read

At this point, I am knee deep in the problems of making the rewind system. It is tough to try to do anything else but try to fix this almost-working system, but I figure this is one of the most important parts of my thought process.

I made two new scripts: the TimeManager, and the Rewindable.

The time manager is very simple. It just keeps track of time. It has two, very important static variables: a bool to see if you are rewinding or not, and what the current time is (starting when the game loads). The bool makes the time count down if you are rewinding (won't go below zero), otherwise it keeps going up. Simple, but gets the job done.

The reason that I did this, was there are other things that need to know if you are rewinding of not, which makes sense. My animation class is one of them. Which way should the animation go? Ask the TimeManager. The reason for keeping track of time is for knowing when things happen. I was talking with another student, who had listened to one of Jonathan Blows talks, and he told me that in Braid your movements are only saved if you are moving. That makes a ton of sense to me. It saves a lot of space by not saving the position every time. I just need to save an extra float to have that time stamp of when he was in this position. Awesome.

Right now, the only things that use the TimeManager are my animationBase class and my Rewindable. The animation class uses the static bool to make the animation go the opposite way. Basically, you are facing the wrong way, and you are playing the animation in reverse if it is rewinding. It seemed like an easy way to do it to me.

Alright, onto the Rewindable class: the big one. My idea is that all you have to do is slap this script onto the player, and he will be rewindable. Here's some of the important data: 
private class LastPos 

   float mTimeStamp; 
   float mXPos; 
   float mYPos; 
   public void Set(float aTimeStamp, float aXPos, float aYPos) 
      mTimeStamp = aTimeStamp; 
      mXPos = aXPos; 
      mYPos = aYPos; 

   public float GetTimeStamp() { return mTimeStamp; } 
   public float GetXPos()      { return mXPos; } 
   public float GetYPos()      { return mYPos; } 

List mActions; //List of last positions

LastPos contains all the data that I need when rewinding. I tried to make it a struct, but for some reason the Set function wasn't working, so I just changed it to a class and everything worked perfect.

Using a list seemed like the perfect way to hold all the LastPos'. I need to push new stuff on all the time, so being dynamic was a must. It also is easy to push things onto the back, and pop them off. So, when I am rewinding, all I need to do is look at the last one, and keep popping them off when I get there.

I put this onto the player, then I just needed to Lerp between the positions. I already had the positions, and I also have how long is in between by comparing the timestamps. I didn't plan it, because I didn't know exactly how Lerp worked, but saving the timestamps also let me go backwards at the same speed as I did it forward.

Basically, how it works is, if you are going forward: every couple of frames, it checks if you have moved. If you have, it will save that position and push it onto the mActions list. If you are rewinding, it will initialize the lerp (start pos, end pos, and how long) and then will move you there. I was able to use the TimeManagers currentTime to see if you are past where you are supposed to be, and then just pop off the last thing, and lerp to the next point.

Getting it to rewind at the right speed was tough, because I didn't quite understand what the time argument in Lerp was. To be completely honest, I still don't know exactly how it works. It is a number between 0 and 1, and is kind of a progress bar for how far along you are from your startPos to your endPos. So, 0 is at the start, and 1 is at the end. Either way, it now rewinds at the right speed.

Right now, I am having issues with the animations playing backwards. It is very jittery, and not playing the full animation. I am guessing that it is finding that the character isn't moving, which sets it to the standing animation. So, the rewind is kind of working and the animations are kind of working, but they just aren't working together. It shouldn't be too much of a problem; I just need some time to mess with it to make it work.

Also, I only added the Rewindable to the player. I am thinking I could just add some extra logic to the enemy and moving platform to get them to move backwards when rewinding. That way, I can save more room to get the player to rewind for a longer time. That's the plan at least. The only thing that is rewinding right now is the player, and only his position with broken animation. It will probably still need to be smoothed out after that.

Alright, enough talk for now; there are problems that need fixing! But in the meantime, check out what I got so far:


Just a quick update: I just moved my checking if you should go to the next point logic above the moving logic, and it smoothed the animation out very nicely. Looking good!

(To see/play/download the project of final product, go to my website: http://derek.dittmer.com/please-be-kind.html

Read more about:

Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like