Alexandre LHUILLIER - Projets, histoires & opinions
Accueil Blog Projets Divers À propos

English Version

Le jeu

Ce jeu a été créé pendant la game jam de 2022 du site Développez.com.
Curieusement, nous n’avions aucune inspiration pour le nom du jeu, alors nous avons gardé son nom de code: WE2022 (pour week-end).
Les thèmes de cette année étaient "Jouer avec la/les caméra(s)" et "Big Brother".

Vous êtes enfermé dans une cellule, probablement parce que vous avez le pouvoir de faire passer des objets à travers le retour d’une caméra vidéo. Vos geôliers distraits ont laissé une console de surveillance dans votre cellule, vous donnant accès à toutes les caméras du complexe. Utiliser votre pouvoir pour libérer la sortie en interagissant avec l’environnement à travers les caméras.



Plus d’informations dans le topic dédié: https://www.developpez.net/forums/d2142720/applications/developpement-2d-3d-jeux/projets/we-jv12-participation-nom-cpp-opengl-d3d12-outils-blender-trenchbroom/

Le développement

Avant la jam

1 ou 2 mois avant la jam, j’ai commencé à expérimenter des post-process avec mon moteur, plus exactement du bloom et du depth-of-field, espérant les utiliser dans la jam qui arrivait.

La recherche d’une idée

Une fois que le thème est tombé, je voulais absolument avoir plusieurs render-to-texture pour représenter des retour caméras, donc il valait mieux éviter de multiplier les post-process, de toute façon ils n’étaient pas au point.

J’ai hésité avec plusieurs idées:

Puis j’ai cherché une idée qui tourne autour d’une console de surveillance comme dans le premier concept. A un moment, je me suis dit que ce qui fait l’originalité du premier concept, c’est de pouvoir interagir avec des objets à travers la caméra, et pas juste avec des interrupteurs et des boutons autour de la console de surveillance. Je me suis dit que faire passer des objets à travers l’écran, puis les renvoyer pour interagir avec autre chose, c’était assez cool.

Le but serait donc de se libérer un passage en interagissant avec les caméras. Un moment Biiscuit a pensé à une variation du concept: on ouvrirait une porte à l’aide d’une console de surveillance, puis on se déplacerait dans une nouvelle pièce où il y aurait une autre console de surveillance donnant accès à d’autres caméras pour ouvrir une autre porte, et ainsi de suite. J’ai suggéré qu’on pourrait aussi se déplacer avec la console de surveillance, un peu comme la mallette dans Quadrilateral Cowboy. Mais en vrai, je ne me sentais pas de gérer correctement les collisions d’un personnage qui se déplace, dans les temps (je n’avais pas déjà ça dans ma boîte à outils :p sauf peut-être si, comme dans mon runner en 2020, on se déplaçait uniquement sur du plat.) J’aurais bien aimé qu’à la fin du jeu qu’on a soumis, on puisse se déplacer physiquement jusqu’à la sortie.

Le déroulement du week-end

Niveau programmation, le premier but était déjà de faire plusieurs render-to-texture, puis de les afficher sur des quads dans le monde. J’ai galéré plus que je n’aurais du, puis j’avais finalement 4 écrans dans une map basique vers 2h du matin. Puis je devais détecter que la souris pointe ces quads.
Horreur: avec toutes mes expérimentations sur les post-process et les ombres, j’avais changé mon calcul de matrice inverse (c’est la galère à faire quand on galère en maths), mais maintenant ça cassait la projection quand je voulais que la souris pointe quelque chose. J’ai décidé d’utiliser mon ancien calcul temporairement le temps de la jam, et de vraiment la corriger plus tard. C’était une galère à corriger (tout plein de lignes très peu différentes les unes des autres), mais finalement c’était une erreur bête (J’avais mixé le calcul des composantes depuis une source et le calcul du déterminant d’une autre).

Ensuite, le défi était de pointer un objet à l’intérieur d’un retour caméra. Je l’ai fait en dé-projetant le point d’intersection du pointeur de la souris avec l’écran du retour caméra comme si elle correspondait à la position de la souris sur l’écran du joueur, puis tester le picking à partir de cette position comme si le retour caméra était identique à l’écran du joueur (je ne sais pas si c’est très clair). J’ai testé ça avec une clé que j’avais faite pour un précédent projet (une mise à jour du jeu sous-marin d’ailleurs).

Toutes ces histoires de projection m’ont pris au moins une bonne demi-journée samedi.

Quelques heures plus tard, j’avais un inventaire en bas de l’écran, où s’ajoutaient les objets sur lesquels on cliquait. Une fois le problème de l’interaction à travers les écrans réglés, il était facile de faire glisser un objet récupéré à travers un écran pour le combiner avec un autre.

