[Solved] Creating Threads for Objects

Started by CShelton, Sun 21/02/2010 08:46:20

Previous topic - Next topic

CShelton

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!

suicidal pencil

#1
Code: ags

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

Khris

The only alternative is a Timer.
In the room's before fadein, set it, then renew it inside the rep_ex.

CShelton

#3
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.

Khris

You can make a global array and use player.Room as index.

monkey0506

#5
More specifically you could do something such as this, with a struct:

Code: ags
// 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 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:

Code: ags
// 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.

RickJ

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...

CShelton

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.

Code: ags
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.

SMF spam blocked by CleanTalk