Item Collision
by John Quarles · in Torque Game Engine · 06/04/2005 (10:56 am) · 17 replies
I need to make Items detect when one Item collides with another Item. How can I do that?
#2
06/05/2005 (1:05 pm)
This function is only called when an Item like 'MagicBall' collides with the Player or Terrain. It doesn't get called when an Item collides with another Item. I even gave my Items collision meshes and it still won't call onCollision when colliding with other Items. Any suggestions?
#3
06/05/2005 (1:08 pm)
Actually it only gets called when it collides with the player. Any suggestions?
#4
Items does not collide with others items because collision mask is not set for it.
You need to add "ItemObjectType" to the collision mask in : engine/game/item.cc
Here is my collisionMask : (set at the beginning of the file.)
06/05/2005 (1:16 pm)
Got the same problem a few weeks earlier. Items does not collide with others items because collision mask is not set for it.
You need to add "ItemObjectType" to the collision mask in : engine/game/item.cc
Here is my collisionMask : (set at the beginning of the file.)
const U32 sClientCollisionMask = (TerrainObjectType | InteriorObjectType |
StaticShapeObjectType | VehicleObjectType |
PlayerObjectType | StaticTSObjectType |
ItemObjectType);
#5
06/05/2005 (1:38 pm)
Okay I tried adding ItemObjectType to the collision mask. It didn't work for me. I also noticed that in order for the item to detect any collisions from the player, the player has to move into the item. Then after that initial contact, the item will detect collisions when it moves into an idle player. I'm just moving things around in the editor and calling echo("hit"); in the Item onCollision function. Why does this happen? How do i fix it?
#6
Adding ItemObjectType just worked for me. My problem was when I drop item on the ground they sometimes where dropped into each others. By adding ItemObjectType they now collide. But I don't catch the collide message in the script so I bet you have to solve the script side. Did you try Robert solution together with my fix ? It seems to me that should solve it. Just be carefull that the onCollision method is called on the item Datablock.
06/05/2005 (3:45 pm)
@lynetteAdding ItemObjectType just worked for me. My problem was when I drop item on the ground they sometimes where dropped into each others. By adding ItemObjectType they now collide. But I don't catch the collide message in the script so I bet you have to solve the script side. Did you try Robert solution together with my fix ? It seems to me that should solve it. Just be carefull that the onCollision method is called on the item Datablock.
#7
I went ahead and made Items collidable, nonrotating and nonstatic by default like this in Item.cs:
Then I have another script i made called Collide.cs. These are the objects I'm trying to collide. In my current mission, i have two of these Collide objects. In the editor I move them around and try to collide them:
So in the editor I move the objects around and collide them with things to see how they collide. It works if i collide them with the Player. In the console it prints "HIT!" when they collide with the Player. It doesn't work with terrain and it doesn't work with other items. Other than that the scripts are unchanged. Any ideas?
06/05/2005 (4:25 pm)
Here are the changes i have made in my script. I went ahead and made Items collidable, nonrotating and nonstatic by default like this in Item.cs:
function ItemData::create(%data)
{
%obj = new Item() {
dataBlock = %data;
static = false;
rotate = false;
collideable = true;
};
return %obj;
}Then I have another script i made called Collide.cs. These are the objects I'm trying to collide. In my current mission, i have two of these Collide objects. In the editor I move them around and try to collide them:
datablock ItemData(Collider)
{
category = "Collision";
shapeFile = "~/data/shapes/nasa/fueltanks.dts";
mass = 1;
friction = 1;
elasticity = 0.3;
gravityMod = 0;
pickupName = "a collider";
};
function Collider::onCollision(%this,%obj,%col)
{
echo("HIT!");
}So in the editor I move the objects around and collide them with things to see how they collide. It works if i collide them with the Player. In the console it prints "HIT!" when they collide with the Player. It doesn't work with terrain and it doesn't work with other items. Other than that the scripts are unchanged. Any ideas?
#8
Second: There are two steps to getting item collisions to work correctly. As said above, you must add ItemObjectType to sClientCollisionMask. Secondly, you must add disableCollision(); to the beginning of Item::updatePosition.
As a final note, without some minor source code tweaks, the item will only use its bounding box for collisions instead of a collision mesh.
06/05/2005 (6:55 pm)
First: The item does not call its onCollision method. The onCollision method will only be called by another active collider that hits the item. This is why onCollision is called when the item hits the player, but not the terrain (The player calls the item's onCollision method, the terrain does not).Second: There are two steps to getting item collisions to work correctly. As said above, you must add ItemObjectType to sClientCollisionMask. Secondly, you must add disableCollision(); to the beginning of Item::updatePosition.
As a final note, without some minor source code tweaks, the item will only use its bounding box for collisions instead of a collision mesh.
#9
Hehe, :).
Robert
06/05/2005 (7:08 pm)
I apologize, I forgot to mention I used a heavily modified engine (including modified collision handling and such).Hehe, :).
Robert
#11
Im guessing you meant Item::updatePos. Okay i tried that (all except fot the collision mesh thing) but Items still dont detect collisions with other items.
06/05/2005 (7:39 pm)
@alexIm guessing you meant Item::updatePos. Okay i tried that (all except fot the collision mesh thing) but Items still dont detect collisions with other items.
#12
06/05/2005 (8:08 pm)
I don't know why it isn't working. Unless you somehow broke the inner workings of Torque ( or the item class) , there is absolutely no reason adding ItemObjectType to the collision mask shouldn't cause collisions between items.
#13
This works but I still need to know how to change this to use collision meshes instead of bounding boxes.
06/05/2005 (8:23 pm)
Hey I got it to work by noticing something in the player class. If you look in the Player::findContact method, you will see how the player decides to query collisions for Items. Its inside a very similar loop to one of the loops found in the Item::updatePos function. Here is my new code:while (pList != &rList) {
if ((pList->mConvex->getObject()->getType() & mask) != 0)
{
Box3F convexBox = pList->mConvex->getBoundingBox();
if (testBox.isOverlapped(convexBox))
{
if (pList->mConvex->getObject()->getType() & ItemObjectType) {
// If we've overlapped the worldbounding boxes, then that's it...
Item* item = static_cast<Item*>(pList->mConvex->getObject());
if (this != item->getCollisionObject())
queueCollision(item,getVelocity() - item->getVelocity());
}
pList->mConvex->getPolyList(&sExtrudedPolyList);
}
}This works but I still need to know how to change this to use collision meshes instead of bounding boxes.
#14
2) Refer to Matt's wonderful Collision Tutorial Object . Find all of the collision functions in the Item class, and replace them with calls to the parent functions. ShapeBase does do meshes. There's a bit more, but I'm sure this will be a great start. I can't be of much help here because this is something I never actually got around to. I found what is, in my opinion, a better solution that involved writing a couple thousand lines of code, and it's under NDA so I really can't say much about it.
06/05/2005 (9:15 pm)
1) I still don't know why adding ItemObjectType to the collision mask didn't work for you. It worked splendidly for me.2) Refer to Matt's wonderful Collision Tutorial Object . Find all of the collision functions in the Item class, and replace them with calls to the parent functions. ShapeBase does do meshes. There's a bit more, but I'm sure this will be a great start. I can't be of much help here because this is something I never actually got around to. I found what is, in my opinion, a better solution that involved writing a couple thousand lines of code, and it's under NDA so I really can't say much about it.
#15
06/06/2005 (11:29 am)
Just remembered that I also had trouble because the 3dmodel of item I used was not having a collision box. Once the artist added a collision box and as well with the change I proposed for the collision mask then it worked. But the collision box is required in your model.
#16
I've been messing around with player/item and item/item collision. Thanks for the engine code advice, works great. Here's my problem though:
I'm scripting behavior so that when one moving item collides with another stationary item, the moving item will impart an impulse to the stationary one. The problem with this is that every time two items collide, the engine calls onCollision() for both items (first for the collider, second for the collidee). Getting around this has lead to some less-than-ideal script. Any ideas on how to get the engine to just report onCollision for one of the two when a collision occurs?
07/06/2007 (4:11 pm)
Hello everyone,I've been messing around with player/item and item/item collision. Thanks for the engine code advice, works great. Here's my problem though:
I'm scripting behavior so that when one moving item collides with another stationary item, the moving item will impart an impulse to the stationary one. The problem with this is that every time two items collide, the engine calls onCollision() for both items (first for the collider, second for the collidee). Getting around this has lead to some less-than-ideal script. Any ideas on how to get the engine to just report onCollision for one of the two when a collision occurs?
#17
07/08/2007 (4:06 pm)
Actually, I realized the double-collision behavior occurs in my mission because the colliding Items are always from different datablocks. I figured a way around the mess using global variables...
Torque Owner Robert Pierce
For an example (I am not testing this in any way, so I apologize for errors), let us assume there is a fictitous item of the class "Item" and with the name "MagicBall" (Datablock block would be Item(MagicBall) {...}).
Here is some code that would echo "blue" to the console if the Item (being collided with) is of the Item class, and "red" if the Item (being collided with) is called "MagicBall".
function MagicBall::onCollision(%this,%obj,%col) { if (%col.getClassName() $= "Item") // If the object you are colliding with is of the class "Item" echo("blue"); if (%col.getDataBlock().getName() $= "MagicBall") echo("red"); }This is kind of a poor example, but it should help, :).
Robert