Only single "onCollision" allowed per Sprite?
by Dan McLaughlin · in Torque 2D Beginner · 08/16/2014 (11:29 am) · 3 replies
I've got a sprite scene object and have attached several behaviors to it, each of which has their own onCollision. This is based off the fishTutorial - one is on colliding with food, and the other is with colliding with an enemy. Only one is getting called, it appears that an object can only have one onCollision callback.
Looking at the C++ code, I see the code to execute this in
Scene.cc:void Scene::dispatchBeginContactCallbacks( void )
which calls through to "execute" which only appears to call a single function.
Doesn't chained functions make sense here? I can put the behavior as a case statement, but that violates the independence of behaviors, which is the point in the first place.
Looking at the C++ code, I see the code to execute this in
Scene.cc:void Scene::dispatchBeginContactCallbacks( void )
// Yes, so does it handle the collision callback?
if ( pSceneObjectB->isMethod("onCollision") )
{
// Yes, so perform the script callback on it.
Con::executef( pSceneObjectB, 3, "onCollision",
sceneObjectABuffer,
miscInfoBuffer );
}
else
{
// No, so call it on its behaviors.
const char* args[4] = { "onCollision", "", sceneObjectABuffer, miscInfoBuffer };
pSceneObjectB->callOnBehaviors( 4, args );
}which calls through to "execute" which only appears to call a single function.
Doesn't chained functions make sense here? I can put the behavior as a case statement, but that violates the independence of behaviors, which is the point in the first place.
About the author
#2
08/17/2014 (10:00 am)
If you need all onCollision() callbacks called across all behavior instances then use the behavior signalling system. You can raise a signal - see Behavior Connections like Mike said. No source changes required, but you will have to do some planning. In the Physics Launcher Template this is how we got multiple behavior instances to interact correctly for the projectile, launcher, and target objects to play sounds and animations at various state changes.
#3
08/17/2014 (10:29 am)
Great thanks guys, good ideas. I'll look into.
Associate Mike Lilligreen
Retired T2Der
// Walk backwards through the list just as with components const char* result = ""; bool handled = false; for( SimSet::iterator i = (mBehaviors.end()-1); i >= mBehaviors.begin(); i-- ) { BehaviorInstance *pBehavior = dynamic_cast<BehaviorInstance *>( *i ); AssertFatal( pBehavior, "BehaviorComponent::callOnBehaviors - Bad behavior instance in list." ); AssertFatal( pBehavior->getId() > 0, "Invalid id for behavior component" ); // Use the BehaviorInstance's namespace Namespace *pNamespace = pBehavior->getNamespace(); if(!pNamespace) continue; // Lookup the Callback Namespace entry and then splice callback const char *cbName = StringTable->insert(argv[0]); Namespace::Entry *pNSEntry = pNamespace->lookup(cbName); if( pNSEntry ) { // Set %this to our BehaviorInstance's Object ID argPtrs[1] = const_cast<char *>( pBehavior->getIdString() ); // Change the Current Console object, execute, restore Object SimObject *save = gEvalState.thisObject; gEvalState.thisObject = pBehavior; result = pNSEntry->execute(argc, const_cast<const char **>( ~argPtrs ), &gEvalState); gEvalState.thisObject = save; handled = true; break; } }I suppose if you wanted to avoid changing the source code here, you could use behavior connections to chain functions. The AudioToy provides an example of this. For the merry band of characters, when you click on them, the button down function raises a call to an animation behavior and a sound behavior simultaneously. You can do the same thing with a master onCollision function that raises a call to other behaviors on the same object.