145 lines
4 KiB
TypeScript
145 lines
4 KiB
TypeScript
// import Bluetooth from "./Bluetooth"
|
|
// import FogImages from "./FogImages"
|
|
import BorderTiles from "@components/Gamefield/BorderTiles"
|
|
import EventBar from "@components/Gamefield/EventBar"
|
|
import HitElems from "@components/Gamefield/HitElems"
|
|
import Targets from "@components/Gamefield/Targets"
|
|
import { useDraw } from "@hooks/useDraw"
|
|
import { useDrawProps } from "@hooks/useDrawProps"
|
|
import { useGameProps } from "@hooks/useGameProps"
|
|
import useIndex from "@hooks/useIndex"
|
|
import useSocket from "@hooks/useSocket"
|
|
import { socket } from "@lib/socket"
|
|
import { overlapsWithAnyBorder } from "@lib/utils/helpers"
|
|
import { useRouter } from "next/router"
|
|
import { CSSProperties, useEffect } from "react"
|
|
import { toast } from "react-toastify"
|
|
import Labeling from "./Labeling"
|
|
import Ships from "./Ships"
|
|
|
|
export const count = 12
|
|
|
|
function Gamefield() {
|
|
const { selfUser } = useIndex()
|
|
const router = useRouter()
|
|
const {
|
|
userStates,
|
|
mode,
|
|
target,
|
|
mouseCursor,
|
|
setMouseCursor,
|
|
payload,
|
|
setTargetPreview,
|
|
full,
|
|
reset,
|
|
} = useGameProps()
|
|
const { isConnected } = useSocket()
|
|
|
|
const { canvasRef, onMouseDown, clear } = useDraw()
|
|
const { enable, color, shouldHide } = useDrawProps()
|
|
|
|
useEffect(() => {
|
|
if (
|
|
payload?.game?.state !== "starting" ||
|
|
userStates.reduce((prev, curr) => prev || !curr.isReady, false)
|
|
)
|
|
return
|
|
socket.emit("ships", selfUser?.ships ?? [])
|
|
socket.emit("gameState", "running")
|
|
}, [payload?.game?.state, selfUser?.ships, userStates])
|
|
|
|
useEffect(() => {
|
|
if (payload?.game?.id || !isConnected) return
|
|
socket.emit("update", full)
|
|
}, [full, payload?.game?.id, isConnected])
|
|
|
|
useEffect(() => {
|
|
if (mode < 0) return
|
|
const { x, y, show } = target
|
|
const { shouldShow, ...position } = mouseCursor
|
|
if (
|
|
!shouldShow ||
|
|
(payload?.game?.state === "running" &&
|
|
overlapsWithAnyBorder(position, mode))
|
|
)
|
|
setTargetPreview((t) => ({ ...t, show: false }))
|
|
else {
|
|
setTargetPreview((t) => ({
|
|
...t,
|
|
...position,
|
|
show: !show || x !== position.x || y !== position.y,
|
|
}))
|
|
const handleKeyPress = (event: KeyboardEvent) => {
|
|
if (event.key !== "r") return
|
|
if (payload?.game?.state === "starting") {
|
|
setTargetPreview((t) => ({
|
|
...t,
|
|
orientation: t.orientation === "h" ? "v" : "h",
|
|
}))
|
|
}
|
|
if (payload?.game?.state === "running" && (mode === 1 || mode === 2))
|
|
useGameProps.setState({ mode: mode === 1 ? 2 : 1 })
|
|
}
|
|
document.addEventListener("keydown", handleKeyPress)
|
|
return () => {
|
|
document.removeEventListener("keydown", handleKeyPress)
|
|
}
|
|
}
|
|
}, [mode, mouseCursor, payload?.game?.state, setTargetPreview, target])
|
|
|
|
useEffect(() => {
|
|
if (payload?.game?.state !== "aborted") return
|
|
toast.info("Enemy gave up!")
|
|
router.push("/")
|
|
reset()
|
|
}, [payload?.game?.state, reset, router])
|
|
|
|
useEffect(() => {
|
|
if (payload?.game?.id) return
|
|
const timeout = setTimeout(() => router.push("/"), 5000)
|
|
return () => clearTimeout(timeout)
|
|
}, [payload?.game?.id, router])
|
|
|
|
return (
|
|
<div id="gamefield">
|
|
{/* <Bluetooth /> */}
|
|
<div
|
|
id="game-frame"
|
|
style={{ "--i": count } as CSSProperties}
|
|
onMouseLeave={() =>
|
|
setMouseCursor((e) => ({ ...e, shouldShow: false }))
|
|
}
|
|
>
|
|
<BorderTiles />
|
|
|
|
{/* Collumn lettes and row numbers */}
|
|
<Labeling />
|
|
|
|
<Ships />
|
|
|
|
<HitElems />
|
|
|
|
{/* <FogImages /> */}
|
|
|
|
<Targets />
|
|
|
|
<canvas
|
|
style={
|
|
{
|
|
opacity: shouldHide ? 0 : 1,
|
|
boxShadow: enable ? "inset 0 0 0 2px " + color : "none",
|
|
pointerEvents: enable && !shouldHide ? "auto" : "none",
|
|
} as CSSProperties
|
|
}
|
|
ref={canvasRef}
|
|
onMouseDown={onMouseDown}
|
|
width="648"
|
|
height="648"
|
|
/>
|
|
</div>
|
|
<EventBar clear={clear} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default Gamefield
|