nature of code examples update

This commit is contained in:
Daniel Shiffman
2013-06-03 14:33:49 -04:00
parent dd88eecfe9
commit a9d5c78ebb
46 changed files with 15 additions and 1676 deletions
@@ -1 +0,0 @@
mode=Standard
@@ -1 +0,0 @@
mode=Standard
+12 -14
View File
@@ -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);
}
@@ -21,6 +21,9 @@ void draw() {
ps.run();
ps.addParticle();
}
fill(0);
text("click mouse to add particle systems",10,height-30);
}
void mousePressed() {
@@ -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)));
}
@@ -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;
}
}
}
@@ -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;
}
}
}
@@ -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)));
}
@@ -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;
}
}
}
@@ -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,2 +0,0 @@
mode.id=processing.mode.java.JavaMode
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;
}
}
@@ -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();
}
}
@@ -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();
}
}
}
}
@@ -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
@@ -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();
}
}
@@ -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,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
@@ -1,2 +0,0 @@
mode.id=processing.mode.java.JavaMode
mode=Standard
@@ -1 +0,0 @@
mode=Standard