Code Sketch
Navya Tembhurne
Category: Art
// ============================================================
// ? AI ROBOT ? ENERGY RUN
// NO QUESTIONS ? NO QUIZ
// ============================================================
cleari()
originBottomLeft()
// ============================================================
// GAME VARIABLES
// ============================================================
var robotX = 100.0
var robotY = 120.0
var velocityY = 0.0
var grounded = true
var score = 0
var energy = 100
var gameOver = false
var victory = false
var time = 0.0
var pulse = 0.0
// ============================================================
// ENERGY ORBS
// ============================================================
val orbX = Array(
180.0,
330.0,
470.0,
610.0,
760.0,
250.0,
540.0,
700.0
)
val orbY = Array(
120.0,
190.0,
120.0,
220.0,
120.0,
300.0,
350.0,
280.0
)
val collected =
Array.fill(orbX.length)(false)
// ============================================================
// OBSTACLES
// ============================================================
val obstacleX = Array(
280.0,
430.0,
580.0,
720.0
)
val obstacleY = Array(
100.0,
100.0,
100.0,
100.0
)
// ============================================================
// BACKGROUND STARS
// ============================================================
val starCount = 120
val starsX =
Array.fill(starCount)(
randomDouble(0, cwidth)
)
val starsY =
Array.fill(starCount)(
randomDouble(0, cheight)
)
// ============================================================
// PARTICLES
// ============================================================
class Particle(
x0: Double,
y0: Double
) {
var x = x0
var y = y0
var vx =
randomDouble(-3, 3)
var vy =
randomDouble(2, 6)
var life = 255.0
def update() {
x += vx
y += vy
vy -= 0.15
life -= 5
}
def draw(canvas: CanvasDraw) {
canvas.stroke(
0,
255,
255,
life.toInt
)
canvas.strokeWeight(3)
canvas.point(
x,
y
)
}
}
val particles =
ArrayBuffer.empty[Particle]
// ============================================================
// EXPLOSION
// ============================================================
def explosion(
x: Double,
y: Double
) {
repeat(25) {
particles.append(
new Particle(
x,
y
)
)
}
}
// ============================================================
// BACKGROUND
// ============================================================
def drawBackground(
canvas: CanvasDraw
) {
canvas.fill(
2,
5,
20
)
canvas.noStroke()
canvas.rect(
0,
0,
cwidth,
cheight
)
// Stars
canvas.stroke(
120,
200,
255
)
for (i <- 0 until starCount) {
canvas.strokeWeight(
randomDouble(1, 2)
)
canvas.point(
starsX(i),
starsY(i)
)
}
// Ground
canvas.fill(
8,
20,
35
)
canvas.rect(
0,
60,
cwidth,
45
)
// Neon ground
canvas.stroke(
0,
255,
255
)
canvas.strokeWeight(2)
canvas.line(
0,
105,
cwidth,
105
)
}
// ============================================================
// ENERGY ORBS
// ============================================================
def drawOrbs(
canvas: CanvasDraw
) {
for (i <- orbX.indices) {
if (!collected(i)) {
val glow =
math.sin(
pulse + i
) * 7
// Glow
canvas.fill(
0,
255,
255,
25
)
canvas.noStroke()
canvas.ellipse(
orbX(i),
orbY(i),
40 + glow,
40 + glow
)
// Orb
canvas.fill(
0,
240,
255
)
canvas.stroke(
200,
255,
255
)
canvas.strokeWeight(2)
canvas.ellipse(
orbX(i),
orbY(i),
18,
18
)
// Center
canvas.fill(
255,
255,
255
)
canvas.noStroke()
canvas.ellipse(
orbX(i),
orbY(i),
6,
6
)
}
}
}
// ============================================================
// OBSTACLES
// ============================================================
def drawObstacles(
canvas: CanvasDraw
) {
for (i <- obstacleX.indices) {
canvas.fill(
100,
10,
60
)
canvas.stroke(
255,
0,
100
)
canvas.strokeWeight(3)
canvas.rect(
obstacleX(i),
obstacleY(i),
35,
55
)
// Warning light
canvas.fill(
255,
50,
50
)
canvas.ellipse(
obstacleX(i) + 17,
obstacleY(i) + 42,
8,
8
)
}
}
// ============================================================
// AI ROBOT
// ============================================================
def drawRobot(
canvas: CanvasDraw
) {
val bob =
math.sin(time * 5) * 3
val x =
robotX
val y =
robotY + bob
// Aura
canvas.fill(
0,
255,
255,
20
)
canvas.noStroke()
canvas.ellipse(
x,
y + 30,
80,
100
)
// Legs
canvas.stroke(
70,
120,
150
)
canvas.strokeWeight(7)
canvas.line(
x - 12,
y,
x - 12,
y - 25
)
canvas.line(
x + 12,
y,
x + 12,
y - 25
)
// Body
canvas.fill(
35,
50,
75
)
canvas.stroke(
0,
230,
255
)
canvas.strokeWeight(3)
canvas.rect(
x - 27,
y,
54,
55
)
// Chest core
canvas.fill(
0,
220,
255
)
canvas.ellipse(
x,
y + 27,
20,
20
)
canvas.fill(
255,
255,
255
)
canvas.ellipse(
x,
y + 27,
7,
7
)
// Head
canvas.fill(
55,
70,
95
)
canvas.stroke(
0,
255,
255
)
canvas.strokeWeight(3)
canvas.rect(
x - 35,
y + 55,
70,
48
)
// Face
canvas.fill(
2,
15,
30
)
canvas.rect(
x - 27,
y + 65,
54,
28
)
// Eyes
canvas.fill(
0,
255,
255
)
canvas.ellipse(
x - 14,
y + 79,
10,
7
)
canvas.ellipse(
x + 14,
y + 79,
10,
7
)
// Antenna
canvas.stroke(
0,
220,
255
)
canvas.strokeWeight(3)
canvas.line(
x,
y + 103,
x,
y + 125
)
canvas.fill(
255,
0,
180
)
canvas.ellipse(
x,
y + 130,
10,
10
)
}
// ============================================================
// COLLISION WITH ORBS
// ============================================================
def collectOrbs() {
for (i <- orbX.indices) {
if (!collected(i)) {
val dx =
robotX - orbX(i)
val dy =
robotY - orbY(i)
val distance =
math.sqrt(
dx * dx +
dy * dy
)
if (distance < 35) {
collected(i) = true
score += 100
energy =
math.min(
100,
energy + 10
)
explosion(
orbX(i),
orbY(i)
)
}
}
}
}
// ============================================================
// OBSTACLE COLLISION
// ============================================================
def checkObstacles() {
for (i <- obstacleX.indices) {
if (
math.abs(
robotX -
(obstacleX(i) + 17)
) < 30 &&
robotY < obstacleY(i) + 60 &&
robotY > obstacleY(i) - 10
) {
energy -= 1
robotX -= 5
if (energy <= 0) {
gameOver = true
}
}
}
}
// ============================================================
// WIN CHECK
// ============================================================
def checkVictory() {
var allCollected = true
for (i <- collected.indices) {
if (!collected(i))
allCollected = false
}
if (allCollected) {
victory = true
explosion(
robotX,
robotY
)
}
}
// ============================================================
// PARTICLES UPDATE
// ============================================================
def updateParticles() {
particles.filterInPlace(
p => p.life > 0
)
repeatFor(particles) { p =>
p.update()
}
}
// ============================================================
// UPDATE
// ============================================================
def updateState() {
time += 0.05
pulse += 0.08
updateParticles()
if (
!gameOver &&
!victory
) {
// Gravity
if (!grounded) {
velocityY -= 0.45
robotY += velocityY
}
// Ground
if (robotY <= 120) {
robotY = 120
velocityY = 0
grounded = true
}
collectOrbs()
checkObstacles()
checkVictory()
}
}
// ============================================================
// KEYBOARD
// ============================================================
onKeyPress { key =>
if (
!gameOver &&
!victory
) {
if (
key == Kc.VK_RIGHT
) {
robotX += 12
}
if (
key == Kc.VK_LEFT
) {
robotX -= 12
}
if (
key == Kc.VK_UP &&
grounded
) {
velocityY = 11
grounded = false
}
robotX =
math.max(
40,
math.min(
cwidth - 320,
robotX
)
)
}
}
// ============================================================
// UI
// ============================================================
def drawUI(
canvas: CanvasDraw
) {
canvas.fill(
5,
12,
30,
220
)
canvas.stroke(
0,
220,
255
)
canvas.strokeWeight(2)
canvas.rect(
20,
cheight - 100,
250,
70
)
canvas.fill(
0,
255,
255
)
canvas.text(
"? AI ENERGY RUN",
35,
cheight - 50
)
canvas.fill(
255,
255,
255
)
canvas.text(
s"ENERGY: $energy%",
35,
cheight - 75
)
canvas.text(
s"SCORE: $score",
155,
cheight - 75
)
canvas.fill(
100,
120,
140
)
canvas.text(
"? ? MOVE ? JUMP",
cwidth - 220,
35
)
}
// ============================================================
// GAME OVER
// ============================================================
def drawGameOver(
canvas: CanvasDraw
) {
canvas.fill(
5,
5,
20,
240
)
canvas.rect(
0,
0,
cwidth,
cheight
)
canvas.fill(
255,
40,
80
)
canvas.text(
"SYSTEM OFFLINE",
cwidth / 2 - 65,
cheight / 2 + 40
)
canvas.fill(
255,
255,
255
)
canvas.text(
s"SCORE: $score",
cwidth / 2 - 40,
cheight / 2
)
canvas.text(
"Refresh to restart",
cwidth / 2 - 55,
cheight / 2 - 40
)
}
// ============================================================
// VICTORY
// ============================================================
def drawVictory(
canvas: CanvasDraw
) {
canvas.fill(
5,
10,
25,
240
)
canvas.rect(
0,
0,
cwidth,
cheight
)
canvas.fill(
0,
255,
220
)
canvas.text(
"? AI FULLY CHARGED ?",
cwidth / 2 - 100,
cheight / 2 + 60
)
canvas.fill(
255,
255,
255
)
canvas.text(
s"FINAL SCORE: $score",
cwidth / 2 - 55,
cheight / 2 + 20
)
canvas.text(
"MISSION COMPLETE!",
cwidth / 2 - 65,
cheight / 2 - 20
)
}
// ============================================================
// VIEW
// ============================================================
def viewState(
canvas: CanvasDraw
) {
drawBackground(canvas)
if (
!gameOver &&
!victory
) {
drawOrbs(canvas)
drawObstacles(canvas)
drawRobot(canvas)
drawUI(canvas)
} else if (gameOver) {
drawGameOver(canvas)
} else {
drawVictory(canvas)
}
repeatFor(particles) { p =>
p.draw(canvas)
}
}
// ============================================================
// GAME LOOP
// ============================================================
animateWithCanvasDraw { canvas =>
updateState()
viewState(canvas)
}