Game state and user actions. ARTris — Part #5

Dolapo Toki
Artris Code
Published in
4 min readFeb 17, 2018

This article is part #5 of a series of articles on ARTris. A multiplayer real-time 3D AR Tetris game built with ARKit, Node.js, and Firebase. If you’re new to this series, we recommend you begin with the introduction. Fork the iOS Client and the Game Engine repos to start experimenting.

Game running on Iphone 7+

Today we dive into the components that make up our game-engine, what happens when a player takes an action, and how we calculate the next state for each game session.

Bird’s eye view of the engine

Board, Block, Engine, and Gesture are the four building blocks of our game-engine.

  • Block is the falling block that a player can move or rotate by interacting with the iOS client. A Block knows about its position in the game coordinate system, and it can check for collisions.
  • When a Block falls, it becomes part of the Board. The Board is just a coordinate space where we keep track of the fallen Blocks.
  • Engine is responsible for updating the game state by interacting with the Block. Engine is the middle man between the Block and the Gesture components.
  • Gesture subscribes to the Firebase events for move and rotation actions of each player and communicates the player’s intentions to the Engine.

Engine and Gesture coordinate the events in the game-engine and are responsible for communicating the next state to Firebase. The main-loop of our game-engine is in Engine (no surprises here).

In the rest of this article, we focus on the relationship between the Gesture and the Engine.

Engine

run is the main-loop of the game-engine where we update the game state and dispatch the pending actions.

In run, we invoke the processQueue function which iterates through the player actions and updates the orientation of the Block while enforcing the game constraints.

run or the main-loop

In the above snippet, we pass a callback function to move. After the position of the block is updated the callback function is fired which in turn emits the new game-state to the Firebase engine. We will cover the newEngineState event when we cover the index file later in this article.

processing the guesture queue

processQueue function is a large switch statement that depending on the action type invokes either move or rotation function on the block. It also calculates the parameters based on the action direction (← → ↑ ↓).

Gesture

The gestureListner module implements the Pub/Sub pattern by emitting events that the game cares about to all subscribed listeners. this implementation requires all subscriber to pass the event channel they are interested in and an asynchronous callback method to execute when the event is published.

The player actions are added under game-session/:game-session-id/:player-id/gestures in Firebase realtime database. Under gesturenode are the action types move and rotate where we push the action’s direction.

Firebase structure

When initializing the game engine, we pass in the path to the gesture node of each player to the gesture listener module.

This module listens for new player actions added under move and rotate nodes of each player and emits them to a new channel. We later subscribe to the this channel to push the player actions to the processQueue . By doing so, Guesture acts as a mediator and decouples Engine from Firebase.

Listening to Firebase events and publishing them under a new topic

Finally when we create a new game session we subscribe to the player actions we are interested in and push them into the gestureQueue .

create a new game session

To recap, when the game engine starts, we subscribe to Firebase to receive the new game sessions. As part of initializing the game session, we create a gesture listener object that subscribes to Firebase for all possible player actions. It emits each action to a different channel. We then subscribe to the channels we are interested in to push the player actions to gestureQueue.
The main-loop in the engine runs in a fixed interval and in each execution, it processes all the player actions to create the next state. This new state is then emitted, processed and sent to Firebase.

We know part 5 kind of came late.

Thanks for sticking with us ❤️

--

--