adds option to select game duration for stroke fighter
This commit is contained in:
parent
be545e445b
commit
d9a88aaee0
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -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
|
||||
})
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue