-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuse-game-machine.ts
More file actions
82 lines (76 loc) · 2.21 KB
/
use-game-machine.ts
File metadata and controls
82 lines (76 loc) · 2.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { useCallback, useReducer } from 'react';
import type { Transition } from './use-game-machine.types';
import { gameMachineReducer } from './use-game-machine.reducer';
import { gameLogic, NEW_GAME_STATE } from './use-game-machine.logic';
import { useOnEntry } from './use-game-machine.use-on-entry';
import { melodyPlayer } from '../services/melody-player';
import type { PadId } from '../types';
import type { HighScoreEntry } from 'types.shared';
export type GameMachine = ReturnType<typeof useGameMachine>;
export const useGameMachine = ({
currentHighScore,
}: {
currentHighScore: HighScoreEntry | undefined;
}) => {
const [gameMachine, dispatch] = useReducer(
gameMachineReducer,
NEW_GAME_STATE,
);
// *** Actions ***
const transition: Transition = useCallback(
({ to }) => dispatch({ type: 'transition', to }),
[],
);
const startNewGame = useCallback(
() => dispatch({ type: 'startNewGame' }),
[],
);
const input = useCallback(
(padId: PadId) => dispatch({ type: 'input', padId }),
[],
);
// *** Derived values / Aliases ***
const isNewGame = gameMachine.state === 'newGame';
const isComputerTurn = gameMachine.state === 'computerTurn';
const isUserTurn = gameMachine.state === 'userTurn';
const isPlaying = isUserTurn || isComputerTurn;
const isGameOver = gameMachine.state === 'gameOver';
const userScore = gameMachine.userScore;
const currentScore = isComputerTurn ? userScore : gameMachine.userSeqIndex;
const isNewHighScore = Boolean(
isGameOver && currentHighScore && currentHighScore.score < userScore,
);
// *** State Hooks ***
useOnEntry({
target: 'computerTurn',
currentState: gameMachine.state,
cb: () => {
gameLogic.nextSequence().then(() => {
transition({ to: 'userTurn' });
});
},
});
useOnEntry({
target: 'gameOver',
currentState: gameMachine.state,
cb: () => {
const melody = isNewHighScore ? 'highScore' : 'gameOver';
melodyPlayer.play(melody);
},
});
return {
isNewGame,
isComputerTurn,
isUserTurn,
isPlaying,
isGameOver,
userScore,
currentScore,
isNewHighScore,
actions: {
startNewGame,
input,
transition,
},
};
};