Game Development Community

Another complex Question - about spawning and behaviors in TGB

by Josias Gibbs · in Torque Game Engine · 09/06/2008 (1:55 pm) · 13 replies

I have an object called Swarmship which is invisible, and another object called SwarmshipVisualRep which displays one of 72 subframes based on the rotation of Swarmship (ie: SwarmshipVisualRep is the "sprite" for Swarmship - i have a psudo-isometric view in my game, so I need to do it this way).

Swarmship has a behavior that mounts SwarmshipVisualRep to it, and and SwarmshipVisualRep has a behavior that looks at the rotation of Swarmship, and displays one of 72 subframes based on Swarmship's rotation - in essence, these two objects depend on eachother to function properly.

My question involves spawning these objects in my level (ie: starsystem). I've been using these lines of code to spawn instances of these:


if (!isObject(SpawnShipsBehavior))
%template.addBehaviorField(object01, "The 1st type of ship to spawn", object, "", t2dSceneObject);
%template.addBehaviorField(visual01, "The visual of that ship", object, "", t2dSceneObject);

function SpawnShipsBehavior::spawn(%this)
%clone = %this.object01.cloneWithBehaviors();
%cloneV = %this.visual01.cloneWithBehaviors();

//I find the proper %xPos and %yPos here

%clone.position = %xPos SPC %yPos;
%cloneV.position = %xPos SPC %yPos;
//note: this is not the entire behavior - just the code that seems relevent to this question

