/*

	This is an object in our simulation environment, with a location,
	velocity and acceleration. Our object also has a mass, which effects
	the forces acting upon the object.
	
*/

public class SimObject {

	Vector2D loc;
	Vector2D vel;
	Vector2D accel;
	
	float mass;
	float max_velocity;
	float bounciness;
	float objectSize;
	
	public SimObject(Vector2D loc_, Vector2D vel_, Vector2D accel_, float mass_) {
	
		// Save the properties we've been constructed with
		loc = loc_;
		vel = vel_;
		accel = accel_;
		mass = mass_;
		
		// set some basic defaults for our other properties
		max_velocity = 20.0f;
		bounciness = 0.98f;
		objectSize = 20.0f;
		
	}
	
	public Vector2D getLocation() {
		return loc;
	}
	
	public void setLocation(Vector2D v) {
		loc = v;
	}
	
	public Vector2D getVelocity() {
		return vel;
	}
	
	public void setVelocity(Vector2D v) {
		vel = v;
	}
	
	public Vector2D getAcceleration() {
		return accel;
	}
	
	public void setAcceleration(Vector2D v) {
		accel = v;
	}
	
	public float getMass() {
		return mass;
	}
	
	public void setMass(float m_) {
		mass = m_;
	}
	
	public void addForce(Vector2D v) {
	
		// scale the force by our mass
		v = v.divide(mass);
		
		// add the force to our acceleration
		accel = accel.add(v);
		
	}

	public void simulate() {
		
		// Simulate a step in time for our object
		update();
		contain();
		display();
		
	}
	
	public void update() {
	
		// update our values for velocity and
		// location to reflect our movement
		
		// add acceleration to velocity
		vel = vel.add(accel);
		
		// limit our velocity to a maximum speed
		vel.limit(max_velocity);
		
		// move our object according to our velocity
		loc = loc.add(vel);
		
		// reset the accerlation forces to zero in
		// preperation for the next step in time
		accel.setXY(0.0f, 0.0f);
	}
	
	public void contain() {
	
		// We want to contain our object to the confines
		// of the screen, so here we check to make
		// sure we're within the screen bounds. If we're
		// at the edge of the screen, we "bounce" back
		
		// Contain vertical movement
		if ( (loc.getY() > height - objectSize / 2) || (loc.getY() < objectSize / 2) ) {
		
                        // flip our velocity
                        vel.setY(bounciness * -1.0f * vel.getY());
                        
                        // move our position
                        if (loc.getY() > (height / 2) ) {
                          loc.setY(height - objectSize / 2);
			} else {
                          loc.setY(objectSize / 2);
                        }
			
		}

		// Contain horizontal movement
		if ( (loc.getX() > width - objectSize / 2) || (loc.getX() < objectSize / 2) ) {
		
			vel.setX(bounciness * -1.0f * vel.getX());
			
		}
	}
	
	public void display() {
	
		// display our object on screen
		rectMode(CENTER);
		noStroke();
		fill(32, 64, 128, 200);
		rect(loc.getX(), loc.getY(), objectSize, objectSize);
		
	}
}
