mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
nature of code examples update
This commit is contained in:
@@ -1 +0,0 @@
|
||||
mode=Standard
|
||||
@@ -1 +0,0 @@
|
||||
mode=Standard
|
||||
-1
@@ -1 +0,0 @@
|
||||
mode=Standard
|
||||
Binary file not shown.
Executable → Regular
+12
-14
@@ -6,7 +6,6 @@
|
||||
// Neural network code is all in the "code" folder
|
||||
|
||||
import nn.*;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
ArrayList inputs; // List of training input values
|
||||
Network nn; // Neural Network Object
|
||||
@@ -30,17 +29,17 @@ void setup() {
|
||||
// Create a list of 4 training inputs
|
||||
inputs = new ArrayList();
|
||||
float[] input = new float[2];
|
||||
input[0] = 1;
|
||||
input[1] = 0;
|
||||
input[0] = 1;
|
||||
input[1] = 0;
|
||||
inputs.add((float []) input.clone());
|
||||
input[0] = 0;
|
||||
input[1] = 1;
|
||||
input[0] = 0;
|
||||
input[1] = 1;
|
||||
inputs.add((float []) input.clone());
|
||||
input[0] = 1;
|
||||
input[1] = 1;
|
||||
input[0] = 1;
|
||||
input[1] = 1;
|
||||
inputs.add((float []) input.clone());
|
||||
input[0] = 0;
|
||||
input[1] = 0;
|
||||
input[0] = 0;
|
||||
input[1] = 0;
|
||||
inputs.add((float []) input.clone());
|
||||
}
|
||||
|
||||
@@ -52,7 +51,7 @@ void draw() {
|
||||
// Pick a random training input
|
||||
int pick = int(random(inputs.size()));
|
||||
// Grab that input
|
||||
float[] inp = (float[]) inputs.get(pick);
|
||||
float[] inp = (float[]) inputs.get(pick);
|
||||
// Compute XOR
|
||||
float known = 1;
|
||||
if ((inp[0] == 1.0 && inp[1] == 1.0) || (inp[0] == 0 && inp[1] == 0)) known = 0;
|
||||
@@ -78,7 +77,7 @@ void draw() {
|
||||
// Draw the landscape
|
||||
popMatrix();
|
||||
land.calculate(nn);
|
||||
land.render();
|
||||
land.render();
|
||||
theta += 0.0025;
|
||||
popMatrix();
|
||||
|
||||
@@ -97,7 +96,7 @@ void networkStatus() {
|
||||
text("Total iterations: " + count,10,40);
|
||||
|
||||
for (int i = 0; i < inputs.size(); i++) {
|
||||
float[] inp = (float[]) inputs.get(i);
|
||||
float[] inp = (float[]) inputs.get(i);
|
||||
float known = 1;
|
||||
if ((inp[0] == 1.0 && inp[1] == 1.0) || (inp[0] == 0 && inp[1] == 0)) known = 0;
|
||||
float result = nn.feedForward(inp);
|
||||
@@ -106,8 +105,7 @@ void networkStatus() {
|
||||
}
|
||||
|
||||
float rmse = sqrt(mse/4.0);
|
||||
DecimalFormat df = new DecimalFormat("0.000");
|
||||
text("Root mean squared error: " + df.format(rmse), 10,60);
|
||||
text("Root mean squared error: " + nf(rmse,1,5), 10,60);
|
||||
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
mode=Standard
|
||||
-1
@@ -1 +0,0 @@
|
||||
mode=JavaScript
|
||||
+3
@@ -21,6 +21,9 @@ void draw() {
|
||||
ps.run();
|
||||
ps.addParticle();
|
||||
}
|
||||
|
||||
fill(0);
|
||||
text("click mouse to add particle systems",10,height-30);
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Simple Particle System
|
||||
|
||||
// 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.
|
||||
|
||||
ArrayList<ParticleSystem> systems;
|
||||
|
||||
void setup() {
|
||||
size(800,200);
|
||||
systems = new ArrayList<ParticleSystem>();
|
||||
systems.add(new ParticleSystem(1,new PVector(100,25)));
|
||||
|
||||
smooth();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(255);
|
||||
for (ParticleSystem ps: systems) {
|
||||
ps.run();
|
||||
ps.addParticle();
|
||||
}
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
systems.add(new ParticleSystem(1,new PVector(mouseX,mouseY)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
// Simple Particle System
|
||||
// Daniel Shiffman <http://www.shiffman.net>
|
||||
|
||||
// A simple Particle class
|
||||
|
||||
class Particle {
|
||||
PVector location;
|
||||
PVector velocity;
|
||||
PVector acceleration;
|
||||
float lifespan;
|
||||
|
||||
Particle(PVector l) {
|
||||
acceleration = new PVector(0,0.05);
|
||||
velocity = new PVector(random(-1,1),random(-2,0));
|
||||
location = l.get();
|
||||
lifespan = 255.0;
|
||||
}
|
||||
|
||||
void run() {
|
||||
update();
|
||||
display();
|
||||
}
|
||||
|
||||
// Method to update location
|
||||
void update() {
|
||||
velocity.add(acceleration);
|
||||
location.add(velocity);
|
||||
lifespan -= 2.0;
|
||||
}
|
||||
|
||||
// Method to display
|
||||
void display() {
|
||||
stroke(0,lifespan);
|
||||
strokeWeight(2);
|
||||
fill(127,lifespan);
|
||||
ellipse(location.x,location.y,12,12);
|
||||
}
|
||||
|
||||
// Is the particle still useful?
|
||||
boolean isDead() {
|
||||
if (lifespan < 0.0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Simple Particle System
|
||||
|
||||
// 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
|
||||
|
||||
ParticleSystem(int num, PVector v) {
|
||||
particles = new ArrayList<Particle>(); // Initialize the arraylist
|
||||
origin = v.get(); // 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() {
|
||||
// Using the Iterator b/c we are deleting from list while iterating
|
||||
Iterator<Particle> it = particles.iterator();
|
||||
while (it.hasNext()) {
|
||||
Particle p = it.next();
|
||||
p.run();
|
||||
if (p.isDead()) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addParticle() {
|
||||
particles.add(new Particle(origin));
|
||||
}
|
||||
|
||||
void addParticle(Particle p) {
|
||||
particles.add(p);
|
||||
}
|
||||
|
||||
// A method to test if the particle system still has particles
|
||||
boolean dead() {
|
||||
if (particles.isEmpty()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Simple Particle System
|
||||
|
||||
// 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.
|
||||
|
||||
ArrayList<ParticleSystem> systems;
|
||||
|
||||
void setup() {
|
||||
size(800,200);
|
||||
systems = new ArrayList<ParticleSystem>();
|
||||
systems.add(new ParticleSystem(1,new PVector(100,25)));
|
||||
for (int i = 0; i < 6; i++) {
|
||||
systems.add(new ParticleSystem(1,new PVector(random(width),random(height))));
|
||||
}
|
||||
|
||||
smooth();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(255);
|
||||
for (ParticleSystem ps: systems) {
|
||||
ps.run();
|
||||
ps.addParticle();
|
||||
}
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
systems.add(new ParticleSystem(1,new PVector(mouseX,mouseY)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Simple Particle System
|
||||
|
||||
class Particle {
|
||||
PVector location;
|
||||
PVector velocity;
|
||||
PVector acceleration;
|
||||
float lifespan;
|
||||
|
||||
Particle(PVector l) {
|
||||
acceleration = new PVector(0,0.05);
|
||||
velocity = new PVector(random(-1,1),random(-2,0));
|
||||
location = l.get();
|
||||
lifespan = 255.0;
|
||||
}
|
||||
|
||||
void run() {
|
||||
update();
|
||||
display();
|
||||
}
|
||||
|
||||
// Method to update location
|
||||
void update() {
|
||||
velocity.add(acceleration);
|
||||
location.add(velocity);
|
||||
lifespan -= 2.0;
|
||||
}
|
||||
|
||||
// Method to display
|
||||
void display() {
|
||||
stroke(0,lifespan);
|
||||
strokeWeight(2);
|
||||
fill(127,lifespan);
|
||||
ellipse(location.x,location.y,12,12);
|
||||
}
|
||||
|
||||
// Is the particle still useful?
|
||||
boolean isDead() {
|
||||
if (lifespan < 0.0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
// Simple Particle System
|
||||
// Daniel Shiffman <http://www.shiffman.net>
|
||||
|
||||
// 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
|
||||
|
||||
ParticleSystem(int num, PVector v) {
|
||||
particles = new ArrayList<Particle>(); // Initialize the arraylist
|
||||
origin = v.get(); // 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() {
|
||||
// Using the Iterator b/c we are deleting from list while iterating
|
||||
Iterator<Particle> it = particles.iterator();
|
||||
while (it.hasNext()) {
|
||||
Particle p = it.next();
|
||||
p.run();
|
||||
if (p.isDead()) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addParticle() {
|
||||
particles.add(new Particle(origin));
|
||||
}
|
||||
|
||||
void addParticle(Particle p) {
|
||||
particles.add(p);
|
||||
}
|
||||
|
||||
// A method to test if the particle system still has particles
|
||||
boolean dead() {
|
||||
if (particles.isEmpty()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
mode=Standard
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
mode.id=processing.mode.java.JavaMode
|
||||
mode=Standard
|
||||
-1
@@ -1 +0,0 @@
|
||||
mode=Standard
|
||||
@@ -1,49 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Separation
|
||||
|
||||
// Via Reynolds: http://www.red3d.com/cwr/steer/
|
||||
|
||||
// A list of vehicles
|
||||
ArrayList<Vehicle> vehicles;
|
||||
|
||||
void setup() {
|
||||
size(640,360);
|
||||
// We are now making random vehicles and storing them in an ArrayList
|
||||
vehicles = new ArrayList<Vehicle>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
vehicles.add(new Vehicle(random(width),random(height)));
|
||||
}
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(255);
|
||||
|
||||
for (Vehicle v : vehicles) {
|
||||
// Path following and separation are worked on in this function
|
||||
v.cohesion(vehicles);
|
||||
// Call the generic run method (update, borders, display, etc.)
|
||||
v.update();
|
||||
v.borders();
|
||||
v.display();
|
||||
}
|
||||
|
||||
// Instructions
|
||||
fill(0);
|
||||
text("Drag the mouse to generate new vehicles.",10,height-16);
|
||||
}
|
||||
|
||||
|
||||
void mouseDragged() {
|
||||
vehicles.add(new Vehicle(mouseX,mouseY));
|
||||
|
||||
if (vehicles.size() > 200) {
|
||||
vehicles.remove(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Separation
|
||||
|
||||
// Vehicle class
|
||||
|
||||
class Vehicle {
|
||||
|
||||
// All the usual stuff
|
||||
PVector location;
|
||||
PVector velocity;
|
||||
PVector acceleration;
|
||||
float r;
|
||||
float maxforce; // Maximum steering force
|
||||
float maxspeed; // Maximum speed
|
||||
|
||||
// Constructor initialize all values
|
||||
Vehicle(float x, float y) {
|
||||
location = new PVector(x, y);
|
||||
r = 12;
|
||||
maxspeed = 3;
|
||||
maxforce = 0.2;
|
||||
acceleration = new PVector(0, 0);
|
||||
velocity = new PVector(0, 0);
|
||||
}
|
||||
|
||||
void applyForce(PVector force) {
|
||||
// We could add mass here if we want A = F / M
|
||||
acceleration.add(force);
|
||||
}
|
||||
|
||||
// Cohesion
|
||||
// Method checks for nearby vehicles and steers away
|
||||
void cohesion (ArrayList<Vehicle> vehicles) {
|
||||
float desiredseparation = r*2;
|
||||
PVector sum = new PVector();
|
||||
int count = 0;
|
||||
// For every boid in the system, check if it's too close
|
||||
for (Vehicle other : vehicles) {
|
||||
float d = PVector.dist(location, other.location);
|
||||
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
|
||||
if (d > desiredseparation) {
|
||||
// Calculate vector pointing away from neighbor
|
||||
PVector diff = PVector.sub(location, other.location);
|
||||
diff.normalize();
|
||||
diff.mult(-d); // Weight by distance
|
||||
sum.add(diff);
|
||||
count++; // Keep track of how many
|
||||
}
|
||||
}
|
||||
// Average -- divide by how many
|
||||
if (count > 0) {
|
||||
sum.div(count);
|
||||
// Our desired vector is the average scaled to maximum speed
|
||||
sum.normalize();
|
||||
sum.mult(maxspeed);
|
||||
// Implement Reynolds: Steering = Desired - Velocity
|
||||
PVector steer = PVector.sub(sum, velocity);
|
||||
steer.limit(maxforce);
|
||||
applyForce(steer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Method to update location
|
||||
void update() {
|
||||
// Update velocity
|
||||
velocity.add(acceleration);
|
||||
// Limit speed
|
||||
velocity.limit(maxspeed);
|
||||
location.add(velocity);
|
||||
// Reset accelertion to 0 each cycle
|
||||
acceleration.mult(0);
|
||||
}
|
||||
|
||||
void display() {
|
||||
fill(175);
|
||||
stroke(0);
|
||||
pushMatrix();
|
||||
translate(location.x, location.y);
|
||||
ellipse(0, 0, r, r);
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
// Wraparound
|
||||
void borders() {
|
||||
if (location.x < -r) location.x = width+r;
|
||||
if (location.y < -r) location.y = height+r;
|
||||
if (location.x > width+r) location.x = -r;
|
||||
if (location.y > height+r) location.y = -r;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Crowd Path Following
|
||||
// Via Reynolds: http://www.red3d.com/cwr/steer/CrowdPath.html
|
||||
|
||||
// Using this variable to decide whether to draw all the stuff
|
||||
boolean debug = false;
|
||||
|
||||
|
||||
// A path object (series of connected points)
|
||||
Path path;
|
||||
|
||||
// Two vehicles
|
||||
ArrayList<Vehicle> vehicles;
|
||||
|
||||
void setup() {
|
||||
size(640,360);
|
||||
// Call a function to generate new Path object
|
||||
newPath();
|
||||
|
||||
// We are now making random vehicles and storing them in an ArrayList
|
||||
vehicles = new ArrayList<Vehicle>();
|
||||
for (int i = 0; i < 120; i++) {
|
||||
newVehicle(random(width),random(height));
|
||||
}
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(255);
|
||||
// Display the path
|
||||
path.display();
|
||||
|
||||
for (Vehicle v : vehicles) {
|
||||
// Path following and separation are worked on in this function
|
||||
v.applyBehaviors(vehicles,path);
|
||||
// Call the generic run method (update, borders, display, etc.)
|
||||
v.run();
|
||||
}
|
||||
|
||||
// Instructions
|
||||
fill(0);
|
||||
text("Hit 'd' to toggle debugging lines. Click the mouse to generate new vehicles.",10,height-16);
|
||||
}
|
||||
|
||||
void newPath() {
|
||||
// A path is a series of connected points
|
||||
// A more sophisticated path might be a curve
|
||||
path = new Path();
|
||||
float offset = 60;
|
||||
path.addPoint(offset,offset);
|
||||
path.addPoint(width-offset,offset);
|
||||
path.addPoint(width-offset,height-offset);
|
||||
path.addPoint(width/2,height-offset*3);
|
||||
path.addPoint(offset,height-offset);
|
||||
}
|
||||
|
||||
void newVehicle(float x, float y) {
|
||||
float maxspeed = random(2,4);
|
||||
float maxforce = 0.3;
|
||||
vehicles.add(new Vehicle(new PVector(x,y),maxspeed,maxforce));
|
||||
}
|
||||
|
||||
void keyPressed() {
|
||||
if (key == 'd') {
|
||||
debug = !debug;
|
||||
}
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
newVehicle(mouseX,mouseY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Path Following
|
||||
|
||||
class Path {
|
||||
|
||||
// A Path is an arraylist of points (PVector objects)
|
||||
ArrayList<PVector> points;
|
||||
// A path has a radius, i.e how far is it ok for the boid to wander off
|
||||
float radius;
|
||||
|
||||
Path() {
|
||||
// Arbitrary radius of 20
|
||||
radius = 20;
|
||||
points = new ArrayList<PVector>();
|
||||
}
|
||||
|
||||
// Add a point to the path
|
||||
void addPoint(float x, float y) {
|
||||
PVector point = new PVector(x, y);
|
||||
points.add(point);
|
||||
}
|
||||
|
||||
// Draw the path
|
||||
void display() {
|
||||
strokeJoin(ROUND);
|
||||
|
||||
// Draw thick line for radius
|
||||
stroke(175);
|
||||
strokeWeight(radius*2);
|
||||
noFill();
|
||||
beginShape();
|
||||
for (PVector v : points) {
|
||||
vertex(v.x, v.y);
|
||||
}
|
||||
endShape(CLOSE);
|
||||
// Draw thin line for center of path
|
||||
stroke(0);
|
||||
strokeWeight(1);
|
||||
noFill();
|
||||
beginShape();
|
||||
for (PVector v : points) {
|
||||
vertex(v.x, v.y);
|
||||
}
|
||||
endShape(CLOSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,241 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Path Following
|
||||
|
||||
// Vehicle class
|
||||
|
||||
class Vehicle {
|
||||
|
||||
// All the usual stuff
|
||||
PVector location;
|
||||
PVector velocity;
|
||||
PVector acceleration;
|
||||
float r;
|
||||
float maxforce; // Maximum steering force
|
||||
float maxspeed; // Maximum speed
|
||||
|
||||
// Constructor initialize all values
|
||||
Vehicle( PVector l, float ms, float mf) {
|
||||
location = l.get();
|
||||
r = 12;
|
||||
maxspeed = ms;
|
||||
maxforce = mf;
|
||||
acceleration = new PVector(0, 0);
|
||||
velocity = new PVector(maxspeed, 0);
|
||||
}
|
||||
|
||||
// A function to deal with path following and separation
|
||||
void applyBehaviors(ArrayList vehicles, Path path) {
|
||||
// Follow path force
|
||||
PVector f = follow(path);
|
||||
// Separate from other boids force
|
||||
PVector s = separate(vehicles);
|
||||
// Arbitrary weighting
|
||||
f.mult(3);
|
||||
s.mult(1);
|
||||
// Accumulate in acceleration
|
||||
applyForce(f);
|
||||
applyForce(s);
|
||||
}
|
||||
|
||||
void applyForce(PVector force) {
|
||||
// We could add mass here if we want A = F / M
|
||||
acceleration.add(force);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Main "run" function
|
||||
public void run() {
|
||||
update();
|
||||
borders();
|
||||
render();
|
||||
}
|
||||
|
||||
|
||||
// This function implements Craig Reynolds' path following algorithm
|
||||
// http://www.red3d.com/cwr/steer/PathFollow.html
|
||||
PVector follow(Path p) {
|
||||
|
||||
// Predict location 25 (arbitrary choice) frames ahead
|
||||
PVector predict = velocity.get();
|
||||
predict.normalize();
|
||||
predict.mult(25);
|
||||
PVector predictLoc = PVector.add(location, predict);
|
||||
|
||||
// Now we must find the normal to the path from the predicted location
|
||||
// We look at the normal for each line segment and pick out the closest one
|
||||
PVector normal = null;
|
||||
PVector target = null;
|
||||
float worldRecord = 1000000; // Start with a very high worldRecord distance that can easily be beaten
|
||||
|
||||
// Loop through all points of the path
|
||||
for (int i = 0; i < p.points.size(); i++) {
|
||||
|
||||
// Look at a line segment
|
||||
PVector a = p.points.get(i);
|
||||
PVector b = p.points.get((i+1)%p.points.size()); // Note Path has to wraparound
|
||||
|
||||
// Get the normal point to that line
|
||||
PVector normalPoint = getNormalPoint(predictLoc, a, b);
|
||||
|
||||
// Check if normal is on line segment
|
||||
PVector dir = PVector.sub(b, a);
|
||||
// If it's not within the line segment, consider the normal to just be the end of the line segment (point b)
|
||||
//if (da + db > line.mag()+1) {
|
||||
if (normalPoint.x < min(a.x,b.x) || normalPoint.x > max(a.x,b.x) || normalPoint.y < min(a.y,b.y) || normalPoint.y > max(a.y,b.y)) {
|
||||
normalPoint = b.get();
|
||||
// If we're at the end we really want the next line segment for looking ahead
|
||||
a = p.points.get((i+1)%p.points.size());
|
||||
b = p.points.get((i+2)%p.points.size()); // Path wraps around
|
||||
dir = PVector.sub(b, a);
|
||||
}
|
||||
|
||||
// How far away are we from the path?
|
||||
float d = PVector.dist(predictLoc, normalPoint);
|
||||
// Did we beat the worldRecord and find the closest line segment?
|
||||
if (d < worldRecord) {
|
||||
worldRecord = d;
|
||||
normal = normalPoint;
|
||||
|
||||
// Look at the direction of the line segment so we can seek a little bit ahead of the normal
|
||||
dir.normalize();
|
||||
// This is an oversimplification
|
||||
// Should be based on distance to path & velocity
|
||||
dir.mult(25);
|
||||
target = normal.get();
|
||||
target.add(dir);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the debugging stuff
|
||||
if (debug) {
|
||||
// Draw predicted future location
|
||||
stroke(0);
|
||||
fill(0);
|
||||
line(location.x, location.y, predictLoc.x, predictLoc.y);
|
||||
ellipse(predictLoc.x, predictLoc.y, 4, 4);
|
||||
|
||||
// Draw normal location
|
||||
stroke(0);
|
||||
fill(0);
|
||||
ellipse(normal.x, normal.y, 4, 4);
|
||||
// Draw actual target (red if steering towards it)
|
||||
line(predictLoc.x, predictLoc.y, target.x, target.y);
|
||||
if (worldRecord > p.radius) fill(255, 0, 0);
|
||||
noStroke();
|
||||
ellipse(target.x, target.y, 8, 8);
|
||||
}
|
||||
|
||||
// Only if the distance is greater than the path's radius do we bother to steer
|
||||
if (worldRecord > p.radius) {
|
||||
return seek(target);
|
||||
}
|
||||
else {
|
||||
return new PVector(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// A function to get the normal point from a point (p) to a line segment (a-b)
|
||||
// This function could be optimized to make fewer new Vector objects
|
||||
PVector getNormalPoint(PVector p, PVector a, PVector b) {
|
||||
// Vector from a to p
|
||||
PVector ap = PVector.sub(p, a);
|
||||
// Vector from a to b
|
||||
PVector ab = PVector.sub(b, a);
|
||||
ab.normalize(); // Normalize the line
|
||||
// Project vector "diff" onto line by using the dot product
|
||||
ab.mult(ap.dot(ab));
|
||||
PVector normalPoint = PVector.add(a, ab);
|
||||
return normalPoint;
|
||||
}
|
||||
|
||||
// Separation
|
||||
// Method checks for nearby boids and steers away
|
||||
PVector separate (ArrayList boids) {
|
||||
float desiredseparation = r*2;
|
||||
PVector steer = new PVector(0, 0, 0);
|
||||
int count = 0;
|
||||
// For every boid in the system, check if it's too close
|
||||
for (int i = 0 ; i < boids.size(); i++) {
|
||||
Vehicle other = (Vehicle) boids.get(i);
|
||||
float d = PVector.dist(location, other.location);
|
||||
// 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(location, other.location);
|
||||
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) {
|
||||
// Implement Reynolds: Steering = Desired - Velocity
|
||||
steer.normalize();
|
||||
steer.mult(maxspeed);
|
||||
steer.sub(velocity);
|
||||
steer.limit(maxforce);
|
||||
}
|
||||
return steer;
|
||||
}
|
||||
|
||||
|
||||
// Method to update location
|
||||
void update() {
|
||||
// Update velocity
|
||||
velocity.add(acceleration);
|
||||
// Limit speed
|
||||
velocity.limit(maxspeed);
|
||||
location.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, location); // A vector pointing from the location to the target
|
||||
|
||||
// Normalize desired and scale to maximum speed
|
||||
desired.normalize();
|
||||
desired.mult(maxspeed);
|
||||
// Steering = Desired minus Velocationity
|
||||
PVector steer = PVector.sub(desired, velocity);
|
||||
steer.limit(maxforce); // Limit to maximum steering force
|
||||
|
||||
return steer;
|
||||
}
|
||||
|
||||
|
||||
void render() {
|
||||
// Simpler boid is just a circle
|
||||
fill(75);
|
||||
stroke(0);
|
||||
pushMatrix();
|
||||
translate(location.x, location.y);
|
||||
ellipse(0, 0, r, r);
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
// Wraparound
|
||||
void borders() {
|
||||
if (location.x < -r) location.x = width+r;
|
||||
//if (location.y < -r) location.y = height+r;
|
||||
if (location.x > width+r) location.x = -r;
|
||||
//if (location.y > height+r) location.y = -r;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
class Cell {
|
||||
|
||||
float x, y;
|
||||
float w;
|
||||
float xoff;
|
||||
float yoff;
|
||||
|
||||
int state;
|
||||
|
||||
Cell(float x_, float y_, float w_) {
|
||||
x = x_;
|
||||
y = y_;
|
||||
w = w_;
|
||||
xoff = w/2;
|
||||
yoff = sin(radians(60))*w;
|
||||
state = int(random(2));
|
||||
}
|
||||
|
||||
|
||||
void display() {
|
||||
|
||||
fill(state*255);
|
||||
stroke(0);
|
||||
pushMatrix();
|
||||
translate(x,y);
|
||||
beginShape();
|
||||
vertex(0, yoff);
|
||||
vertex(xoff, 0);
|
||||
vertex(xoff+w, 0);
|
||||
vertex(2*w, yoff);
|
||||
vertex(xoff+w, 2*yoff);
|
||||
vertex(xoff, 2*yoff);
|
||||
vertex(0, yoff);
|
||||
endShape();
|
||||
popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Outline for game of life
|
||||
// This is just a grid of hexagons right now
|
||||
|
||||
GOL gol;
|
||||
|
||||
void setup() {
|
||||
size(800, 200);
|
||||
gol = new GOL();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(255);
|
||||
gol.display();
|
||||
}
|
||||
|
||||
// reset board when mouse is pressed
|
||||
void mousePressed() {
|
||||
gol.init();
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
class GOL {
|
||||
|
||||
float w = 20;
|
||||
float h = sin(radians(60))*w;
|
||||
int columns, rows;
|
||||
|
||||
// Game of life board
|
||||
Cell[][] board;
|
||||
|
||||
|
||||
GOL() {
|
||||
// Initialize rows, columns and set-up arrays
|
||||
columns = width/int(w*3);
|
||||
rows = height/int(h);
|
||||
board = new Cell[columns][rows];
|
||||
init();
|
||||
}
|
||||
|
||||
void init() {
|
||||
float h = sin(radians(60))*w;
|
||||
for (int i = 0; i < columns; i++) {
|
||||
for (int j = 0; j < rows; j++) {
|
||||
if (j % 2 == 0) board[i][j] = new Cell(i*w*3, j*h,w);
|
||||
else board[i][j] = new Cell(i*w*3+w+h/2, j*h, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This is the easy part, just draw the cells, fill 255 for '1', fill 0 for '0'
|
||||
void display() {
|
||||
for ( int i = 0; i < columns;i++) {
|
||||
for ( int j = 0; j < rows;j++) {
|
||||
board[i][j].display();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
class Cell {
|
||||
|
||||
float x, y;
|
||||
float w;
|
||||
|
||||
int state;
|
||||
int previous;
|
||||
|
||||
Cell(float x_, float y_, float w_) {
|
||||
x = x_;
|
||||
y = y_;
|
||||
w = w_;
|
||||
|
||||
state = int(random(2));
|
||||
previous = state;
|
||||
}
|
||||
|
||||
void savePrevious() {
|
||||
previous = state;
|
||||
}
|
||||
|
||||
void newState(int s) {
|
||||
state = s;
|
||||
}
|
||||
|
||||
void display() {
|
||||
if (previous == 0 && state == 1) fill(0,0,255);
|
||||
else if (state == 1) fill(0);
|
||||
else if (previous == 1 && state == 0) fill(255,0,0);
|
||||
else fill(255);
|
||||
stroke(0);
|
||||
rect(x, y, w, w);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
class GOL {
|
||||
|
||||
int w = 8;
|
||||
int columns, rows;
|
||||
|
||||
// Game of life board
|
||||
Cell[][] board;
|
||||
|
||||
|
||||
GOL() {
|
||||
// Initialize rows, columns and set-up arrays
|
||||
columns = width/w;
|
||||
rows = height/w;
|
||||
board = new Cell[columns][rows];
|
||||
init();
|
||||
}
|
||||
|
||||
void init() {
|
||||
for (int i = 0; i < columns; i++) {
|
||||
for (int j = 0; j < rows; j++) {
|
||||
board[i][j] = new Cell(i*w, j*w, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The process of creating the new generation
|
||||
void generate() {
|
||||
for ( int i = 0; i < columns;i++) {
|
||||
for ( int j = 0; j < rows;j++) {
|
||||
board[i][j].savePrevious();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Loop through every spot in our 2D array and check spots neighbors
|
||||
for (int x = 0; x < columns; x++) {
|
||||
for (int y = 0; y < rows; y++) {
|
||||
|
||||
// Add up all the states in a 3x3 surrounding grid
|
||||
int neighbors = 0;
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
neighbors += board[(x+i+columns)%columns][(y+j+rows)%rows].previous;
|
||||
}
|
||||
}
|
||||
|
||||
// A little trick to subtract the current cell's state since
|
||||
// we added it in the above loop
|
||||
neighbors -= board[x][y].previous;
|
||||
|
||||
// Rules of Life
|
||||
if ((board[x][y].state == 1) && (neighbors < 2)) board[x][y].newState(0); // Loneliness
|
||||
else if ((board[x][y].state == 1) && (neighbors > 3)) board[x][y].newState(0); // Overpopulation
|
||||
else if ((board[x][y].state == 0) && (neighbors == 3)) board[x][y].newState(1); // Reproduction
|
||||
// else do nothing!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is the easy part, just draw the cells, fill 255 for '1', fill 0 for '0'
|
||||
void display() {
|
||||
for ( int i = 0; i < columns;i++) {
|
||||
for ( int j = 0; j < rows;j++) {
|
||||
board[i][j].display();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// A basic implementation of John Conway's Game of Life CA
|
||||
|
||||
// Each cell is now an object!
|
||||
|
||||
GOL gol;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
gol = new GOL();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(255);
|
||||
|
||||
gol.generate();
|
||||
gol.display();
|
||||
}
|
||||
|
||||
// reset board when mouse is pressed
|
||||
void mousePressed() {
|
||||
gol.init();
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
mode.id=processing.mode.java.JavaMode
|
||||
mode=Java
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Stochastic Tree
|
||||
// Renders a simple tree-like structure via recursion
|
||||
// Angles and number of branches are random
|
||||
|
||||
void setup() {
|
||||
size(600, 400);
|
||||
newTree();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
newTree();
|
||||
}
|
||||
|
||||
void newTree() {
|
||||
background(255);
|
||||
fill(0);
|
||||
text("Click mouse to generate a new tree", 10, height-20);
|
||||
|
||||
stroke(0);
|
||||
// Start the tree from the bottom of the screen
|
||||
translate(width/2, height);
|
||||
// Start the recursive branching!
|
||||
branch(120);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void branch(float h) {
|
||||
// thickness of the branch is mapped to its length
|
||||
float sw = map(h, 2, 120, 1, 5);
|
||||
strokeWeight(sw);
|
||||
// Draw the actual branch
|
||||
line(0, 0, 0, -h);
|
||||
// Move along to end
|
||||
translate(0, -h);
|
||||
|
||||
// Each branch will be 2/3rds the size of the previous one
|
||||
h *= 0.66f;
|
||||
|
||||
// All recursive functions must have an exit condition!!!!
|
||||
// Here, ours is when the length of the branch is 2 pixels or less
|
||||
if (h > 2) {
|
||||
// A random number of branches
|
||||
int n = int(random(1, 4));
|
||||
for (int i = 0; i < n; i++) {
|
||||
// Picking a random angle
|
||||
float theta = random(-PI/2, PI/2);
|
||||
pushMatrix(); // Save the current state of transformation (i.e. where are we now)
|
||||
rotate(theta); // Rotate by theta
|
||||
branch(h); // Ok, now call myself to branch again
|
||||
popMatrix(); // Whenever we get back here, we "pop" in order to restore the previous matrix state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
mode.id=processing.mode.java.JavaMode
|
||||
mode=Standard
|
||||
@@ -1,61 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Recursive Tree (w/ ArrayList)
|
||||
|
||||
// A class for one branch in the system
|
||||
|
||||
class Branch {
|
||||
// Each has a location, velocity, and timer
|
||||
// We could implement this same idea with different data
|
||||
PVector loc;
|
||||
PVector vel;
|
||||
float timer;
|
||||
float timerstart;
|
||||
|
||||
Branch(PVector l, PVector v, float n) {
|
||||
loc = l.get();
|
||||
vel = v.get();
|
||||
timerstart = n;
|
||||
timer = timerstart;
|
||||
}
|
||||
|
||||
// Move location
|
||||
void update() {
|
||||
loc.add(vel);
|
||||
}
|
||||
|
||||
// Draw a dot at location
|
||||
void render() {
|
||||
fill(0);
|
||||
noStroke();
|
||||
ellipseMode(CENTER);
|
||||
ellipse(loc.x,loc.y,2,2);
|
||||
}
|
||||
|
||||
// Did the timer run out?
|
||||
boolean timeToBranch() {
|
||||
timer--;
|
||||
if (timer < 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new branch at the current location, but change direction by a given angle
|
||||
Branch branch(float angle) {
|
||||
// What is my current heading
|
||||
float theta = vel.heading2D();
|
||||
// What is my current speed
|
||||
float mag = vel.mag();
|
||||
// Turn me
|
||||
theta += radians(angle);
|
||||
// Look, polar coordinates to cartesian!!
|
||||
PVector newvel = new PVector(mag*cos(theta),mag*sin(theta));
|
||||
// Return a new Branch
|
||||
return new Branch(loc,newvel,timerstart*0.66f);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Recursive Tree (w/ ArrayList)
|
||||
|
||||
// Recursive branching "structure" without an explicitly recursive function
|
||||
// Instead we have an ArrayList to hold onto N number of elements
|
||||
// For every element in the ArrayList, we add 2 more elements, etc. (this is the recursion)
|
||||
|
||||
// An arraylist that will keep track of all current branches
|
||||
ArrayList<Branch> tree;
|
||||
|
||||
void setup() {
|
||||
size(200,200);
|
||||
background(255);
|
||||
// Setup the arraylist and add one branch to it
|
||||
tree = new ArrayList();
|
||||
// A branch has a starting location, a starting "velocity", and a starting "timer"
|
||||
Branch b = new Branch(new PVector(width/2,height),new PVector(0,-0.5),100);
|
||||
// Add to arraylist
|
||||
tree.add(b);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// Try erasing the background to see how it works
|
||||
// background(255);
|
||||
|
||||
// Let's stop when the arraylist gets too big
|
||||
if (tree.size() < 1024) {
|
||||
// For every branch in the arraylist
|
||||
for (int i = tree.size()-1; i >= 0; i--) {
|
||||
// Get the branch, update and draw it
|
||||
Branch b = tree.get(i);
|
||||
b.update();
|
||||
b.render();
|
||||
// If it's ready to split
|
||||
if (b.timeToBranch()) {
|
||||
tree.remove(i); // Delete it
|
||||
tree.add(b.branch( 30)); // Add one going right
|
||||
tree.add(b.branch(-25)); // Add one going left
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Recursive Tree (w/ ArrayList)
|
||||
|
||||
// A class for one branch in the system
|
||||
|
||||
class Branch {
|
||||
// Each has a location, velocity, and timer
|
||||
// We could implement this same idea with different data
|
||||
PVector start;
|
||||
PVector end;
|
||||
PVector vel;
|
||||
float timer;
|
||||
float timerstart;
|
||||
|
||||
boolean growing = true;
|
||||
|
||||
Branch(PVector l, PVector v, float n) {
|
||||
start = l.get();
|
||||
end = l.get();
|
||||
vel = v.get();
|
||||
timerstart = n;
|
||||
timer = timerstart;
|
||||
}
|
||||
|
||||
// Move location
|
||||
void update() {
|
||||
if (growing) {
|
||||
end.add(vel);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a dot at location
|
||||
void render() {
|
||||
stroke(0);
|
||||
line(start.x,start.y,end.x,end.y);
|
||||
}
|
||||
|
||||
// Did the timer run out?
|
||||
boolean timeToBranch() {
|
||||
timer--;
|
||||
if (timer < 0 && growing) {
|
||||
growing = false;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new branch at the current location, but change direction by a given angle
|
||||
Branch branch(float angle) {
|
||||
// What is my current heading
|
||||
float theta = vel.heading2D();
|
||||
// What is my current speed
|
||||
float mag = vel.mag();
|
||||
// Turn me
|
||||
theta += radians(angle);
|
||||
// Look, polar coordinates to cartesian!!
|
||||
PVector newvel = new PVector(mag*cos(theta),mag*sin(theta));
|
||||
// Return a new Branch
|
||||
return new Branch(end,newvel,timerstart*0.66f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Recursive Tree (w/ ArrayList)
|
||||
|
||||
// A class for a leaf that gets placed at the end of
|
||||
// the last branches
|
||||
|
||||
class Leaf {
|
||||
PVector loc;
|
||||
|
||||
Leaf(PVector l) {
|
||||
loc = l.get();
|
||||
}
|
||||
|
||||
void display() {
|
||||
noStroke();
|
||||
fill(50,100);
|
||||
ellipse(loc.x,loc.y,4,4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Recursive Tree (w/ ArrayList)
|
||||
// Nature of Code, Chapter 8
|
||||
|
||||
// Recursive branching "structure" without an explicitly recursive function
|
||||
// Instead we have an ArrayList to hold onto N number of elements
|
||||
// For every element in the ArrayList, we add 2 more elements, etc. (this is the recursion)
|
||||
|
||||
// An arraylist that will keep track of all current branches
|
||||
ArrayList<Branch> tree;
|
||||
ArrayList<Leaf> leaves;
|
||||
|
||||
void setup() {
|
||||
size(200,200);
|
||||
background(255);
|
||||
// Setup the arraylist and add one branch to it
|
||||
tree = new ArrayList<Branch>();
|
||||
leaves = new ArrayList<Leaf>();
|
||||
// A branch has a starting location, a starting "velocity", and a starting "timer"
|
||||
Branch b = new Branch(new PVector(width/2,height),new PVector(0,-0.5),100);
|
||||
// Add to arraylist
|
||||
tree.add(b);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(255);
|
||||
|
||||
// Let's stop when the arraylist gets too big
|
||||
// For every branch in the arraylist
|
||||
for (int i = tree.size()-1; i >= 0; i--) {
|
||||
// Get the branch, update and draw it
|
||||
Branch b = tree.get(i);
|
||||
b.update();
|
||||
b.render();
|
||||
// If it's ready to split
|
||||
if (b.timeToBranch()) {
|
||||
if (tree.size() < 1024) {
|
||||
//tree.remove(i); // Delete it
|
||||
tree.add(b.branch( 30)); // Add one going right
|
||||
tree.add(b.branch(-25)); // Add one going left
|
||||
}
|
||||
else {
|
||||
leaves.add(new Leaf(b.end));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Leaf leaf : leaves) {
|
||||
leaf.display();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// Stochastic Tree with angles fluctuating with Perlin noise
|
||||
// Nature of Code, Chapter 8
|
||||
|
||||
// Perlin noise offset
|
||||
float yoff = 0;
|
||||
// Random seed to control randomness while drawing the tree
|
||||
int seed = 5;
|
||||
|
||||
|
||||
void setup() {
|
||||
size(800, 200);
|
||||
smooth();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(255);
|
||||
fill(0);
|
||||
//text("Click mouse to generate a new tree", 10, height-20);
|
||||
|
||||
stroke(0);
|
||||
// Start the tree from the bottom of the screen
|
||||
translate(width/2, height);
|
||||
// Move alogn through noise
|
||||
yoff += 0.005;
|
||||
randomSeed(seed);
|
||||
// Start the recursive branching!
|
||||
branch(60, 0);
|
||||
}
|
||||
|
||||
|
||||
void mousePressed() {
|
||||
// New tree starts with new noise offset and new random seed
|
||||
yoff = random(1000);
|
||||
seed = millis();
|
||||
}
|
||||
|
||||
|
||||
void branch(float h, float xoff) {
|
||||
// thickness of the branch is mapped to its length
|
||||
float sw = map(h, 2, 100, 1, 5);
|
||||
strokeWeight(sw);
|
||||
// Draw the branch
|
||||
line(0, 0, 0, -h);
|
||||
// Move along to end
|
||||
translate(0, -h);
|
||||
|
||||
// Each branch will be 2/3rds the size of the previous one
|
||||
h *= 0.7f;
|
||||
|
||||
// Move along through noise space
|
||||
xoff += 0.1;
|
||||
|
||||
if (h > 4) {
|
||||
// Random number of branches
|
||||
int n = int(random(0, 5));
|
||||
for (int i = 0; i < n; i++) {
|
||||
|
||||
// Here the angle is controlled by perlin noise
|
||||
// This is a totally arbitrary way to do it, try others!
|
||||
float theta = map(noise(xoff+i, yoff), 0, 1, -PI/3, PI/3);
|
||||
if (n%2==0) theta *= -1;
|
||||
|
||||
pushMatrix(); // Save the current state of transformation (i.e. where are we now)
|
||||
rotate(theta); // Rotate by theta
|
||||
branch(h, xoff); // Ok, now call myself to branch again
|
||||
popMatrix(); // Whenever we get back here, we "pop" in order to restore the previous matrix state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
mode=Standard
|
||||
@@ -1,65 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
/* LSystem Class */
|
||||
|
||||
// An LSystem has a starting sentence
|
||||
// An a ruleset
|
||||
// Each generation recursively replaces characteres in the sentence
|
||||
// Based on the rulset
|
||||
|
||||
class LSystem {
|
||||
|
||||
String sentence; // The sentence (a String)
|
||||
Rule[] ruleset; // The ruleset (an array of Rule objects)
|
||||
int generation; // Keeping track of the generation #
|
||||
|
||||
// Construct an LSystem with a startin sentence and a ruleset
|
||||
LSystem(String axiom, Rule[] r) {
|
||||
sentence = axiom;
|
||||
ruleset = r;
|
||||
generation = 0;
|
||||
}
|
||||
|
||||
// Generate the next generation
|
||||
void generate() {
|
||||
// An empty StringBuffer that we will fill
|
||||
StringBuffer nextgen = new StringBuffer();
|
||||
// For every character in the sentence
|
||||
for (int i = 0; i < sentence.length(); i++) {
|
||||
// What is the character
|
||||
char curr = sentence.charAt(i);
|
||||
// We will replace it with itself unless it matches one of our rules
|
||||
String replace = "" + curr;
|
||||
// Check every rule
|
||||
for (int j = 0; j < ruleset.length; j++) {
|
||||
char a = ruleset[j].getA();
|
||||
// if we match the Rule, get the replacement String out of the Rule
|
||||
if (a == curr) {
|
||||
replace = ruleset[j].getB();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Append replacement String
|
||||
nextgen.append(replace);
|
||||
}
|
||||
// Replace sentence
|
||||
sentence = nextgen.toString();
|
||||
// Increment generation
|
||||
generation++;
|
||||
}
|
||||
|
||||
String getSentence() {
|
||||
return sentence;
|
||||
}
|
||||
|
||||
int getGeneration() {
|
||||
return generation;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
// A Class to describe an LSystem Rule
|
||||
|
||||
class Rule {
|
||||
char a;
|
||||
String b;
|
||||
|
||||
Rule(char a_, String b_) {
|
||||
a = a_;
|
||||
b = b_;
|
||||
}
|
||||
|
||||
char getA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
String getB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/* Daniel Shiffman */
|
||||
/* http://www.shiffman.net */
|
||||
|
||||
class Turtle {
|
||||
|
||||
String todo;
|
||||
float len;
|
||||
float theta;
|
||||
|
||||
Turtle(String s, float l, float t) {
|
||||
todo = s;
|
||||
len = l;
|
||||
theta = t;
|
||||
}
|
||||
|
||||
void render() {
|
||||
stroke(0);
|
||||
for (int i = 0; i < todo.length(); i++) {
|
||||
char c = todo.charAt(i);
|
||||
if (c == 'F' || c == 'G') {
|
||||
line(0,0,len,0);
|
||||
translate(len,0);
|
||||
}
|
||||
else if (c == '+') {
|
||||
rotate(theta);
|
||||
}
|
||||
else if (c == '-') {
|
||||
rotate(-theta);
|
||||
}
|
||||
else if (c == '[') {
|
||||
pushMatrix();
|
||||
}
|
||||
else if (c == ']') {
|
||||
popMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setLen(float l) {
|
||||
len = l;
|
||||
}
|
||||
|
||||
void changeLen(float percent) {
|
||||
len *= percent;
|
||||
}
|
||||
|
||||
void setToDo(String s) {
|
||||
todo = s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
// The Nature of Code
|
||||
// Daniel Shiffman
|
||||
// http://natureofcode.com
|
||||
|
||||
LSystem lsys;
|
||||
Turtle turtle;
|
||||
|
||||
void setup() {
|
||||
size(600, 600);
|
||||
/*
|
||||
// Create an empty ruleset
|
||||
Rule[] ruleset = new Rule[2];
|
||||
// Fill with two rules (These are rules for the Sierpinksi Gasket Triangle)
|
||||
ruleset[0] = new Rule('F',"F--F--F--G");
|
||||
ruleset[1] = new Rule('G',"GG");
|
||||
// Create LSystem with axiom and ruleset
|
||||
lsys = new LSystem("F--F--F",ruleset);
|
||||
turtle = new Turtle(lsys.getSentence(),width*2,TWO_PI/3);
|
||||
*/
|
||||
|
||||
/*Rule[] ruleset = new Rule[1];
|
||||
//ruleset[0] = new Rule('F',"F[F]-F+F[--F]+F-F");
|
||||
ruleset[0] = new Rule['F',"FF+[+F-F-F]-[-F+F+F]");
|
||||
lsys = new LSystem("F-F-F-F",ruleset);
|
||||
turtle = new Turtle(lsys.getSentence(),width-1,PI/2);
|
||||
*/
|
||||
|
||||
Rule[] ruleset = new Rule[1];
|
||||
ruleset[0] = new Rule('F', "FF+[+F-F-F]-[-F+F+F]");
|
||||
lsys = new LSystem("F", ruleset);
|
||||
turtle = new Turtle(lsys.getSentence(), width/4, radians(25));
|
||||
|
||||
|
||||
|
||||
smooth();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(255);
|
||||
fill(0);
|
||||
text("Click mouse to generate", 10, height-20);
|
||||
|
||||
translate(width/2, height);
|
||||
rotate(-PI/2);
|
||||
turtle.render();
|
||||
noLoop();
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
lsys.generate();
|
||||
turtle.setToDo(lsys.getSentence());
|
||||
turtle.changeLen(0.5);
|
||||
redraw();
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
mode.id=processing.mode.java.JavaMode
|
||||
mode=Standard
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
mode.id=processing.mode.java.JavaMode
|
||||
mode=Standard
|
||||
@@ -1 +0,0 @@
|
||||
mode=Standard
|
||||
-1
@@ -1 +0,0 @@
|
||||
mode=Standard
|
||||
Reference in New Issue
Block a user