2
\$\begingroup\$

I have been implementing behavior for enemies in my game and so far I have been doing it sort of like below:

public void update()
{
    if (frame > 60 && frame % 30 == 0)
    {
        shootAtPlayer();
    }
    frame++;
}

Which is meaning after frame 60 shoot the player every 30 frames. The frame-count is important as the game is fixed frame-rate and everything is relying on this at the moment. There are many small scripts for enemy behavior like above and I currently iterate through each one calling update(). I have realized it will quickly get unweildy dealing in absolute frames and I want to move towards a pattern where I can specify to do X for 60 frames then do Y e.t.c, something that is easily understandable and easy to write. I want to go for something like below:

wait(60)
while(true)
{
    shootAtPlayer();
    wait(30);
}

I was wondering if there is a design pattern that would easily support such a syntax. My initial thoughts were to create a thread for each script object and have the wait implemented similar to below:

wait(int frames)
{
    while(frames > 0)
    {
        frames--;
        suspend();
    }
}

with the method running the scripts calling resume in turn on each script. I could potentially have up to 300 scripts running at once which would mean 300 threads to handle. Am I taking the correct approach to solving this problem?

I am programming this in C# XNA.

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

It would be simpler to create to use events and fibers

Using a fiber means you can yield and return how many frames to wait until it should be called it again.

Then with a priority queue you can iterate over all events scheduled for the current frame.

IEnumerator<int> ai_script() 
    yield return 60;
    while(true)
    {
        shootAtPlayer();
        yield return 30;
    }
}

and then in the gameloop

while(running){

    frame++;
    updateFysics();

    IEnumerator<int> ie;
    while((ie = delayQueue.Pop(frame))!=null){
        if(ie.MoveNext()){//move next then does the call true means there is another wait, false means the task is done
            delayQueue.add(ie,ie.Current+frame);//Current holds the delay requested
        }
    }

}

This solution is heavy misuse of C# syntax, but you can use explicit Fibers instead.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .