Kojo Wiki

docs for Kojo

View source on GitHub

Sample game - Recall Power

This activity has the following desired goals:

  • Learning to understand a given (more complex) game (M, T).
  • Learning to make selected changes in a given piece of (complex) code (M, T).

Game code

The code for the game is shown below. Study it to fully understand how the game works.

cleari()
setBackground(white)
val cb = canvasBounds

val randomNums = ArrayBuffer.empty[Int]

repeat(4) {
    var n = random(1, 10)
    while (randomNums.contains(n)) {
        n = random(1, 10)
    }
    randomNums.append(n)
}

def gameOver() {
    stopAnimation()
    erasePictures()
    drawCenteredMessage(s"Game Over. Your score is: $score", cm.darkGreen, 30)
}

var currNumber = 0
var prevNum = 0
var currNumberPic = Picture.text("")
var playerTurn = false
val currSeq = ArrayBuffer.empty[Int]
var currSeqIdx = 0
val numToPic = HashMap.empty[Int, Picture]
var seqLen = 4
var erase = false
var score = 0

val scorePic = Picture.text(score, 20)
scorePic.setPosition(cb.x, cb.y + cb.height)
scorePic.setPenColor(black)

def reset() {
    playerTurn = false
    currSeq.clear()
    currSeqIdx = 0
    seqLen += 1
    horivert.setFillColor(cm.darkBlue)
}

def currClickHandler(n: Int) {
    if (n == currSeq(currSeqIdx)) {
        if (currSeqIdx == currSeq.length - 1) {
            reset()
        }
        else {
            currSeqIdx += 1
        }
        score += 1
        scorePic.update(score)
    }
    else {
        gameOver()
    }
}

onKeyPress { c =>
    if (playerTurn) {
        val num = c - 48
        val pic = numToPic.getOrElse(num, null)
        if (pic != null) {
            pic.setPenColor(red)
        }
        else {
            gameOver()
        }
    }
}

onKeyRelease { c =>
    if (playerTurn) {
        val num = c - 48
        val pic = numToPic.getOrElse(num, null)
        if (pic != null) {
            pic.setPenColor(black)
            currClickHandler(num)
        }
        else {
            gameOver()
        }
    }
}

def textOnRect(n: Int) = {
    val pic = penColor(black) -> picStackCentered(fillColor(cm.darkBlue) -> Picture.rectangle(50, 50), Picture.text(n, 20))
    pic.onMousePress { (x, y) =>
        if (playerTurn) {
            pic.setPenColor(red)
        }
    }
    pic.onMouseRelease { (x, y) =>
        if (playerTurn) {
            pic.setPenColor(black)
            currClickHandler(n)
        }
    }
    numToPic.put(n, pic)
    pic
}

val horizontalPics = picRowCentered(
    textOnRect(randomNums(0)), Picture.hgap(50), textOnRect(randomNums(1)))

val verticalPics = picColCentered(
    textOnRect(randomNums(2)), Picture.vgap(50), textOnRect(randomNums(3)))

val horivert = picStackCentered(horizontalPics, verticalPics)

drawCentered(horivert)

draw(scorePic)

def switchToPlayerMode() {
    playerTurn = true
    horivert.setFillColor(cm.lightBlue)
}

timer(500) {
    if (!playerTurn) {
        if (erase) {
            currNumberPic.erase()
            erase = false
            if (currSeq.length == seqLen) {
                switchToPlayerMode()
            }
        }
        else {
            currNumber = randomFrom(randomNums)
            while (currNumber == prevNum) {
                currNumber = randomFrom(randomNums)
            }
            currSeq.append(currNumber)
            currNumberPic = Picture.text(currNumber, 20)
            currNumberPic.setPenColor(cm.darkGreen)
            drawCentered(currNumberPic)
            erase = true
            prevNum = currNumber
        }
    }
}
activateCanvas()
val maxTime = 60
showGameTime(maxTime + 1, "", cm.darkGreen, 15)

timer(maxTime * 1000) {
    gameOver()
}

Exercise

1. Improve the dynamics of the game as you see fit!


Copyright © 2010–2022. Licensed as per Terms of Use.