// Yoo Jin Shin
// Section D
// yoojins@andrew.cmu.edu
// Project 11 Turtle Freesytle
function turtleLeft(d) {
this.angle -= d;
}
function turtleRight(d) {
this.angle += d;
}
function turtleForward(p) {
var rad = radians(this.angle);
var newx = this.x + cos(rad) * p;
var newy = this.y + sin(rad) * p;
this.goto(newx, newy);
}
function turtleBack(p) {
this.forward(-p);
}
function turtlePenDown() {
this.penIsDown = true;
}
function turtlePenUp() {
this.penIsDown = false;
}
function turtleGoTo(x, y) {
if (this.penIsDown) {
stroke(this.color);
strokeWeight(this.weight);
line(this.x, this.y, x, y);
}
this.x = x;
this.y = y;
}
function turtleDistTo(x, y) {
return sqrt(sq(this.x - x) + sq(this.y - y));
}
function turtleAngleTo(x, y) {
var absAngle = degrees(atan2(y - this.y, x - this.x));
var angle = ((absAngle - this.angle) + 360) % 360.0;
return angle;
}
function turtleTurnToward(x, y, d) {
var angle = this.angleTo(x, y);
if (angle < 180) {
this.angle += d;
} else {
this.angle -= d;
}
}
function turtleSetColor(c) {
this.color = c;
}
function turtleSetWeight(w) {
this.weight = w;
}
function turtleFace(angle) {
this.angle = angle;
}
function makeTurtle(tx, ty) {
var turtle = {x: tx, y: ty,
angle: 0.0,
penIsDown: true,
color: color(128),
weight: 1,
left: turtleLeft, right: turtleRight,
forward: turtleForward, back: turtleBack,
penDown: turtlePenDown, penUp: turtlePenUp,
goto: turtleGoTo, angleto: turtleAngleTo,
turnToward: turtleTurnToward,
distanceTo: turtleDistTo, angleTo: turtleAngleTo,
setColor: turtleSetColor, setWeight: turtleSetWeight,
face: turtleFace};
return turtle;
}
var particles = [];
function setup() {
createCanvas(480, 480);
// Making particles/"rain"
for (var i = 0; i < np; i++) {
var p = makeParticle(200, 200,
random(-50, 50), random(-50, 50));
particles.push(p);
}
frameRate(10);
}
function draw() {
// Gradient green/grass background based on mouse
var r = map(mouseX, 0, width, 70, 120);
var b = map(mouseY, 0, height, 90, 120);
background(r, 170, b);
// Center rose on mouse
var ttl = makeTurtle(mouseX, mouseY);
ttl.penDown();
ttl.setColor("pink");
ttl.setWeight(1);
ttl.left(frameCount);
ttl.face(190);
for (var i = 0; i < 25; i++) {
ttl.face(225 - i * 100);
for (var j = 0; j < 6; j++) {
ttl.forward(3 + i * 2);
ttl.left(80);
}
}
ttl.penUp();
/// Left smaller rose
var ttl2 = makeTurtle(mouseX - 50, mouseY);
ttl2.penDown();
ttl2.setColor(150);
ttl2.setWeight(1);
ttl2.left(frameCount);
ttl2.face(190);
for (var i = 0; i < 10; i++) {
ttl2.face(225 - i * 100);
for (var j = 0; j < 6; j++) {
ttl2.forward(2 + i * 2);
ttl2.left(70);
}
}
ttl.penUp();
/// Right smaller rose
var ttl2 = makeTurtle(mouseX + 50, mouseY);
ttl2.penDown();
ttl2.setColor(150);
ttl2.setWeight(1);
ttl2.left(frameCount);
ttl2.face(190);
for (var i = 0; i < 10; i++) {
ttl2.face(225 - i * 100);
for (var j = 0; j < 6; j++) {
ttl2.forward(2 + i * 2);
ttl2.left(70);
}
}
ttl.penUp();
// Draw all particles in the array
if (mouseIsPressed) {
var newp = makeParticle(mouseX, mouseY,
random(-10, 10), random(-10, 0));
particles.push(newp);
}
newParticles = [];
for (var i = 0; i < particles.length; i++) {
var p = particles[i];
p.step();
p.draw();
if (p.age < 200) {
newParticles.push(p);
}
}
particles = newParticles;
}
var gravity = 0.3; // downward acceleration
var springy = 0.7; // how much velocity is retained after bounce
var drag = 0.0001; // drag causes particles to slow down
var np = 100; // how many particles
var COLORS = ["White", "#86E3F2", "#37A3B5", "#357CA8", "#14608E"];
function particleStep() {
this.age++;
this.x += this.dx;
this.y += this.dy;
if (this.x > width) { // bounce off right wall
this.x = width - (this.x - width);
this.dx = -this.dx * springy;
} else if (this.x < 0) { // bounce off left wall
this.x = -this.x;
this.dx = -this.dx * springy;
}
if (this.y > height) { // bounce off bottom
this.y = height - (this.y - height);
this.dy = -this.dy * springy;
} else if (this.y < 0) { // bounce off top
this.y = -this.y;
this.dy = -this.dy * springy;
}
this.dy = this.dy + gravity; // force of gravity
var vs = Math.pow(this.dx, 2) + Math.pow(this.dy, 2);
var d = vs * drag;
d = min(d, 1);
// Repelling force from center rose
var rpx = mouseX;
var rpy = mouseY;
var d2 = dist(rpx, rpy, this.x, this.y);
var rpc = 9000;
var f = rpc / (Math.pow(d2, 2));
var dirx = (this.x - rpx) / d2;
var diry = (this.y - rpy) / d2;
// scale dx and dy to include drag effect
this.dx *= (1 - d);
this.dx += dirx * f;
this.dy *= (1 - d)
this.dy += diry * f;
}
function particleDraw() {
fill(this.particleColor);
noStroke();
ellipse(this.x, this.y, this.particleSize, this.particleSize);
point(this.x, this.y);
}
function pickColor() {
return COLORS[int(random(COLORS.length))];
}
function pickSize() {
return random(5, 30);
}
// create a "Particle" object with position and velocity
function makeParticle(px, py, pdx, pdy) {
p = {x: px,
y: py,
dx: pdx,
dy: pdy,
age: 0,
step: particleStep,
draw: particleDraw,
particleColor : pickColor(),
particleSize : pickSize(),
}
return p;
}
I created this project with a flower garden in mind: there are rose-like shapes created using turtle, a green, grass-like background, and many blue, rain-like particles. There is a force around the center rose that repels the rain.