Remove JSX from useGameEvents Hook
This commit is contained in:
parent
4bb3054a0e
commit
8397320a6b
7 changed files with 98 additions and 79 deletions
|
@ -1,5 +1,5 @@
|
||||||
import { CSSProperties, Dispatch, SetStateAction } from 'react'
|
import { CSSProperties, Dispatch, SetStateAction } from 'react'
|
||||||
import { borderCN, cornerCN, fieldIndex } from '../utils/helpers'
|
import { borderCN, cornerCN, fieldIndex } from '../lib/utils/helpers'
|
||||||
import { Position, MouseCursor } from '../interfaces/frontend'
|
import { Position, MouseCursor } from '../interfaces/frontend'
|
||||||
|
|
||||||
type TilesType = {
|
type TilesType = {
|
||||||
|
@ -35,7 +35,8 @@ function BorderTiles({ props: { count, settingTarget, setMouseCursor, setLastLef
|
||||||
tilesProperties.push({ key, classNameString, isGameTile, x: x + 1, y: y + 1 })
|
tilesProperties.push({ key, classNameString, isGameTile, x: x + 1, y: y + 1 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return <>
|
|
||||||
|
return (<>
|
||||||
{tilesProperties.map(({ key, classNameString, isGameTile, x, y }) => {
|
{tilesProperties.map(({ key, classNameString, isGameTile, x, y }) => {
|
||||||
return <div
|
return <div
|
||||||
key={key}
|
key={key}
|
||||||
|
@ -46,7 +47,7 @@ function BorderTiles({ props: { count, settingTarget, setMouseCursor, setLastLef
|
||||||
onMouseLeave={() => setLastLeftTile({ x, y })}
|
onMouseLeave={() => setLastLeftTile({ x, y })}
|
||||||
></div>
|
></div>
|
||||||
})}
|
})}
|
||||||
</>
|
</>)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BorderTiles
|
export default BorderTiles
|
||||||
|
|
33
leaky-ships/components/EventBar.tsx
Normal file
33
leaky-ships/components/EventBar.tsx
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import React, { Dispatch, SetStateAction } from 'react'
|
||||||
|
import { Items, Target } from '../interfaces/frontend'
|
||||||
|
import Item from './Item'
|
||||||
|
|
||||||
|
function EventBar({ props: { setMode, setTarget } }: {
|
||||||
|
props: {
|
||||||
|
setMode: Dispatch<SetStateAction<number>>,
|
||||||
|
setTarget: Dispatch<SetStateAction<Target>>
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
const items: Items[] = [
|
||||||
|
{ icon: 'burger-menu', text: 'Menu' },
|
||||||
|
{ icon: 'radar', text: 'Radar scan', mode: 0, amount: 1 },
|
||||||
|
{ icon: 'torpedo', text: 'Fire torpedo', mode: 1, amount: 1 },
|
||||||
|
{ icon: 'scope', text: 'Fire missile', mode: 2 },
|
||||||
|
{ icon: 'gear', text: 'Settings' }
|
||||||
|
]
|
||||||
|
return (
|
||||||
|
<div className='event-bar'>
|
||||||
|
{items.map((e, i) => (
|
||||||
|
<Item key={i} props={{
|
||||||
|
...e, callback: () => {
|
||||||
|
if (e.mode !== undefined)
|
||||||
|
setMode(e.mode)
|
||||||
|
setTarget(e => ({ ...e, show: false }))
|
||||||
|
}
|
||||||
|
}} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EventBar
|
|
@ -1,21 +1,21 @@
|
||||||
import { CSSProperties } from 'react'
|
import { CSSProperties } from 'react'
|
||||||
// import Bluetooth from './Bluetooth'
|
// import Bluetooth from './Bluetooth'
|
||||||
import BorderTiles from './BorderTiles'
|
import BorderTiles from './BorderTiles'
|
||||||
|
import EventBar from './EventBar'
|
||||||
// import FogImages from './FogImages'
|
// import FogImages from './FogImages'
|
||||||
import HitElems from './HitElems'
|
import HitElems from './HitElems'
|
||||||
import Labeling from './Labeling'
|
import Labeling from './Labeling'
|
||||||
import Ships from './Ships'
|
import Ships from './Ships'
|
||||||
import useGameEvent from './useGameEvent'
|
import useGameEvent from '../lib/hooks/useGameEvent'
|
||||||
|
import Targets from './Targets'
|
||||||
|
|
||||||
function Gamefield() {
|
function Gamefield() {
|
||||||
|
|
||||||
const count = 12
|
const count = 12
|
||||||
const {
|
const {
|
||||||
targets,
|
pointersProps,
|
||||||
eventBar,
|
targetsProps,
|
||||||
setLastLeftTile,
|
tilesProps,
|
||||||
settingTarget,
|
|
||||||
setMouseCursor,
|
|
||||||
hits
|
hits
|
||||||
} = useGameEvent(count)
|
} = useGameEvent(count)
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ function Gamefield() {
|
||||||
{/* <Bluetooth /> */}
|
{/* <Bluetooth /> */}
|
||||||
<div id="game-frame" style={{ '--i': count } as CSSProperties}>
|
<div id="game-frame" style={{ '--i': count } as CSSProperties}>
|
||||||
{/* Bordes */}
|
{/* Bordes */}
|
||||||
<BorderTiles props={{ count, settingTarget, setMouseCursor, setLastLeftTile }} />
|
<BorderTiles props={tilesProps} />
|
||||||
|
|
||||||
{/* Collumn lettes and row numbers */}
|
{/* Collumn lettes and row numbers */}
|
||||||
<Labeling count={count} />
|
<Labeling count={count} />
|
||||||
|
@ -36,10 +36,10 @@ function Gamefield() {
|
||||||
|
|
||||||
{/* Fog images */}
|
{/* Fog images */}
|
||||||
{/* <FogImages /> */}
|
{/* <FogImages /> */}
|
||||||
{targets}
|
<Targets props={pointersProps} />
|
||||||
{/* <span id='dev-debug' style={{gridArea: '1 / 12 / 1 / 15', backgroundColor: 'red', zIndex: 3} as CSSProperties}>Debug</span> */}
|
{/* <span id='dev-debug' style={{gridArea: '1 / 12 / 1 / 15', backgroundColor: 'red', zIndex: 3} as CSSProperties}>Debug</span> */}
|
||||||
</div>
|
</div>
|
||||||
{eventBar}
|
<EventBar props={targetsProps} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import { CSSProperties } from 'react'
|
import { CSSProperties } from 'react'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { faRadar } from '@fortawesome/pro-thin-svg-icons'
|
import { faRadar } from '@fortawesome/pro-thin-svg-icons'
|
||||||
|
import { Target, TargetList } from '../interfaces/frontend'
|
||||||
|
|
||||||
|
export interface PointerProps extends Target, TargetList {
|
||||||
|
imply: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
function GamefieldPointer({ props: {
|
function GamefieldPointer({ props: {
|
||||||
preview,
|
preview,
|
||||||
|
@ -12,17 +17,7 @@ function GamefieldPointer({ props: {
|
||||||
type,
|
type,
|
||||||
edges,
|
edges,
|
||||||
imply
|
imply
|
||||||
} }: {
|
} }: { props: PointerProps }) {
|
||||||
props: {
|
|
||||||
preview: boolean,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
show: boolean,
|
|
||||||
type: string,
|
|
||||||
edges: string[],
|
|
||||||
imply: boolean,
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
const isRadar = type === 'radar'
|
const isRadar = type === 'radar'
|
||||||
const style = !(isRadar && !edges.filter(s => s).length) ? { '--x': x, '--y': y } : { '--x1': x - 1, '--x2': x + 2, '--y1': y - 1, '--y2': y + 2 }
|
const style = !(isRadar && !edges.filter(s => s).length) ? { '--x': x, '--y': y } : { '--x1': x - 1, '--x2': x + 2, '--y1': y - 1, '--y2': y + 2 }
|
||||||
return (
|
return (
|
||||||
|
|
20
leaky-ships/components/Targets.tsx
Normal file
20
leaky-ships/components/Targets.tsx
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Target } from '../interfaces/frontend'
|
||||||
|
import GamefieldPointer, { PointerProps } from './GamefieldPointer'
|
||||||
|
|
||||||
|
function Targets({ props: { composeTargetTiles, target, targetPreview } }: {
|
||||||
|
props: {
|
||||||
|
composeTargetTiles: (target: Target) => PointerProps[],
|
||||||
|
target: Target,
|
||||||
|
targetPreview: Target
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
return (<>
|
||||||
|
{[
|
||||||
|
...composeTargetTiles(target).map((props, i) => <GamefieldPointer key={'t' + i} props={props} />),
|
||||||
|
...composeTargetTiles(targetPreview).map((props, i) => <GamefieldPointer key={'p' + i} props={props} />)
|
||||||
|
]}
|
||||||
|
</>)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Targets
|
|
@ -1,8 +1,14 @@
|
||||||
import { useCallback, useEffect, useMemo, useReducer, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useReducer, useState } from 'react'
|
||||||
import { hitReducer, initlialLastLeftTile, initlialTarget, initlialTargetPreview, initlialMouseCursor, isHit } from '../utils/helpers'
|
import { hitReducer, initlialLastLeftTile, initlialTarget, initlialTargetPreview, initlialMouseCursor } from '../utils/helpers'
|
||||||
import { Hit, Items, Mode, MouseCursor, Target, Position } from '../interfaces/frontend'
|
import { Hit, Mode, MouseCursor, Target, Position } from '../../interfaces/frontend'
|
||||||
import Item from './Item'
|
import { arst } from '../../components/GamefieldPointer'
|
||||||
import GamefieldPointer from './GamefieldPointer'
|
|
||||||
|
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: [[{ x: 0, y: 0 }]], type: 'missile' }
|
||||||
|
]
|
||||||
|
|
||||||
function useGameEvent(count: number) {
|
function useGameEvent(count: number) {
|
||||||
const [lastLeftTile, setLastLeftTile] = useState<Position>(initlialLastLeftTile)
|
const [lastLeftTile, setLastLeftTile] = useState<Position>(initlialLastLeftTile)
|
||||||
|
@ -14,13 +20,6 @@ function useGameEvent(count: number) {
|
||||||
const [hits, DispatchHits] = useReducer(hitReducer, [] as Hit[])
|
const [hits, DispatchHits] = useReducer(hitReducer, [] as Hit[])
|
||||||
const [mode, setMode] = useState(0)
|
const [mode, setMode] = useState(0)
|
||||||
|
|
||||||
const modes = useMemo<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: [[{ x: 0, y: 0 }]], type: 'missile' }
|
|
||||||
], [])
|
|
||||||
|
|
||||||
const targetList = useCallback((target: Position) => {
|
const targetList = useCallback((target: Position) => {
|
||||||
const { pointerGrid, type } = modes[mode]
|
const { pointerGrid, type } = modes[mode]
|
||||||
const xLength = pointerGrid.length
|
const xLength = pointerGrid.length
|
||||||
|
@ -46,10 +45,10 @@ function useGameEvent(count: number) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.reduce((prev, curr) => [...prev, ...curr], [])
|
.reduce((prev, curr) => [...prev, ...curr], [])
|
||||||
}, [mode, modes])
|
}, [mode])
|
||||||
|
|
||||||
const settingTarget = useCallback((isGameTile: boolean, x: number, y: number) => {
|
const settingTarget = useCallback((isGameTile: boolean, x: number, y: number) => {
|
||||||
if (!isGameTile || isHit(hits, x, y).length)
|
if (!isGameTile || isHit(x, y).length)
|
||||||
return
|
return
|
||||||
setMouseCursor(e => ({ ...e, shouldShow: false }))
|
setMouseCursor(e => ({ ...e, shouldShow: false }))
|
||||||
setTarget(t => {
|
setTarget(t => {
|
||||||
|
@ -67,9 +66,15 @@ function useGameEvent(count: number) {
|
||||||
})
|
})
|
||||||
}, [count, hits, targetList])
|
}, [count, hits, targetList])
|
||||||
|
|
||||||
const isSet = useCallback((x: number, y: number) => !!targetList(target).filter(field => x === field.x && y === field.y).length && target.show, [target, 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) => {
|
const isHit = useCallback((x: number, y: number) => {
|
||||||
|
return hits.filter(h => h.x === x && h.y === y)
|
||||||
|
}, [hits])
|
||||||
|
|
||||||
|
const composeTargetTiles = useCallback((target: Target): arst[] => {
|
||||||
const { preview, show } = target
|
const { preview, show } = target
|
||||||
const result = targetList(target).map(({ x, y, type, edges }) => {
|
const result = targetList(target).map(({ x, y, type, edges }) => {
|
||||||
return {
|
return {
|
||||||
|
@ -79,15 +84,12 @@ function useGameEvent(count: number) {
|
||||||
show,
|
show,
|
||||||
type,
|
type,
|
||||||
edges,
|
edges,
|
||||||
imply: !!isHit(hits, x, y).length || (!!isSet(x, y) && preview)
|
imply: !!isHit(x, y).length || (!!isSet(x, y) && preview)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
}, [hits, isSet, targetList])
|
}, [hits, isSet, targetList])
|
||||||
|
|
||||||
// if (!targetPreviewPos.shouldShow)
|
|
||||||
// return
|
|
||||||
|
|
||||||
// handle visibility and position change of targetPreview
|
// handle visibility and position change of targetPreview
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { show, x, y } = targetPreview
|
const { show, x, y } = targetPreview
|
||||||
|
@ -97,7 +99,7 @@ function useGameEvent(count: number) {
|
||||||
|
|
||||||
if (show && !appearOK)
|
if (show && !appearOK)
|
||||||
setTargetPreview(e => ({ ...e, show: false }))
|
setTargetPreview(e => ({ ...e, show: false }))
|
||||||
if (!show && mouseCursor.shouldShow && eventReady && appearOK && !isHit(hits, x, y).length && !isSet && !hasLeft)
|
if (!show && mouseCursor.shouldShow && eventReady && appearOK && !isHit(x, y).length && !isSet && !hasLeft)
|
||||||
setTargetPreview(e => ({ ...e, show: true }))
|
setTargetPreview(e => ({ ...e, show: true }))
|
||||||
}, [targetPreview, mouseCursor.shouldShow, hits, eventReady, appearOK, lastLeftTile, target])
|
}, [targetPreview, mouseCursor.shouldShow, hits, eventReady, appearOK, lastLeftTile, target])
|
||||||
|
|
||||||
|
@ -133,39 +135,10 @@ function useGameEvent(count: number) {
|
||||||
}
|
}
|
||||||
}, [targetPreview.show])
|
}, [targetPreview.show])
|
||||||
|
|
||||||
const targets = useMemo(() => [
|
|
||||||
...composeTargetTiles(target).map((props, i) => <GamefieldPointer key={'t' + i} props={props} />),
|
|
||||||
...composeTargetTiles(targetPreview).map((props, i) => <GamefieldPointer key={'p' + i} props={props} />)
|
|
||||||
], [composeTargetTiles, target, targetPreview])
|
|
||||||
|
|
||||||
const eventBar = useMemo(() => {
|
|
||||||
const items: Items[] = [
|
|
||||||
{ icon: 'burger-menu', text: 'Menu' },
|
|
||||||
{ icon: 'radar', text: 'Radar scan', mode: 0, amount: 1 },
|
|
||||||
{ icon: 'torpedo', text: 'Fire torpedo', mode: 1, amount: 1 },
|
|
||||||
{ icon: 'scope', text: 'Fire missile', mode: 2 },
|
|
||||||
{ icon: 'gear', text: 'Settings' }
|
|
||||||
]
|
|
||||||
return (
|
|
||||||
<div className='event-bar'>
|
|
||||||
{items.map((e, i) => (
|
|
||||||
<Item key={i} props={{
|
|
||||||
...e, callback: () => {
|
|
||||||
if (e.mode !== undefined)
|
|
||||||
setMode(e.mode)
|
|
||||||
setTarget(e => ({ ...e, show: false }))
|
|
||||||
}
|
|
||||||
}} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}, [])
|
|
||||||
return {
|
return {
|
||||||
targets,
|
tilesProps: { count, settingTarget, setMouseCursor, setLastLeftTile },
|
||||||
eventBar,
|
pointersProps: { composeTargetTiles, target, targetPreview },
|
||||||
setLastLeftTile,
|
targetsProps: { setMode, setTarget },
|
||||||
settingTarget,
|
|
||||||
setMouseCursor,
|
|
||||||
hits
|
hits
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import { Hit, HitDispatch } from "../interfaces/frontend"
|
import { Hit, HitDispatch } from "../../interfaces/frontend"
|
||||||
|
|
||||||
export function borderCN(count: number, x: number, y: number) {
|
export function borderCN(count: number, x: number, y: number) {
|
||||||
if (x === 0)
|
if (x === 0)
|
||||||
|
@ -58,6 +58,3 @@ export const initlialMouseCursor = {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0
|
y: 0
|
||||||
}
|
}
|
||||||
export function isHit(hits: Hit[], x: number, y: number) {
|
|
||||||
return hits.filter(h => h.x === x && h.y === y)
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue