All files / physics/worker effects.js

0% Statements 0/47
0% Branches 0/5
0% Functions 0/7
0% Lines 0/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81                                                                                                                                                                 
import { EXPLOSION_SIZES, EXPLOSION_STRENGTHS } from "../constants";
import world from "./world";
 
export const createGhostCollider = (radius, position) => {
    const ghostCollider = new Ammo.btGhostObject();
    const transform = new Ammo.btTransform();
 
    ghostCollider.setCollisionShape(new Ammo.btSphereShape(radius));
    ghostCollider.getWorldTransform(transform);
 
    transform.setIdentity();
    transform.setOrigin(position);
    transform.setRotation(new Ammo.btQuaternion(0, 0, 0, 1));
 
    ghostCollider.setWorldTransform(transform);
 
    return { ghostCollider, transform };
};
 
export const forEachGhostCollision = (ghostCollider, forEachCallback = () => {}) => {
    const collisions = ghostCollider.getNumOverlappingObjects();
    for (let i=0; i<collisions; i++) {
        const object = Ammo.castObject(ghostCollider.getOverlappingObject(i), Ammo.btRigidBody);
        const transform = new Ammo.btTransform();
 
        object.getWorldTransform(transform);
        forEachCallback(object, transform, i);
 
        Ammo.destroy(transform);
    }
}
 
export const getExplosionPosition = (uuid, position) => {
    let explosionPosition = position;
    if (!explosionPosition) {
        const { body } = world.getElement(uuid);
        const motionState = body.getMotionState();
        const transform = new Ammo.btTransform();
 
        motionState.getWorldTransform(transform);
        explosionPosition = transform.getOrigin();
    }
 
    return explosionPosition;
};
 
export const getExplosionImpulse = (position, explosionPosition, strength) => {
    const distance = position.op_sub(explosionPosition);
    distance.normalize();
    const impulse = distance.op_mul(strength);
 
    impulse.setY(impulse.y() + strength);
 
    return impulse;
}
 
export const createExplosion = ({
    uuid,
    position,
    radius = EXPLOSION_SIZES.SMALL,
    strength = EXPLOSION_STRENGTHS.MEDIUM
}) => {
    try {
        const explosionPosition = getExplosionPosition(uuid, position);
        const { ghostCollider, transform } = createGhostCollider(radius, explosionPosition);
 
        world.addCollisionObject(ghostCollider);
 
        forEachGhostCollision(ghostCollider, (object, objectTransform) => {
            const origin = objectTransform.getOrigin();
            object.activate(true);
            object.applyCentralImpulse(getExplosionImpulse(origin, explosionPosition, strength));
        });
 
        world.getDynamicsWorld().removeCollisionObject(ghostCollider);
        Ammo.destroy(ghostCollider);
        Ammo.destroy(transform);
    } catch(e) {
        console.log(e);
    }
}