Archived

This topic is now archived and is closed to further replies.

NightwingX

Master Game Loop

Recommended Posts

NightwingX    122
How can you make multi-tasking Loops that will not stop the Master Loop Structure? Say, you want a charactor to collect a certain resource, and you want the charactor to do it automatically and continue until the resources have not been depleted - AND still keep the master loop free to execute the collection loop, and to continue any other loops that are going on. Like in AOE II (Age of Empires II) you can make a villager collect stone, and keep collecting until the stone in depleted. But, you can also have multiple charactors do different things at the same time. How is this done? How do loops get generated and then erased? How can you keep the game going? Aren''t there a FIXED amount of "Work" loops avaliable, or can they be made? If anyone has ever created such a game, please give me a few hints. It would be ALOT of help to me. Thank you for reading this.
quote:
Age of Empires II The Age of Kings

Share this post


Link to post
Share on other sites
farmersckn    122
Using loops for each character is not the right way to do what you want to do. "Gathering" for instance, is a function of the character''s A.I. So, in your update function, you will test to see if the character is "Gathering", and then "Gather".

void Character::Update()
{
if(myAIState="Gather") {
Gather();
}
}

void Character::GiveResources(int Amount)
{
myResourceCount += Amount;
}

void Character::Gather()
{
myResourceTarget.TakeResources(10);
GiveResources(10);
if(myResourceCount>100) {
myAIState="ReturnWithResources";
}
}

Then you loop through each character and have them gather.

for(i=0; i myCharacters.Update()
}

Also put motion code into the update function, as well as attack and other stuff.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Just a guess here considering I haven''t made any of my own games yet, slightly less technical look at it than farmersckn''s fine example

I wouldn''t call it a loop so much as checking a state in the game loop each time it iterates.

For example, when your main loop gets to the part that does all the character AI, have it do something along the lines of "if there are still resources, continue digging, if not, stop digging" and then let your main loop continue. So this state gets checked each time your main loop loops. Eventually resources will be gone (if you decrement resources as the character digs, or whatever) and the character will eventually stop digging.

I hope that makes sense

Klowner

Share this post


Link to post
Share on other sites
NightwingX    122
Thanks for the information. Can you possibly show me how a Main Loop structure looks like, with a few example functions? I have made more simpler games, but using a Master Game Loop would be a first for me.

-Thanks

Share this post


Link to post
Share on other sites
Pik    100
Look for one of Andre Lamothe''s writings that tells about neural networks and infinite state machines. The simplistic way to do something like that though, would be to have a state variable (0=idle, 1=heading to dest, 2= collecting wood, etc.) and then go through a linked list of and move everything another step, changing states when necessary. For example, you could have a linked list of villagers, and when going through it, you take appropriate actions for the states.
0 (idle): check resources, assign to gather lowest
1 (head to dest): move a step closer
2 (collect wood): keep collecting or start to town

These state variables would help with other things too. Say a monster attacks the peasant, then you would set his state to 3 (run like hell). Be sure to check out Lamothe''s article though. It can be found in the Articles section or on his site, www.xgames3d.com

Share this post


Link to post
Share on other sites
NightwingX    122
THANKS PIK!!!!! THAT IS A REALLY GOOD IDEA!! In fact, that is what I will go with. One question: There would be ALOT of numbers...right? Like:

0 - Do this
1 - Do that
3 - Do another thing

Then implimenting like:


Const GoGatherWood = 7;
// And other constants

While(Game = InProgress)
{ // The game loop

getInput();
Villager(CordX = 12, CordY = 23, Command = "GoGatherWood");
// ... Other code ...


} // End of game loop

Does that look any good?

Share this post


Link to post
Share on other sites
TerranFury    142
I agree with most of the previous posters. The key to making your units perform looping behavior is not to create a program-code loop, but a sequence of actions that end up causing themselves to repeat.

Keep a list of "things to do" for each unit. Now, you have a main game loop that calls a render function and gets user input, etc. Add to that loop a call to a function that loops through all the characters and performs whatever task is top on their list.

