/* Spirotropism 9 July 2004 Nancy Doubleday Graphics Turtles by Steve Kurtz More ideas from Mike Axelrod Two turtles move in related spirals, collecting points which are used for bezier curves. More turtles are used to aim and tween the spirals. Move the mouse to aim the center. Hold down the mouse to clear the screen. */ float tweenA = 0.0; // values btwn 0 and 1 float tweenB = 0.0; float baseColor = random(1); Runner wanderer = new Runner(250,220, 0.9 ,77); // turtles to change the spiral data Chaser chas = new Chaser(100,400, 1.2, 120); void setup(){ colorMode(HSB,1.0); size (750,600); // set the screen size background(0.7, 0.2, 0.1 ); // clear the screen smooth(); // antialiased noFill(); wanderer.penUp(); chas.penUp(); chas.setTarget(wanderer); println(baseColor); } void loop( ){ // bouncer stuff wanderer.doLoop(); // chas stuff chas.doLoop(); tweenA = abs(chas.getX()/width); tweenB = abs(chas.getY()/height); float a = 130+ tweenA * 25; // base angle float b = (a-0.7) + tweenB ; //angle range drawPattern(a,b); // draw the spiral } String getInfo (){ float a = 130+ tweenA * 25; // base angle float b = (a-0.7) + 1 * tweenB ; //angle range String s = " runner: "+(int)wanderer.getX() +", "+(int)wanderer.getY(); s += " chas: "+(int)chas.getX() +", "+(int)chas.getY(); s += " %: "+nf(tweenA,1,3)+", "+nf(tweenB,1,3) + " Ang: "+nf(a,3,2)+", "+nf(b,3,2); s += " bCol: "+ nf(baseColor,1,3 ); return s; } void mouseMoved(){ wanderer.moveTo(mouseX, mouseY); } void mousePressed(){ println( getInfo() ); } void keyPressed(){ if (key==' ') { background(baseColor-tweenA*.1, 0.15 , 0.2); // clear the screen } else { println( getInfo() ); } } void drawPattern(float ang, float ang2){ float x = chas.getX(); float y = chas.getY(); Turtle T1 = new Turtle(x, y, 1 ,0); // Initial position of our turtle Turtle T2 = new Turtle(x, y, 1 ,0); // Initial position of our turtle T1.penUp(); T2.penUp(); float d = 5; baseColor += 0.00001; // very slowly change the color palette if (baseColor>=1.0)baseColor = 0; if (mousePressed){ background(baseColor-tweenA*.1, 0.15 , 0.2); // clear the screen } for ( int i=0;i<94;i++) { ///////////////////////////////// looop float huey = baseColor + tweenA*0.1 - i/400.0; //colorize if (huey > 1) huey -= 1; float sat = float(100-i)/150; float brite = tweenB*0.07 + i/100.0; stroke(huey, sat, brite, 0.2); T1.right(ang); // move T1.forward( ); T2.right(ang2); T2.forward( ); d = (d+1.3) * (1.08 - tweenB*0.07); // unwind the spiral T1.setSpeed(d); T2.setSpeed(d); if (i % 5 == 0) { float c1x, c1y, c2x, c2y, b1x, b1y, b2x, b2y; // four (x,y) values for bezier c1x = T1.lastX; c1y =T1.lastY; b1x = T2.lastX; b1y =T2.lastY; b2x = T2.getX(); b2y =T2.getY(); c2x = T1.getX(); c2y =T1.getY(); bezier( c2x, c2y, b2x, b2y, c1x, c1y, b1x, b1y); } else if (i > 15) { if (i % 5 == 4){ // some dots stroke(huey, sat, brite, 0.3); ellipse(T1.getX(), T1.getY(), 1,1); } } } } class Turtle { // Graphics Turtle by Steve Kurtz public final static float DEGRAD = PI/180.0; private float ang; // heading as clockwise angle in degrees private float rad; // angle in radians private float curX; // current X-coordinate private float curY; // current Y -coordinate private float lastX; // Temporary values for last known position private float lastY; private float speed; public boolean pen; // true equals pen down and drawing public Turtle() { } public Turtle(float x, float y, float spd) { curX = x; curY = y; speed = spd; ang = 0; // default heading -- that away --> pen = true; // default pen down } public Turtle(float x, float y, float spd, float ang) { curX = x; curY = y; ang = ang; pen = true; // default pen down } public float getX() { return curX; } public float getY() { return curY; } public void penUp() { pen = false; // pen up } public void penDown() { pen = true; // pen down } public void moveTo(float tx, float ty){ curX = tx; curY = ty; lastX = curX; lastY = curY; } public void forward() { lastX = curX; lastY = curY; rad = (360-ang) * DEGRAD; curX += speed * cos(rad); curY += speed * sin(rad); if(pen) { line(lastX,lastY, curX, curY); // if the pen is down draw! } } public float getSpeed(){ return speed; } public void setSpeed(float s){ speed = s; } public void incrSpeed(float s){ speed += s; } public float getAngle( ) { return ang; } public void setAngle(float angle){ ang = angle; } public void left(float angle) { ang -= angle; } public void right(float angle) { ang += angle; } public void headFor(Turtle t) { float dy = (curY-t.getY()); float dx = (t.getX()- curX); ang = atan2(dy,dx) / DEGRAD; } public float getDistance(Turtle t){ float dx = this.getX() - t.getX(); float dy = this.getY() - t.getY(); return sqrt(dx*dx + dy*dy); } } class Runner extends Turtle { private float speed; public Runner(float x, float y, float spd, float angl) { super(x,y, spd); this.left(random(angl)); } public void doLoop(){ this.right(random(6.0)); this.left(random(6.0)); this.forward( ); this.driftTowardCenter(); } public void driftTowardCenter(){ int margin = 200; if(this.getX() > width+margin) this.setAngle(random(160,200)); if(this.getX() < -1*margin) this.setAngle(random(-20,20)); if(this.getY() > height+margin/3) this.setAngle(random(70,110)); if(this.getY() < -1*margin) this.setAngle(random(250,290)); } } class Chaser extends Turtle { private float origSpeed; public Turtle target; public Chaser(float x, float y, float spd, float angl) { super(x,y, spd); origSpeed = spd; this.left(random(angl)); } public void doLoop(){ this.headFor(target); float dist = this.getDistance(wanderer); float spd = this.getSpeed(); if (dist < spd*300) { this.setSpeed( spd*0.98); } else { if (spd < origSpeed){ this.setSpeed(spd*1.02); } } this.forward( ); } public void setTarget(Turtle t){ target = t; } }