diff --git a/frontend/public/fog/fog1.png b/frontend/public/fog/fog1.png new file mode 100644 index 0000000..abe37e3 Binary files /dev/null and b/frontend/public/fog/fog1.png differ diff --git a/frontend/public/fog/fog2.png b/frontend/public/fog/fog2.png new file mode 100644 index 0000000..502096b Binary files /dev/null and b/frontend/public/fog/fog2.png differ diff --git a/frontend/public/fog/fog3.png b/frontend/public/fog/fog3.png new file mode 100644 index 0000000..2c8dede Binary files /dev/null and b/frontend/public/fog/fog3.png differ diff --git a/frontend/public/fog/fog4.png b/frontend/public/fog/fog4.png new file mode 100644 index 0000000..5f352b5 Binary files /dev/null and b/frontend/public/fog/fog4.png differ diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 044e9d3..dd3839e 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,60 +1,151 @@ -import { faXmark } from '@fortawesome/free-solid-svg-icons'; +import { faBurst, faCrosshairs, faXmark } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { CSSProperties } from 'react'; -import './App.scss'; +import { CSSProperties, useState } from 'react'; +import './styles/App.scss'; function App() { - let borders: JSX.Element[] = []; + const [target, setTarget] = useState({ + event: false, + x: 0, + y: 0 + }) + const [targetPreview, setTargetPreview] = useState({ + event: false, + x: 0, + y: 0, + style: { + height: 0, + top: 0, + left: 0, + width: 0 + } + }) + + let borderTiles: JSX.Element[] = []; + let shipElems: JSX.Element[] = []; let elems2: { field: string, x: number, y: number, }[] = []; - let elems: { + let hitElems: { field: string, x: number, y: number, }[] = [], count = 12; - for (let x = 0; x < count; x++) { + for (let y = 0; y < count; y++) { elems2.push(...[ - { field: String.fromCharCode(65+x), x: x+2, y: 1 }, - { field: (x+1).toString(), x: 1, y: x+2 }, - { field: String.fromCharCode(65+x), x: x+2, y: count+2 }, - { field: (x+1).toString(), x: count+2, y: x+2 } - ]) - for (let y = 0; y < count; y++) { - elems.push({ field: String.fromCharCode(65+x)+(y), x: x+2, y: y+2 }) + // Up + { field: String.fromCharCode(65+y), x: y+2, y: 1 }, + // Left + { field: (y+1).toString(), x: 1, y: y+2 }, + // Bottom + { field: String.fromCharCode(65+y), x: y+2, y: count+2 }, + // Right + { field: (y+1).toString(), x: count+2, y: y+2 } + ]); + for (let x = 0; x < count; x++) { + hitElems.push({ field: String.fromCharCode(65+x)+(y), x: x+2, y: y+2 }) } } - for (let x = 0; x < count+2; x++) { - for (let y = 0; y < count+2; y++) { - borders.push(
) + const hitSVGs = hitElems.map((obj, i) => +
+ +
); + for (let y = 0; y < count+2; y++) { + for (let x = 0; x < count+2; x++) { + const corner = [ + x === 0 && y === 0 ? 'left-top-corner' : '', + x === count+1 && y === 0 ? 'right-top-corner' : '', + x === 0 && y === count+1 ? 'left-bottom-corner' : '', + x === count+1 && y === count+1 ? 'right-bottom-corner' : '' + ].filter(s => s); + const border = [ + x === 0 ? 'left' : '', + y === 0 ? 'top' : '', + x === count+1 ? 'right' : '', + y === count+1 ? 'bottom' : '' + ].filter(s => s); + const borderType = corner.length ? corner[0] : border[0]; + const action = x > 0 && x < count+1 && y > 0 && y < count+1; + const classNames = [ + 'border-tile', + borderType ? `edge ${borderType}` : '', + action ? 'action' : '' + ].join(' ') + borderTiles.push( +
setTarget({ event: true, x, y }) : () => {}} + onMouseEnter={e => { + const target = e.target as HTMLDivElement + if (action) { + setTargetPreview({ + event: true, + x, + y, + style: { + height: target.offsetHeight, + left: target.offsetLeft, + top: target.offsetTop, + width: target.offsetWidth, + } + }) + } else { + setTargetPreview(e => Object.assign({...e}, { + style: { + height: target.offsetHeight, + left: target.offsetLeft, + top: target.offsetTop, + width: target.offsetWidth, + } + })) + } + }} + onMouseLeave={action ? () => setTargetPreview(e => Object.assign({...e}, {event: false})) : () => {}} + >
) } } + + + for (let i = 1; i <= 6; i++) { + shipElems.push( +
+ {`${i}.svg`}/ +
); + } return (
{[1,2,3,4,5,6,11,12,13,14].map((num, i) => {`${num}.svg`})} + {[1,2,3,4].map((num, i) => {`fog${num}.png`})}
- { borders } - {elems2.map((obj, i) => - {obj.field} - )} - {/*
*/} - {elems.map((obj, i) => -
- -
)} - {[1,2,3,4,5,6].map((num, i) => -
- {`${num}.svg`}/ -
)} - {/*
- {`${3}.svg`} -
*/} - {/*
*/} + {/* Bordes */} + { borderTiles } + + {/* Collumn lettes and row numbers */} + {elems2.map((obj, i) => + {obj.field} + )} + { hitSVGs } + + {/* Ships */} + {/* { shipElems } */} + + {/* Fog images */} + {/* {`fog1.png`} + {`fog1.png`} + {`fog4.png`} */} +
+ +
+
+ +

Edit src/App.tsx and save to reload. diff --git a/frontend/src/styles/App.scss b/frontend/src/styles/App.scss index d039398..b0e1f1b 100644 --- a/frontend/src/styles/App.scss +++ b/frontend/src/styles/App.scss @@ -1,3 +1,7 @@ +@use './mixins/display' as *; +@use './mixins/effects' as *; +@import './mixins/variables'; + .App { text-align: center; } @@ -14,10 +18,9 @@ } .App-header { - background-color: #282c34; + background-color: $theme; min-height: 100vh; - display: flex; - flex-direction: column; + @include flex-col; align-items: center; justify-content: center; font-size: calc(10px + 2vmin); @@ -38,61 +41,81 @@ } #game-frame { - border: 1px solid orange; + // border: 1px solid orange; // position: relative; - height: 900px; - width: 900px; + height: 945px; + width: 945px; display: grid; align-items: center; justify-items: center; - grid-template-rows: .5fr repeat(12, 1fr) .5fr; - grid-template-columns: .5fr repeat(12, 1fr) .5fr; + grid-template-rows: .75fr repeat(12, 1fr) .75fr; + grid-template-columns: .75fr repeat(12, 1fr) .75fr; // grid-gap: 1px solid blue; > .r1 { grid-column: var(--x); grid-row: var(--y); } - > .border { + > .border-tile { box-sizing: border-box; border: 1px solid blue; height: 100%; width: 100%; grid-column: var(--x); grid-row: var(--y); + + &.edge { + border: 1px solid gray; + } + + &.left-top-corner { + -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 { + -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 { + -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 { + -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 { + -webkit-mask-image: -webkit-gradient(linear, right top, + left top, from(rgba(0,0,0,1)), to(rgba(0,0,0,0))); + } + &.right { + -webkit-mask-image: -webkit-gradient(linear, left top, + right top, from(rgba(0,0,0,1)), to(rgba(0,0,0,0))); + } + &.top { + -webkit-mask-image: -webkit-gradient(linear, left bottom, + left top, from(rgba(0,0,0,1)), to(rgba(0,0,0,0))); + } + &.bottom { + -webkit-mask-image: -webkit-gradient(linear, left top, + left bottom, from(rgba(0,0,0,1)), to(rgba(0,0,0,0))); + } } > :not(.border) { box-sizing: border-box; - border: 1px solid red; + // border: 1px solid red; } > span { vertical-align: center; + user-select: none; } -// } -// #game { - // grid-area: 2 / 2 / -2 / -2; - // border: 5px solid orange; - // // position: relative; - // display: grid; - // // grid-gap: 1px solid blue; - - // .missle { - // height: 50px; - // width: 50px; - // position: absolute; - // border: 1px solid red; - // top: calc(50px + 100px * var(--y)); - // left: calc(50px + 100px* var(--x)); - // transform: translateX(-50%) translateY(-50%); - // } - - #test-ship { + .ship { height: 100%; width: 100%; position: relative; - display: flex; - flex-direction: column; + @include flex-col; align-items: center; // justify-content: center; border: 1px solid yellow; @@ -128,8 +151,8 @@ grid-column: 3 / 7; } } - - .svg-r1 { + + .hit-svg { // border: 2px solid blue; // height: 50px; @@ -137,13 +160,13 @@ height: 100%; width: 100%; position: relative; - display: flex; - // flex-direction: column; + @include flex; // align-items: center; // align-self: center; // justify-self: center; grid-column: var(--x); grid-row: var(--y); + pointer-events: none; svg { position: absolute; @@ -152,6 +175,28 @@ box-sizing: border-box; padding: 25%; + + &.fa-burst { + color: red; + } + } + &.target { + color: red; + opacity: 0; + + &.show { + opacity: 1; + } + } + &.target-preview { + color: orange; + opacity: 0; + position: absolute; + @include transition(.2s); + + &.show { + opacity: 1; + } } } .r2 { @@ -160,4 +205,21 @@ .r3 { border: 2px solid yellowgreen; } + + .fog-left { + grid-area: 1 / 1 / -1 / -1; + align-self: flex-start; + width: inherit; + transform: rotate(180deg); + } + .fog-right { + grid-area: 1 / 1 / -1 / -1; + align-self: flex-end; + width: inherit; + } + .fog-middle { + grid-area: 4 / 4 / -4 / -4; + // align-self: flex-end; + width: inherit; + } } \ No newline at end of file