159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * To change this template, choose Tools | Templates
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * and open the template in the editor.
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage jme3test.bullet;
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.asset.AssetManager;
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.PhysicsSpace;
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.PhysicsTickListener;
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.collision.PhysicsCollisionEvent;
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.collision.PhysicsCollisionListener;
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.collision.PhysicsCollisionObject;
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.collision.shapes.CollisionShape;
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.collision.shapes.SphereCollisionShape;
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.control.RigidBodyControl;
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.objects.PhysicsGhostObject;
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.objects.PhysicsRigidBody;
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.effect.ParticleEmitter;
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.effect.ParticleMesh.Type;
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.effect.shapes.EmitterSphereShape;
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeExporter;
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeImporter;
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.Material;
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.ColorRGBA;
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f;
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException;
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Iterator;
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/**
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author normenhansen
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class BombControl extends RigidBodyControl implements PhysicsCollisionListener, PhysicsTickListener {
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private float explosionRadius = 10;
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private PhysicsGhostObject ghostObject;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f vector = new Vector3f();
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f vector2 = new Vector3f();
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private float forceFactor = 1;
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private ParticleEmitter effect;
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private float fxTime = 0.5f;
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private float maxTime = 4f;
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private float curTime = -1.0f;
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private float timer;
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BombControl(CollisionShape shape, float mass) {
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super(shape, mass);
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        createGhostObject();
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public BombControl(AssetManager manager, CollisionShape shape, float mass) {
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super(shape, mass);
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        createGhostObject();
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        prepareEffect(manager);
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setPhysicsSpace(PhysicsSpace space) {
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super.setPhysicsSpace(space);
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (space != null) {
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            space.addCollisionListener(this);
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void prepareEffect(AssetManager assetManager) {
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int COUNT_FACTOR = 1;
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float COUNT_FACTOR_F = 1f;
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect = new ParticleEmitter("Flame", Type.Triangle, 32 * COUNT_FACTOR);
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setSelectRandomImage(true);
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setStartColor(new ColorRGBA(1f, 0.4f, 0.05f, (float) (1f / COUNT_FACTOR_F)));
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setEndColor(new ColorRGBA(.4f, .22f, .12f, 0f));
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setStartSize(1.3f);
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setEndSize(2f);
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setShape(new EmitterSphereShape(Vector3f.ZERO, 1f));
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setParticlesPerSec(0);
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setGravity(0, -5f, 0);
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setLowLife(.4f);
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setHighLife(.5f);
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setInitialVelocity(new Vector3f(0, 7, 0));
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setVelocityVariation(1f);
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setImagesX(2);
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setImagesY(2);
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        mat.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        effect.setMaterial(mat);
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected void createGhostObject() {
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ghostObject = new PhysicsGhostObject(new SphereCollisionShape(explosionRadius));
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void collision(PhysicsCollisionEvent event) {
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (space == null) {
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (event.getObjectA() == this || event.getObjectB() == this) {
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            space.add(ghostObject);
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            ghostObject.setPhysicsLocation(getPhysicsLocation(vector));
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            space.addTickListener(this);
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (effect != null && spatial.getParent() != null) {
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                curTime = 0;
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                effect.setLocalTranslation(spatial.getLocalTranslation());
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                spatial.getParent().attachChild(effect);
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                effect.emitAllParticles();
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            space.remove(this);
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            spatial.removeFromParent();
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void prePhysicsTick(PhysicsSpace space, float f) {
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        space.removeCollisionListener(this);
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void physicsTick(PhysicsSpace space, float f) {
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //get all overlapping objects and apply impulse to them
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Iterator<PhysicsCollisionObject> it = ghostObject.getOverlappingObjects().iterator(); it.hasNext();) {
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            PhysicsCollisionObject physicsCollisionObject = it.next();
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (physicsCollisionObject instanceof PhysicsRigidBody) {
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                PhysicsRigidBody rBody = (PhysicsRigidBody) physicsCollisionObject;
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                rBody.getPhysicsLocation(vector2);
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                vector2.subtractLocal(vector);
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                float force = explosionRadius - vector2.length();
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                force *= forceFactor;
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                force = force > 0 ? force : 0;
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                vector2.normalizeLocal();
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                vector2.multLocal(force);
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                ((PhysicsRigidBody) physicsCollisionObject).applyImpulse(vector2, Vector3f.ZERO);
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        space.removeTickListener(this);
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        space.remove(ghostObject);
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void update(float tpf) {
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super.update(tpf);
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if(enabled){
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            timer+=tpf;
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if(timer>maxTime){
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if(spatial.getParent()!=null){
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    space.removeCollisionListener(this);
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    space.remove(this);
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    spatial.removeFromParent();
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (enabled && curTime >= 0) {
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            curTime += tpf;
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (curTime > fxTime) {
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                curTime = -1;
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                effect.removeFromParent();
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the explosionRadius
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getExplosionRadius() {
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return explosionRadius;
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param explosionRadius the explosionRadius to set
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setExplosionRadius(float explosionRadius) {
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.explosionRadius = explosionRadius;
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        createGhostObject();
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getForceFactor() {
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return forceFactor;
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setForceFactor(float forceFactor) {
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.forceFactor = forceFactor;
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void read(JmeImporter im) throws IOException {
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        throw new UnsupportedOperationException("Reading not supported.");
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void write(JmeExporter ex) throws IOException {
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        throw new UnsupportedOperationException("Saving not supported.");
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
190