Pendant ce temps, Biiscuit créait des objets dans Blender: un pied de biche, un digicode, une carte d’accès.

En voulant importer ces objets dans le jeu, je me suis aperçu que mon chargement des fichiers .gltf et .glb était très lacunaire: je chargeais bien toutes les données du json, mais à la fin ça ne marchait bien que s’il y avait un seul mesh (et un skin, mais ça importe peu pour ce projet), avec une seule primitive dans la terminologie du glTF. Ça marchait bien quand je faisais des modèles moi-même et que je connaissais la contrainte, mais pour un graphiste, c’est évidemment un bug. Et utiliser plusieurs matériaux pour avoir des zones de couleur différente dans blender divise le mesh en plusieurs primitives dans le glTF.
Je gérais aussi mal la hiérarchie des nodes dans la scène, du coup si un node parent était scalé et translaté, la transformation n’était pas la bonne au finale.
Pour avoir quelque chose de fonctionnel dans le jeu, j’ai légèrement changé le chargement de ces modèles pour que toutes les primitives soient chargé, et j’ai juste peint les vertices avec la couleur du matériau. Il était inenvisageable évidemment de supporter toutes les features des matériaux, je ne sais pas si j’en arriverai à bout un jour :p

C’est à cause de ces problèmes qu’après la jam, j’ai décidé de me lancer dans la création d’un viewer de modèles (je me concentre sur le glTF et sur mes propres formats) pour éviter ce genre de mauvaises surprises à l’avenir. Je le teste avec plein de modèles de test qui viennent du github du format, et d’autres que je trouve sur sketchfab, pour blinder mon loader.

Le but est déjà de supporter toutes les features de la scène et toutes les combinaisons de formats d’animations (animation de meshes séparés, skinning, et plus tard morph targets), et aussi au maximum les matériaux, selon les besoins de mes jeux.

Jusqu’ici la spec du glTF est assez bien faite, je n’ai pas trop eu à lutter, à part pour une chose qui n’est pas très bien explicitée: si un node a un scale négatif, les faces du/des mesh(es) enfants doivent être flippés. Et il se trouve que c’était le cas du pied-de-biche :p Heureusement, quelqu’un a fait plein de modèles de test pour ce genre de cas: https://github.com/KhronosGroup/glTF-Asset-Generator/blob/master/Output/Positive/Node_NegativeScale/README.md. Le pied-de-biche de Biiscuit fonctionne bien maintenant, mais il faudra aussi tester tous ces modèles au cas où.

Biiscuit a aussi fait la map du jeu, dans TrenchBroom, et les textures qui vont avec, notamment les cartons et les caisses. Dans ce jeu, comme les seules collisions sont du picking, ce n’est pas forcément pertinent d’utiliser un éditeur à base de CSG, mais je n’étais pas confiant sur le fait de bien charger une map entièrement faite dans Blender (et vu mes problèmes précédents pour de petits objets, j’avais raison :p)

Vers 17h le dimanche, j’avais avancé sur quelques features “faciles”:
Dans le désordre:

Il me restait encore:

J’ai sorti une proof of concept vers 19h30, avec une map encore en chantier et un minimum de caméras, le seul objet était encore la grosse clé rouge et il n’y avait qu’une seule porte avec laquelle interagir pour gagner.
Il me restait encore à ajouter:

Au dernier moment, j’ai récupéré la map pour y ajouter objets et caméras, puis au moment de la tester dans le moteur avant tout, elle s’affichait tout en noir... Après pas mal de temps perdu, il s’est avéré que c’était le vieux problème de mal initialiser ses variables :p Un uniform dans un shader (la matrice de projection) n’était initialisé qu’au moment de faire les render-to-texture, et comme il n’y avait aucune caméra encore dans la map (contrairement à ma petite map de test où j’essayais les features), même le “vrai monde” ne s’affichait pas correctement.

J’ai donc ajouté les entités (objets à ramasser, caméras, transformé certains groupes de brushes en entités pour les portes), un peu testé que le niveau fonctionnait, puis envoyé une version vers 1h du matin.

Il y a quelques petites choses dont je ne suis pas satisfait, comme le fait que pouvoir switcher parmi tous les écrans débloqués sur un écran avec les touches fléchées n’est pas bien expliqué à mon goût (idéalement, il aurait fallu ajouter de l’UI supplémentaire à l’écran à mon goût), ou le fait que les écrans flottent dans le vide et qu’on ne voit pas le moniteur “physique” autour, quand on ne connaît pas le jeu on ne comprend pas forcément que c’est censé être une console de surveillance. Mais en voyant d’autres personnes tester le jeu, il semblait avoir l’effet espéré :)

Les leçons à en retirer:

La dernière version sortie (Windows)