pxt-microbit/tests/wg-perfect-pancakes.ts

268 строки
9.9 KiB
TypeScript

let state: string
let timer: number
let gesturesRunning: boolean
let wasShake: boolean
let wasLogoUp: boolean
let wasLogoDown: boolean
let wasScreenUp: boolean
let wasScreenDown: boolean
while (true) {
splashScreen()
if (input.buttonIsPressed(Button.B)) {
// animate: add pancake
basic.showAnimation(`
# # # # # # . . . # . . . . . . . . . . . . . . .
. . . . . . # # # . . # # # . . . . . . . . . . .
. . . . . . . . . . # . . . # # . . . # . . . . .
. . . . . . . . . . . . . . . . # # # . . # # # .
. . . . . . . . . . . . . . . . . . . . # . . . #
`, 250)
runGameOnce()
// animate: pancake done
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # . # # # # # . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . # . . . # # # # # # # . . . # . . . . . . . . . . . # . # . . . . . . . # . # . . . . . .
. . . . . . . . . . . # # # . # # # # # . # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# . . . # # # # # # # . . . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
`, 250)
} else if (input.buttonIsPressed(Button.A)) {
testShake()
}
}
/**
* Runs one complete game from start to end
*/
function runGameOnce() {
let score = 0
let cooks = 0
let target_time = 0
// make sure no gestures are outstanding from last game
wasShake = false
wasLogoUp = false
wasLogoDown = false
wasScreenUp = false
wasScreenDown = false
state = "NEWSIDE"
while (true) {
// Handle any gestures that can happen at any time
let gesture = getGesture()
if (gesture == "FLOOR") {
state = "DROPPED"
}
// Run code appropriate to the present state of the game
if (state == "NEWSIDE") {
target_time = 5 + Math.random(5)
state = "COOKING"
startTimer()
} else if (state == "COOKING") {
// animate: cooking
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . # . . . . . . . . . . . . . #
# # # # # . # # # # # # # # # # # # # .
`, 100)
if (gesture == "FLIP") {
state = "FLIPPING"
} else if (getTimerSec() >= target_time) {
state = "READY"
score = score + 1
startTimer()
}
} else if (state == "READY") {
// animate: ready
basic.showAnimation(`
. . . . .
. . . . .
. . . . .
# . . . #
. # # # .
`, 100)
if (getTimerSec() > 2) {
state = "BURNING"
score = score - 1
startTimer()
} else if (gesture == "FLIP") {
state = "FLIPPING"
}
} else if (state == "BURNING") {
// animate: burning
basic.showAnimation(`
. . . . . . . . . . . . . # . . . . # .
. . . . . . . . # . . # . # . . # . . .
. . . . . . # . # . . # . . . . . . . .
. . . . . . # . . . . . . . . . . . . .
# # # # # # # # # # # # # # # # # # # #
`, 100)
if (gesture == "SKY") {
state = "NEWSIDE"
} else if (getTimerSec() > 2) {
state = "BURNT"
}
} else if (state == "FLIPPING") {
// animate: flipping
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . # . . . . . . . . . . . . . # . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . # # # # # . # # . . . # # # . . . # # . # # # # # . . . . . . . . . .
. . . . . . . . . . # # # # # . . . . . . . . # # . # # # . # # . . . . . . . . # # # # # . . . . .
. . . . . # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # #
# # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
`, 100)
// Prevent a spurious double-flip from happening
wasShake = false
cooks = cooks + 1
if (cooks == 5) {
state = "GAMEOVER"
} else {
state = "NEWSIDE"
}
} else if (state == "DROPPED") {
// animate: dropped
basic.showAnimation(`
# . . . # . . . . . # . . . # . . . . .
. # . # . . . . . . . # . # . . . . . .
. . # . . . . . . . . . # . . . . . . .
. # . # . . . . . . . # . # . . . . . .
# . . . # . . . . . # . . . # . . . . .
`, 250)
score = 0
state = "GAMEOVER"
} else if (state == "BURNT") {
// animate: burnt
basic.showAnimation(`
. . . . . . . . . . . . . . . . . . . . . . # . . . . . . . . # . # . . . . . . . # # # .
. . . . . . . . . . . . . . . . . # . . . . . . . . # . # . . . . . . . # # # . . . . . .
. . . . . . . . . . . . . . . . . . . . . # . # . . . . . . . # # # . . . . . . . . . . .
. . . . . . # . # . . # # # . . # . # . . . . . . . # # # . . . . . . . . . . . . . . . .
# # # # # . # # # . . # # # . . # # # . . # # # . . . . . . . . . . . . . . . . . . . . .
`, 250)
score = 0
state = "GAMEOVER"
} else if (state == "GAMEOVER") {
animateScore(score)
state = "WAITEJECT"
} else if (state == "WAITEJECT") {
if (gesture == "UPSIDEDOWN") {
return
}
}
}
}
/**
* show score (0..9) flashing
* @param score TODO
*/
function animateScore(score: number) {
score = Math.clamp(0, 9, score)
for (let i = 0; i < 5; i++) {
basic.showNumber(score, 0)
basic.pause(500)
basic.clearScreen()
basic.pause(500)
}
basic.showNumber(score, 0)
}
/**
* NOTE: Eventually this will move into a gesture library
* It hides all the nasty detail of detecting gestures
*/
function getGesture(): string {
if (!gesturesRunning) {
input.onShake(() => {
wasShake = true
})
input.onLogoUp(() => {
wasLogoUp = true
})
input.onLogoDown(() => {
wasLogoDown = true
})
input.onScreenUp(() => {
wasScreenUp = true
})
input.onScreenDown(() => {
wasScreenDown = true
})
gesturesRunning = true
}
// work out which of a possible set of gestures has occurred:
// Button gestures and movement gestures both handled
// This is so that it is easy to also use this on the simulator too
// Generally, B is used for normal OK, A is used for abnormal RECOVERY
// (flip is a normal action, touch sky to turn off smoke alarm is recovery)
let a = input.buttonIsPressed(Button.A)
let b = input.buttonIsPressed(Button.B)
if (state == "COOKING" || state == "READY") {
if (b || wasShake) {
wasShake = false
return "FLIP"
}
} else if (state == "FLIPPING") {
if (a || wasLogoDown) {
wasLogoDown = false
return "FLOOR"
}
} else if (state == "BURNING") {
if (a || wasLogoUp) {
wasLogoUp = false
return "SKY"
}
} else if (state == "GAMEOVER" || state == "WAITEJECT") {
if (b || wasScreenDown) {
wasScreenDown = false
return "UPSIDEDOWN"
}
}
return "NONE"
}
/**
* start timer by sampling runningtime and storing into starttime
*/
function startTimer() {
timer = input.runningTime()
}
/**
* get the elapsed time from the global starttime with ref to running time
* in seconds.
*/
function getTimerSec(): number {
let t = (input.runningTime() - timer) / 1000
return t
}
/**
* Show a splash screen "Perfect Pancakes >>>"
* Splash screen "PP" with little arrow pointing to the start button
*/
function splashScreen() {
let splash = images.createImage(`
# # # # . . . . . . # # # # . . . . . . . . . . . . . . . . . . . . .
# . . . # . . . . . # . . . # # . . . . . # . . . . . # . . . . . # .
# # # # . . . . . . # # # # . . # . . . . . # . . . . . # . . . . . #
# . . . . . . . . . # . . . . # . . . . . # . . . . . # . . . . . # .
# . . . . . . . . . # . . . . . . . . . . . . . . . . . . . . . . . .
`)
// use show image (not show animation) so that button press is more responsive
let index = 0
// Any button press finishes the splash screen
while (!input.buttonIsPressed(Button.B) && !input.buttonIsPressed(Button.A)) {
splash.showImage(index * 5)
index = index + 1
if (index > splash.width() / 5) {
index = 0
}
basic.pause(250)
}
}
function testShake() { }