Input recording and playback
Some stuff for recording and playing back input. Useful for cutscenes, and maybe for testing some things.
First, a few functions:
Code:
const int CRKEY_UP = 00000000000001b;
const int CRKEY_DOWN = 00000000000010b;
const int CRKEY_LEFT = 00000000000100b;
const int CRKEY_RIGHT = 00000000001000b;
const int CRKEY_A = 00000000010000b;
const int CRKEY_B = 00000000100000b;
const int CRKEY_L = 00000001000000b;
const int CRKEY_R = 00000010000000b;
const int CRKEY_START = 00000100000000b;
const int CRKEY_MAP = 00001000000000b;
const int CRKEY_EX1 = 00010000000000b;
const int CRKEY_EX2 = 00100000000000b;
const int CRKEY_EX3 = 01000000000000b;
const int CRKEY_EX4 = 10000000000000b;
void ReplayInput(int inputArr, int pressArr)
{
int inputPtr=-2; // Start at -2 so they'll increment to 0
int pressPtr=-2;
int currInput;
int currPress;
int inputTimer=0;
int pressTimer=0;
bool inputDone=false;
bool pressDone=false;
while(true)
{
// Advance through the Input* array.
if(!inputDone)
{
if(inputTimer>0)
inputTimer--;
else
{
// Timer expired; move to the next input.
inputPtr+=2;
if(inputPtr<SizeOfArray(inputArr))
{
currInput=inputArr[inputPtr];
inputTimer=inputArr[inputPtr+1]-1;
// If the timer was 0, consider this the end.
if(inputTimer<0)
{
inputDone=true;
currInput=0;
}
}
else
{
// Reached the end
inputDone=true;
currInput=0;
}
}
}
// Advance through the Press* array.
if(!pressDone)
{
if(pressTimer>0)
pressTimer--;
else
{
// Timer expired; move to the next input.
pressPtr+=2;
if(pressPtr<SizeOfArray(pressArr))
{
currPress=pressArr[pressPtr];
pressTimer=pressArr[pressPtr+1]-1;
// If the timer was 0, consider this the end.
if(pressTimer<0)
{
pressDone=true;
currPress=0;
}
}
else
{
// Reached the end.
pressDone=true;
currPress=0;
}
}
}
// Check if finished here so there's not an extra
// frame of no input at the end.
if(inputDone && pressDone)
return;
SetInput(currInput, currPress);
Waitframe();
}
}
int GetInput()
{
int keys=0;
if(Link->InputUp)
keys|=CRKEY_UP;
if(Link->InputDown)
keys|=CRKEY_DOWN;
if(Link->InputLeft)
keys|=CRKEY_LEFT;
if(Link->InputRight)
keys|=CRKEY_RIGHT;
if(Link->InputA)
keys|=CRKEY_A;
if(Link->InputB)
keys|=CRKEY_B;
if(Link->InputL)
keys|=CRKEY_L;
if(Link->InputR)
keys|=CRKEY_R;
if(Link->InputStart)
keys|=CRKEY_START;
if(Link->InputMap)
keys|=CRKEY_MAP;
if(Link->InputEx1)
keys|=CRKEY_EX1;
if(Link->InputEx2)
keys|=CRKEY_EX2;
if(Link->InputEx3)
keys|=CRKEY_EX3;
if(Link->InputEx4)
keys|=CRKEY_EX4;
return keys;
}
int GetPressed()
{
int keys=0;
if(Link->PressUp)
keys|=CRKEY_UP;
if(Link->PressDown)
keys|=CRKEY_DOWN;
if(Link->PressLeft)
keys|=CRKEY_LEFT;
if(Link->PressRight)
keys|=CRKEY_RIGHT;
if(Link->PressA)
keys|=CRKEY_A;
if(Link->PressB)
keys|=CRKEY_B;
if(Link->PressL)
keys|=CRKEY_L;
if(Link->PressR)
keys|=CRKEY_R;
if(Link->PressStart)
keys|=CRKEY_START;
if(Link->PressMap)
keys|=CRKEY_MAP;
if(Link->PressEx1)
keys|=CRKEY_EX1;
if(Link->PressEx2)
keys|=CRKEY_EX2;
if(Link->PressEx3)
keys|=CRKEY_EX3;
if(Link->PressEx4)
keys|=CRKEY_EX4;
return keys;
}
void SetInput(int input, int press)
{
Link->InputUp=input&CRKEY_UP;
Link->PressUp=press&CRKEY_UP;
Link->InputDown=input&CRKEY_DOWN;
Link->PressDown=press&CRKEY_DOWN;
Link->InputLeft=input&CRKEY_LEFT;
Link->PressLeft=press&CRKEY_LEFT;
Link->InputRight=input&CRKEY_RIGHT;
Link->PressRight=press&CRKEY_RIGHT;
Link->InputA=input&CRKEY_A;
Link->PressA=press&CRKEY_A;
Link->InputB=input&CRKEY_B;
Link->PressB=press&CRKEY_B;
Link->InputL=input&CRKEY_L;
Link->PressL=press&CRKEY_L;
Link->InputR=input&CRKEY_R;
Link->PressR=press&CRKEY_R;
Link->InputStart=input&CRKEY_START;
Link->PressStart=press&CRKEY_START;
Link->InputMap=input&CRKEY_MAP;
Link->PressMap=press&CRKEY_MAP;
Link->InputEx1=input&CRKEY_EX1;
Link->PressEx1=press&CRKEY_EX1;
Link->InputEx2=input&CRKEY_EX2;
Link->PressEx2=press&CRKEY_EX2;
Link->InputEx3=input&CRKEY_EX3;
Link->PressEx3=press&CRKEY_EX3;
Link->InputEx4=input&CRKEY_EX4;
Link->PressEx4=press&CRKEY_EX4;
}
GetInput() and GetPressed() return numbers representing the state of Link->Input* and Link->Press* for all standard keys (directions, start, map, A/B/L/R/Ex*). SetInput() takes those same numbers as arguments and sets each Input and Press variable accordingly.
ReplayInput() takes two arrays. The first is a series of Input*, and the second is a series of Press*. The arrays consist of pairs of input states and durations. For instance:
int inputArr[] = { CRKEY_DOWN, 30, CRKEY_DOWN | CRKEY_A, 10, CRKEY_UP, 15 };
That represents down being held for 30 frames, down+A for 10 frames, and up for 15 frames. The Press* array works the same way, even though keys aren't normally newly pressed for consecutive frames.
Hit the character limit. Continued below.