I thought this code was working fine, but now I'm not so sure. I've been trying to do some AI for these ships, but when I have the Swarmship object do things (ie: change it's rotation), these changes don't visually show up in the SwarmshipVisualRep object (it just sits there)- which makes me think that maybe the two objects aren't "linked up" like they were in the template objects (with each object containing a behavior that "referenced" the other object)

Should my code work? If not, then how do I spawn a pair of objects that are dependent on eachother?

#1
09/06/2008 (2:26 pm)
If you clone an object that has a behavior with a field equal to an object id, the cloned object will have the same object id in its field, which means it will be matching the rotation of the template object, not what you want.

Perhaps assign the object to track rotation of to %cloneV inside your spawn method.
#2
09/07/2008 (9:00 am)
I'll try that.
#3
09/07/2008 (10:12 am)
Hmm - tracking the rotation of %cloneV seems to be harder than I thought it would be. Here's what I'm doing in my spawn behavior(which doesn't seem to work):


//###########
//#
%clone = %this.object01.cloneWithBehaviors();
%cloneV = %this.visual01.cloneWithBehaviors();

//i figure out the xPos and yPos here

%clone.position = %xPos SPC %yPos;
%cloneV.position = %xPos SPC %yPos;
%cloneV.objectToDisplay = %clone; //note : I also tried %cloneV.owner.objectToDisplay = %clone.owner;
//#
//###########


Now keep in mind that %cloneV has a behavior that contains an objectToDisplay field:


//####
//#
%template.addBehaviorField(objectToDisplay, "The object whos rotation determines which subframe we display", object,"", t2dSceneObject);

//a bunch of code that doesn't have anything to do with this question

%this.owner.setImageMap(iMap01Spikewing, ((%this.objectToDisplay.rotation+360)%360)/5 );
//#
//####


Unfortunately, it doesn't work - the Swarmship object changes it's rotation, and the SwarmshipVisualRep just sits still with no change. What am I doing wrong (I'm hoping it's an absurdly simple syntax error)?

(also, I wanted to mention that my code all works perfectly for the pair of template objects, the problem only arises once I clone them)
#4
09/07/2008 (1:13 pm)
Try this,
%cloneV.getBehavior("yourbehaviorname").objectToDisplay = %clone;
#5
09/07/2008 (2:16 pm)
Uh oh - that might be a problem. Each of my ships has a different behavior being used to display it (ie: the Spikewing ship has the behavior DisplaySpikewing.cs, the Human Freighter has the behavior DisplayHumanFreighter.cs). Each of these behaviors has a variable called objectToDisplay - but the behaviors themselves have different names. I could just use a whole lot of if-statements I suppose... but I would really prefer to do it a better way.

Is there any way to arrange behaviors in a class-hierarchy sort of thing (ie: all of my display ship behaviors would be sub-classes of another behavior called displayShip, which would be the super-class)?

edit: or, if there isn't a way to do that, is there any other way to do what I'm trying to do? (Your line of code worked by the way, but only if I hard coded a single display behavior into it - I still need to get it working for all display behaviors)
#6
09/07/2008 (5:37 pm)
Then you might want to store the objectToDisplay on the object itself rather than the behavior, then have the behavior written such that it knows that and looks there for it.
#7
09/20/2008 (9:40 am)
Ok, so I created a dynamic field in the Swarmship object called "objectToMount", and a dynamic field in the SwarmshipVisualRep object called "objectToDisplay". Both of these fields default to 0. In my spawn behavior, I now have:


//###########
//#
%clone = %this.object01.cloneWithBehaviors();
%cloneV = %this.visual01.cloneWithBehaviors();

//i figure out the xPos and yPos here

%clone.position = %xPos SPC %yPos;
%cloneV.position = %xPos SPC %yPos;

%cloneV.objectToDisplay = %clone;
%clone.objectToMount = %cloneV;
//#
//###########


now keep in mind that %clone now has a mount behavior that contains this :


//#################
//##
function MountToThisNoRotationNoTargetBehavior::onAddToScene(%this, %scenegraph)
{

%this.schedule(100, "scheduledMount");

}

function MountToThisNoRotationNoTargetBehavior::scheduledMount(%this)
{
if (%this.objectToMount != 0)
%this.objectToMount.mount(%this.owner, %this.xMount, %this.yMount, %this.mountForce, false);
else
%this.schedule(33, "scheduledMount");
}
//##
//#################


and %cloneV has a similar behavior for displaying the object specified in objectToDisplay.
The problem is that %clone's objectToMount field never gets changed from it's default value of 0

(
ie: %clone has a behavior that contains:
if (%this.objectToMount == 0)
{}//do nothing
else
do the AI for %clone

and the if statement remains true forever - the AI never happens
)

My question is: how do I set %cloneV's objectToDisplay field to %clone, and how do I set %clone's objectToMount field to %cloneV?

As far as I can tell, my code should do it... but it doesn't. Any help would be appreciated.

edit: wow, this is long.
#8
09/20/2008 (11:19 am)
Ok this is pretty confusing to look at on a forum, but lets see.

Isn't this the same issue? Here's where you assign:
%cloneV.objectToDisplay = %clone;
%clone.objectToMount = %cloneV;

%clone/V is a t2dSceneObject NOT a behavior. But you said you are checking the field inside a behavior, meaning "%this" is the wrong object.

Heres where you check them:
if (%this.objectToMount == 0)
{}
// probably should be...
if ( %this.owner.objectToMount == 0 )
{}
#9
09/20/2008 (12:03 pm)
Hmm - ok, there's good news and bad news...

The good news is that you were right - changing it to %this.owner.objectToMount fixed the check.

The bad news is that the lines:

//####
//#
%cloneV.objectToDisplay = %clone;
%clone.objectToMount = %cloneV;
//#
//####

still don't do what I want them to do - the two objects spawn, but the SpikewingVisualRep object just sits there, while the Spikewing object acts on it's AI and starts flying around.
#10
09/20/2008 (12:07 pm)
Hmm - ok, there's good news and bad news...

The good news is that you were right - changing it to %this.owner.objectToMount fixed the check.

The bad news is that the lines:

//####
//#
%cloneV.objectToDisplay = %clone;
%clone.objectToMount = %cloneV;
//#
//####

still don't do what I want them to do - the two objects spawn, but the SpikewingVisualRep object just sits there, while the Spikewing object acts on it's AI and starts flying around.
#11
09/20/2008 (12:18 pm)
If the visual rep is setting there then I guess its not getting mounted?
#12
09/20/2008 (3:23 pm)
Hmm - ok, there's good news and bad news...

The good news is that you were right - changing it to %this.owner.objectToMount fixed the check.

The bad news is that the lines:

//####
//#
%cloneV.objectToDisplay = %clone;
%clone.objectToMount = %cloneV;
//#
//####

still don't do what I want them to do - the two objects spawn, but the SpikewingVisualRep object just sits there, while the Spikewing object acts on it's AI and starts flying around.
#13
09/21/2008 (9:46 am)
DING!!! Yes - I got it working. All I needed to do was change %this.objectToMount to %this.owner.objectToMount (in the other files), and %this.objectToDisplay to %this.owner.objectToDisplay. Thanks for all your help.