API Docs for:
Show:

File: physics\ForceGenerators.js


//=====Generic force generator=====

/**
 A generic force generator. It applies the specified force directly to the entity.
 @class ForceGenerator
 @constructor
 @param forceX {Number} The x component of the force vector.
 @param forceY {Number} The y component of the force vector.
 */
function ForceGenerator(forceX, forceY){
    this._forceVector = new Vector2D(forceX, forceY);
}

/**
 @method applyForce
 @param entity {Entity} The entity this force should be applied to. It's required that the entity has the Movable component.
 */
ForceGenerator.prototype.applyForce = function(entity){
    var movableComponent = entity.get(Movable);
    
    if(!movableComponent){
        return;
    }
    
    movableComponent.applyForce(this._forceVector);
};

/**
 Retrieves the force vector.
 @method getForceVector
 @param vector {Vector2D} The vector to which the force vector will be copied.
 */
ForceGenerator.prototype.getForceVector = function(vector){
    vector.x = this._forceVector.x;
    vector.y = this._forceVector.y;
};

/**
 Sets new values for the force vector.
 @method setForceVector
 @param forceX {Number} The x component of the new force vector.
 @param forceY {Number} The y component of the new force vector.
 */
ForceGenerator.prototype.setForceVector = function(forceX, forceY){
    this._forceVector.x = forceX;
    this._forceVector.y = forceY;
};

//=====Gravity force generator=====

/**
 This generator applies a force to the entity that gives it the specified acceleration.
 @class GravityGenerator
 @constructor
 @param gravityX {Number} The x component of the acceleration vector.
 @param gravityY {Number} The y component of the acceleration vector.
 */
function GravityGenerator(gravityX, gravityY){
    this._gravityVector = new Vector2D(gravityX, gravityY);
}

/**
 @method applyForce
 @param entity {Entity} The entity this force should be applied to. It's required that the entity has the Movable component.
 */
GravityGenerator.prototype.applyForce = (function(){
    
    var force = new Vector2D();

    return function(entity){
        var movableComponent = entity.get(Movable);
        
        if(!movableComponent){
            return;
        }
        
        //If the entity's mass is infinite, then if either of the gravity vector's components is 0,
        //the multiplication by mass will result in NaN (0 * infinity = NaN).
        //To avoid this, simply don't apply the force if mass is infinite.
        if(movableComponent.getMass() !== Number.POSITIVE_INFINITY){
            this._gravityVector.multiplied(movableComponent.getMass(), force)
            movableComponent.applyForce(force);
        }
    };
})();

/**
 Retrieves the gravity acceleration vector.
 @method getGravityVector
 @param vector {Vector2D} The vector to which the gravity vector will be copied.
 */
GravityGenerator.prototype.getGravityVector = function(vector){
    vector.x = this._gravityVector.x;
    vector.y = this._gravityVector.y;
};

/**
 Sets new values for the gravity acceleration vector.
 @method setGravityVector
 @param gravityX {Number} The x component of the new acceleration vector.
 @param gravityY {Number} The y component of the new acceleration vector.
 */
GravityGenerator.prototype.setGravityVector = function(gravityX, gravityY){
    this._gravityVector.x = gravityX;
    this._gravityVector.y = gravityY;
};

//=====Anchored spring force generator=====

/**
 This generator simulates a spring with one end attached to a fixed point in space and the other to an entity.
 @class AnchoredSpringGenerator
 @constructor
 @param anchorPointX {Number} The x component of the fixed point.
 @param anchorPointY {Number} The y component of the fixed point.
 @param restLength {Number}
 @param stiffness {Number}
 */
function AnchoredSpringGenerator(anchorPointX, anchorPointY, restLength, stiffness){        
    this._anchorPoint = new Vector2D(anchorPointX, anchorPointY);
    this._restLength = restLength || 0;
    this._stiffness = stiffness || 0;
}

/**
 @method applyForce
 @param entity {Entity} The entity the spring force should be applied to. It's required that the entity has the Movable and Position components.
 */
AnchoredSpringGenerator.prototype.applyForce = (function(){

    var force = new Vector2D();

    return function(entity){
        var positionComponent = entity.get(Position),
            movableComponent = entity.get(Movable);
            
        if( !(positionComponent && movableComponent) ){
            return;
        }
        
        this._anchorPoint.subtracted(positionComponent, force);
        var distance = force.magnitude();
            
        //Don't do anything if the beginning and the end of the spring are right on top of each other.
        if(distance === 0){
            return;
        }
        
        //Use the already calculated distance to normalize the force vector.
        force.divide(distance);
        force.multiply((distance - this._restLength) * this._stiffness);
        
        movableComponent.applyForce(force);
    };
})();

