Retour à l'accueil

EN COURS

Dernière mise à jour : 2026-03-04

Super Toboggan 3D

Après un jeu PS Vita me voilà à faire un jeu PlayDate ! Pour celleux qui ne savent pas la playdate c'est une petit console jaune, avec un écran noir et blanc et une manivelle (oui !). Ça fait un moment que j'en ai une, j'y ai joué un peu, j'ai fait le Lucas Pope sorti dessus, et puis après j'avoue elle est partie prendre la poussière. Néanmoins j'avais toujours dans un coin de la tête de faire un jeu dessus...
Lors du Lyon Game Dev de janvier, je discutais avec Ludo qui fait des jeux sur playdate justement (il a sorti Crank Stone recemment), et il me disait que la mode en ce moment c'était les jeux en 3D. Là mon cerveau s'est dit : et si on essayais ????? J'ai très vite fait le lien avec une envie vague que j'avais dans un coin de la tête de créer un clone de SpeedX 3D.
L'étape 1 c'était de regarder comment on fait de la 3D sur playdate, j'ai trouvé ce billet de blog trop bien qui justement récapitule toutes les façons de faire. Arrivé vers le bas de la page est listé Mini3D qui fait partie de l'API offcielle de la PlayDate.

Première 3D

Étape 1 : faire un cube. J'ai repris la démo 3D en lua qui est dans le SDK de la playdate, et je l'ai modifiée pour faire apparaitre un cube que je fais tourner avec la manivelle. Ça m'a permis de me remettre en têt les base de la 3D (notamment l'ordre des points d'un triangle!). Étape 2 : réécrire en C le code, pour le moment je n'avais pas de problème de performance (heureusement, ce n'est qu'un cube 😅), mais je savias que ça n'allait pas durer, j'ai donc réécrit en C. Ça été interessant à faire et ça marche !

Le tunnel

Le player

J'hésite à représenter le joueur, dans SpeedX3D il n'y est pas, mais je me dis que quand même ça peut prendre plus clair. Du coup je voudrais bien un genre de vaisseau triangulaire proche de la caméra sur le tube. J'ai fait un premier test en en faisant un node à part (via mini3D), mais je ne comprend pas bien pourquoi ses coordonnées ne correspondaient pas à celle du tube, au final je fais un second essai en dessinant direct le player sur le même noeud que le tube. C'est interessat ça me permet de comprendre le code de génération du tunnel (que j'avoue j'ai copié collé de XScreenSaver 😇)

Je viens de découvrir l'option pour draw en wireframe, le rendu est tellement mieux. Seulement ça ne prend pas en compte orderTable donc je réécris la lib pour que ça le fasse. J'ai réussi, ça m'a permis de corriger le wireframe qui se faisait pas en noir, le rendu est bien stylé maintenant, je suis content.

