gameRuntime.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { type GameDefinition } from './gameDefinition'
  2. import { type GameEvent } from './gameEvent'
  3. import { type GameResult } from './gameResult'
  4. import { type GameSessionState } from './gameSessionState'
  5. import { EMPTY_GAME_PRESENTATION_STATE, type GamePresentationState } from '../presentation/presentationState'
  6. import { EMPTY_HUD_PRESENTATION_STATE, type HudPresentationState } from '../presentation/hudPresentationState'
  7. import { EMPTY_MAP_PRESENTATION_STATE, type MapPresentationState } from '../presentation/mapPresentationState'
  8. import { ClassicSequentialRule } from '../rules/classicSequentialRule'
  9. import { ScoreORule } from '../rules/scoreORule'
  10. import { type RulePlugin } from '../rules/rulePlugin'
  11. export class GameRuntime {
  12. definition: GameDefinition | null
  13. plugin: RulePlugin | null
  14. state: GameSessionState | null
  15. presentation: GamePresentationState
  16. mapPresentation: MapPresentationState
  17. hudPresentation: HudPresentationState
  18. lastResult: GameResult | null
  19. constructor() {
  20. this.definition = null
  21. this.plugin = null
  22. this.state = null
  23. this.presentation = EMPTY_GAME_PRESENTATION_STATE
  24. this.mapPresentation = EMPTY_MAP_PRESENTATION_STATE
  25. this.hudPresentation = EMPTY_HUD_PRESENTATION_STATE
  26. this.lastResult = null
  27. }
  28. clear(): void {
  29. this.definition = null
  30. this.plugin = null
  31. this.state = null
  32. this.presentation = EMPTY_GAME_PRESENTATION_STATE
  33. this.mapPresentation = EMPTY_MAP_PRESENTATION_STATE
  34. this.hudPresentation = EMPTY_HUD_PRESENTATION_STATE
  35. this.lastResult = null
  36. }
  37. loadDefinition(definition: GameDefinition): GameResult {
  38. this.definition = definition
  39. this.plugin = this.resolvePlugin(definition)
  40. this.state = this.plugin.initialize(definition)
  41. const result: GameResult = {
  42. nextState: this.state,
  43. presentation: this.plugin.buildPresentation(definition, this.state),
  44. effects: [],
  45. }
  46. this.presentation = result.presentation
  47. this.mapPresentation = result.presentation.map
  48. this.hudPresentation = result.presentation.hud
  49. this.lastResult = result
  50. return result
  51. }
  52. startSession(startAt = Date.now()): GameResult {
  53. return this.dispatch({ type: 'session_started', at: startAt })
  54. }
  55. dispatch(event: GameEvent): GameResult {
  56. if (!this.definition || !this.plugin || !this.state) {
  57. const emptyState: GameSessionState = {
  58. status: 'idle',
  59. startedAt: null,
  60. endedAt: null,
  61. completedControlIds: [],
  62. currentTargetControlId: null,
  63. inRangeControlId: null,
  64. score: 0,
  65. guidanceState: 'searching',
  66. modeState: null,
  67. }
  68. const result: GameResult = {
  69. nextState: emptyState,
  70. presentation: EMPTY_GAME_PRESENTATION_STATE,
  71. effects: [],
  72. }
  73. this.lastResult = result
  74. this.presentation = result.presentation
  75. this.mapPresentation = result.presentation.map
  76. this.hudPresentation = result.presentation.hud
  77. return result
  78. }
  79. const result = this.plugin.reduce(this.definition, this.state, event)
  80. this.state = result.nextState
  81. this.presentation = result.presentation
  82. this.mapPresentation = result.presentation.map
  83. this.hudPresentation = result.presentation.hud
  84. this.lastResult = result
  85. return result
  86. }
  87. getPresentation(): GamePresentationState {
  88. return this.presentation
  89. }
  90. getMapPresentation(): MapPresentationState {
  91. return this.mapPresentation
  92. }
  93. getHudPresentation(): HudPresentationState {
  94. return this.hudPresentation
  95. }
  96. resolvePlugin(definition: GameDefinition): RulePlugin {
  97. if (definition.mode === 'classic-sequential') {
  98. return new ClassicSequentialRule()
  99. }
  100. if (definition.mode === 'score-o') {
  101. return new ScoreORule()
  102. }
  103. throw new Error(`未支持的玩法模式: ${definition.mode}`)
  104. }
  105. }