|  | 
 
 
 
 
 
Tutorial about recording and playback a game session.
 Then, during playback, the file is red one line at each frame, and the line is parsed. 
The keys red in the line, will simulate the same key pressure.
 
 In order to apply these concepts, you have to write your player keyboard or mouse control in a way that the same function called by the keys pressed, can be called also indipendently by the replay engine. In other words, suppose you have an astroship, and you move it left and right using the arrow keys; here is how the code may be: But in this way, we have the ship movement embedded in the if keydown() statement; later, your replay engine can't replicate that, unless you write a clone of that function. What I want to suggest here, is to write generic functions for movement, so that they can be called also from another point of the program, for example from your playback engine. So the lines above, should look like: You can, of course, using just one function here; I did split it in two functions because I find it more clear, even if redundant. Then later, your playback engine will use this function when reads the file: But WTH that if condition means, I hear you cry again... Hey, calm down and relax m8 ! Take a break now.. what's about a cup of tea ? I like very much Twinings... Ok ok, let's go on ! ;-) When you want to record the game session, you have to record the key pressed by the player, right ? Where to record it ? Simple, just use a plain text file. A plain text file has lots of advantages.. you can easily inspect it, easily read and write.. Ok, and how to record the key pressed ? Now, you have to choose your 'protocol' here... say, for example, to write an "R" if the user presses the right button, an "L" if he presses the left button, an "F" if he presses fire, and so on. The thing to keep in mind here is to use unique letters for every key, otherwise if you use "R" for right and for fire, then later you don't know what to do... And also, if the user presses more than one key per time, we have to write both in the same line. Later, the line will be parsed, and each letter will cause the related function to be called. For example, suppose you press the left and fire button while recording. Then, using the protocol above, at that frame you will write, in the file, the string: "LF" Later, reading that line, your playback engine will check: if there is an L in the line, then perform the left movement if there is an R in the line, then perform the right movement Beware ! See that the test for the left comes first, and the test for the right comes after, why ? Well, look here: You see ? First we have coded the check for the left, and then for the right key. The playback engine must obey to this sequence. But now, back to our playback engine: how can we translate these two lines ?: read line from the file if there is an L in the line, then perform the left movement One way could be: See, we read the line, and if the line contains the char "L", then we execute the same function move_ship_left that was called when the user pressed the left button. This, for example, is the way I perform all the movements in my asteroids remake: Important: at each frame, you should write a line to the file, even if the player press no key; the reason is that otherwise the file will be out of sync, because we did not keep track of the command 'no key pressed' ! So, when the player does not press any key, write the symbol "-" or whatever you like, which even if it will be not considered by the parsing function, will keep the file sincronized with the game frame. Notice that when the demo is played back, then the player keyboard control should be deactivated, I mean, the player should not control the ship, otherwise he puts the playback out of sync. You may consider also to use a game status variable; in this way, you can, for example, loop through a presentation, a menu, or the game, depending on the value of this variable. I find it very useful, expecially when the game itself contains more than one status (ex. player playing, exploding, waiting for a new level, etc.). In this example, a game status will be used for Record mode and playback mode. Oh wait... where do we write that dam#*ed file ? Hem... almost forget it.. During record game, at each press of the key, we should add our key to a string that later will be write on the file. I mean, let's consider our ship movement control during recording: As you can see, at each frame a line is written; it could contain any char like "LRF", "L", and so on, or just a "-" if no key were pressed. Well, I hope I have explained all the important things; with this tutorial and with the commented source code, I'm confident you will master it in a while. Of course, for any question please feel free to contact me, and I will be more than glad for being of any help. One thing I want to add: if you plan to play the playback file on other machines, bare in mind these advice: --- sin and cos gives different values on different pc ! Even if the difference is small, you may use your own sin and cos lookup table: just prepare a list of data statement for each sin and cos (from 0 to 360) on your developing pc; then read this values on two array, for example mysin an mycos, and use that instead of using sin and cos. --- real numbers (float) give also different values. In my asteroid remake I use float too, but the difference does not affect playback. --- rotated images; if you use rotated images, and then you use imagewidth and imageheight commands, bare in mind that these commands can give different values on different pc; I mean, the imagewidth can differ by one or two pixels, which is enough to mess up your playback. You can't imagine how much time I've spent to find out this strange behaviour ! The game session recorded on my machine, that runs perfectly on the same machine, gave umpredictable results on different pc, and believe me, that taked me nights and days before I figured out !!!. The workaround was to set the width and height of the related images, to a constant value. In this way, no imageheight and imagewidth were used anymore. But how hard it was to find that out ...!!! 
So keep in mind these advices, and you will be safe. Hopefully...
 Don't forget to take a look to my asteroids remake, which uses exactly the method described: 
Have fun,
 For a printable copy of this article, please click HERE. 
 This site is Copyright© 2000-2004, BlitzCoder. All rights reserved.   |