Fixed targetPreview
This commit is contained in:
parent
986555a368
commit
b3695916a0
15 changed files with 237 additions and 302 deletions
|
@ -1,23 +1,22 @@
|
|||
import { Position, MouseCursor } from "../../interfaces/frontend"
|
||||
import { MouseCursor } from "../../interfaces/frontend"
|
||||
import { count } from "./Gamefield"
|
||||
import { borderCN, cornerCN, fieldIndex } from "@lib/utils/helpers"
|
||||
import { CSSProperties, Dispatch, SetStateAction } from "react"
|
||||
|
||||
type TilesType = {
|
||||
key: number
|
||||
isGameTile: boolean
|
||||
classNameString: string
|
||||
className: string
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
|
||||
function BorderTiles({
|
||||
props: { count, settingTarget, setMouseCursor, setLastLeftTile },
|
||||
props: { settingTarget, setMouseCursor },
|
||||
}: {
|
||||
props: {
|
||||
count: number
|
||||
settingTarget: (isGameTile: boolean, x: number, y: number) => void
|
||||
setMouseCursor: Dispatch<SetStateAction<MouseCursor>>
|
||||
setLastLeftTile: Dispatch<SetStateAction<Position>>
|
||||
}
|
||||
}) {
|
||||
let tilesProperties: TilesType[] = []
|
||||
|
@ -31,10 +30,10 @@ function BorderTiles({
|
|||
const classNames = ["border-tile"]
|
||||
if (borderType) classNames.push("edge", borderType)
|
||||
if (isGameTile) classNames.push("game-tile")
|
||||
const classNameString = classNames.join(" ")
|
||||
const className = classNames.join(" ")
|
||||
tilesProperties.push({
|
||||
key,
|
||||
classNameString,
|
||||
className,
|
||||
isGameTile,
|
||||
x: x + 1,
|
||||
y: y + 1,
|
||||
|
@ -44,17 +43,16 @@ function BorderTiles({
|
|||
|
||||
return (
|
||||
<>
|
||||
{tilesProperties.map(({ key, classNameString, isGameTile, x, y }) => {
|
||||
{tilesProperties.map(({ key, className, isGameTile, x, y }) => {
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
className={classNameString}
|
||||
className={className}
|
||||
style={{ "--x": x, "--y": y } as CSSProperties}
|
||||
onClick={() => settingTarget(isGameTile, x, y)}
|
||||
onMouseEnter={() =>
|
||||
setMouseCursor({ x, y, shouldShow: isGameTile })
|
||||
}
|
||||
onMouseLeave={() => setLastLeftTile({ x, y })}
|
||||
></div>
|
||||
)
|
||||
})}
|
||||
|
|
|
@ -1,35 +1,98 @@
|
|||
// import Bluetooth from './Bluetooth'
|
||||
// import FogImages from './FogImages'
|
||||
import { Hit, MouseCursor, Target } from "../../interfaces/frontend"
|
||||
import Labeling from "./Labeling"
|
||||
import Ships from "./Ships"
|
||||
import useGameEvent from "@hooks/useGameEvent"
|
||||
import { CSSProperties } from "react"
|
||||
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 {
|
||||
hitReducer,
|
||||
initlialTarget,
|
||||
initlialTargetPreview,
|
||||
initlialMouseCursor,
|
||||
overlapsWithAnyBorder,
|
||||
isHit,
|
||||
composeTargetTiles,
|
||||
} from "@lib/utils/helpers"
|
||||
import { CSSProperties, useCallback } from "react"
|
||||
import { useEffect, useReducer, useState } from "react"
|
||||
|
||||
export const count = 12
|
||||
|
||||
function Gamefield() {
|
||||
const count = 12
|
||||
const { BorderTiles, HitElems, Targets, EventBar } = useGameEvent(count)
|
||||
const [target, setTarget] = useState<Target>(initlialTarget)
|
||||
const [targetPreview, setTargetPreview] = useState<Target>(
|
||||
initlialTargetPreview
|
||||
)
|
||||
const [mouseCursor, setMouseCursor] =
|
||||
useState<MouseCursor>(initlialMouseCursor)
|
||||
const [hits, DispatchHits] = useReducer(hitReducer, [] as Hit[])
|
||||
const [mode, setMode] = useState(0)
|
||||
|
||||
const settingTarget = useCallback(
|
||||
(isGameTile: boolean, x: number, y: number) => {
|
||||
if (!isGameTile || isHit(x, y, hits).length) return
|
||||
setTarget((t) => {
|
||||
if (t.x === x && t.y === y && t.show) {
|
||||
DispatchHits({
|
||||
type: "fireMissile",
|
||||
payload: { hit: (x + y) % 2 !== 0, x, y },
|
||||
})
|
||||
return { preview: false, show: false, x, y }
|
||||
} else {
|
||||
const target = { show: true, x, y }
|
||||
if (overlapsWithAnyBorder(target, mode)) return t
|
||||
return target
|
||||
}
|
||||
})
|
||||
},
|
||||
[hits, mode]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
console.log(1)
|
||||
const { x, y, show } = target
|
||||
const { shouldShow, ...position } = mouseCursor
|
||||
if (!shouldShow || overlapsWithAnyBorder(position, mode))
|
||||
setTargetPreview((e) => ({ ...e, show: false }))
|
||||
else {
|
||||
console.log(2, position)
|
||||
setTargetPreview({
|
||||
...position,
|
||||
show: !show || x !== position.x || y !== position.y,
|
||||
})
|
||||
}
|
||||
}, [mode, mouseCursor, target])
|
||||
|
||||
return (
|
||||
<div id="gamefield">
|
||||
{/* <Bluetooth /> */}
|
||||
<div id="game-frame" style={{ "--i": count } as CSSProperties}>
|
||||
<div
|
||||
id="game-frame"
|
||||
style={{ "--i": count } as CSSProperties}
|
||||
onMouseLeave={() =>
|
||||
setMouseCursor((e) => ({ ...e, shouldShow: false }))
|
||||
}
|
||||
>
|
||||
{/* Bordes */}
|
||||
<BorderTiles />
|
||||
<BorderTiles props={{ settingTarget, setMouseCursor }} />
|
||||
|
||||
{/* Collumn lettes and row numbers */}
|
||||
<Labeling count={count} />
|
||||
|
||||
{/* Ships */}
|
||||
<Ships />
|
||||
|
||||
<HitElems />
|
||||
<HitElems hits={hits} />
|
||||
|
||||
{/* Fog images */}
|
||||
{/* <FogImages /> */}
|
||||
<Targets />
|
||||
|
||||
<Targets props={{ target, targetPreview, mode, hits }} />
|
||||
{/* <span id='dev-debug' style={{gridArea: '1 / 12 / 1 / 15', backgroundColor: 'red', zIndex: 3} as CSSProperties}>Debug</span> */}
|
||||
</div>
|
||||
<EventBar />
|
||||
<EventBar props={{ setMode, setTarget }} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ export interface PointerProps extends Target, TargetList {
|
|||
}
|
||||
|
||||
function GamefieldPointer({
|
||||
props: { preview, x, y, show, type, edges, imply },
|
||||
props: { x, y, show, type, edges, imply },
|
||||
preview,
|
||||
}: {
|
||||
props: PointerProps
|
||||
preview?: boolean
|
||||
}) {
|
||||
const isRadar = type === "radar"
|
||||
const style = !(isRadar && !edges.filter((s) => s).length)
|
||||
|
|
|
@ -1,24 +1,26 @@
|
|||
import { Target } from "../../interfaces/frontend"
|
||||
import GamefieldPointer, { PointerProps } from "./GamefieldPointer"
|
||||
import { Hit, Target } from "../../interfaces/frontend"
|
||||
import GamefieldPointer from "./GamefieldPointer"
|
||||
import { composeTargetTiles } from "@lib/utils/helpers"
|
||||
import React from "react"
|
||||
|
||||
function Targets({
|
||||
props: { composeTargetTiles, target, targetPreview },
|
||||
props: { target, targetPreview, mode, hits },
|
||||
}: {
|
||||
props: {
|
||||
composeTargetTiles: (target: Target) => PointerProps[]
|
||||
target: Target
|
||||
targetPreview: Target
|
||||
mode: number
|
||||
hits: Hit[]
|
||||
}
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
{[
|
||||
...composeTargetTiles(target).map((props, i) => (
|
||||
...composeTargetTiles(target, mode, hits).map((props, i) => (
|
||||
<GamefieldPointer key={"t" + i} props={props} />
|
||||
)),
|
||||
...composeTargetTiles(targetPreview).map((props, i) => (
|
||||
<GamefieldPointer key={"p" + i} props={props} />
|
||||
...composeTargetTiles(targetPreview, mode, hits).map((props, i) => (
|
||||
<GamefieldPointer key={"p" + i} props={props} preview />
|
||||
)),
|
||||
]}
|
||||
</>
|
||||
|
|
|
@ -9,9 +9,26 @@ import { useSession } from "next-auth/react"
|
|||
import { useRouter } from "next/router"
|
||||
import { Fragment, useEffect, useState } from "react"
|
||||
|
||||
function WithDots({ children }: { children: string }) {
|
||||
const [dots, setDots] = useState(3)
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => setDots((e) => (e % 3) + 1), 1000)
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
return (
|
||||
<>
|
||||
{children + " "}
|
||||
{Array.from(Array(dots), () => ".").join("")}
|
||||
{Array.from(Array(3 - dots), (_, i) => (
|
||||
<Fragment key={i}> </Fragment>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
||||
const { payload, full, leave, reset } = useGameProps()
|
||||
const [dots, setDots] = useState(3)
|
||||
const { isConnected } = useSocket()
|
||||
const router = useRouter()
|
||||
const { data: session } = useSession()
|
||||
|
@ -21,12 +38,6 @@ function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
|||
socket.emit("update", full)
|
||||
}, [full, payload?.game?.id, isConnected])
|
||||
|
||||
useEffect(() => {
|
||||
if (payload?.player2) return
|
||||
const interval = setInterval(() => setDots((e) => (e % 3) + 1), 1000)
|
||||
return () => clearInterval(interval)
|
||||
}, [payload?.player2])
|
||||
|
||||
return (
|
||||
<div className="mx-32 flex flex-col self-stretch rounded-3xl bg-gray-400">
|
||||
<div className="flex items-center justify-between border-b-2 border-slate-900">
|
||||
|
@ -58,11 +69,9 @@ function LobbyFrame({ openSettings }: { openSettings: () => void }) {
|
|||
/>
|
||||
) : (
|
||||
<p className="font-farro w-96 text-center text-4xl font-medium">
|
||||
Warte auf {isConnected ? "Spieler 2" : "Verbindung"}{" "}
|
||||
{Array.from(Array(dots), () => ".").join("")}
|
||||
{Array.from(Array(3 - dots), (_, i) => (
|
||||
<Fragment key={i}> </Fragment>
|
||||
))}
|
||||
<WithDots>
|
||||
{"Warte auf " + (isConnected ? "Spieler 2" : "Verbindung")}
|
||||
</WithDots>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -14,7 +14,7 @@ function Player({
|
|||
}) {
|
||||
const text =
|
||||
player?.name ?? "Spieler " + (player?.index === "player2" ? "2" : "1")
|
||||
const primary = userId === player?.id
|
||||
const primary = userId && userId === player?.id
|
||||
|
||||
return (
|
||||
<div className="flex w-96 flex-col items-center gap-16 py-8">
|
||||
|
|
|
@ -1,235 +0,0 @@
|
|||
import {
|
||||
Hit,
|
||||
Mode,
|
||||
MouseCursor,
|
||||
Target,
|
||||
Position,
|
||||
} from "../interfaces/frontend"
|
||||
import BorderTiles from "@components/Gamefield/BorderTiles"
|
||||
import EventBar from "@components/Gamefield/EventBar"
|
||||
import type { PointerProps } from "@components/Gamefield/GamefieldPointer"
|
||||
import HitElems from "@components/Gamefield/HitElems"
|
||||
import Targets from "@components/Gamefield/Targets"
|
||||
import {
|
||||
hitReducer,
|
||||
initlialLastLeftTile,
|
||||
initlialTarget,
|
||||
initlialTargetPreview,
|
||||
initlialMouseCursor,
|
||||
} from "@lib/utils/helpers"
|
||||
import { useCallback, useEffect, useReducer, useState } from "react"
|
||||
|
||||
const modes: Mode[] = [
|
||||
{
|
||||
pointerGrid: Array.from(Array(3), () => Array.from(Array(3))),
|
||||
type: "radar",
|
||||
},
|
||||
{
|
||||
pointerGrid: Array.from(Array(3), () => Array.from(Array(1))),
|
||||
type: "htorpedo",
|
||||
},
|
||||
{
|
||||
pointerGrid: Array.from(Array(1), () => Array.from(Array(3))),
|
||||
type: "vtorpedo",
|
||||
},
|
||||
{
|
||||
pointerGrid: Array.from(Array(1), () => Array.from(Array(1))),
|
||||
type: "missile",
|
||||
},
|
||||
]
|
||||
|
||||
function useGameEvent(count: number) {
|
||||
const [lastLeftTile, setLastLeftTile] =
|
||||
useState<Position>(initlialLastLeftTile)
|
||||
const [target, setTarget] = useState<Target>(initlialTarget)
|
||||
const [eventReady, setEventReady] = useState(false)
|
||||
const [appearOK, setAppearOK] = useState(false)
|
||||
const [targetPreview, setTargetPreview] = useState<Target>(
|
||||
initlialTargetPreview
|
||||
)
|
||||
const [mouseCursor, setMouseCursor] =
|
||||
useState<MouseCursor>(initlialMouseCursor)
|
||||
const [hits, DispatchHits] = useReducer(hitReducer, [] as Hit[])
|
||||
const [mode, setMode] = useState(0)
|
||||
|
||||
const targetList = useCallback(
|
||||
(target: Position) => {
|
||||
const { pointerGrid, type } = modes[mode]
|
||||
const xLength = pointerGrid.length
|
||||
const yLength = pointerGrid[0].length
|
||||
const { x: targetX, y: targetY } = target
|
||||
return pointerGrid
|
||||
.map((arr, i) => {
|
||||
return arr.map((_, i2) => {
|
||||
const relativeX = -Math.floor(xLength / 2) + i
|
||||
const relativeY = -Math.floor(yLength / 2) + i2
|
||||
const x = targetX + (relativeX ?? 0)
|
||||
const y = targetY + (relativeY ?? 0)
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
type,
|
||||
edges: [
|
||||
i === 0 ? "left" : "",
|
||||
i === xLength - 1 ? "right" : "",
|
||||
i2 === 0 ? "top" : "",
|
||||
i2 === yLength - 1 ? "bottom" : "",
|
||||
],
|
||||
}
|
||||
})
|
||||
})
|
||||
.reduce((prev, curr) => [...prev, ...curr], [])
|
||||
},
|
||||
[mode]
|
||||
)
|
||||
|
||||
const isHit = useCallback(
|
||||
(x: number, y: number) => {
|
||||
return hits.filter((h) => h.x === x && h.y === y)
|
||||
},
|
||||
[hits]
|
||||
)
|
||||
|
||||
const settingTarget = useCallback(
|
||||
(isGameTile: boolean, x: number, y: number) => {
|
||||
if (!isGameTile || isHit(x, y).length) return
|
||||
setMouseCursor((e) => ({ ...e, shouldShow: false }))
|
||||
setTarget((t) => {
|
||||
if (t.x === x && t.y === y && t.show) {
|
||||
DispatchHits({
|
||||
type: "fireMissile",
|
||||
payload: { hit: (x + y) % 2 !== 0, x, y },
|
||||
})
|
||||
return { preview: false, show: false, x, y }
|
||||
} else {
|
||||
const target = { preview: false, show: true, x, y }
|
||||
const hasAnyBorder = targetList(target).filter(({ x, y }) =>
|
||||
isBorder(x, y, count)
|
||||
).length
|
||||
if (hasAnyBorder) return t
|
||||
return target
|
||||
}
|
||||
})
|
||||
},
|
||||
[count, isHit, targetList]
|
||||
)
|
||||
|
||||
const isSet = useCallback(
|
||||
(x: number, y: number) => {
|
||||
return (
|
||||
!!targetList(target).filter((field) => x === field.x && y === field.y)
|
||||
.length && target.show
|
||||
)
|
||||
},
|
||||
[target, targetList]
|
||||
)
|
||||
|
||||
const composeTargetTiles = useCallback(
|
||||
(target: Target): PointerProps[] => {
|
||||
const { preview, show } = target
|
||||
const result = targetList(target).map(({ x, y, type, edges }) => {
|
||||
return {
|
||||
preview,
|
||||
x,
|
||||
y,
|
||||
show,
|
||||
type,
|
||||
edges,
|
||||
imply: !!isHit(x, y).length || (!!isSet(x, y) && preview),
|
||||
}
|
||||
})
|
||||
return result
|
||||
},
|
||||
[isHit, isSet, targetList]
|
||||
)
|
||||
|
||||
// handle visibility and position change of targetPreview
|
||||
useEffect(() => {
|
||||
const { show, x, y } = targetPreview
|
||||
// if mouse has moved too quickly and last event was entering and leaving the same field, it must have gone outside the grid
|
||||
const hasLeft = x === lastLeftTile.x && y === lastLeftTile.y
|
||||
const isSet = x === target.x && y === target.y && target.show
|
||||
|
||||
if (show && !appearOK) setTargetPreview((e) => ({ ...e, show: false }))
|
||||
if (
|
||||
!show &&
|
||||
mouseCursor.shouldShow &&
|
||||
eventReady &&
|
||||
appearOK &&
|
||||
!isHit(x, y).length &&
|
||||
!isSet &&
|
||||
!hasLeft
|
||||
)
|
||||
setTargetPreview((e) => ({ ...e, show: true }))
|
||||
}, [
|
||||
targetPreview,
|
||||
mouseCursor.shouldShow,
|
||||
isHit,
|
||||
eventReady,
|
||||
appearOK,
|
||||
lastLeftTile,
|
||||
target,
|
||||
])
|
||||
|
||||
// enable targetPreview event again after 200 ms.
|
||||
useEffect(() => {
|
||||
setEventReady(false)
|
||||
const previewTarget = { x: mouseCursor.x, y: mouseCursor.y }
|
||||
const hasAnyBorder = targetList(previewTarget).filter(({ x, y }) =>
|
||||
isBorder(x, y, count)
|
||||
).length
|
||||
if (targetPreview.show || !appearOK || hasAnyBorder) return
|
||||
const autoTimeout = setTimeout(() => {
|
||||
setTargetPreview((e) => ({ ...e, ...previewTarget }))
|
||||
setEventReady(true)
|
||||
setAppearOK(true)
|
||||
}, 300)
|
||||
|
||||
// or abort if state has changed early
|
||||
return () => {
|
||||
clearTimeout(autoTimeout)
|
||||
}
|
||||
}, [
|
||||
appearOK,
|
||||
count,
|
||||
mouseCursor.x,
|
||||
mouseCursor.y,
|
||||
targetList,
|
||||
targetPreview.show,
|
||||
])
|
||||
|
||||
// approve targetPreview new position after 200 mil. sec.
|
||||
useEffect(() => {
|
||||
// early return to start cooldown only when about to show up
|
||||
const autoTimeout = setTimeout(
|
||||
() => {
|
||||
setAppearOK(!targetPreview.show)
|
||||
},
|
||||
targetPreview.show ? 500 : 300
|
||||
)
|
||||
|
||||
// or abort if movement is repeated early
|
||||
return () => {
|
||||
clearTimeout(autoTimeout)
|
||||
}
|
||||
}, [targetPreview.show])
|
||||
|
||||
return {
|
||||
BorderTiles: () => (
|
||||
<BorderTiles
|
||||
props={{ count, settingTarget, setMouseCursor, setLastLeftTile }}
|
||||
/>
|
||||
),
|
||||
HitElems: () => <HitElems hits={hits} />,
|
||||
Targets: () => (
|
||||
<Targets props={{ composeTargetTiles, target, targetPreview }} />
|
||||
),
|
||||
EventBar: () => <EventBar props={{ setMode, setTarget }} />,
|
||||
}
|
||||
}
|
||||
|
||||
function isBorder(x: number, y: number, count: number) {
|
||||
return x < 2 || x > count + 1 || y < 2 || y > count + 1
|
||||
}
|
||||
|
||||
export default useGameEvent
|
|
@ -3,7 +3,6 @@ export interface Position {
|
|||
y: number
|
||||
}
|
||||
export interface Target extends Position {
|
||||
preview: boolean
|
||||
show: boolean
|
||||
}
|
||||
export interface MouseCursor extends Position {
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
import type { Hit, HitDispatch } from "../../interfaces/frontend"
|
||||
import type {
|
||||
Hit,
|
||||
HitDispatch,
|
||||
Mode,
|
||||
Position,
|
||||
Target,
|
||||
TargetList,
|
||||
} from "../../interfaces/frontend"
|
||||
import { count } from "@components/Gamefield/Gamefield"
|
||||
import { PointerProps } from "@components/Gamefield/GamefieldPointer"
|
||||
|
||||
export function borderCN(count: number, x: number, y: number) {
|
||||
if (x === 0) return "left"
|
||||
|
@ -28,10 +37,92 @@ export function hitReducer(formObject: Hit[], action: HitDispatch) {
|
|||
return formObject
|
||||
}
|
||||
}
|
||||
export const initlialLastLeftTile = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
||||
const modes: Mode[] = [
|
||||
{
|
||||
pointerGrid: Array.from(Array(3), () => Array.from(Array(3))),
|
||||
type: "radar",
|
||||
},
|
||||
{
|
||||
pointerGrid: Array.from(Array(3), () => Array.from(Array(1))),
|
||||
type: "htorpedo",
|
||||
},
|
||||
{
|
||||
pointerGrid: Array.from(Array(1), () => Array.from(Array(3))),
|
||||
type: "vtorpedo",
|
||||
},
|
||||
{
|
||||
pointerGrid: Array.from(Array(1), () => Array.from(Array(1))),
|
||||
type: "missile",
|
||||
},
|
||||
]
|
||||
|
||||
function isBorder(x: number, y: number, count: number) {
|
||||
return x < 2 || x > count + 1 || y < 2 || y > count + 1
|
||||
}
|
||||
|
||||
export function isHit(x: number, y: number, hits: Hit[]) {
|
||||
return hits.filter((h) => h.x === x && h.y === y)
|
||||
}
|
||||
|
||||
function isSet(x: number, y: number, targetList: TargetList[], show: boolean) {
|
||||
return (
|
||||
!!targetList.filter((field) => x === field.x && y === field.y).length &&
|
||||
show
|
||||
)
|
||||
}
|
||||
|
||||
function targetList(
|
||||
{ x: targetX, y: targetY }: Position,
|
||||
mode: number
|
||||
): TargetList[] {
|
||||
const { pointerGrid, type } = modes[mode]
|
||||
const xLength = pointerGrid.length
|
||||
const yLength = pointerGrid[0].length
|
||||
return pointerGrid
|
||||
.map((arr, i) => {
|
||||
return arr.map((_, i2) => {
|
||||
const relativeX = -Math.floor(xLength / 2) + i
|
||||
const relativeY = -Math.floor(yLength / 2) + i2
|
||||
const x = targetX + (relativeX ?? 0)
|
||||
const y = targetY + (relativeY ?? 0)
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
type,
|
||||
edges: [
|
||||
i === 0 ? "left" : "",
|
||||
i === xLength - 1 ? "right" : "",
|
||||
i2 === 0 ? "top" : "",
|
||||
i2 === yLength - 1 ? "bottom" : "",
|
||||
],
|
||||
}
|
||||
})
|
||||
})
|
||||
.reduce((prev, curr) => [...prev, ...curr], [])
|
||||
}
|
||||
|
||||
export function overlapsWithAnyBorder(target: Position, mode: number) {
|
||||
return targetList(target, mode).filter(({ x, y }) => isBorder(x, y, count))
|
||||
.length
|
||||
}
|
||||
|
||||
export function composeTargetTiles(
|
||||
target: Target,
|
||||
mode: number,
|
||||
hits: Hit[]
|
||||
): PointerProps[] {
|
||||
const { show } = target
|
||||
return targetList(target, mode).map((targetItem) => {
|
||||
const { x, y } = targetItem
|
||||
return {
|
||||
...targetItem,
|
||||
show,
|
||||
imply: !!isHit(x, y, hits).length,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const initlialTarget = {
|
||||
preview: false,
|
||||
show: false,
|
||||
|
|
|
@ -43,6 +43,11 @@ export default async function create(
|
|||
create: {
|
||||
userId: id,
|
||||
index: "player1",
|
||||
chats: {
|
||||
create: {
|
||||
event: "created",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -119,7 +119,6 @@ const SocketHandler = async (
|
|||
})
|
||||
let body: GamePropsSchema
|
||||
if (user_Game.index === "player1" && enemy) {
|
||||
console.log(1)
|
||||
body = composeBody(
|
||||
(
|
||||
await prisma.user_Game.update({
|
||||
|
@ -140,7 +139,6 @@ const SocketHandler = async (
|
|||
).game
|
||||
)
|
||||
} else {
|
||||
console.log(2)
|
||||
const game = await prisma.game.findUnique({
|
||||
where: {
|
||||
id: socket.data.gameId,
|
||||
|
@ -151,7 +149,6 @@ const SocketHandler = async (
|
|||
body = composeBody(game)
|
||||
}
|
||||
const { payload, hash } = body
|
||||
console.log(payload?.player1, payload?.player2)
|
||||
if (!payload || !hash) return cb(false)
|
||||
io.to(socket.data.gameId).emit(
|
||||
"playerEvent",
|
||||
|
|
|
@ -16,6 +16,12 @@ export default function Lobby() {
|
|||
<meta name="description" content="Generated by create next app" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/cpfont_ote/CP Font.otf"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
/>
|
||||
</Head>
|
||||
<div
|
||||
className={classNames(
|
||||
|
|
|
@ -15,8 +15,11 @@ import { toast } from "react-toastify"
|
|||
import { Icons } from "react-toastify"
|
||||
|
||||
export function isAuthenticated(res: Response) {
|
||||
if (status[`${res.status}_CLASS`] === status.classes.SUCCESSFUL)
|
||||
return res.json()
|
||||
switch (status[`${res.status}_CLASS`]) {
|
||||
case status.classes.SUCCESSFUL:
|
||||
case status.classes.REDIRECTION:
|
||||
return res.json()
|
||||
}
|
||||
|
||||
const resStatus = status[`${res.status}_CLASS`]
|
||||
if (typeof resStatus !== "string") return
|
||||
|
@ -60,10 +63,13 @@ export default function Start() {
|
|||
|
||||
const gameFetch = useCallback(
|
||||
async (pin?: string) => {
|
||||
const gamePromise = fetch("/api/game/" + (!pin ? "create" : "join"), {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ pin }),
|
||||
})
|
||||
const gameRequestPromise = fetch(
|
||||
"/api/game/" + (!pin ? "create" : "join"),
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({ pin }),
|
||||
}
|
||||
)
|
||||
.then(isAuthenticated)
|
||||
.then((game) => GamePropsSchema.parse(game))
|
||||
|
||||
|
@ -76,9 +82,9 @@ export default function Start() {
|
|||
hideProgressBar: true,
|
||||
closeButton: false,
|
||||
})
|
||||
const res = await gamePromise.catch(() =>
|
||||
const res = await gameRequestPromise.catch(() =>
|
||||
toast.update(toastId, {
|
||||
render: "Es ist ein Fehler aufgetreten 🤯",
|
||||
render: "Es ist ein Fehler aufgetreten bei der Anfrage 🤯",
|
||||
type: "error",
|
||||
icon: Icons.error,
|
||||
theme: "colored",
|
||||
|
@ -108,7 +114,7 @@ export default function Start() {
|
|||
)
|
||||
.catch(() =>
|
||||
toast.update(toastId, {
|
||||
render: "Es ist ein Fehler aufgetreten 🤯",
|
||||
render: "Es ist ein Fehler aufgetreten beim Seiten wechsel 🤯",
|
||||
type: "error",
|
||||
icon: Icons.error,
|
||||
theme: "colored",
|
||||
|
|
|
@ -197,7 +197,7 @@ body {
|
|||
}
|
||||
|
||||
&.preview {
|
||||
--color: lawngreen;
|
||||
--color: forestgreen;
|
||||
background-color: #0001;
|
||||
// border: 5px dashed var(--color);
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
@font-face {
|
||||
font-family: "CP_Font";
|
||||
src: url("/fonts/cpfont_ote/CP Font.otf") format("opentype");
|
||||
}
|
||||
|
||||
@mixin CP_Font {
|
||||
font-family: "CP_Font", sans-serif;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue