Aller au contenu principal
sports_esports Lab Canvas 2D Lancer de rayons DDA Pseudo-3D Anti-fisheye

Raycaster — un moteur pseudo-3D façon Wolfenstein en Canvas 2D

Un moteur pseudo-3D réécrit from scratch en Canvas 2D : une carte en grille parcourue par un rayon par colonne d'écran (DDA), une projection en perspective où la hauteur de chaque tranche est ∝ 1/distance, et la correction de la distorsion fisheye par la distance perpendiculaire au plan de la caméra. Rendu colonne par colonne façon Wolfenstein 3D, zéro dépendance.

Flèches ↑ ↓ ou W / S : avancer et reculer Flèches ← → ou A / D : pivoter (ou glisser à la souris) Espace : mettre en pause

De la 2D pure à l'illusion de la 3D

Ce moteur n'a rien d'un vrai moteur 3D : il n'y a ni polygones, ni matrices de projection, ni carte de profondeur. Juste une carte en grille — des cases pleines (murs) et des cases vides — parcourue par des rayons, exactement comme le faisait Wolfenstein 3D en 1992 sur des machines qui ne savaient pas dessiner un triangle texturé. Toute la sensation de relief tient dans une idée : lancer un rayon par colonne d'écran et en déduire la hauteur d'un mur.

Un rayon par colonne, avancé en DDA

Pour chaque colonne de l'image, je construis un rayon qui part de la caméra et traverse le plan de l'écran, puis je le fais avancer sur la grille par DDA (Digital Differential Analyzer). Plutôt que de progresser à petits pas réguliers — coûteux et faillible — le DDA saute directement d'une frontière de cellule à la suivante : à chaque itération, je compare la distance jusqu'au prochain bord vertical et jusqu'au prochain bord horizontal, et j'avance vers le plus proche. En quelques sauts, le rayon atteint la première case pleine. C'est exact, sans jamais « rater » un mur fin, et borné par la taille de la carte.

La hauteur d'un mur est l'inverse de sa distance

Une fois le mur touché, la projection en perspective se résume à une division : la hauteur de la tranche verticale à dessiner est inversement proportionnelle à la distance. Un mur deux fois plus loin occupe deux fois moins de hauteur à l'écran. Je dessine alors une seule bande verticale, centrée, aussi haute que le dicte cette distance — et l'accumulation de ces bandes, colonne après colonne, reconstitue un couloir en perspective sans jamais manipuler la moindre géométrie 3D.

Corriger la distorsion « fisheye »

Le piège classique : si l'on mesure la distance euclidienne du joueur au mur, les murs se courbent vers les bords de l'écran comme dans un objectif fisheye. La parade est de projeter cette distance sur l'axe de la caméra — d'utiliser la distance perpendiculaire au plan de la caméra, et non la distance au point de vue. Le calcul tombe naturellement du DDA, sans trigonométrie coûteuse par pixel, et les murs redeviennent bien droits.

Teinter pour donner du relief

Un couloir tout d'une couleur resterait plat. J'assombris donc chaque tranche selon deux critères : la distance — un brouillard discret fait fondre les murs lointains dans l'obscurité — et l'orientation de la face touchée, les faces nord-sud étant rendues plus sombres que les faces est-ouest. Ce simple contraste entre deux teintes suffit à faire lire les angles et les coins, et donne au rendu colonne par colonne son épaisseur.

Ce que je retire d'un vieux truc d'arcade

Le raycasting est un modèle réduit de ce que je recherche sur les projets sérieux : choisir la représentation qui rend le problème simple. Ici, ramener un rendu 3D à une boucle de divisions sur une grille transforme un calcul intimidant en code clair, rapide et prévisible. C'est la même démarche que j'applique à une architecture logicielle — trouver l'angle qui fait disparaître la complexité inutile — pour livrer une base performante que votre équipe pourra reprendre et faire évoluer sans moi.

Photo d'Emmanuel BALLERY, fondateur de x10

À propos de l'auteur

Emmanuel BALLERY est le fondateur de x10 solutions. Ces petits jeux sont surtout un plaisir de développeur, codés le week-end — pas une vitrine de mes missions, qui sont bien plus exigeantes. J'y soigne quand même la performance et la lisibilité, par habitude.

Voir plus arrow_forward
rocket_launch

Un vrai projet en tête ?

Ce petit jeu m'amuse, mais il ne dit pas grand-chose de mon métier : mes missions sont bien plus complexes. Si vous avez une application à concevoir ou à fiabiliser, c'est là que je suis vraiment utile.

Discuter de mon projet arrow_forward