// 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; boolean mating = false; float nw; float nh; float hunger; DNA dna; float sexGene; String sex; float minMass; float hornyGene; float hornyFactor; boolean reproduce = false; boolean justMated = false; float foodInc; float foodGene; float deathRate; float healthGene; float maxMass; Thing(Vector3D a, Vector3D v, Vector3D l, float m_, DNA dna_) { acc = a.copy(); vel = v.copy(); loc = l.copy(); mass = m_; dna = dna_; G = 0.9f; timer = 0; nw = mass + mass; nh = mass + mass/6; hunger = hunger_; minMass = minMass_; sexGene = dna.getGene(0); if (sexGene > 0.5) sex = "male"; else sex = "female"; hornyGene = dna.getGene(1); hornyFactor = hornyFactor_ * (1+hornyGene); hunger = hunger_ * (1-hornyGene); foodInc = foodInc_; max_vel = max_vel_; deathRate = deathRate_; maxMass = maxMass_; /* foodGene = dna.getGene(2); foodInc = foodInc_ * (1+ foodGene); max_vel = max_vel_ * (1-foodGene); healthGene = dna.getGene(3); deathRate = deathRate_ * (1+healthGene); maxMass = maxMass_ * (1-healthGene); */ } float get_maxMass(){ return maxMass; } DNA getDNA(){ return dna; } float getHunger(){ return hunger; } Vector3D getLoc() { return loc; } Vector3D getVel() { return vel; } float getMass() { return mass; } float getX(){ return loc.x; } float getY(){ return loc.y; } String getSex(){ return sex; } void addMass(){ mass += foodInc; max_vel -= foodInc/100; } void remMass(){ mass -= deathRate; } Vector3D calcGravForce(Thing t, String attractionType) { Vector3D dir = Vector3D.sub(t.getLoc(), loc); // Calculate direction of force float d = dir.magnitude(); // Distance between objects d = constrain(d,1,50); // 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 * hornyFactor * t.getMass()) / (d * d); // Calculate gravitional force magnitude dir.mult(force); // Get force vector --> magnitude * direction return dir; } void reduce_vel(){ max_vel -= 0.5; } 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,1,dMin); // 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 * repForce * 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() { mass -= deathRate; px = loc.x; py = loc.y; vel.add(acc); vel.limit(max_vel); loc.add(vel); acc.setXYZ(0.0,0.0,0.0); //println("mass "+mass); } // Method to display void render() { ellipseMode(CENTER); noStroke(); float age = 255*(mass/maxMass); if (dead){ age = 0; } else{ if (sex == "male"){ // Draw a triangle rotated in the direction of velocity float theta = vel.heading2D() + radians(135); stroke(10,10,255); fill(100,100,255,age); pushMatrix(); translate(loc.x,loc.y); rotate(theta); beginShape(); vertex(0, 0); vertex(mass, 0); vertex(mass/4, mass/4); vertex(mass, mass); vertex(mass/4, mass/4); vertex(0, mass); vertex(0, 0); endShape(); ellipse(mass,mass,mass,mass); popMatrix(); } else{ // Draw a triangle rotated in the direction of velocity float theta = vel.heading2D() + radians(135); stroke(200,50,50); fill(255,100,100); pushMatrix(); translate(loc.x,loc.y); rotate(theta); beginShape(); vertex(mass/4, 0); vertex(mass/2, mass/4); vertex(mass-mass/4, 0); vertex(mass, mass/4); vertex(mass-mass/4, mass/2); vertex(mass, mass-mass/4); vertex(mass-mass/4, mass); vertex(mass/2, mass-mass/4); vertex(mass/4, mass); vertex(0, mass-mass/4); vertex(mass/4, mass/2); vertex(0, mass/4); vertex(mass/4, 0); endShape(); ellipse(mass*1.3,mass*1.3,mass*1.3,mass*1.3); popMatrix(); } } } void set_mating(boolean r) { mating = r; } boolean get_mating() { //if (mating) { println("I'm mating");} return mating; } void set_justMated(boolean r){ justMated = r; } boolean get_justMated(){ return justMated; } 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; } void set_reproduce(boolean r){ reproduce = r; } boolean get_reproduce(){ return reproduce; } }