Deviation of rotating bounding spheres

I make a two-inch game and use BoundingSphere for the hit box as a short cut.

The problem is that many things rotate all the time, and I need to develop a way to calculate the “exact” bounce angle when the ball hits other circular objects.

Any hints, tips and tricks are welcome

/ Change Could not find anything but to deal with this, kindly works

This is called as soon as a collision is detected between two BoundingSphere.

private void CollisionRebound(Sprites.BaseSprite attacker, Vector2 defender) { //Work out the rotation that would result in a "dead on" collision //thus rebounding the attacker straight back the way they came. float directHitRotation = (float)Math.Atan2(defender.Y - attacker.Position.Y , defender.X - attacker.Position.X); //only really needed if the rotation is a negative value but is easier to work from in general. float attackerRotation = attacker.rotation; //This makes the rotation a positive number, it cant be less that -2PI //so adding 2PI will leave us with a positive rotation. if (attackerRotation < 0) { attackerRotation += (float)(Math.PI * 2); } //If the rotation is greater than the "dead on" rotation the rotation //needs to increase. if (attackerRotation > directHitRotation) { //we add "PiOver2" or "90 degrees" to "dead on" rotation because we do, dont know enough //trig to explain it just know it works, we then add 90 degrees minus the difference between //our two rotation to give us our outgoing angle, the +0.01f is for the rare case where the //difference is 90 which would give us no change in rotation but if the two spheres have collided //(which they have to before coming to this code chunk) there will be at least some change. attackerRotation = directHitRotation + (float)MathHelper.PiOver2 + ((float)MathHelper.PiOver2 - (attackerRotation - directHitRotation) + 0.01f); } //If the rotation is less than the "dead on" rotation the rotation //need to decrease. else if (attackerRotation < directHitRotation) { //same as previous chunk but we will be minusing the angle attackerRotation = directHitRotation - (float)MathHelper.PiOver2 - ((float)MathHelper.PiOver2 - (attackerRotation - directHitRotation) - 0.01f); } else if (attackerRotation == directHitRotation) { //either of the two calculations could be used here but would result in the same outcome //which is rotating the attacker 180 degrees, so just add 2PI instead. attackerRotation += (float)Math.PI; } //Here we just assign out new output rotation to the attacker entity. attacker.rotation = attackerRotation; } 

just get an “attacker” sticking out in the “defender” occasionally, any suggestions for fixing it?

Comments have been added to explain the code to others interested in using it.

+4
source share
1 answer

I am going to take a hit on this without trying it, so I cannot guarantee that it is accurate. Also, this is pseudo code.

We need to know the point of collision between the spheres. If you expect each frame to detect a collision, your spheres are likely to be partially interpenetrating, so the first thing I would like to do is push them out of each other. To do this, you need to know how far each one can go.

 Vector3 BtoA = (SphereA.center - SphereB.center); Vector3 AtoB = (SphereB.center - SphereA.center); float currentDistance = AtoB.length(); float minimumDistance = SphereA.radius + SphereB.radius; // If the spheres are interpenetrating then push them apart until // they're colliding only at a single point. // Do a quick sanity check here if ( currentDistance > minimumDistance ) { // Your spheres aren't close enough to be touching, how did you get here? } else if ( currentDistance < minimumDistance ) { // We move each sphere away by half of the penetration distance. float penetrationDistance = currentDistance - minimumDistance; Vector3 unitBtoA = BtoA.unitize(); SphereA.position = SphereA.position + (unitBtoA * penetrationDistance * 0.5f); Vector3 unitAtoB = AtoB.unitize(); SphereB.position = SphereB.position + (unitAtoB * penetrationDistance * 0.5f); // Note that now that we have repositioned the spheres they have different AtoB and // BtoA vectors, and theoretically could be colliding with spheres very close to // them that they weren't colliding with before. We now recalculate our difference vectors BtoA = (SphereA.center - SphereB.center); AtoB = (SphereB.center - SphereA.center); } // Ok, now we know that the spheres are only touching at one point. We can now calculate // the reflection/deflection // I believe the code for calculating a deflection of a velocity off of a surface // given the normal of that surface is something like this. This assumes no energy // is lost on the bounce as well, which isn't realistic. Vector3 Reflect( Vector3 velocity, Vector3 surfaceNormal ) { const float dotProductTimesTwo = velocity.Dot(surfaceNormal) * 2.0f; velocity.x -= dotProductTimesTwo * surfaceNormal.x; velocity.y -= dotProductTimesTwo * surfaceNormal.y; velocity.z -= dotProductTimesTwo * surfaceNormal.z; } // Using the above function, we reflect the velocities of both spheres Vector3 unitBtoA = BtoA.unitize(); Vector3 unitAtoA = AtoA.unitize(); SphereA.velocity = Reflect( SphereA.velocity, unitBtoA ); SphereB.velocity = Reflect( SphereA.velocity, unitAtoB ); 

If you want to be more precise with your refusal, you should be able to figure out, based on the depth of penetration of the spheres, how much time has passed since they would have collided if you had not used the framework-based application. This should allow you to calculate how much they should be far now that they have bounced apart. If you calculate this time, you can take the speed of the sphere, which we calculated above, and change the position of the spheres by this amount of time.

 // This variable would hold the amount of time since the spheres actually would have collided float extra_time; SphereA.position = SphereA.position + (SphereA.velocity * extra_time); SphereB.position = SphereB.position + (SphereB.velocity * extra_time); 

As I said earlier, I have not tested this code at all, so it may not work at all, but at least it may be a good starting point for you or it may be close to functional. Hope this helps. Good luck.

0
source

All Articles