edited css and readme
This commit is contained in:
parent
7304922e86
commit
c8773ed546
15
README.md
15
README.md
@ -1,11 +1,13 @@
|
||||
# Online multiplayer Ludo
|
||||
WORK IN PROGRESS ...
|
||||
## 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))
|
||||
|
||||
## Interface
|
||||

|
||||
|
||||
## Installation
|
||||
Play this game [here]()
|
||||
Play this game [here](https://smaga-wiktor-ludo.herokuapp.com)
|
||||
```
|
||||
npm i
|
||||
npm start
|
||||
@ -18,12 +20,15 @@ node server.js
|
||||
### Backend
|
||||
- Node.js
|
||||
- Express
|
||||
- express-session
|
||||
- MongoDB
|
||||
- Express-session
|
||||
- MongoDB, Mongoose
|
||||
- MongoDB sessions store
|
||||
- Maybe Redis in future
|
||||
### Frontend
|
||||
- React
|
||||
- Axios
|
||||
- Material UI
|
||||
- Canvas
|
||||
## ToDo
|
||||
- Redis
|
||||
- SocketIO
|
||||
- Add more game logic
|
||||
@ -32,7 +32,7 @@ router.post('/move', function (req, res){
|
||||
doc.players[index+1].nowMoving = true;
|
||||
}
|
||||
// Updating timer
|
||||
doc.nextMoveTime = Date.now()+30000;
|
||||
doc.nextMoveTime = Date.now()+15000;
|
||||
RoomModel.findOneAndUpdate({_id: req.session.roomId}, doc, function(err, doc){
|
||||
res.send("Correctly Moved!");
|
||||
});
|
||||
|
||||
@ -18,7 +18,8 @@ var changeReadyState = (req, res, exit) =>{
|
||||
}
|
||||
if(updatedPlayers.filter(player => player.ready).length >= 2){
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -58,7 +58,8 @@ 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()+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.pawns = getStartPositions();
|
||||
}
|
||||
@ -100,7 +101,7 @@ router.get('/', function(req,res){
|
||||
}else{
|
||||
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){
|
||||
if(err){
|
||||
res.status(500).send(err)
|
||||
|
||||
@ -2,20 +2,17 @@ const express = require("express");
|
||||
const cors = require('cors');
|
||||
const cookieParser = require('cookie-parser')
|
||||
const session = require('express-session')
|
||||
const bodyParser = require('body-parser');
|
||||
|
||||
const app = express();
|
||||
app.use(cookieParser());
|
||||
app.use(bodyParser.urlencoded({
|
||||
app.use(express.urlencoded({
|
||||
extended: true
|
||||
}));
|
||||
app.use(bodyParser.json());
|
||||
app.use(express.json());
|
||||
app.set('trust proxy', 1)
|
||||
app.use(cors({
|
||||
origin: [
|
||||
'localhost:3001',
|
||||
'http://localhost:3001',
|
||||
'https://localhost:3001'
|
||||
],
|
||||
credentials: true,
|
||||
}))
|
||||
|
||||
@ -16,12 +16,9 @@ function App() {
|
||||
useEffect(() => {
|
||||
axios.get('http://localhost:3000/player', {
|
||||
withCredentials:true,
|
||||
mode: 'cors'
|
||||
})
|
||||
.then( response => {
|
||||
.then(response => {
|
||||
setPlayerData(response.data)
|
||||
console.log(response.data);
|
||||
|
||||
response.data.roomId!=null ? setRedirect(true) : setRedirect(false);
|
||||
});
|
||||
},[]);
|
||||
@ -29,15 +26,13 @@ function App() {
|
||||
const handleExit = e => {
|
||||
e.preventDefault();
|
||||
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 = () => {
|
||||
axios.get('http://localhost:3000/player/', {
|
||||
withCredentials:true,
|
||||
mode: 'cors',
|
||||
headers: { "Content-Type": "application/json" },
|
||||
})
|
||||
.then(response => {
|
||||
setPlayerData(response.data);
|
||||
|
||||
@ -20,7 +20,6 @@ const Gameboard = () => {
|
||||
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){
|
||||
@ -36,6 +35,7 @@ const Gameboard = () => {
|
||||
setNowMoving(false);
|
||||
}
|
||||
}
|
||||
checkWin();
|
||||
setPlayers(response.data.players);
|
||||
setPawns(response.data.pawns);
|
||||
setTime(response.data.nextMoveTime);
|
||||
@ -43,6 +43,7 @@ const Gameboard = () => {
|
||||
})
|
||||
}
|
||||
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){
|
||||
alert("Red Won")
|
||||
}else if(pawns.filter(pawn => pawn.color === 'blue' && pawn.position === 79).length === 4){
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
.navbar-container{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.navbar-container>div{
|
||||
margin-right: 10px;
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import NameContainer from './navbar-components/NameContainer'
|
||||
import ReadyButton from './navbar-components/ReadyButton'
|
||||
import './Navbar.css';
|
||||
|
||||
const Navbar = ({ players, started, time }) => {
|
||||
return(
|
||||
<div className = "navbar-container">
|
||||
|
||||
@ -8,7 +8,7 @@ import five from '../../images/dice/5.png';
|
||||
import six from '../../images/dice/6.png';
|
||||
|
||||
const Dice = ({ rolledNumberCallback, nowMoving }) => {
|
||||
const [rolledNumber, setRolledNumber] = useState()
|
||||
const [rolledNumber, setRolledNumber] = useState();
|
||||
const [images] = useState([one, two, three, four, five, six]);
|
||||
const handleRoll = () => {
|
||||
axios.get('http://localhost:3000/game/roll').then(response => {
|
||||
@ -19,8 +19,8 @@ const Dice = ({ rolledNumberCallback, nowMoving }) => {
|
||||
})
|
||||
}
|
||||
return(
|
||||
<div>
|
||||
{rolledNumber ? <img src={images[rolledNumber - 1]} width="100" height="100"/> : nowMoving ? <button onClick={handleRoll}>Roll</button> : null }
|
||||
<div className="dice-container">
|
||||
{rolledNumber ? <img src={images[rolledNumber - 1]} width="100" height="100"/> : nowMoving ? <button onClick={handleRoll}> Roll </button> : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
.canvas-container{
|
||||
margin: 10px;
|
||||
}
|
||||
@ -2,7 +2,6 @@ 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, rolledNumber }) => {
|
||||
const context = useContext(PlayerDataContext);
|
||||
@ -44,8 +43,8 @@ const Map = ({ pawns, nowMoving, rolledNumber }) => {
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const handleCanvasClick = event => {
|
||||
// If hint pawn exist it means that pawn can move
|
||||
if(hintPawn){
|
||||
@ -56,10 +55,8 @@ const Map = ({ pawns, nowMoving, rolledNumber }) => {
|
||||
y = event.clientY - rect.top;
|
||||
for(const pawn of pawns){
|
||||
if (ctx.isPointInPath(pawn.circle, x, y)) {
|
||||
axios.post('http://localhost:3000/game/move', {pawnId: pawn._id, position: hintPawn.position},
|
||||
{
|
||||
withCredentials: true,
|
||||
}).then(() => {
|
||||
axios.post('http://localhost:3000/game/move', {pawnId: pawn._id, position: hintPawn.position}, {withCredentials: true})
|
||||
.then(() => {
|
||||
setHintPawn(null);
|
||||
});
|
||||
|
||||
@ -125,7 +122,6 @@ const Map = ({ pawns, nowMoving, rolledNumber }) => {
|
||||
return position + rolledNumber;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
const handleMouseMove = event => {
|
||||
if(nowMoving && rolledNumber){
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import './NameContainer.css';
|
||||
|
||||
const NameContainer = ( {player, time} ) => {
|
||||
const getRemainingTime = () => {
|
||||
return Math.round((time - Date.now())/1000)+1;
|
||||
@ -11,7 +11,6 @@ const NameContainer = ( {player, time} ) => {
|
||||
{player.nowMoving ? <div className="timer"> {getRemainingTime()} </div> : null}
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default NameContainer;
|
||||
BIN
src/images/readme1.png
Normal file
BIN
src/images/readme1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 124 KiB |
@ -4,3 +4,39 @@ body{
|
||||
flex-direction: column;
|
||||
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;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user