Jump to content


Photo

Help with replay system


  • Please log in to reply
2 replies to this topic

#1 LucaPM

LucaPM

    GMC Member

  • New Member
  • 2 posts
  • Version:GM8

Posted 17 June 2012 - 10:23 AM

Hi everyone,
My friend and I have been working on a replay system for our game for quite some time.The replay system works like this:
First,we initialize the replay system and we create an array containing the key inputs used by the game (as well as other variables used by the replay system's scripts):
// Map which key does what
keys[0] = objParentPlayer.keyLeft;
keys[1] = objParentPlayer.keyRight;
keys[2] = objParentPlayer.keyUp;
keys[3] = objParentPlayer.keyDown;
keys[4] = objParentPlayer.keyFire;
keys[5] = objParentPlayer.keyMelee;
keys[6] = objParentPlayer.keyShield;
keys[7] = objParentPlayer.keyFocus;

frameNum = 0; //Which frame we are on
frameKeys = 0; //Which keycombination we currently have at a frame
record = true;  //If it is recording
playBack = false;   //If it is replaying

Then we use another script (which,apparently,works just fine) to record the player actions and store it to an INI file:
//First a clean array to record the inputs. Each element represents a key.
for (i = 0; i <= 7; i += 1)
{
    individualKeys[i] = 0;
}

//Record inputs from each key. 1 for push, 2 for release. Save in array each key state.
for (i = 0; i <= 7; i += 1)
{
    a = 0;
    switch (true)
    {
    case keyboard_check_pressed(keys[i]) == true:
        a = 1 break;
    case keyboard_check_released(keys[i]) == true:
        a = 2 break;
    }
    individualKeys[i] = a * power(10,7-i);
}

//Now, translate the array to a number we can save to the ini-file
frameKeys = 0;
for (i = 0; i <= 7; i += 1)
{
    frameKeys += individualKeys[i];
}

//Save the current key-state for current frame to the ini-file. Add extra zeroes if not 8 digit
// to make translation work properly
if frameKeys != 0
{
    frameKeys = string(frameKeys);
    while string_length(frameKeys)<8
    {
        frameKeys = "0"+frameKeys;
    }
    
    ini_open('LastReplay');
        ini_key_delete('PLAYER ACTIONS','Frame ' + string(frameNum+1));
        ini_write_string('PLAYER ACTIONS','Frame ' + string(frameNum+1),frameKeys);
    ini_close();
}

//Go to next frame
frameNum += 1

It will output something like this:
[PLAYER ACTIONS]
Frame 30=00100000
Frame 40=00200000
Frame 44=01000000
Frame 58=00010000
Frame 59=02000000
Frame 74=10000000
Frame 75=00020000
Frame 89=00100000
...

Each digit represents a key : the first digit is the left arrow,the second the right arrow,the third the up arrow and so on (see the array I've showed you before) and 1 means a key is pressed,2 a key is released and 0 means no action;for example at frame 30 the up arrow was pressed while at frame 40 it was released.
Finally,we have a script that reads the INI file and simulates keystrokes accordingly to the INI file that we generated before:
//Read the key-combination for the current frame
ini_open('LastReplay');
   keyCombination = string(ini_read_real('PLAYER ACTIONS','Frame ' + string(frameNum+1),frameKeys));
ini_close();

//Each digit represent a key state. Translate the digits to keyinputs.
for (i = 0; i < 8; i += 1){
    keyToSimulate = string_char_at(string(keyCombination),i+1);
    
    key = keys[i];
    if keyToSimulate == "1"
        keyboard_key_press(key)
 
    if keyToSimulate == "2"
        keyboard_key_release(key)
}

//Go to next frame
frameNum += 1

Howerer,for some reason,the playback script simply won't work and it will treat every key as key 0 (aka the left arrow).We've been trying to fix this for ages with no luck.
Any ideas?
  • 0

#2 slayer 64

slayer 64

    GMC Member

  • GMC Member
  • 3275 posts
  • Version:GM8.1

Posted 18 June 2012 - 03:41 AM

i wouldn't use ini files and i wouldn't use so many string functions and i wouldn't make everything so complicated. try writing everything to a ds list and saving it, or a binary file. don't use 1 for press and 2 for release, make a separate list for each. then you can use 0 or 1.
these functions will take 8 true or false values and put them into a number between 0 and 255. got em from 39dll codez
built byte
/*
  returns a byte based on true/false arguments
  argument0-argument7 = bit values
*/
return 
    argument0*128+
    argument1*64+
    argument2*32+
    argument3*16+
    argument4*8+
    argument5*4+
    argument6*2+
    argument7*1
read byte
/*
  Reads the bit at a certain position in a number
  argument0 = number
  argument1 = bit position (0-7)
  returns the bit value (true/false)
*/
return (argument0 & power(2, argument1))>0
to fix your currently awful code: looks like you're writing the values as a string and reading them as a real, game maker ain't likin that. you should read the values from the ini file using real and string to see wtf game maker is seeing. this code should work based on my old goat experience.
//Read the key-combination for the current frame
ini_open('LastReplay')
keyCombination=ini_read_string('PLAYER ACTIONS','Frame ' + string(frameNum+1),frameKeys)
ini_close()

//Each digit represent a key state. Translate the digits to keyinputs.
for (i = 1; i < 7; i += 1)
switch string_char_at(keyCombination,i)
{
    case "1": keyboard_key_press(keys[i]) break
    case "2": keyboard_key_release(keys[i])
}

//Go to next frame
frameNum+=1

  • 2

#3 LucaPM

LucaPM

    GMC Member

  • New Member
  • 2 posts
  • Version:GM8

Posted 18 June 2012 - 01:48 PM

Well,we already knew the code was sloppy and everything,we just wanted something that worked (altrough it obivously didn't)
Thanks to you we've rewritten everything and now it works just fine! :thumbsup:
  • 1




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users