Monday, December 6, 2021

Making a turn-based game: Getting started with boardgame.io

For my game, I went looking for a framework that would handle some of the boring parts and free me up to focus on the game mechanics and logic. It didn't actually take much hunting to stumble upon boardgame.io, which I was surprised to discover handled just about everything I wanted.

In this post, I'll talk a bit about my choice of engine and the steps I took to get started.

Architecture

The boardgame.io framework has several features I appreciate:

Language and libraries

  • Designed to run on NodeJS, which I'm already familiar with
  • Includes React components
  • Includes TypeScript type bindings

Features

  • State synchronization between server and clients
  • Client-side prediction of next move on public state, to speed up the experience
  • Automated client information hiding
  • Game state machine library
  • Debugging UI
  • Integration with a couple of backing stores
  • Rudimentary multi-game server and client lobby

The framework was designed with Heroku in mind, but I was able to get it working on a shared DreamHost server. For the remainder of this post, I'll go into that process (which involved a lot of dead-ends, but eventually worked!).

Getting started with a boardgame.io project

For this project, I set up a pretty standard Node project:

  • installed nvm using the wget directions
  • nvm install 12.22.7 to sync with version required by DreamHost for compatibility with Passenger Phusion
  • configured the project to use TypeScript
  • Started setting up the boardgame.io tic-tac-toe tutorial

By the end of this stage, I had the following files set up:

tsconfig.json ``` { "compilerOptions": { /* Language and Environment / "target": "es6", / Set the JavaScript language version for emitted JavaScript and include compatible library declarations. / "lib": ["es2015"], / Specify a set of bundled library declaration files that describe the target runtime environment. */

/* Modules */
"module": "commonjs",                                /* Specify what module code is generated. */
"rootDir": "src",                                    /* Specify the root folder within your source files. */
"moduleResolution": "node",                          /* Specify how TypeScript looks up a file from a given module specifier. */

/* Emit */
"outDir": "build",                                   /* Specify an output folder for all emitted files. */

/* Interop Constraints */
"esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
"forceConsistentCasingInFileNames": false,           /* Ensure that casing is correct in imports. */

/* Type Checking */
"strict": true,                                      /* Enable all strict type-checking options. */

/* Completeness */
 "skipLibCheck": true                                /* Skip type checking all .d.ts files. */

} } ```

tslint.json


{
    "defaultSeverity": "error",
    "extends": [
        "tslint:recommended"
    ],
    "jsRules": {},
    "rules": {
        "no-console": false
    },
    "rulesDirectory": []
}

One note about the boardgame.io tutorials: they'll mention using parcel-bundler, but it's deprecated for parcel.

Next on the list was to set up React.

  • npm install react (which gave me v17.0.2)
  • npm i --save-dev @types/react
  • add "jsx": "react" to compilerOptions in tsconfig.json
  • npm install react-dom
  • add dom to lib in compilerOptions
  • add "include": ["./src/*"] as a peer to compilerOptions (note: src/* is not the same and will result in failure to find modules)

This gets us halfway to a working solution, but to serve from DreamHost, we'll need to have a JavaScript program that Node.JS can run and a program (likely one JS file) that can be vended to the client. Configuring that is the next step.

No comments:

Post a Comment