Skip to content

Overview

The goal is to create a multiplayer game, which is easy to maintain and extend. Compared to single player games, the architecture of multiplayer games is a little more complex. In this project we tried to find a balance between our ambitious game design ideas and the limitations set to us by the complex multiplayer architecture.

This handbook is structured in a way that you can read it from top to bottom, but you can also jump to a specific sections if you want to. The following sections will give you an overview of the architecture of the game.

Conception

As we didn't have prior experience with PhaserJS project structure, we were inspired by other phaser-built games. We tried out many different structures in small trial-and-error projects, finally leading to the creation of this project structure.

This lead to us having to refactor the project structure several times to meet our needs. This is why we were not able to provide a detailed project conception in advance before writing the first LoC.

Frameworks

  • Phaser: For the levels we are using Phaser which is a game engine for creating 2D games.
  • Vue: We want to create a responsive user inferface which is why we are using a Web Framework.
  • Tailwind CSS: For easy styling we are using Tailwind CSS.
  • Colyseus: We use Colyseus to enable multiplayer functionality.
  • ESLint: Linting is used for Code quality.
  • Vitest: For Unit-Testing we us Vitest.

Project Structure

For this project we are using a monorepo. This means that all code is in one repository and types and classes can easily be shared between client and server.

The project is structured as follows:

  • client: Contains all client side code.
  • server: Contains all server side code.
  • shared: Contains all shared code between client and server.

Running the Game

Prerequisites

Before you start, make sure you have Node.js installed on your machine.

Before running the game for the first time, you need to install all dependencies. To do this, run the following command in the root directory of the project:

bash
npm install

If you are running into install issues, try to install the dependencies that can be found here.

Running the game requires both the server and client being started. Doing this requires two terminal windows, since this process needs to be simultaneous.

Starting the Server

To start the server, navigate to the server directory using following command:

bash
cd server

Then start the server through:

bash
npm run start

Starting the Client

In a new terminal window, navigate to the client directory:

bash
cd client

Then start the client:

bash
npm run start

The game should now be running, and you can access it in your browser. If the port is not already in use, the client will be available at http://localhost:8080. Otherwise, look at the output of the client terminal and copy the correct URL to your browser. It is recommended to use a chromium based browser such as Chrome, Brave or Arc.

INFO

Since this is a multiplayer game, you need to open the game in two different browser windows. Note that both windows need to be in focus, otherwise the game of any inactive window will be paused and the physics simulation will not work correctly.

Linting

Running linter manually:

bash
npm run lint

To fix linting issues automatically, you can use the following command:

bash
npm run lint:fix

TIP

It is recommended to configure your IDE to automatically fix linting issues on save and to run the linter before committing changes.

Unit Tests

To run the tests, you need to navigate to the root directory of the project and run the following command:

bash
npm run test

Starting the Vitest Web-Interface:

bash
npm run test:ui

See coverage of the tests:

bash
npm run test:coverage

More information about unit testing can be found in the tests section.

Tile Extruder

When using tilesets, it is recommended to use a tile extruder to avoid tile bleeding.

Use the following command to extrude the tileset:

bash
npx tile-extruder --tileWidth 32 --tileHeight 32 --margin 1 --spacing 2 --input <your_tileset> --output <tileset_output>

Make sure to set the correct margin and spacing values when importing the tileset into Tiled.