Game Development Community

Can somebody please explain setCollisionPhysics?

by John Klimek · in Torque Game Builder · 02/21/2006 (10:32 am) · 15 replies

I'm a bit confused on the difference between setCollissionActive and setCollisionPhysics.

From what I've read and understand, setCollissionActive will simply allow objects to collide (either by an object touching it, or having it touch another object). Now from what I understand if a collission occurs then a callback happens and you can do whatever you want as a result of the collission.

Well, how does setCollisionPhysics fit into this picture? Does setCollisionPhysics simply ignore the callback function?

Thanks,
John

#1
02/21/2006 (2:25 pm)
SetCollisionActive() controls whether or not collisions can occur with the object. If they can't occur here then it makes no difference how they are processed. As you note, ::onCollision() allows you to have code triggered by a collision occuring.

setCollisionPhysics() controls whether or not the physics engine is engaged.

Say you have two objects, both with setCollisionActive(true, true) and setCollisionPhysics(false, false). If the two objects collide (as defined by their collision bounding boxes) then an ::onCollision() event is generated. If you haven't defined that function then nothing happens, the objects continue as if there had been no collision at all.

If collisions is how points are scored you might have an onCollision() function something like:
t2dSceneObject::onCollision(<parameters>) {
  %srcObj.score += 100;
  }
In that case something would happen, one object would have it's "score" attribute incremented, but the objects would continue as if there had been no collision at all.

On the other hand if you setCollisionPhysics(true, true) then the physics engine is engaged and they react according to the parameters set for the objects (damping, mass, etc.)

Tim Doty
#2
03/07/2006 (8:41 pm)
Related to this topic, maybe someone can tell me whether it is possible to do what I want without any special hacking or using the CUSTOM feature....

In our game we have several projectiles colliding with each other, player paddles, and playfield walls, bouncing off all of them via the RIGID response mode. They also invoke the collision callback to play sounds and do some other physical feats.

Now we're adding a new playfield feature: "pockets." The projectiles should not bounce off of pockets. Instead they should pass right through, but still detect the collision and invoke the callback. But there seems to be no intrinsic means by which to specify that objects which bounce in response to some collisions should do nothing in response to others.

The simplest way I can see to accomplish this is to mount an invisible object on the balls with their own collision group, set these to only collide with pockets, and set pockets to only collide with these.

Does anyone have another suggestion, or am I on the right track?
#3
03/07/2006 (10:45 pm)
For your pockets objects only, use:

setCollisionActive(true, true);
setPhysicsActive(false, false);
setCollisionCallback(true);

That should do what you want, or get you close. You may not even need the setCollisionCallback() if you don't need the pockets themselves to ever know they were collided with.
#4
03/08/2006 (2:54 am)
Yep, you'd think that would work. But it doesn't. The projectiles still bounce off the pockets.
#5
03/08/2006 (3:31 am)
Wouldn't it be
SetCollisionActive(false,true); ?

Otherwise it sends collisions to all other objects ie for the rocket.
#6
03/08/2006 (5:05 am)
Pocket...? Rocket...? What's going on here? ;-)

I followed the advice of these two threads, but they don't fully apply in my case:
www.garagegames.com/mg/forums/result.thread.php?qt=32717
www.garagegames.com/mg/forums/result.thread.php?qt=31822

The reason I believe these examples don't fully apply is that our game's projectiles need to collide with each other. That seems to mean that they must send and receive collisions, and they must send and receive physics. Mounting a separate "trigger" object on them specifically for pockets appears to be necessary in our case.

I'm wondering something else now. For a single collision event, how many callbacks can potentially be invoked? I understand that if I set both SEND and RECEIVE to TRUE on both objects, and then set CALLBACK=TRUE on only one of the objects, I'll get 2 callbacks for every collision, right? But if I set CALLBACK=TRUE on both objects, does that mean I'll get 4 callbacks?

EDIT: Added this comment.
#7
03/08/2006 (6:35 am)
In earlier versions there was a bug which caused multiple collision callbacks for a single collision, but I believe that there is only one in the current beta. That should be easy enough to test though.

