ESA DestinE AAS - Demonstrators
Game Demonstrator with Godot Engine

Image godot for dev

Manual for developers

Goal of the demonstrator

Play with DestinE data:

  • Create a gamified scene from the chosen location

  • View and interact with the scene

  • Set up a gameplay based on DESP data, to raise awareness about climate change

Components overview

Overview

The main components are:

  • the Web game application that the final user opens in its web browser,

  • the server that provides data to the web app, and picks original from the DestinE data APIs,

  • the geoserver that provides water layers to the main server.

Prerequisites

EarthDataHub

In order to import DEM data (terrain elevation model), we use EarthDataHub API that needs registering:

  1. Go to earthdatahub website: https://earthdatahub.destine.eu/

  2. User needs a valid Destination Earth account

  3. Go to ‘Account Settings’

  4. Get or create a personal access token

This is needed in case of using the topo library module and the game server.

Developpement

Environment

Game app

  • Install Godot 4.3 according the OS you are using: https://godotengine.org/download/archive/4.3-stable/
    The prefered OS used by dev team is Windows.
    As per the Godot documentation: Extract and run. Godot is self-contained and does not require installation.

  • Get the project source code from its git repository,

  • Launch Godot Engine application,

  • Open game app project from the game folder (file project.godot)

Server

Specified dev and prod OS is Linux but this server component is supposibly portable as it is a Python based web server.

  • Install Python 3.12.x (a venv can be used). For linux, any standard and fairly up-to-date distribution will provide installation of 3.12.*. Refer to the documentation of your distribution to use the proper package manager.

  • Get the project source code from its repository: git clone https://github.com/atosfordestine/game

  • Install python dependencies using requirements.txt in your project working copy using pip: pip3.12 install -r server/requirements.txt

Run

Game app

