pxt-calliope/tests/wg-catching-raindrops.ts

249 lines
8.9 KiB
TypeScript

let speed: number
let cupCapacity: number
let maxMisses: number
let autoEmpty: boolean
let movement: boolean
let sensitivity: number
let cupX: number
let cupInverted: boolean
let highscore = 0
while (true) {
// configure game settings
// ##CHALLENGE1: reconfigure game
cupCapacity = 5
speed = 6
maxMisses = 3
autoEmpty = false
movement = true
sensitivity = 400
cupX = 2
// show the spash screen
// ##CHALLENGE 2: CHANGE SPLASH SCREEN
basic.showAnimation(`
. . . . . . . . . .
. . . . . . # . # .
. . . . . . . . . .
. # . # . . # . # .
. # # # . . # # # .
`, 400)
// Decide what to do based on which button is pressed
if (input.buttonIsPressed(Button.A)) {
let finalScore = playGame()
// ##CHALLENGE 3 ADD HIGH SCORE
if (finalScore > highscore) {
basic.showString("HIGH", 150)
highscore = finalScore
}
basic.showNumber(finalScore, 150)
} else if (input.buttonIsPressed(Button.B)) {
testMovement()
} else {
basic.pause(100)
}
}
function playGame(): number {
let cup = images.createImage(`
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . # . # . . . . . .
. . . . . . # # # . . . . . .
`)
let score = 0
let dropsInCup = 0
let misses = 0
let dropX = 0
let dropY = 0
let prevDropY = -1
let cupX1 = 2
let prevCupX = -1
let state = "NEWDROP"
startGame()
while (true) {
if (state == "NEWDROP") {
// create a new drop at a random position
dropX = Math.random(5)
dropY = 0
state = "RAINING"
} else if (state == "RAINING") {
// calculate new positions
cupX1 = getCupPosition()
let thisDropY = dropY / speed
// Only redraw the screen if something has changed (prevent flashing)
if (cupX1 != prevCupX || thisDropY != prevDropY) {
basic.clearScreen()
// draw cup
cup.showImage(7 - cupX1)
if (dropsInCup == cupCapacity) {
// a full cup
led.plot(cupX1, 3)
}
// draw drop
led.plot(dropX, thisDropY)
prevCupX = cupX1
prevDropY = thisDropY
}
basic.pause(100)
if (thisDropY >= 4) {
state = "ATCUP"
} else {
dropY = dropY + 1
}
if (cupInverted && dropsInCup >= cupCapacity) {
state = "EMPTYING"
}
} else if (state == "ATCUP") {
if (dropX == cupX1) {
state = "CATCH"
} else {
state = "MISS"
}
} else if (state == "MISS") {
// ##CHALLENGE: long beep on miss
beep(500)
misses = misses + 1
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . .
. . . . . . # . # . . . . . . . . . . .
. . . . . . # # # . . # . # . . . . . .
. # . # . . . . . . . # # # . . # . # .
. # # # . . . # . . . . . . . . # # # .
`, 400)
if (misses > maxMisses) {
state = "GAMEOVER"
} else {
state = "NEWDROP"
}
} else if (state == "CATCH") {
// ##CHALLENGE: short beep on catch
beep(200)
dropsInCup = dropsInCup + 1
basic.showAnimation(`
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. # # # . # . # . # . # . # .
. # # # . # # # # # . # # # .
`, 400)
if (dropsInCup == cupCapacity) {
state = "FULL"
score = score + 1
} else if (dropsInCup > cupCapacity) {
state = "OVERFLOW"
} else {
score = score + 1
state = "NEWDROP"
}
} else if (state == "FULL") {
basic.showAnimation(`
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . # # # . . . . . .
. # # # . . # # # . . # # # .
. # # # . . # # # . . # # # .
`, 400)
if (autoEmpty) {
state = "EMPTYING"
} else {
state = "NEWDROP"
}
} else if (state == "EMPTYING") {
if (cupInverted) {
basic.showAnimation(`
. . . . . . . . . . . . . . . . . # . . . . . . .
. . . . . . . . . . . . # . . . . . . . . . . . .
. . . . . . . # . . . . . . . . . . . . . . . . .
. # # # . . # . # . . # . # . . # . # . . # . # .
. # # # . . # # # . . # # # . . # # # . . # # # .
`, 400)
} else {
basic.showAnimation(`
. . . . . . . . . . . # # # . . # # # . . # # # . . # # # . . # # # . . . . . . . . . . .
. . . . . . # # . . . # # # . . # . # . . # . # . . # . # . . # . # . . # # . . . . . . .
. . . . . . # # . . . . . . . . . # . . . . . . . . . . . . . . . . . . # . . . . . . . .
. # # # . . # # . . . . . . . . . . . . . . # . . . . . . . . . . . . . # # . . . # . # .
. # # # . . . . . . . . . . . . . . . . . . . . . . . # . . . . . . . . . . . . . # # # .
`, 400)
}
dropsInCup = 0
// ##CHALLENGE: Speed up on every level change
if (speed > 1) {
speed = speed - 1
}
state = "NEWDROP"
} else if (state == "OVERFLOW") {
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . # # # . . # . # . . . . . . . . . . . . . . . .
. # # # . . # # # . # # # # # # # # # # . # # # . . # # # .
. # # # . . # # # . . # # # . . # # # . # # # # # . # # # .
`, 400)
state = "GAMEOVER"
} else if (state == "GAMEOVER") {
// ##CHALLENGE: Make a sound on game over
beep(700)
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # . # # # # # . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # . # # # # # . # . # . . . . . . . . . . . . # . # . . . . . .
. . . . . . . . . . . . . . . . . . . . . # # # . # # # # # . # . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. # . # . . . . . . . # # # . # # # # # . # . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. # # # . # # # # # . # . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
`, 400)
break
}
}
return score
}
function testMovement() {
while (!input.buttonIsPressed(Button.A)) {
// ##CHALLENGE 5: Add accelerometer test mode
let x = getCupPosition()
basic.clearScreen()
led.plot(x, 2)
basic.pause(200)
}
}
function getCupPosition(): number {
if (movement) {
let acc = input.acceleration(Dimension.X) / sensitivity
cupX = Math.clamp(0, 4, acc + 2)
return cupX
}
if (input.buttonIsPressed(Button.A)) {
if (cupX > 0) {
cupX = cupX - 1
}
} else if (input.buttonIsPressed(Button.B)) {
if (cupX < 4) {
cupX = cupX + 1
}
}
return cupX
}
function startGame() {
basic.clearScreen()
// If button still held from start-game, wait until it is released
while (input.buttonIsPressed(Button.A)) {
// wait for button to be released
}
// handlers that work out if cup is turned upside down or not
input.onLogoDown(() => {
cupInverted = true
})
input.onLogoUp(() => {
cupInverted = false
})
}
function beep(p: number) {
pins.digitalWritePin(DigitalPin.P0, 1)
basic.pause(p)
pins.digitalWritePin(DigitalPin.P0, 0)
}