Because T2D is single threaded only one object is being moved at any one time (well, I suppose you could flag them as moving/static to do otherwise, but I'm reasonably certain this is not the case). It is my understanding that the moving object generates the collision (send) if the impacted object is amenable (receive). There is a matter of overlap and doing a setPosition() can generate a collision, but again, there is always the 'active' object.

I understand the question about the callback, however. Easy enough to test for though.

Tim Doty
#8
03/08/2006 (6:49 am)
I thought it were 2 callbacks, one for each of the two objects, at least if they are set to receive collisions.
#9
03/08/2006 (6:51 am)
You're probably right. Here in a few minutes I'll hopefully get a test done which will determine the behavior.
#10
03/08/2006 (6:59 am)
In the code example below a collision between %pocket and %trigger generates only one callback, with %pocket as the %srcObj. If you change %trigger's callback to TRUE then you'll get a second callback with %pocket as the %dstObj.

%pocket.setCollisionCallback( true );
%pocket.setCollisionActive( true, false );

%trigger.setCollisionCallback( false );
%trigger.setCollisionActive( false, true );
#11
03/08/2006 (7:02 am)
I think that establishes the pattern for intended behavior. If the setCollisionPhysics() behaves otherwise I'd hazard that is a bug and report it there. It certainly contradicted Stephen Zepp's expection.
#12
03/08/2006 (7:36 am)
Let me see if I understand you correctly. Zepp expected his example code to allow "Object B" to pass right through "Object A" because it seems to make sense that disabling physics send/receive for Object A would trump the physics settings of Object B. But as it turns out, the settings of Object A don't matter. As long as Object B has its physics enabled, it will still be physically affected by a collision with Object A.

That certainly surprised me too. Whereas the collision send/receive requires mutual receptivity, physics send/receive doesn't. It does make sense if you consider the collision part to take precedence over the physics part, however. That is, in order for physics to be engaged at all, you first have to set the collision flags and masks. Once the flags and masks are set then physics will be engaged if even one object is set to send/receive physics.

So perhaps it's a question of pure semantics. Calling both parameter pairs "send/receive" may simply be misleading. Because as it turns out, physics can be "received" even from something which isn't "sending" them. In that case, the physics "received" is as if it came from a non-moving object, which mayhap be the intended behavior.
#13
03/08/2006 (11:19 am)
Update: I was incorrect, you cannot do what the original poster asked with stock:

quote from Melv:

Quote:
No, you couldn't set that situation up stock. The
failing would be due to the fact that you can only set
the collision-response "setCollisionPhysics()" related
to send/receive collisions but you cannot further
refine it to a collision response based upon only a
set of groups/layers.

In plainer english, if you tell A & B they can both
collide with A, B & C *and* that you want a physics
response for sent/received collisions, you have no way
to say "have a physics response only from A & B".

Essentially, group/layer filtering on collisions is at
the collision-detection level, not at the
collision-response level.
#14
03/09/2006 (6:53 am)
I had to do something very similar in my game and ran into the same problem. Here's how I worked around it. First, as soon as the ball colides with the pocket use setCollisionSuppress() on the pocket. The callback happens before the engin changes the velocity of the objects. Now do what ever it is that happens to the ball. Schedule a function to restore the collisions for the pocket. In that function, first set the collisions on again, then cast for collisions with the ball using castCollisionList(). If the ball is still coliding then supress the collsions again and reschedule the function. And that should do it! Oh, you also might want to set the pocket to Immovable. If you couldn't follow me just say so and I'll try to whip up some example code.

-Peter
#15
03/13/2006 (1:33 pm)
Hello! Thanks for your suggestion. I had considered something like that but decided on a different approach. I'm using - as I mentioned - an extra SceneObject attached to the ball object, and registering the collision continuously while it's in progress. In my case, I want the balls to be able to jump over the pocket if going fast enough. Also I only want the contact to be registered for the central region of the ball (since that simulates the area in contact with the ground surface).

While the collision is in progress my handler routine slows the ball's motion by a percentage. Simultaneously, it is accelerated towards the center of the pocket. This combination is pretty effective, and tweakable for different types of "pockets" or other "traps" and "triggers" by setting special properties on each item.

When the ball first contacts a pocket I set a schedule to count up how many times (e.g., how long) the ball is *still* in contact with the same pocket. If it remains in contact long enough, the combination of being close to the center and going slowly enough causes it to state-change into "plunk" mode. The ball's pocket-collision trigger is removed, "plop" is played, and the ball gets a schedule to gradually shrink, darken, and center it. All this is done without changing its ability to collide till the very end.

The reasoning behind my approach is that I want an arbitrary number of balls, and an arbitrary number of pockets, all placed wherever they may be at user discretion. So I need to keep collisions active at all times. Counting up the duration of the collision by setting a schedule - and resetting that count when the collision isn't happening - is the only means I know to test state transition from colliding to not colliding. Other threads have suggested a similar approach.

Thanks everyone for your feedback. Despite the semi-kludge of adding an extra trigger to the ball, I still find it more elegant than having to hack the C++ to make a more granular collision system. And frankly it's nice to have the flexibility of a different collision area w/r/t pockets.