Skip to content
Snippets Groups Projects
Commit da8fb58c authored by Simon Magnusson's avatar Simon Magnusson
Browse files

Can now join two players together in a single lobby via invite system

parent 3abf2d1a
Branches
No related tags found
No related merge requests found
...@@ -12,8 +12,8 @@ import GameBoard from './gameBoard/GameBoard'; ...@@ -12,8 +12,8 @@ import GameBoard from './gameBoard/GameBoard';
function PlayGamePage() { function PlayGamePage() {
const [boardWidth, setBoardWidth] = useState(700); const [boardWidth, setBoardWidth] = useState(600);
const [boardHeight, setBoardHeight] = useState(700); const [boardHeight, setBoardHeight] = useState(400);
const [socket, setSocket] = useState(null); const [socket, setSocket] = useState(null);
const pageTitle = "the most thrilling tic-tac-toe"; const pageTitle = "the most thrilling tic-tac-toe";
......
...@@ -7,9 +7,12 @@ import { selectUsers } from '../../store/usersSlice'; // to get token stuff ...@@ -7,9 +7,12 @@ import { selectUsers } from '../../store/usersSlice'; // to get token stuff
const GameBoard = () => { const GameBoard = () => {
// ID for user, gotten from firebase login info :) // ID for user, gotten from firebase login info :)
const user = useSelector(selectUsers); const user = useSelector(selectUsers);
// const userIsLoading = useSelector(state => state.user.isLoading);
const [gameStarted, setGameStarted] = useState(false); // when another player connects this turns true and it allows the match to start const [gameStarted, setGameStarted] = useState(false); // when another player connects this turns true and it allows the match to start
const [invitationCode, setInvitationCode] = useState(""); // starts blank, but gets it from the socket connection! const [gameID, setGameID] = useState(""); // starts blank, but gets it from the socket connection!
const [otherPlayer, setOtherPlayer] = useState({username: "", color: ""}); // When other player connects this is filled in const [otherPlayer, setOtherPlayer] = useState({username: "", color: ""}); // When other player connects this is filled in
const [invitationCode, setInvitationCode] = useState("");
// TODO, add color of players choosing // TODO, add color of players choosing
// camera and component logic // camera and component logic
...@@ -41,46 +44,71 @@ const GameBoard = () => { ...@@ -41,46 +44,71 @@ const GameBoard = () => {
height: gameBoardRef.current.offsetHeight, height: gameBoardRef.current.offsetHeight,
}); });
} }
}, []); }, [gameBoardRef]); // this caused a big issue
useEffect(() => { useEffect(() => {
updateDimensions(); updateDimensions();
// Update dimensions on window resize to keep responsive // Update dimensions on window resize to keep responsive
window.addEventListener('resize', updateDimensions); window.addEventListener('resize', updateDimensions);
return () => window.removeEventListener('resize', updateDimensions); return () => window.removeEventListener('resize', updateDimensions);
}, [dimensions]); }, []);
// CONNECT TO SERVER // SERVER WEBSOCKET CALLS
// EEP EEP
useEffect(() => { useEffect(() => {
// Connect to the Socket.IO server // Connect to the Socket.IO server
const newSocket = io(`http://${window.location.hostname}:3000`, { const newSocket = io(`http://${window.location.hostname}:3000`, {
query: { query: {
username: "test", username: user.currentUser.username,
playerID: "1234", playerID: user.currentUser.id, // the id assigned from firebase
color: "infrared" // color: "infrared" // todo, this would be kinda nice actually to have :)
} }
} }
); );
setSocket(newSocket); setSocket(newSocket);
return () => newSocket.close(); // cleanup code :D // could add more to this to send more data
}, [user, setSocket]);
return () => newSocket.close(); // WEBSOCKET CALLS CLIENT => SERVER
}, [setSocket]);
const sendMessage = () => { function joinGameWithCode(code) {
socket.emit('send_message', { message: 'Hello from client!' }); socket.emit('join_game_as_second_player', {gameID: code});
}; }
function sendPiecePlacement(xPos, yPos, playerSymbol) { function sendPiecePlacement(xPos, yPos, playerSymbol) {
socket.emit('placed_piece', {x: xPos, y: yPos, symbol: playerSymbol}); socket.emit('placed_piece', {x: xPos, y: yPos, symbol: playerSymbol});
} }
// SERVER => CLIENT WEBSOCKET CALLS
useEffect(() => { useEffect(() => {
if (socket) { if (socket) {
socket.on('game_setup', (data) => {
console.log('Received game ID:', data.newGame.gameID);
setGameID(data.newGame.gameID);
});
socket.on('connected_to_match', (data) => { socket.on('connected_to_match', (data) => {
}); });
socket.on('ack_join_second_player', (data) => {
if (data.joined_success) {
console.log("joined yuh");
console.log(data.otherPlayer);
} else {
console.log("didn't work bruh, wrong code");
}
});
socket.on('second_player_joined_game', (data) => {
console.log(data.otherPlayer);
});
socket.on("valid_placement", (data) => { socket.on("valid_placement", (data) => {
...@@ -97,6 +125,7 @@ const GameBoard = () => { ...@@ -97,6 +125,7 @@ const GameBoard = () => {
setIsMouseDown(true); setIsMouseDown(true);
//setIsDragging(true); //setIsDragging(true);
dragStartRef.current = { x: event.clientX, y: event.clientY }; dragStartRef.current = { x: event.clientX, y: event.clientY };
cameraStartRef.current = { ...camera }; cameraStartRef.current = { ...camera };
...@@ -222,6 +251,8 @@ const GameBoard = () => { ...@@ -222,6 +251,8 @@ const GameBoard = () => {
return false; return false;
} }
// Adjusted render function to use component dimensions // Adjusted render function to use component dimensions
const renderGameBoard = () => { const renderGameBoard = () => {
const startCol = Math.floor(camera.x / cellSize); const startCol = Math.floor(camera.x / cellSize);
...@@ -293,8 +324,26 @@ const GameBoard = () => { ...@@ -293,8 +324,26 @@ const GameBoard = () => {
style={{ width: '100px', margin: '10px 0' }} // Adjust input width to fit the design style={{ width: '100px', margin: '10px 0' }} // Adjust input width to fit the design
/> />
</div> </div>
<div>
Game Code:
<input
type="text"
value={invitationCode}
onChange={(e) => setInvitationCode(e.target.value)}
style={{ margin: '10px 0', color: 'black' }} // Ensure input text is visible
/>
<button
onClick={(e) => {
joinGameWithCode(invitationCode);
}}
style={{ margin: '10px 0' }}
>
Join Game
</button>
</div>
<div>Camera: x = {camera.x}, y = {camera.y}</div> <div>Camera: x = {camera.x}, y = {camera.y}</div>
<div>Clicked on: x = {clickedAt.x}, y = {clickedAt.y}</div> <div>Clicked on: x = {clickedAt.x}, y = {clickedAt.y}</div>
<div> invitationCode = {gameID}</div>
</div> </div>
{renderGameBoard()} {renderGameBoard()}
......
...@@ -23,9 +23,18 @@ io.on('connection', (socket) => { ...@@ -23,9 +23,18 @@ io.on('connection', (socket) => {
console.log(name); console.log(name);
console.log(id); console.log(id);
players[socket.id] = {username: name, playerID: id}; const gameID = generateGameID(); // generate a random gameID for the game when connecting
//io.emit('connected_to_match', {playerID: joinedPlayers}); firstPlayer = createNewPlayer(name, id, socket.id, gameID);
newGame = setUpNewGame(gameID, firstPlayer);
// Send the gameID back to the client
socket.emit('game_setup', { newGame });
players[socket.id] = firstPlayer;
printGameInfo(gameID);
socket.on('disconnect', () => { socket.on('disconnect', () => {
console.log(`Client with id ${socket.id} disconnected`); console.log(`Client with id ${socket.id} disconnected`);
...@@ -33,9 +42,62 @@ io.on('connection', (socket) => { ...@@ -33,9 +42,62 @@ io.on('connection', (socket) => {
delete players[socket.id]; // Remove player data delete players[socket.id]; // Remove player data
}); });
socket.on('send_message', (data) => { socket.on('join_game_as_second_player', (data) => {
console.log(data); // first step of this is to see that the invitation code used is actually a game that exists
io.emit('receive_message', data); // Broadcast the message to all clients var gameID = data.gameID;
var game = findGame(gameID);
console.log("tried to join with this gameID: ", gameID);
if (game) {
console.log(`Client with name "${players[socket.id].username}" is added`);
// // Take out the game that was generated before deciding to join an existing game
// var p = players[socket.id];
// var toBeDeletedGame = p.gameID;
// var deleteIndex;
// for (let index = 0; index < games.length; index++) {
// if (games[index].gameID === toBeDeletedGame) {
// deleteIndex = index;
// }
// }
// delete games[deleteIndex]; // shit way of doing it but eh we refactor later yuh, deleted the game tho
// we want to edit the data directly so we use the index of the game and edit it that way
// first though, assign the player to the new gameID
players[socket.id].gameID = game.gameID;
// then assign this player as the second player
for (let i = 0; i < games.length; i++) {
if (games[i].gameID === gameID) {
games[i].secondPlayer = players[socket.id];
}
}
printGameInfo(gameID);
// send info about the game to the player that joined with code
io.to(socket.id).emit('ack_join_second_player', {
joined_success: true,
otherPlayer: {playerID: game.firstPlayer.playerID,
username: game.firstPlayer.username,
socketID: game.firstPlayer.socketID
},
gameID: gameID,
});
// emit to the first player that another player has joined!
io.to(game.firstPlayer.socketID).emit('second_player_joined_game', {
otherPlayer: {
playerID: game.secondPlayer.playerID,
username: game.secondPlayer.username,
socketID: game.secondPlayer.socketID
}
});
} else { // emit that the code is wrong and shit is fckd!
console.log("Game didn't exist");
io.to(socket.id).emit('ack_join_second_player', {
joined_success: false,
});
}
}); });
socket.on('placed_piece', (data) => { socket.on('placed_piece', (data) => {
...@@ -91,6 +153,94 @@ function addToBoard(xPos, yPos, playerSymbol) { ...@@ -91,6 +153,94 @@ function addToBoard(xPos, yPos, playerSymbol) {
// BOARD GAMEPLAY SOCKET STUFF EEP EEP EEP // BOARD GAMEPLAY SOCKET STUFF EEP EEP EEP
// YAAAS // YAAAS
var active_games = []; var games = [];
var players = []; // players currently connected and hooked into the chiral network var players = []; // players currently connected and hooked into the chiral network
/*
board structure :)
{
active: true/false
gameID: theAssignedID
firstPlayer: player1
secondPlayer player2
whoseTurn: p1/p2
boardState: []
}
player structure :O
{
socketID: idFromSocketConnection
playerID: firebaseID
gameID: assignedToThisGame
username: player name
color: string-hexvalue //todo
}
*/
function createNewPlayer(name, id, socket, game) { // add color;
return { socketID: socket, username: name, playerID: id, gameID: game };
}
function generateGameID() {
return Math.random().toString(36).substring(3, 9).toUpperCase(); // Simple example of a unique ID generator
}
// Underlying ID assigned to the player, if the gameboard times out it could reconnect with this!
function generatePlayerID() {
return Math.random().toString(36).substring(3, 10).toUpperCase();
}
function setUpNewGame(ID, firstP) {
var newGame = {active: false,
gameID: ID,
firstPlayer: firstP,
secondPlayer: {},
whoseTurn: firstP,
boardState: []
};
games.push(newGame);
return newGame;
}
// when a player joins the game
function addPlayerToGame(gameID, secondP) {
for (let i = 0; i < games.length; i++) {
if (games[i].gameID === gameID) {
game = games[i];
game.secondPlayer = secondP;
break;
}
}
}
function startGame(gameID) {
for (let i = 0; i < games.length; i++) {
if (games[i].gameID === gameID) {
game = games[i];
game.active = true;
break;
}
}
}
function findGame(gameID) {
for (let i = 0; i < games.length; i++) {
if (games[i].gameID === gameID) {
return games[i];
}
}
}
function printGameInfo(gameID) {
for (let i = 0; i < games.length; i++) {
if (games[i].gameID === gameID) {
console.log(games[i]);
break;
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment