Online Card Game with Node.js and Socket.io – Episode 5

This post is 4 years old. (Or older!) Code samples may not work, screenshots may be missing and links could be broken. Although some of the content may be relevant please take it with a pinch of salt.

I am in the final stages of putting this game together - I'd say that at this time I have a working demo that encompasses of the following:

  • Auto-creation of a test room that can have one table
  • Auto-creation of a test table that can have 2 players
  • Players need to enter their names to join a table
  • Basic gameplay is fully implemented but additional rules are missing
  • If the pack of cards get emptied, the discard pile is reshuffled and will become the new pack
  • Messages are passed in between the connected clients to indicated end of turn events

Before I get into the details of describing some cool JavaScript code all behind this, you may be wondering where/how do I test all this. I have a local test environment (running a heavily customised Ubuntu server) but I have also rolled this project out to a small amount of friends - and my choice was to use Amazon EC2. If you haven't used the EC2 environment before -- it allows you to run your own virtual machine in the cloud - accessible everywhere, and the best thing is that for new users, it's free for a whole year. There is a lot of material out there that can help you to setup a virtual server with the necessary options, as well as recommendations on how to setup the virtual machine to run a node.js project. I found this post by Ben Nadel the most useful.

Let me share a screenshot of the application now (compare it with the screenshot shown in episode 2 of the article series) of the gameplay and the GUI (or should we say, WUI?).

The initial screen that players see - both have got 5 cards assigned and the first card in the discarded pile is placed automatically.

During the gameplay, you can see how many cards the other player has in their hand.

And finally, announcing the winner.

You have probably noticed the "It's your turn" and "It's your opponent's turn" messages, it's a great addition to the game as before the only indication a player had whether it's his/her turn or not was to either see the discarded pile updated or the remaining cards counter decrease by one (indicates that the opponent draw a card) - none of these are pretty, so a solution had to be made. Without anything further to do, I give you the Messaging module - a new JavaScript class that essentially sends messages to players connected to the websocket server, with some extras added - it can:

  • Send a message to every player
  • Send a message to every player but the player who is initiating the conversation
  • Send a message only to one player
Messaging.prototype.sendToAll = function (event, message, socket, player) {
for (var i = 0; i < player.length; i++) {
socket.sockets.socket(player[i].id).emit(event, message);
}
};

Messaging.prototype.sendToAllButPlayer = function (
event,
message,
socket,
players,
player

) {
for (var i = 0; i < players.length; i++) {
if (players[i].id != player.id) {
socket.sockets.socket(players[i].id).emit(event, message);
}
}
};

Messaging.prototype.sendToAPlayer = function (
event,
message,
socket,
players,
player

) {
for (var i = 0; i < players.length; i++) {
if (players[i].id == player.id) {
socket.sockets.socket(players[i].id).emit(event, message);
}
}
};

And the server calls the appropriate functions in the draw and play methods.

messaging.sendToAPlayer(
'turn',
{ myturn: false },
socket,
room.players,
player
);
messaging.sendToAllPlayersButPlayer(
'turn',
{ myturn: true },
socket,
room.players,
player
);

The frontend is always listening for the turn message to be emitted by the server and acts accordingly:

socket.on('turn', function (data) {
if (data.myturn) {
$('#progressUpdate').html("It's your turn.");
} else {
$('#progressUpdate').html("It's your opponent's turn.");
}
});

And there you have it, messages are being sent between client(s) and the server, making the necessary updates.

The project is nearly finished and once the code is cleaned up, I will commit the codebase to GitHub, however there are still a lot of things to do. I need to implement Room/Table creation, additional rules for the card game (there are a number of action cards, which, upon played, allow the player to make special requests - i.e. if an Ace is played, the player can ask for a suit, and the next player has to either play a card of the requested suit, or counter with another Ace and make a new request). Also, the frontend needs some makeover. Until next time!