So whats the plan? Express? How do I WebSockets, client connections, rooms, server-side, client-side, i hit my face with both open hands in despair again. I imagined all the work that will need to be done BEFORE actually making any game or “app”. Quick google for “multiplayer game server node js” revealed to me couple of bootstrap options.
Pomelo (which I believe I saw earlier somewhere) looked mature, but after opening their GitHub issues It was clear to me that I wouldn’t fit their community - most of the issues were in Chinese.
Lance was next in line. Went through the features list - lookin’ good! But let’s continue the research.
Then I found Colyseus. I admit, I fell for the “match-making” point from their feature list. This feature could probably be done with more or less time in other engines too. It has a client-side JS implementation in different repo, It also has client integration with Unity3D and Construct2. Colyseus is new, right now at version 0.5, still being worked on… Ah, what the hell! Let’s clone that example and see how it works. I don’t have that much time to prepare a full-blown research with pros and cons of each library.
So in couple of hours I managed to make a working chat room. My example project uses Webpack with webpack-dev-server for the client-side code, to speed up development and manage my js/html code better. I try to follow all the rules and good practices now, can’t allow myself to write spaghetti code anymore. So I start writing with ES6 and use neatly arranged modules. After a minute I hit that roadblock again:
import something from 'path' ^^^^^^ SyntaxError: Unexpected token import
Node doesn’t understand
Personally I disagree with transpiling node, its not there yet because it is complicated to properly implement https://t.co/lKyaFygFGm— Lizzie Davison (@LizzieDavison1) August 31, 2017
tl;dr - use
module.exports, leave transpiling for the client-side code.
So I did. And with clean heart I could continue.
What kind of game I could create now? Recently I’ve designed Monstrous Escape, I’d love to play this game online with someone :) But first things first, let’s start smaller please. Don’t let that be ANOTHER project with overflowing list of TODO features never-to-be-finished… How about a simple “war” cards game. The rules are simple, every player is dealt with cards, each round they show their topmost card on the pile, the player with higher card takes all cards until one player is left with no cards in his deck. The game is really simple and really boooring to play in real life, but in code it manifests itself as an already thick layer of complexity. There are a bunch of object here: Player, Card, Deck, Pile. Those last two are actually the same thing, Containers of cards, but both will be rendered differently in the browser. There should also be a round cycle.
I got my notebook and drew out some basic interactions between objects in any state of the gameplay. I want it to be universal. It should be easy to use that “cards API” to create any kind of cards game - using classic set of cards or any custom tabletop/boardgame kind of game. Maybe this tiny API will evolve into “tabletop API” someday? Tabletop Simulator JS! … one can dream.
Stop! React time.
So I’ve got this chat module, which works but is essentially still a spaghetti code. A tiny perfectionist inside me wonders “what could we do to make it better and scalable?“. A rhetorical question, he already knows the answer. A colleague from our office talked a lot about React and Redux recently. I practiced some React days ago but never gotten to use Redux. I needed to store every piece of information in one neat package, only one. No more storing variables around many different classes, modules, files. With React, I can write “dumb” components, whose job is only to visually present the data from state, and with Redux I’m managing the state itself. Before I go any further I just had to re-write what I currently had - tiny chat app - and use React/Redux combo.
I opened redux.js.org and before finding installation instructions I noticed that they have a big list of free “Getting started” videos. Watched them all, feels good.
For now I’m sure that I’m going to use React on the client-side of the code. On the server-side Colyseus already has some kind of state machine that I could use. I just used my recent knowledge of reducers and wrote a couple of those to manage a list of: players, cards, containers and various game state variables…
After couple of days I realized that It was a bad idea.
RTFM or ask for help…
I’ve lost a couple of days trying to understand, why some state changes were not sent to the client. Colyseus has a
setState() function, which I assumed is to be used when I want to update the whole state. So I wrote my server-side reducers logic all around it… and nothing happened. Only the initial game state was sent to the client, only once the client joined the room. Nothing else.
I have a tendency to just go boldly into the example code, without reading any documentation. I just go back to it, when a function name is not fully self-explanatory or when I know I need to achieve something, but I don’t know what function to use. This time I made the same mistake. Unlucky for me, Colyseus is pretty new and they don’t have a full documentation on it, only some example code and tutorial. But my code still didn’t work, so I went to their gitter chat as my last resort:
setStateshould be used only once, whenever you use it, the client will receive only one big
"add"operation. To receive detailed information the state should be mutated
MUTATED! That’s my problem, I manipulated server-side state the same way I did with Redux on the client - “replace, don’t mutate”… Changing 1/4 of my server code to be mutations finally gave me some results. In the below video you’ll see one client - host, the other client is off screen. Only the host can start the match, but both players can increase or decrease that silly test number.
To be continued.
See you later.