pixi-fusion
Version:
This module offers a set of common components needed for playing games.
125 lines (124 loc) • 4.27 kB
JavaScript
import React, { createContext, useCallback, useMemo, useRef, useState } from "react";
import { GameStatus } from "../types";
export const GameContext = createContext({
reset: () => { },
pause: () => { },
start: () => { },
stop: () => { },
timeout: 0,
status: GameStatus.READY,
startTime: null,
pauseTime: 0,
endTime: null
});
export const GameContextProvider = ({ children, timeout: inputTimeout = 0, events }) => {
const timerRef = useRef(null);
const timeout = Math.max(0, inputTimeout);
const [status, setStatus] = useState(GameStatus.READY);
const [startTime, setStartTime] = useState(null);
const [endTime, setEndTime] = useState(null);
const [pauseTime, setPauseTime] = useState(0);
const [pausedAtTime, setPausedAtTime] = useState(null);
const onTimedOut = useCallback(() => {
const newEndTime = +new Date();
const newStatus = GameStatus.TIMEDOUT;
setEndTime(newEndTime);
setStatus(GameStatus.TIMEDOUT);
events?.onTimedOut?.({
startTime,
endTime: newEndTime,
status: newStatus,
pausedAtTime: null,
pauseTime
});
}, [events, pauseTime, startTime]);
const start = useCallback(() => {
const newStartTime = startTime || +new Date();
const newStatus = GameStatus.IN_PROGRESS;
const newEndTime = null;
const newPauseTime = pausedAtTime ? pauseTime + +new Date() - (pausedAtTime || 0) : 0;
setStatus(newStatus);
setStartTime((currentStartTime) => currentStartTime || newStartTime);
setPauseTime(newPauseTime);
setPausedAtTime(null);
setEndTime(newEndTime);
if (timeout !== 0) {
timerRef.current = setTimeout(() => {
onTimedOut();
}, timeout * 1000);
}
events?.onStart?.({
startTime: newStartTime,
endTime: newEndTime,
status: newStatus,
pausedAtTime: null,
pauseTime: newPauseTime
});
}, [events, onTimedOut, pauseTime, pausedAtTime, startTime, timeout]);
const reset = useCallback(() => {
const newStartTime = null;
const newStatus = GameStatus.READY;
const newEndTime = null;
const newPausedAtTime = null;
const newPauseTime = 0;
setStatus(newStatus);
setStartTime(newStartTime);
setEndTime(newEndTime);
setPauseTime(newPauseTime);
setPausedAtTime(newPausedAtTime);
if (timerRef.current) {
clearTimeout(timerRef.current);
}
events?.onReset?.({
startTime: newStartTime,
endTime: newEndTime,
status: newStatus,
pausedAtTime: newPausedAtTime,
pauseTime: newPauseTime
});
}, [events]);
const stop = useCallback(() => {
const newStatus = GameStatus.COMPLETED;
const newEndTime = +new Date();
if (timerRef.current) {
clearTimeout(timerRef.current);
}
setEndTime(+new Date());
setStatus(GameStatus.COMPLETED);
events?.onStop?.({
startTime,
endTime: newEndTime,
status: newStatus,
pausedAtTime,
pauseTime
});
}, [events, pauseTime, pausedAtTime, startTime]);
const pause = useCallback(() => {
const newStatus = GameStatus.PAUSED;
const newPausedAtTime = +new Date();
if (timerRef.current) {
clearTimeout(timerRef.current);
}
setStatus(GameStatus.PAUSED);
setPausedAtTime(newPausedAtTime);
events?.onPause?.({
startTime,
endTime: null,
pausedAtTime: newPausedAtTime,
status: newStatus,
pauseTime
});
}, [events, pauseTime, startTime]);
const contextValue = useMemo(() => ({
status,
startTime,
endTime,
pauseTime,
timeout,
stop,
start,
reset,
pause
}), [timeout, status, startTime, endTime, pauseTime, pause, reset, start, stop]);
return React.createElement(GameContext.Provider, { value: contextValue }, children);
};