.. role:: raw-html-m2r(raw) :format: html ESA DestinE AAS - Demonstrators :raw-html-m2r:`
`\ Game Demonstrator with Godot Engine .. image:: img/img_doc_for_developers.png :target: img/img_doc_for_developers.png :alt: 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 ------------------- .. image:: img/overview.png :target: img/overview.png :alt: 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/\ :raw-html-m2r:`
` The prefered OS used by dev team is Windows.\ :raw-html-m2r:`
` 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!\ :raw-html-m2r:`
` 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='' DESTINE_GAME_SERVER_FOLDER= DESP_PASSWORD= DESP_USERNAME= PYTHONPATH=../lib uvicorn main:app --port --host --workers 4``\ :raw-html-m2r:`
` 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.\ :raw-html-m2r:`
` 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.\ :raw-html-m2r:`
` 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.\ :raw-html-m2r:`
` Finally, depending on the class of the tile, an element such as a tree, building, etc. is added.\ :raw-html-m2r:`
` 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.).\ :raw-html-m2r:`
` 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.\ :raw-html-m2r:`
` 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.\ :raw-html-m2r:`
` 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.\ :raw-html-m2r:`
` Our geoserver instance offers this from a resource file (geopackage containing rivers and oceans representation).\ :raw-html-m2r:`
` Current database from https://data.apps.fao.org/catalog/dataset/76e4aacc-b89e-4091-831f-63986fe029f9\ :raw-html-m2r:`
` 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.\ :raw-html-m2r:`
` * ``Dockerfile.game`` that builds the docker image running the ``npx`` local web server serving the game web app (the actual godot game). :raw-html-m2r:`
` 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).\ :raw-html-m2r:`
` 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 /game-server: .`` * ``sudo docker build -f Dockerfile.game --tag /game: .`` 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. :raw-html-m2r:`
` 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``.\ :raw-html-m2r:`
` 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 :raw-html-m2r:`LICENSE` file).