#28953 - Andor - Tue Nov 09, 2004 4:22 am
For my game, I've coded up a actor management/scripting system based on one that I programmed in Visual Basic for my games on the PC. In this system, each actor is an instance of the class cActor, which contains all the variables an actor could ever possibly need, along with all the routines for interpreting the scripts that I feed it.
However, it appears that my actor management system is terribly slow on the GBA: 12 actors on the screen, doing very little aside from walking around, consume no less than 127 vblanks (~156,464 cpu cycles). I have no idea why this should take so long (aside from the obvious: I'm new to c++, and my code is poorly written =P).
What's especially slow is when I have one actor read/write to another actor's variables:
From the Actor's script (stored in a s16 const array):
This is the routine that is run by that statement:
And this is the routine that gets a variable (this is called every time the Actor needs to get the contents of a variable:
And for the record, here is the definition of class cActor:
I would be happy to post the entire system, but it's over 1400 lines long, and I'm not sure anyone would want to bother looking through it (if I'm wrong, and anyone is interested, I'd be more than happy to post it - it's reasonably well formated and shouldn't be too hard to get through).
Off the top of anyone's head, am I doing anything wrong - something that might explain why my actor system is so slow?
However, it appears that my actor management system is terribly slow on the GBA: 12 actors on the screen, doing very little aside from walking around, consume no less than 127 vblanks (~156,464 cpu cycles). I have no idea why this should take so long (aside from the obvious: I'm new to c++, and my code is poorly written =P).
What's especially slow is when I have one actor read/write to another actor's variables:
From the Actor's script (stored in a s16 const array):
Code: |
//get the value of variable8 of the Actor whose index = 5.
//in other words: me.variable9 = Actors[5].variable1 asGetOtherVar, 5, avVariable1, avVariable9, |
This is the routine that is run by that statement:
Code: |
void cActorEntity::ActorScript_GetOtherVar(s16 vvar1, s16 vvar2, s16 vvar3)
{ s16 ActorIndex, VarToGet, retVariable, retValue; if (ActorScript_IsAVariable(vvar1) == 1) {ActorIndex = ActorScript_GetVariable(vvar1);} else {ActorIndex = vvar1;} //don't get the value of the second vvar - instead, pass the index of the variable desired. VarToGet = vvar2; //don't get the value of the third vvar - instead, pass the index of the variable desired. retVariable = vvar3; retValue = Actors[ActorIndex].ActorScript_GetVariable(VarToGet); ActorScript_SetVariable(retVariable, retValue); return; } |
And this is the routine that gets a variable (this is called every time the Actor needs to get the contents of a variable:
Code: |
s16 cActorEntity::ActorScript_GetVariable(u16 vartoget)
{ switch (vartoget) { case avTileX : //tileX return tileX; case avTileY : //tileY return tileY; case avOffsetX : //offsetX return offsetX; case avOffsetY : //offsetY return offsetY; case avSpriteID : //spriteID return spriteID; case avSpriteFrame : //spriteFrame return spriteFrame; case avSpriteSize : //spriteSize return 0; //because you can't read the sprite size. oh well, eh? case avSpritePalette : //spritePalette return spritePalette; case avSpriteAddress : //spriteAddress return spriteAddress; case avSpeed : //speed return speed; case avScriptID : //scriptID return scriptID; case avScriptLine : //scriptLine return scriptLine; case avReturnScriptLine : //returnScriptLine return returnScriptLine; case avActivateID : //activateID return activateID; case avActivateLine : //activateLine return activateLine; case avReturnActivateLine : //returnActivateLine return returnActivateLine; case avVariable1 : //variable1 return variable1; case avVariable2 : //variable2 return variable2; case avVariable3 : //variable3 return variable3; case avVariable4 : //variable4 return variable4; case avVariable5 : //variable5 return variable5; case avVariable6 : //variable6 return variable6; case avVariable7 : //variable7 return variable7; case avVariable8 : //variable8 return variable8; case avVariable9 : //variable9 return variable9; case avVariable10 : //variable10 return variable10; case avVariable11 : //variable11 return variable11; case avVariable12 : //variable12 return variable12; case avFlag_ActivateN : //flag_activateN switch (flags & 0x8000) { case 0 : return 0; default : return 1; } case avFlag_ActivateS : //flag_activateS switch (flags & 0x4000) { case 0 : return 0; default : return 1; } case avFlag_ActivateW : //flag_activateW switch (flags & 0x2000) { case 0 : return 0; default : return 1; } case avFlag_ActivateE : //flag_activateE switch (flags & 0x1000) { case 0 : return 0; default : return 1; } case avFlag_MovingN : //flag_movingN switch (flags & 0x0800) { case 0 : return 0; default : return 1; } case avFlag_MovingS : //flag_movingS switch (flags & 0x0400) { case 0 : return 0; default : return 1; } case avFlag_MovingW : //flag_movingW switch (flags & 0x0200) { case 0 : return 0; default : return 1; } case avFlag_MovingE : //flag_movingE switch (flags & 0x0100) { case 0 : return 0; default : return 1; } case avFlag_HFlip : //flag_HFlip switch (flags & 0x0010) { case 0 : return 0; default : return 1; } case avFlag_Visible : //flag_Visible switch (flags & 0x0008) { case 0 : return 0; default : return 1; } case avFlag_WhichScript : //flag_WhichScript switch (flags & 0x0004) { case 0 : return 0; default : return 1; } case avFlag_NoPause : //flag_NoPause switch (flags & 0x0002) { case 0 : return 0; default : return 1; } case avFlag_InUse : //flag_InUse switch (flags & 0x0001) { case 0 : return 0; default : return 1; } } } |
And for the record, here is the definition of class cActor:
Code: |
class cActor {
public: s16 tileX, tileY; s16 offsetX, offsetY; u16 spriteAddress; s16 spriteID, spriteFrame, spriteSize1, spriteSize2, spritePalette; s16 speed; s16 scriptID, scriptLine, returnScriptLine; s16 activateID, activateLine, returnActivateLine; s16 variable1, variable2, variable3, variable4; s16 variable5, variable6, variable7, variable8; s16 variable9, variable10, variable11, variable12; u16 flags; void RunActorScript(); void Activate(); void Deactivate(); s16 ActorScript_GetVariable(u16 vartoget); void ActorScript_SetVariable(u16 vartoset, s32 value); private: u8 ActorScript_IsAVariable(s16 vartotest); void ActorScript_Set(s16 var1, s16 vvar2); void ActorScript_Add(s16 var1, s16 vvar2, s16 vvar3); void ActorScript_Sub(s16 var1, s16 vvar2, s16 vvar3); void ActorScript_Mul(s16 var1, s16 vvar2, s16 vvar3); void ActorScript_Div(s16 var1, s16 vvar2, s16 vvar3); void ActorScript_Mod(s16 var1, s16 vvar2, s16 vvar3); void ActorScript_Inc(s16 var1); void ActorScript_Dec(s16 var1); void ActorScript_Rnd(s16 var1, s16 vvar2, s16 vvar3); void ActorScript_MovA(s16 vvar1, s16 vvar2); void ActorScript_MovR(s16 vvar1, s16 vvar2); void ActorScript_Goto(s16 value); u8 ActorScript_If(s16 vvar1, s16 var2, s16 vvar3); void ActorScript_SendCmd(s16 var1, s16 vvar2, s16 vvar3, s16 vvar4); void ActorScript_CallMacro(s16 var1); void ActorScript_Return(); void ActorScript_GetBlockStatus(s16 vvar1, s16 vvar2, s16 var3); void ActorScript_SetBlockStatus(s16 vvar1, s16 vvar2, s16 vvar3); void ActorScript_Spawn(s16 var1); void ActorScript_Kill(s16 var1); void ActorScript_SetOtherVar(s16 vvar1, s16 vvar2, s16 vvar3); void ActorScript_GetOtherVar(s16 vvar1, s16 vvar2, s16 vvar3); void AdvanceScriptToEndIf(); }; |
I would be happy to post the entire system, but it's over 1400 lines long, and I'm not sure anyone would want to bother looking through it (if I'm wrong, and anyone is interested, I'd be more than happy to post it - it's reasonably well formated and shouldn't be too hard to get through).
Off the top of anyone's head, am I doing anything wrong - something that might explain why my actor system is so slow?