Home | History | Annotate | Download | only in bullet
      1 /*
      2  * To change this template, choose Tools | Templates
      3  * and open the template in the editor.
      4  */
      5 package jme3test.bullet;
      6 
      7 import com.jme3.asset.AssetManager;
      8 import com.jme3.bullet.PhysicsSpace;
      9 import com.jme3.bullet.PhysicsTickListener;
     10 import com.jme3.bullet.collision.PhysicsCollisionEvent;
     11 import com.jme3.bullet.collision.PhysicsCollisionListener;
     12 import com.jme3.bullet.collision.PhysicsCollisionObject;
     13 import com.jme3.bullet.collision.shapes.CollisionShape;
     14 import com.jme3.bullet.collision.shapes.SphereCollisionShape;
     15 import com.jme3.bullet.control.RigidBodyControl;
     16 import com.jme3.bullet.objects.PhysicsGhostObject;
     17 import com.jme3.bullet.objects.PhysicsRigidBody;
     18 import com.jme3.effect.ParticleEmitter;
     19 import com.jme3.effect.ParticleMesh.Type;
     20 import com.jme3.effect.shapes.EmitterSphereShape;
     21 import com.jme3.export.JmeExporter;
     22 import com.jme3.export.JmeImporter;
     23 import com.jme3.material.Material;
     24 import com.jme3.math.ColorRGBA;
     25 import com.jme3.math.Vector3f;
     26 import java.io.IOException;
     27 import java.util.Iterator;
     28 
     29 /**
     30  *
     31  * @author normenhansen
     32  */
     33 public class BombControl extends RigidBodyControl implements PhysicsCollisionListener, PhysicsTickListener {
     34 
     35     private float explosionRadius = 10;
     36     private PhysicsGhostObject ghostObject;
     37     private Vector3f vector = new Vector3f();
     38     private Vector3f vector2 = new Vector3f();
     39     private float forceFactor = 1;
     40     private ParticleEmitter effect;
     41     private float fxTime = 0.5f;
     42     private float maxTime = 4f;
     43     private float curTime = -1.0f;
     44     private float timer;
     45 
     46     public BombControl(CollisionShape shape, float mass) {
     47         super(shape, mass);
     48         createGhostObject();
     49     }
     50 
     51     public BombControl(AssetManager manager, CollisionShape shape, float mass) {
     52         super(shape, mass);
     53         createGhostObject();
     54         prepareEffect(manager);
     55     }
     56 
     57     public void setPhysicsSpace(PhysicsSpace space) {
     58         super.setPhysicsSpace(space);
     59         if (space != null) {
     60             space.addCollisionListener(this);
     61         }
     62     }
     63 
     64     private void prepareEffect(AssetManager assetManager) {
     65         int COUNT_FACTOR = 1;
     66         float COUNT_FACTOR_F = 1f;
     67         effect = new ParticleEmitter("Flame", Type.Triangle, 32 * COUNT_FACTOR);
     68         effect.setSelectRandomImage(true);
     69         effect.setStartColor(new ColorRGBA(1f, 0.4f, 0.05f, (float) (1f / COUNT_FACTOR_F)));
     70         effect.setEndColor(new ColorRGBA(.4f, .22f, .12f, 0f));
     71         effect.setStartSize(1.3f);
     72         effect.setEndSize(2f);
     73         effect.setShape(new EmitterSphereShape(Vector3f.ZERO, 1f));
     74         effect.setParticlesPerSec(0);
     75         effect.setGravity(0, -5f, 0);
     76         effect.setLowLife(.4f);
     77         effect.setHighLife(.5f);
     78         effect.setInitialVelocity(new Vector3f(0, 7, 0));
     79         effect.setVelocityVariation(1f);
     80         effect.setImagesX(2);
     81         effect.setImagesY(2);
     82         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
     83         mat.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
     84         effect.setMaterial(mat);
     85     }
     86 
     87     protected void createGhostObject() {
     88         ghostObject = new PhysicsGhostObject(new SphereCollisionShape(explosionRadius));
     89     }
     90 
     91     public void collision(PhysicsCollisionEvent event) {
     92         if (space == null) {
     93             return;
     94         }
     95         if (event.getObjectA() == this || event.getObjectB() == this) {
     96             space.add(ghostObject);
     97             ghostObject.setPhysicsLocation(getPhysicsLocation(vector));
     98             space.addTickListener(this);
     99             if (effect != null && spatial.getParent() != null) {
    100                 curTime = 0;
    101                 effect.setLocalTranslation(spatial.getLocalTranslation());
    102                 spatial.getParent().attachChild(effect);
    103                 effect.emitAllParticles();
    104             }
    105             space.remove(this);
    106             spatial.removeFromParent();
    107         }
    108     }
    109 
    110     public void prePhysicsTick(PhysicsSpace space, float f) {
    111         space.removeCollisionListener(this);
    112     }
    113 
    114     public void physicsTick(PhysicsSpace space, float f) {
    115         //get all overlapping objects and apply impulse to them
    116         for (Iterator<PhysicsCollisionObject> it = ghostObject.getOverlappingObjects().iterator(); it.hasNext();) {
    117             PhysicsCollisionObject physicsCollisionObject = it.next();
    118             if (physicsCollisionObject instanceof PhysicsRigidBody) {
    119                 PhysicsRigidBody rBody = (PhysicsRigidBody) physicsCollisionObject;
    120                 rBody.getPhysicsLocation(vector2);
    121                 vector2.subtractLocal(vector);
    122                 float force = explosionRadius - vector2.length();
    123                 force *= forceFactor;
    124                 force = force > 0 ? force : 0;
    125                 vector2.normalizeLocal();
    126                 vector2.multLocal(force);
    127                 ((PhysicsRigidBody) physicsCollisionObject).applyImpulse(vector2, Vector3f.ZERO);
    128             }
    129         }
    130         space.removeTickListener(this);
    131         space.remove(ghostObject);
    132     }
    133 
    134     @Override
    135     public void update(float tpf) {
    136         super.update(tpf);
    137         if(enabled){
    138             timer+=tpf;
    139             if(timer>maxTime){
    140                 if(spatial.getParent()!=null){
    141                     space.removeCollisionListener(this);
    142                     space.remove(this);
    143                     spatial.removeFromParent();
    144                 }
    145             }
    146         }
    147         if (enabled && curTime >= 0) {
    148             curTime += tpf;
    149             if (curTime > fxTime) {
    150                 curTime = -1;
    151                 effect.removeFromParent();
    152             }
    153         }
    154     }
    155 
    156     /**
    157      * @return the explosionRadius
    158      */
    159     public float getExplosionRadius() {
    160         return explosionRadius;
    161     }
    162 
    163     /**
    164      * @param explosionRadius the explosionRadius to set
    165      */
    166     public void setExplosionRadius(float explosionRadius) {
    167         this.explosionRadius = explosionRadius;
    168         createGhostObject();
    169     }
    170 
    171     public float getForceFactor() {
    172         return forceFactor;
    173     }
    174 
    175     public void setForceFactor(float forceFactor) {
    176         this.forceFactor = forceFactor;
    177     }
    178 
    179 
    180     @Override
    181     public void read(JmeImporter im) throws IOException {
    182         throw new UnsupportedOperationException("Reading not supported.");
    183     }
    184 
    185     @Override
    186     public void write(JmeExporter ex) throws IOException {
    187         throw new UnsupportedOperationException("Saving not supported.");
    188     }
    189 }
    190