[SOLVED] Temporary attack hitboxes
-
- Posts: 10
- Joined: Wed Apr 15, 2015 9:50 pm
[SOLVED] Temporary attack hitboxes
Hello everyone,
I am currently using Ogre3D and Bullet to create a 3D game. I do not have a lot of Bullet experience, although.
Situation: I have two characters right now, which are both represented by capsules physically.
Here's an unnecessary screenshot:
So let's say the player wants to attack the enemy penguin. My idea was to temporarily spawn an attack hitbox like Marth's red circles right here:
How can you accomplish that in Bullet?
Do I just temporarily spawn some static btRigidBodies? But how can I register "the hit" in my Enemy class, where I control the rigid body?
I want to maybe change the penguin's animation to a hit animation. Also, can you recommend me any resources to learn more about Bullet? Thanks.
I am currently using Ogre3D and Bullet to create a 3D game. I do not have a lot of Bullet experience, although.
Situation: I have two characters right now, which are both represented by capsules physically.
Here's an unnecessary screenshot:
So let's say the player wants to attack the enemy penguin. My idea was to temporarily spawn an attack hitbox like Marth's red circles right here:
How can you accomplish that in Bullet?
Do I just temporarily spawn some static btRigidBodies? But how can I register "the hit" in my Enemy class, where I control the rigid body?
I want to maybe change the penguin's animation to a hit animation. Also, can you recommend me any resources to learn more about Bullet? Thanks.
Last edited by Waschmaschine on Tue May 26, 2015 6:10 pm, edited 1 time in total.
-
- Posts: 225
- Joined: Wed Jan 07, 2009 11:43 am
- Location: London
Re: Temporary attack hitboxes
Probably best thing to use is ghost collision objects as you don't really want them to effect the physics of the world. If you look at the ghost demo you'll see an example, including how you might use a collision callback or similar. You can use the callback to trigger situations in your game . e.g. you can test for a hit between the ghost hitboxes and your entity and send a 'message' to the entity to say it's been hit, and by what. You can them have some logic to play an animation, take damage etc.
-
- Posts: 10
- Joined: Wed Apr 15, 2015 9:50 pm
Re: Temporary attack hitboxes
Thank you for your response!xexuxjy wrote:Probably best thing to use is ghost collision objects as you don't really want them to effect the physics of the world. If you look at the ghost demo you'll see an example, including how you might use a collision callback or similar. You can use the callback to trigger situations in your game . e.g. you can test for a hit between the ghost hitboxes and your entity and send a 'message' to the entity to say it's been hit, and by what. You can them have some logic to play an animation, take damage etc.
Here's what I did:
Code: Select all
// Create hitbox for attack
_phyAttackGhostObject = new btPairCachingGhostObject();
_phyAttackGhostObject->setCollisionShape( new btSphereShape(0.5) );
_phyAttackGhostObject->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);
_phyAttackGhostObject->setUserPointer(this);
_phyWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
-Check for collision after simulation step. ( Shouldn't this be done by the callback? ) Code: http://www.bulletphysics.org/mediawiki- ... hostObject
-Added the line
Code: Select all
collisionEvent( manifold->getBody0(), manifold->getBody1() );
Code: Select all
void Player::collisionEvent(const btCollisionObject* pBody0, const btCollisionObject * pBody1){
btCollisionObject* ghostObj = static_cast<btCollisionObject*>(_phyAttackGhostObject);
if (ghostObj == pBody0){
if (pBody1->getCollisionFlags() == btCollisionObject::CF_CHARACTER_OBJECT &&
pBody1 != _phyGhostObject){
Enemy* enemy = static_cast<Enemy*>(pBody1->getUserPointer());
enemy->wasHit();
}
} else {
if (pBody0->getCollisionFlags() == btCollisionObject::CF_CHARACTER_OBJECT &&
pBody0 != _phyGhostObject){
Enemy* enemy = static_cast<Enemy*>(pBody0->getUserPointer());
enemy->wasHit();
}
}
}
And this works! Kind of, though:
The sphere is not touching the left wall, but it registers a hit with my setup. It does not touch the floor!
Any advice for this or the callback?
-
- Posts: 225
- Joined: Wed Jan 07, 2009 11:43 am
- Location: London
Re: Temporary attack hitboxes
Hmm, tricky to see from that. But I couldn't see anything obviously wrong.
Would you expect the sphere to intersect the floor based on it's size and the offset from the player you're generating it at? How far away from the wall do you have to be before it stops generating 'false' collisions?
Would you expect the sphere to intersect the floor based on it's size and the offset from the player you're generating it at? How far away from the wall do you have to be before it stops generating 'false' collisions?
-
- Posts: 10
- Joined: Wed Apr 15, 2015 9:50 pm
Re: Temporary attack hitboxes
No, when I move further away from the wall I do not get a collision, not even with the floor.xexuxjy wrote:Hmm, tricky to see from that. But I couldn't see anything obviously wrong.
Would you expect the sphere to intersect the floor based on it's size and the offset from the player you're generating it at?
The end of the wall is located at x=17.xexuxjy wrote:How far away from the wall do you have to be before it stops generating 'false' collisions?
This generates hits:
Code: Select all
hitboxTrans.setOrigin(btVector3(17.76135, 1.5, 0));
Code: Select all
hitboxTrans.setOrigin(btVector3(17.7617, 1.5, 0));
Again, here's a screen of a collision. Note that I decoupled it from the player's position.
Edit: I tried it again with a radius of 1.0, getting the same offset.
Bonus question: Why is
Code: Select all
_phyWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
-
- Posts: 225
- Joined: Wed Jan 07, 2009 11:43 am
- Location: London
Re: Temporary attack hitboxes
Memories a bit flakey on this but :
You set-up a single btGhostPairCallback (only once) to allow the broad-phase to pass on the results of it's collision tests to the ghost objects directly. The ghost objects are a bit different in that they remember the colliding pairs (rather than just having the impulses applied to them as the result of the collisions) . This is handy for things like triggers,sensors and the like.
If you remove that line then the code in your kinematic controller then it doesn't have any information it needs to keep itself off the ground , walk forward, step up and so on (I've glanced back over the code and when you provide the controller with a ghost shape it uses a special case for it's convexSweepTest that relies on the ghost object holding it's overlapping pairs).
Of course none of this solves your real problem of the collisions appearing in the 'wrong' place. It may be worth turning on the AABB's for visualisation as it looks like ghosts just use the AABB and it may help to show any discrepancies (though I'm not sure how the AABB can be that much out from the collision sphere....)
You set-up a single btGhostPairCallback (only once) to allow the broad-phase to pass on the results of it's collision tests to the ghost objects directly. The ghost objects are a bit different in that they remember the colliding pairs (rather than just having the impulses applied to them as the result of the collisions) . This is handy for things like triggers,sensors and the like.
If you remove that line then the code in your kinematic controller then it doesn't have any information it needs to keep itself off the ground , walk forward, step up and so on (I've glanced back over the code and when you provide the controller with a ghost shape it uses a special case for it's convexSweepTest that relies on the ghost object holding it's overlapping pairs).
Of course none of this solves your real problem of the collisions appearing in the 'wrong' place. It may be worth turning on the AABB's for visualisation as it looks like ghosts just use the AABB and it may help to show any discrepancies (though I'm not sure how the AABB can be that much out from the collision sphere....)
-
- Posts: 10
- Joined: Wed Apr 15, 2015 9:50 pm
Re: Temporary attack hitboxes
Thanks for clearing that up.
Still, I debugged my code using this.
Output:
17.2614 1 -0.5
18.2614 2 0.5
Again, I used the hit generating distance with the wall ending at x=17 and a radius of 0.5:
The output seems OK because the difference in each dimension of the AABB is double the radius.
How do I turn on the AABBs? This made me realize that the error source could be on the side of my DebugDrawer implementation, i.e. BtOgre.xexuxjy wrote: Of course none of this solves your real problem of the collisions appearing in the 'wrong' place. It may be worth turning on the AABB's for visualisation as it looks like ghosts just use the AABB and it may help to show any discrepancies (though I'm not sure how the AABB can be that much out from the collision sphere....)
Still, I debugged my code using this.
Code: Select all
btTransform t = _phyAttackGhostObject->getWorldTransform();
btVector3 v1,v2;
_phyAttackGhostObject->getCollisionShape()->getAabb(t,v1,v2);
std::cout << v1.x() << " " << v1.y() << " " << v1.z() << std::endl;
std::cout << v2.x() << " " << v2.y() << " " << v2.z() << std::endl;
17.2614 1 -0.5
18.2614 2 0.5
Again, I used the hit generating distance with the wall ending at x=17 and a radius of 0.5:
Code: Select all
btTransform hitboxTrans;
hitboxTrans.setIdentity();
hitboxTrans.setOrigin(btVector3(17.76135, 1.5, 0));
_phyAttackGhostObject->setWorldTransform(hitboxTrans);
-
- Posts: 225
- Joined: Wed Jan 07, 2009 11:43 am
- Location: London
Re: Temporary attack hitboxes
If you're using debug drawer you can include : DBG_DrawAabb in your draw mask .
If your project can be packaged up at all, i'd be happy to try and debug why you're getting those results.
If your project can be packaged up at all, i'd be happy to try and debug why you're getting those results.
-
- Posts: 10
- Joined: Wed Apr 15, 2015 9:50 pm
Re: Temporary attack hitboxes
I've hacked together a minmal example:xexuxjy wrote:If you're using debug drawer you can include : DBG_DrawAabb in your draw mask .
If your project can be packaged up at all, i'd be happy to try and debug why you're getting those results.
http://pastebin.com/drCKCKrL
Additional include directories:
$(BULLET_ROOT)\src;
Additional library directories:
$(BULLET_ROOT)\lib\Debug;
Input:
BulletDynamics_Debug.lib;BulletCollision_Debug.lib;LinearMath_Debug.lib;
-
- Posts: 225
- Joined: Wed Jan 07, 2009 11:43 am
- Location: London
Re: Temporary attack hitboxes
Thanks.
I've had a quick run through.
with position at 1.27 then the broadphase is generating a provisional overlap (probably down to the way the floats are quantized), with 1.30 then there is no overlap generated.
to get round this issue, you can change your checkCollision function as follows :
it will then not generate collisions for 1.27 or 1.3 , but will for 0.8
I've had a quick run through.
with position at 1.27 then the broadphase is generating a provisional overlap (probably down to the way the floats are quantized), with 1.30 then there is no overlap generated.
to get round this issue, you can change your checkCollision function as follows :
Code: Select all
for (int p = 0; p < manifold->getNumContacts(); p++){
const btManifoldPoint&pt = manifold->getContactPoint(p);
if (pt.getDistance() < 0.f)
{
// TODO: ADD STUFF
collisionEvent(manifold->getBody0(), manifold->getBody1());
const btVector3& ptA = pt.getPositionWorldOnA();
const btVector3& ptB = pt.getPositionWorldOnB();
const btVector3& normalOnB = pt.m_normalWorldOnB;
/// work here
}
}
-
- Posts: 10
- Joined: Wed Apr 15, 2015 9:50 pm
Re: Temporary attack hitboxes
Thank you, we're done here. I guess I owe you a beverage of your liking.xexuxjy wrote:Thanks.
I've had a quick run through.
with position at 1.27 then the broadphase is generating a provisional overlap (probably down to the way the floats are quantized), with 1.30 then there is no overlap generated.
to get round this issue, you can change your checkCollision function as follows :it will then not generate collisions for 1.27 or 1.3 , but will for 0.8Code: Select all
for (int p = 0; p < manifold->getNumContacts(); p++){ const btManifoldPoint&pt = manifold->getContactPoint(p); if (pt.getDistance() < 0.f) { // TODO: ADD STUFF collisionEvent(manifold->getBody0(), manifold->getBody1()); const btVector3& ptA = pt.getPositionWorldOnA(); const btVector3& ptB = pt.getPositionWorldOnB(); const btVector3& normalOnB = pt.m_normalWorldOnB; /// work here } }
-
- Posts: 225
- Joined: Wed Jan 07, 2009 11:43 am
- Location: London
Re: [SOLVED] Temporary attack hitboxes
Heh, np. good luck with the rest of your project.