/**
 Retrieves the position of the anchor point.
 @method getAnchorPoint
 @param vector {Vector2D} The vector to which the anchor point's position will be copied.
 */
AnchoredSpringGenerator.prototype.getAnchorPoint = function(vector){
    vector.x = this._anchorPoint.x;
    vector.y = this._anchorPoint.y;
};

/**
 Sets a new position for the anchor point.
 @method setAnchorPoint
 @param anchorPointX {Number} The x component of the new anchor point.
 @param anchorPointY {Number} The y component of the new anchor point.
 */
AnchoredSpringGenerator.prototype.setAnchorPoint = function(anchorPointX, anchorPointY){
    this._anchorPoint.x = anchorPointX;
    this._anchorPoint.y = anchorPointY;
};

/**
 @method getRestLength
 @return {Number}
 */
AnchoredSpringGenerator.prototype.getRestLength = function(){
    return this._restLength;
};

/**
 @method setRestLength
 @param restLength {Number}
 */
AnchoredSpringGenerator.prototype.setRestLength = function(restLength){
    this._restLength = restLength;
};

/**
 @method getStiffness
 @return {Number}
 */
AnchoredSpringGenerator.prototype.getStiffness = function(){
    return this._stiffness;
};

/**
 @method setStiffness
 @param stiffness {Number}
 */
AnchoredSpringGenerator.prototype.setStiffness = function(stiffness){
    this._stiffness = stiffness;
};

//=====Spring force generator that applies the force to both ends=====

/**
 This generator simulates a spring with both ends attached to entities.
 @class SpringGenerator
 @constructor
 @param entity {Entity} This entity should have the Position and Movable components.
 @param restLength {Number}
 @param stiffness {Number}
 */
function SpringGenerator(entity, restLength, stiffness){
    this._entity = entity;
    this._restLength = restLength || 0;
    this._stiffness = stiffness || 0;
}

/**
 @method applyForce
 @param entity {Entity} The other entity the spring force should be applied to. This entity should have the Position and Movable components.
 */
SpringGenerator.prototype.applyForce = (function(){
    
    var force = new Vector2D();

    return function(entity){
        
        if(!this._entity){
            return;
        }
        
        var positionA = this._entity.get(Position),
            movableA = this._entity.get(Movable),
            positionB = entity.get(Position),
            movableB = entity.get(Movable);
            
        if(!(positionA && movableA && positionB && movableB)){
            return;
        }
        
        positionA.subtracted(positionB, force);
        var distance = force.magnitude();
            
        //Don't do anything if the beginning and the end of the spring are right on top of each other.
        if(distance === 0){
            return;
        }
        
        //Use the already calculated distance to normalize the force vector.
        force.divide(distance);
        force.multiply((distance - this._restLength) * this._stiffness);
        
        movableB.applyForce(force);
        movableA.applyForce(force.invert());
    };
    
})();

/**
 @method setEntity
 @param entity {Entity} This entity should have the Position and Movable components.
 */
SpringGenerator.prototype.setEntity = function(entity){
    this._entity = entity;
};

/**
 @method getEntity
 @return {Entity}
 */
SpringGenerator.prototype.getEntity = function(){
    return this._entity;
};

/**
 @method getRestLength
 @return {Number}
 */
SpringGenerator.prototype.getRestLength = function(){
    return this._restLength;
};

/**
 @method setRestLength
 @param restLength {Number}
 */
SpringGenerator.prototype.setRestLength = function(restLength){
    this._restLength = restLength;
};

/**
 @method getStiffness
 @return {Number}
 */
SpringGenerator.prototype.getStiffness = function(){
    return this._stiffness;
};

/**
 @method setStiffness
 @param stiffness {Number}
 */
SpringGenerator.prototype.setStiffness = function(stiffness){
    this._stiffness = stiffness;
};

//=====Drag force generator=====

/**
 This generator simulates the force of drag.
 @class DragGenerator
 @constructor
 */
function DragGenerator(){
    
}

/**
 @method applyForce
 @param entity {Entity} The entity to which the drag should be applied. It's required that the entity has the Movable component.
 */
DragGenerator.prototype.applyForce = (function(){

    var force = new Vector2D();

    return function(entity){
        var movableComponent = entity.get(Movable);
        
        if(!movableComponent){
            return;
        }
        
        movableComponent.getVelocity(force);
        force.multiply(-movableComponent.getDragCoefficient());
        movableComponent.applyForce(force);
    };
})();