
org.flixel.system.FlxReplay Maven / Gradle / Ivy
The newest version!
package org.flixel.system;
import org.flixel.FlxG;
import org.flixel.system.input.Input;
import org.flixel.system.replay.FrameRecord;
import org.flixel.system.replay.MouseRecord;
import com.badlogic.gdx.utils.Array;
/**
* The replay object both records and replays game recordings,
* as well as handle saving and loading replays to and from files.
* Gameplay recordings are essentially a list of keyboard and mouse inputs,
* but since Flixel is fairly deterministic, we can use these to play back
* recordings of gameplay with a decent amount of fidelity.
*
* @author Thomas Weston
*/
public class FlxReplay
{
/**
* The random number generator seed value for this recording.
*/
public float seed;
/**
* The current frame for this recording.
*/
public int frame;
/**
* The number of frames in this recording.
*/
public int frameCount;
/**
* Whether the replay has finished playing or not.
*/
public boolean finished;
/**
* Internal container for all the frames in this replay.
*/
protected Array _frames;
/**
* Internal tracker for max number of frames we can fit before growing the _frames
again.
*/
protected int _capacity;
/**
* Internal helper variable for keeping track of where we are in _frames
during recording or replay.
*/
protected int _marker;
/**
* Instantiate a new replay object. Doesn't actually do much until you call create() or load().
*/
public FlxReplay()
{
seed = 0;
frame = 0;
frameCount = 0;
finished = false;
_frames = null;
_capacity = 0;
_marker = 0;
}
/**
* Clean up memory.
*/
public void destroy()
{
if(_frames == null)
return;
int i = frameCount-1;
while(i >= 0)
_frames.get(i--).destroy();
_frames = null;
}
/**
* Create a new gameplay recording. Requires the current random number generator seed.
*
* @param Seed The current seed from the random number generator.
*/
public void create(float Seed)
{
destroy();
init();
seed = Seed;
rewind();
}
/**
* Load replay data from a String
object.
* Strings can come from embedded assets or external
* files loaded through the debugger overlay.
*
* @param FileContents A String
object containing a gameplay recording.
*/
public void load(String FileContents)
{
init();
String[] lines = FileContents.split("\r?\n|\r");
seed = Float.parseFloat(lines[0]);
String line;
int i = 1;
int l = lines.length;
while(i < l)
{
line = lines[i++];
if(line.length() > 3)
{
_frames.add(new FrameRecord().load(line));
frameCount++;
if(frameCount >= _capacity)
{
_capacity *= 2;
_frames.ensureCapacity(_capacity - _frames.size);
}
}
}
rewind();
}
/**
* Common initialization terms used by both create()
and load()
to set up the replay object.
*/
protected void init()
{
_capacity = 100;
_frames = new Array(_capacity);
frameCount = 0;
}
/**
* Save the current recording data off to a String
object.
* Basically goes through and calls FrameRecord.save()
on each frame in the replay.
*
* @return The gameplay recording in simple ASCII format.
*/
public String save()
{
if(frameCount <= 0)
return null;
String output = seed+"\n";
int i = 0;
while(i < frameCount)
output += _frames.get(i++).save() + "\n";
return output;
}
/**
* Get the current input data from the input managers and store it in a new frame record.
*/
public void recordFrame()
{
Array keysRecord = FlxG.keys.record();
MouseRecord mouseRecord = FlxG.mouse.record();
if((keysRecord == null) && (mouseRecord == null))
{
frame++;
return;
}
_frames.add(new FrameRecord().create(frame++,keysRecord,mouseRecord));
frameCount++;
if(frameCount >= _capacity)
{
_capacity *= 2;
_frames.ensureCapacity(_capacity - _frames.size);
}
}
/**
* Get the current frame record data and load it into the input managers.
*/
public void playNextFrame()
{
FlxG.resetInput();
if(_marker >= frameCount)
{
finished = true;
return;
}
if(_frames.get(_marker).frame != frame++)
return;
FrameRecord fr = _frames.get(_marker++);
if(fr.keys != null)
FlxG.keys.playback(fr.keys);
if(fr.mouse != null)
FlxG.mouse.playback(fr.mouse);
}
/**
* Reset the replay back to the first frame.
*/
public void rewind()
{
_marker = 0;
frame = 0;
finished = false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy