And I'm back! This will be the last time, because I have finished it! I found some bugs, and put some extra polish into it.
So the first thing that I did was finish getting those sounds to rewind. After actually getting a sound to play in reverse, it wasn't too hard, though I did have some trouble with it. I knew I would need to save the time stamps of when these sounds played, so they could be played in reverse, but I didn't know how to organize them. I tried and failed a few times, but it is working quite well now. All the sounds are kept in a master sound list, with the time stamp (int variable) and an index into an array that holds that sound (byte variable), so that I know which sound was played at that time.
No problem - until I ran into something that I had not foreseen. I knew for playing the sounds backwards, I would need to save them when the sound finished playing and play it from there. Cool, that works, but when I rewind the rewind (play it forward) the sounds are really messed up. That is because they are playing at the end of when they should be playing. Even if I saved the sounds when the sound started, it would sound weird if I played them now in reverse. Hmm… I thought of having two different sound lists for rewinding and forward, along with a bunch of other bad ideas, but found a better solution: save them when they are played, and when rewinding, check the time stamp minus the clip's length. It isn't frame perfect I'm sure, but it sounds great and I can't even tell that it isn't perfect. Now the game sounds really awesome!
I then found a bunch of little things that made it better. The rewind would mess up if the frame rate dropped, so I just used a constant variable of what the target frame rate was and used that instead of Time.deltaTime. It isn't perfect, but it looks a lot better than it did, and it also saves me from having to save off the deltas for everything that can be rewinded. I found a nice texture import setting: changing filter mode to point made my little sprites look nice and pixilated. I also fixed quite a few very strange problems with rewinding deaths. One was where if the player died and you tapped the rewind button, the game would never do that pause when you died. I also remember the enemy reviving itself when it should have been dead. It seems to all be working fine now. I also stumbled upon something called delegates, which helped me a ton. I was trying to figure out how to let other things know when the rewind started, ended, or speed changed, and the delegate was just perfect. Basically, it is just a bunch of function pointers, so if you call the delegate, it just calls everything in it. It cleaned up my code and was super easy to use.
Alright, after I fixed a few things, I started adding more. I put in that blinking "SHIFT" message when the player dies, so he knows what to do. It was basically the same thing as the showing rewind speed, but only if the player was dead. I also changed the fonts in my game so looks a bit nicer than the default Arial fonts.
The next thing I wanted to add was some screen effect when you are rewinding, like in Braid how it goes into black and white when you rewind and the screen just kind of moves around. After doing a bit of researching (googling), I found that only Unity Pro supports screen effects. Since I couldn't find any way to do it in Unity Free, and I didn't feel like learning how to write my own shader, I went with something kind of hacky. I took Unity's water, added some transparency to it, tweaked some of the water's shader's variables, made it change colors if you are rewinding or rewinding your rewind, made it fade nicely in and out depending on the speed, and bam. To be completely honest, it doesn't look as good as I hoped, but it's still better than nothing. I wasn't going to do all that work and end up with no screen effects.
Alright, the last thing I really wanted to add to my game was those motion trails when you are rewinding, like how Braid does it. It really looks awesome, and I'm glad I did it. It took me quite a while to get it working right. I had a lot of problems figuring out how to save those positions and put the sprites there. Basically, what I did was have 12 game objects in a list, and going through and setting the last one in the list to the first one in the list, and also set that objects position to the players'. So now it cycles through the objects and puts them at them at the player. That wasn't too hard.
What was hard was getting the transparency just right. I wanted to have three of them show up for each rewind speed (so 3 for 1x, 6 for 2x, and so on), and have the last three's transparency lower than the last's, so the end of that motion trail would look cool. The way I was cycling through the list didn't quite work with that in more than one way, so I changed up the way I cycled through the list. I made two sections of the list and cycled through them both, basically the active ones and the inactive ones (because they need to be updated also so they have the right positions when they show up). That worked very nicely. Then I made it so they fade in and fade out, and after a bit of tinkering with it, it looked great.
I've read that the way I am cycling through the list is a bit inefficient (saving the last one, deleting the last one, and putting the saved off at the front of the list), but it was the best solution I could think of. Also, it starts looking a bit strange when you rewind at 8x speed, because even updating the trail's positions every frame isn't enough to keep up and look good. I've tried getting around that somehow, but figured it isn't too big of a problem. Other than those two problems, I think it works fine though.
The last thing I added were some spikes to kill the player, because I wanted to make sure the player could die and figure out the rewind button (because it now flashes "SHIFT") rather then getting frustrated. Just a design thing, but still important.
Alright, now it's done! Well almost. I had problems with the aspect ratio in an actual build because I used the Free Aspect when I was in the editor. So, everything was scaled to this strange aspect ratio that I couldn't make a build of. So I just changed it to 1024x768 and added some more level to it.
This time it is finished for good! I did everything that I wanted to do to this project and more, because I had so much fun with it and managed my time right. I ran into tons of problems, but luckily was able to overcome most of them. I learned a ton more about Unity and programming in general. Just a couple of months ago, I thought rewinding in a game was magic. Now, the magic is gone and I understand how it works. It is kind of sad, but after playing through my little test level, I am glad I took on this awesome project.
I've put up the game and the project if you would like to play it or see how I did put it together, so be sure to check that out.
Thanks for reading! I hope you found it interesting or learned something!
(To see/play/download the project of final product, go to my website: http://derek.dittmer.com/please-be-kind.html)