import { type GameEffect } from '../core/gameResult' import { DEFAULT_GAME_HAPTICS_CONFIG, type FeedbackCueKey, type GameHapticsConfig } from './feedbackConfig' export class HapticsDirector { enabled: boolean config: GameHapticsConfig constructor(config: GameHapticsConfig = DEFAULT_GAME_HAPTICS_CONFIG) { this.enabled = true this.config = config } configure(config: GameHapticsConfig): void { this.config = config } setEnabled(enabled: boolean): void { this.enabled = enabled } destroy(): void {} trigger(key: FeedbackCueKey): void { if (!this.enabled || !this.config.enabled) { return } const cue = this.config.cues[key] if (!cue || !cue.enabled) { return } try { if (cue.pattern === 'long') { wx.vibrateLong() } else { wx.vibrateShort({ type: 'medium' }) } } catch {} } handleEffects(effects: GameEffect[]): void { for (const effect of effects) { if (effect.type === 'session_started') { this.trigger('session_started') continue } if (effect.type === 'session_finished') { this.trigger('session_finished') continue } if (effect.type === 'session_cancelled') { this.trigger('session_finished') continue } if (effect.type === 'punch_feedback' && effect.tone === 'warning') { this.trigger('punch_feedback:warning') continue } if (effect.type === 'guidance_state_changed') { if (effect.guidanceState === 'searching') { this.trigger('guidance:searching') continue } if (effect.guidanceState === 'approaching') { this.trigger('guidance:approaching') continue } this.trigger('guidance:ready') continue } if (effect.type === 'control_completed') { if (effect.controlKind === 'start') { this.trigger('control_completed:start') continue } if (effect.controlKind === 'finish') { this.trigger('control_completed:finish') continue } this.trigger('control_completed:control') } } } }