Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: CShelton on Sun 21/02/2010 08:46:20

Title: [Solved] Creating Threads for Objects
Post by: CShelton on Sun 21/02/2010 08:46:20
This should be very simple, and I've probably overlooked it, but is there a way to create object specific threads?

For example:

I have a puddle of water Object that needs to run a drip animation every now and then. In other development environments, I would set up a thread for the puddle, a block of script that tells the puddle to run its drip animation every random() seconds.

The thread for that object runs endlessly, firing off now and then causing it to play the animation, but it's not held up by waits or blocking commands because it's running it's own isolated thread.

I can kind of accomplish this right now by putting loop counters in my room_RepExec, but I'd love to know if there's a more elaborate solution.

Thanks for suggestions!
Title: Re: Creating Threads for Objects
Post by: suicidal pencil on Sun 21/02/2010 21:34:01

int DripObject;

function GetFreeObject()
{
 Object* p_object;
 int counter = 0;
 while(counter <= 39)
 {
   p_object = object[counter];
   if((p_object != null) && (p_object.Graphic == 0)) return counter;
   else counter++;
 }
 return 0;
}

function PlayDripAnimation()
{
 if(DripObject != null) return 0;
 int DripObject = GetFreeObject();
 object[FreeObject].SetView(x); //x is whatever view has the drip animation
 object[FreeObject].Animate(x, y, eOnce, eNoBlock, eForwards);
 return 0;
}

function room_RepExec()
{
 if(Random(100) >= 99) PlayDripAnimation();
}


That will create and animate the drip, but not move or release the object when you want it to.

Of course, you can always just set one specific object for it, and do away with the 'GetFreeObject()' function
Title: Re: Creating Threads for Objects
Post by: Khris on Sun 21/02/2010 22:09:15
The only alternative is a Timer.
In the room's before fadein, set it, then renew it inside the rep_ex.
Title: Re: Creating Threads for Objects
Post by: CShelton on Wed 24/02/2010 20:16:42
Thanks for the replies Gents.

Suicidal, while I appreciate the effort that went into your post, you've given me a thorough solution for that particular example (occasional water drips). I intend to use threaded scripts for many different applictions.

Khris, I'm going with your suggestion and using timers. At this point I've set up 5 globals that are initialized to 0 upon entry of any new room. I've written a very simple advanceTimers() function and that will keep all the timers moving.

I'm slightly concerned with how this will work with the auto-state saving feature, but I'll just have to work around that.

Maybe I can make room specific vars that all functions can access? That would be a more complete solution.
Title: Re: Creating Threads for Objects
Post by: Khris on Wed 24/02/2010 21:51:20
You can make a global array and use player.Room as index.
Title: Re: Creating Threads for Objects
Post by: monkey0506 on Wed 24/02/2010 22:03:27
More specifically you could do something such as this, with a struct:

// GlobalScript.ash

struct __RoomVars {
 bool object_isDoor[AGS_MAX_OBJECTS];
 bool hotspot_isExit[AGS_MAX_HOTSPOTS];
 // or whatever else you need
};

import __RoomVars RoomVars[3000];

// GlobalScript.asc

__RoomVars RoomVars[3000];
export RoomVars;

// wherever

if (RoomVars[player.Room].object_isDoor[20]) {
 // object 20 in the current room is a door
}


BTW, regarding accessing room scripts from other scripts, there is the CallRoomScript (http://www.americangirlscouts.org/agswiki/Game_/_Global_functions#CallRoomScript) function. Only works on the current room (since that's the only room script that is loaded) but you can then do something such as:

// GlobalScript.asc

function CallRoomRepExec() {
  CallRoomScript(999);
}

// roomX.asc

function room_RepExec() {
  // ...
}

function on_call(int value) {
  if (value == 999) room_RepExec();
}


You would have to put that on_call function into every room script for that to work of course, but it's just an example of how you can reach the room script from the global script.
Title: Re: Creating Threads for Objects
Post by: RickJ on Wed 24/02/2010 23:54:51
As you probably surmised already from the replies so far, AGS itself does no provide this.  Long ago (before the time of modules) I created a thing called AnimationEngine that allowed this kind of thing to be done.  It's long fallen into obsolence and so last year I created a Thread Module that was much better and took advantage of the newer AGS features.   Unfortunately I had a hard disk failure as I was on the verge of releasing it and so it's now all gone; except for some incoomprehensible notes and silly notions floating around in my head.   

For me this is something that is absolutely essential so I intend re-creating it when I find  some time.   I'll be sure to let you know...
Title: Re: Creating Threads for Objects
Post by: CShelton on Thu 25/02/2010 04:18:38
I'm going to marked this as solved for now. Thanks everyone!

Monkey, using a struct has worked out nicely for doing pseudo threads, thanks for the code snippets. I'm able to manage quite a bit with the following members, such as one-off or infinite room threads.

struct __RoomVars
{
 int roomTimer[MAX_ROOM_TIMERS];
 bool roomTimerOnce[MAX_ROOM_TIMERS];
 bool roomTimerFired[MAX_ROOM_TIMERS];
 int roomTimerTargetNumber[MAX_ROOM_TIMERS];
 int roomTimerCount;
};




Rick, a fancy module that handles this sort of thing would be great. I'll probably be deep into my own hacks at that point, but I'm sure others would benefit greatly.