Initial Commit
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Chain.
|
||||
*
|
||||
* One mass is attached to the mouse position and the other
|
||||
* is attached the position of the other mass. The gravity
|
||||
* in the environment pulls down on both.
|
||||
*/
|
||||
|
||||
|
||||
Spring2D s1, s2;
|
||||
|
||||
float gravity = 9.0;
|
||||
float mass = 2.0;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
fill(255, 126);
|
||||
// Inputs: x, y, mass, gravity
|
||||
s1 = new Spring2D(0.0, width/2, mass, gravity);
|
||||
s2 = new Spring2D(0.0, width/2, mass, gravity);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
s1.update(mouseX, mouseY);
|
||||
s1.display(mouseX, mouseY);
|
||||
s2.update(s1.x, s1.y);
|
||||
s2.display(s1.x, s1.y);
|
||||
}
|
||||
|
||||
class Spring2D {
|
||||
float vx, vy; // The x- and y-axis velocities
|
||||
float x, y; // The x- and y-coordinates
|
||||
float gravity;
|
||||
float mass;
|
||||
float radius = 30;
|
||||
float stiffness = 0.2;
|
||||
float damping = 0.7;
|
||||
|
||||
Spring2D(float xpos, float ypos, float m, float g) {
|
||||
x = xpos;
|
||||
y = ypos;
|
||||
mass = m;
|
||||
gravity = g;
|
||||
}
|
||||
|
||||
void update(float targetX, float targetY) {
|
||||
float forceX = (targetX - x) * stiffness;
|
||||
float ax = forceX / mass;
|
||||
vx = damping * (vx + ax);
|
||||
x += vx;
|
||||
float forceY = (targetY - y) * stiffness;
|
||||
forceY += gravity;
|
||||
float ay = forceY / mass;
|
||||
vy = damping * (vy + ay);
|
||||
y += vy;
|
||||
}
|
||||
|
||||
void display(float nx, float ny) {
|
||||
noStroke();
|
||||
ellipse(x, y, radius*2, radius*2);
|
||||
stroke(255);
|
||||
line(x, y, nx, ny);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
// The Boid class
|
||||
|
||||
class Boid {
|
||||
|
||||
PVector position;
|
||||
PVector velocity;
|
||||
PVector acceleration;
|
||||
float r;
|
||||
float maxforce; // Maximum steering force
|
||||
float maxspeed; // Maximum speed
|
||||
|
||||
Boid(float x, float y) {
|
||||
acceleration = new PVector(0, 0);
|
||||
|
||||
// This is a new PVector method not yet implemented in JS
|
||||
// velocity = PVector.random2D();
|
||||
|
||||
// Leaving the code temporarily this way so that this example runs in JS
|
||||
float angle = random(TWO_PI);
|
||||
velocity = new PVector(cos(angle), sin(angle));
|
||||
|
||||
position = new PVector(x, y);
|
||||
r = 2.0;
|
||||
maxspeed = 2;
|
||||
maxforce = 0.03;
|
||||
}
|
||||
|
||||
void run(ArrayList<Boid> boids) {
|
||||
flock(boids);
|
||||
update();
|
||||
borders();
|
||||
render();
|
||||
}
|
||||
|
||||
void applyForce(PVector force) {
|
||||
// We could add mass here if we want A = F / M
|
||||
acceleration.add(force);
|
||||
}
|
||||
|
||||
// We accumulate a new acceleration each time based on three rules
|
||||
void flock(ArrayList<Boid> boids) {
|
||||
PVector sep = separate(boids); // Separation
|
||||
PVector ali = align(boids); // Alignment
|
||||
PVector coh = cohesion(boids); // Cohesion
|
||||
// Arbitrarily weight these forces
|
||||
sep.mult(1.5);
|
||||
ali.mult(1.0);
|
||||
coh.mult(1.0);
|
||||
// Add the force vectors to acceleration
|
||||
applyForce(sep);
|
||||
applyForce(ali);
|
||||
applyForce(coh);
|
||||
}
|
||||
|
||||
// Method to update position
|
||||
void update() {
|
||||
// Update velocity
|
||||
velocity.add(acceleration);
|
||||
// Limit speed
|
||||
velocity.limit(maxspeed);
|
||||
position.add(velocity);
|
||||
// Reset accelertion to 0 each cycle
|
||||
acceleration.mult(0);
|
||||
}
|
||||
|
||||
// A method that calculates and applies a steering force towards a target
|
||||
// STEER = DESIRED MINUS VELOCITY
|
||||
PVector seek(PVector target) {
|
||||
PVector desired = PVector.sub(target, position); // A vector pointing from the position to the target
|
||||
// Scale to maximum speed
|
||||
desired.normalize();
|
||||
desired.mult(maxspeed);
|
||||
|
||||
// Above two lines of code below could be condensed with new PVector setMag() method
|
||||
// Not using this method until Processing.js catches up
|
||||
// desired.setMag(maxspeed);
|
||||
|
||||
// Steering = Desired minus Velocity
|
||||
PVector steer = PVector.sub(desired, velocity);
|
||||
steer.limit(maxforce); // Limit to maximum steering force
|
||||
return steer;
|
||||
}
|
||||
|
||||
void render() {
|
||||
// Draw a triangle rotated in the direction of velocity
|
||||
float theta = velocity.heading2D() + radians(90);
|
||||
// heading2D() above is now heading() but leaving old syntax until Processing.js catches up
|
||||
|
||||
fill(200, 100);
|
||||
stroke(255);
|
||||
pushMatrix();
|
||||
translate(position.x, position.y);
|
||||
rotate(theta);
|
||||
beginShape(TRIANGLES);
|
||||
vertex(0, -r*2);
|
||||
vertex(-r, r*2);
|
||||
vertex(r, r*2);
|
||||
endShape();
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
// Wraparound
|
||||
void borders() {
|
||||
if (position.x < -r) position.x = width+r;
|
||||
if (position.y < -r) position.y = height+r;
|
||||
if (position.x > width+r) position.x = -r;
|
||||
if (position.y > height+r) position.y = -r;
|
||||
}
|
||||
|
||||
// Separation
|
||||
// Method checks for nearby boids and steers away
|
||||
PVector separate (ArrayList<Boid> boids) {
|
||||
float desiredseparation = 25.0f;
|
||||
PVector steer = new PVector(0, 0, 0);
|
||||
int count = 0;
|
||||
// For every boid in the system, check if it's too close
|
||||
for (Boid other : boids) {
|
||||
float d = PVector.dist(position, other.position);
|
||||
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
|
||||
if ((d > 0) && (d < desiredseparation)) {
|
||||
// Calculate vector pointing away from neighbor
|
||||
PVector diff = PVector.sub(position, other.position);
|
||||
diff.normalize();
|
||||
diff.div(d); // Weight by distance
|
||||
steer.add(diff);
|
||||
count++; // Keep track of how many
|
||||
}
|
||||
}
|
||||
// Average -- divide by how many
|
||||
if (count > 0) {
|
||||
steer.div((float)count);
|
||||
}
|
||||
|
||||
// As long as the vector is greater than 0
|
||||
if (steer.mag() > 0) {
|
||||
// First two lines of code below could be condensed with new PVector setMag() method
|
||||
// Not using this method until Processing.js catches up
|
||||
// steer.setMag(maxspeed);
|
||||
|
||||
// Implement Reynolds: Steering = Desired - Velocity
|
||||
steer.normalize();
|
||||
steer.mult(maxspeed);
|
||||
steer.sub(velocity);
|
||||
steer.limit(maxforce);
|
||||
}
|
||||
return steer;
|
||||
}
|
||||
|
||||
// Alignment
|
||||
// For every nearby boid in the system, calculate the average velocity
|
||||
PVector align (ArrayList<Boid> boids) {
|
||||
float neighbordist = 50;
|
||||
PVector sum = new PVector(0, 0);
|
||||
int count = 0;
|
||||
for (Boid other : boids) {
|
||||
float d = PVector.dist(position, other.position);
|
||||
if ((d > 0) && (d < neighbordist)) {
|
||||
sum.add(other.velocity);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
sum.div((float)count);
|
||||
// First two lines of code below could be condensed with new PVector setMag() method
|
||||
// Not using this method until Processing.js catches up
|
||||
// sum.setMag(maxspeed);
|
||||
|
||||
// Implement Reynolds: Steering = Desired - Velocity
|
||||
sum.normalize();
|
||||
sum.mult(maxspeed);
|
||||
PVector steer = PVector.sub(sum, velocity);
|
||||
steer.limit(maxforce);
|
||||
return steer;
|
||||
}
|
||||
else {
|
||||
return new PVector(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Cohesion
|
||||
// For the average position (i.e. center) of all nearby boids, calculate steering vector towards that position
|
||||
PVector cohesion (ArrayList<Boid> boids) {
|
||||
float neighbordist = 50;
|
||||
PVector sum = new PVector(0, 0); // Start with empty vector to accumulate all positions
|
||||
int count = 0;
|
||||
for (Boid other : boids) {
|
||||
float d = PVector.dist(position, other.position);
|
||||
if ((d > 0) && (d < neighbordist)) {
|
||||
sum.add(other.position); // Add position
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
sum.div(count);
|
||||
return seek(sum); // Steer towards the position
|
||||
}
|
||||
else {
|
||||
return new PVector(0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// The Flock (a list of Boid objects)
|
||||
|
||||
class Flock {
|
||||
ArrayList<Boid> boids; // An ArrayList for all the boids
|
||||
|
||||
Flock() {
|
||||
boids = new ArrayList<Boid>(); // Initialize the ArrayList
|
||||
}
|
||||
|
||||
void run() {
|
||||
for (Boid b : boids) {
|
||||
b.run(boids); // Passing the entire list of boids to each boid individually
|
||||
}
|
||||
}
|
||||
|
||||
void addBoid(Boid b) {
|
||||
boids.add(b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Flocking
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* An implementation of Craig Reynold's Boids program to simulate
|
||||
* the flocking behavior of birds. Each boid steers itself based on
|
||||
* rules of avoidance, alignment, and coherence.
|
||||
*
|
||||
* Click the mouse to add a new boid.
|
||||
*/
|
||||
|
||||
Flock flock;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
flock = new Flock();
|
||||
// Add an initial set of boids into the system
|
||||
for (int i = 0; i < 150; i++) {
|
||||
flock.addBoid(new Boid(width/2,height/2));
|
||||
}
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(50);
|
||||
flock.run();
|
||||
}
|
||||
|
||||
// Add a new boid into the System
|
||||
void mousePressed() {
|
||||
flock.addBoid(new Boid(mouseX,mouseY));
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Forces (Gravity and Fluid Resistence) with Vectors
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* Demonstration of multiple force acting on bodies (Mover class)
|
||||
* Bodies experience gravity continuously
|
||||
* Bodies experience fluid resistance when in "water"
|
||||
*
|
||||
* For the basics of working with PVector, see
|
||||
* http://processing.org/learning/pvector/
|
||||
* as well as examples in Topics/Vectors/
|
||||
*
|
||||
*/
|
||||
|
||||
// Five moving bodies
|
||||
Mover[] movers = new Mover[10];
|
||||
|
||||
// Liquid
|
||||
Liquid liquid;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
reset();
|
||||
// Create liquid object
|
||||
liquid = new Liquid(0, height/2, width, height/2, 0.1);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
|
||||
// Draw water
|
||||
liquid.display();
|
||||
|
||||
for (Mover mover : movers) {
|
||||
|
||||
// Is the Mover in the liquid?
|
||||
if (liquid.contains(mover)) {
|
||||
// Calculate drag force
|
||||
PVector drag = liquid.drag(mover);
|
||||
// Apply drag force to Mover
|
||||
mover.applyForce(drag);
|
||||
}
|
||||
|
||||
// Gravity is scaled by mass here!
|
||||
PVector gravity = new PVector(0, 0.1*mover.mass);
|
||||
// Apply gravity
|
||||
mover.applyForce(gravity);
|
||||
|
||||
// Update and display
|
||||
mover.update();
|
||||
mover.display();
|
||||
mover.checkEdges();
|
||||
}
|
||||
|
||||
fill(255);
|
||||
text("click mouse to reset", 10, 30);
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
reset();
|
||||
}
|
||||
|
||||
// Restart all the Mover objects randomly
|
||||
void reset() {
|
||||
for (int i = 0; i < movers.length; i++) {
|
||||
movers[i] = new Mover(random(0.5, 3), 40+i*70, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Forces (Gravity and Fluid Resistence) with Vectors
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* Demonstration of multiple force acting on bodies (Mover class)
|
||||
* Bodies experience gravity continuously
|
||||
* Bodies experience fluid resistance when in "water"
|
||||
*/
|
||||
|
||||
// Liquid class
|
||||
class Liquid {
|
||||
|
||||
|
||||
// Liquid is a rectangle
|
||||
float x, y, w, h;
|
||||
// Coefficient of drag
|
||||
float c;
|
||||
|
||||
Liquid(float x_, float y_, float w_, float h_, float c_) {
|
||||
x = x_;
|
||||
y = y_;
|
||||
w = w_;
|
||||
h = h_;
|
||||
c = c_;
|
||||
}
|
||||
|
||||
// Is the Mover in the Liquid?
|
||||
boolean contains(Mover m) {
|
||||
PVector l = m.position;
|
||||
if (l.x > x && l.x < x + w && l.y > y && l.y < y + h) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate drag force
|
||||
PVector drag(Mover m) {
|
||||
// Magnitude is coefficient * speed squared
|
||||
float speed = m.velocity.mag();
|
||||
float dragMagnitude = c * speed * speed;
|
||||
|
||||
// Direction is inverse of velocity
|
||||
PVector drag = m.velocity.copy();
|
||||
drag.mult(-1);
|
||||
|
||||
// Scale according to magnitude
|
||||
drag.setMag(dragMagnitude);
|
||||
return drag;
|
||||
}
|
||||
|
||||
void display() {
|
||||
noStroke();
|
||||
fill(127);
|
||||
rect(x, y, w, h);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Forces (Gravity and Fluid Resistence) with Vectors
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* Demonstration of multiple force acting on bodies (Mover class)
|
||||
* Bodies experience gravity continuously
|
||||
* Bodies experience fluid resistance when in "water"
|
||||
*/
|
||||
|
||||
|
||||
class Mover {
|
||||
|
||||
// position, velocity, and acceleration
|
||||
PVector position;
|
||||
PVector velocity;
|
||||
PVector acceleration;
|
||||
|
||||
// Mass is tied to size
|
||||
float mass;
|
||||
|
||||
Mover(float m, float x, float y) {
|
||||
mass = m;
|
||||
position = new PVector(x, y);
|
||||
velocity = new PVector(0, 0);
|
||||
acceleration = new PVector(0, 0);
|
||||
}
|
||||
|
||||
// Newton's 2nd law: F = M * A
|
||||
// or A = F / M
|
||||
void applyForce(PVector force) {
|
||||
// Divide by mass
|
||||
PVector f = PVector.div(force, mass);
|
||||
// Accumulate all forces in acceleration
|
||||
acceleration.add(f);
|
||||
}
|
||||
|
||||
void update() {
|
||||
|
||||
// Velocity changes according to acceleration
|
||||
velocity.add(acceleration);
|
||||
// position changes by velocity
|
||||
position.add(velocity);
|
||||
// We must clear acceleration each frame
|
||||
acceleration.mult(0);
|
||||
}
|
||||
|
||||
// Draw Mover
|
||||
void display() {
|
||||
stroke(255);
|
||||
strokeWeight(2);
|
||||
fill(255, 200);
|
||||
ellipse(position.x, position.y, mass*16, mass*16);
|
||||
}
|
||||
|
||||
// Bounce off bottom of window
|
||||
void checkEdges() {
|
||||
if (position.y > height) {
|
||||
velocity.y *= -0.9; // A little dampening when hitting the bottom
|
||||
position.y = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Gravitational Attraction (3D)
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* Simulating gravitational attraction
|
||||
* G ---> universal gravitational constant
|
||||
* m1 --> mass of object #1
|
||||
* m2 --> mass of object #2
|
||||
* d ---> distance between objects
|
||||
* F = (G*m1*m2)/(d*d)
|
||||
*
|
||||
* For the basics of working with PVector, see
|
||||
* http://processing.org/learning/pvector/
|
||||
* as well as examples in Topics/Vectors/
|
||||
*
|
||||
*/
|
||||
|
||||
// A bunch of planets
|
||||
Planet[] planets = new Planet[10];
|
||||
// One sun (note sun is not attracted to planets (violation of Newton's 3rd Law)
|
||||
Sun s;
|
||||
|
||||
// An angle to rotate around the scene
|
||||
float angle = 0;
|
||||
|
||||
void setup() {
|
||||
size(640, 360, P3D);
|
||||
// Some random planets
|
||||
for (int i = 0; i < planets.length; i++) {
|
||||
planets[i] = new Planet(random(0.1, 2), random(-width/2, width/2), random(-height/2, height/2), random(-100, 100));
|
||||
}
|
||||
// A single sun
|
||||
s = new Sun();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
// Setup the scene
|
||||
sphereDetail(8);
|
||||
lights();
|
||||
translate(width/2, height/2);
|
||||
rotateY(angle);
|
||||
|
||||
|
||||
// Display the Sun
|
||||
s.display();
|
||||
|
||||
// All the Planets
|
||||
for (Planet planet : planets) {
|
||||
// Sun attracts Planets
|
||||
PVector force = s.attract(planet);
|
||||
planet.applyForce(force);
|
||||
// Update and draw Planets
|
||||
planet.update();
|
||||
planet.display();
|
||||
}
|
||||
|
||||
// Rotate around the scene
|
||||
angle += 0.003;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Gravitational Attraction (3D)
|
||||
// Daniel Shiffman <http://www.shiffman.net>
|
||||
|
||||
// A class for an orbiting Planet
|
||||
|
||||
class Planet {
|
||||
|
||||
// Basic physics model (position, velocity, acceleration, mass)
|
||||
PVector position;
|
||||
PVector velocity;
|
||||
PVector acceleration;
|
||||
float mass;
|
||||
|
||||
Planet(float m, float x, float y, float z) {
|
||||
mass = m;
|
||||
position = new PVector(x, y, z);
|
||||
velocity = new PVector(1, 0); // Arbitrary starting velocity
|
||||
acceleration = new PVector(0, 0);
|
||||
}
|
||||
|
||||
// Newton's 2nd Law (F = M*A) applied
|
||||
void applyForce(PVector force) {
|
||||
PVector f = PVector.div(force, mass);
|
||||
acceleration.add(f);
|
||||
}
|
||||
|
||||
// Our motion algorithm (aka Euler Integration)
|
||||
void update() {
|
||||
velocity.add(acceleration); // Velocity changes according to acceleration
|
||||
position.add(velocity); // position changes according to velocity
|
||||
acceleration.mult(0);
|
||||
}
|
||||
|
||||
// Draw the Planet
|
||||
void display() {
|
||||
noStroke();
|
||||
fill(255);
|
||||
pushMatrix();
|
||||
translate(position.x, position.y, position.z);
|
||||
sphere(mass*8);
|
||||
popMatrix();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Gravitational Attraction (3D)
|
||||
// Daniel Shiffman <http://www.shiffman.net>
|
||||
|
||||
// A class for an attractive body in our world
|
||||
|
||||
class Sun {
|
||||
float mass; // Mass, tied to size
|
||||
PVector position; // position
|
||||
float G; // Universal gravitational constant (arbitrary value)
|
||||
|
||||
Sun() {
|
||||
position = new PVector(0, 0);
|
||||
mass = 20;
|
||||
G = 0.4;
|
||||
}
|
||||
|
||||
|
||||
PVector attract(Planet m) {
|
||||
PVector force = PVector.sub(position, m.position); // Calculate direction of force
|
||||
float d = force.mag(); // Distance between objects
|
||||
d = constrain(d, 5.0, 25.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
|
||||
float strength = (G * mass * m.mass) / (d * d); // Calculate gravitional force magnitude
|
||||
force.setMag(strength); // Get force vector --> magnitude * direction
|
||||
return force;
|
||||
}
|
||||
|
||||
// Draw Sun
|
||||
void display() {
|
||||
stroke(255);
|
||||
noFill();
|
||||
pushMatrix();
|
||||
translate(position.x, position.y, position.z);
|
||||
sphere(mass*2);
|
||||
popMatrix();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// A subclass of Particle
|
||||
|
||||
class CrazyParticle extends Particle {
|
||||
|
||||
// Just adding one new variable to a CrazyParticle
|
||||
// It inherits all other fields from "Particle", and we don't have to retype them!
|
||||
float theta;
|
||||
|
||||
// The CrazyParticle constructor can call the parent class (super class) constructor
|
||||
CrazyParticle(PVector l) {
|
||||
// "super" means do everything from the constructor in Particle
|
||||
super(l);
|
||||
// One more line of code to deal with the new variable, theta
|
||||
theta = 0.0;
|
||||
}
|
||||
|
||||
// Notice we don't have the method run() here; it is inherited from Particle
|
||||
|
||||
// This update() method overrides the parent class update() method
|
||||
void update() {
|
||||
super.update();
|
||||
// Increment rotation based on horizontal velocity
|
||||
float theta_vel = (velocity.x * velocity.mag()) / 10.0f;
|
||||
theta += theta_vel;
|
||||
}
|
||||
|
||||
// This display() method overrides the parent class display() method
|
||||
void display() {
|
||||
// Render the ellipse just like in a regular particle
|
||||
super.display();
|
||||
// Then add a rotating line
|
||||
pushMatrix();
|
||||
translate(position.x, position.y);
|
||||
rotate(theta);
|
||||
stroke(255, lifespan);
|
||||
line(0, 0, 25, 0);
|
||||
popMatrix();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Multiple Particle Systems
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* Click the mouse to generate a burst of particles
|
||||
* at mouse position.
|
||||
*
|
||||
* Each burst is one instance of a particle system
|
||||
* with Particles and CrazyParticles (a subclass of Particle)
|
||||
* Note use of Inheritance and Polymorphism here.
|
||||
*/
|
||||
|
||||
ArrayList<ParticleSystem> systems;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
systems = new ArrayList<ParticleSystem>();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
for (ParticleSystem ps : systems) {
|
||||
ps.run();
|
||||
ps.addParticle();
|
||||
}
|
||||
if (systems.isEmpty()) {
|
||||
fill(255);
|
||||
textAlign(CENTER);
|
||||
text("click mouse to add particle systems", width/2, height/2);
|
||||
}
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
systems.add(new ParticleSystem(1, new PVector(mouseX, mouseY)));
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// A simple Particle class
|
||||
|
||||
class Particle {
|
||||
PVector position;
|
||||
PVector velocity;
|
||||
PVector acceleration;
|
||||
float lifespan;
|
||||
|
||||
Particle(PVector l) {
|
||||
acceleration = new PVector(0, 0.05);
|
||||
velocity = new PVector(random(-1, 1), random(-2, 0));
|
||||
position = l.copy();
|
||||
lifespan = 255.0;
|
||||
}
|
||||
|
||||
void run() {
|
||||
update();
|
||||
display();
|
||||
}
|
||||
|
||||
// Method to update position
|
||||
void update() {
|
||||
velocity.add(acceleration);
|
||||
position.add(velocity);
|
||||
lifespan -= 2.0;
|
||||
}
|
||||
|
||||
// Method to display
|
||||
void display() {
|
||||
stroke(255, lifespan);
|
||||
fill(255, lifespan);
|
||||
ellipse(position.x, position.y, 8, 8);
|
||||
}
|
||||
|
||||
// Is the particle still useful?
|
||||
boolean isDead() {
|
||||
return (lifespan < 0.0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// An ArrayList is used to manage the list of Particles
|
||||
|
||||
class ParticleSystem {
|
||||
|
||||
ArrayList<Particle> particles; // An arraylist for all the particles
|
||||
PVector origin; // An origin point for where particles are birthed
|
||||
|
||||
ParticleSystem(int num, PVector v) {
|
||||
particles = new ArrayList<Particle>(); // Initialize the arraylist
|
||||
origin = v.copy(); // Store the origin point
|
||||
for (int i = 0; i < num; i++) {
|
||||
particles.add(new Particle(origin)); // Add "num" amount of particles to the arraylist
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void run() {
|
||||
// Cycle through the ArrayList backwards, because we are deleting while iterating
|
||||
for (int i = particles.size()-1; i >= 0; i--) {
|
||||
Particle p = particles.get(i);
|
||||
p.run();
|
||||
if (p.isDead()) {
|
||||
particles.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addParticle() {
|
||||
Particle p;
|
||||
// Add either a Particle or CrazyParticle to the system
|
||||
if (int(random(0, 2)) == 0) {
|
||||
p = new Particle(origin);
|
||||
}
|
||||
else {
|
||||
p = new CrazyParticle(origin);
|
||||
}
|
||||
particles.add(p);
|
||||
}
|
||||
|
||||
void addParticle(Particle p) {
|
||||
particles.add(p);
|
||||
}
|
||||
|
||||
// A method to test if the particle system still has particles
|
||||
boolean dead() {
|
||||
return particles.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// A simple Particle class
|
||||
|
||||
class Particle {
|
||||
PVector position;
|
||||
PVector velocity;
|
||||
PVector acceleration;
|
||||
float lifespan;
|
||||
|
||||
Particle(PVector l) {
|
||||
acceleration = new PVector(0, 0.05);
|
||||
velocity = new PVector(random(-1, 1), random(-2, 0));
|
||||
position = l.copy();
|
||||
lifespan = 255.0;
|
||||
}
|
||||
|
||||
void run() {
|
||||
update();
|
||||
display();
|
||||
}
|
||||
|
||||
// Method to update position
|
||||
void update() {
|
||||
velocity.add(acceleration);
|
||||
position.add(velocity);
|
||||
lifespan -= 1.0;
|
||||
}
|
||||
|
||||
// Method to display
|
||||
void display() {
|
||||
stroke(255, lifespan);
|
||||
fill(255, lifespan);
|
||||
ellipse(position.x, position.y, 8, 8);
|
||||
}
|
||||
|
||||
// Is the particle still useful?
|
||||
boolean isDead() {
|
||||
if (lifespan < 0.0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// A class to describe a group of Particles
|
||||
// An ArrayList is used to manage the list of Particles
|
||||
|
||||
class ParticleSystem {
|
||||
ArrayList<Particle> particles;
|
||||
PVector origin;
|
||||
|
||||
ParticleSystem(PVector position) {
|
||||
origin = position.copy();
|
||||
particles = new ArrayList<Particle>();
|
||||
}
|
||||
|
||||
void addParticle() {
|
||||
particles.add(new Particle(origin));
|
||||
}
|
||||
|
||||
void run() {
|
||||
for (int i = particles.size()-1; i >= 0; i--) {
|
||||
Particle p = particles.get(i);
|
||||
p.run();
|
||||
if (p.isDead()) {
|
||||
particles.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Simple Particle System
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* Particles are generated each cycle through draw(),
|
||||
* fall with gravity and fade out over time
|
||||
* A ParticleSystem object manages a variable size (ArrayList)
|
||||
* list of particles.
|
||||
*/
|
||||
|
||||
ParticleSystem ps;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
ps = new ParticleSystem(new PVector(width/2, 50));
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
ps.addParticle();
|
||||
ps.run();
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
// A simple Particle class, renders the particle as an image
|
||||
|
||||
class Particle {
|
||||
PVector loc;
|
||||
PVector vel;
|
||||
PVector acc;
|
||||
float lifespan;
|
||||
PImage img;
|
||||
|
||||
Particle(PVector l, PImage img_) {
|
||||
acc = new PVector(0, 0);
|
||||
float vx = randomGaussian()*0.3;
|
||||
float vy = randomGaussian()*0.3 - 1.0;
|
||||
vel = new PVector(vx, vy);
|
||||
loc = l.copy();
|
||||
lifespan = 100.0;
|
||||
img = img_;
|
||||
}
|
||||
|
||||
void run() {
|
||||
update();
|
||||
render();
|
||||
}
|
||||
|
||||
// Method to apply a force vector to the Particle object
|
||||
// Note we are ignoring "mass" here
|
||||
void applyForce(PVector f) {
|
||||
acc.add(f);
|
||||
}
|
||||
|
||||
// Method to update position
|
||||
void update() {
|
||||
vel.add(acc);
|
||||
loc.add(vel);
|
||||
lifespan -= 2.5;
|
||||
acc.mult(0); // clear Acceleration
|
||||
}
|
||||
|
||||
// Method to display
|
||||
void render() {
|
||||
imageMode(CENTER);
|
||||
tint(255, lifespan);
|
||||
image(img, loc.x, loc.y);
|
||||
// Drawing a circle instead
|
||||
// fill(255,lifespan);
|
||||
// noStroke();
|
||||
// ellipse(loc.x,loc.y,img.width,img.height);
|
||||
}
|
||||
|
||||
// Is the particle still useful?
|
||||
boolean isDead() {
|
||||
if (lifespan <= 0.0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// A class to describe a group of Particles
|
||||
// An ArrayList is used to manage the list of Particles
|
||||
|
||||
class ParticleSystem {
|
||||
|
||||
ArrayList<Particle> particles; // An arraylist for all the particles
|
||||
PVector origin; // An origin point for where particles are birthed
|
||||
PImage img;
|
||||
|
||||
ParticleSystem(int num, PVector v, PImage img_) {
|
||||
particles = new ArrayList<Particle>(); // Initialize the arraylist
|
||||
origin = v.copy(); // Store the origin point
|
||||
img = img_;
|
||||
for (int i = 0; i < num; i++) {
|
||||
particles.add(new Particle(origin, img)); // Add "num" amount of particles to the arraylist
|
||||
}
|
||||
}
|
||||
|
||||
void run() {
|
||||
for (int i = particles.size()-1; i >= 0; i--) {
|
||||
Particle p = particles.get(i);
|
||||
p.run();
|
||||
if (p.isDead()) {
|
||||
particles.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method to add a force vector to all particles currently in the system
|
||||
void applyForce(PVector dir) {
|
||||
// Enhanced loop!!!
|
||||
for (Particle p : particles) {
|
||||
p.applyForce(dir);
|
||||
}
|
||||
}
|
||||
|
||||
void addParticle() {
|
||||
particles.add(new Particle(origin, img));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Smoke Particle System
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* A basic smoke effect using a particle system. Each particle
|
||||
* is rendered as an alpha masked image.
|
||||
*/
|
||||
|
||||
ParticleSystem ps;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
PImage img = loadImage("texture.png");
|
||||
ps = new ParticleSystem(0, new PVector(width/2, height-60), img);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
|
||||
// Calculate a "wind" force based on mouse horizontal position
|
||||
float dx = map(mouseX, 0, width, -0.2, 0.2);
|
||||
PVector wind = new PVector(dx, 0);
|
||||
ps.applyForce(wind);
|
||||
ps.run();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
ps.addParticle();
|
||||
}
|
||||
|
||||
// Draw an arrow representing the wind force
|
||||
drawVector(wind, new PVector(width/2, 50, 0), 500);
|
||||
}
|
||||
|
||||
// Renders a vector object 'v' as an arrow and a position 'loc'
|
||||
void drawVector(PVector v, PVector loc, float scayl) {
|
||||
pushMatrix();
|
||||
float arrowsize = 4;
|
||||
// Translate to position to render vector
|
||||
translate(loc.x, loc.y);
|
||||
stroke(255);
|
||||
// Call vector heading function to get direction (note that pointing up is a heading of 0) and rotate
|
||||
rotate(v.heading());
|
||||
// Calculate length of vector & scale it to be bigger or smaller if necessary
|
||||
float len = v.mag()*scayl;
|
||||
// Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction)
|
||||
line(0, 0, len, 0);
|
||||
line(len, 0, len-arrowsize, +arrowsize/2);
|
||||
line(len, 0, len-arrowsize, -arrowsize/2);
|
||||
popMatrix();
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Soft Body
|
||||
* by Ira Greenberg.
|
||||
*
|
||||
* Softbody dynamics simulation using curveVertex() and curveTightness().
|
||||
*/
|
||||
|
||||
// center point
|
||||
float centerX = 0, centerY = 0;
|
||||
|
||||
float radius = 45, rotAngle = -90;
|
||||
float accelX, accelY;
|
||||
float springing = .0009, damping = .98;
|
||||
|
||||
//corner nodes
|
||||
int nodes = 5;
|
||||
float nodeStartX[] = new float[nodes];
|
||||
float nodeStartY[] = new float[nodes];
|
||||
float[]nodeX = new float[nodes];
|
||||
float[]nodeY = new float[nodes];
|
||||
float[]angle = new float[nodes];
|
||||
float[]frequency = new float[nodes];
|
||||
|
||||
// soft-body dynamics
|
||||
float organicConstant = 1;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
//center shape in window
|
||||
centerX = width/2;
|
||||
centerY = height/2;
|
||||
// iniitalize frequencies for corner nodes
|
||||
for (int i=0; i<nodes; i++){
|
||||
frequency[i] = random(5, 12);
|
||||
}
|
||||
noStroke();
|
||||
frameRate(30);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
//fade background
|
||||
fill(0, 100);
|
||||
rect(0,0,width, height);
|
||||
drawShape();
|
||||
moveShape();
|
||||
}
|
||||
|
||||
void drawShape() {
|
||||
// calculate node starting positions
|
||||
for (int i=0; i<nodes; i++){
|
||||
nodeStartX[i] = centerX+cos(radians(rotAngle))*radius;
|
||||
nodeStartY[i] = centerY+sin(radians(rotAngle))*radius;
|
||||
rotAngle += 360.0/nodes;
|
||||
}
|
||||
|
||||
// draw polygon
|
||||
curveTightness(organicConstant);
|
||||
fill(255);
|
||||
beginShape();
|
||||
for (int i=0; i<nodes; i++){
|
||||
curveVertex(nodeX[i], nodeY[i]);
|
||||
}
|
||||
for (int i=0; i<nodes-1; i++){
|
||||
curveVertex(nodeX[i], nodeY[i]);
|
||||
}
|
||||
endShape(CLOSE);
|
||||
}
|
||||
|
||||
void moveShape() {
|
||||
//move center point
|
||||
float deltaX = mouseX-centerX;
|
||||
float deltaY = mouseY-centerY;
|
||||
|
||||
// create springing effect
|
||||
deltaX *= springing;
|
||||
deltaY *= springing;
|
||||
accelX += deltaX;
|
||||
accelY += deltaY;
|
||||
|
||||
// move predator's center
|
||||
centerX += accelX;
|
||||
centerY += accelY;
|
||||
|
||||
// slow down springing
|
||||
accelX *= damping;
|
||||
accelY *= damping;
|
||||
|
||||
// change curve tightness
|
||||
organicConstant = 1-((abs(accelX)+abs(accelY))*.1);
|
||||
|
||||
//move nodes
|
||||
for (int i=0; i<nodes; i++){
|
||||
nodeX[i] = nodeStartX[i]+sin(radians(angle[i]))*(accelX*2);
|
||||
nodeY[i] = nodeStartY[i]+sin(radians(angle[i]))*(accelY*2);
|
||||
angle[i]+=frequency[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Spring.
|
||||
*
|
||||
* Click, drag, and release the horizontal bar to start the spring.
|
||||
*/
|
||||
|
||||
// Spring drawing constants for top bar
|
||||
int springHeight = 32; // Height
|
||||
int left; // Left position
|
||||
int right; // Right position
|
||||
int max = 200; // Maximum Y value
|
||||
int min = 100; // Minimum Y value
|
||||
boolean over = false; // If mouse over
|
||||
boolean move = false; // If mouse down and over
|
||||
|
||||
// Spring simulation constants
|
||||
float M = 0.8; // Mass
|
||||
float K = 0.2; // Spring constant
|
||||
float D = 0.92; // Damping
|
||||
float R = 150; // Rest position
|
||||
|
||||
// Spring simulation variables
|
||||
float ps = R; // Position
|
||||
float vs = 0.0; // Velocity
|
||||
float as = 0; // Acceleration
|
||||
float f = 0; // Force
|
||||
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
rectMode(CORNERS);
|
||||
noStroke();
|
||||
left = width/2 - 100;
|
||||
right = width/2 + 100;
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(102);
|
||||
updateSpring();
|
||||
drawSpring();
|
||||
}
|
||||
|
||||
void drawSpring() {
|
||||
|
||||
// Draw base
|
||||
fill(0.2);
|
||||
float baseWidth = 0.5 * ps + -8;
|
||||
rect(width/2 - baseWidth, ps + springHeight, width/2 + baseWidth, height);
|
||||
|
||||
// Set color and draw top bar
|
||||
if(over || move) {
|
||||
fill(255);
|
||||
} else {
|
||||
fill(204);
|
||||
}
|
||||
rect(left, ps, right, ps + springHeight);
|
||||
}
|
||||
|
||||
|
||||
void updateSpring() {
|
||||
// Update the spring position
|
||||
if(!move) {
|
||||
f = -K * (ps - R); // f=-ky
|
||||
as = f / M; // Set the acceleration, f=ma == a=f/m
|
||||
vs = D * (vs + as); // Set the velocity
|
||||
ps = ps + vs; // Updated position
|
||||
}
|
||||
if(abs(vs) < 0.1) {
|
||||
vs = 0.0;
|
||||
}
|
||||
|
||||
// Test if mouse is over the top bar
|
||||
if(mouseX > left && mouseX < right && mouseY > ps && mouseY < ps + springHeight) {
|
||||
over = true;
|
||||
} else {
|
||||
over = false;
|
||||
}
|
||||
|
||||
// Set and constrain the position of top bar
|
||||
if(move) {
|
||||
ps = mouseY - springHeight/2;
|
||||
ps = constrain(ps, min, max);
|
||||
}
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
if(over) {
|
||||
move = true;
|
||||
}
|
||||
}
|
||||
|
||||
void mouseReleased() {
|
||||
move = false;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Springs.
|
||||
*
|
||||
* Move the mouse over one of the circles and click to re-position.
|
||||
* When you release the mouse, it will snap back into position.
|
||||
* Each circle has a slightly different behavior.
|
||||
*/
|
||||
|
||||
|
||||
int num = 3;
|
||||
Spring[] springs = new Spring[num];
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
noStroke();
|
||||
springs[0] = new Spring(240, 260, 40, 0.98, 8.0, 0.1, springs, 0);
|
||||
springs[1] = new Spring(320, 210, 120, 0.95, 9.0, 0.1, springs, 1);
|
||||
springs[2] = new Spring(180, 170, 200, 0.90, 9.9, 0.1, springs, 2);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(51);
|
||||
|
||||
for (Spring spring : springs) {
|
||||
spring.update();
|
||||
spring.display();
|
||||
}
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
for (Spring spring : springs) {
|
||||
spring.pressed();
|
||||
}
|
||||
}
|
||||
|
||||
void mouseReleased() {
|
||||
for (Spring spring : springs) {
|
||||
spring.released();
|
||||
}
|
||||
}
|
||||
|
||||
class Spring {
|
||||
// Screen values
|
||||
float xpos, ypos;
|
||||
float tempxpos, tempypos;
|
||||
int size = 20;
|
||||
boolean over = false;
|
||||
boolean move = false;
|
||||
|
||||
// Spring simulation constants
|
||||
float mass; // Mass
|
||||
float k = 0.2; // Spring constant
|
||||
float damp; // Damping
|
||||
float rest_posx; // Rest position X
|
||||
float rest_posy; // Rest position Y
|
||||
|
||||
// Spring simulation variables
|
||||
//float pos = 20.0; // Position
|
||||
float velx = 0.0; // X Velocity
|
||||
float vely = 0.0; // Y Velocity
|
||||
float accel = 0; // Acceleration
|
||||
float force = 0; // Force
|
||||
|
||||
Spring[] friends;
|
||||
int me;
|
||||
|
||||
// Constructor
|
||||
Spring(float x, float y, int s, float d, float m,
|
||||
float k_in, Spring[] others, int id) {
|
||||
xpos = tempxpos = x;
|
||||
ypos = tempypos = y;
|
||||
rest_posx = x;
|
||||
rest_posy = y;
|
||||
size = s;
|
||||
damp = d;
|
||||
mass = m;
|
||||
k = k_in;
|
||||
friends = others;
|
||||
me = id;
|
||||
}
|
||||
|
||||
void update() {
|
||||
if (move) {
|
||||
rest_posy = mouseY;
|
||||
rest_posx = mouseX;
|
||||
}
|
||||
|
||||
force = -k * (tempypos - rest_posy); // f=-ky
|
||||
accel = force / mass; // Set the acceleration, f=ma == a=f/m
|
||||
vely = damp * (vely + accel); // Set the velocity
|
||||
tempypos = tempypos + vely; // Updated position
|
||||
|
||||
force = -k * (tempxpos - rest_posx); // f=-ky
|
||||
accel = force / mass; // Set the acceleration, f=ma == a=f/m
|
||||
velx = damp * (velx + accel); // Set the velocity
|
||||
tempxpos = tempxpos + velx; // Updated position
|
||||
|
||||
|
||||
if ((overEvent() || move) && !otherOver() ) {
|
||||
over = true;
|
||||
} else {
|
||||
over = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test to see if mouse is over this spring
|
||||
boolean overEvent() {
|
||||
float disX = tempxpos - mouseX;
|
||||
float disY = tempypos - mouseY;
|
||||
if (sqrt(sq(disX) + sq(disY)) < size/2 ) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure no other springs are active
|
||||
boolean otherOver() {
|
||||
for (int i=0; i<num; i++) {
|
||||
if (i != me) {
|
||||
if (friends[i].over == true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void display() {
|
||||
if (over) {
|
||||
fill(153);
|
||||
} else {
|
||||
fill(255);
|
||||
}
|
||||
ellipse(tempxpos, tempypos, size, size);
|
||||
}
|
||||
|
||||
void pressed() {
|
||||
if (over) {
|
||||
move = true;
|
||||
} else {
|
||||
move = false;
|
||||
}
|
||||
}
|
||||
|
||||
void released() {
|
||||
move = false;
|
||||
rest_posx = xpos;
|
||||
rest_posy = ypos;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user