Go through Godot documentation (https://docs.godotengine.org/en/stable/) to learn how to use it!
The game/Content/Data/config.json may need to be modified in parameter game_server_ip_port to connect to your the server instance of your choice.

Server

A server dev can be run with something like in the server folder: EARTHDATAHUB_API_KEY='<your key>' DESTINE_GAME_SERVER_FOLDER=<path to the /game/game repo> DESP_PASSWORD=<your DESP account password> DESP_USERNAME=<your DESP account username> PYTHONPATH=../lib uvicorn main:app --port <your local port> --host <your public IP> --workers 4
The server/dev.sh is a launch script that does the same thing – it needs to be filled with your proper values.

Game app code structure

This documentation provides an overview of the folder structure and the purpose of each directory within the project.

Structure Overview

/addons /Application     /Ressource /Assets /Content /Game /Scenes /Template /UserInterface

1. /addons

This folder contains various Godot extensions that enhance the engine’s functionality. These extensions can add new features, tools, or functionalities to the project, aiding development. At the moment the extensions we use are:

  • “EasyCharts”: it is used to draw IPCC scenario trajectory lines and player-decision scenario lines on a chart,

  • “jwt”: is used to decode token data from DestinE IAM.

2. /Application

The Application folder contains data essential for continuity in the game. It stores “resource type“ data used thoroughly in the game and saved on the user’s computer. It typically contains user settings, saved games, and other persistent data that ensures continuity when the player returns to the game.

3. /Assets

This folder contains all game assets typically used, including but not limited to:

  • Textures (e.g., background images)

  • Sprites (e.g., sprites, character (desti) sprites)

  • Font (e.g., in-game typography)

  • Tilesets (e.g., game objects, environments)

These assets are essential to the visual and auditory experience of the game.

4. /Content

The Content folder includes game mechanics-related assets, readable content for players and Server-related scripts that might fetch more information.

  • Files stored in the data subfolder contain sensible information used by the core mechanics and level design, influencing how the game is played.

  • Intel cards are readable pieces of information or narrative elements within the game that the player can discover.

  • Server.gd and Utils.gd are scripts that deliver or transform content for other scripts.

5. /Game

This folder contains scripts related to gameplay logic that can be used in various parts of the game, without being specific to a particular scene.

  • GameManager: A helper script that manages the overall game flow, accessible throughout the game.

  • RoadMapCanvas: A script responsible for managing the guessing part of the game, essential to the gameplay of the Mystery Mode.

6. /Scenes

This folder contains all the game scenes, each representing a different part of the game.

  • TitleScreen: The opening screen of the game.

  • MapGuesser: The scene where players interact with the guessing mechanics typical of the Mystery Mode.

  • MapScene: The main scene where the game is played.

  • Ending: The closing scene, displayed at the end of the game.

7. /UserInterface

This folder holds scripts that handle the user interface (UI) interactions. These scripts often work in conjunction with the scenes from the Template folder.

  • Some scripts manage UI elements, ensuring smooth player interaction.

  • Other scripts act as managers or event handlers that control UI components across the entire game.


This structure ensures that different types of game data, scripts, and assets are well-organized and accessible for development and iteration.

Map creation

Coordinate retrieval is handled by several functions that detect the scene that sent them, then convert them to EPSG3857 if required.
If there is a problem loading the scene, an error message is displayed and the scene_choice.tscn is loaded again.

func set_tile(osm_data, climate_code, data_dict)

This function creates the game scene.
This function traverses the file osm_data, representing a matrix, containing the classification of each part of the treated area. For each element of the matrix, one or more tiles (depending on terrain elevation) of the type corresponding to the given class and climate, with climate_code and data_dict, are created.
Finally, depending on the class of the tile, an element such as a tree, building, etc. is added.
When, at a given position, the number of tiles created exceeds a certain level, a mountain is placed in its place.

func add_points_of_interest()

This function displays points of interest in the scene (water, forest, city, farmland, etc.).
These points of interest are buttons that display an information popup when the user clicks on them. This popup contains various pieces of information about forests, towns, fields, etc. Their text changes as the game progresses. To display these points of interest, we first scan the scene to detect groups of objects (a group of trees represents a forest, for example). To do this, for each object, we collect the positions around it and count the number of objects of the same type. If the number of identical objects around it exceeds a certain percentage, its position is saved. Then choose a position at random from those recorded. If no group exists for an object type, then the point of interest is considered unrepresentative.
This procedure is repeated for each type of object.

Game Mechanics

Map guesser

If the player chose to play in Mystery mode, a random selection will be chosen for him. Before lanching the main game, he will have to find, with the help of a Sentinel-2 image and with the generated scene, where he is. A score will be computed from the distance between guessed and correct location:

score(D) = 5000 \times e^{-\frac{D}{800}}

D is the distance between guessed and correct location

Game progress

General

For each step, after clicking on a bubble that provides the player with information about the environment (points of interest), the player is presented with a choice of actions by Desty. The player can only choose one action. These actions directly affect the amount of CO2 released into the atmosphere, which will change the scene over the course of the game.

An environmental indicators panel is located in the top right corner of the screen, providing various information such as the temperature difference compared to the pre-industrial era, sea level rise, local temperature, and other indicators in Mystery mode.

For the CO2 calculation, we assume we start in the worst-case scenario from the IPCC. At each step, we add the impact of the player’s action to the current scenario forecast for the next 20 years, then we compare this value to the forecasts of all scenarios and select as the reference scenario for the next step the one with the CO2 value closest to it.

The map is then regenerated to simulate the consequences of the player’s actions. As the temperature rises, the colors of the area slightly yellow. To achieve this result, our tileset has been designed so that the columns are repetitions of the previous columns but with a yellowed hue. We then choose the column with the variable temp_offset, which is equal to the floor of the temperature difference between the current world and the pre-industrial world. The temperature also affects the density of trees in the area; as it increases, more trees disappear.

Actions proposed

Actions are classified according to their impact, we have considered:

  • Big actions (ppm impact > 30)

  • Medium actions (ppm impact > 10)

  • Medium small actions (ppm impact > 4)

  • Small actions (ppm impact > 0)

  • False good ideads ppm impact = 0

On every step we have the choice between 1 medium, 1 medium small, 1 small, 1 false good idea and either a big action or a random action among all the list. The player will always have a big action on first question, and another big action will be proposed either in step 2,3 or 4

Mystery mode changes

Custom evolutions are made for some locations:

  • Ariquemes (Amazonia): Deforestation in a preselected square, can be stopped if player take the action that stops the deforestation

  • Siberian Taïga Forest: Deforestation in a preselected square, can be stopped if player take the action that stops the deforestation

  • Groenland (Arctic): Ice melting in the whole area, linked to the related indicator

  • Nile Delta: Nile Delta flooding

Score computation

At the end of the game, a score is calculated. The score is 100 if the player achieves the best possible temperature : 2.15 °C , 0 if they reach the worst scenario (SSP5-8.5) temperature: 4.41 °C, and proportionally in between.

score(t) = 100 * pow((worst_t - t)/(worst_t-best_t), 5)

where worst_t = 4.41 and best_t = 2.15

Server code structure

This REST API server provides endpoints for the game application to collect data (including climate data) from DESP, compute climate zone, register player score and get player board, and download any resource file from the repository.

Library

A python library is provided and comes with the server. It provides these features:

  • cl_zone: Climate Zone computation, based on climate data vectors

  • copernicus_land: Copernicus Land adaptation layer

  • desp_service: DESP climate data collecting and extraction

  • file_repo: A service to expose file downloading from a repository

  • land: base landuse analysis and classification computation

  • playerdb: A lightweight json file to store and request for players statistics

  • tiles_to_wms: functions to build a WMS service from a XYZ tiles service

  • topo: extract SRTM from earthdatahub and levelize

  • water: water layer got from a geoserver server

Here are the details:

cl_zone (climate zone)

This module provides a climate zone computation implementation of the Koppen algorithm. The input is a set of one 12-value data vector for average temperature for each month starting with January, and a set of 12-value data vector for cumulative precipitation for each month starting with January.

copernicus_land

This module defines the Copernicus landuse data to be used with the ‘land’ module:

  • the categories and the mapping to our own landuse categories.

desp_service

This module connects to DESP data API to collect climate data (temperatures and precipitations) and performs some transformation for climate zone computation. Refer to cds_service module for details.
This module uses the python destinelab package for authent.

Data are converted as follows:

  • the temperatures are converted from Kelvin into Celsius,

  • the precipitation is converted from meter into millimeter and expressed from daily to monthly cumulation precipitations,

file_repo

This module allows returning a file from a local-to-the-server repository, if this file exists.

land

This module defines the base land use categories for our usage:

  • urban: any industrial or urban or artificialized area,

  • crops

  • shrubs

  • forests

  • vegetation: vegetation that is not in the previous categories

  • snow/ice

  • water bodies

  • wetlands

It also provides a base classification function that

  • a given category to color table

  • the pixel class detection is done by selecting the category with the closest RGB color (min distance) (1), (1) To increase performances for the whole processing, the low-level function that performs this detection is written in pure C and wrapped as a Python library in the implementaion.

playerdb

This module uses TinyDB python package to provide a lightweigth json DB to:

  • store player score,

  • search for the closest other player scores and return them.

tiles_to_wms

From a source XYZ tile server, at a specified Z level, an output picture is produced within the input box bounding box (a coords tuple):

  • the XYZ coords of tiles that cover the given bounding box are computed

  • the selected tiles are downloaded from the given source tile server

  • the downloaded tiles are assembled into one unique raster that is at this point covering more than the requested by bbox area

  • this raster is then clipped to match exactly the requested area

topo

To download a piece of terrain elevation model for a given area as a raster, and output this raster in the specified width and height in pixels.

  • get_topo

    • input bbox is bounding box as a tuple of coordinates,

    • the output raster dimension is specified by dim_x and dim_y Digitize a terrain model by layers of a given thickness (in meters)

  • levelize: the input dem raster of elevation values are:

    • recalibrated at 0 for the minimum altitude in the scene,

    • levelize at level_height parameter

water

This module enables to download from a geoserver a raster picturing the water bodies in a given area

  • get_water_raster

    • input src_url is the geoserver url to request for and recover data

  • analyze_water_raster analyze the input raster to select pixels above a threshold value and consider as water

Server endpoints

The server currently provides these endpoints to be used by the game app:

/climate_zone

This endpoint takes as inputs

  • either a bounding box (4326), and an optional year to compute the climate zone based on the climate_zone library. In this case, the computed climate zone is returned as well as the 2 vectors of the 12 values (12 months) of temperatues and precipitations that were found for this area.

  • or 2 vectors 12 values (12 months) of temperatures and precipitations. In this case, the climate zone will be computed straight from these data.

/classification_v2

This endpoint produces a matrix of classification and topography from the given bounding box. takes as inputs a bounding box (4326), and dimensions for the output matrix. It uses the functions from the tiles_to_wms, land and topo modules. Note: the earthdatahub server provides data only above the 60° north latitude, if not available the elevation 0 is set for all pixels.

/player_score

Store a pair (‘player name’, ‘player score’) in a playerdb.json. Also return a list of (player name, scores) for the 5 immediatly above and 5 immediatly below the input player score.

/download

Download a file content from the given input file path, if it exist in the server file repository. The repository is defined by the DESTINE_GAME_SERVER_FOLDER env variable.

geoserver

The server classification service relies on a geoserver server offering a WMS service providing tiles of water bodies in grey scale.

Our geoserver instance offers this from a resource file (geopackage containing rivers and oceans representation).

Current database from https://data.apps.fao.org/catalog/dataset/76e4aacc-b89e-4091-831f-63986fe029f9

Configuration

The server comes with a config.json file to configure some items:

  • iam: configure which authentication provider will be used: it can be either ivv for ivv iam, or iam for genuine DestinE IAM or no to disable user access verification (for game app testing purpose),

  • logging_level: logging level amoungst debug, info, …

  • self_url: the public URL where this DestinE climate game is accessible,

  • ivv_iam_url: the URL to access ivv iam userinfo endpoint,

  • copernicus_src_url: the URL to access copernicus storage of landuse tiles,

  • water_geoserver_base_url: URL to access the geoserver service for water bodies

  • water_geoserver_layer: WMS layer to use to obtain water bodies map image,

  • levelize_threshold: height in meters of each level when digitizing terrain elevation

  • tiles_z_level: Z precision when collecting tiles from source terrain classification (finer is slower, 10 seems the good balance)

  • climate_data_file: name of the locally stored grib file when caching climate data

  • hda_url: the URL to access DestinE HDA api,

  • hda_collection: the collection name to request for ERA5 climate data we need (monthly means)

  • topo_url: the URL to access globaldem API,

  • year: reference year to compute climate data for.

IAM Identity and Access Management

Context

DESP applications shall connect with DESP IAM to identify and authorize users prior using any service. Current DESP IAM solution is based on ‘Keycloak’.

Integration

User login shall be performed prior to access the game app. This means that the mail url to access the game app is a redirection to the Keycloak flow that will in the end redirect to the proper game app URL by adding some identification and/or authorization tokens.

Keycloak configuration

A ‘client’ destine-game is configured with the main items:

  • ‘Root URL’ is the main URL to publicly access the game,

  • ‘Valid redirect URIs’ is the URL to actually access the game,

  • ‘Web origins’ is same as redirect.

Implementation

Current implementation is:

  • the Kubernetes ingress rule for the public game URL redirect to Keycloak openid-connect/auth.

  • the Keycloak login page does its thing and then redirect to actual game URL, adding:

    • session_state

    • iss

    • code

Server-side access token ensuring

DESP autorization work flow has 2 steps:

  • DESP authentication provides a DESP access token,

  • DEDL autorization provides a DEDL access token from DESP access token.

Our current workflow is:

  • the game app obtains DESP access token through IAM Autorisation Code Flow, and add this access token to each request to the game server,

  • the game server tries to obtain DEDL access token from the given DESP access token,

  • if the DEDL access token is succesfully obtained, the request is performed and data are returned to the game app.

Image build & running instance

Docker images

In the main folder, they are:

  • Dockerfile.server that builds the docker image running the API server.

  • Dockerfile.game that builds the docker image running the npx local web server serving the game web app (the actual godot game).
    This html5 application is the result of exporting the whole game app from godot editor (https://docs.godotengine.org/en/stable/tutorials/export/exporting_for_web.html).
    The godot app shall be exported in the export folder prior to building the server image.

Some usefull commands

  • sudo docker build -f Dockerfile.server --tag <registry>/game-server:<release> .

  • sudo docker build -f Dockerfile.game --tag <registry>/game:<release> .

Kubernetes deploy

The deploy folder provides Kubernetes resources to install:

  • a deploy for running the game server,

  • a deploy for running the API server,

  • a deploy for running the geoserver server,

  • an ingress for the route to access the game server,

  • an ingress for the route to access the API server,

  • an ingress for the route to access the geoserver server,

  • a pvc to create storage for the API server,

  • a service to access the game server,

  • a service to access the API server,

  • a service to access the geoserver server.

Startup

After initial startup of the server in the Kubernetes cluster, or for an update purpose, the resources from the game folder must be uploaded into the server pod. Doing so the server will then provide a downloading endpoint for the web application to be able to download resource files at run time.
This is done by running the deploy_current_game.sh script in the game folder.

Delivery

This chapter is about delivery of the different artifacts listed or mentionned in this documentation.

Code repository

The whole code repository is released in a public git repository at https://github.com/atosfordestine/game.
This release is extracted from the developers private git repository, hence does not contain any history or files that are not intended to be delivered to final users.

Images & repository

The server, geoserver and app server are packaged as Docker images, archived in a tar file. They are delivered as artifacts in a shared location that is specified during/after delivery.

License

This game is free, it has been developed by ATOS for ESA DestinE. Licensed under the Apache License, Version 2.0 (refer to the LICENSE file).