Craig Mattson (Personal Website)
Home - Blog, News, About MePrograms - C#.Net, Java, VB6MusicWebsites

Viewing News Article

Action Replay in Games (13/08/2007 11:25:23 AM)

On MSN tonight, I was discussing the theory of Action Replay in games and how to apply this technology to my own programs. For those reading this and wondering what the hell is this guy talking about and want something more interesting to read/see, might I suggest you look here.

For those who were not mesmorised by the above link, Action Replay is a concept used in games to record replays or demos of what happens within a game. To keep the file sizes down, one would assume they use their own algorithms to store important data to be replayed back in a stream, probably tied together using :o timers or threads. But how do they do it?

I am working on a web project (for argument sakes, lets assume I am creating a knock off of the game, Quibbles that I first had a VB3 version of in 1995) that requires me to record an instant replay of these 3 quibbles during a race. There needs to be consideration on file storage (lets say 100MB for race Storage), and consideration on the accuracy of the race. So how does one approach it?

Record using Video:

This is by far the most accurate way to record anything. What ever is recorded in video format is guaranteed to be the same on all computer systems and other video capable devices. But this poses the biggest problem of all. File size. In 100MB, that's less than 100 races. What if this project of mine is to last for 2-3 years at any time before a clean out? Say 8 races a day for 365 days a year at 1MB each, this is just way too much. 2920MB just for races is a little bit absurd.

Record frame by frame where each and every object is:

Most games these days probably use this method given the file size of the demo files recorded. For instance, 5-6MB for a file storing 20 seconds of footage must be storing something spectacular. This type of method would be great as no actual physics has to be recorded, nor do you have to record un-necessary footage on each frame like the landscape. In this type of game above, we are looking at storing say: the quibbles x and y position for the entire race.

If a race lasts 30 seconds, and a quibble moves 30 times per second, then this is a staggering 2,700 frames. Whilst the file size is much smaller to store 2,700 peices of information, what happens if the project was to be increased to have 30 racing and races go for 2 to 3 minutes? This becomes up to 162,000 frames. Certainly unviable when file sizes would reach 1MB very quickly (only 33% of that of the video option).

With this in consideration, maybe we should investigate a hybrid of the above theory, especially for a website?

Random Seeds for AI:

This theory comes in handy. In computing, each random number has a seed. For instance, a seed of 1 may produce between 1 and 100 the series 1, 5, 9, 16 as the first four numbers. This is the same as long as the seed is the same, so instead of storing each frame, maybe we just give each quibble a random generated seed that is stored somewhere for the replay? This theory is a supurb theory for this kind of game, but what if we wanted to take speed into consideration? The seed isn't very helpful then.

Probability Distribution with Key Frames:

Well, here is an idea that may be useful. Lets say we are running a replay on a race for the 3 minutes defined above. The important key thing to take into consideration in a race is precision, especially within the last part of the race, say... the last half of a screen? What if, using the example above we worked out that for the last 400 pixels of a race that happened to be 10,000 pixels long was the most important? You know, ensuring that the finishing position didn't change?

The idea is that say each second of the race (180) up until the last 400, we store in the initial recording the position. This means for approximately 170 seconds, we store just one value. For the last 10 seconds roughly, we can afford to be more precise and at 30 for 10 seconds means about 300 extras on the 170 there. This mounts up ofcourse to about 15,000 frames. Certainly more managable at about 40-50KB.

So in the replay how do we deal with the gaps between the one second? Well, if we store in the keyframe that at 1 second, the x value needs to be at a particular place, you can either use a probability distribution of values to get there, or just increase an average of the distance (for instance, if x was 2 for the frame before and is now 4, then move 2/30 per frame). This would do the job, but would look very strange.

The 2 ways to fix this is to either a) increase the key frames to once every half a second (increases overall data to 20,000 (50KB to 60KB) making it more accurate) or b) use probability to generate some form of movement. As long as they get to the end and roughly resemble it, the user should be none the wiser unless they are analysis buffs.

Seeds with Key Frames:

The final idea is to use seeds at particular key frames. As mentioned above, the seed has a predefined sequence of random numbers that could be used appropriately. Given we want to take into account speed and skill to generate a race, it is possible that the script organises before the race starts a random number. This would be stored in the demo file, and before the race starts, we would then define what the maximum left/right is and how often it can reach the desired maximum left/right movement (speed and skill respectively) and use the seed to generate.

The only concern I have is the synchronisation so to improve this, you could introduce key frames at every second or two just to ensure everything is on track.

Here is a rough type of thing I am trying to replicate that would work all the time providing a random seed is generated. Please note that this is almost pseudocode for PHP. Although this code compiles and works, it is only a working model and doesn't actually produce anything more than a list of numbers.

        srand($RANDOM_SEED_NUMBER); //Seed generated at random by script
        $high = 0; //Sets up a count
        $low = 0;  //Sets up another count
        for($i=0; $i < 100; $i++) //Tests 100 times
            $testseed = rand($SKILL_LEVEL,100); //Determines high/low probability for skill
            if($testseed >= 90) //If reaches certain point
                $avd = rand($MEDIUM_SPEED,$FASTEST_SPEED); //Move high amount based on medium speed
            } else {
                $avd = rand(1,
$MEDIUM_SPEED); //Move up to medium
            echo $avd."<br />";
        echo "High: ".$high." Low: ".$low;

Either way I choose to go, this is one widely undocumented feature that Google can't seem to find for me. I'd be interested to hear other input on this situation, so yeah - if you have anything you could possibly add, the comments are there for your use :)

[Print View]