During the Real-Time Web course, we were asked to build a real-time application.
Goals of this course:
- deal with real-time complexity;
- handle real-time client-server interaction;
- handle real-rime data management;
- handle multi-user support.
I've never really worked with socket.io before. I did do a project containing socket.io but I was responsible for login/signing up (with passport.js). This project will be the first project implementing sockets from scratch. I'm excited to learn more about it.
I started with a basic setup of the server and client. A user can enter a username and then chat with other users.
// server side
io.on('connection', (socket) => {
console.log('user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
socket.on('CHAT_MESSAGE', (msg) => {
io.emit('chat message', msg);
});
});
// client side
const socket = io();
const messages = document.querySelector('ul');
const form = document.querySelector('form');
const input = document.querySelector('input');
form.addEventListener('submit', (e) => {
e.preventDefault();
if (input.value) {
socket.emit('CHAT_MESSAGE', input.value);
input.value = '';
}
});
socket.on('CHAT_MESSAGE', (msg) => {
const li = document.createElement('li');
li.textContent = msg;
messages.appendChild(li);
});
I found this to be fairly easy (I clearly didn't know what was coming yet..).
I started this week by brainstorming about what I wanted to build. I eventually came up with the idea of a Tic Tac Toe game. I also wanted to implement rooms, and a chat feature in those rooms, so users could chat with each other while playing the game.
I found it quite difficult to implement rooms. I had to do a lot of research to get it working. It took the whole week, but I eventually got it working ;)!
I would like my Real-Time application to have the following features:
-
Users must be able to choose their own username
-
Users must be able to create a room
-
Users must be able to join a room
-
Users must be able to chat with other users
-
Users must be able to play a game of Tic Tac Toe
- System must be able to only allow Tic Tac Toe to be played when there are min. two players in a room
- System must be able to randomly select two players from a room
- Users must be able to see the game board and the current player (even if they join the game later)
- Users (that play) must be able to place a marker on the game board, other users can't place a marker
- Users must be able to see who won the game
- Users must be able to restart the game
After having trouble with implementing the rooms, I didn't know if I could finish the rest of the project in one week. But when trying to implement other features, I started to understand socket.io more and more.
When creating the tictactoe game I encountered some problems. One of which was that when a user joined the room when there was already a game going on, the user would not be able to see the game. I fixed this by saving different variables in the server.
if (!rooms.hasOwnProperty(roomId)) {
rooms[roomId] = {
users: {},
selectedUsers: [],
currentPlayer: null,
currentPlayerSocketId: null,
gameData: {
x: null,
o: null,
cells: ['', '', '', '', '', '', '', '', ''],
winner: null
}
};
}
One of the conditions was that an api had to be added. I chose the GIPHY api. Users can send GIFs in chat, and the app sends a random winner or loser GIF to the winner and loser.
The final result can be found here.
A data life cycle refers to (a visual representation of) the different stages involved in the transfer of data over a network socket.
The life cycle of this application starts at the homescreen, where users have the option to either create a new room or join an existing one. This user data is exchanged between the client and server through a fetch to /user/:esi
. When trying to join a room with a username that's already present in the room, the server will send back an error message.
Upon room join, a loader will be shown, then the room. The room will show the current players in the room, the chat and the start game button. When the room contains 2 or more users, the start button can be clicked and 2 players from the chat will randomly get selected. These 2 players will be able to play a game of Tic Tac Toe. The other users will be able to spectate the game. When the game is over, everyone will be able to clear the game and start a new one.
Event name | Description | Emit | Listen |
---|---|---|---|
JOIN_ROOM |
Sends user info to the server | Client | Server |
ERROR |
Sends error message to the client | Server | Client |
LOADER |
Shows loading screen | Server | Client |
USERS_IN_ROOM |
Sends info of all users in room to the client | Server | Client |
SHOW_BUTTON_GAME |
If room.size >= 2, shows start game button | Server | Client |
HIDE_BUTTON_GAME |
If room.size < 2, hides start game button | Server | Client |
MESSAGE_IN_CHAT |
Sends message | Both | Both |
START_TYPING |
Sends typing message | Both | Both |
STOP_TYPING |
Removes typing message | Both | Both |
SHOW_GAME |
Shows game board | Server | Client |
SHOW_GAME_PLAYER |
Allows current player to interact with game board | Server | Client |
REMOVE_GAME_PLAYER |
Removes ability to interact with game board | Server | Client |
SHOW_STARTED_GAME |
Shows game board with saved data (for users that join later) | Server | Client |
SELECTED_USERS |
Sends selected users to the client | Server | Client |
CELL_CLICK |
Sends cell index to the server | Client | Server |
GAME_OVER |
Disables game board and show clear game button | Server | Client |
GAME_OVER_WINNER |
Sends winner/loser GIF to players | Server | Client |
USERS_IN_ROOM_DELETE |
Sends updated users in room to the client | Server | Client |
CLEAR_GAME |
Clears game board | Server | Client |
- Choosing your own username
- Creating/joining a room
Chat
- Sending a message
- Sending a private message (
/msg [username] [message]
) - Sending a GIF
- Seeing who's typing
Tic Tac Toe
- Starting a game (ONLY when the room has a minimum of 2 users)
- Playing a game (ONLY when you're selected)
- Restarting a game (ONLY when the game is over)
- Restart option will also be displayed when a playing player leaves (a message saying this player left will also be displayed)
- When the game is over, the winner and loser will receive a GIF