/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package jme3test.bullet; import com.jme3.asset.AssetManager; import com.jme3.bullet.PhysicsSpace; import com.jme3.bullet.PhysicsTickListener; import com.jme3.bullet.collision.PhysicsCollisionEvent; import com.jme3.bullet.collision.PhysicsCollisionListener; import com.jme3.bullet.collision.PhysicsCollisionObject; import com.jme3.bullet.collision.shapes.CollisionShape; import com.jme3.bullet.collision.shapes.SphereCollisionShape; import com.jme3.bullet.control.RigidBodyControl; import com.jme3.bullet.objects.PhysicsGhostObject; import com.jme3.bullet.objects.PhysicsRigidBody; import com.jme3.effect.ParticleEmitter; import com.jme3.effect.ParticleMesh.Type; import com.jme3.effect.shapes.EmitterSphereShape; import com.jme3.export.JmeExporter; import com.jme3.export.JmeImporter; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import java.io.IOException; import java.util.Iterator; /** * * @author normenhansen */ public class BombControl extends RigidBodyControl implements PhysicsCollisionListener, PhysicsTickListener { private float explosionRadius = 10; private PhysicsGhostObject ghostObject; private Vector3f vector = new Vector3f(); private Vector3f vector2 = new Vector3f(); private float forceFactor = 1; private ParticleEmitter effect; private float fxTime = 0.5f; private float maxTime = 4f; private float curTime = -1.0f; private float timer; public BombControl(CollisionShape shape, float mass) { super(shape, mass); createGhostObject(); } public BombControl(AssetManager manager, CollisionShape shape, float mass) { super(shape, mass); createGhostObject(); prepareEffect(manager); } public void setPhysicsSpace(PhysicsSpace space) { super.setPhysicsSpace(space); if (space != null) { space.addCollisionListener(this); } } private void prepareEffect(AssetManager assetManager) { int COUNT_FACTOR = 1; float COUNT_FACTOR_F = 1f; effect = new ParticleEmitter("Flame", Type.Triangle, 32 * COUNT_FACTOR); effect.setSelectRandomImage(true); effect.setStartColor(new ColorRGBA(1f, 0.4f, 0.05f, (float) (1f / COUNT_FACTOR_F))); effect.setEndColor(new ColorRGBA(.4f, .22f, .12f, 0f)); effect.setStartSize(1.3f); effect.setEndSize(2f); effect.setShape(new EmitterSphereShape(Vector3f.ZERO, 1f)); effect.setParticlesPerSec(0); effect.setGravity(0, -5f, 0); effect.setLowLife(.4f); effect.setHighLife(.5f); effect.setInitialVelocity(new Vector3f(0, 7, 0)); effect.setVelocityVariation(1f); effect.setImagesX(2); effect.setImagesY(2); Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md"); mat.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png")); effect.setMaterial(mat); } protected void createGhostObject() { ghostObject = new PhysicsGhostObject(new SphereCollisionShape(explosionRadius)); } public void collision(PhysicsCollisionEvent event) { if (space == null) { return; } if (event.getObjectA() == this || event.getObjectB() == this) { space.add(ghostObject); ghostObject.setPhysicsLocation(getPhysicsLocation(vector)); space.addTickListener(this); if (effect != null && spatial.getParent() != null) { curTime = 0; effect.setLocalTranslation(spatial.getLocalTranslation()); spatial.getParent().attachChild(effect); effect.emitAllParticles(); } space.remove(this); spatial.removeFromParent(); } } public void prePhysicsTick(PhysicsSpace space, float f) { space.removeCollisionListener(this); } public void physicsTick(PhysicsSpace space, float f) { //get all overlapping objects and apply impulse to them for (Iterator it = ghostObject.getOverlappingObjects().iterator(); it.hasNext();) { PhysicsCollisionObject physicsCollisionObject = it.next(); if (physicsCollisionObject instanceof PhysicsRigidBody) { PhysicsRigidBody rBody = (PhysicsRigidBody) physicsCollisionObject; rBody.getPhysicsLocation(vector2); vector2.subtractLocal(vector); float force = explosionRadius - vector2.length(); force *= forceFactor; force = force > 0 ? force : 0; vector2.normalizeLocal(); vector2.multLocal(force); ((PhysicsRigidBody) physicsCollisionObject).applyImpulse(vector2, Vector3f.ZERO); } } space.removeTickListener(this); space.remove(ghostObject); } @Override public void update(float tpf) { super.update(tpf); if(enabled){ timer+=tpf; if(timer>maxTime){ if(spatial.getParent()!=null){ space.removeCollisionListener(this); space.remove(this); spatial.removeFromParent(); } } } if (enabled && curTime >= 0) { curTime += tpf; if (curTime > fxTime) { curTime = -1; effect.removeFromParent(); } } } /** * @return the explosionRadius */ public float getExplosionRadius() { return explosionRadius; } /** * @param explosionRadius the explosionRadius to set */ public void setExplosionRadius(float explosionRadius) { this.explosionRadius = explosionRadius; createGhostObject(); } public float getForceFactor() { return forceFactor; } public void setForceFactor(float forceFactor) { this.forceFactor = forceFactor; } @Override public void read(JmeImporter im) throws IOException { throw new UnsupportedOperationException("Reading not supported."); } @Override public void write(JmeExporter ex) throws IOException { throw new UnsupportedOperationException("Saving not supported."); } }