Compare commits

..

2 Commits

Author SHA1 Message Date
9c84bb2efe custom player names 2022-04-15 15:16:38 -06:00
489d9e32ee in progress 2022-02-04 17:23:50 -07:00
6 changed files with 97 additions and 35 deletions

View File

@ -3521,6 +3521,15 @@
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"optional": true "optional": true
}, },
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"optional": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bluebird": { "bluebird": {
"version": "3.7.2", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@ -6395,6 +6404,12 @@
} }
} }
}, },
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"optional": true
},
"filesize": { "filesize": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz", "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz",
@ -10109,6 +10124,12 @@
"resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
}, },
"nan": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
"optional": true
},
"nanoid": { "nanoid": {
"version": "3.1.20", "version": "3.1.20",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
@ -15228,7 +15249,11 @@
"version": "1.2.13", "version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"optional": true "optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
}, },
"glob-parent": { "glob-parent": {
"version": "3.1.0", "version": "3.1.0",
@ -15822,7 +15847,11 @@
"version": "1.2.13", "version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"optional": true "optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
}, },
"glob-parent": { "glob-parent": {
"version": "3.1.0", "version": "3.1.0",

View File

@ -385,6 +385,10 @@ a {
.msg-receive:hover, .msg-send:hover{ .msg-receive:hover, .msg-send:hover{
opacity: .9; opacity: .9;
} }
.your-name-input{
font-size: 15px;
line-height: 1.5em;
}
/*media query*/ /*media query*/
@media only screen and (max-width: 480px) @media only screen and (max-width: 480px)
{ {
@ -394,6 +398,11 @@ a {
align-items: center; align-items: center;
} }
.homepage-menu {
flex-direction: column;
align-items: center;
}
.topInfo .topInfo
{ {
flex-direction: column; flex-direction: column;

View File

@ -22,8 +22,8 @@ import gameOverSound from '../assets/sounds/game-over-sound.mp3'
//DRAW 4 WILD - 600 //DRAW 4 WILD - 600
let socket let socket
// const ENDPOINT = 'http://localhost:5000' const ENDPOINT = 'http://localhost:5000'
const ENDPOINT = 'https://uno-online-multiplayer.herokuapp.com/' //const ENDPOINT = 'https://uno-online-multiplayer.herokuapp.com/'
const Game = (props) => { const Game = (props) => {
const data = queryString.parse(props.location.search) const data = queryString.parse(props.location.search)
@ -35,17 +35,21 @@ const Game = (props) => {
const [currentUser, setCurrentUser] = useState('') const [currentUser, setCurrentUser] = useState('')
const [message, setMessage] = useState('') const [message, setMessage] = useState('')
const [messages, setMessages] = useState([]) const [messages, setMessages] = useState([])
const [playerName, setPlayerName] = useState(data.playerName)
const [player1Name, setPlayer1Name] = useState('Player 1')
const [player2Name, setPlayer2Name] = useState('Player 2')
useEffect(() => { useEffect(() => {
const connectionOptions = { const connectionOptions = {
"forceNew" : true, "forceNew" : true,
"reconnectionAttempts": "Infinity", "reconnectionAttempts": "Infinity",
"timeout" : 10000, "timeout" : 10000,
"transports" : ["websocket"] "transports" : ["websocket"]
} }
socket = io.connect(ENDPOINT, connectionOptions) socket = io.connect(ENDPOINT, connectionOptions)
socket.emit('join', {room: room}, (error) => { socket.emit('join', {room: room, playerName: playerName}, (error) => {
if(error) if(error)
setRoomFull(true) setRoomFull(true)
}) })
@ -156,12 +160,22 @@ const Game = (props) => {
socket.on("roomData", ({ users }) => { socket.on("roomData", ({ users }) => {
setUsers(users) setUsers(users)
// For each user, update the name
users.forEach(function(user){
if(user.name === 'Player 1'){
setPlayer1Name(user.playerName)
}else if(user.name === 'Player 2'){
setPlayer2Name(user.playerName)
}
})
}) })
socket.on('currentUserData', ({ name }) => { socket.on('currentUserData', ({ name }) => {
setCurrentUser(name) setCurrentUser(name)
}) })
socket.on('message', message => { socket.on('message', message => {
setMessages(messages => [ ...messages, message ]) setMessages(messages => [ ...messages, message ])
@ -174,7 +188,7 @@ const Game = (props) => {
const checkGameOver = (arr) => { const checkGameOver = (arr) => {
return arr.length === 1 return arr.length === 1
} }
const checkWinner = (arr, player) => { const checkWinner = (arr, player) => {
return arr.length === 1 ? player : '' return arr.length === 1 ? player : ''
} }
@ -688,7 +702,7 @@ const Game = (props) => {
} }
} }
//check for number match - if draw 2 card played on draw 2 card //check for number match - if draw 2 card played on draw 2 card
else if(currentNumber === 252) { else if(currentNumber === 252) {
console.log('number matched!') console.log('number matched!')
//check who played the card and return new state accordingly //check who played the card and return new state accordingly
if(cardPlayedBy === 'Player 1') { if(cardPlayedBy === 'Player 1') {
@ -1012,7 +1026,7 @@ const Game = (props) => {
break; break;
} }
} }
const onCardDrawnHandler = () => { const onCardDrawnHandler = () => {
//extract player who drew the card //extract player who drew the card
const cardDrawnBy = turn const cardDrawnBy = turn
@ -1214,7 +1228,7 @@ const Game = (props) => {
} }
} }
} }
return ( return (
<div className={`Game backgroundColorR backgroundColor${currentColor}`}> <div className={`Game backgroundColorR backgroundColor${currentColor}`}>
{(!roomFull) ? <> {(!roomFull) ? <>
@ -1231,6 +1245,7 @@ const Game = (props) => {
pause() pause()
setMusicMuted(!isMusicMuted) setMusicMuted(!isMusicMuted)
}}>{isMusicMuted ? <span className="material-icons">music_off</span> : <span className="material-icons">music_note</span>}</button> }}>{isMusicMuted ? <span className="material-icons">music_off</span> : <span className="material-icons">music_note</span>}</button>
<a href='/'><button className="game-button red">QUIT</button></a>
</span> </span>
</div> </div>
@ -1243,9 +1258,9 @@ const Game = (props) => {
{gameOver ? <div>{winner !== '' && <><h1>GAME OVER</h1><h2>{winner} wins!</h2></>}</div> : {gameOver ? <div>{winner !== '' && <><h1>GAME OVER</h1><h2>{winner} wins!</h2></>}</div> :
<div> <div>
{/* PLAYER 1 VIEW */} {/* PLAYER 1 VIEW */}
{currentUser === 'Player 1' && <> {currentUser === 'Player 1' && <>
<div className='player2Deck' style={{pointerEvents: 'none'}}> <div className='player2Deck' style={{pointerEvents: 'none'}}>
<p className='playerDeckText'>Player 2</p> <p className='playerDeckText'>{player2Name}</p>
{player2Deck.map((item, i) => ( {player2Deck.map((item, i) => (
<img <img
key={i} key={i}
@ -1258,20 +1273,15 @@ const Game = (props) => {
</div> </div>
<br /> <br />
<div className='middleInfo' style={turn === 'Player 2' ? {pointerEvents: 'none'} : null}> <div className='middleInfo' style={turn === 'Player 2' ? {pointerEvents: 'none'} : null}>
<button className='game-button' disabled={turn !== 'Player 1'} onClick={onCardDrawnHandler}>DRAW CARD</button>
{playedCardsPile && playedCardsPile.length>0 && {playedCardsPile && playedCardsPile.length>0 &&
<img <img
className='Card' className='Card'
src={require(`../assets/cards-front/${playedCardsPile[playedCardsPile.length-1]}.png`).default} src={require(`../assets/cards-front/${playedCardsPile[playedCardsPile.length-1]}.png`).default}
/> } /> }
<button className='game-button orange' disabled={player1Deck.length !== 2} onClick={() => {
setUnoButtonPressed(!isUnoButtonPressed)
playUnoSound()
}}>UNO</button>
</div> </div>
<br /> <br />
<div className='player1Deck' style={turn === 'Player 1' ? null : {pointerEvents: 'none'}}> <div className='player1Deck' style={turn === 'Player 1' ? null : {pointerEvents: 'none'}}>
<p className='playerDeckText'>Player 1</p> <p className='playerDeckText'>{player1Name}</p>
{player1Deck.map((item, i) => ( {player1Deck.map((item, i) => (
<img <img
key={i} key={i}
@ -1281,6 +1291,14 @@ const Game = (props) => {
/> />
))} ))}
</div> </div>
<br />
<div className='middleInfo' style={turn === 'Player 2' ? {pointerEvents: 'none'} : null}>
<button className='game-button' disabled={turn !== 'Player 1'} onClick={onCardDrawnHandler}>DRAW CARD</button>
<button className='game-button orange' disabled={player1Deck.length !== 2} onClick={() => {
setUnoButtonPressed(!isUnoButtonPressed)
playUnoSound()
}}>UNO</button>
</div>
<div className="chatBoxWrapper"> <div className="chatBoxWrapper">
<div className="chat-box chat-box-player1"> <div className="chat-box chat-box-player1">
@ -1309,7 +1327,7 @@ const Game = (props) => {
{/* PLAYER 2 VIEW */} {/* PLAYER 2 VIEW */}
{currentUser === 'Player 2' && <> {currentUser === 'Player 2' && <>
<div className='player1Deck' style={{pointerEvents: 'none'}}> <div className='player1Deck' style={{pointerEvents: 'none'}}>
<p className='playerDeckText'>Player 1</p> <p className='playerDeckText'>{player1Name}</p>
{player1Deck.map((item, i) => ( {player1Deck.map((item, i) => (
<img <img
key={i} key={i}
@ -1322,20 +1340,15 @@ const Game = (props) => {
</div> </div>
<br /> <br />
<div className='middleInfo' style={turn === 'Player 1' ? {pointerEvents: 'none'} : null}> <div className='middleInfo' style={turn === 'Player 1' ? {pointerEvents: 'none'} : null}>
<button className='game-button' disabled={turn !== 'Player 2'} onClick={onCardDrawnHandler}>DRAW CARD</button>
{playedCardsPile && playedCardsPile.length>0 && {playedCardsPile && playedCardsPile.length>0 &&
<img <img
className='Card' className='Card'
src={require(`../assets/cards-front/${playedCardsPile[playedCardsPile.length-1]}.png`).default} src={require(`../assets/cards-front/${playedCardsPile[playedCardsPile.length-1]}.png`).default}
/> } /> }
<button className='game-button orange' disabled={player2Deck.length !== 2} onClick={() => {
setUnoButtonPressed(!isUnoButtonPressed)
playUnoSound()
}}>UNO</button>
</div> </div>
<br /> <br />
<div className='player2Deck' style={turn === 'Player 1' ? {pointerEvents: 'none'} : null}> <div className='player2Deck' style={turn === 'Player 1' ? {pointerEvents: 'none'} : null}>
<p className='playerDeckText'>Player 2</p> <p className='playerDeckText'>{player2Name}</p>
{player2Deck.map((item, i) => ( {player2Deck.map((item, i) => (
<img <img
key={i} key={i}
@ -1345,6 +1358,14 @@ const Game = (props) => {
/> />
))} ))}
</div> </div>
<br />
<div className='middleInfo' style={turn === 'Player 1' ? {pointerEvents: 'none'} : null}>
<button className='game-button' disabled={turn !== 'Player 2'} onClick={onCardDrawnHandler}>DRAW CARD</button>
<button className='game-button orange' disabled={player2Deck.length !== 2} onClick={() => {
setUnoButtonPressed(!isUnoButtonPressed)
playUnoSound()
}}>UNO</button>
</div>
<div className="chatBoxWrapper"> <div className="chatBoxWrapper">
<div className="chat-box chat-box-player2"> <div className="chat-box chat-box-player2">
@ -1372,9 +1393,6 @@ const Game = (props) => {
</div> } </div> }
</> } </> }
</> : <h1>Room full</h1> } </> : <h1>Room full</h1> }
<br />
<a href='/'><button className="game-button red">QUIT</button></a>
</div> </div>
) )
} }

View File

@ -4,19 +4,22 @@ import randomCodeGenerator from '../utils/randomCodeGenerator'
const Homepage = () => { const Homepage = () => {
const [roomCode, setRoomCode] = useState('') const [roomCode, setRoomCode] = useState('')
const [playerName, setPlayerName] = useState('')
return ( return (
<div className='Homepage'> <div className='Homepage'>
<div className='homepage-menu'> <div className='homepage-menu'>
<img src={require('../assets/logo.png').default} width='200px' /> <img src={require('../assets/logo.png').default} width='200px' />
<br />
<input type='text' placeholder='Your name' className="your-name-input" onChange={(event) => setPlayerName(event.target.value)} />
<div className='homepage-form'> <div className='homepage-form'>
<div className='homepage-join'> <div className='homepage-join'>
<input type='text' placeholder='Game Code' onChange={(event) => setRoomCode(event.target.value)} /> <input type='text' placeholder='Game Code' onChange={(event) => setRoomCode(event.target.value)} />
<Link to={`/play?roomCode=${roomCode}`}><button className="game-button green">JOIN GAME</button></Link> <Link to={`/play?roomCode=${roomCode}&playerName=${playerName}`}><button className="game-button green">JOIN GAME</button></Link>
</div> </div>
<h1>OR</h1> <h1>OR</h1>
<div className='homepage-create'> <div className='homepage-create'>
<Link to={`/play?roomCode=${randomCodeGenerator(5)}`}><button className="game-button orange">CREATE GAME</button></Link> <Link to={`/play?roomCode=${randomCodeGenerator(5)}&playerName=${playerName}`}><button className="game-button orange">CREATE GAME</button></Link>
</div> </div>
</div> </div>
</div> </div>

View File

@ -16,11 +16,14 @@ app.use(cors())
io.on('connection', socket => { io.on('connection', socket => {
socket.on('join', (payload, callback) => { socket.on('join', (payload, callback) => {
let numberOfUsersInRoom = getUsersInRoom(payload.room).length let numberOfUsersInRoom = getUsersInRoom(payload.room).length
let username = numberOfUsersInRoom===0 ? 'Player 1' : 'Player 2';
const { error, newUser} = addUser({ const { error, newUser} = addUser({
id: socket.id, id: socket.id,
name: numberOfUsersInRoom===0 ? 'Player 1' : 'Player 2', name: username,
room: payload.room room: payload.room,
playerName: payload.playerName
}) })
if(error) if(error)

View File

@ -1,11 +1,11 @@
const users = [] const users = []
const addUser = ({id, name, room}) => { const addUser = ({id, name, room, playerName}) => {
const numberOfUsersInRoom = users.filter(user => user.room === room).length const numberOfUsersInRoom = users.filter(user => user.room === room).length
if(numberOfUsersInRoom === 2) if(numberOfUsersInRoom === 2)
return { error: 'Room full' } return { error: 'Room full' }
const newUser = { id, name, room } const newUser = { id, name, room, playerName}
users.push(newUser) users.push(newUser)
return { newUser } return { newUser }
} }