// much more convenient than standard arrays // you don't need to specify a length import java.util.ArrayList; void setup() { size(800, 600); background(255); //noLoop(); } void draw() { /* background(255); translate(10, 10); int row= 10; int col = 5; int xSpace = 100; int ySpace = 100; for(int x = 0; x < row; x++) { for(int y = 0; y < col; y++ ) { pushMatrix(); Man2 aMan2 = new Man2(); translate( x*xSpace, y*ySpace ); aMan2.render(); popMatrix(); } } int row2= 10; int col2 = 5; int xSpace2 = 200; int ySpace2 = 200; for(int x = 0; x < row2; x++) { for(int y = 0; y < col2; y++ ) { pushMatrix(); Man aMan = new Man(); translate( x*xSpace2, y*ySpace2 ); //rotate(random(0, TWO_PI)); aMan.render(); popMatrix(); } } translate(width/2, height/2); Man2 aMan2 = new Man2(); Man aMan = new Man(); */ } void mousePressed(){ // make a man here pushMatrix(); translate( mouseX, mouseY ); float s = random(100); if (s > 50){ //make it gray stroke (100); } else{ stroke(0); } float a = random(100); if (a >50){ rotate(random(0, TWO_PI)); //angle the guy } float r = random(100); if (r > 80){ //make big man Man aMan = new Man(); aMan.render(); } else{ //make little man Man2 aMan2 = new Man2(); aMan2.render(); } //Man2 aMan2 = new Man2(); //translate( mouseX, mouseY ); //aMan.render(); popMatrix(); } class Man { DMPath facePath; DMPath bodyPath; DMPath llegPath; DMPath rlegPath; Man() { // edit the locations here, might be a good idea to grab a piece of graph paper facePath = new DMPath(); facePath.moveToPoint(-25, -25); facePath.curveToPoint(-25, -37.5, -12.5, -50, 0, -50); facePath.curveToPoint(12.5, -50, 25, -37.5, 25, -25); facePath.curveToPoint(25, -12.5, 12.5, 0, 0, 0); facePath.curveToPoint(-12.5, 0, -25, -12.5, -25, -25); bodyPath= new DMPath(); bodyPath.moveToPoint(0,0); bodyPath.curveToPoint(35,10, 35,25, 35,60); bodyPath.lineToPoint(35,100); bodyPath.lineToPoint(-35,100); bodyPath.lineToPoint(-35,60); bodyPath.curveToPoint(-35,25, -35,5, 0,0); llegPath= new DMPath(); llegPath.moveToPoint(-15,100); llegPath.lineToPoint(-15,100); llegPath.lineToPoint(-15,140); rlegPath= new DMPath(); rlegPath.moveToPoint(15,100); rlegPath.lineToPoint(15,100); rlegPath.lineToPoint(15,140); } void render() { DMPath randomFace = randomizePath(facePath); DMPath randomBody = randomizePath(bodyPath); DMPath randomLleg = randomizePath(llegPath); DMPath randomRleg = randomizePath(rlegPath); // randomize the face strokeWeight(2); // stroke(255,0,0); randomFace.strokePath(); strokeWeight(2); randomBody.strokePath(); strokeWeight(2); randomRleg.strokePath(); strokeWeight(2); randomLleg.strokePath(); } } class Man2 { DMPath facePath; DMPath bodyPath; DMPath llegPath; DMPath rlegPath; Man2() { // edit the locations here, might be a good idea to grab a piece of graph paper facePath = new DMPath(); facePath.moveToPoint(-5, -5); facePath.curveToPoint(-5, -6, -3, 10, 0, -10); facePath.curveToPoint(3, -10, 5, -6, 5, -5); facePath.curveToPoint(5, -3, 3, 0, 0, 0); facePath.curveToPoint(-3, 0, -5, -3, -5, -5); bodyPath= new DMPath(); bodyPath.moveToPoint(0,0); bodyPath.curveToPoint(5,2, 5,7, 5,14); bodyPath.lineToPoint(5,20); bodyPath.lineToPoint(-5,20); bodyPath.lineToPoint(-5,14); bodyPath.curveToPoint(-5,7, -5,2, 0,0); llegPath= new DMPath(); llegPath.moveToPoint(-2.5,20); llegPath.lineToPoint(-2.5,20); llegPath.lineToPoint(-2.5,30); rlegPath= new DMPath(); rlegPath.moveToPoint(2.5,20); rlegPath.lineToPoint(2.5,20); rlegPath.lineToPoint(2.5,30); } void render() { DMPath randomFace = randomizePath(facePath); DMPath randomBody = randomizePath(bodyPath); DMPath randomLleg = randomizePath(llegPath); DMPath randomRleg = randomizePath(rlegPath); // randomize the face strokeWeight(1); randomFace.strokePath(); strokeWeight(1); randomBody.strokePath(); strokeWeight(1); randomRleg.strokePath(); strokeWeight(1); randomLleg.strokePath(); } } DMPath randomizePath(DMPath aPath) { DMPath randomizedPath = aPath.copy(); //println(randomizedPath.lines); for(int i = 0; i < randomizedPath.lines.size(); i++) { DMLine cline = (DMLine)randomizedPath.lines.get(i); cline.p0.p.x += random(-2, 2); cline.p0.p.y += random(-2, 2); //cline.p0.cp.x += random(-5, 5); //cline.p0.cp.y += random(-5, 5); cline.p1.p.x += random(-2, 2); cline.p1.p.y += random(-2, 2); //cline.p1.cp.x += random(-5, 5); //cline.p1.cp.y += random(-5, 5); } return randomizedPath; } // a simple vector class class DMVector { float x, y; DMVector(float _x, float _y) { x = _x; y = _y; } // vector addition DMVector add(DMVector other) { return new DMVector(x+other.x, y+other.y); } // vector subtraction DMVector sub(DMVector other) { return new DMVector(x-other.x, y-other.y); } // vector multiplication DMVector mult(float scalar) { return new DMVector(x*scalar, y*scalar); } // if the vector close to zero? boolean isZero() { return (x == 0 && y == 0); } // it's important to copying an object like // DMVector in assignments to avoid weird // side effects DMVector copy() { return new DMVector(x, y); } // by providing a toString method // Java can properly provide a description // of your object in string concatenations String toString() { return "<" + x + ", " + y + ">"; } } // convenience, returns a zero vector DMVector ZeroVector() { return new DMVector(0, 0); } // a bezier curve point, holds a point and a control point // a lines are represented as bezier points, regular lines // simply have start point whose control point matches // and an end point whose control point mathces class DMBPoint { DMVector p; DMVector cp; // constructor with two float DMBPoint(float x, float y) { p = new DMVector(x, y); cp = p.copy(); } // constructor with DMVector DMBPoint(DMVector _p) { p = _p.copy(); cp = new DMVector(_p.x, _p.y); } // constructor with four floats DMBPoint(float x, float y, float cpx, float cpy) { p = new DMVector(x, y); cp = new DMVector(cpx, cpy); } // constructor with 2 DMVectors DMBPoint(DMVector _p, DMVector _cp) { p = _p.copy(); cp = _cp.copy(); } // return true of the control point is different from the point boolean hasControlPoint() { return !(p.sub(cp).isZero()); } // it's important to copy an object // we don't want weird side effects DMBPoint copy() { return new DMBPoint(p.copy(), cp.copy()); } String toString() { return "(" + p + ", " + cp + ")"; } } // convenience class class DMLine { DMBPoint p0, p1; DMLine(DMVector _p0, DMVector _p1) { p0 = new DMBPoint(_p0); p1 = new DMBPoint(_p1); } DMLine(DMBPoint _p0, DMBPoint _p1) { p0 = _p0.copy(); p1 = _p1.copy(); } DMLine copy() { return new DMLine(p0, p1); } String toString() { return "[" + p0 + ", " + p1 + "]"; } } // our path class class DMPath { DMVector firstPoint; ArrayList lines; // simple constructor DMPath() { // set first point to the zero vector firstPoint = ZeroVector(); // create a new ArrayList object lines = new ArrayList(); } // simple constructor DMPath(DMVector _firstPoint, ArrayList _lines) { // set first point to the zero vector firstPoint = _firstPoint.copy(); // copy all the lines lines = new ArrayList(); for(int i = 0; i < _lines.size(); i++) { lines.add(((DMLine)_lines.get(i)).copy()); } } // return the last end point on the path DMVector getLastPoint() { int nlines = lines.size(); // if no lines yet, just return first point if(nlines == 0) { return firstPoint; } else { // other wise return the point value of the end point // of the last line stored int lastIndex = nlines - 1; return ((DMLine)lines.get(lastIndex)).p1.p; } } // you should call this function before calling // anything else, otherwise the first point will be (0, 0) // once called you should not call this again void moveToPoint(float x, float y) { firstPoint = new DMVector(x, y); } // line the path to the specified point void lineToPoint(float x, float y) { if(firstPoint == null) { print("Error: No first point set!"); } else { DMVector p = this.getLastPoint(); DMVector np = new DMVector(x, y); lines.add(new DMLine(p, np)); } } // add a cubic bezier curve to the path void curveToPoint(float cp0x, float cp0y, float cp1x, float cp1y, float p1x, float p1y) { if(firstPoint == null) { print("Error: No first point set!"); } else { // get the last point DMVector last = this.getLastPoint(); DMVector cp0 = new DMVector(cp0x, cp0y); DMVector cp1 = new DMVector(cp1x, cp1y); DMVector p1 = new DMVector(p1x, p1y); lines.add(new DMLine(new DMBPoint(last, cp0), new DMBPoint(p1, cp1))); } } // look for any bezier curves and decompose them into the // constituent line segments ArrayList decompose() { // we will store all of our real line points here ArrayList allPoints = new ArrayList(); // get two points at a time for(int i = 0; i < lines.size(); i++) { DMLine cline = (DMLine)lines.get(i); // if either point has a control point // we need to decompose the bezier // into line segments if(cline.p0.hasControlPoint() || cline.p1.hasControlPoint()) { // confusing isn't it ArrayList bpoints = DMBezier((float)cline.p0.p.x, (float)cline.p0.p.y, (float)cline.p0.cp.x, (float)cline.p0.cp.y, (float)cline.p1.cp.x, (float)cline.p1.cp.y, (float)cline.p1.p.x, (float)cline.p1.p.y); // add all these allPoints.addAll(bpoints); } else { // otherwise just add the point values allPoints.add(cline.p0.p); allPoints.add(cline.p1.p); } } return allPoints; } // connect the end point to the first point // no more commands should be issued to the // path object after this void close() { lines.add(new DMLine(this.getLastPoint(), firstPoint)); } // render the path void strokePath() { // first decompose all of our paths ArrayList renderPoints = this.decompose(); // then render them all noFill(); beginShape(); for(int i = 0; i < renderPoints.size(); i++) { DMVector p = (DMVector)renderPoints.get(i); vertex(p.x, p.y); } endShape(); } DMPath copy() { return new DMPath(firstPoint, lines); } void writeToFile(PrintWriter output) { } } // Convenience function that returns an ArrayList of the points // in the bezier curve ArrayList DMBezier(float p0x, float p0y, float cp0x, float cp0y, float cp1x, float cp1y, float p1x, float p1y) { ArrayList points = new ArrayList(); // B(t) = ((1-t)^3 * P0) + (3t(1-t)^2 * P1) + (3(t^2)(1-t) * P3) + (t^3 * P4) float delta = 0.05; // the starting point float cx, cy; for(float t = 0; t <= 1.0; t += delta) { // calc the next point cx = (pow(1-t,3)*p0x) + (3*t*pow(1-t,2)*cp0x) + (3*pow(t,2)*(1-t)*cp1x) + (pow(t,3)*p1x); cy = (pow(1-t,3)*p0y) + (3*t*pow(1-t,2)*cp0y) + (3*pow(t,2)*(1-t)*cp1y) + (pow(t,3)*p1y); points.add(new DMVector(cx, cy)); } return points; }