What determines if an object is the src or dst for collisions?
by Philip Mansfield · in Torque Game Builder · 03/05/2005 (8:04 am) · 16 replies
If I have two objects that collide, how is it determined which is the source and which is the destination?
Without knowing how this works, I can see my code being a bit more complicated (having to account for the sender being A or B).
If an object is only set to send (like a bullet) or receive (like a target) then it's a bit easier to account for collisions.
Without knowing how this works, I can see my code being a bit more complicated (having to account for the sender being A or B).
If an object is only set to send (like a bullet) or receive (like a target) then it's a bit easier to account for collisions.
#2
Thanks. I guess what I was getting at, was (in the case of two moving objects that both send and receive) does the bullet hit the target, or does the target hit the bullet?
I guess the best way is to test for both conditions in this case.
03/05/2005 (8:25 am)
Melv,Thanks. I guess what I was getting at, was (in the case of two moving objects that both send and receive) does the bullet hit the target, or does the target hit the bullet?
I guess the best way is to test for both conditions in this case.
#3
03/05/2005 (8:32 am)
I changed the parameter names in onCollide() to %receiver and %sender because it was confusing me with the %src and %dst naming. Made things much easier to think about for me. :)
#4
You've got a stationary object and you fire a bullet at it and both objects have send and receive collisions active.
If the bullet hits the stationary object, the bullet will be the source (sender) and the stationary one the destination (receiver). This is true and if the bullet does not overlap the object (for whatever reason), then this would be the end of it. Imagine though that the stationary object is not stationary at all but is moving towards the bullet. Now you get what I described previously as the bullet slams into the now not-stationary object but when it comes to check collisions for the other object, it could well collide with the bullet and therefore you get a callback where the source (sender) is the object and the destination (receiver) is the bullet.
If you only want the collision checks to go one way, then simply configure them to do so e.g. you may want the bullets to be senders only so that they don't ever appear as a receiver.
I can understand this stuff can be confusing and that we've yet to document it.
- Melv.
03/05/2005 (8:56 am)
@Philip: There isn't an answer to that, it all depends on the situation. Think of it this way...You've got a stationary object and you fire a bullet at it and both objects have send and receive collisions active.
If the bullet hits the stationary object, the bullet will be the source (sender) and the stationary one the destination (receiver). This is true and if the bullet does not overlap the object (for whatever reason), then this would be the end of it. Imagine though that the stationary object is not stationary at all but is moving towards the bullet. Now you get what I described previously as the bullet slams into the now not-stationary object but when it comes to check collisions for the other object, it could well collide with the bullet and therefore you get a callback where the source (sender) is the object and the destination (receiver) is the bullet.
If you only want the collision checks to go one way, then simply configure them to do so e.g. you may want the bullets to be senders only so that they don't ever appear as a receiver.
I can understand this stuff can be confusing and that we've yet to document it.
- Melv.
#5
I've set the planes to be senders and receivers, and bullets to be senders only. This seems to work fine and the planes can continue to shoot each other down with the code:
However, I'm thinking the simplest way to code for collisions is:
That does away with all the extra checking of if the plane hits the ground or the ground hits the plane, and the same for the bullets.
But try as I might to get this to work, it just refuses to check for the correct collisions. I've tried variations on which objects are senders and/or recivers, and if I echo out the source and destination objects I get:
So that leaves me in the original position of having to check various different objects against each other instead of being to check one object against several.
A bit of advice on this would be welcome as it's driving my poor little brain into melt down :(
03/07/2005 (5:08 am)
I've been experimenting with this a bit in order to streamline some of the collision code in my biplane game.I've set the planes to be senders and receivers, and bullets to be senders only. This seems to work fine and the planes can continue to shoot each other down with the code:
function fxSceneObject2D::onCollision( %srcObj, %dstObj, blah blah )
{
if (%srcObj.tag $= "redBullet")
{
if (%dstObj.tag $= "bluePlane")
{ blah blah }
}
}However, I'm thinking the simplest way to code for collisions is:
function fxSceneObject2D::onCollision( %srcObj, %dstObj, blah blah )
{
if (%srcObj.tag $= "bluePlane")
{
if (%dstObj.tag $= "redBullet")
{ blah blah }
if (%dstObj.tag $= "ground")
{ blah blah }
}
}That does away with all the extra checking of if the plane hits the ground or the ground hits the plane, and the same for the bullets.
But try as I might to get this to work, it just refuses to check for the correct collisions. I've tried variations on which objects are senders and/or recivers, and if I echo out the source and destination objects I get:
Quote:and that loops in my log a few times, so I know the collisions are happening, just not how I'm thinking they should happen.
src: bluePlane has hit dst: redBullet
src: redBullet has hit dst: bluePlane
src: redBullet has hit dst: bluePlane
src: bluePlane has hit dst: redBullet
src: bluePlane has hit dst: redBullet
src: redBullet has hit dst: bluePlane
src: redBullet has hit dst: bluePlane
src: bluePlane has hit dst: redBullet
src: bluePlane has hit dst: redBullet
So that leaves me in the original position of having to check various different objects against each other instead of being to check one object against several.
A bit of advice on this would be welcome as it's driving my poor little brain into melt down :(
#6
I haven't seen anything in the TorqueScript documentation about allowed array index key types, so I'll assume the key values have to resolve to integers.
If (and that's a BIG if) TorqueScript uses a sparse array implementation, creating a 2D array using the objects IDs as keys, and the appropriate action as the array value would do the trick. Just make sure to store two values in the array, one for each ordering of the objects.
$collision[%obj1,%obj2] = "action1";
$collision[%obj2,%obj1] = "action1";
$collision[%obj3,%obj1] = "action2";
$collision[%obj1,%obj3] = "action2";
I hope this works, If not, I'm going to need another plan sometime this week :-)
03/07/2005 (7:31 am)
Well, I'm still FAR too noobesque in Torque to know the best answer, but here's an idea that may help.I haven't seen anything in the TorqueScript documentation about allowed array index key types, so I'll assume the key values have to resolve to integers.
If (and that's a BIG if) TorqueScript uses a sparse array implementation, creating a 2D array using the objects IDs as keys, and the appropriate action as the array value would do the trick. Just make sure to store two values in the array, one for each ordering of the objects.
$collision[%obj1,%obj2] = "action1";
$collision[%obj2,%obj1] = "action1";
$collision[%obj3,%obj1] = "action2";
$collision[%obj1,%obj3] = "action2";
I hope this works, If not, I'm going to need another plan sometime this week :-)
#7
Unless ofcourse I'm missing something...
03/07/2005 (7:41 am)
But it's such a pain having to code to allow every object to collide with every other object. I can see the potential flexibility that having a send/receive collision system offers, but if you just want some basic stuff, you end up having to jump through all sorts of hoops to get it done.Unless ofcourse I'm missing something...
#8
if you do something like that then whenever you want to set collision
setCollision($player, 31, 31 );
or something similar
then you could also link this to another function that streamlines the process of checking collision... similar to what was mentioned with an array.
Right now I basically have a database coded in Torquescript (check my plan) and I can see some ways to set up your own system of checking collisions a bit more streamlined... maybe I'll try a mock up
03/07/2005 (7:49 am)
Creating functions can often help speed up tedious aspects of coding :)function setCollision(%obj, %layer, %group)
{
%obj.setCollisionActive( true, true );
%obj.setCollisionCallback( true );
%obj.setCollisionMasks( %group, %layer );
}if you do something like that then whenever you want to set collision
setCollision($player, 31, 31 );
or something similar
then you could also link this to another function that streamlines the process of checking collision... similar to what was mentioned with an array.
Right now I basically have a database coded in Torquescript (check my plan) and I can see some ways to set up your own system of checking collisions a bit more streamlined... maybe I'll try a mock up
#9
"Collisions"
fields
damage
objectsToDamage
objectsToIgnore
actions
Instance: Bullet
damage = 10;
objectsToCollide = bluePlane;
objectsToIgnore = bullets;
actions = "damage";
Instance: BluePlane
damage = 0;
objectsToCollide = enemyPlanes;
objectsToIgnore = bullets;
actions = "destroy";
Instance: Ground
damage = 1000;
objectsToCollide = planes;
objectsToIgnore = bullets;
actions = "destroy";
Table
"gameObjects"
fields
objects
Instance: bluePlane
objects = "bluePlane";
Instance: planes
objects = "blueplane enemyPlane";
Instance: enemyPlanes
objects = "blackPlane redPlane";
maybe something like that
then in the collision checking run a loop like (some helper functions would be created to easily interface with database (very very simple to do)
This is just a quick conceptualization though
03/07/2005 (8:22 am)
Table"Collisions"
fields
damage
objectsToDamage
objectsToIgnore
actions
Instance: Bullet
damage = 10;
objectsToCollide = bluePlane;
objectsToIgnore = bullets;
actions = "damage";
Instance: BluePlane
damage = 0;
objectsToCollide = enemyPlanes;
objectsToIgnore = bullets;
actions = "destroy";
Instance: Ground
damage = 1000;
objectsToCollide = planes;
objectsToIgnore = bullets;
actions = "destroy";
Table
"gameObjects"
fields
objects
Instance: bluePlane
objects = "bluePlane";
Instance: planes
objects = "blueplane enemyPlane";
Instance: enemyPlanes
objects = "blackPlane redPlane";
maybe something like that
then in the collision checking run a loop like (some helper functions would be created to easily interface with database (very very simple to do)
for(%i=0;%i<getCollisionCount("Collisions");%i++)
{
if(getCollisionObjectName(%i, %srcObj) $= "true")
{
if(checkIfCollide(%i, %dstObj) $= "true")
{
performCollisionAcitons(%i, %dstObj);
}
}
}This is just a quick conceptualization though
#10
The reason you can control whether collisions are sent/received on each object is so that you can control the direction of valid collisions. Without this idea, you have to test every object in both directions which will at least double your collision detection time.
Imagine a wall which you fire bullets at. The bullets move, the wall does not. Let's think about the bullets for a moment. There's nothing else in the scene that will collide with the bullets (receive collisions) but the bullets can collide with the wall (send collisions) so we're only interested in giving the bullets a send ability. Now let's think about the wall. There's no point in giving it send collisions but we want it to receive collisions which is the opposite of the bullet so we can configure it to receive and not send collisions. If an object doesn't send collisions, it will not be tested to see if it has collided with objects but, objects that do have send collisions active may collide with it but only if it has receive collisions.
The callback may seem confusing but try to think of it in a different way if you will.
If your only interested in objects that move, only look at the %srcObj (I'll rename this to %sendObj in the next update). The %dstObj (%receiveObj) is for reference only. It just says what object we collided with. The scroller demo only uses the %srcObj to test what objects collided with something else. It ignores the objects that it collides with because they receive collisions and will get called immediately afterwards saying that they collided as well.
If your problem is that you need to decide what to do with both objects, then quite simply, don't put your collision code in the callback but put it in another function like this...
Just remember that, dependant upon what you're doing, you may get several continuous collisions. For instance, you may want to stop the collision checks whilst you play an explosion. In that case, just issue a "%obj.setCollisionSuppress(true)" command and you won't get any more collisions on that object until you turn suppression off.
- Melv.
03/07/2005 (9:45 am)
We want to do much more tutorial detail on this so let me explain how it happens. For a minute, ignore the "onCollision" callback.The reason you can control whether collisions are sent/received on each object is so that you can control the direction of valid collisions. Without this idea, you have to test every object in both directions which will at least double your collision detection time.
Imagine a wall which you fire bullets at. The bullets move, the wall does not. Let's think about the bullets for a moment. There's nothing else in the scene that will collide with the bullets (receive collisions) but the bullets can collide with the wall (send collisions) so we're only interested in giving the bullets a send ability. Now let's think about the wall. There's no point in giving it send collisions but we want it to receive collisions which is the opposite of the bullet so we can configure it to receive and not send collisions. If an object doesn't send collisions, it will not be tested to see if it has collided with objects but, objects that do have send collisions active may collide with it but only if it has receive collisions.
The callback may seem confusing but try to think of it in a different way if you will.
If your only interested in objects that move, only look at the %srcObj (I'll rename this to %sendObj in the next update). The %dstObj (%receiveObj) is for reference only. It just says what object we collided with. The scroller demo only uses the %srcObj to test what objects collided with something else. It ignores the objects that it collides with because they receive collisions and will get called immediately afterwards saying that they collided as well.
If your problem is that you need to decide what to do with both objects, then quite simply, don't put your collision code in the callback but put it in another function like this...
function handleCollision( %obj )
{
// Handle Object Collision...
...
}... and then simply call this from the collision callback like this...function onCollision( ... )
{
handleCollision(%srcObj);
handleCollision(%dstObj);
}Just remember that, dependant upon what you're doing, you may get several continuous collisions. For instance, you may want to stop the collision checks whilst you play an explosion. In that case, just issue a "%obj.setCollisionSuppress(true)" command and you won't get any more collisions on that object until you turn suppression off.
- Melv.
#11
is a beautiful beautiful thing ! Cuts down a lot of scripting workaround to get the same effect lol...
thx for that post Melv, helped me examine collision too
03/07/2005 (9:49 am)
%obj.setCollisionSuppress()is a beautiful beautiful thing ! Cuts down a lot of scripting workaround to get the same effect lol...
thx for that post Melv, helped me examine collision too
#12
As I say, sorry for having to muddle through this. We'll look back on this period and laugh I guess.
"Do you remember when we only had a single tutorial!".
- Melv.
03/07/2005 (9:53 am)
There's also a physics suppress too which is equally handy.As I say, sorry for having to muddle through this. We'll look back on this period and laugh I guess.
"Do you remember when we only had a single tutorial!".
- Melv.
#13
I shall try out a few of those things and see how I get on. I think I'm being a bit nobbled by my own lack of programming experience, but I'm getting there.
03/07/2005 (9:59 am)
Thanks everyone :)I shall try out a few of those things and see how I get on. I think I'm being a bit nobbled by my own lack of programming experience, but I'm getting there.
#14
I need to build some tutorials on some basic things (as my team's project progresses I will release tutorials on the steps we went through)
but in all respect that "single tutorial" is great, some real good coding practice as well, making all my teammates go through it lol, whether they like it or not ;) programmer or not... that way they can understand some good game coding structure and the backend of this! I would recommend that tutorial as a great starting point for any game programmer in any language. Some of the hardest things to grasp is how to structure things in programming (lol in coding my torquescript DB I was forced to deal with some my own structural ineptness
03/07/2005 (10:02 am)
Lol @ Melv... you got a point... when we have multitudes of tutorials !I need to build some tutorials on some basic things (as my team's project progresses I will release tutorials on the steps we went through)
but in all respect that "single tutorial" is great, some real good coding practice as well, making all my teammates go through it lol, whether they like it or not ;) programmer or not... that way they can understand some good game coding structure and the backend of this! I would recommend that tutorial as a great starting point for any game programmer in any language. Some of the hardest things to grasp is how to structure things in programming (lol in coding my torquescript DB I was forced to deal with some my own structural ineptness
#15
A lot of in-game collisions are "one-shot", or "final", and need to be removed from the collision system after the initial impact, before another collision event occurs. Otherwise, everything has to code debounce logic to prevent multiple notifications from causing issues.
I haven't tried any of this yet with T2D, though. This is just pain remembered from past game coding. More things to play with this week :-)
03/07/2005 (2:07 pm)
The directed collision stuff definitely reduces the complexity. In the situation where a lot of objects on the screen are both senders and receivers of collision data, though, things can get a little tricky, although I'm not sure if T2D suffers from the usual collision problems.A lot of in-game collisions are "one-shot", or "final", and need to be removed from the collision system after the initial impact, before another collision event occurs. Otherwise, everything has to code debounce logic to prevent multiple notifications from causing issues.
I haven't tried any of this yet with T2D, though. This is just pain remembered from past game coding. More things to play with this week :-)
#16
- Melv.
03/07/2005 (2:34 pm)
@Terry: Agreed. That's why issuing a "setCollisionSuppress" is so useful. Stops reports on an object dead in their tracks. :)- Melv.
Associate Melv May
- Melv.