Pour le player en lui même, mes essais ne sont pas concluants, je voulais un genre de pyramide collé contre la paroi et j'arrive pas à avoir cet effet, j'ai envie de voir si faire comme SpeedX3D (la camera c'est le player) je m'en sortirai mieux.

J'ai réussi à faire en sorte que la camera soit sur le tube et avec la manivelle je la tourne. Par contre j'ai un soucis, les faces se clipent trop facilement quand un seul de leur vertex passe derrière la camera, je tente de bidouiller ça. Pas facile, je suis descndu jusque dans le draw fragment sans trouver qui était à l'origine de ce comportement. Bon déjà la camera comme joueur ça marche, par contre j'ai divisé par deux mon framerate sur playdate, faut que je vois comment optimiser.

Les obstacles

Dans un premier temps je sidetrack: j'ai trouvé comment optimiser, je rend les portions de tunnel lointaine (donc culled la plupart du temps) avec moins de faces, j'ai un 30 fps constant (ça me semble une bonne target). Ensuite j'ai regardé si je pouvais changer la couleur des sections du tube pour en faire des sombres (un peu comme dans les toboggan aquatique quand il fait noir!), pour la couleur c'était facile mais le wireframe il fallait le passer en blanc. J'ai donc encore touché à des choses directement dans le sdk, maintenant la couleur du wireframe est décidé dans la face et non plus dans la shape. Ça marche !

Bon, les obstacles... Je sais pas trop pas quel bout le prendre, va falloir que j'instantie de nouvelles shapes, je vais 100% avoir à nouveau des galères avec la mémoire... Déjà je vais essayer d'en draw 1, de me mettre au bon endroit dans la boucle de dessin du tunnel. Ok j'ai réussi un premier truc :

Avec un peu d'algorithmie j'ai réussi à trouver les bons vertex pour faire une pyramide. Puis plusieurs, j'ai galérer à trouver un bon moyen d'allouer la mémoire.

Bon, les obstacles fonctionnent lorsque ce sont toujours les memes par section, et par niveau. Mais bon ce n'est pas terrible, j'aimerai bien pouvoir varier, mais ça fait n'imp avec les triangles et ça crash. C'est lié à la façon dont je hack mini3D (je change chaque frame des valeurs qui sont prévues pour être fiexes, genre les faces et les vertex). Après beaucoup d'essai erreur, j'ai trouvé l'astuce : je reset la liste de points chaque frame, en plus ça me permet de libérer régulièrement de la mémoire, c'est top. Ça marche, maintenant j'ai envie de me faire un éditeur de niveaux sur Godot.

Je viens de tester sur Playdate et... les allocations mémoire chaque frame c'est pas trop ça, mes FPS sont à 15 :/ Il va falloir que je trouve une autre idée.

Le clipping de la caméra

Un truc qui me gène depuis le début c'est que les faces du tunnel proches de la caméra disparaissent, du coup on voit à travers et notamment l'extérieur des sections suivantes du tunnel, et puis c'est moche.

Le problème en question, c'est bof bof quand même.

Dans le README de Mini3D c'est en effet écrit que dessiner les faces qui ont au moins un vertex derrière la caméra n'est pas pris en charge. Je me suis dis bêtement que je pourrais dans un premier temps commenter la ligne qui s'occupe du skip, mais je ne l'ai pas trouvée... J'ai commenté / décommenté des trucs pour essayer de comprendre, mais sans succès. Alors je me suis rappelé que Mini3D+, une réécriture du Mini3D officiel que j'utilise avant la fonction pour afficher les faces proches de la caméra. En lisant le code je comprend que ce qui est fait c'est de créer des plus petites faces qui elles sont entièrement visibles par la caméra. En désespoir de cause, je décipe de transitionner vers Mini3D+, j'aimais bien l'idée de rester sur le SDK officiel mais bon, ça me parait pas possible de résoudre mon problème simplement et Mini3D+ est là à me tendre les bras.
L'API c'est pensée pour être compatible donc j'ai fait une branche sur mon dépôt et j'ai remplacé le dossier de Mini3D, avec quelques ajustement ça a très vite fonctionné, donc c'est cool. Ensuite il a fallut que je reporte les modifications au rendu que j'avais faites, ça m'a pris un peu de temps puisque Mini3D+ a rajouté des fonctions qui changent des structures et des fonctions, mais j'y suis arrivé. Très content, le clipping c'était le dernier truc qui me fasait peur pour la viabilité du projet (j'imagine que Panic aurait pas aimé pour le publier sur le Catalog). J'ai l'impression qu'avec Mini3D+ j'ai un framerate légèrement plus stable, donc j'y gagne sur tous ls plans j'ai l'impression. Il y a des macro à configurer aussi faudra que je regarde s'il y a des choses qui peuvent m'intéresser.

J'ai un soucis avec la caméra, le UP a l'air géré différement, en effet Mini3D+ a complètement changé la fonction SetCamera, flemme de comprendre les changements, je vais porter l'ancienne. Ça marche, maintenant je vais nettoyer les trucs qui me servent à rien dans Mini3D+ (genre le lua et les trucs de karts). Je supprime aussi les lib pour lire des textures, ça ne m'interesse pas et ça alourdi beaucoup la compilation. je voulais aussi supprimer les imposteurs, mais c'est trop lié au code de la scène donc je le laisse, ça va ça coute pas grand chose.

Un tool pour le level design

En C le tunnel est simplement un tableau des points par lesquels il doit passer, et le reste est calculé par un CatMull. C'est léger et pratique mais ça fait que c'est pas facile d'itérer sur la forme du tunnel. Je me suis donc attelé à la création d'un tool en Godot. J'avais déjà utilisé les Path3D et les CSGPolygon pour FediRacing et FUCK AI pour faire des formes le 3D qui suivent une courbe, c'est donc là dessus que c'est porté mon choix immédiatement. Mon besoin c'est juste de pouvoir donner des points en format texte (qui viennent du C) et que ça me fasse le tunnel associé dans Godot, puis à l'inverve que je puisse exporter un tunnel modifié dans Godot en liste de points pour le code en C. Ce n'était pas très compliqué à faire et à marche, surtout que je ne m'embête pas refaire le CatMull, la forme générale du tunnel me convient très bien.

Voilà ce que ça donne

Notes diverses

Mettre à jour le SDK

Il faut rajouter set -gx PLAYDATE_SDK_PATH /run/media/paul/Developpement/Gamedev/playdate/PlaydateSDK-3.XX/ dans la config du shell (moi c'est fish, donc dans .config/fish/config.fish), il faut aussi que je change mon run.sh avec le nouveau chemin (peut-être que je pourrais aller le lire dans le path si j'étais malin).