Now how can such a technique result in "looping" behavior? It''s quite simple. Let''s say you have three actions: "mine," "walk to mine," and "walk to storage pit." Now let''s say you elect the unit and tell it to mine. Other actions are removed from its list and WALK_TO_MINE is added to the list. Then, each iteration of your main game loop, when the loop that iterates through each unit reaches this particular miner, he takes one more step along his path to the mine. Now, when he finally gets there, the WalkToMine() function can detect this (because he''s next to the mine) and will remove the WALK_TO_MINE action form the list and adds a MINE action. Now, each iteration of the game loop, the MINE action is performed. The Mine() function contains a check to see if the miner can carry any more gold. If he cannot, then it removes itself from the list, and adds the WALK_TO_STORAGE_PIT action to the list. This is performed each iteration of the game loop until the storage piut is reached, in much the same way that the miner walked to the mine until he was next to it. When he gets to the storage pit, the WalkToStoragePit function removes the WALK_TO_STORAGE_PIT action from the list, and adds the WALK_TO_MINE action.

Here''s a little pseudocode:

  

//your main game loop

while(exit == false)
{
GetInput();
DoAI(listofunits);
Render();
}



And here''s how your DoAI() function could work:

  

void DoAI(Unit * unitsList)
{
for(Unit * u = unitsList; u != NULL; u = u->next) //Traverse linked list of units

{
for(Action * a = u->actionList; a != NULL; a = a->next) //Traverse linked list of unit''s actions

{
a->doAction();
}
}
}



This, as you can see, is a rather OO approach. What I do is I have a linked list of Unit object, each of which contains a linked list of Action objects. Action is a base class from which all actions, like WalkToMine(), are derived. That could be a framework for your units'' AI. Using such a system, each unit is a state machine. The key to making their behavior work correctly is simply to properly maintain the list of actions for each unit. A better name for this could be the Action Queue. This way, you could have a list of actions which are executed either in order of the time they were issued or in order of importance. Such a technique could easily allow for things like waypoints.

Hopefully you now have an idea of how to go about doing this.

Share this post


Link to post
Share on other sites
TerranFury    142
In your typical RTS, each side can have up to 200 units, right? So, let''s say there are four players; then there could be 800 units in the list. Each of those units probably wouldn''t have more than a few actions in the list. Villagers would each probably have only one. The units of a stationary army on guard would not have any. The units that would probably have the most would be scouts that you send off to lots of waypoints, because they would have a lot of WalkToCoordinate(x, y) (or something like that) actions in their lists. Your lists could, in theory, reach any size. You probably wouldn''t need to, but you might want to use an array instead of a linked list and put a cap on the number of actions. I''d go with the linked list though.

If you want more info on linked lists (I don''t know how much experience you have; I apologise if I''m telling you things you already know), they have a short tutorial over at http://www.cprogramming.com in their "Tutorials" section that might be helpful.

An alternative to all these linked lists and arrays would be to use an stl data structure like the STL vector or list. I don''t really use them though, so I can''t offer too much advice when it comes to using them.

Share this post


Link to post
Share on other sites
CryptoHobes    122
Minor suggestions... from the above code, the ai''s update cycle is linked to the render speed - a bit of a no-no.

You can execute all the ai objects in lockstep:

void UpdateAi()
{
AiNode* node;

for (node = GetAiNodeList(); node != null; node = node->next)
node->thinks(node);
}

void MainLoop(void)
{
while (!done)
{
clock_t ticks = clock();

GetInput();
if (ticks >= nextai)
{
UpdateAi();
nextai += CLOCKS_PER_SEC / aifps;
}
Render(ticks);
}
}

or execute all of the objects in their own times and at their own rates

void UpdateAi(clock_t ticks)
{
AiNode* node;

for (node = ainodelist; node != null; node = node->next)
{
if (node->ticks <= ticks)
node->thinks(node);
}
}

void MainLoop(void)
{
while (!done)
{
clock_t ticks = clock();

GetInput();
UpdateAi(ticks);
Render(ticks);
}
}

where ''thinks'' is a pointer to the function to update the node

Both methods have their pros and cons.

For preference, I have all objects operating in lockstep and use a tree structure to hold the objects - not a list. The tree structure allows parent objects to exert a modicum of control over the children and also can be used to enforce the sequence of object updates (within the parent/child relationship).

Share this post


Link to post
Share on other sites