adds a game over screen
This commit is contained in:
parent
873cbbe5a3
commit
4cd8d9c699
|
|
@ -8,6 +8,7 @@
|
|||
import kaboom from 'kaboom'
|
||||
import StrokeFighterBattleScene from './StrokeFighterBattleScene.js'
|
||||
import StrokeFighterStartScene from './StrokeFighterStartScene.js'
|
||||
import StrokeFighterGameOverScene from './StrokeFighterGameOverScene.js'
|
||||
|
||||
/**
|
||||
* creates and initializes the rowing games
|
||||
|
|
@ -23,7 +24,8 @@ export function createRowingGames (rootComponent, canvasElement, clientWidth, cl
|
|||
root: rootComponent,
|
||||
crisp: false,
|
||||
width: clientWidth,
|
||||
height: clientHeight
|
||||
height: clientHeight,
|
||||
font: 'sinko'
|
||||
})
|
||||
// for now show debug infos all the time
|
||||
// k.debug.inspect = true
|
||||
|
|
@ -31,8 +33,8 @@ export function createRowingGames (rootComponent, canvasElement, clientWidth, cl
|
|||
// todo: once there are multiple games, asset loadingshould be moved to the individual games
|
||||
const assets = '/assets'
|
||||
const sprites = ['enemyBlack1', 'enemyBlue2', 'enemyGreen3', 'enemyRed4', 'enemyRed5', 'playerShip2_orange',
|
||||
'spaceShips_004', 'spaceShips_006', 'spaceShips_007', 'spaceShips_009', 'star1', 'star2',
|
||||
'laserRed01', 'laserRed09']
|
||||
'playerLife2_orange', 'spaceShips_004', 'spaceShips_006', 'spaceShips_007', 'spaceShips_009', 'star1', 'star2',
|
||||
'laserRed01', 'laserRed09', 'shield1']
|
||||
|
||||
for (const sprite of sprites) {
|
||||
k.loadSprite(sprite, `${assets}/sprites/${sprite}@2x.png`)
|
||||
|
|
@ -42,8 +44,9 @@ export function createRowingGames (rootComponent, canvasElement, clientWidth, cl
|
|||
|
||||
// todo: check if there is some kaboomish way to get the active scene
|
||||
let activeScene
|
||||
k.scene('strokeFighterBattle', () => { activeScene = StrokeFighterBattleScene(k) })
|
||||
k.scene('strokeFighterStart', () => { activeScene = StrokeFighterStartScene(k) })
|
||||
k.scene('strokeFighterBattle', (args) => { activeScene = StrokeFighterBattleScene(k, args) })
|
||||
k.scene('strokeFighterStart', (args) => { activeScene = StrokeFighterStartScene(k, args) })
|
||||
k.scene('strokeFighterGameOver', (args) => { activeScene = StrokeFighterGameOverScene(k, args) })
|
||||
|
||||
k.go('strokeFighterStart')
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import addSpaceBackground from './SpaceBackground.js'
|
|||
* Creates the main scene of Storke Fighter
|
||||
* @param {import('kaboom').KaboomCtx} k Kaboom Context
|
||||
*/
|
||||
export default function StrokeFighterBattleScene (k) {
|
||||
export default function StrokeFighterBattleScene (k, args) {
|
||||
// how much stroke power is needed to fire high power lasers
|
||||
const THRESHOLD_POWER = 180
|
||||
// training duration in seconds
|
||||
|
|
@ -23,6 +23,7 @@ export default function StrokeFighterBattleScene (k) {
|
|||
const BULLET_SPEED = 1200
|
||||
const ENEMY_SPEED = 60
|
||||
const PLAYER_SPEED = 480
|
||||
const PLAYER_LIFES = 3
|
||||
const SPRITE_WIDTH = 90
|
||||
const ENEMIES = [
|
||||
{ sprite: 'enemyBlack1', health: 1 },
|
||||
|
|
@ -36,7 +37,8 @@ export default function StrokeFighterBattleScene (k) {
|
|||
{ sprite: 'spaceShips_009', health: 2 }
|
||||
]
|
||||
|
||||
let trainingTime = 0
|
||||
let trainingTime = args?.trainingTime || 0
|
||||
let playerLifes = args?.gameOver ? 0 : PLAYER_LIFES
|
||||
|
||||
const ui = k.add([
|
||||
k.fixed(),
|
||||
|
|
@ -63,6 +65,31 @@ export default function StrokeFighterBattleScene (k) {
|
|||
k.origin('center')
|
||||
])
|
||||
|
||||
if (args?.gameOver) {
|
||||
const shield = k.add([
|
||||
k.sprite('shield1'),
|
||||
k.scale(0.5),
|
||||
k.area(),
|
||||
k.opacity(0.4),
|
||||
k.pos(player.pos),
|
||||
k.origin('center')
|
||||
])
|
||||
|
||||
shield.onUpdate(() => {
|
||||
shield.pos = player.pos
|
||||
})
|
||||
|
||||
shield.onCollide('enemy', (enemy) => {
|
||||
k.destroy(enemy)
|
||||
k.shake(4)
|
||||
k.play('hit', {
|
||||
detune: -1200,
|
||||
volume: 0.6,
|
||||
speed: k.rand(0.5, 2)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function moveLeft () {
|
||||
player.move(-PLAYER_SPEED, 0)
|
||||
if (player.pos.x < 0) {
|
||||
|
|
@ -80,11 +107,19 @@ export default function StrokeFighterBattleScene (k) {
|
|||
player.onCollide('enemy', (enemy) => {
|
||||
k.destroy(enemy)
|
||||
k.shake(4)
|
||||
background.redflash()
|
||||
k.play('hit', {
|
||||
detune: -1200,
|
||||
volume: 0.6,
|
||||
speed: k.rand(0.5, 2)
|
||||
})
|
||||
playerLifes -= 1
|
||||
drawPlayerLifes()
|
||||
if (playerLifes <= 0) {
|
||||
k.go('strokeFighterGameOver', {
|
||||
trainingTime
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
player.onUpdate(() => {
|
||||
|
|
@ -142,7 +177,6 @@ export default function StrokeFighterBattleScene (k) {
|
|||
spawnBullet(player.pos.sub(20, 40))
|
||||
spawnBullet(player.pos.sub(-20, 40))
|
||||
} else {
|
||||
background.redflash()
|
||||
spawnBullet(player.pos.sub(0, 65))
|
||||
spawnBullet(player.pos.sub(20, 40))
|
||||
spawnBullet(player.pos.sub(-20, 40))
|
||||
|
|
@ -185,7 +219,7 @@ export default function StrokeFighterBattleScene (k) {
|
|||
})
|
||||
|
||||
const timer = ui.add([
|
||||
k.text('00:00', { size: 25, font: 'sinko' }),
|
||||
k.text('00:00', { size: 25 }),
|
||||
k.pos(10, 10),
|
||||
k.fixed()
|
||||
])
|
||||
|
|
@ -200,6 +234,21 @@ export default function StrokeFighterBattleScene (k) {
|
|||
}
|
||||
})
|
||||
|
||||
function drawPlayerLifes () {
|
||||
k.destroyAll('playerLife')
|
||||
|
||||
// todo: would want to draw these on the "ui", but not sure on how to delete them then...
|
||||
for (let i = 1; i <= playerLifes; i++) {
|
||||
k.add([
|
||||
k.sprite('playerLife2_orange'),
|
||||
k.scale(0.5),
|
||||
k.pos(k.width() - i * 40, 10),
|
||||
k.z(100),
|
||||
'playerLife'
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
// converts a timestamp in seconds to a human readable hh:mm:ss format
|
||||
function secondsToTimeString (secondsTimeStamp) {
|
||||
if (secondsTimeStamp === Infinity) return '∞'
|
||||
|
|
@ -260,6 +309,7 @@ export default function StrokeFighterBattleScene (k) {
|
|||
k.wait(60 / currentSPM, scheduleNextEnemy)
|
||||
}
|
||||
|
||||
drawPlayerLifes()
|
||||
scheduleNextEnemy()
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
Implements the Start Screen of the Stroke Fighter Game
|
||||
*/
|
||||
|
||||
import addSpaceBackground from './SpaceBackground.js'
|
||||
|
||||
/**
|
||||
* Creates the main scene of Storke Fighter
|
||||
* @param {import('kaboom').KaboomCtx} k Kaboom Context
|
||||
*/
|
||||
export default function StrokeFighterGameOverScene (k, args) {
|
||||
addSpaceBackground(k)
|
||||
|
||||
k.add([
|
||||
k.text('Stroke Fighter', { size: 50 }),
|
||||
k.pos(k.width() / 2, 50),
|
||||
k.origin('center')
|
||||
])
|
||||
k.add([
|
||||
k.text('Game Over', { size: 40 }),
|
||||
k.pos(k.width() / 2, 180),
|
||||
k.origin('center')
|
||||
])
|
||||
k.add([
|
||||
k.sprite('playerShip2_orange'),
|
||||
k.scale(0.5),
|
||||
k.pos(k.width() / 2, 320),
|
||||
k.origin('center')
|
||||
])
|
||||
const restartButton = k.add([
|
||||
k.text('Restart', { size: 40 }),
|
||||
k.area({ cursor: 'pointer' }),
|
||||
k.pos(k.width() / 2, 440),
|
||||
k.origin('center')
|
||||
])
|
||||
k.add([
|
||||
k.text('... or keep rowing to finish your workout', { size: 18 }),
|
||||
k.pos(k.width() / 2, 550),
|
||||
k.origin('center')
|
||||
])
|
||||
restartButton.onClick(() => {
|
||||
console.log('click')
|
||||
k.go('strokeFighterStart')
|
||||
})
|
||||
|
||||
let motionDetectionEnabled = false
|
||||
k.wait(5, () => {
|
||||
motionDetectionEnabled = true
|
||||
})
|
||||
|
||||
let lastStrokeState = 'DRIVING'
|
||||
function appState (appState) {
|
||||
if (!motionDetectionEnabled) {
|
||||
return
|
||||
}
|
||||
if (appState?.metrics.strokeState === undefined) {
|
||||
return
|
||||
}
|
||||
if (lastStrokeState === 'DRIVING' && appState.metrics.strokeState === 'RECOVERY') {
|
||||
driveFinished(appState.metrics)
|
||||
}
|
||||
lastStrokeState = appState.metrics.strokeState
|
||||
}
|
||||
|
||||
function driveFinished (metrics) {
|
||||
k.go('strokeFighterBattle', {
|
||||
gameOver: true,
|
||||
trainingTime: args?.trainingTime
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
appState
|
||||
}
|
||||
}
|
||||
|
|
@ -11,16 +11,16 @@ import addSpaceBackground from './SpaceBackground.js'
|
|||
* Creates the main scene of Storke Fighter
|
||||
* @param {import('kaboom').KaboomCtx} k Kaboom Context
|
||||
*/
|
||||
export default function StrokeFighterStartScene (k) {
|
||||
export default function StrokeFighterStartScene (k, args) {
|
||||
addSpaceBackground(k)
|
||||
|
||||
k.add([
|
||||
k.text('Stroke Fighter', { size: 50, font: 'sinko' }),
|
||||
k.text('Stroke Fighter', { size: 50 }),
|
||||
k.pos(k.width() / 2, 50),
|
||||
k.origin('center')
|
||||
])
|
||||
k.add([
|
||||
k.text('start rowing...', { size: 40, font: 'sinko' }),
|
||||
k.text('start rowing...', { size: 40 }),
|
||||
k.pos(k.width() / 2, 110),
|
||||
k.origin('center')
|
||||
])
|
||||
|
|
@ -55,17 +55,17 @@ export default function StrokeFighterStartScene (k) {
|
|||
|
||||
const explainPos = k.vec2(40, 260)
|
||||
k.add([
|
||||
k.text('light stroke = ', { size: 28, font: 'sinko' }),
|
||||
k.text('light stroke = ', { size: 28 }),
|
||||
k.pos(explainPos),
|
||||
k.origin('left')
|
||||
])
|
||||
k.add([
|
||||
k.text('normal stroke = ', { size: 28, font: 'sinko' }),
|
||||
k.text('normal stroke = ', { size: 28 }),
|
||||
k.pos(explainPos.add(0, 140)),
|
||||
k.origin('left')
|
||||
])
|
||||
k.add([
|
||||
k.text('heavy stroke = ', { size: 28, font: 'sinko' }),
|
||||
k.text('heavy stroke = ', { size: 28 }),
|
||||
k.pos(explainPos.add(0, 280)),
|
||||
k.origin('left')
|
||||
])
|
||||
|
|
@ -79,8 +79,15 @@ export default function StrokeFighterStartScene (k) {
|
|||
])
|
||||
}
|
||||
|
||||
let motionDetectionEnabled = false
|
||||
k.wait(5, () => {
|
||||
motionDetectionEnabled = true
|
||||
})
|
||||
let lastStrokeState = 'DRIVING'
|
||||
function appState (appState) {
|
||||
if (!motionDetectionEnabled) {
|
||||
return
|
||||
}
|
||||
if (appState?.metrics.strokeState === undefined) {
|
||||
return
|
||||
}
|
||||
|
|
@ -91,7 +98,7 @@ export default function StrokeFighterStartScene (k) {
|
|||
}
|
||||
|
||||
function driveFinished (metrics) {
|
||||
k.wait(2, () => { k.go('strokeFighterBattle') })
|
||||
k.go('strokeFighterBattle')
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
Loading…
Reference in New Issue