Skip to main content
gamedev.net
🔒 Locked

Sequencing Code

Started by shabtronic 4 replies 1.2k views
Original Post
shabtronic
shabtronic
HI I'm trying to come up with a way to sequence code easily and without using a million classes.

I want to be able to execute code x frames in the future for y frame duration - something like this:

if (HitSomething)
{
Seq(10,20,PlaySound,"CrashHit.wav"); // Call fun Playsound("CrashHit.wav") in 10 frames time for 20 frames
Seq(10,50,StarFlare,10,20,1.5,4); // Call func StarFlare(10,20,1.5,5) in 10 frames time for 50 frames
}

This is great because it can handle any function, and the code is localised. I can do this - but it's alot of work to get the Variadic stuff working across different platform - requires some hardcore asm to calc the Param stack Size and setup the epilog code e.t.c.

wondering if there are any neat tricks to get something similar.
TheUnbeliever
TheUnbeliever
What's wrong with a priority queue of triggers? That can be as light or heavy-weight as you like.
[TheUnbeliever]
shabtronic
shabtronic
That sounds interesting, I envisage that to work something like this: (assuming the string pool compare works)

void TriggerSys(char* TriggerName,u32 FrameTime)
{
switch (TriggerName)
{
case "BigEyes" :
{
switch (FrameTime)
{
case 0: MorphToBigEyes(0.1); break
case 40: MorphToSmallEyes(0.1); break
case 80: MorphToNormalEyes(0.1); break
}
break;
}
case "BoomSound":
{
PlayWav("Boom.wav");
break;
}
}
}

void TriggerHandler() {...}
MainLoop()
{

if (thisthing)
{
AddTrigger("BigEyes",0,81); // Trigger BigEyes in o frames time for 81 frames duration
AddTrigger("BoomSound",100,1); // Trigger BoomSound in 100 frames time for 1 frame
}

TriggerHandler();
}


is that what your talking about?
BeerNutts
BeerNutts
No, I think you could fit it in the way you initially had it, kind of like this (C++, non-proof-read, but should give you an idea):


// in header file

// void *pParams is some type (or struct) cast to void * to be passed around.
// BE CAREFUL WITH void *!!
typedef void (*tSeqFunc)(void *pParam);

struct tSeqData
{
int FrameToStart;
int NumFramesCall,
tSeqFunc SeqFunc;
void *pParams;

} ;

std::list<tSeqData> SequenceList;


void Seq(int FrameToStart, int NumFramesCall, tSeqFunc SeqFunc, void *pParams)
{
tSeqData DeqData;

// Set FrameToStart at specific frame, just add to the current frame

SeqData.FrameToStart = FrameToStart + CurrentFrame;
SeqData.NumFramesCall = NumFramesCall;
SeqData.SeqFunc = SeqFunc;
SeqData.pParams = pParams;

// insert in list, you should insert in ordered list, so earliest ones are 1st, so you can stop checking
// ones that haven't started yet. I'll let you do that
SequenceList.push_back(SeqData);
}

// in Game Loop, make check
CurrentFrame++;

for (std::list<tSeqData>::iterator it = SequenceList.begin();
it != SequenceList.end(); ) {
if (it->FrameToStart <= CurrentFrame) {
// Call function
it->SeqFunc(it->pParams);

// check if this was last call
if (it->FrameToStart + it->NumFramesCall >= CurrentFrame) {
// remove this one from the list
SequenceList.erase(it);
}
else {
it++;
}
}
else {
// if Ordered List, you've reached an element that hasn't started, so you could break here
}
}


Personally, I'd do that with milliseconds, not frames, but, I guess it depends on what you want to do.
My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)
shabtronic
shabtronic
Hey That's cool I actually did that on my first pass, a very similar mechanism of just a Func pointer and some timing, my only issue with that is, I have to write multiple callbacks. I'm using frames because it's guaranteed to run at 60fps - else I would be using parametric seconds as the timer.

If I was working with a big team - I would engineer it so it's super awesome and all that, My main thing is that I'm designing this game and writing it at the same time, and I'm finding that having to switch from engineer to design whilst I'm coding really kills the creativity, hence I was looking for a super slick way of doing it. It sounds bonkers that - having to write a small function could do that - but that really does happen with me!



void BigEyes(u32 FrameTime)
{
switch (FrameTime)
{

case 0: TweakMorphFromFile("EyesBig.txt",0.2); break;
case 50:TweakMorphFromFile("EyesMassive.txt",0.2);break;
case 100:TweakMorphFromFile("EyesNormal.txt",0.2);break;
}
}


void BlinkEyes(u32 FrameTime)
{

switch (FrameTime)
{
case 0: TweakMorphFromFile("EyesBlink.txt",0.6); break;
case 10:TweakMorphFromFile("EyesNormal.txt",0.4);break;
}
}

void MainLoop()
{

if (rr<0.01 && rr>=0.005)
AddSequence(BlinkEyes,0,11);
if (rr<0.005)
AddSequencer(BigEyes,0,101);

UpdateSequences();}
Telastyn
Telastyn
Nothing is guaranteed to run at 60fps. Use times; UTC times or tickcount at that.

boost::function (or std::function in C++11), or function objects in general are used in these cases. No need to make variadic anything when you just want to execute 'something'.

If you're using raw function pointers or void pointers in modern C++, you're likely doing something wrong.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.