From 7c3eb6ed57c56ee8a80d9342e6b8327372008987 Mon Sep 17 00:00:00 2001 From: Meleeman01 Date: Sat, 18 Jan 2025 21:08:50 -0600 Subject: [PATCH] working on gameflow added turnState logic, basic puzzle solving logic --- index.html | 65 ++++++++++++++++++++++-- server.js | 125 +++++++++++++++++++++++++++++++++++++++-------- thingstotest.txt | 8 ++- 3 files changed, 173 insertions(+), 25 deletions(-) diff --git a/index.html b/index.html index aa52d02..446f50f 100644 --- a/index.html +++ b/index.html @@ -264,7 +264,7 @@ // Start spinning function startSpin(targetIndex) { console.log('targetIndex: ',targetIndex); - let resultingSpeed = wheelSpinSpeedData[targetIndex]; + let resultingSpeed = wheelSpinSpeedData[targetIndex[0]]; console.log('resultingSpeed: ', resultingSpeed); if (spinning) return; rotation = 0 - (.283*6) @@ -276,12 +276,13 @@ console.log(anglePerSegment); let currentRotation = rotation; // Start from the current rotation - spinSpeed = wheelSpinSpeedData[targetIndex]; // Initial speed + spinSpeed = wheelSpinSpeedData[targetIndex[0]]; // Initial speed function animate() { if ( spinSpeed < 0.001) { spinning = false; - console.log(`Landed on: ${wheel[targetIndex]}`); + spinSpeed = 0; + console.log(`Landed on: ${wheel[targetIndex[0]]}`); return; } // console.log('currentRotation: ',currentRotation); @@ -413,6 +414,20 @@ nameDialog.close(); }); } + + function changeSpinGuessState(message) { + if(message.turnState == 'spin') { + document.getElementById("spin-wheel").style.display = "none"; + document.getElementById("guess-letter").style.display = "inline"; + document.getElementById("guess-button").style.display = "inline"; + } + if (message.turnState == 'guess') { + document.getElementById("spin-wheel").style.display = "none"; + document.getElementById("guess-letter").style.display = "inline"; + document.getElementById("guess-button").style.display = "inline"; + } + + } const socket = new WebSocket("ws://localhost:8080"); document.getElementById("create-room").onclick = function () { @@ -495,6 +510,16 @@ document.getElementById("guess-letter").style.display = "none"; document.getElementById("guess-button").style.display = "none"; } + if (message.type === "new_puzzle") { + let result = drawPuzzle(message); + console.log('new_puzzle', message); + console.log(result); + document.getElementById("status").innerText = "New Puzzle!"; + document.getElementById("start-game").style.display = "none"; + document.getElementById("spin-wheel").style.display = "inline"; + document.getElementById("guess-letter").style.display = "none"; + document.getElementById("guess-button").style.display = "none"; + } if (message.type === "spin_result") { console.log('spin result recieved'); @@ -510,9 +535,11 @@ console.log(filterResultsArr[0][0]); //if there is multiple entries where the spin exists pick a random index. if(filterResultsArr.length > 1) { - startSpin(filterResultsArr[Math.floor(Math.random() * filterResultsArr.length)][0]); + console.log('if fra.length > 1',filterResultsArr[0]) + startSpin(filterResultsArr[0][0]); } else{ + console.log('else',filterResultsArr[0]) startSpin(filterResultsArr[0]); } document.getElementById("spin-wheel").style.display = "none"; @@ -527,9 +554,39 @@ if (message.puzzle) { drawPuzzle(message); } + if (message.turnState) { + changeSpinGuessState(message); + } } + if (message.type === "next_turn") { + document.getElementById("spin-wheel").style.display = "none"; + document.getElementById("guess-letter").style.display = "none"; + document.getElementById("guess-button").style.display = "none"; + if (window.you == message.user) { + //send message since + socket.send(JSON.stringify({ type: "confirm_id"})); + } + } + if (message.type === "next_turn_confirmed") { + //this means its your turn + console.log('its your turn, id confirmed'); + document.getElementById("spin-wheel").style.display = "inline"; + document.getElementById("guess-letter").style.display = "none"; + document.getElementById("guess-button").style.display = "none"; + } + if (message.type === "next_turn_denied") { + //silently deny the user the next turn if trying to assume the same name as another user + console.log('its not your turn yet!'); + document.getElementById("spin-wheel").style.display = "none"; + document.getElementById("guess-letter").style.display = "none"; + document.getElementById("guess-button").style.display = "none"; + } + if (message.type === "puzzle_solved") { + console.log('puzzle has been solved!!!'); + } + if (message.type === "new_leader") { drawPlayers(message); document.getElementById("status").innerText = "You are now the party leader!"; diff --git a/server.js b/server.js index cd64218..22c7d22 100644 --- a/server.js +++ b/server.js @@ -6,11 +6,12 @@ const crypto = require('crypto') const wss = new WebSocket.Server({ port: 8080 }) const rooms = {} // Stores rooms and their clients -const wheel = [ - 'lose a turn',800,350,450,700,300,600,5000, - 300,600,300,500,800,550,400,300,900,500,'spin again', - 900,'Bankrupt',600,400,300 -] //represents wheel in wheel of fortune game. +// const wheel = [ +// 'lose a turn',800,350,450,700,300,600,5000, +// 300,600,300,500,800,550,400,300,900,500,'spin again', +// 900,'Bankrupt',600,400,300 +// ] //represents wheel in wheel of fortune game. +const wheel = ['spin again','Bankrupt','lose a turn'] function removeProp(obj, prop) { obj = JSON.parse(JSON.stringify(obj)) if(!Array.isArray(prop)){ @@ -146,8 +147,12 @@ function checkGuess(letter,gameStateObject) { console.log(currentPuzzle) if (typeof currentPuzzle.answer == 'string') { + //check if user already guessed one of teh given letters + if (currentPuzzle.puzzle.find((x)=> x.toUpperCase() == letter.toUpperCase())) { + console.log('user gave a guess on a given letter...') + return false + } //first create an indexed hashMap - let charArray = currentPuzzle.answer.split('') let matches = [] for(const c in charArray) { @@ -156,6 +161,7 @@ function checkGuess(letter,gameStateObject) { matches.push({id:c,letter:char}) } } + //if there are any matches write them to the gameState Object if (!matches.length) { return false @@ -164,6 +170,12 @@ function checkGuess(letter,gameStateObject) { for(const m of matches) { gameStateObject.puzzles[gameStateObject.puzzleLevel].puzzle[m.id] = m.letter } + //make sure to check if a win occurred + // convert the answer string into an array of characters + let checkAnswer = currentPuzzle.answer.split('') + if (currentPuzzle.puzzle.every((val,i)=> val.toUpperCase() === checkAnswer[i].toUpperCase())) { + return 'puzzleSolved' + } console.log('matches found!!!', gameStateObject.puzzles[gameStateObject.puzzleLevel].puzzle) return [true, matches.length] } @@ -174,7 +186,56 @@ function checkGuess(letter,gameStateObject) { else console.error('invalid input to checkGuess() function',currentPuzzle.puzzle[0]) } +//these functions must have both gameStateobject and websockets initialized before use!!! +function rewardUser(gameStateObject,ws) { + const roomCode = ws.roomCode + const room = rooms[ws.roomCode] + //find the current player + let currentUserTurn = gameStateObject.players[gameStateObject.turn] + currentUserTurn.win++ + gameStateObject.puzzleLevel++ + + room.clients.forEach((client) => { + client.send(JSON.stringify({ + type: 'puzzle_solved', roomCode, + user: currentUserTurn.name + })) + }) +} +function changeTurn(gameStateObject,ws) { + const room = rooms[ws.roomCode] + if (gameStateObject.turn == gameStateObject.players.length - 1) { + gameStateObject.turn = 0 + } + else gameStateObject.turn++ + + //alert next user of their turn + room.clients.forEach((client) => { + client.send(JSON.stringify( + { type: 'next_turn', + user:room.gameState.players[room.gameState.turn].name, + })) + }) +} +function loadNewPuzzle(gameStateObject,ws) { + const room = rooms[ws.roomCode] + const newPuzzle = loadCurrentPuzzle(gameStateObject) + room.gameState.turnState = 'spin' + room.gameState.puzzles[room.gameState.puzzleLevel] = newPuzzle + room.gameState.levelsRemaining = (room.gameState.puzzles.length - 1 - room.gameState.puzzleLevel) + + room.clients.forEach((client) => { + client.send(JSON.stringify({ + type: 'new_puzzle', + roomCode: ws.roomCode, + // eslint-disable-next-line no-undef + puzzle: removeProp(newPuzzle,'answer'), + turn:room.gameState.turn, + turnState:room.gameState.turnState + })) + }) +} // function checkIfClientExistsInRoom(ws,room) { // console.log(room,ws) // //assumes ws message is sent and room code exists @@ -234,6 +295,14 @@ wss.on('connection', (ws) => { }) } + if (data.type === 'confirm_id') { + const room = rooms[ws.roomCode] + const currentUserTurn = room.gameState.players[room.gameState.turn] + room.gameState.turnState = 'spin' + if (ws.name == currentUserTurn.name && ws.identifierToken == currentUserTurn.id) { + ws.send(JSON.stringify({ type:'next_turn_confirmed'})) + } else ws.send(JSON.stringify({ type:'next_turn_denied'})) + } if (data.type === 'create_room') { const roomCode = uuidv4().slice(0, 5) ws.name = getRandomName() @@ -298,8 +367,11 @@ wss.on('connection', (ws) => { } if (data.type === 'start_game') { - + const room = rooms[ws.roomCode] + if (room.gameState.started) { + ws.send(JSON.stringify({ type: 'error', message: 'game has already been started' })) + } const currentPuzzle = loadCurrentPuzzle(room.gameState) // const clientPuzzle = Object.entries(currentPuzzle).filter(([key])=> key != 'answer') @@ -312,7 +384,8 @@ wss.on('connection', (ws) => { room.gameState.players.push({ id:client.identifierToken, name:client.name, - points:0 + points:0, + wins:0 }) }) console.log(room.gameState) @@ -350,16 +423,22 @@ wss.on('connection', (ws) => { // Simulate a wheel spin result and update room state let spinResult = getRandomValue(wheel) if (spinResult == 'Bankrupt') { - spinResult = 0 - } - if (spinResult == 'spin again') { - spinResult = 0 room.gameState.players = room.gameState.players.map((player) => { - return player.id == ws.identifierToken ? {...player, points:player.points + spinResult, condition:'spin again'} : player + return player.id == ws.identifierToken ? {...player, points:0} : player }) } + if (spinResult == 'spin again') { + + room.gameState.players = room.gameState.players.map((player) => { + return player.id == ws.identifierToken ? {...player, points:player.points + 0, condition:'spin again'} : player + }) + } + if (spinResult == 'lose a turn') { + console.log('lose a turn here ig...?') + changeTurn(room.gameState,ws) + } room.gameState.players = room.gameState.players.map((player) => { - return player.id == ws.identifierToken ? {...player, points:player.points + spinResult} : player + return player.id == ws.identifierToken ? {...player, points:player.points + 0} : player }) console.log('players', room.gameState.players) room.gameState.spinResult = spinResult @@ -380,29 +459,35 @@ wss.on('connection', (ws) => { ws.send(JSON.stringify({ type: 'error', message: 'its not your turn to guess!' })) return } - room.gameState.turnState = 'spin' + room.gameState.turnState = 'guess' const { letter } = data // Handle guess logic (e.g., check if the letter is in the puzzle) const guessResult = checkGuess(letter,room.gameState) if (!guessResult) { + room.gameState.turnState = 'spin' //if the player guesses incorrectly, and theres more than one player, //its the next players turn room.clients.forEach((client) => { client.send(JSON.stringify( { type: 'guess_result', letter, correct: guessResult, - player: ws === room.leader ? 'Leader' : 'Player' })) + player: ws === room.leader ? 'Leader' : 'Player', + turnState:room.gameState.turnState + })) }) - if (room.gameState.turn == room.gameState.players.length - 1) { - room.gameState.turn = 0 - } - else room.gameState.turn++ + changeTurn(room.gameState,ws) + + } + else if(guessResult === 'puzzleSolved') { + rewardUser(room.gameState,ws) + loadNewPuzzle(room.gameState,ws) } else { //the player guessed correctly and its still their turn + room.gameState.turn = 'spin' room.clients.forEach((client) => client.send(JSON.stringify( { type: 'guess_result', letter, diff --git a/thingstotest.txt b/thingstotest.txt index 2f3f101..ffaf6a9 100644 --- a/thingstotest.txt +++ b/thingstotest.txt @@ -2,4 +2,10 @@ things to test.txt test joining room on already started game -don't use async testing in mocha if possible. \ No newline at end of file +don't use async testing in mocha if possible. + +//check spin again and unify the UI to check turnState, +//make sure the messages being recieved are canonized. + +//figure out how to check for string data vs number data when doing the spin wheel +//only pass an integer to the startSpin function, so less code needs to be changed. \ No newline at end of file