Manuel missle fire
This commit is contained in:
parent
2ebaccfb2d
commit
4e8de6d7e0
4 changed files with 50 additions and 59 deletions
|
@ -6,7 +6,7 @@ import FogImages from './components/FogImages';
|
||||||
import HitElems from './components/HitElems';
|
import HitElems from './components/HitElems';
|
||||||
import Labeling from './components/Labeling';
|
import Labeling from './components/Labeling';
|
||||||
import Ships from './components/Ships';
|
import Ships from './components/Ships';
|
||||||
import { hitReducer, initlialTarget, initlialTargetPreview } from './helpers';
|
import { hitReducer, initlialTarget, initlialTargetPreview, isHit } from './helpers';
|
||||||
import { HitType, TargetPreviewType, TargetType } from './interfaces';
|
import { HitType, TargetPreviewType, TargetType } from './interfaces';
|
||||||
import './styles/App.scss';
|
import './styles/App.scss';
|
||||||
|
|
||||||
|
@ -16,26 +16,6 @@ function App() {
|
||||||
const [target, setTarget] = useState<TargetType>(initlialTarget);
|
const [target, setTarget] = useState<TargetType>(initlialTarget);
|
||||||
const [targetPreview, setTargetPreview] = useState<TargetPreviewType>(initlialTargetPreview);
|
const [targetPreview, setTargetPreview] = useState<TargetPreviewType>(initlialTargetPreview);
|
||||||
const [hits, DispatchHits] = useReducer(hitReducer, [] as HitType[]);
|
const [hits, DispatchHits] = useReducer(hitReducer, [] as HitType[]);
|
||||||
const [x, setX] = useState(0);
|
|
||||||
const [y, setY] = useState(0);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (hits.length === count*count)
|
|
||||||
return;
|
|
||||||
if (x === count) {
|
|
||||||
setX(0);
|
|
||||||
setY(y => y+1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const autoTimer = setTimeout(() => {
|
|
||||||
DispatchHits({type: 'fireMissle', payload: {hit: (x+y)%2 !== 0, x: x+2, y: y+2}});
|
|
||||||
setX(x => x+1);
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearTimeout(autoTimer);
|
|
||||||
}
|
|
||||||
}, [x, y, hits.length]);
|
|
||||||
|
|
||||||
// handle visibility and position change of targetPreview
|
// handle visibility and position change of targetPreview
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -47,11 +27,11 @@ function App() {
|
||||||
if (show) {
|
if (show) {
|
||||||
// hide preview to change position when hidden
|
// hide preview to change position when hidden
|
||||||
setTargetPreview(e => ({...e, appearOK: false, eventReady: false, show: false}));
|
setTargetPreview(e => ({...e, appearOK: false, eventReady: false, show: false}));
|
||||||
} else if (shouldShow && appearOK) {
|
} else if (shouldShow && appearOK && !isHit(hits, newX, newY).length) {
|
||||||
// BUT only appear again if it's supposed to (in case the mouse left over the edge) and ()
|
// BUT only appear again if it's supposed to (in case the mouse left over the edge) and ()
|
||||||
setTargetPreview(e => ({...e, appearOK: false, eventReady: false, show: true, x: newX, y: newY}));
|
setTargetPreview(e => ({...e, appearOK: false, eventReady: false, show: true, x: newX, y: newY}));
|
||||||
}
|
}
|
||||||
}, [targetPreview])
|
}, [targetPreview, hits])
|
||||||
|
|
||||||
// enable targetPreview event again after 200 mil. sec.
|
// enable targetPreview event again after 200 mil. sec.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -87,7 +67,7 @@ function App() {
|
||||||
<header className="App-header">
|
<header className="App-header">
|
||||||
<div id="game-frame" style={{'--i': count} as CSSProperties}>
|
<div id="game-frame" style={{'--i': count} as CSSProperties}>
|
||||||
{/* Bordes */}
|
{/* Bordes */}
|
||||||
<BorderTiles count={count} targets={{setTarget, setTargetPreview}} />
|
<BorderTiles count={count} actions={{setTarget, setTargetPreview, hits, DispatchHits}} />
|
||||||
|
|
||||||
{/* Collumn lettes and row numbers */}
|
{/* Collumn lettes and row numbers */}
|
||||||
<Labeling count={count} />
|
<Labeling count={count} />
|
||||||
|
@ -99,10 +79,10 @@ function App() {
|
||||||
|
|
||||||
{/* Fog images */}
|
{/* Fog images */}
|
||||||
{/* <FogImages /> */}
|
{/* <FogImages /> */}
|
||||||
<div className={`hit-svg target ${target.show ? 'show' : ''}`} style={{'--x': target.x+1, '--y': target.y+1} as CSSProperties}>
|
<div className={`hit-svg target ${target.show ? 'show' : ''}`} style={{'--x': target.x, '--y': target.y} as CSSProperties}>
|
||||||
<FontAwesomeIcon icon={faCrosshairs} />
|
<FontAwesomeIcon icon={faCrosshairs} />
|
||||||
</div>
|
</div>
|
||||||
<div className={`hit-svg target-preview ${targetPreview.show && (target.x !== targetPreview.x || target.y !== targetPreview.y) ? 'show' : ''}`} style={{'--x': targetPreview.x+1, '--y': targetPreview.y+1} as CSSProperties}>
|
<div className={`hit-svg target-preview ${targetPreview.show && (target.x !== targetPreview.x || target.y !== targetPreview.y) ? 'show' : ''}`} style={{'--x': targetPreview.x, '--y': targetPreview.y} as CSSProperties}>
|
||||||
<FontAwesomeIcon icon={faCrosshairs} />
|
<FontAwesomeIcon icon={faCrosshairs} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { CSSProperties } from 'react';
|
import { CSSProperties, Dispatch, SetStateAction } from 'react';
|
||||||
import { borderCN, cornerCN, fieldIndex } from '../helpers';
|
import { borderCN, cornerCN, fieldIndex, isHit } from '../helpers';
|
||||||
import { TargetPreviewType, TargetType } from '../interfaces';
|
import { HitDispatchType, HitType, TargetPreviewType, TargetType } from '../interfaces';
|
||||||
|
|
||||||
function BorderTiles({count, targets: {setTarget, setTargetPreview}}: {count: number, targets: {setTarget: React.Dispatch<React.SetStateAction<TargetType>>, setTargetPreview: React.Dispatch<React.SetStateAction<TargetPreviewType>>}}) {
|
function BorderTiles({count, actions: {setTarget, setTargetPreview, hits, DispatchHits}}: {count: number, actions: {setTarget: Dispatch<SetStateAction<TargetType>>, setTargetPreview: Dispatch<SetStateAction<TargetPreviewType>>, hits: HitType[], DispatchHits: Dispatch<HitDispatchType>}}) {
|
||||||
let tilesProperties: {
|
let tilesProperties: {
|
||||||
key: number,
|
key: number,
|
||||||
isGameTile: boolean,
|
isGameTile: boolean,
|
||||||
|
@ -23,7 +23,7 @@ function BorderTiles({count, targets: {setTarget, setTargetPreview}}: {count: nu
|
||||||
if (isGameTile)
|
if (isGameTile)
|
||||||
classNames.push('game-tile');
|
classNames.push('game-tile');
|
||||||
const classNameString = classNames.join(' ')
|
const classNameString = classNames.join(' ')
|
||||||
tilesProperties.push({key, classNameString, isGameTile, x, y})
|
tilesProperties.push({key, classNameString, isGameTile, x: x+1, y: y+1})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return <>
|
return <>
|
||||||
|
@ -31,10 +31,19 @@ function BorderTiles({count, targets: {setTarget, setTargetPreview}}: {count: nu
|
||||||
return <div
|
return <div
|
||||||
key={key}
|
key={key}
|
||||||
className={classNameString}
|
className={classNameString}
|
||||||
style={{'--x': (x + 1), '--y': (y + 1)} as CSSProperties}
|
style={{'--x': x, '--y': y} as CSSProperties}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isGameTile)
|
if (!isGameTile && !isHit(hits, x, y).length)
|
||||||
setTarget({ show: true, x, y });
|
return;
|
||||||
|
setTarget(t => {
|
||||||
|
if (t.x === x && t.y === y) {
|
||||||
|
DispatchHits({type: 'fireMissle', payload: {hit: (x+y)%2 !== 0, x, y}});
|
||||||
|
return { show: false, x, y };
|
||||||
|
} else {
|
||||||
|
return { show: true, x, y };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}}
|
}}
|
||||||
onMouseEnter={() => setTargetPreview(e => ({...e, newX: x, newY: y, shouldShow: isGameTile}))}
|
onMouseEnter={() => setTargetPreview(e => ({...e, newX: x, newY: y, shouldShow: isGameTile}))}
|
||||||
></div>
|
></div>
|
||||||
|
|
|
@ -1,5 +1,28 @@
|
||||||
import { HitType, HitDispatchType } from "./interfaces";
|
import { HitType, HitDispatchType } from "./interfaces";
|
||||||
|
|
||||||
|
export const borderCN = (count: number, x: number, y: number) => {
|
||||||
|
if (x === 0)
|
||||||
|
return 'left';
|
||||||
|
if (y === 0)
|
||||||
|
return 'top';
|
||||||
|
if (x === count+1)
|
||||||
|
return 'right';
|
||||||
|
if (y === count+1)
|
||||||
|
return 'bottom';
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
export const cornerCN = (count: number, x: number, y: number) => {
|
||||||
|
if (x === 0 && y === 0)
|
||||||
|
return 'left-top-corner';
|
||||||
|
if (x === count+1 && y === 0)
|
||||||
|
return 'right-top-corner';
|
||||||
|
if (x === 0 && y === count+1)
|
||||||
|
return 'left-bottom-corner';
|
||||||
|
if (x === count+1 && y === count+1)
|
||||||
|
return 'right-bottom-corner';
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
export const fieldIndex = (count: number, x: number, y: number) => y*(count+2)+x;
|
||||||
export const hitReducer = (formObject: HitType[], action: HitDispatchType) => {
|
export const hitReducer = (formObject: HitType[], action: HitDispatchType) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
|
||||||
|
@ -12,29 +35,6 @@ export const hitReducer = (formObject: HitType[], action: HitDispatchType) => {
|
||||||
return formObject;
|
return formObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const fieldIndex = (count: number, x: number, y: number) => y*(count+2)+x;
|
|
||||||
export const cornerCN = (count: number, x: number, y: number) => {
|
|
||||||
if (x === 0 && y === 0)
|
|
||||||
return 'left-top-corner';
|
|
||||||
if (x === count+1 && y === 0)
|
|
||||||
return 'right-top-corner';
|
|
||||||
if (x === 0 && y === count+1)
|
|
||||||
return 'left-bottom-corner';
|
|
||||||
if (x === count+1 && y === count+1)
|
|
||||||
return 'right-bottom-corner';
|
|
||||||
return '';
|
|
||||||
};
|
|
||||||
export const borderCN = (count: number, x: number, y: number) => {
|
|
||||||
if (x === 0)
|
|
||||||
return 'left';
|
|
||||||
if (y === 0)
|
|
||||||
return 'top';
|
|
||||||
if (x === count+1)
|
|
||||||
return 'right';
|
|
||||||
if (y === count+1)
|
|
||||||
return 'bottom';
|
|
||||||
return '';
|
|
||||||
};
|
|
||||||
export const initlialTarget = {
|
export const initlialTarget = {
|
||||||
show: false,
|
show: false,
|
||||||
x: 0,
|
x: 0,
|
||||||
|
@ -49,4 +49,5 @@ export const initlialTargetPreview = {
|
||||||
show: false,
|
show: false,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0
|
y: 0
|
||||||
};
|
};
|
||||||
|
export const isHit = (hits: HitType[], x: number, y: number) => hits.filter(h => h.x === x && h.y === y);
|
||||||
|
|
|
@ -25,5 +25,6 @@ export interface HitType {
|
||||||
};
|
};
|
||||||
|
|
||||||
interface fireMissle { type: 'fireMissle', payload: { x: number, y: number, hit: boolean } };
|
interface fireMissle { type: 'fireMissle', payload: { x: number, y: number, hit: boolean } };
|
||||||
|
interface removeMissle { type: 'removeMissle', payload: { x: number, y: number, hit: boolean } };
|
||||||
|
|
||||||
export type HitDispatchType = fireMissle;
|
export type HitDispatchType = fireMissle | removeMissle;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue