commit
11bc75aa61
22 changed files with 479 additions and 284 deletions
|
@ -1,24 +1,24 @@
|
||||||
import { CSSProperties, Dispatch, SetStateAction } from 'react';
|
import { CSSProperties, Dispatch, SetStateAction } from 'react';
|
||||||
import { borderCN, cornerCN, fieldIndex, isHit } from '../helpers';
|
import { borderCN, cornerCN, fieldIndex } from '../helpers';
|
||||||
import { HitDispatchType, HitType, LastLeftTileType, TargetPreviewPosType, TargetType } from '../interfaces';
|
import { LastLeftTileType, TargetPreviewPosType } from '../interfaces';
|
||||||
|
|
||||||
function BorderTiles({ props: { count, setTarget, setTargetPreviewPos, hits, DispatchHits, setLastLeftTile } }: {
|
type TilesType = {
|
||||||
|
key: number,
|
||||||
|
isGameTile: boolean,
|
||||||
|
classNameString: string,
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
}
|
||||||
|
|
||||||
|
function BorderTiles({ props: { count, settingTarget, setTargetPreviewPos, setLastLeftTile } }: {
|
||||||
props: {
|
props: {
|
||||||
count: number,
|
count: number,
|
||||||
setTarget: Dispatch<SetStateAction<TargetType>>,
|
settingTarget: (isGameTile: boolean, x: number, y: number) => void,
|
||||||
setTargetPreviewPos: Dispatch<SetStateAction<TargetPreviewPosType>>,
|
setTargetPreviewPos: Dispatch<SetStateAction<TargetPreviewPosType>>,
|
||||||
hits: HitType[],
|
|
||||||
DispatchHits: Dispatch<HitDispatchType>,
|
|
||||||
setLastLeftTile: Dispatch<SetStateAction<LastLeftTileType>>
|
setLastLeftTile: Dispatch<SetStateAction<LastLeftTileType>>
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
let tilesProperties: {
|
let tilesProperties: TilesType[] = [];
|
||||||
key: number,
|
|
||||||
isGameTile: boolean,
|
|
||||||
classNameString: string,
|
|
||||||
x: number,
|
|
||||||
y: number
|
|
||||||
}[] = [];
|
|
||||||
|
|
||||||
for (let y = 0; y < count + 2; y++) {
|
for (let y = 0; y < count + 2; y++) {
|
||||||
for (let x = 0; x < count + 2; x++) {
|
for (let x = 0; x < count + 2; x++) {
|
||||||
|
@ -41,20 +41,7 @@ function BorderTiles({ props: { count, setTarget, setTargetPreviewPos, hits, Dis
|
||||||
key={key}
|
key={key}
|
||||||
className={classNameString}
|
className={classNameString}
|
||||||
style={{ '--x': x, '--y': y } as CSSProperties}
|
style={{ '--x': x, '--y': y } as CSSProperties}
|
||||||
onClick={() => {
|
onClick={() => settingTarget(isGameTile, x, y)}
|
||||||
if (!isGameTile || isHit(hits, x, y).length)
|
|
||||||
return;
|
|
||||||
setTargetPreviewPos(e => ({ ...e, shouldShow: false }))
|
|
||||||
setTarget(t => {
|
|
||||||
if (t.x === x && t.y === y && t.show) {
|
|
||||||
DispatchHits({ type: 'fireMissle', payload: { hit: (x + y) % 2 !== 0, x, y } });
|
|
||||||
return { show: false, x, y };
|
|
||||||
} else {
|
|
||||||
return { show: true, x, y };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}}
|
|
||||||
onMouseEnter={() => setTargetPreviewPos({ x, y, shouldShow: isGameTile })}
|
onMouseEnter={() => setTargetPreviewPos({ x, y, shouldShow: isGameTile })}
|
||||||
onMouseLeave={() => setLastLeftTile({ x, y })}
|
onMouseLeave={() => setLastLeftTile({ x, y })}
|
||||||
></div>
|
></div>
|
||||||
|
|
|
@ -14,10 +14,9 @@ function Gamefield() {
|
||||||
targets,
|
targets,
|
||||||
eventBar,
|
eventBar,
|
||||||
setLastLeftTile,
|
setLastLeftTile,
|
||||||
setTarget,
|
settingTarget,
|
||||||
setTargetPreviewPos,
|
setTargetPreviewPos,
|
||||||
hits,
|
hits
|
||||||
DispatchHits
|
|
||||||
} = useGameEvent(count);
|
} = useGameEvent(count);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -25,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, setTarget, setTargetPreviewPos, hits, DispatchHits, setLastLeftTile }} />
|
<BorderTiles props={{ count, settingTarget, setTargetPreviewPos, setLastLeftTile }} />
|
||||||
|
|
||||||
{/* Collumn lettes and row numbers */}
|
{/* Collumn lettes and row numbers */}
|
||||||
<Labeling count={count} />
|
<Labeling count={count} />
|
||||||
|
@ -38,6 +37,7 @@ function Gamefield() {
|
||||||
{/* Fog images */}
|
{/* Fog images */}
|
||||||
{/* <FogImages /> */}
|
{/* <FogImages /> */}
|
||||||
{targets}
|
{targets}
|
||||||
|
{/* <span id='dev-debug' style={{gridArea: '1 / 12 / 1 / 15', backgroundColor: 'red', zIndex: 3} as CSSProperties}>Debug</span> */}
|
||||||
</div>
|
</div>
|
||||||
{eventBar}
|
{eventBar}
|
||||||
</div>
|
</div>
|
||||||
|
|
35
leaky-ships/components/GamefieldPointer.tsx
Normal file
35
leaky-ships/components/GamefieldPointer.tsx
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import { faCrosshairs } from '@fortawesome/pro-solid-svg-icons';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { CSSProperties } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { faRadar } from '@fortawesome/pro-thin-svg-icons';
|
||||||
|
|
||||||
|
function GamefieldPointer({ props: {
|
||||||
|
preview,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
show,
|
||||||
|
type,
|
||||||
|
edges,
|
||||||
|
imply
|
||||||
|
} }: {
|
||||||
|
props: {
|
||||||
|
preview: boolean,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
show: boolean,
|
||||||
|
type: string,
|
||||||
|
edges: string[],
|
||||||
|
imply: boolean,
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
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 }
|
||||||
|
return (
|
||||||
|
<div className={classNames('hit-svg', { preview: preview }, 'target', type, { show: show }, ...edges, { imply: imply })} style={style as CSSProperties}>
|
||||||
|
<FontAwesomeIcon icon={!isRadar ? faCrosshairs : faRadar} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GamefieldPointer
|
|
@ -1,7 +1,7 @@
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { CSSProperties, useEffect, useMemo, useState } from 'react'
|
import { CSSProperties, useEffect, useMemo, useState } from 'react'
|
||||||
|
|
||||||
function Homepage() {
|
function Grid() {
|
||||||
|
|
||||||
const floorClient = (number: number) => Math.floor(number / 50)
|
const floorClient = (number: number) => Math.floor(number / 50)
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ function Homepage() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id='tiles' style={{ '--columns': params.columns, '--rows': params.rows, '--bg-color-1': colors[count % colors.length], '--bg-color-2': colors[(count + 1) % colors.length] } as CSSProperties}>
|
<div id='tiles' style={{ '--columns': params.columns, '--rows': params.rows, '--bg-color-1': colors[count % colors.length], '--bg-color-2': colors[(count + 1) % colors.length] } as CSSProperties}>
|
||||||
{Array.from(Array(params.quantity)).map((_tile, index) => createTile(index))}
|
{Array.from(Array(params.quantity), (_tile, index) => createTile(index))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [params, position, active, count])
|
}, [params, position, active, count])
|
||||||
|
@ -84,4 +84,4 @@ function Homepage() {
|
||||||
return createTiles
|
return createTiles
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Homepage
|
export default Grid
|
|
@ -1,7 +1,7 @@
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { CSSProperties, useEffect, useMemo, useState } from 'react'
|
import { CSSProperties, useEffect, useMemo, useState } from 'react'
|
||||||
|
|
||||||
function Homepage2() {
|
function Grid2() {
|
||||||
|
|
||||||
const floorClient = (number: number) => Math.floor(number / 50)
|
const floorClient = (number: number) => Math.floor(number / 50)
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ function Homepage2() {
|
||||||
<div className="center-div">
|
<div className="center-div">
|
||||||
<h1 className={classNames('headline', (!active ? 'active' : 'inactive'))}>{sentences[count % sentences.length]}</h1>
|
<h1 className={classNames('headline', (!active ? 'active' : 'inactive'))}>{sentences[count % sentences.length]}</h1>
|
||||||
</div>
|
</div>
|
||||||
{Array.from(Array(params.quantity)).map((_tile, index) => createTile(index))}
|
{Array.from(Array(params.quantity), (_tile, index) => createTile(index))}
|
||||||
</div >
|
</div >
|
||||||
)
|
)
|
||||||
}, [params, position, active, action, count])
|
}, [params, position, active, action, count])
|
||||||
|
@ -89,4 +89,4 @@ function Homepage2() {
|
||||||
return createTiles
|
return createTiles
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Homepage2
|
export default Grid2
|
|
@ -1,4 +1,4 @@
|
||||||
import { faBurst, faXmark } from '@fortawesome/free-solid-svg-icons';
|
import { faBurst, faXmark } from '@fortawesome/pro-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { CSSProperties } from 'react';
|
import { CSSProperties } from 'react';
|
||||||
import { HitType } from '../interfaces';
|
import { HitType } from '../interfaces';
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { faCrosshairs } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
||||||
import { CSSProperties } from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { TargetType } from '../interfaces';
|
|
||||||
|
|
||||||
function Target({ props: { preview, type, edges, imply }, target: { x, y, show } }: { props: { preview?: boolean, type: string, edges: string[], imply: boolean }, target: TargetType }) {
|
|
||||||
return (
|
|
||||||
<div className={classNames('hit-svg', preview ? 'target-preview' : 'target', type, { show: show }, ...edges, { imply: imply })} style={{ '--x': x, '--y': y } as CSSProperties}>
|
|
||||||
<FontAwesomeIcon icon={faCrosshairs} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Target
|
|
|
@ -1,152 +1,111 @@
|
||||||
import { useCallback, useEffect, useMemo, useReducer, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useReducer, useState } from 'react';
|
||||||
import { hitReducer, initlialLastLeftTile, initlialTarget, initlialTargetPreview, initlialTargetPreviewPos, isHit } from '../helpers';
|
import { hitReducer, initlialLastLeftTile, initlialTarget, initlialTargetPreview, initlialTargetPreviewPos, isHit } from '../helpers';
|
||||||
import { HitType, ItemsType, LastLeftTileType, TargetListType, TargetModifierType, TargetPreviewPosType, TargetPreviewType, TargetType } from '../interfaces';
|
import { HitType, ItemsType, LastLeftTileType, ModeType, TargetPreviewPosType, TargetType } from '../interfaces';
|
||||||
import Item from './Item';
|
import Item from './Item';
|
||||||
import Target from './Target';
|
import GamefieldPointer from './GamefieldPointer';
|
||||||
|
|
||||||
export const modes = {
|
|
||||||
none: { xEnable: true, yEnable: true, type: 'none' },
|
|
||||||
radar: { xEnable: true, yEnable: true, type: 'radar' },
|
|
||||||
hTorpedo: { xEnable: true, yEnable: false, type: 'torpedo' },
|
|
||||||
vTorpedo: { xEnable: false, yEnable: true, type: 'torpedo' },
|
|
||||||
missle: { xEnable: false, yEnable: false, type: 'missle' }
|
|
||||||
}
|
|
||||||
|
|
||||||
function useGameEvent(count: number) {
|
function useGameEvent(count: number) {
|
||||||
const [lastLeftTile, setLastLeftTile] = useState<LastLeftTileType>(initlialLastLeftTile);
|
const [lastLeftTile, setLastLeftTile] = useState<LastLeftTileType>(initlialLastLeftTile);
|
||||||
const [target, setTarget] = useState<TargetType>(initlialTarget);
|
const [target, setTarget] = useState<TargetType>(initlialTarget);
|
||||||
const [eventReady, setEventReady] = useState(false);
|
const [eventReady, setEventReady] = useState(false);
|
||||||
const [appearOK, setAppearOK] = useState(false);
|
const [appearOK, setAppearOK] = useState(false);
|
||||||
const [targetPreview, setTargetPreview] = useState<TargetPreviewType>(initlialTargetPreview);
|
const [targetPreview, setTargetPreview] = useState<TargetType>(initlialTargetPreview);
|
||||||
const [targetPreviewPos, setTargetPreviewPos] = useState<TargetPreviewPosType>(initlialTargetPreviewPos);
|
const [targetPreviewPos, setTargetPreviewPos] = useState<TargetPreviewPosType>(initlialTargetPreviewPos);
|
||||||
const [hits, DispatchHits] = useReducer(hitReducer, [] as HitType[]);
|
const [hits, DispatchHits] = useReducer(hitReducer, [] as HitType[]);
|
||||||
const [mode, setMode] = useState<keyof typeof modes>('none')
|
// const [mode, setMode] = useState<[number, string]>([0, ''])
|
||||||
const [targetList, setTargetList] = useState<TargetListType[]>([])
|
const [mode, setMode] = useState(0)
|
||||||
const [targetPreviewList, setTargetPreviewList] = useState<TargetListType[]>([])
|
|
||||||
|
|
||||||
function modXY<T>(e: TargetType, mod: TargetModifierType) {
|
const modes = useMemo<ModeType[]>(() => [
|
||||||
const { show, ...pos } = e
|
{ pointerGrid: Array.from(Array(3), () => Array.from(Array(3))), type: 'radar' },
|
||||||
const { target, params } = mod
|
{ pointerGrid: Array.from(Array(3), () => Array.from(Array(1))), type: 'htorpedo' },
|
||||||
return {
|
{ pointerGrid: Array.from(Array(1), () => Array.from(Array(3))), type: 'vhtorpedo' },
|
||||||
target: {
|
{ pointerGrid: [[{ x: 0, y: 0 }]], type: 'missle' }
|
||||||
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 settingTarget = useCallback((isGameTile: boolean, x: number, y: number) => {
|
||||||
|
if (!isGameTile || isHit(hits, x, y).length)
|
||||||
const scopeGrid = useMemo(() => {
|
return;
|
||||||
const { xEnable, yEnable } = modes[mode]
|
setTargetPreviewPos(e => ({ ...e, shouldShow: false }))
|
||||||
const matrix: TargetModifierType[][] = []
|
setTarget(t => {
|
||||||
let y = 0
|
if (t.x === x && t.y === y && t.show) {
|
||||||
let x = 0
|
DispatchHits({ type: 'fireMissle', payload: { hit: (x + y) % 2 !== 0, x, y } });
|
||||||
const yLength = (yEnable ? 2 : 0)
|
return { preview: false, show: false, x, y };
|
||||||
const xLength = (xEnable ? 2 : 0)
|
} else {
|
||||||
for (let i = 0; i <= yLength; i++) {
|
return { preview: false, show: true, x, y };
|
||||||
for (let i2 = 0; i2 <= xLength; i2++) {
|
|
||||||
y = i + (yEnable ? -1 : 0);
|
|
||||||
x = i2 + (xEnable ? -1 : 0);
|
|
||||||
|
|
||||||
(matrix[i] ??= [])[i2] = {
|
|
||||||
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
|
|
||||||
}, [mode])
|
|
||||||
|
|
||||||
const Targets = useCallback((targets: TargetListType[], preview?: boolean) => {
|
|
||||||
const { type } = modes[mode]
|
|
||||||
return targets.map(({ target, params }, i) => <Target key={i} props={{ type, preview, ...params }} target={target} />)
|
|
||||||
}, [mode])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
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)
|
|
||||||
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))
|
|
||||||
return e
|
|
||||||
return result
|
|
||||||
})
|
})
|
||||||
}, [scopeGrid, target, count, hits]);
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
const targetList = useCallback((target: TargetType) => {
|
||||||
const result = scopeGrid.map(e => modXY(targetPreview, e))
|
const { pointerGrid, type } = modes[mode]
|
||||||
.filter(({ target: { x, y } }) => {
|
const xLength = pointerGrid.length
|
||||||
const border = [
|
const yLength = pointerGrid[0].length
|
||||||
x < 2,
|
const { x: targetX, y: targetY } = target
|
||||||
x > count + 1,
|
return pointerGrid.map((arr, i) => {
|
||||||
y < 2,
|
return arr.map((_, i2) => {
|
||||||
y > count + 1,
|
const relativeX = -Math.floor(xLength / 2) + i;
|
||||||
].reduce((prev, curr) => prev || curr, false)
|
const relativeY = -Math.floor(yLength / 2) + i2;
|
||||||
return !border
|
const x = targetX + (relativeX ?? 0)
|
||||||
}).map(field => {
|
const y = targetY + (relativeY ?? 0)
|
||||||
const { target, params } = field
|
return {
|
||||||
const { x, y } = target
|
x,
|
||||||
if (isHit(hits, x, y).length || isSet(x, y))
|
y,
|
||||||
return { ...field, params: { ...params, imply: true } }
|
type,
|
||||||
return field
|
edges: [
|
||||||
|
i === 0 ? 'left' : '',
|
||||||
|
i === xLength - 1 ? 'right' : '',
|
||||||
|
i2 === 0 ? 'top' : '',
|
||||||
|
i2 === yLength - 1 ? 'bottom' : '',
|
||||||
|
]
|
||||||
|
}
|
||||||
})
|
})
|
||||||
if (!targetPreviewPos.shouldShow)
|
|
||||||
return
|
|
||||||
setTargetPreviewList(e => {
|
|
||||||
if (JSON.stringify(e) === JSON.stringify(result))
|
|
||||||
return e
|
|
||||||
return result
|
|
||||||
})
|
})
|
||||||
}, [scopeGrid, targetPreview, count, hits, isSet, targetPreviewPos.shouldShow]);
|
.reduce((prev, curr) => [...prev, ...curr], [])
|
||||||
|
}, [mode, modes])
|
||||||
|
|
||||||
|
const isSet = useCallback((x: number, y: number) => !!targetList(target).filter(field => x === field.x && y === field.y).length && target.show, [target, targetList])
|
||||||
|
|
||||||
|
const composeTargetTiles = useCallback((target: TargetType) => {
|
||||||
|
const { preview, show } = target
|
||||||
|
const result = targetList(target).map(({ x, y, type, edges }) => {
|
||||||
|
return {
|
||||||
|
preview,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
show,
|
||||||
|
type,
|
||||||
|
edges,
|
||||||
|
imply: !!isHit(hits, x, y).length || (!!isSet(x, y) && preview),
|
||||||
|
// isborder: x < 2 || x > count + 1 || y < 2 || y > count + 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// .filter(({ isborder }) => !isborder)
|
||||||
|
return result
|
||||||
|
}, [count, 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;
|
||||||
// if mouse has moved too quickly and last event was entering and leaving the same field, it must have gone outside the grid
|
// 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 hasLeft = x === lastLeftTile.x && y === lastLeftTile.y
|
||||||
|
const isSet = x === target.x && y === target.y && target.show
|
||||||
|
|
||||||
if (show && !appearOK)
|
if (show && !appearOK)
|
||||||
setTargetPreview(e => ({ ...e, show: false }));
|
setTargetPreview(e => ({ ...e, show: false }));
|
||||||
if (!show && targetPreviewPos.shouldShow && eventReady && appearOK && !isHit(hits, x, y).length && !hasLeft)
|
if (!show && targetPreviewPos.shouldShow && eventReady && appearOK && !isHit(hits, x, y).length && !isSet && !hasLeft)
|
||||||
setTargetPreview(e => ({ ...e, show: true }));
|
setTargetPreview(e => ({ ...e, show: true }));
|
||||||
}, [targetPreview, targetPreviewPos.shouldShow, hits, eventReady, appearOK, lastLeftTile])
|
}, [targetPreview, targetPreviewPos.shouldShow, hits, eventReady, appearOK, lastLeftTile, target])
|
||||||
|
|
||||||
// enable targetPreview event again after 200 mil. sec.
|
// enable targetPreview event again after 200 mil. sec.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { x: newX, y: newY } = targetPreviewPos;
|
|
||||||
setEventReady(false);
|
setEventReady(false);
|
||||||
if (targetPreview.show || !appearOK)
|
if (targetPreview.show || !appearOK)
|
||||||
return;
|
return;
|
||||||
const autoTimeout = setTimeout(() => {
|
const autoTimeout = setTimeout(() => {
|
||||||
setTargetPreview(e => ({ ...e, x: newX, y: newY }));
|
setTargetPreview(e => ({ ...e, x: targetPreviewPos.x, y: targetPreviewPos.y }));
|
||||||
setEventReady(true);
|
setEventReady(true);
|
||||||
setAppearOK(true);
|
setAppearOK(true);
|
||||||
}, 300);
|
}, 300);
|
||||||
|
@ -155,14 +114,14 @@ function useGameEvent(count: number) {
|
||||||
return () => {
|
return () => {
|
||||||
clearTimeout(autoTimeout);
|
clearTimeout(autoTimeout);
|
||||||
}
|
}
|
||||||
}, [targetPreviewPos, targetPreview.show, appearOK]);
|
}, [appearOK, targetPreview.show, targetPreviewPos.x, targetPreviewPos.y]);
|
||||||
|
|
||||||
// approve targetPreview new position after 200 mil. sec.
|
// approve targetPreview new position after 200 mil. sec.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// early return to start cooldown only when about to show up
|
// early return to start cooldown only when about to show up
|
||||||
const autoTimeout = setTimeout(() => {
|
const autoTimeout = setTimeout(() => {
|
||||||
setAppearOK(!targetPreview.show)
|
setAppearOK(!targetPreview.show)
|
||||||
}, 500);
|
}, targetPreview.show ? 500 : 300);
|
||||||
|
|
||||||
// or abort if movement is repeated early
|
// or abort if movement is repeated early
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -170,23 +129,23 @@ function useGameEvent(count: number) {
|
||||||
}
|
}
|
||||||
}, [targetPreview.show]);
|
}, [targetPreview.show]);
|
||||||
|
|
||||||
const targets = useMemo(() => <>
|
const targets = useMemo(() => [
|
||||||
{Targets(targetPreviewList, true)}
|
...composeTargetTiles(target).map((props, i) => <GamefieldPointer key={'t' + i} props={props} />),
|
||||||
{Targets(targetList)}
|
...composeTargetTiles(targetPreview).map((props, i) => <GamefieldPointer key={'p' + i} props={props} />)
|
||||||
</>, [Targets, targetList, targetPreviewList])
|
], [composeTargetTiles, target, targetPreview])
|
||||||
|
|
||||||
const eventBar = useMemo(() => {
|
const eventBar = useMemo(() => {
|
||||||
const items: ItemsType[] = [
|
const items: ItemsType[] = [
|
||||||
{ icon: 'burger-menu', text: 'Menu' },
|
{ icon: 'burger-menu', text: 'Menu' },
|
||||||
{ icon: 'radar', text: 'Radar scan', type: 'radar', amount: 1 },
|
{ icon: 'radar', text: 'Radar scan', mode: 0, amount: 1 },
|
||||||
{ icon: 'missle', text: 'Fire torpedo', type: 'hTorpedo', amount: 1 },
|
{ icon: 'missle', text: 'Fire torpedo', mode: 1, amount: 1 },
|
||||||
{ icon: 'scope', text: 'Fire missle', type: 'missle' },
|
{ icon: 'scope', text: 'Fire missle', mode: 2 },
|
||||||
{ icon: 'gear', text: 'Settings' }
|
{ icon: 'gear', text: 'Settings' }
|
||||||
]
|
]
|
||||||
return (
|
return (
|
||||||
<div className='event-bar'>
|
<div className='event-bar'>
|
||||||
{items.map((e, i) => (
|
{items.map((e, i) => (
|
||||||
<Item key={i} props={{ ...e, callback: () => { setMode(e.type as any); setTarget(e => ({ ...e, show: false })) } }} />
|
<Item key={i} props={{ ...e, callback: () => { e.mode !== undefined ? setMode(e.mode) : {}; setTarget(e => ({ ...e, show: false })) } }} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -195,10 +154,9 @@ function useGameEvent(count: number) {
|
||||||
targets,
|
targets,
|
||||||
eventBar,
|
eventBar,
|
||||||
setLastLeftTile,
|
setLastLeftTile,
|
||||||
setTarget,
|
settingTarget,
|
||||||
setTargetPreviewPos,
|
setTargetPreviewPos,
|
||||||
hits,
|
hits
|
||||||
DispatchHits
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,11 +40,13 @@ export const initlialLastLeftTile = {
|
||||||
y: 0
|
y: 0
|
||||||
};
|
};
|
||||||
export const initlialTarget = {
|
export const initlialTarget = {
|
||||||
|
preview: false,
|
||||||
show: false,
|
show: false,
|
||||||
x: 2,
|
x: 2,
|
||||||
y: 2
|
y: 2
|
||||||
};
|
};
|
||||||
export const initlialTargetPreview = {
|
export const initlialTargetPreview = {
|
||||||
|
preview: true,
|
||||||
show: false,
|
show: false,
|
||||||
x: 2,
|
x: 2,
|
||||||
y: 2
|
y: 2
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
import { modes } from "./components/useGameEvent";
|
|
||||||
|
|
||||||
export type LastLeftTileType = {
|
export type LastLeftTileType = {
|
||||||
x: number,
|
x: number,
|
||||||
y: number
|
y: number
|
||||||
}
|
}
|
||||||
export type TargetType = {
|
export type TargetType = {
|
||||||
show: boolean,
|
preview: boolean,
|
||||||
x: number,
|
|
||||||
y: number
|
|
||||||
};
|
|
||||||
export type TargetPreviewType = {
|
|
||||||
show: boolean,
|
show: boolean,
|
||||||
x: number,
|
x: number,
|
||||||
y: number
|
y: number
|
||||||
|
@ -20,30 +14,19 @@ export type TargetPreviewPosType = {
|
||||||
y: number
|
y: number
|
||||||
}
|
}
|
||||||
export type TargetListType = {
|
export type TargetListType = {
|
||||||
target: {
|
x: number,
|
||||||
show: boolean,
|
y: number,
|
||||||
x: number,
|
type: string,
|
||||||
y: number,
|
edges: string[]
|
||||||
},
|
|
||||||
params: {
|
|
||||||
edges: string[],
|
|
||||||
imply: boolean
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
export type TargetModifierType = {
|
export type ModeType = {
|
||||||
target: {
|
pointerGrid: any[][],
|
||||||
x: number,
|
type: string
|
||||||
y: number,
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
edges: string[],
|
|
||||||
imply: boolean
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
export type ItemsType = {
|
export type ItemsType = {
|
||||||
icon: string,
|
icon: string,
|
||||||
text: string,
|
text: string,
|
||||||
type?: keyof typeof modes,
|
mode?: number,
|
||||||
amount?: number,
|
amount?: number,
|
||||||
}
|
}
|
||||||
export type FieldType = {
|
export type FieldType = {
|
||||||
|
|
108
leaky-ships/package-lock.json
generated
108
leaky-ships/package-lock.json
generated
|
@ -9,9 +9,13 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.2.1",
|
"@fortawesome/pro-duotone-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
"@fortawesome/pro-light-svg-icons": "^6.2.1",
|
||||||
|
"@fortawesome/pro-regular-svg-icons": "^6.2.1",
|
||||||
|
"@fortawesome/pro-solid-svg-icons": "^6.2.1",
|
||||||
|
"@fortawesome/pro-thin-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
|
"@fortawesome/sharp-solid-svg-icons": "^6.2.1",
|
||||||
"@next/font": "13.1.1",
|
"@next/font": "13.1.1",
|
||||||
"@types/node": "18.11.18",
|
"@types/node": "18.11.18",
|
||||||
"@types/react": "18.0.26",
|
"@types/react": "18.0.26",
|
||||||
|
@ -94,10 +98,10 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@fortawesome/free-regular-svg-icons": {
|
"node_modules/@fortawesome/pro-duotone-svg-icons": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://npm.fontawesome.com/@fortawesome/free-regular-svg-icons/-/6.2.1/free-regular-svg-icons-6.2.1.tgz",
|
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-duotone-svg-icons/-/6.2.1/pro-duotone-svg-icons-6.2.1.tgz",
|
||||||
"integrity": "sha512-wiqcNDNom75x+pe88FclpKz7aOSqS2lOivZeicMV5KRwOAeypxEYWAK/0v+7r+LrEY30+qzh8r2XDaEHvoLsMA==",
|
"integrity": "sha512-8kG2rcHxGdb8yGb2KLZN7Ht014Nf4lefvXP+pihJAE9Jy515g/xPwglkFMu3Ue6MBtcdrLPIYirV8664ubAVgA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-common-types": "6.2.1"
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
},
|
},
|
||||||
|
@ -105,10 +109,43 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@fortawesome/free-solid-svg-icons": {
|
"node_modules/@fortawesome/pro-light-svg-icons": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://npm.fontawesome.com/@fortawesome/free-solid-svg-icons/-/6.2.1/free-solid-svg-icons-6.2.1.tgz",
|
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-light-svg-icons/-/6.2.1/pro-light-svg-icons-6.2.1.tgz",
|
||||||
"integrity": "sha512-oKuqrP5jbfEPJWTij4sM+/RvgX+RMFwx3QZCZcK9PrBDgxC35zuc7AOFsyMjMd/PIFPeB2JxyqDr5zs/DZFPPw==",
|
"integrity": "sha512-QTs61d6jAnYhjXuaRUTexv+KQuxzkwG5jjOGBQOGOnOoGZgho6AEU/a5r2Awgv5o+It50C/LduPnboA31P1NUQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/pro-regular-svg-icons": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-regular-svg-icons/-/6.2.1/pro-regular-svg-icons-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-U3JCqJjwkNSrxgDafsBBUQBbOlvTsa4Odtn7m01NDko45pZu2nh3eqCexovy4y6LzWXXP/Spq+AO29CBpCW8yA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/pro-solid-svg-icons": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-solid-svg-icons/-/6.2.1/pro-solid-svg-icons-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-gIGrv/hcw5/UsW0swBfxL9jwb2F+Yut+9QY47ZPs8+Ac9/AmYxIzJ31ZnYawwLdrxU/09Unc+AHbTfn0QXLfvQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/pro-thin-svg-icons": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-thin-svg-icons/-/6.2.1/pro-thin-svg-icons-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-X+lubysMJrNf/Qw9lDt7BkD9An0pwOEzOMMTaY2dEKN901SJENJ/Y5Ne23CCWSZwAHydoz5EN4JCMVJS+wEkvQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-common-types": "6.2.1"
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
},
|
},
|
||||||
|
@ -128,6 +165,17 @@
|
||||||
"react": ">=16.3"
|
"react": ">=16.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@fortawesome/sharp-solid-svg-icons": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://npm.fontawesome.com/@fortawesome/sharp-solid-svg-icons/-/6.2.1/sharp-solid-svg-icons-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-fK/gm8TDlMEWo1x7KuQD1ZfD98PF28wtmQHs8AgdQk0GS0QV0wBfxOWEmG+BM857Obras9xjSj7p7DwhfRWCZA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.11.8",
|
"version": "0.11.8",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
||||||
|
@ -3515,18 +3563,42 @@
|
||||||
"@fortawesome/fontawesome-common-types": "6.2.1"
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@fortawesome/free-regular-svg-icons": {
|
"@fortawesome/pro-duotone-svg-icons": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://npm.fontawesome.com/@fortawesome/free-regular-svg-icons/-/6.2.1/free-regular-svg-icons-6.2.1.tgz",
|
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-duotone-svg-icons/-/6.2.1/pro-duotone-svg-icons-6.2.1.tgz",
|
||||||
"integrity": "sha512-wiqcNDNom75x+pe88FclpKz7aOSqS2lOivZeicMV5KRwOAeypxEYWAK/0v+7r+LrEY30+qzh8r2XDaEHvoLsMA==",
|
"integrity": "sha512-8kG2rcHxGdb8yGb2KLZN7Ht014Nf4lefvXP+pihJAE9Jy515g/xPwglkFMu3Ue6MBtcdrLPIYirV8664ubAVgA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@fortawesome/fontawesome-common-types": "6.2.1"
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@fortawesome/free-solid-svg-icons": {
|
"@fortawesome/pro-light-svg-icons": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://npm.fontawesome.com/@fortawesome/free-solid-svg-icons/-/6.2.1/free-solid-svg-icons-6.2.1.tgz",
|
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-light-svg-icons/-/6.2.1/pro-light-svg-icons-6.2.1.tgz",
|
||||||
"integrity": "sha512-oKuqrP5jbfEPJWTij4sM+/RvgX+RMFwx3QZCZcK9PrBDgxC35zuc7AOFsyMjMd/PIFPeB2JxyqDr5zs/DZFPPw==",
|
"integrity": "sha512-QTs61d6jAnYhjXuaRUTexv+KQuxzkwG5jjOGBQOGOnOoGZgho6AEU/a5r2Awgv5o+It50C/LduPnboA31P1NUQ==",
|
||||||
|
"requires": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@fortawesome/pro-regular-svg-icons": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-regular-svg-icons/-/6.2.1/pro-regular-svg-icons-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-U3JCqJjwkNSrxgDafsBBUQBbOlvTsa4Odtn7m01NDko45pZu2nh3eqCexovy4y6LzWXXP/Spq+AO29CBpCW8yA==",
|
||||||
|
"requires": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@fortawesome/pro-solid-svg-icons": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-solid-svg-icons/-/6.2.1/pro-solid-svg-icons-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-gIGrv/hcw5/UsW0swBfxL9jwb2F+Yut+9QY47ZPs8+Ac9/AmYxIzJ31ZnYawwLdrxU/09Unc+AHbTfn0QXLfvQ==",
|
||||||
|
"requires": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@fortawesome/pro-thin-svg-icons": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-thin-svg-icons/-/6.2.1/pro-thin-svg-icons-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-X+lubysMJrNf/Qw9lDt7BkD9An0pwOEzOMMTaY2dEKN901SJENJ/Y5Ne23CCWSZwAHydoz5EN4JCMVJS+wEkvQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@fortawesome/fontawesome-common-types": "6.2.1"
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
}
|
}
|
||||||
|
@ -3539,6 +3611,14 @@
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@fortawesome/sharp-solid-svg-icons": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://npm.fontawesome.com/@fortawesome/sharp-solid-svg-icons/-/6.2.1/sharp-solid-svg-icons-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-fK/gm8TDlMEWo1x7KuQD1ZfD98PF28wtmQHs8AgdQk0GS0QV0wBfxOWEmG+BM857Obras9xjSj7p7DwhfRWCZA==",
|
||||||
|
"requires": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@humanwhocodes/config-array": {
|
"@humanwhocodes/config-array": {
|
||||||
"version": "0.11.8",
|
"version": "0.11.8",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
||||||
|
|
|
@ -10,9 +10,13 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.2.1",
|
"@fortawesome/pro-duotone-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
"@fortawesome/pro-light-svg-icons": "^6.2.1",
|
||||||
|
"@fortawesome/pro-regular-svg-icons": "^6.2.1",
|
||||||
|
"@fortawesome/pro-solid-svg-icons": "^6.2.1",
|
||||||
|
"@fortawesome/pro-thin-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
|
"@fortawesome/sharp-solid-svg-icons": "^6.2.1",
|
||||||
"@next/font": "13.1.1",
|
"@next/font": "13.1.1",
|
||||||
"@types/node": "18.11.18",
|
"@types/node": "18.11.18",
|
||||||
"@types/react": "18.0.26",
|
"@types/react": "18.0.26",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import '../styles/App.scss'
|
import '../styles/App.scss'
|
||||||
import '../styles/home.scss'
|
import '../styles/grid.scss'
|
||||||
import '../styles/home2.scss'
|
import '../styles/grid2.scss'
|
||||||
|
import '../styles/homepage.scss'
|
||||||
import type { AppProps } from 'next/app'
|
import type { AppProps } from 'next/app'
|
||||||
|
|
||||||
export default function App({ Component, pageProps }: AppProps) {
|
export default function App({ Component, pageProps }: AppProps) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import Homepage2 from '../components/Homepage2'
|
import Grid from '../components/Grid'
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
|
@ -13,7 +13,7 @@ export default function Home() {
|
||||||
<main>
|
<main>
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<header className="App-header">
|
<header className="App-header">
|
||||||
<Homepage2 />
|
<Grid />
|
||||||
</header>
|
</header>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
22
leaky-ships/pages/grid2.tsx
Normal file
22
leaky-ships/pages/grid2.tsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import Head from 'next/head'
|
||||||
|
import Grid2 from '../components/Grid2'
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Create Next App</title>
|
||||||
|
<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" />
|
||||||
|
</Head>
|
||||||
|
<main>
|
||||||
|
<div className="App">
|
||||||
|
<header className="App-header">
|
||||||
|
<Grid2 />
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,22 +1,32 @@
|
||||||
import Head from 'next/head'
|
import { faCompass } from '@fortawesome/pro-solid-svg-icons'
|
||||||
import Homepage from '../components/Homepage'
|
import { faCirclePlay } from '@fortawesome/pro-thin-svg-icons'
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
const [heWantsToPlay, setHeWantsToPlay] = useState(false)
|
||||||
<>
|
return (
|
||||||
<Head>
|
<div id='box'>
|
||||||
<title>Create Next App</title>
|
<button id='navExpand'>
|
||||||
<meta name="description" content="Generated by create next app" />
|
<FontAwesomeIcon icon={faCompass} />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
</button>
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<div className='beforeStartBox'>
|
||||||
</Head>
|
<img id='shield' src="/assets/shield.png" alt="Shield Logo" />
|
||||||
<main>
|
{!heWantsToPlay ?
|
||||||
<div className="App">
|
<>
|
||||||
<header className="App-header">
|
<div id='videoWrapper'>
|
||||||
<Homepage />
|
<FontAwesomeIcon icon={faCirclePlay} />
|
||||||
</header>
|
</div>
|
||||||
|
<button id='startButton' onClick={() => setHeWantsToPlay(true)}>START</button>
|
||||||
|
</> :
|
||||||
|
<div id='startBox'>
|
||||||
|
<div>
|
||||||
|
<button className='optionButton'>Raum erstellen</button>
|
||||||
|
<button className='optionButton'>Raum beitreten</button>
|
||||||
|
<button className='optionButton'>Zuschauen</button>
|
||||||
|
</div>
|
||||||
|
</div>}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
)
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
// import styles from '../styles/Home.module.css'
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
|
@ -12,10 +11,11 @@ export default function Home() {
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<main>
|
<main>
|
||||||
<p><Link href='/gamefield'>Gamefield</Link></p>
|
<p><Link href='/gamefield' target='_blank'>Gamefield</Link></p>
|
||||||
<p><Link href='/homepage'>Homepage</Link></p>
|
<p><Link href='/homepage' target='_blank'>Homepage</Link></p>
|
||||||
<p><Link href='/homepage2'>Homepage2</Link></p>
|
<p><Link href='/grid' target='_blank'>Grid Effect</Link></p>
|
||||||
<p><Link href='/socketio'>SocketIO</Link></p>
|
<p><Link href='/grid2' target='_blank'>Grid Effect with Content</Link></p>
|
||||||
|
<p><Link href='/socketio' target='_blank'>SocketIO</Link></p>
|
||||||
</main>
|
</main>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,8 +7,6 @@ body {
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
sans-serif;
|
sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
@ -159,15 +157,45 @@ body {
|
||||||
--color: red;
|
--color: red;
|
||||||
color: var(--color);
|
color: var(--color);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
|
&.preview {
|
||||||
|
--color: orange;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.target-preview {
|
&.preview {
|
||||||
--color: orange;
|
|
||||||
color: var(--color);
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@include transition(.5s);
|
@include transition(.5s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.radar {
|
||||||
|
--color: limegreen;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.left):not(.right):not(.top):not(.bottom) {
|
||||||
|
// border: 5px solid var(--color);
|
||||||
|
grid-area: var(--y1) /var(--x1) /var(--y2) /var(--x2);
|
||||||
|
|
||||||
|
svg {
|
||||||
|
opacity: 1;
|
||||||
|
padding: 12.5%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.imply {
|
||||||
|
box-shadow: 0 0 6px 6px #fff4;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.preview {
|
||||||
|
--color: lawngreen;
|
||||||
|
background-color: #0001;
|
||||||
|
// border: 5px dashed var(--color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.show {
|
&.show {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
@ -192,20 +220,22 @@ body {
|
||||||
border-bottom: 2px solid var(--color);
|
border-bottom: 2px solid var(--color);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.imply.left {
|
&.imply {
|
||||||
border-left: 2px dashed white;
|
&.left {
|
||||||
}
|
border-left: 2px dashed white;
|
||||||
|
}
|
||||||
|
|
||||||
&.imply.right {
|
&.right {
|
||||||
border-right: 2px dashed white;
|
border-right: 2px dashed white;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.imply.top {
|
&.top {
|
||||||
border-top: 2px dashed white;
|
border-top: 2px dashed white;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.imply.bottom {
|
&.bottom {
|
||||||
border-bottom: 2px dashed white;
|
border-bottom: 2px dashed white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.left.top {
|
&.left.top {
|
||||||
|
|
98
leaky-ships/styles/homepage.scss
Normal file
98
leaky-ships/styles/homepage.scss
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#box {
|
||||||
|
border: 2px solid black;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
background-color: #282c34;
|
||||||
|
|
||||||
|
#navExpand {
|
||||||
|
position: absolute;
|
||||||
|
top: 64px;
|
||||||
|
left: 64px;
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
background-color: black;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
height: 50%;
|
||||||
|
width: 50%;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.beforeStartBox {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
#shield {
|
||||||
|
width: 450px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#videoWrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 225px;
|
||||||
|
width: 525px;
|
||||||
|
background-color: #2227;
|
||||||
|
border: 2px solid black;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
font-size: 4em;
|
||||||
|
color: #231f20;
|
||||||
|
|
||||||
|
path {
|
||||||
|
stroke: black;
|
||||||
|
stroke-width: 2px;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#startButton {
|
||||||
|
font-size: 2.5em;
|
||||||
|
color: white;
|
||||||
|
background-color: black;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 2rem 6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#startBox {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #B1B2B5CC;
|
||||||
|
border: 3px solid black;
|
||||||
|
padding: 3rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
min-width: 60vw;
|
||||||
|
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
.optionButton {
|
||||||
|
font-size: 2em;
|
||||||
|
color: #B1B2B5CC;
|
||||||
|
background-color: #000C;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1rem 4rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,37 +18,37 @@
|
||||||
}
|
}
|
||||||
@mixin gradient-edge {
|
@mixin gradient-edge {
|
||||||
&.left-top-corner {
|
&.left-top-corner {
|
||||||
-webkit-mask-image: -webkit-gradient(linear, right bottom,
|
mask-image: -webkit-gradient(linear, right bottom, left top, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0)));
|
||||||
left top, color-stop(0, rgba(0,0,0,1)), color-stop(0.5, rgba(0,0,0,0)));
|
-webkit-mask-image: -webkit-gradient(linear, right bottom, left top, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0)));
|
||||||
}
|
}
|
||||||
&.right-top-corner {
|
&.right-top-corner {
|
||||||
-webkit-mask-image: -webkit-gradient(linear, left bottom,
|
mask-image: -webkit-gradient(linear, left bottom, right top, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0)));
|
||||||
right top, color-stop(0, rgba(0,0,0,1)), color-stop(0.5, rgba(0,0,0,0)));
|
-webkit-mask-image: -webkit-gradient(linear, left bottom, right top, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0)));
|
||||||
}
|
}
|
||||||
&.left-bottom-corner {
|
&.left-bottom-corner {
|
||||||
-webkit-mask-image: -webkit-gradient(linear, right top,
|
mask-image: -webkit-gradient(linear, right top, left bottom, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0)));
|
||||||
left bottom, color-stop(0, rgba(0,0,0,1)), color-stop(0.5, rgba(0,0,0,0)));
|
-webkit-mask-image: -webkit-gradient(linear, right top, left bottom, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0)));
|
||||||
}
|
}
|
||||||
&.right-bottom-corner {
|
&.right-bottom-corner {
|
||||||
-webkit-mask-image: -webkit-gradient(linear, left top,
|
mask-image: -webkit-gradient(linear, left top, right bottom, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0)));
|
||||||
right bottom, color-stop(0, rgba(0,0,0,1)), color-stop(0.5, rgba(0,0,0,0)));
|
-webkit-mask-image: -webkit-gradient(linear, left top, right bottom, color-stop(0, rgba(0, 0, 0, 1)), color-stop(0.5, rgba(0, 0, 0, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
&.left {
|
&.left {
|
||||||
-webkit-mask-image: -webkit-gradient(linear, right top,
|
mask-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0)));
|
||||||
left top, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));
|
-webkit-mask-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0)));
|
||||||
}
|
}
|
||||||
&.right {
|
&.right {
|
||||||
-webkit-mask-image: -webkit-gradient(linear, left top,
|
mask-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0)));
|
||||||
right top, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));
|
-webkit-mask-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0)));
|
||||||
}
|
}
|
||||||
&.top {
|
&.top {
|
||||||
-webkit-mask-image: -webkit-gradient(linear, left bottom,
|
mask-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0)));
|
||||||
left top, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));
|
-webkit-mask-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0)));
|
||||||
}
|
}
|
||||||
&.bottom {
|
&.bottom {
|
||||||
-webkit-mask-image: -webkit-gradient(linear, left top,
|
mask-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0)));
|
||||||
left bottom, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));
|
-webkit-mask-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue