Code Sketch
siddhi gandas
cleari()
originBottomLeft()
// ============================================================
// STOP PLASTIC POLLUTION
// ADVANCED ENVIRONMENT ANIMATION
// ============================================================
var time = 0.0
var cleaning = false
var cleanAmount = 0.0
var flash = 0.0
var wave = 0.0
var messageIndex = 0
var messageTimer = 0
val message = "STOP PLASTIC POLLUTION"
// ------------------------------------------------------------
// PLASTIC PARTICLES
// ------------------------------------------------------------
case class PlasticPiece(
var x: Double,
var y: Double,
var vx: Double,
var vy: Double,
var size: Double,
var angle: Double,
var rot: Double
)
val plastic =
scala.collection.mutable.ArrayBuffer.empty[PlasticPiece]
for (i <- 0 until 130) {
plastic.append(
PlasticPiece(
10.0 + math.random * (cwidth - 20.0),
55.0 + math.random * 190.0,
(math.random - 0.5) * 0.5,
(math.random - 0.5) * 0.25,
4.0 + math.random * 10.0,
math.random * 3.14,
(math.random - 0.5) * 0.08
)
)
}
// ------------------------------------------------------------
// BIRDS
// ------------------------------------------------------------
val birdX =
Array(
90.0,
170.0,
500.0,
620.0
)
val birdY =
Array(
330.0,
365.0,
345.0,
380.0
)
// ------------------------------------------------------------
// HELPERS
// ------------------------------------------------------------
def clamp(
v: Double,
lo: Double,
hi: Double
): Double = {
math.max(
lo,
math.min(hi, v)
)
}
// ------------------------------------------------------------
// UPDATE PLASTIC
// ------------------------------------------------------------
def updatePlastic(): Unit = {
plastic.foreach { p =>
if (!cleaning) {
p.x += p.vx
p.y += p.vy
if (p.x < 0)
p.x = cwidth
if (p.x > cwidth)
p.x = 0
if (p.y < 45)
p.y = 45
if (p.y > 260)
p.y = 260
p.angle += p.rot
} else {
p.x +=
(p.x - cwidth / 2.0) * 0.010
p.y +=
2.5 + cleanAmount * 5.0
p.angle += 0.08
if (p.y > cheight + 20) {
p.x =
20 + math.random * (cwidth - 40)
p.y =
60 + math.random * 180
if (cleanAmount < 0.90) {
p.y = 300 + math.random * 100
}
}
}
}
}
// ------------------------------------------------------------
// BACKGROUND
// ------------------------------------------------------------
def drawBackground(
canvas: CanvasDraw
): Unit = {
canvas.background(
205,
225,
235
)
// Sky
canvas.fill(
150,
215,
240
)
canvas.noStroke()
canvas.rect(
0,
150,
cwidth,
cheight - 150
)
// Horizon
canvas.fill(
90,
150,
75
)
canvas.rect(
0,
125,
cwidth,
70
)
// Ground
val green =
70.0 +
cleanAmount * 70.0
val greenInt =
clamp(
green,
60.0,
150.0
).toInt
canvas.fill(
55,
greenInt,
55
)
canvas.rect(
0,
0,
cwidth,
145
)
// Dirty area
val dirtyAlpha =
clamp(
255.0 - cleanAmount * 255.0,
0.0,
255.0
).toInt
canvas.fill(
70,
65,
55,
dirtyAlpha
)
canvas.rect(
0,
45,
cwidth,
110
)
// Sun
canvas.fill(
255,
225,
110,
230
)
canvas.ellipse(
cwidth - 90,
cheight - 75,
70,
70
)
}
// ------------------------------------------------------------
// TREES
// ------------------------------------------------------------
def drawTree(
canvas: CanvasDraw,
x: Double,
y: Double,
scale: Double
): Unit = {
val appear =
clamp(
cleanAmount * 1.7,
0.0,
1.0
)
if (appear <= 0)
return
val trunkH =
75.0 * scale * appear
canvas.fill(
95,
60,
35
)
canvas.noStroke()
canvas.rect(
x - 9 * scale,
y,
18 * scale,
trunkH
)
canvas.fill(
40,
135,
55
)
canvas.ellipse(
x,
y + trunkH + 20 * scale,
65 * scale * appear,
55 * scale * appear
)
canvas.fill(
70,
165,
60
)
canvas.ellipse(
x - 20 * scale,
y + trunkH + 5 * scale,
50 * scale * appear,
50 * scale * appear
)
canvas.ellipse(
x + 20 * scale,
y + trunkH + 8 * scale,
50 * scale * appear,
50 * scale * appear
)
}
// ------------------------------------------------------------
// COW
// ------------------------------------------------------------
def drawCow(
canvas: CanvasDraw,
x: Double,
y: Double,
scale: Double,
direction: Double
): Unit = {
val bob =
math.sin(time * 3.0 + x * 0.01) *
2.0
val bodyY =
y + bob
// Shadow
canvas.fill(
0,
0,
0,
45
)
canvas.ellipse(
x,
y - 18,
75 * scale,
15 * scale
)
// Body
canvas.fill(
165,
105,
55
)
canvas.stroke(
80,
55,
35
)
canvas.strokeWeight(2)
canvas.ellipse(
x,
bodyY,
72 * scale,
43 * scale
)
// White patch
canvas.fill(
220,
200,
165
)
canvas.noStroke()
canvas.ellipse(
x - 8 * direction,
bodyY + 4,
28 * scale,
23 * scale
)
// Head
canvas.fill(
150,
90,
48
)
canvas.ellipse(
x + 38 * direction,
bodyY + 12,
28 * scale,
25 * scale
)
// Ear
canvas.fill(
120,
72,
40
)
canvas.ellipse(
x + 47 * direction,
bodyY + 27,
13 * scale,
8 * scale
)
// Eye
canvas.fill(
20,
20,
20
)
canvas.ellipse(
x + 45 * direction,
bodyY + 15,
4 * scale,
4 * scale
)
// Legs
val legMove =
math.sin(time * 5.0 + x * 0.02) *
4.0
canvas.stroke(
95,
60,
40
)
canvas.strokeWeight(
6 * scale
)
canvas.line(
x - 22 * scale,
bodyY - 16,
x - 24 * scale + legMove,
bodyY - 38
)
canvas.line(
x + 5 * scale,
bodyY - 16,
x + 6 * scale - legMove,
bodyY - 38
)
// Horns
canvas.stroke(
220,
205,
175
)
canvas.strokeWeight(
3 * scale
)
canvas.line(
x + 45 * direction,
bodyY + 24,
x + 52 * direction,
bodyY + 34
)
canvas.line(
x + 38 * direction,
bodyY + 24,
x + 33 * direction,
bodyY + 34
)
}
// ------------------------------------------------------------
// BIRDS
// ------------------------------------------------------------
def drawBirds(
canvas: CanvasDraw
): Unit = {
canvas.stroke(
35,
55,
65
)
canvas.strokeWeight(2)
for (i <- birdX.indices) {
val x =
birdX(i) +
math.sin(time + i) * 20
val y =
birdY(i) +
math.cos(time * 2 + i) * 8
canvas.noFill()
canvas.arc(
x - 8,
y,
16,
10,
math.Pi,
math.Pi * 2
)
canvas.arc(
x + 8,
y,
16,
10,
math.Pi,
math.Pi * 2
)
}
}
// ------------------------------------------------------------
// PLASTIC
// ------------------------------------------------------------
def drawPlastic(
canvas: CanvasDraw
): Unit = {
val alpha =
clamp(
255.0 -
cleanAmount * 255.0,
0.0,
255.0
).toInt
plastic.foreach { p =>
if (alpha > 0) {
canvas.fill(
150,
160,
165,
alpha
)
canvas.stroke(
100,
105,
110,
alpha
)
canvas.strokeWeight(1)
canvas.pushMatrix()
canvas.translate(
p.x,
p.y
)
canvas.rotate(
p.angle
)
canvas.rect(
-p.size,
-p.size * 0.5,
p.size * 2.0,
p.size
)
canvas.popMatrix()
}
}
}
// ------------------------------------------------------------
// CLEANUP WAVE
// ------------------------------------------------------------
def drawCleanupWave(
canvas: CanvasDraw
): Unit = {
if (!cleaning)
return
val r =
40.0 +
cleanAmount * 350.0
canvas.noFill()
canvas.stroke(
70,
230,
170,
150
)
canvas.strokeWeight(3)
canvas.ellipse(
cwidth / 2.0,
115,
r,
r * 0.55
)
canvas.stroke(
160,
255,
200,
90
)
canvas.ellipse(
cwidth / 2.0,
115,
r * 0.75,
r * 0.40
)
}
// ------------------------------------------------------------
// ECO BUTTON
// ------------------------------------------------------------
def drawButton(
canvas: CanvasDraw
): Unit = {
val bx =
cwidth / 2.0 - 115.0
val by =
25.0
canvas.fill(
20,
130,
70
)
canvas.stroke(
210,
255,
220
)
canvas.strokeWeight(2)
canvas.rect(
bx,
by,
230,
38
)
canvas.fill(
255,
255,
255
)
canvas.noStroke()
if (!cleaning) {
canvas.text(
"START CLEANUP",
bx + 70,
by + 25
)
} else {
canvas.text(
"CLEANING PLASTIC...",
bx + 55,
by + 25
)
}
}
// ------------------------------------------------------------
// POLLUTION METER
// ------------------------------------------------------------
def drawMeter(
canvas: CanvasDraw
): Unit = {
val px =
20.0
val py =
cheight - 55.0
canvas.fill(
15,
25,
30,
220
)
canvas.stroke(
230,
240,
240
)
canvas.strokeWeight(1.5)
canvas.rect(
px,
py,
210,
25
)
val polluted =
1.0 - cleanAmount
canvas.fill(
210,
70,
45
)
canvas.rect(
px + 5,
py + 5,
200 * polluted,
15
)
canvas.fill(
20,
90,
55
)
canvas.rect(
px + 5 +
200 * polluted,
py + 5,
200 * cleanAmount,
15
)
canvas.fill(
255,
255,
255
)
canvas.noStroke()
canvas.text(
"ENVIRONMENT STATUS",
px,
py + 42
)
}
// ------------------------------------------------------------
// MESSAGE
// ------------------------------------------------------------
def drawMessage(
canvas: CanvasDraw
): Unit = {
if (messageIndex <= 0)
return
val shown =
message.substring(
0,
messageIndex
)
canvas.fill(
255,
255,
255
)
canvas.stroke(
10,
80,
60,
120
)
canvas.strokeWeight(2)
canvas.text(
shown,
cwidth / 2.0 - 125,
cheight - 22
)
}
// ------------------------------------------------------------
// COMPLETE SCENE
// ------------------------------------------------------------
def drawScene(
canvas: CanvasDraw
): Unit = {
drawBackground(canvas)
drawBirds(canvas)
drawTree(
canvas,
75,
120,
1.0
)
drawTree(
canvas,
cwidth - 75,
120,
1.0
)
drawCow(
canvas,
145,
100,
1.0,
1.0
)
drawCow(
canvas,
cwidth - 170,
145,
0.75,
-1.0
)
drawPlastic(canvas)
drawCleanupWave(canvas)
drawButton(canvas)
drawMeter(canvas)
drawMessage(canvas)
}
// ------------------------------------------------------------
// MAIN ANIMATION
// ------------------------------------------------------------
animateWithCanvasDraw { canvas =>
time += 0.04
wave += 0.08
updatePlastic()
if (cleaning) {
cleanAmount += 0.0018
if (cleanAmount >= 1.0) {
cleanAmount = 1.0
}
flash =
math.max(
0.0,
flash - 0.04
)
}
messageTimer += 1
if (
cleaning &&
messageTimer % 5 == 0 &&
messageIndex < message.length
) {
messageIndex += 1
}
drawScene(canvas)
// Click detection
if (
isMousePressed &&
mouseX >= cwidth / 2.0 - 115 &&
mouseX <= cwidth / 2.0 + 115 &&
mouseY >= 25 &&
mouseY <= 63 &&
!cleaning
) {
cleaning = true
flash = 1.0
cleanAmount = 0.0
messageIndex = 0
messageTimer = 0
}
}