adds option to select game duration for stroke fighter

This commit is contained in:
Lars Berning 2022-03-07 19:40:10 +01:00
parent be545e445b
commit d9a88aaee0
No known key found for this signature in database
GPG Key ID: 028E73C9E1D8A0B3
6 changed files with 133 additions and 49 deletions

View File

@ -44,6 +44,7 @@ export function createRowingGames (rootComponent, clientWidth, clientHeight) {
k.scene('strokeFighterBattle', (args) => { activeScene = StrokeFighterBattleScene(k, args) })
k.scene('strokeFighterStart', (args) => { activeScene = StrokeFighterStartScene(k, args) })
k.scene('strokeFighterEnd', (args) => { activeScene = StrokeFighterEndScene(k, args) })
k.scene('disposed', () => { activeScene = undefined })
k.go('strokeFighterStart')
@ -59,6 +60,8 @@ export function createRowingGames (rootComponent, clientWidth, clientHeight) {
* clean up the game resources
*/
function dispose () {
// k.quit does not seem to end the game 'yet', so we move to an empty scene to stop all events...
k.go('disposed')
k.quit()
}

View File

@ -14,8 +14,6 @@ import addSpaceBackground from './SpaceBackground.js'
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
const TARGET_TIME = 10 * 60
// strokes per minute at start of training
const SPM_START = 18
// strokes per minute at end of training
@ -39,6 +37,8 @@ export default function StrokeFighterBattleScene (k, args) {
]
let trainingTime = args?.trainingTime || 0
// training duration in seconds
const targetTime = args?.targetTime || 10 * 60
let playerLifes = args?.gameState === 'LOST' ? 0 : args?.playerLifes ? args?.playerLifes : PLAYER_LIFES
const ui = k.add([
@ -131,6 +131,7 @@ export default function StrokeFighterBattleScene (k, args) {
if (args?.gameState === 'WON') {
k.go('strokeFighterEnd', {
trainingTime,
targetTime,
gameState: 'WON',
overtimePossible: false
})
@ -138,6 +139,7 @@ export default function StrokeFighterBattleScene (k, args) {
} else {
k.go('strokeFighterEnd', {
trainingTime,
targetTime,
gameState: 'LOST',
overtimePossible: true
})
@ -269,13 +271,15 @@ export default function StrokeFighterBattleScene (k, args) {
trainingTime += k.dt()
const newTrainingTimeRounded = Math.round(trainingTime)
if (trainingTimeRounded !== newTrainingTimeRounded) {
timer.text = `${secondsToTimeString(newTrainingTimeRounded)} / ${k.debug.fps()}fps`
const time = newTrainingTimeRounded >= targetTime ? newTrainingTimeRounded : targetTime - newTrainingTimeRounded
timer.text = `${secondsToTimeString(time)} / ${k.debug.fps()}fps`
trainingTimeRounded = newTrainingTimeRounded
if (trainingTimeRounded >= TARGET_TIME) {
if (newTrainingTimeRounded >= targetTime) {
// if we already lost the game before, go back to loose message without possibility for overtime
if (args?.gameState === 'LOST') {
k.go('strokeFighterEnd', {
trainingTime,
targetTime,
playerLifes,
gameState: 'LOST',
overtimePossible: false
@ -285,6 +289,7 @@ export default function StrokeFighterBattleScene (k, args) {
if (!(args?.gameState)) {
k.go('strokeFighterEnd', {
trainingTime,
targetTime,
playerLifes,
gameState: 'WON',
overtimePossible: true
@ -355,7 +360,7 @@ export default function StrokeFighterBattleScene (k, args) {
}
function scheduleNextEnemy () {
const percentTrainingFinished = trainingTime / TARGET_TIME
const percentTrainingFinished = trainingTime / targetTime
// linearly increase the SPM over time
let currentSPM = SPM_START + (SPM_END - SPM_START) * percentTrainingFinished
let maxEnemyHealth = 1

View File

@ -6,9 +6,10 @@
*/
import addSpaceBackground from './SpaceBackground.js'
import { addButton } from './arcadeHelper.js'
/**
* Creates the main scene of Storke Fighter
* Creates the game over screen scene of Storke Fighter
* @param {import('kaboom').KaboomCtx} k Kaboom Context
* @param {Object} args the game state
*/
@ -40,23 +41,15 @@ export default function StrokeFighterEndScene (k, args) {
k.origin('center')
])
const restartButton = k.add([
k.rect(300, 60),
k.area(),
k.pos(k.width() / 2, 440),
k.scale(1),
k.origin('center'),
k.outline(2, k.rgb(255, 255, 255)),
k.color(54, 80, 128)
])
const restartText = k.add([
k.text('Restart', { size: 40 }),
k.area({ cursor: 'pointer' }),
k.pos(k.width() / 2, 440),
k.scale(1),
k.origin('center'),
k.color(255, 255, 255)
])
addButton({
k,
pos: k.vec2(k.width() / 2, 440),
width: 300,
height: 60,
text: 'Restart',
textOptions: { size: 40 },
onClick: () => { k.go('strokeFighterStart') }
})
if (args?.overtimePossible) {
if (args?.gameState === 'LOST') {
@ -73,27 +66,6 @@ export default function StrokeFighterEndScene (k, args) {
])
}
}
restartButton.onClick(() => {
k.go('strokeFighterStart')
})
restartButton.onUpdate(() => {
if (restartButton.isHovering()) {
k.cursor('pointer')
restartButton.scale = k.vec2(1.2)
restartText.scale = k.vec2(1.2)
const t = k.time() * 10
restartButton.color = k.rgb(
k.wave(0, 255, t),
k.wave(0, 255, t + 2),
k.wave(0, 255, t + 4)
)
} else {
k.cursor('default')
restartButton.scale = k.vec2(1)
restartText.scale = k.vec2(1)
restartButton.color = k.rgb(54, 80, 128)
}
})
let motionDetectionEnabled = false
if (args?.overtimePossible) {

View File

@ -6,9 +6,10 @@
*/
import addSpaceBackground from './SpaceBackground.js'
import { addButton } from './arcadeHelper.js'
/**
* Creates the main scene of Stroke Fighter
* Creates the start screen scene of Stroke Fighter
* @param {import('kaboom').KaboomCtx} k Kaboom Context
*/
export default function StrokeFighterStartScene (k, args) {
@ -20,7 +21,64 @@ export default function StrokeFighterStartScene (k, args) {
k.origin('center')
])
const shipsPos = k.vec2(520, 240)
const GAME_DURATION_OPTIONS = [3, 5, 10, 15, 20, 30]
let selectedGameDuration = 1
const selectorPos = k.vec2(150, 140)
k.add([
k.text('time:', { size: 28 }),
k.pos(selectorPos),
k.origin('center')
])
addButton({
k,
pos: selectorPos.add(100, 0),
width: 60,
height: 48,
text: '-',
textOptions: { size: 28 },
onClick: () => {
selectedGameDuration = Math.max(selectedGameDuration - 1, 0)
durationSelectorText.text = displayTime(selectedGameDuration)
}
})
const durationSelectorText = k.add([
k.text(displayTime(selectedGameDuration), { size: 28 }),
k.pos(selectorPos.add(168, 0)),
k.origin('center')
])
addButton({
k,
pos: selectorPos.add(230, 0),
width: 60,
height: 48,
text: '+',
textOptions: { size: 28 },
onClick: () => {
selectedGameDuration = Math.min(selectedGameDuration + 1, GAME_DURATION_OPTIONS.length - 1)
durationSelectorText.text = displayTime(selectedGameDuration)
}
})
k.add([
k.text('minutes', { size: 28 }),
k.pos(selectorPos.add(280, 0)),
k.origin('left')
])
function displayTime (option) {
let time = GAME_DURATION_OPTIONS[option].toString()
if (time.length === 1) {
time = '0' + time
}
return time
}
const shipsPos = k.vec2(550, 280)
const ship1 = k.add([
k.sprite('playerShip'),
k.scale(0.5),
@ -48,7 +106,7 @@ export default function StrokeFighterStartScene (k, args) {
addBullet(ship3.pos.sub(20, 40))
addBullet(ship3.pos.sub(-20, 40))
const explainPos = k.vec2(60, 240)
const explainPos = k.vec2(90, 280)
k.add([
k.text('light stroke = ', { size: 28 }),
k.pos(explainPos),
@ -99,7 +157,7 @@ export default function StrokeFighterStartScene (k, args) {
}
function driveFinished (metrics) {
k.go('strokeFighterBattle')
k.go('strokeFighterBattle', { targetTime: GAME_DURATION_OPTIONS[selectedGameDuration] * 60 })
}
return {

View File

@ -0,0 +1,44 @@
'use strict'
/*
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
Implements some common helpers for the games
*/
export function addButton ({ k, node = k, pos, width, height, text, textOptions, onClick }) {
const button = node.add([
k.rect(width, height),
k.area(),
k.pos(pos),
k.origin('center'),
k.outline(2, k.rgb(0, 0, 0)),
k.color(54, 80, 128)
])
node.add([
k.text(text, textOptions),
k.area({ cursor: 'pointer' }),
k.pos(button.pos.add(2, 1)),
k.origin('center'),
k.color(255, 255, 255)
])
button.onClick(() => {
onClick()
})
button.onUpdate(() => {
if (button.isHovering()) {
k.cursor('pointer')
const t = k.time() * 10
button.color = k.rgb(
k.wave(0, 255, t),
k.wave(0, 255, t + 2),
k.wave(0, 255, t + 4)
)
} else {
// todo: resetting the cursor here will not work as expected if we have multiple buttons on the page
// seems like kaboom does not yet have an elegant way of how to do this...
k.cursor('default')
button.color = k.rgb(54, 80, 128)
}
})
}

View File

@ -186,8 +186,10 @@ function getConfig () {
}
}
/*
replayRowingSession(handleRotationImpulse, {
filename: 'data/recordings/2022-02-18_12-51-00_raw.csv',
filename: 'recordings/WRX700_2magnets.csv',
realtime: true,
loop: true
})
*/