Code Sketch
dolly 24
Category: Art
cleari()
originBottomLeft()
var shipX = 400.0
var shipY = 90.0
var score = 0
var lives = 3
var level = 1
var tick = 0
var gameOver = false
var bossActive = false
var bossX = 400.0
var bossHP = 10
var bossMaxHP = 10
var bossDir = 1.0
var nextBossScore = 50
val meteorX = Array(100.0, 250.0, 400.0, 550.0, 700.0)
val meteorY = Array(500.0, 650.0, 800.0, 950.0, 1100.0)
val bulletX = Array.fill(20)(0.0)
val bulletY = Array.fill(20)(0.0)
val bulletOn = Array.fill(20)(false)
val starX = Array(180.0, 350.0, 520.0, 680.0)
val starY = Array(400.0, 600.0, 800.0, 1000.0)
val starTaken = Array.fill(4)(false)
def resetGame() {
shipX = 400.0
score = 0
lives = 3
level = 1
tick = 0
gameOver = false
bossActive = false
bossX = 400.0
bossHP = 10
bossMaxHP = 10
bossDir = 1.0
nextBossScore = 50
for (i <- meteorY.indices) {
meteorY(i) = 500.0 + i * 150.0
meteorX(i) = 100.0 + i * 140.0
}
for (i <- bulletOn.indices) {
bulletOn(i) = false
}
for (i <- starTaken.indices) {
starTaken(i) = false
starY(i) = 400.0 + i * 200.0
}
}
def fireBullet() {
for (i <- bulletOn.indices) {
if (!bulletOn(i)) {
bulletOn(i) = true
bulletX(i) = shipX
bulletY(i) = shipY + 20
return
}
}
}
onKeyPress { key =>
if (key == Kc.VK_R) {
resetGame()
}
if (!gameOver) {
if (key == Kc.VK_LEFT) {
shipX = math.max(25.0, shipX - 25.0)
}
if (key == Kc.VK_RIGHT) {
shipX = math.min(cwidth - 25.0, shipX + 25.0)
}
if (key == Kc.VK_SPACE) {
fireBullet()
}
}
}
def drawBackground(c: CanvasDraw) {
c.fill(3, 4, 25)
c.noStroke()
c.rect(0, 0, cwidth, cheight)
for (i <- 0 until 70) {
val x = (i * 137 + tick * (i % 3 + 1)) % cwidth.toInt
val y = (i * 197) % cheight.toInt
c.fill(120, 180, 255)
c.ellipse(x.toDouble, y.toDouble, 2, 2)
}
c.fill(20, 25, 65)
c.rect(0, 0, cwidth, 5)
}
def drawShip(c: CanvasDraw) {
c.fill(0, 210, 255)
c.stroke(255, 255, 255)
c.strokeWeight(2)
c.rect(shipX - 18, shipY - 12, 36, 28)
c.fill(30, 90, 255)
c.noStroke()
c.ellipse(shipX, shipY + 17, 22, 24)
c.fill(255, 100, 10)
c.ellipse(shipX, shipY - 20, 12, 18)
c.fill(255, 255, 100)
c.ellipse(shipX, shipY + 5, 10, 10)
}
def drawMeteors(c: CanvasDraw) {
for (i <- meteorX.indices) {
c.fill(190, 65, 45)
c.stroke(255, 150, 60)
c.strokeWeight(2)
c.ellipse(meteorX(i), meteorY(i), 30, 30)
}
}
def drawBullets(c: CanvasDraw) {
for (i <- bulletOn.indices) {
if (bulletOn(i)) {
c.fill(50, 255, 100)
c.noStroke()
c.rect(bulletX(i) - 3, bulletY(i), 6, 18)
}
}
}
def drawStars(c: CanvasDraw) {
for (i <- starX.indices) {
if (!starTaken(i)) {
c.fill(255, 235, 0)
c.noStroke()
c.ellipse(starX(i), starY(i), 18, 18)
}
}
}
def drawBoss(c: CanvasDraw) {
if (bossActive) {
c.fill(180, 20, 90)
c.stroke(255, 80, 150)
c.strokeWeight(3)
c.rect(bossX - 55, cheight - 150, 110, 55)
c.fill(255, 30, 50)
c.noStroke()
c.ellipse(bossX - 28, cheight - 122, 15, 15)
c.ellipse(bossX + 28, cheight - 122, 15, 15)
c.fill(255, 255, 255)
c.text(
s"BOSS HP: $bossHP",
bossX - 40,
cheight - 80
)
}
}
def updateGame() {
if (!gameOver) {
tick += 1
val meteorSpeed = 4.0 + level * 0.7
val starSpeed = 3.0 + level * 0.2
for (i <- meteorY.indices) {
meteorY(i) -= meteorSpeed
if (meteorY(i) < 0) {
meteorY(i) = cheight + 30
meteorX(i) = randomDouble(30, cwidth - 30)
}
if (
math.abs(meteorX(i) - shipX) < 30 &&
math.abs(meteorY(i) - shipY) < 28
) {
lives -= 1
meteorY(i) = cheight + 100
meteorX(i) = randomDouble(30, cwidth - 30)
if (lives <= 0) {
gameOver = true
}
}
}
for (i <- bulletOn.indices) {
if (bulletOn(i)) {
bulletY(i) += 12
if (bulletY(i) > cheight) {
bulletOn(i) = false
}
for (j <- meteorX.indices) {
if (
bulletOn(i) &&
math.abs(bulletX(i) - meteorX(j)) < 25 &&
math.abs(bulletY(i) - meteorY(j)) < 25
) {
bulletOn(i) = false
meteorY(j) = cheight + 50
meteorX(j) = randomDouble(30, cwidth - 30)
score += 5
}
}
if (
bulletOn(i) &&
bossActive &&
math.abs(bulletX(i) - bossX) < 60 &&
math.abs(bulletY(i) - (cheight - 120)) < 40
) {
bulletOn(i) = false
bossHP -= 1
if (bossHP <= 0) {
bossActive = false
score += 50
level += 1
nextBossScore += 50
bossHP = 10 + level * 3
bossMaxHP = bossHP
}
}
}
}
for (i <- starY.indices) {
starY(i) -= starSpeed
if (starY(i) < 0) {
starY(i) = cheight + 80
starX(i) = randomDouble(30, cwidth - 30)
starTaken(i) = false
}
if (
!starTaken(i) &&
math.abs(starX(i) - shipX) < 25 &&
math.abs(starY(i) - shipY) < 25
) {
starTaken(i) = true
score += 10
}
}
if (score >= nextBossScore && !bossActive) {
bossActive = true
}
if (bossActive) {
bossX += bossDir * (3.0 + level * 0.3)
if (bossX > cwidth - 65) {
bossDir = -1.0
}
if (bossX < 65) {
bossDir = 1.0
}
}
if (tick % 100 == 0) {
score += 5
}
}
}
def drawScore(c: CanvasDraw) {
c.fill(255, 255, 255)
c.noStroke()
c.text(s"SCORE: $score", 20, cheight - 30)
c.text(s"LIVES: $lives", 20, cheight - 55)
c.text(s"LEVEL: $level", 20, cheight - 80)
c.text("SPACE SHOOTER", cwidth / 2 - 60, cheight - 30)
}
def drawGameOver(c: CanvasDraw) {
c.fill(5, 5, 30)
c.noStroke()
c.rect(0, 0, cwidth, cheight)
c.fill(255, 50, 70)
c.text("GAME OVER!", cwidth / 2 - 45, cheight / 2 + 35)
c.fill(255, 255, 255)
c.text(s"FINAL SCORE: $score", cwidth / 2 - 55, cheight / 2)
c.text(s"LEVEL REACHED: $level", cwidth / 2 - 60, cheight / 2 - 30)
c.text("Press R to Restart", cwidth / 2 - 60, cheight / 2 - 65)
}
animateWithCanvasDraw { c =>
updateGame()
if (!gameOver) {
drawBackground(c)
drawStars(c)
drawMeteors(c)
drawBullets(c)
drawShip(c)
drawBoss(c)
drawScore(c)
} else {
drawGameOver(c)
}
}