Fun to program and play
Sockets are connections kept open between a server and client so they can communicate more quickly. Traditional AJAX requests look like this: “client makes a call and server responds.” Sockets are different, because they allow the client and the server to call each other at any time, so unlike AJAX, the server can send messages to the client without the client making a request first. This open connection allows us to create live events, which are great for things like chat rooms, notifications, collaborative web pages, and games.
So how do we set up a socket event? Let’s say we have a game where users fly around in ships and fire lasers at each other. Our server needs to listen for when our users say that they fired a laser and our clients need to listen for when our server says another client fired a laser. So we add a listener for “fire” on the server and on the client. Then when the fire actually happens, our user calls “emit” to tell the server we fired. The server might do something with that data, and then call “broadcast” to tell all the other clients about it so they can handle it. Now all the users with a socket connection know that a user has fired a laser.
So there’s many clients, which client should actually “emit” an event. An easy use case is when a user fires a laser: a user clicks fire, and tells the server about it. That’s easy enough, but what about when a user gets hit by a laser. Who should report to the server that a user was hit?
And what about mutually exclusive events, for instance picking up a health pack when there is only one on the board. Well that’s the same deal.
So some examples of each kind of sharing. In a chat client like Messenger, the origin reports data to say when a user is typing. If you’re ever playing a multiplayer game and it freezes, you might see a message that says “Migrating Host.” That’s because the user the was the host left and it needs to find a new user to be the host for the rest of that game. And Google’s new platform Stadia, which is more like a streaming service, the server actually plays the game. It would kinda be like playing Blackmirror’s Bandersnatch episode but with a lot more input options.
So once a user or host fires off an event, where does that data go?
So if our data is coming in at different times, and we can’t just put it on screen as soon as we get it, what can we do?
Note: You won’t see a whole lot of socket games that have acceleration for these timing reasons. Most games are constant velocity, or if there are multiple velocities, the change is immediate. It’s difficult to correct a user’s position when momentum is involved.
So we’re going to be playing a game with a delay, or one that’s a little jumpy, that probably isn’t the best user experience, right? Well, we can “fix” socket limitations through designing different gameplay or adding animation. For example:
Users might be annoyed that they don’t move immediately when they tap buttons. We can mitigate that by having a thruster animation happen when they push the button, even if the movement happens a little later.
Or if a user doesn’t like that they’re not firing immediately. We could have the ship animate a little charge up effect before the fire happens. We can control how long an animation runs for even when we cannot control how long it takes our data to send through the socket.
An issue in this game is that, when a user spawns, lasers that have already been fired don’t show up right away. We could add an event that shares all the lasers to the user when they first show up but that’s tricky. We would be sharing a large array through the socket. Or we could spawn them in a safezone so the lasers on screen don’t matter anyway, so just don’t show them. Or we could make the login screen be an overlay to the game so the user is already on the game page and is already receiving socket updates while they’re logging in.
Design can solve problems that programming cannot
Okay, so maybe you aren’t an animator, what else can we do to make gameplay faster?
We can try and use the socket as little as possible. This means if an animation doesn’t have to be the same on every screen, like an explosion, then don’t make an event for it. Or if players don’t need to know when others are reloading for the game to be played, then there’s no need to make an event for it, perhaps it can be inferred from a different event too.
For example, and this is more advanced than this game, but maybe you only need to share information to people in your part of the screen, if you’re gonna have a high score board for the whole room, then players on the opposite side don’t need to know your location, they just need the score.
We can try and send as little data as possible through the socket when we do use it. If you already know a player’s name, then the name doesn’t need to be included in every message. Rather than defining strings for event names we can use numbers instead. We can also shorten the names and flatten the objects that we send through the socket.
And once we have the data we want to send, we can send it as a buffer instead.
Some key takeaways to socket games. Think about: