diff --git a/backend/routes/game.js b/backend/routes/game.js index 0a0b5f5..f141723 100644 --- a/backend/routes/game.js +++ b/backend/routes/game.js @@ -23,5 +23,9 @@ router.get('/roll', function (req, res){ res.send({number: Math.ceil(Math.random() * 6)}); }); +router.post('/move', function (req, res){ + +}); + module.exports = router; \ No newline at end of file diff --git a/backend/routes/player.js b/backend/routes/player.js index 25fecf5..0302592 100644 --- a/backend/routes/player.js +++ b/backend/routes/player.js @@ -18,6 +18,7 @@ var changeReadyState = (req, res, exit) =>{ } if(updatedPlayers.filter(player => player.ready).length >= 2){ updatedDoc.started = true; + updatedDoc.nextMoveTime = Date.now()+15; updatedDoc.players[0].nowMoving = true; } diff --git a/backend/routes/room.js b/backend/routes/room.js index 8b201be..3142b13 100644 --- a/backend/routes/room.js +++ b/backend/routes/room.js @@ -57,6 +57,7 @@ router.post('/add', function (req, res) { if (players.length === 4) { updateObj.full = true; // Room is full updateObj.started = true; // Game started + updateObj.nextMoveTime = Date.now()+15; updateObj.players[0].nowMoving = true; //First joined player moving updateObj.pawns = getStartPositions(); } diff --git a/backend/schemas/room.js b/backend/schemas/room.js index f7082f7..2d13e52 100644 --- a/backend/schemas/room.js +++ b/backend/schemas/room.js @@ -6,7 +6,7 @@ var RoomSchema = new Schema({ createDate: Date, started: Boolean, full: Boolean, - timer: Number, + nextMoveTime: Number, players: [{ name: String, color: String, diff --git a/src/App.js b/src/App.js index 9f7518d..ca8ff7e 100644 --- a/src/App.js +++ b/src/App.js @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, createContext } from 'react'; import axios from 'axios'; import { Beforeunload } from 'react-beforeunload'; @@ -7,10 +7,10 @@ import { BrowserRouter as Router , Route , Redirect, Switch } from 'react-router import Gameboard from './components/Gameboard' import NameInput from './components/NameInput'; -function App() { +export const PlayerDataContext = createContext(); - const [id, setId] = useState(''); - const [color, setColor] = useState(''); +function App() { + const [playerData, setPlayerData] = useState(); const [redirect, setRedirect] = useState(); useEffect(() => { @@ -19,11 +19,12 @@ function App() { mode: 'cors' }) .then( response => { - setId(response.data.playerId); - setColor(response.data.color); + setPlayerData(response.data) + console.log(response.data); + response.data.roomId!=null ? setRedirect(true) : setRedirect(false); }); - },[id]) + },[]); const handleExit = e => { e.preventDefault(); @@ -32,16 +33,16 @@ function App() { }); } - const idCallback = (id)=>{ + const idCallback = () => { axios.get('http://localhost:3000/player/', { withCredentials:true, mode: 'cors', headers: { "Content-Type": "application/json" }, }) .then(response => { - setId(response.data.playerId); - setColor(response.data.color); - setRedirect(true) + setPlayerData(response.data); + console.log(response.data); + setRedirect(true); }) } @@ -57,7 +58,9 @@ function App() { - + + + diff --git a/src/components/Gameboard.jsx b/src/components/Gameboard.jsx index 5412ff3..7e10c84 100644 --- a/src/components/Gameboard.jsx +++ b/src/components/Gameboard.jsx @@ -1,26 +1,33 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useContext } from 'react'; +import { PlayerDataContext } from '../App' import axios from 'axios'; import Map from './game-board-components/Map' import Dice from './game-board-components/Dice' import Navbar from './Navbar' -const Gameboard = ({id, color}) => { +const Gameboard = () => { + // Context data + const context = useContext(PlayerDataContext); + const [id, setId] = useState(); + // Render data const [pawns, setPawns] = useState([]); const [players, setPlayers] = useState([]); + // Game logic data const [rolledNumber, setRolledNumber] = useState(''); + const [time, setTime] = useState(); const [nowMoving, setNowMoving] = useState(false); const [started, setStarted] = useState(false); - //fetching players data to display them in navbar + // Fetching game data const fetchData = () => { axios.get('http://localhost:3000/room/',{ withCredentials:true, mode: 'cors', }).then((response)=>{ + // Filling navbar with empty player nick container while(response.data.players.length !== 4){ - response.data.players.push({ - name: "...", - }) - } + response.data.players.push({name: "...",}); + }; + // Checks if client is currently moving player by session ID if(id===response.data.players.find(player => player.nowMoving === true)?._id){ setNowMoving(true); }else{ @@ -28,10 +35,12 @@ const Gameboard = ({id, color}) => { } setPlayers(response.data.players); setPawns(response.data.pawns); + setTime(response.data.nextMoveTime); setStarted(response.data.started); }) } - useEffect(()=>{ + useEffect(() => { + setId(context.playerId); //sending ajax every 1 sec const interval = setInterval(fetchData, 1000); return () => clearInterval(interval); @@ -43,9 +52,9 @@ const Gameboard = ({id, color}) => { return ( <> - + {nowMoving ? : null} - + ) diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 9506425..23fe5d2 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -2,11 +2,11 @@ import React from 'react'; import NameContainer from './navbar-components/NameContainer' import ReadyButton from './navbar-components/ReadyButton' import './Navbar.css'; -const Navbar = ( { players, started }) => { +const Navbar = ({ players, started, time }) => { return( -
- {players.map( (player, index) => - +
+ {players.map((player, index) => + )} {started ? null : }
diff --git a/src/components/game-board-components/Map.jsx b/src/components/game-board-components/Map.jsx index ea714db..3f42e71 100644 --- a/src/components/game-board-components/Map.jsx +++ b/src/components/game-board-components/Map.jsx @@ -1,9 +1,14 @@ -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef, useState, useContext } from 'react'; +import { PlayerDataContext } from '../../App'; +import axios from 'axios'; import positions from './positions'; import './Map.css'; -const Map = ({ pawns, nowMoving, color, rolledNumber }) => { +const Map = ({ pawns, nowMoving, rolledNumber }) => { + const context = useContext(PlayerDataContext); + const [color, setColor] = useState(); const [hintPawn, setHintPawn] = useState(); + const paintPawn = (context, x, y, color) =>{ const circle = new Path2D(); circle.arc(x, y, 12, 0, 2 * Math.PI); @@ -26,6 +31,11 @@ const Map = ({ pawns, nowMoving, color, rolledNumber }) => { y = event.clientY - rect.top; for(const pawn of pawns){ if (context.isPointInPath(pawn.circle, x, y)) { + axios.post('http://localhost:3000/game/move', { + withCredentials: true, + mode: 'cors', + data: {_id: pawn._id} + }); setHintPawn(null); } } @@ -65,6 +75,7 @@ const Map = ({ pawns, nowMoving, color, rolledNumber }) => { if(nowMoving && rolledNumber){ const canvas = canvasRef.current; const context = canvas.getContext('2d'); + // Gets x and y cords of mouse on canvas const rect = canvas.getBoundingClientRect(), x = event.clientX - rect.left, y = event.clientY - rect.top; @@ -81,7 +92,7 @@ const Map = ({ pawns, nowMoving, color, rolledNumber }) => { if (context.isPointInPath(pawn.circle, x, y) && pawn.color === color && (pawn.position>15 || rolledNumber === 1 || rolledNumber === 6)) { canvas.style.cursor = "pointer"; const pawnPosition = getHintPawnPosition(pawn); - setHintPawn({x: positions[pawnPosition].x, y: positions[pawnPosition].y, color: 'grey'}); + setHintPawn({id: pawn._id, x: positions[pawnPosition].x, y: positions[pawnPosition].y, color: 'grey'}); break; }else{ setHintPawn(null); @@ -91,10 +102,10 @@ const Map = ({ pawns, nowMoving, color, rolledNumber }) => { } }; const rerenderCanvas = () => { - const canvas = canvasRef.current - const context = canvas.getContext('2d') + const canvas = canvasRef.current; + const context = canvas.getContext('2d'); var image = new Image(); - image.src = 'https://img-9gag-fun.9cache.com/photo/a8GdpYZ_460s.jpg' + image.src = 'https://img-9gag-fun.9cache.com/photo/a8GdpYZ_460s.jpg'; image.onload = function() { context.drawImage(image, 0 , 0); pawns.forEach( (pawn, index) => { @@ -107,8 +118,10 @@ const Map = ({ pawns, nowMoving, color, rolledNumber }) => { } // Rerender canvas when pawns have changed useEffect(() => { + setColor(context.color); rerenderCanvas(); }, [pawns]); + return( { /> ) } -export default Map \ No newline at end of file +export default Map; \ No newline at end of file diff --git a/src/components/navbar-components/NameContainer.css b/src/components/navbar-components/NameContainer.css index b56054a..4973b6f 100644 --- a/src/components/navbar-components/NameContainer.css +++ b/src/components/navbar-components/NameContainer.css @@ -5,6 +5,17 @@ color: white; font-weight: bold; display: flex; + text-align: center; justify-content: center; align-items: center; } +.timer{ + background-color: darkblue; + color: white; + position: relative; + top: -20px; + left: 15px; + width: 30px; + height: 20px; + border-radius: 5px; +} \ No newline at end of file diff --git a/src/components/navbar-components/NameContainer.jsx b/src/components/navbar-components/NameContainer.jsx index 6d5bfc4..a8cc3d5 100644 --- a/src/components/navbar-components/NameContainer.jsx +++ b/src/components/navbar-components/NameContainer.jsx @@ -1,10 +1,14 @@ import React from 'react'; -import './NameContainer.css' -const NameContainer = ( {player} ) => { +import './NameContainer.css'; +const NameContainer = ( {player, time} ) => { + const getRemainingTime = () => { + return Math.floor((time - Date.now())/1000); + } return (
- {player.name} + {player.name} + {player.nowMoving ?
{getRemainingTime()}
: null}
)