(e: TargetType, mod: TargetModifierType) {
+ const { show, ...pos } = e
+ const { target, params } = mod
+ return {
+ target: {
+ show,
+ x: pos.x + (target.x ?? 0),
+ y: pos.y + (target.y ?? 0)
+ },
+ params
+ }
}
- const isSet = useCallback((x: number, y: number) => targetList.filter(target => x === target.x && y === target.y).length && target.show, [targetList, target])
+ const isSet = useCallback((x: number, y: number) => targetList.filter(({ target }) => x === target.x && y === target.y).length && target.show, [targetList, target])
const scopeGrid = useMemo(() => {
- const { xEnable, yEnable, type } = modes[mode]
- const matrix: { x: number, y: number, edges: string[] }[][] = []
+ const { xEnable, yEnable } = modes[mode]
+ const matrix: TargetModifierType[][] = []
let y = 0
let x = 0
const yLength = (yEnable ? 2 : 0)
@@ -53,38 +52,47 @@ function useGameEvent(count: number) {
x = i2 + (xEnable ? -1 : 0);
(matrix[i] ??= [])[i2] = {
- x,
- y,
- edges: [
- i2 === 0 ? 'left' : '',
- i2 === xLength ? 'right' : '',
- i === 0 ? 'top' : '',
- i === yLength ? 'bottom' : '',
- ]
+ target: {
+ x,
+ y,
+ },
+ params: {
+ edges: [
+ i2 === 0 ? 'left' : '',
+ i2 === xLength ? 'right' : '',
+ i === 0 ? 'top' : '',
+ i === yLength ? 'bottom' : '',
+ ],
+ imply: false
+ }
}
}
}
const fields = matrix.reduce((prev, curr) => [...prev, ...curr], [])
- return { fields, type }
- }, [modes, mode])
+ return fields
+ }, [mode])
- const Targets = useCallback((targets: { show: boolean, x: number, y: number, edges: string[] }[], preview?: boolean) => {
- const { type } = scopeGrid
- return targets.map(({ edges, ...target }, i) => )
- }, [scopeGrid, mode])
+ const Targets = useCallback((targets: TargetListType[], preview?: boolean) => {
+ const { type } = modes[mode]
+ return targets.map(({ target, params }, i) => )
+ }, [mode])
useEffect(() => {
- const { fields } = scopeGrid
- const result = fields.map(e => modXY(target, e))
- .filter(({ x, y }) => {
+ const result = scopeGrid.map(e => modXY(target, e))
+ .filter(({ target: { x, y } }) => {
const border = [
x < 2,
x > count,
y < 2,
y > count,
].reduce((prev, curr) => prev || curr, false)
- // console.log(!isHit(hits, x, y).length, !borders)
- return !isHit(hits, x, y).length && !border
+ return !border
+ }).map(field => {
+ const { target, params } = field
+ const { x, y } = target
+ if (isHit(hits, x, y).length)
+ return { ...field, params: { ...params, imply: true } }
+ return field
})
setTargetList(e => {
if (JSON.stringify(e) === JSON.stringify(result))
@@ -94,24 +102,30 @@ function useGameEvent(count: number) {
}, [scopeGrid, target, count, hits]);
useEffect(() => {
- const { fields } = scopeGrid
- const result = fields.map(e => modXY(targetPreview, e))
- .filter(({ x, y }) => {
+ const result = scopeGrid.map(e => modXY(targetPreview, e))
+ .filter(({ target: { x, y } }) => {
const border = [
x < 2,
x > count + 1,
y < 2,
y > count + 1,
].reduce((prev, curr) => prev || curr, false)
- // console.log(!isHit(hits, x, y).length, !isSet(x, y), !borders)
- return !isHit(hits, x, y).length && !isSet(x, y) && !border
+ return !border
+ }).map(field => {
+ const { target, params } = field
+ const { x, y } = target
+ if (isHit(hits, x, y).length || isSet(x, y))
+ return { ...field, params: { ...params, imply: true } }
+ return field
})
+ if (!targetPreviewPos.shouldShow)
+ return
setTargetPreviewList(e => {
if (JSON.stringify(e) === JSON.stringify(result))
return e
return result
})
- }, [scopeGrid, targetPreview, count, hits, isSet]);
+ }, [scopeGrid, targetPreview, count, hits, isSet, targetPreviewPos.shouldShow]);
// handle visibility and position change of targetPreview
useEffect(() => {
@@ -162,13 +176,13 @@ function useGameEvent(count: number) {
>, [Targets, targetList, targetPreviewList])
const eventBar = useMemo(() => {
- const items = [
- { icon: 'burger-menu', text: 'Menu' },
- { icon: 'radar', text: 'Radar scan', type: 'radar' },
- { icon: 'missle', text: 'Fire torpedo', type: 'hTorpedo' },
- { icon: 'scope', text: 'Fire missle', type: 'missle' },
- { icon: 'gear', text: 'Settings' }
- ]
+ const items: ItemsType[] = [
+ { icon: 'burger-menu', text: 'Menu' },
+ { icon: 'radar', text: 'Radar scan', type: 'radar', amount: 1 },
+ { icon: 'missle', text: 'Fire torpedo', type: 'hTorpedo', amount: 1 },
+ { icon: 'scope', text: 'Fire missle', type: 'missle' },
+ { icon: 'gear', text: 'Settings' }
+ ]
return (
{items.map((e, i) => (
diff --git a/leaky-ships/interfaces.ts b/leaky-ships/interfaces.ts
index 3ad75f4..83bd8ec 100644
--- a/leaky-ships/interfaces.ts
+++ b/leaky-ships/interfaces.ts
@@ -1,34 +1,78 @@
-export interface LastLeftTileType {
+import { modes } from "./components/useGameEvent";
+
+export type LastLeftTileType = {
x: number,
y: number
}
-export interface TargetType {
+export type TargetType = {
show: boolean,
x: number,
y: number
};
-export interface TargetPreviewType {
+export type TargetPreviewType = {
show: boolean,
x: number,
y: number
};
-export interface TargetPreviewPosType {
+export type TargetPreviewPosType = {
shouldShow: boolean,
x: number,
y: number
}
-export interface FieldType {
+export type TargetListType = {
+ target: {
+ show: boolean,
+ x: number,
+ y: number,
+ },
+ params: {
+ edges: string[],
+ imply: boolean
+ }
+}
+export type TargetModifierType = {
+ target: {
+ x: number,
+ y: number,
+ },
+ params: {
+ edges: string[],
+ imply: boolean
+ }
+}
+export type ItemsType = {
+ icon: string,
+ text: string,
+ type?: keyof typeof modes,
+ amount?: number,
+}
+export type FieldType = {
field: string,
x: number,
y: number,
};
-export interface HitType {
+export type HitType = {
hit: boolean,
x: number,
y: number,
};
-interface fireMissle { type: 'fireMissle', payload: { x: number, y: number, hit: boolean } };
-interface removeMissle { type: 'removeMissle', payload: { x: number, y: number, hit: boolean } };
+type fireMissle = {
+ type: 'fireMissle',
+ payload: {
+ x: number,
+ y: number,
+ hit: boolean
+ }
+};
+type removeMissle = {
+ type:
+ 'removeMissle',
+ payload: {
+ x: number,
+ y: number,
+ hit: boolean
+ }
+};
export type HitDispatchType = fireMissle | removeMissle;
diff --git a/leaky-ships/styles/App.scss b/leaky-ships/styles/App.scss
index 73b72ee..bea03e9 100644
--- a/leaky-ships/styles/App.scss
+++ b/leaky-ships/styles/App.scss
@@ -154,7 +154,7 @@ body {
color: red;
}
}
-
+
&.target {
--color: red;
color: var(--color);
@@ -172,6 +172,10 @@ body {
opacity: 1;
}
+ &.imply>svg {
+ opacity: 0;
+ }
+
&.left {
border-left: 2px solid var(--color);
}
@@ -188,6 +192,22 @@ body {
border-bottom: 2px solid var(--color);
}
+ &.imply.left {
+ border-left: 2px dashed white;
+ }
+
+ &.imply.right {
+ border-right: 2px dashed white;
+ }
+
+ &.imply.top {
+ border-top: 2px dashed white;
+ }
+
+ &.imply.bottom {
+ border-bottom: 2px dashed white;
+ }
+
&.left.top {
border-top-left-radius: 8px;
}
@@ -246,12 +266,31 @@ body {
gap: .5rem;
width: 128px;
- img {
- width: 64px;
- padding: 8px;
- @include pixelart;
- background-color: white;
- border-radius: 1rem;
+ .container {
+ img {
+ width: 64px;
+ padding: 8px;
+ @include pixelart;
+ background-color: white;
+ border-radius: 1rem;
+ }
+
+ &.amount {
+ position: relative;
+
+ &::after {
+ content: var(--amount);
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ color: black;
+ background-color: white;
+ border: 1px solid black;
+ border-radius: 8px;
+ font-size: 16px;
+ padding: 2px 8px;
+ }
+ }
}
span {