249 lines
8.9 KiB
TypeScript
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)
|
||
|
}
|