package com.bitwaffle.spaceguts.physics; import java.util.Iterator; import java.util.NoSuchElementException; import javax.vecmath.Quat4f; import org.lwjgl.util.vector.Vector3f; import com.bitwaffle.spaceguts.audio.SoundSource; import com.bitwaffle.spaceguts.entities.DynamicEntity; import com.bitwaffle.spaceguts.entities.Entities; import com.bitwaffle.spaceout.entities.dynamic.Missile; import com.bitwaffle.spaceout.interfaces.Health; import com.bitwaffle.spaceout.interfaces.Projectile; import com.bitwaffle.spaceout.resources.Sounds; import com.bulletphysics.collision.dispatch.CollisionObject; import com.bulletphysics.collision.narrowphase.ManifoldPoint; import com.bulletphysics.collision.narrowphase.PersistentManifold; import com.bulletphysics.dynamics.DynamicsWorld; import com.bulletphysics.dynamics.InternalTickCallback; import com.bulletphysics.linearmath.Transform; /** * This handles updating EVERYTHING in the game. At the end of every physics tick, * it goes through every object and updates the information in the lists in Entities * that the renderer looks at when drawing. * * @author TranquilMarmot */ public class DynamicEntityCallback extends InternalTickCallback { @Override public void internalTick(DynamicsWorld world, float timeStep) { Iterator<CollisionObject> it = world.getCollisionObjectArray() .iterator(); while (it.hasNext()) { CollisionObject c = null; try { c = it.next(); } catch (NoSuchElementException e) { //FIXME what causes this? it = world.getCollisionObjectArray().iterator(); } if (c != null) { processEntity(c, timeStep); } } checkForCollisions(); // this is a very important call! Updates the camera, skybox, and any non-dynamic entities Entities.updateAll(timeStep); } /** * Updates an entity's location and then performs any necessary logic * * @param c * Collision object for the entity being updated * @param timeStep * Amount of time passed since last tick */ private void processEntity(CollisionObject c, float timeStep) { DynamicEntity ent = (DynamicEntity) c.getUserPointer(); if (ent.removeFlag) { Physics.dynamicsWorld.removeCollisionObject(c); Entities.dynamicEntities.remove(ent); } else { // get the rigid body's world transform Transform trans = new Transform(); ent.rigidBody.getMotionState().getWorldTransform(trans); // set this entity's location javax.vecmath.Vector3f origin = trans.origin; ent.location.set(origin.x, origin.y, origin.z); // set this entity's rotation Quat4f rot = new Quat4f(); trans.getRotation(rot); ent.rotation.set(rot.x, rot.y, rot.z, rot.w); ent.update(timeStep); } } private static void checkForCollisions(){ for(int i = 0; i < Physics.dispatcher.getNumManifolds(); i++){ PersistentManifold contactManifold = Physics.dispatcher.getManifoldByIndexInternal(i); CollisionObject objA = (CollisionObject) contactManifold.getBody0(); CollisionObject objB = (CollisionObject) contactManifold.getBody1(); for(int j = 0; j < contactManifold.getNumContacts(); j++){ ManifoldPoint point = contactManifold.getContactPoint(j); if(point.getDistance() < 0.0f){ //Vector3f ptA = new Vector3f(), ptB = new Vector3f(), normalOnB; //point.getPositionWorldOnA(ptA); //point.getPositionWorldOnB(ptB); //normalOnB = point.normalWorldOnB; DynamicEntity entA = (DynamicEntity) objA.getUserPointer(); DynamicEntity entB = (DynamicEntity) objB.getUserPointer(); if(entA instanceof Projectile && entB instanceof Health) bulletHealthCollision((Projectile) entA, (Health) entB); else if(entB instanceof Projectile && entA instanceof Health) bulletHealthCollision((Projectile) entB, (Health) entA); /* System.out.println("Contact point " + j + ":\nA: " + entA.type + " " + ptA.x + " " + ptA.y + " " + ptA.z); System.out.println("B: " + entB.type + " " + ptB.x + " " + ptB.y + " " + ptB.z); System.out.println("Normal on B: " + normalOnB.x + " " + normalOnB.y + " " + normalOnB.z); */ } } } } private static void bulletHealthCollision(Projectile bullet, Health health){ if(bullet.getOwner() != health) health.hurt(bullet.getDamage()); // explode if the bullet is a missile if(bullet instanceof Missile) ((Missile) bullet).explode(); // else make a noise else{ SoundSource hit = new SoundSource(Sounds.HIT, false, ((DynamicEntity)health).location, new Vector3f(0.01f, 0.01f, 0.01f)); hit.playSound(); hit.removeFlag = true; } } }