Code Sketch


navya
By: Mhalsakant School
Category: Art
// ========================================
// SPACE SHOOTER
// Kojo Coding Competition
// ========================================

cleari()
originBottomLeft()

// GAME VARIABLES

var shipX = 400.0
var shipY = 90.0

var score = 0
var lives = 3
var gameOver = false
var tick = 0

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 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(starX.length)(false)

// KEYBOARD CONTROLS

onKeyPress { key =>
    if (!gameOver) {
        if (key == Kc.VK_LEFT) {
            shipX -= 25
        }

        if (key == Kc.VK_RIGHT) {
            shipX += 25
        }

        shipX = math.max(
            30,
            math.min(cwidth - 30, shipX)
        )
    }
}

// DRAW BACKGROUND

def drawBackground(canvas: CanvasDraw) {
    canvas.fill(5, 5, 30)
    canvas.noStroke()
    canvas.rect(0, 0, cwidth, cheight)

    canvas.fill(180, 200, 255)

    for (i <- 0 until 50) {
        val x = (i * 137) % cwidth.toInt
        val y = (i * 197) % cheight.toInt

        canvas.ellipse(
            x.toDouble,
            y.toDouble,
            3,
            3
        )
    }
}

// DRAW SPACESHIP

def drawShip(canvas: CanvasDraw) {
    canvas.fill(0, 220, 255)
    canvas.stroke(255, 255, 255)
    canvas.strokeWeight(2)

    canvas.rect(
        shipX - 20,
        shipY - 15,
        40,
        30
    )

    canvas.fill(255, 80, 20)
    canvas.noStroke()

    canvas.ellipse(
        shipX,
        shipY - 20,
        14,
        18
    )

    canvas.fill(255, 255, 0)

    canvas.ellipse(
        shipX,
        shipY + 5,
        12,
        12
    )
}

// DRAW METEORS

def drawMeteors(canvas: CanvasDraw) {
    canvas.fill(255, 80, 40)
    canvas.stroke(255, 180, 80)
    canvas.strokeWeight(2)

    for (i <- meteorX.indices) {
        canvas.ellipse(
            meteorX(i),
            meteorY(i),
            30,
            30
        )
    }
}

// DRAW STARS

def drawStars(canvas: CanvasDraw) {
    for (i <- starX.indices) {
        if (!starTaken(i)) {
            canvas.fill(255, 240, 0)
            canvas.noStroke()

            canvas.ellipse(
                starX(i),
                starY(i),
                18,
                18
            )
        }
    }
}

// UPDATE GAME

def updateGame() {
    if (!gameOver) {
        tick += 1

        // Move meteors

        for (i <- meteorY.indices) {
            meteorY(i) -= 5

            if (meteorY(i) < 0) {
                meteorY(i) = cheight + 50
                meteorX(i) =
                    randomDouble(30, cwidth - 30)
            }

            // Meteor collision

            if (
                math.abs(meteorX(i) - shipX) < 30 &&
                math.abs(meteorY(i) - shipY) < 30
            ) {
                lives -= 1
                meteorY(i) = cheight + 100

                if (lives <= 0) {
                    gameOver = true
                }
            }
        }

        // Move stars

        for (i <- starY.indices) {
            starY(i) -= 3

            if (starY(i) < 0) {
                starY(i) = cheight + 100
                starTaken(i) = false
            }

            // Collect stars

            if (
                !starTaken(i) &&
                math.abs(starX(i) - shipX) < 25 &&
                math.abs(starY(i) - shipY) < 25
            ) {
                starTaken(i) = true
                score += 10
            }
        }

        // Bonus points for survival

        if (tick % 100 == 0) {
            score += 5
        }
    }
}

// DRAW SCOREBOARD

def drawScore(canvas: CanvasDraw) {
    canvas.fill(255, 255, 255)
    canvas.noStroke()

    canvas.text(
        s"SCORE: $score",
        25,
        cheight - 35
    )

    canvas.text(
        s"LIVES: $lives",
        25,
        cheight - 60
    )

    canvas.text(
        "SPACE SHOOTER",
        cwidth / 2 - 65,
        cheight - 35
    )
}

// GAME OVER SCREEN

def drawGameOver(canvas: CanvasDraw) {
    canvas.fill(10, 10, 35)
    canvas.noStroke()
    canvas.rect(0, 0, cwidth, cheight)

    canvas.fill(255, 60, 60)

    canvas.text(
        "GAME OVER!",
        cwidth / 2 - 55,
        cheight / 2 + 40
    )

    canvas.fill(255, 255, 255)

    canvas.text(
        s"FINAL SCORE: $score",
        cwidth / 2 - 65,
        cheight / 2
    )

    canvas.text(
        "Refresh to play again",
        cwidth / 2 - 75,
        cheight / 2 - 40
    )
}

// GAME LOOP

animateWithCanvasDraw { canvas =>
    updateGame()

    if (!gameOver) {
        drawBackground(canvas)
        drawStars(canvas)
        drawMeteors(canvas)
        drawShip(canvas)
        drawScore(canvas)
    } else {
        drawGameOver(canvas)
    }
}