edited css and readme

This commit is contained in:
Wenszel 2021-04-30 12:24:19 +02:00
parent 7304922e86
commit c8773ed546
16 changed files with 67 additions and 67 deletions

View File

@ -1,11 +1,13 @@
# Online multiplayer Ludo # Online multiplayer Ludo
WORK IN PROGRESS ...
## About ## About
**Ludo** is a strategy board game for two to four players, in which the players race their four tokens from start to finish according to the rolls of a single die. Like other cross and circle games, Ludo is derived from the Indian game Pachisi, but simpler. The game and its variations are popular in many countries and under various names. [Read more](https://en.wikipedia.org/wiki/Ludo_(board_game)) **Ludo** is a strategy board game for two to four players, in which the players race their four tokens from start to finish according to the rolls of a single die. Like other cross and circle games, Ludo is derived from the Indian game Pachisi, but simpler. The game and its variations are popular in many countries and under various names. [Read more](https://en.wikipedia.org/wiki/Ludo_(board_game))
## Interface
![Interface](https://github.com/Wenszel/mern-ludo/blob/main/src/images/readme1.png?raw=true)
## Installation ## Installation
Play this game [here]() Play this game [here](https://smaga-wiktor-ludo.herokuapp.com)
``` ```
npm i npm i
npm start npm start
@ -18,12 +20,15 @@ node server.js
### Backend ### Backend
- Node.js - Node.js
- Express - Express
- express-session - Express-session
- MongoDB - MongoDB, Mongoose
- MongoDB sessions store - MongoDB sessions store
- Maybe Redis in future
### Frontend ### Frontend
- React - React
- Axios - Axios
- Material UI - Material UI
- Canvas - Canvas
## ToDo
- Redis
- SocketIO
- Add more game logic

View File

@ -32,7 +32,7 @@ router.post('/move', function (req, res){
doc.players[index+1].nowMoving = true; doc.players[index+1].nowMoving = true;
} }
// Updating timer // Updating timer
doc.nextMoveTime = Date.now()+30000; doc.nextMoveTime = Date.now()+15000;
RoomModel.findOneAndUpdate({_id: req.session.roomId}, doc, function(err, doc){ RoomModel.findOneAndUpdate({_id: req.session.roomId}, doc, function(err, doc){
res.send("Correctly Moved!"); res.send("Correctly Moved!");
}); });

View File

@ -18,7 +18,8 @@ var changeReadyState = (req, res, exit) =>{
} }
if(updatedPlayers.filter(player => player.ready).length >= 2){ if(updatedPlayers.filter(player => player.ready).length >= 2){
updatedDoc.started = true; updatedDoc.started = true;
updatedDoc.nextMoveTime = Date.now()+30000; updatedDoc.players = updatedDoc.players.map(player => player.ready === true);
updatedDoc.nextMoveTime = Date.now() + 15000;
updatedDoc.players[0].nowMoving = true; updatedDoc.players[0].nowMoving = true;
} }

View File

@ -58,7 +58,8 @@ router.post('/add', function (req, res) {
if (players.length === 4) { if (players.length === 4) {
updateObj.full = true; // Room is full updateObj.full = true; // Room is full
updateObj.started = true; // Game started updateObj.started = true; // Game started
updateObj.nextMoveTime = Date.now()+30000; updateObj.nextMoveTime = Date.now() + 15000;
updateObj.players = updateObj.players.map(player => player.ready === true);
updateObj.players[0].nowMoving = true; //First joined player moving updateObj.players[0].nowMoving = true; //First joined player moving
updateObj.pawns = getStartPositions(); updateObj.pawns = getStartPositions();
} }
@ -100,7 +101,7 @@ router.get('/', function(req,res){
}else{ }else{
doc.players[index + 1].nowMoving = true; doc.players[index + 1].nowMoving = true;
} }
doc.nextMoveTime = Date.now()+30000; doc.nextMoveTime = Date.now()+15000;
RoomModel.findOneAndUpdate({_id: req.session.roomId}, doc, function(err, docs){ RoomModel.findOneAndUpdate({_id: req.session.roomId}, doc, function(err, docs){
if(err){ if(err){
res.status(500).send(err) res.status(500).send(err)

View File

@ -2,20 +2,17 @@ const express = require("express");
const cors = require('cors'); const cors = require('cors');
const cookieParser = require('cookie-parser') const cookieParser = require('cookie-parser')
const session = require('express-session') const session = require('express-session')
const bodyParser = require('body-parser');
const app = express(); const app = express();
app.use(cookieParser()); app.use(cookieParser());
app.use(bodyParser.urlencoded({ app.use(express.urlencoded({
extended: true extended: true
})); }));
app.use(bodyParser.json()); app.use(express.json());
app.set('trust proxy', 1) app.set('trust proxy', 1)
app.use(cors({ app.use(cors({
origin: [ origin: [
'localhost:3001',
'http://localhost:3001', 'http://localhost:3001',
'https://localhost:3001'
], ],
credentials: true, credentials: true,
})) }))

View File

@ -16,12 +16,9 @@ function App() {
useEffect(() => { useEffect(() => {
axios.get('http://localhost:3000/player', { axios.get('http://localhost:3000/player', {
withCredentials:true, withCredentials:true,
mode: 'cors'
}) })
.then( response => { .then(response => {
setPlayerData(response.data) setPlayerData(response.data)
console.log(response.data);
response.data.roomId!=null ? setRedirect(true) : setRedirect(false); response.data.roomId!=null ? setRedirect(true) : setRedirect(false);
}); });
},[]); },[]);
@ -29,15 +26,13 @@ function App() {
const handleExit = e => { const handleExit = e => {
e.preventDefault(); e.preventDefault();
window.addEventListener('unload', () => { window.addEventListener('unload', () => {
axios.post('http://localhost:3000/player/exit', {withCredentials:true, mode: 'cors'}) axios.post('http://localhost:3000/player/exit', {withCredentials:true, })
}); });
} }
const idCallback = () => { const idCallback = () => {
axios.get('http://localhost:3000/player/', { axios.get('http://localhost:3000/player/', {
withCredentials:true, withCredentials:true,
mode: 'cors',
headers: { "Content-Type": "application/json" },
}) })
.then(response => { .then(response => {
setPlayerData(response.data); setPlayerData(response.data);

View File

@ -20,7 +20,6 @@ const Gameboard = () => {
const fetchData = () => { const fetchData = () => {
axios.get('http://localhost:3000/room/',{ axios.get('http://localhost:3000/room/',{
withCredentials:true, withCredentials:true,
mode: 'cors',
}).then((response)=>{ }).then((response)=>{
// Filling navbar with empty player nick container // Filling navbar with empty player nick container
while(response.data.players.length !== 4){ while(response.data.players.length !== 4){
@ -36,6 +35,7 @@ const Gameboard = () => {
setNowMoving(false); setNowMoving(false);
} }
} }
checkWin();
setPlayers(response.data.players); setPlayers(response.data.players);
setPawns(response.data.pawns); setPawns(response.data.pawns);
setTime(response.data.nextMoveTime); setTime(response.data.nextMoveTime);
@ -43,6 +43,7 @@ const Gameboard = () => {
}) })
} }
const checkWin = () => { const checkWin = () => {
// Player wins when all pawns with same color are inside end base
if(pawns.filter(pawn => pawn.color === 'red' && pawn.position === 73).length === 4){ if(pawns.filter(pawn => pawn.color === 'red' && pawn.position === 73).length === 4){
alert("Red Won") alert("Red Won")
}else if(pawns.filter(pawn => pawn.color === 'blue' && pawn.position === 79).length === 4){ }else if(pawns.filter(pawn => pawn.color === 'blue' && pawn.position === 79).length === 4){

View File

@ -1,7 +0,0 @@
.navbar-container{
display: flex;
flex-direction: row;
}
.navbar-container>div{
margin-right: 10px;
}

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import NameContainer from './navbar-components/NameContainer' import NameContainer from './navbar-components/NameContainer'
import ReadyButton from './navbar-components/ReadyButton' import ReadyButton from './navbar-components/ReadyButton'
import './Navbar.css';
const Navbar = ({ players, started, time }) => { const Navbar = ({ players, started, time }) => {
return( return(
<div className = "navbar-container"> <div className = "navbar-container">

View File

@ -8,7 +8,7 @@ import five from '../../images/dice/5.png';
import six from '../../images/dice/6.png'; import six from '../../images/dice/6.png';
const Dice = ({ rolledNumberCallback, nowMoving }) => { const Dice = ({ rolledNumberCallback, nowMoving }) => {
const [rolledNumber, setRolledNumber] = useState() const [rolledNumber, setRolledNumber] = useState();
const [images] = useState([one, two, three, four, five, six]); const [images] = useState([one, two, three, four, five, six]);
const handleRoll = () => { const handleRoll = () => {
axios.get('http://localhost:3000/game/roll').then(response => { axios.get('http://localhost:3000/game/roll').then(response => {
@ -19,8 +19,8 @@ const Dice = ({ rolledNumberCallback, nowMoving }) => {
}) })
} }
return( return(
<div> <div className="dice-container">
{rolledNumber ? <img src={images[rolledNumber - 1]} width="100" height="100"/> : nowMoving ? <button onClick={handleRoll}>Roll</button> : null } {rolledNumber ? <img src={images[rolledNumber - 1]} width="100" height="100"/> : nowMoving ? <button onClick={handleRoll}> Roll </button> : null}
</div> </div>
) )
} }

View File

@ -1,3 +0,0 @@
.canvas-container{
margin: 10px;
}

View File

@ -2,7 +2,6 @@ import React, { useEffect, useRef, useState, useContext } from 'react';
import { PlayerDataContext } from '../../App'; import { PlayerDataContext } from '../../App';
import axios from 'axios'; import axios from 'axios';
import positions from './positions'; import positions from './positions';
import './Map.css';
const Map = ({ pawns, nowMoving, rolledNumber }) => { const Map = ({ pawns, nowMoving, rolledNumber }) => {
const context = useContext(PlayerDataContext); const context = useContext(PlayerDataContext);
@ -44,8 +43,8 @@ const Map = ({ pawns, nowMoving, rolledNumber }) => {
}else{ }else{
return false; return false;
} }
} }
const handleCanvasClick = event => { const handleCanvasClick = event => {
// If hint pawn exist it means that pawn can move // If hint pawn exist it means that pawn can move
if(hintPawn){ if(hintPawn){
@ -56,10 +55,8 @@ const Map = ({ pawns, nowMoving, rolledNumber }) => {
y = event.clientY - rect.top; y = event.clientY - rect.top;
for(const pawn of pawns){ for(const pawn of pawns){
if (ctx.isPointInPath(pawn.circle, x, y)) { if (ctx.isPointInPath(pawn.circle, x, y)) {
axios.post('http://localhost:3000/game/move', {pawnId: pawn._id, position: hintPawn.position}, axios.post('http://localhost:3000/game/move', {pawnId: pawn._id, position: hintPawn.position}, {withCredentials: true})
{ .then(() => {
withCredentials: true,
}).then(() => {
setHintPawn(null); setHintPawn(null);
}); });
@ -125,7 +122,6 @@ const Map = ({ pawns, nowMoving, rolledNumber }) => {
return position + rolledNumber; return position + rolledNumber;
} }
} }
}; };
const handleMouseMove = event => { const handleMouseMove = event => {
if(nowMoving && rolledNumber){ if(nowMoving && rolledNumber){

View File

@ -1,21 +0,0 @@
.name-container{
width: 100px;
height: 50px;
border-radius: 5px;
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;
}

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import './NameContainer.css';
const NameContainer = ( {player, time} ) => { const NameContainer = ( {player, time} ) => {
const getRemainingTime = () => { const getRemainingTime = () => {
return Math.round((time - Date.now())/1000)+1; return Math.round((time - Date.now())/1000)+1;
@ -11,7 +11,6 @@ const NameContainer = ( {player, time} ) => {
{player.nowMoving ? <div className="timer"> {getRemainingTime()} </div> : null} {player.nowMoving ? <div className="timer"> {getRemainingTime()} </div> : null}
</div> </div>
) )
} }
export default NameContainer; export default NameContainer;

BIN
src/images/readme1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

View File

@ -4,3 +4,39 @@ body{
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
.canvas-container{
margin: 10px;
}
.dice-container{
position: absolute;
top: 30%;
left: 20%;
}
.navbar-container{
display: flex;
flex-direction: row;
}
.navbar-container>div{
margin-right: 10px;
}
.name-container{
width: 100px;
height: 50px;
border-radius: 5px;
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;
}