// Attraction // Daniel Shiffman // A class to describe a thing in our world, has vectors for location, velocity, and acceleration // Also includes scalar values for mass, maximum velocity, and elasticity class Thing { Vector3D loc; Vector3D vel; Vector3D acc; float mass; float max_vel; float bounce = 5.0f; // How "elastic" is the object float G; // Universal gravitational constant float timer; boolean eating = false; boolean ate = false; boolean dead = false; float nw; float nh; Thing(Vector3D a, Vector3D v, Vector3D l, float m_) { acc = a.copy(); vel = v.copy(); loc = l.copy(); mass = m_; max_vel = 5.0f; G = 0.9f; timer = 0; nw = mass + mass; nh = mass + mass/6; } Vector3D getLoc() { return loc; } Vector3D getVel() { return vel; } float getMass() { return mass; } float getX(){ return loc.x; } float getY(){ return loc.y; } void addMass(float foodMass){ mass += foodMass; max_vel += foodMass/50; nw = mass + mass; nh = mass + mass/6; } Vector3D calcGravForce(Thing t) { Vector3D dir = Vector3D.sub(t.getLoc(), loc); // Calculate direction of force float d = dir.magnitude(); // Distance between objects d = constrain(d,200.0f,100.0f); // Limiting the distance to eliminate "extreme" results for very close or very far objects dir.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction) float force = (G * mass * t.getMass()) / (d * d); // Calculate gravitional force magnitude dir.mult(force); // Get force vector --> magnitude * direction return dir; } Vector3D calcRepForce(Thing t) { Vector3D dir = Vector3D.sub(loc, t.getLoc()); // Calculate direction of force float d = dir.magnitude(); // Distance between objects d = constrain(d,300.0f,100.0f); // Limiting the distance to eliminate "extreme" results for very close or very far objects dir.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction) float force = (G * mass * t.getMass()) / (d * d); // Calculate gravitional force magnitude dir.mult(force); // Get force vector --> magnitude * direction return dir; } void add_force(Vector3D force) { force.div(mass); acc.add(force); if (showVectors) { drawVector(force,loc,1000); } } void setAcc(Vector3D v) { acc = v.copy(); } // Main method to operate object void go() { update(); render(); } void stop() { px = loc.x; py = loc.y; vel.add(new Vector3D(0,0,0)); vel.limit(0); loc.add(new Vector3D(0,0,0)); acc.setXYZ(0.0,0.0,0.0); } // Method to update location void update() { if (dead){ stop(); } else{ px = loc.x; py = loc.y; vel.add(acc); vel.limit(max_vel); loc.add(vel); acc.setXYZ(0.0,0.0,0.0); } } // Method to display void render() { ellipseMode(CENTER); noStroke(); xoff += 0.5; yoff += 0.5; nw = mass + mass; nh = mass + mass/6; noStroke(); //fill(random(0,50),random(0,50),random(150,255)); if (dead){ nw = mass; nh = mass; fill(50,50,100); ellipse(loc.x,loc.y,nw,nh); fill(255); ellipse(loc.x+nw/2, loc.y,noise(xoff) * nw/3 + nw/3,noise(yoff) * nh/4 + nh/4); eating = false; ate = false; } else{ fill(noise(xoff)*20+50,noise(xoff)*20+50,noise(xoff)*100+200); ellipse(loc.x,loc.y,nw,nh); //fill(random(0,150),random(100,250),random(200,255)); fill(noise(xoff)*20+150,noise(xoff)*50+175,noise(xoff)*20+225); if(loc.x < px){ ellipse(loc.x+nw/2, loc.y,noise(xoff) * nw/3 + nw/3,noise(yoff) * nh/4 + nh/4); } else{ ellipse(loc.x-nw/2, loc.y,noise(xoff) * nw/3 + nw/3,noise(yoff) * nh/4 + nh/4); } if(eating){ nw = mass + mass; nh = mass + mass/6; //println("eating"); //fill(200,10,10); stroke(0,200,200); strokeWeight(3); noFill(); ellipse(loc.x,loc.y,nw,nh); if (timer%10 == 0){ ate = true; eating = false; } } eating = false; ate = false; } timer++; } void eating() { eating = true; } boolean ate(){ return ate; } void die(){ dead = true; } boolean dead(){ return dead; } float getW(){ nw = mass + mass; return nw; } float getH(){ nh = mass + mass/6; return nh; } }