Back to blog

Thursday, June 3, 2027

Building a Simple Spaceship Game Server with Altruist

cover

Introduction: Building a Multiplayer Spaceship Server with Altruist

Developing a multiplayer spaceship server can be a fun and rewarding project. With the Altruist framework, building such games becomes significantly easier thanks to its built-in support for managing players, game rooms, and movement mechanics. In this blog post, we will show you how to build a simple spaceship server using the Altruist GamePortal and ForwardMovementPortal to handle player connections, movement, and room management.

Project Overview

The game is built using Altruist's GamePortal and ForwardMovementPortal. The GamePortal is responsible for managing player connections, room assignments, and game session cleanup, while the ForwardMovementPortal allows players to move their spaceship within the game environment.

Here’s a breakdown of the process:

  1. GamePortal: Manages player connections, disconnections, and room assignments.
  2. ForwardMovementPortal: Handles player movement, such as rotating and moving up within the game.
  3. Setup: Map these portals using the Altruist setup API to create the necessary endpoints and run the game server.

Key Features and Implementation

1. Altruist Game Portal

The AltruistGamePortal<TPlayerEntity> class is at the heart of your game's multiplayer management. It handles player connections, assigns them to rooms, and cleans up inactive sessions.

Available Events

  • handshake: Used to obtain basic information such as your client id and available rooms from the server.
  • join-game: Allows a player to join an available game session.
  • leave-game: Removes a player from the game session.
  • Session Cleanup: Automatically cleans inactive sessions periodically.
public class SpaceshipGamePortal : AltruistGamePortal<Spaceship> {
   public SimpleGamePortal(IPortalContext context, ILoggerFactory loggerFactory) : base(context, loggerFactory)
    {
    }
}

The GamePortal automatically manages game sessions and player connections. By extending this class, you can create your own game portal tailored to the game logic of your choice.

2. Altruist Forward Movement Portal

For handling movement, Altruist provides the ForwardMovementPortal, which enables players to move their ships in the game world.

public class SpaceshipMovementPortal : ForwardMovementPortal<Spaceship> {
   public SpaceshipMovementPortal(IPortalContext context, ILoggerFactory loggerFactory) : base(context, loggerFactory)
    {
    }
}

The ForwardMovementPortal handles the movement input for the player’s spaceship, including actions like rotating, moving up, or engaging turbo speed.

3. Setting Up the Game Server

With both the GamePortal and ForwardMovementPortal defined, we can now configure and map them to endpoints in the Altruist setup. This step makes the necessary WebSocket endpoints available for the client to connect to the game and send movement commands.

Altruist Setup

In your AltruistBuilder setup, you map the portals to the appropriate endpoints. For example:

AltruistBuilder.Create(args)
    .WithWebsocket(setup => setup
        .MapPortal<SpaceshipGamePortal>("/game")
        .MapPortal<SpaceshipMovementPortal>("/game")
    )
    .WebApp() // for websockets we need a WebApp
    .StartServer();
dotnet run

4. Example Usage

Once the server is running and the portals are mapped, clients can connect to the game and start sending movement commands.

Join Game Request

To join the game, the client sends a WebSocket message with the player's username.

Request Payload:

{
  "event": "join-game",
  "name": "Player1"
}

Note:

Optionally, if you wish to place a player in a specific room, or world position:

{
  "event": "join-game",
  "name": "Player1",
  "room": "room_id" // optional, altuist provides a default room for each player
  "position": [132, 148]  // optional, by default the player is placed at (0,0)
}

To handle the response, the client should be prepared for two types of packets:

  1. A SuccessPacket sent specifically to your client.
  2. A SyncPacket containing the newly joined player entity, which is broadcast to all relevant clients.

1. Success Packet

This packet confirms that the player has successfully joined the game.

{
  "header": {
    "timestamp": "generated_timestamp",
    "receiver": "your_client_id",
    "sender": "server"
  },
  "type": "SuccessPacket",
  "status": "success",
  "message": "Player Player1 joined room 123"
}

2. Sync Packet

This packet contains the updated game state, including the new player's position and other relevant properties.

{
  "header": {
    "timestamp": "generated_timestamp",
    "receiver": "your_client_id",
    "sender": "server"
  },
  "type": "SyncPacket",
  "data": {
    "position": [30, 45]
    // ... other changed properties
  }
}

Note:

Use the "receiver" field in the "header" to identify whether the packet is meant for your client. If it's a SyncPacket, ensure you either spawn or update the player in the game world accordingly.


Expected Response (Failure):

{
  "header": {
    "timestamp": "generated_timestamp",
    "receiver": "your_client_id",
    "sender": "server"
  },
  "type": "JoinFailedPacket",
  "status": "error",
  "message": "Username is required!"
}

Sync Movement Request

For moving the spaceship, the client sends WebSocket messages to the /game endpoint. Here’s how to move up or rotate the spaceship:

Move Up Request:

{
  "event": "move",
  "moveUp": true
}

Example Rotate Left Request:

{
  "event": "move",
  "rotateLeft": true
}

The movement service provided by the framework handles the rest, ensuring the spaceship's position is updated in the game world. Once a player's position is updated (synced) each client should be prepared for accepting the sync.

Expected Sync Response

{
  "header": {
    "timestamp": "generated_timestamp",
    "receiver": "your_client_id",
    "sender": "server"
  },
  "type": "SyncPacket",
  "data": {
     "position": [30, 45],
    // ... other changed properties
  }
}

Conclusion: Simplifying Game Development with Altruist

With Altruist, building a multiplayer spaceship server becomes an easy task. By leveraging the GamePortal and ForwardMovementPortal, developers can quickly create and manage game rooms, handle player connections, and implement smooth player movement—all with minimal code.

Check out the full implementation on GitHub and explore how these portals can help you create a variety of multiplayer games with ease.