dao-game / commit
Multiplayer mostly working.
public/index.html | 24 ++++++--- public/online.html | 2 +- public/styles.css | 102 +-------------------------------------- readme.md | 4 +- src/local-game.ts | 16 +++--- src/remote-game.ts | 22 +++++++-- tools/esbuild-build-and-serve.ts | 65 +++++++++++++------------ 7 files changed, 81 insertions(+), 154 deletions(-) diff --git a/public/index.html b/public/index.html index dc8de5a..14baf73 100644 --- a/public/index.html +++ b/public/index.html @@ -11,11 +11,14 @@ </head> <body> - <div class="invisible"> + <div id="placeholders" class="invisible"> <p class="piece p1-piece" id="default-p1-piece"></p> <p class="piece p2-piece" id="default-p2-piece"></p> + <div id="other-mouse"> + <img src="./cursor.png" alt="cursor" /> + </div> </div> - <main> + <main class="invisible"> <div class="controls"> <span class="p1-turn-text"> Red's turn </span> <span class="divider">|</span> @@ -34,6 +37,7 @@ </button> </div> </main> + <hr /> <div class="title"> @@ -47,7 +51,8 @@ The game consists of only one simple rule and three ways to win. Pieces move in a straight line, including diagonally, as far as possible with no jumps. The three ways to win are arranging your - pieces in a straight line on the board (not diagonally), occupying + pieces in a straight line on the board (not diagonally), + occupying the four corners, or forming a 2x2 square anywhere on the board. </div> <hr /> @@ -55,15 +60,18 @@ <div class="info"> <p> Here is the - <a href="https://gitlab.com/fuzzy-rp/dao-game" target="_blank" + <a href="https://gitlab.com/fuzzy-rp/dao-game" + target="_blank" rel="noopener">source code</a> </p> </div> - <div id="other-mouse"> - <img src="./cursor.png" alt="cursor" /> - </div> - + <script type="module"> + const bundle = import('./bundle.js'); + debugger; + console.log('Hi!'); + bundle.play(); + </script> </body> </html> \ No newline at end of file diff --git a/public/online.html b/public/online.html index 5c4d114..ad554d7 100644 --- a/public/online.html +++ b/public/online.html @@ -12,7 +12,7 @@ <script defer src="bundle.js"></script> </head> - <body style="display: none;"> + <body> <div class="invisible"> <p class="piece p1-piece" id="default-p1-piece"></p> <p class="piece p2-piece" id="default-p2-piece"></p> diff --git a/public/styles.css b/public/styles.css index 6f9a281..12f0275 100644 --- a/public/styles.css +++ b/public/styles.css @@ -11,7 +11,7 @@ } main { - display: flex; + /* display: flex; */ flex-direction: column; justify-content: space-between; align-items: center; @@ -27,19 +27,16 @@ body { div { display: flex; justify-content: space-between; - /* display: inline; - flex: 1; */ } #other-mouse { position: absolute; - /* top: -16px; - left: -32px; */ z-index: 1000; pointer-events: none; } .invisible { + /* visibility: hidden; */ display: none; } @@ -78,7 +75,6 @@ td { text-align: center; color: lightgray; background-color: white; - /* border: 1px solid black; */ border-radius: 10px; padding: 10px; -ms-user-select: none; @@ -204,9 +200,6 @@ td { } } -/* .pulsing { - animation: pulsingSize 1.5s infinite; -} */ @keyframes activePulsing { from { width: var(--active-size); @@ -221,94 +214,3 @@ td { height: var(--active-size); } } - -/* breaks */ - -/* @media screen and (max-width: 560px) { - .red-piece { - height: 4.5vw; - width: 4.5vw; - } - - .black-piece { - height: 4.5vw; - width: 4.5vw; - } - - td { - width: 12vw; - height: 12vw; - } - - .red-turn-text { - font-size: 40px; - } - - .black-turn-text { - font-size: 40px; - } - - table { - margin: 0; - } - - .mobile { - display: block; - } - - .desktop { - display: none; - } - - .red-turn-text { - -webkit-transform:rotate(-180deg); - -moz-transform:rotate(-180deg); - -o-transform:rotate(-180deg); - transform:rotate(-180deg); - filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2); - } -} - -@media screen and (max-width: 380px) { - .red-piece { - height: 3vw; - width: 3vw; - } - - .black-piece { - height: 3vw; - width: 3vw; - } -} - -@media screen and (max-width: 345px) { - .red-piece { - height: 2.5vw; - width: 2.5vw; - } - - .black-piece { - height: 2.5vw; - width: 2.5vw; - } -} - -@media screen and (max-width: 300px) { - .red-piece { - height: 1.5vw; - width: 1.5vw; - } - - .black-piece { - height: 1.5vw; - width: 1.5vw; - } - - .red-turn-text { - font-size: 35px; - } - - .black-turn-text { - font-size: 35px; - } -} */ diff --git a/readme.md b/readme.md index 46f2a15..1646fb8 100644 --- a/readme.md +++ b/readme.md @@ -20,4 +20,6 @@ This project is using [esbuild](https://esbuild.github.io/getting-started/#build ## Todos 1. Online multiplayer -2. There's a bug where opening a new tab results in the same session data, look into this and figure out why and how to prevent this +2. Figure out way to have different pages access different JS +3. There's a bug where opening a new tab results in the same session data, look into this and figure out why and how to prevent this +4. Publish versions of all branches diff --git a/src/local-game.ts b/src/local-game.ts index cfee804..396921d 100644 --- a/src/local-game.ts +++ b/src/local-game.ts @@ -14,15 +14,15 @@ export class LocalGame extends Game { listenerManager: ListenerManager = new ListenerManager(); // DOM references - private readonly dom = { + readonly dom = { defaultP1Piece: document.getElementById('default-p1-piece'), defaultP2Piece: document.getElementById('default-p2-piece'), resetButton: document.getElementById('reset-button') as HTMLInputElement, undoButton: document.getElementById('undo-button') as HTMLInputElement, cells: () => Array.from(document.querySelectorAll('td')), allPieces: () => Array.from(document.querySelectorAll('.piece')), - p1TurnText: () => Array.from(document.querySelectorAll('.p1-turn-text')), - p2TurnText: () => Array.from(document.querySelectorAll('.p2-turn-text')), + p1TurnText: () => Array.from(document.querySelectorAll('.p1-turn-text'))[0], + p2TurnText: () => Array.from(document.querySelectorAll('.p2-turn-text'))[0], }; private getPiecesAndCoords(playerId: string) { @@ -110,14 +110,14 @@ export class LocalGame extends Game { const { dom, currentPlayerId, player1Id, canUndoMove, moveHistory, listenerManager, selectedPiece } = this; // reset text - dom.p1TurnText().forEach((t) => t.classList.remove(classNames.selectedPlayerText)); - dom.p2TurnText().forEach((t) => t.classList.remove(classNames.selectedPlayerText)); + dom.p1TurnText().classList.remove(classNames.selectedPlayerText); + dom.p2TurnText().classList.remove(classNames.selectedPlayerText); const isP1Turn = currentPlayerId === player1Id; if (isP1Turn) { - dom.p1TurnText().forEach((t) => t.classList.add(classNames.selectedPlayerText)); + dom.p1TurnText().classList.add(classNames.selectedPlayerText); } else { - dom.p2TurnText().forEach((t) => t.classList.add(classNames.selectedPlayerText)); + dom.p2TurnText().classList.add(classNames.selectedPlayerText); } dom.undoButton.disabled = canUndoMove; @@ -231,7 +231,7 @@ export class LocalGame extends Game { // start! export const playGame = () => { - const lg = new LocalGame('Red', 'Blue', 'Red'); + const lg = new LocalGame('Red', 'Blue'); lg.resetUi(); lg.setActiveUi(); }; diff --git a/src/remote-game.ts b/src/remote-game.ts index 2923ead..5f43230 100644 --- a/src/remote-game.ts +++ b/src/remote-game.ts @@ -16,6 +16,7 @@ interface PeerData { mousePos?: Pos; move?: Move; } +const peerOptions: PeerJSOption = { debug: 4 }; const { getter: getData, setter: setData } = useSessionStorage<LocalData>('dao-game', { id: undefined, peerId: undefined }); const otherMouseElement = document.getElementById('other-mouse'); const openInNewTab = (url: string) => { @@ -52,9 +53,16 @@ export class PeerGame extends LocalGame { super(player1Id, player2Id); this.selfId = selfId; this.conn = conn; + + const { dom } = this; + const isLocalP1 = player1Id === selfId; + (dom.p1TurnText() as HTMLSpanElement).innerText = isLocalP1 ? `Local turn` : `Remote turn`; + (dom.p2TurnText() as HTMLSpanElement).innerText = isLocalP1 ? `Remote turn` : `Local turn`; } public override setActiveUi(): void { - const isLocalTurn = this.currentPlayerId === this.selfId; + const { currentPlayerId, selfId } = this; + + const isLocalTurn = currentPlayerId === selfId; if (isLocalTurn) { super.setActiveUi(); } @@ -68,18 +76,24 @@ export class PeerGame extends LocalGame { public static async createPeerGame(): Promise<PeerGame> { let { id, peerId } = getData(); - const main = document.getElementsByTagName('body')[0]; + const main = document.getElementsByTagName('main')[0]; let game: PeerGame = undefined; const handleConn = (conn: Peer.DataConnection) => { + if (game !== undefined) { + conn.close(); + return; + } + id = peer.id; peerId = conn.peer; setData({ id, peerId }); const isLocalP1 = getFirstPlayerId(id, peerId) === id; - const game = isLocalP1 ? new PeerGame(id, peerId, id, conn) : new PeerGame(peerId, id, id, conn); + game = isLocalP1 ? new PeerGame(id, peerId, id, conn) : new PeerGame(peerId, id, id, conn); game.resetUi(); game.setActiveUi(); + main.classList.remove('invisible'); main.addEventListener('mousemove', (ev: MouseEvent) => { const peerData: PeerData = { mousePos: { x: ev.x, y: ev.y } }; @@ -110,7 +124,6 @@ export class PeerGame extends LocalGame { const { host, protocol, pathname, search } = location; const queryParams = new URLSearchParams(search); - const peerOptions: PeerJSOption = { debug: 0 }; const peer = id === undefined ? new Peer(peerOptions) : new Peer(id, peerOptions); window.onunload = () => peer.destroy(); peer.on('connection', (conn) => handleConn(conn)); @@ -133,6 +146,7 @@ export class PeerGame extends LocalGame { }); while (game === undefined) { + console.log('Waiting to connect to peer'); await delay(500); } return game; diff --git a/tools/esbuild-build-and-serve.ts b/tools/esbuild-build-and-serve.ts index 1f39f91..4632dc5 100644 --- a/tools/esbuild-build-and-serve.ts +++ b/tools/esbuild-build-and-serve.ts @@ -5,40 +5,41 @@ import http from 'http'; const hostPort = 3000; const serveOptions: esbuild.ServeOptions = { - servedir: 'public' + servedir: 'public', }; const buildOptions: esbuild.BuildOptions = { - entryPoints: ['src/app.ts'], - bundle: true, - outfile: 'public/bundle.js', - sourcemap: true + entryPoints: ['src/app.ts'], + bundle: true, + outfile: 'public/bundle.js', + sourcemap: true, }; -esbuild.serve(serveOptions, buildOptions) - .then(result => { - const { host, port } = result; - http - .createServer((req, res) => { - const options: http.RequestOptions = { - hostname: host, - port: port, - path: req.url, - method: req.method, - headers: req.headers - }; - const proxyReq = http.request(options, proxyRes => { - if (proxyRes.statusCode === 404) { - res.writeHead(404, { 'Content-Type': 'text/html' }); - res.end('<h1>A custom 404 page</h1>'); - return; - } +esbuild.serve(serveOptions, buildOptions).then((result) => { + const { host, port } = result; + http + .createServer((req, res) => { + const options: http.RequestOptions = { + hostname: host, + port: port, + path: req.url, + method: req.method, + headers: req.headers, + }; + const proxyReq = http.request(options, (proxyRes) => { + if (proxyRes.statusCode === 404) { + res.writeHead(404, { 'Content-Type': 'text/html' }); + res.end('<h1>A custom 404 page</h1>'); + return; + } - res.writeHead(proxyRes.statusCode!, proxyRes.headers); - proxyRes.pipe(res, { end: true }); - }); + res.writeHead(proxyRes.statusCode!, proxyRes.headers); + proxyRes.pipe(res, { end: true }); + }); - req.pipe(proxyReq, { end: true }); - }) - .listen(hostPort, () => { - childProcess.exec(`start http://localhost:${hostPort}/`); - }); - }); \ No newline at end of file + req.pipe(proxyReq, { end: true }); + }) + .listen(hostPort, () => { + const url = `http://localhost:${hostPort}/`; + // childProcess.exec(`start ${url}`); + console.log(`Server serving at ${url}`); + }); +});