Code Sketch
ganux art
Category: Art
cleari()
originBottomLeft()
class Sketch {
var t = 0.0
var bob = 0.0
var headX = 0.0
var eyeX = 0.0
var eyeY = 0.0
var blink = 0.0
var glow = 0.0
var scan = 0.0
var wave = 0.0
var clickX = 0.0
var clickY = 0.0
var ripple = 0.0
var pulse = 0.0
var waving = false
var clicked = false
var talking = true
val messages = Array(
"HELLO HUMAN!",
"AI SYSTEM ONLINE",
"WELCOME CREATOR",
"FUTURE IS HERE!",
"I AM YOUR ROBOT"
)
var messageIndex = 0
var messageTimer = 0.0
def clamp(v: Double, lo: Double, hi: Double): Double =
math.max(lo, math.min(hi, v))
def alpha(v: Double): Int =
clamp(v, 0.0, 255.0).toInt
def cx: Double = cwidth / 2.0
def cy: Double = cheight / 2.0
def setup(c: CanvasDraw): Unit = {
c.background(3, 8, 24)
}
// --------------------------------------------------
// SPACE BACKGROUND
// --------------------------------------------------
def backgroundFX(c: CanvasDraw): Unit = {
c.background(3, 8, 24)
for (i <- 0 until 70) {
val x = ((i * 137 + 19) % 997).toDouble *
cwidth / 997.0
val y = ((i * 83 + 31) % 991).toDouble *
cheight / 991.0
val s = 1.0 +
math.abs(math.sin(t * 2.0 + i)) * 2.0
c.noStroke()
c.fill(
40,
180,
255,
alpha(50 + 100 *
math.abs(math.sin(t + i)))
)
c.ellipse(x, y, s, s)
}
// Floor
c.noStroke()
c.fill(8, 19, 38)
c.rect(0, 0, cwidth, 38)
c.fill(0, 180, 255, 40)
c.ellipse(cx, 35, 430, 22)
// Floor grid
c.stroke(0, 120, 180, 45)
c.strokeWeight(1)
for (i <- 0 until 15) {
val x = i * cwidth / 14.0
c.line(cx, 38, x, 0)
}
for (i <- 0 until 5) {
val y = i * 8.0
c.line(0, y, cwidth, y)
}
}
// --------------------------------------------------
// FUTURISTIC TV
// --------------------------------------------------
def drawTV(c: CanvasDraw): Unit = {
val x = cx
val y = cy + 10
// Shadow
c.noStroke()
c.fill(0, 0, 0, 130)
c.ellipse(x, 48, 500, 40)
// TV body
c.fill(12, 24, 42)
c.stroke(0, 160, 220)
c.strokeWeight(4)
c.rect(x - 265, y - 105, 530, 290)
// Outer frame
c.noFill()
c.stroke(0, 230, 255, 180)
c.strokeWeight(2)
c.rect(x - 255, y - 95, 510, 270)
// Inner metallic border
c.stroke(80, 115, 150)
c.strokeWeight(2)
c.rect(x - 238, y - 78, 476, 236)
// Screen
c.fill(3, 15, 32)
c.stroke(0, 220, 255, alpha(140 + 90 *
math.sin(glow)))
c.strokeWeight(3)
c.rect(x - 225, y - 65, 450, 210)
// Screen glow
c.noStroke()
c.fill(0, 140, 220, 22)
c.ellipse(x, y + 20, 410, 180)
// Scan beam
val scanY = y - 60 + (scan % 195.0)
c.fill(0, 220, 255, 35)
c.rect(x - 220, scanY, 440, 9)
c.stroke(0, 230, 255, 120)
c.strokeWeight(1)
c.line(x - 220, scanY, x + 220, scanY)
// Screen scan lines
for (i <- 0 until 20) {
c.stroke(20, 180, 230, 18)
c.line(
x - 220,
y - 57 + i * 10.0,
x + 220,
y - 57 + i * 10.0
)
}
// Frame corner indicators
c.stroke(0, 255, 255)
c.strokeWeight(3)
c.line(x - 245, y + 145, x - 215, y + 145)
c.line(x - 245, y + 145, x - 245, y + 120)
c.line(x + 245, y + 145, x + 215, y + 145)
c.line(x + 245, y + 145, x + 245, y + 120)
c.line(x - 245, y - 85, x - 215, y - 85)
c.line(x + 245, y - 85, x + 215, y - 85)
// Buttons
for (i <- 0 until 3) {
c.fill(25, 80, 110)
c.stroke(0, 200, 255)
c.strokeWeight(1)
c.ellipse(x - 35 + i * 35, y - 88, 10, 10)
}
// Power LED
c.noStroke()
c.fill(0, 255, 190, alpha(120 + 120 *
math.sin(t * 4)))
c.ellipse(x + 215, y - 88, 9, 9)
// Stand
c.fill(15, 29, 48)
c.stroke(0, 160, 210)
c.strokeWeight(2)
c.rect(x - 45, 48, 90, 26)
c.rect(x - 100, 36, 200, 12)
c.fill(0, 190, 255, 70)
c.noStroke()
c.rect(x - 80, 39, 160, 3)
}
// --------------------------------------------------
// ROTATING ENERGY RINGS
// --------------------------------------------------
def energyRings(c: CanvasDraw): Unit = {
val x = cx
val y = cy + 2 + bob
c.noFill()
c.stroke(0, 210, 255, 90)
c.strokeWeight(2)
c.ellipse(x, y, 155, 100)
c.stroke(0, 255, 210, 120)
c.ellipse(
x,
y,
175 + math.sin(t * 2) * 8,
115 + math.cos(t * 2) * 6
)
// Energy nodes
for (i <- 0 until 8) {
val a = t * 1.5 + i * math.Pi / 4.0
val px = x + math.cos(a) * 82
val py = y + math.sin(a) * 48
c.noStroke()
c.fill(0, 230, 255, 210)
c.ellipse(px, py, 5, 5)
}
// Reactor beams
c.stroke(0, 180, 255, 55)
c.strokeWeight(1)
for (i <- 0 until 12) {
val a = t + i * math.Pi / 6.0
c.line(
x + math.cos(a) * 40,
y + math.sin(a) * 28,
x + math.cos(a) * 75,
y + math.sin(a) * 44
)
}
}
// --------------------------------------------------
// ROBOT LOWER BODY
// --------------------------------------------------
def drawBase(c: CanvasDraw): Unit = {
val x = cx
val y = cy - 8 + bob
// Legs
c.stroke(190, 220, 235)
c.strokeWeight(12)
c.line(x - 19, y - 35, x - 23, y - 57)
c.line(x + 19, y - 35, x + 23, y - 57)
// Feet
c.fill(25, 65, 90)
c.stroke(0, 220, 255)
c.strokeWeight(2)
c.ellipse(x - 25, y - 60, 29, 12)
c.ellipse(x + 25, y - 60, 29, 12)
// Hips
c.fill(120, 155, 180)
c.ellipse(x, y - 30, 56, 28)
}
// --------------------------------------------------
// ROBOT BODY + REACTOR
// --------------------------------------------------
def drawBody(c: CanvasDraw): Unit = {
val x = cx
val y = cy + 3 + bob
// Shoulder joints
c.fill(25, 85, 115)
c.stroke(0, 210, 255)
c.strokeWeight(2)
c.ellipse(x - 43, y + 28, 25, 28)
c.ellipse(x + 43, y + 28, 25, 28)
// Torso
c.fill(180, 205, 220)
c.stroke(45, 80, 105)
c.strokeWeight(3)
c.ellipse(x, y + 4, 82, 90)
// Chest armor
c.fill(28, 80, 112)
c.stroke(0, 210, 255)
c.strokeWeight(2)
c.ellipse(x, y + 17, 49, 50)
// Reactor aura
c.noStroke()
c.fill(0, 190, 255, alpha(60 +
60 * math.sin(t * 3)))
c.ellipse(x, y + 17, 40, 40)
// Reactor core
c.fill(0, 235, 255)
c.ellipse(x, y + 17, 24, 24)
c.fill(225, 255, 255)
c.ellipse(x, y + 17, 10, 10)
// Chest labels
c.fill(5, 35, 55)
c.text("AI", x - 7, y - 5)
// Chest status lights
for (i <- 0 until 3) {
c.fill(
0,
255,
190,
alpha(100 + 100 *
math.sin(t * 4 + i))
)
c.ellipse(x - 15 + i * 15, y - 22, 5, 5)
}
}
// --------------------------------------------------
// ARTICULATED ARMS
// --------------------------------------------------
def drawArms(c: CanvasDraw): Unit = {
val x = cx
val y = cy + 3 + bob
val swing =
if (waving) math.sin(wave) * 22
else math.sin(t * 2) * 4
// Left upper arm
c.stroke(195, 220, 235)
c.strokeWeight(10)
c.line(x - 42, y + 30, x - 61, y + 7)
c.fill(30, 100, 135)
c.stroke(0, 210, 255)
c.strokeWeight(2)
c.ellipse(x - 61, y + 7, 17, 17)
// Left forearm
c.stroke(195, 220, 235)
c.strokeWeight(8)
c.line(x - 61, y + 7, x - 69, y - 18)
c.fill(185, 215, 230)
c.stroke(0, 180, 220)
c.ellipse(x - 70, y - 22, 17, 18)
// Right arm
val handY = y + 12 + swing
c.stroke(195, 220, 235)
c.strokeWeight(10)
c.line(x + 42, y + 30, x + 61, y + 7)
c.fill(30, 100, 135)
c.stroke(0, 210, 255)
c.strokeWeight(2)
c.ellipse(x + 61, y + 7, 17, 17)
c.stroke(195, 220, 235)
c.strokeWeight(8)
c.line(x + 61, y + 7, x + 73, handY)
// Hand
c.fill(200, 225, 238)
c.stroke(0, 200, 245)
c.strokeWeight(2)
c.ellipse(x + 75, handY, 18, 20)
// Fingers
c.stroke(100, 180, 210)
c.strokeWeight(2)
for (i <- 0 until 3) {
c.line(
x + 79,
handY - 6 + i * 5,
x + 86,
handY - 8 + i * 5
)
}
}
// --------------------------------------------------
// ADVANCED ROBOT HEAD
// --------------------------------------------------
def drawHead(c: CanvasDraw): Unit = {
val x = cx + headX
val y = cy + 68 + bob
// Antenna
c.stroke(130, 180, 205)
c.strokeWeight(3)
c.line(x, y + 28, x, y + 43)
c.noStroke()
c.fill(0, 240, 255, alpha(120 +
120 * math.sin(t * 5)))
c.ellipse(x, y + 47, 15, 15)
c.fill(210, 255, 255)
c.ellipse(x, y + 47, 5, 5)
// Ears
c.fill(40, 105, 135)
c.stroke(0, 200, 255)
c.strokeWeight(2)
c.ellipse(x - 40, y, 13, 25)
c.ellipse(x + 40, y, 13, 25)
// Main head
c.fill(190, 215, 230)
c.stroke(65, 125, 155)
c.strokeWeight(3)
c.rect(x - 35, y - 27, 70, 55)
// Face visor
c.fill(4, 22, 40)
c.stroke(0, 210, 255)
c.strokeWeight(2)
c.rect(x - 29, y - 16, 58, 31)
// Eyes
val eyeHeight =
if (math.sin(blink) > 0.985) 2.0 else 10.0
c.noStroke()
c.fill(0, 190, 255, 70)
c.ellipse(x - 14 + eyeX, y + 1 + eyeY, 20, 19)
c.ellipse(x + 14 + eyeX, y + 1 + eyeY, 20, 19)
c.fill(70, 240, 255)
c.ellipse(x - 14 + eyeX, y + 1 + eyeY, 9, eyeHeight)
c.ellipse(x + 14 + eyeX, y + 1 + eyeY, 9, eyeHeight)
c.fill(255, 255, 255, 220)
c.ellipse(x - 16 + eyeX, y + 3 + eyeY, 3, 3)
c.ellipse(x + 12 + eyeX, y + 3 + eyeY, 3, 3)
// Mouth
c.stroke(0, 230, 255)
c.strokeWeight(2)
if (talking) {
c.noFill()
c.ellipse(
x,
y - 10,
15,
3 + math.abs(math.sin(t * 7)) * 7
)
} else {
c.line(x - 7, y - 10, x + 7, y - 10)
}
// Forehead LED
c.noStroke()
c.fill(0, 255, 210, alpha(140 +
100 * math.sin(t * 4)))
c.ellipse(x, y + 21, 7, 5)
}
// --------------------------------------------------
// HOLOGRAPHIC SPEECH PANEL
// --------------------------------------------------
def drawHUD(c: CanvasDraw): Unit = {
val x = cx + 108
val y = cy + 98
// Panel
c.fill(3, 22, 40, 235)
c.stroke(0, 210, 255, 220)
c.strokeWeight(2)
c.rect(x, y - 5, 126, 72)
// Header
c.fill(0, 175, 220, 100)
c.noStroke()
c.rect(x + 2, y + 48, 122, 16)
c.fill(180, 250, 255)
c.text("AI SYSTEM", x + 12, y + 53)
// Animated dialogue
c.fill(100, 245, 255)
c.text(messages(messageIndex), x + 7, y + 30)
c.fill(40, 170, 205)
c.text("STATUS: ACTIVE", x + 7, y + 13)
// Equalizer
for (i <- 0 until 12) {
val h = 3 +
math.abs(math.sin(t * 5 + i * 0.7)) * 10
c.fill(0, 220, 255, 210)
c.rect(x + 8 + i * 9, y - 1, 5, h)
}
}
// --------------------------------------------------
// RADAR HUD
// --------------------------------------------------
def drawRadar(c: CanvasDraw): Unit = {
val x = cx - 175
val y = cy + 102
c.noFill()
c.stroke(0, 180, 220, 110)
c.strokeWeight(1)
c.ellipse(x, y, 56, 56)
c.ellipse(x, y, 36, 36)
c.ellipse(x, y, 16, 16)
c.line(x - 28, y, x + 28, y)
c.line(x, y - 28, x, y + 28)
val a = t * 2.0
c.stroke(0, 255, 190)
c.strokeWeight(2)
c.line(
x, y,
x + math.cos(a) * 26,
y + math.sin(a) * 26
)
c.noStroke()
c.fill(0, 255, 190)
c.ellipse(
x + math.cos(a) * 18,
y + math.sin(a) * 18,
4,
4
)
c.fill(100, 220, 255)
c.text("SCANNER", x - 25, y - 37)
}
// --------------------------------------------------
// INTERACTION RIPPLE
// --------------------------------------------------
def drawRipple(c: CanvasDraw): Unit = {
if (clicked) {
ripple += 2.0
c.noFill()
c.stroke(0, 230, 255, alpha(220 - ripple))
c.strokeWeight(2)
c.ellipse(clickX, clickY, ripple, ripple)
c.ellipse(clickX, clickY, ripple * 0.65, ripple * 0.65)
if (ripple > 100) {
ripple = 0
clicked = false
}
}
}
// --------------------------------------------------
// STATUS BAR
// --------------------------------------------------
def drawStatus(c: CanvasDraw): Unit = {
c.fill(100, 230, 255)
c.noStroke()
c.text("N E U R O / A I", 20, cheight - 25)
c.fill(0, 255, 190)
c.text("SYSTEM ONLINE", cwidth - 125, cheight - 25)
c.fill(90, 170, 205)
c.text(
"TOUCH SCREEN TO ACTIVATE ROBOT",
cx - 125,
15
)
// Status indicator
c.fill(0, 255, 180, alpha(100 +
140 * math.abs(math.sin(t * 3))))
c.ellipse(cwidth - 20, cheight - 20, 8, 8)
}
// --------------------------------------------------
// MAIN ANIMATION LOOP
// --------------------------------------------------
def drawLoop(c: CanvasDraw): Unit = {
t += 0.045
glow += 0.07
scan += 1.6
blink += 0.035
pulse += 0.06
messageTimer += 0.045
if (messageTimer > 3.0) {
messageTimer = 0
messageIndex = (messageIndex + 1) % messages.length
}
backgroundFX(c)
drawTV(c)
// Mouse / touch interaction
if (isMousePressed) {
clickX = mouseX.toDouble
clickY = mouseY.toDouble
clicked = true
ripple = 0
waving = true
wave = 0
talking = !talking
messageIndex = (messageIndex + 1) % messages.length
messageTimer = 0
}
// Eye tracking
eyeX = clamp(
(mouseX.toDouble - cx) * 0.018,
-4.0,
4.0
)
eyeY = clamp(
(mouseY.toDouble - cy) * 0.018,
-3.0,
3.0
)
// Smooth head tracking
val desiredHead = clamp(
(mouseX.toDouble - cx) * 0.025,
-9.0,
9.0
)
headX += (desiredHead - headX) * 0.08
// Floating body
bob = math.sin(t * 2.0) * 2.5
// Wave animation
if (waving) {
wave += 0.22
if (wave > 6.28) {
waving = false
wave = 0
}
}
energyRings(c)
drawBase(c)
drawBody(c)
drawArms(c)
drawHead(c)
drawHUD(c)
drawRadar(c)
drawRipple(c)
drawStatus(c)
}
}
val sketch = new Sketch
canvasSketch(sketch)