ESA DestinE AAS - Demonstrators
Game Demonstrator with Godot Engine

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

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:
Go to earthdatahub website: https://earthdatahub.destine.eu/
User needs a valid Destination Earth account
Go to ‘Account Settings’
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 (fileproject.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
anddim_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, oriam
for genuine DestinE IAM orno
to disable user access verification (for game app testing purpose),logging_level
: logging level amoungstdebug
,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 bodieswater_geoserver_layer
: WMS layer to use to obtain water bodies map image,levelize_threshold
: height in meters of each level when digitizing terrain elevationtiles_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 datahda_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 thenpx
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 theexport
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).