package com.bitwaffle.spaceguts.entities;
import org.lwjgl.util.vector.Quaternion;
import org.lwjgl.util.vector.Vector3f;
import com.bitwaffle.spaceout.entities.player.Backpack;
import com.bulletphysics.collision.dispatch.CollisionObject;
import com.bulletphysics.collision.shapes.CollisionShape;
/**
* An item that can be added to the player's inventory.
* Whenever something that can pick this up gets near it, it should use the
* {@code setFollowing} method so that the pickup gravitates towards whatever is trying to
* pick it up.
* The pickup will follow whatever it's set to as long as the {@code following} is not null.
* If you want a pickup to stop following, just set {@code following} to null.
*
* @author TranquilMarmot
*/
public abstract class Pickup extends DynamicEntity{
/** What this pickup is gravitating towards */
protected DynamicEntity following;
/** How far this pickup can be grabbed from */
private float pickupDistance;
/** How fast the pickup gravitates towards what it's following */
private float pickupSpeed = 1.8f;
/** Inventory to add item to when it gets picked up */
private Backpack destinationInventory;
/** Used to increase speed over time while following */
float timeFollowing;
/**
* Pickup constructor
* @param location Location of pickup
* @param rotation Rotation of pickup
* @param shape Shape to use for pickup
* @param mass Mass of pickup
* @param restitution Resitution of pickup
* @param collisionGroup From {@link CollisionTypes}
* @param collidesWith From {@link CollisionTypes}
*/
public Pickup(Vector3f location, Quaternion rotation,
CollisionShape shape, float mass, float restitution,
short collisionGroup, short collidesWith) {
super(location, rotation, shape, mass, restitution, collisionGroup,
collidesWith);
// so the diamonds don't deactivate at the wrong times
this.rigidBody.setActivationState(CollisionObject.ISLAND_SLEEPING);
}
@Override
/**
* Update this pickup (anything extending this class should call super.update(timeStep))
*/
public void update(float timeStep){
if(following != null)
gravitateTowards(timeStep);
}
/**
* @param inventory Pick up the inventory item and add it to an Inventory
*/
public void pickup(Backpack inventory){
inventory.addInventoryItem(this);
removeFlag = true;
}
/**
* Sets what a pickup is following
* @param toFollow New entity to follow
* @param pickupDistance How far away the pickup can be picked up from
* @param destinationInventory Inventory to place pickup in when it is picked up
*/
public void setFollowing(DynamicEntity toFollow, float pickupDistance, Backpack destinationInventory){
this.following = toFollow;
this.pickupDistance = pickupDistance;
this.destinationInventory = destinationInventory;
}
/**
* Gravitates towards whatever the pickup is following
* @param timeStep Time since last update
*/
private void gravitateTowards(float timeStep){
// check if we're close enough to pick up
if(Entities.distance(this.location, following.location) <= pickupDistance){
this.pickup(destinationInventory);
} else{
timeFollowing += timeStep;
// find the difference between this's location and following's location then negate it to go towards it
Vector3f subtract = new Vector3f();
Vector3f.sub(this.location, following.location, subtract);
subtract.negate(subtract);
javax.vecmath.Vector3f linvec = new javax.vecmath.Vector3f();
this.following.rigidBody.getLinearVelocity(linvec);
// add linear velocity so that the pickup doesn't trail behind
float dx = (subtract.x * pickupSpeed) + linvec.x;
float dy = (subtract.y * pickupSpeed) + linvec.y;
float dz = (subtract.z * pickupSpeed) + linvec.z;
// set linear velocity to go towards following
this.rigidBody.setLinearVelocity(new javax.vecmath.Vector3f(dx, dy, dz));
// give it a good twirl
this.rigidBody.setAngularVelocity(new javax.vecmath.Vector3f(subtract.x, subtract.y, subtract.z));
}
}
}