Un raycaster basique avec canvas

 


Le raycaster en action

Voir la démo.

Pourquoi ?

Après avoir réalisé à mon plus grand plaisir que le sympathique élément <canvas> dont j'avais entendu parler (en), non seulement allait être supporté dans Firefox, mais était déjà supporté dans la version actuelle de Safari, je me devais de tenter une petite expérience.

La présentation et le tutoriel canvas que j'ai trouvé ici sur MDC sont excellents mais personne n'a encore rien écrit sur l'animation, j'ai donc pensé porter un raycaster basique sur lequel j'avais travaillé il y a quelque temps, et voir quelle sorte de performance nous pouvions attendre d'un pixel buffer écrit en JavaScript.

Comment ?

L'idée de base est d'employer setInterval à intervalle régulier, correspondant au frame rate désiré. Après chaque intervalle, une fonction de mise à jour redessine le canvas, affichant la vue actuelle. Je sais que j'aurais pu commencer avec un exemple plus simple, mais je suis sur que le tutoriel canvas va y conduire, et je voulais voir si je pouvais y arriver.

Donc, à chaque mise à jour le raycaster vérifie si vous avez pressé une touche récemment, pour s'éviter des calculs si vous êtes immobile. S'il y a eu un mouvement, le canvas est effacé, le ciel et le sol sont dessinés, la position et l'orientation de la caméra corrigées et les rayons projetés. Lorsque les rayons rencontrent un mur, ils créent une bandelette verticale de canvas de la couleur du mur qu'ils ont touché, mélangée à une nuance plus sombre de cette couleur en fonction de la distance au mur. La hauteur de la bandelette est modulée par la distance entre le mur et la caméra, et la bandelette est dessinée centrée sur la ligne d'horizon.

Le code que j'ai obtenu est l'amalgame des chapitres raycaster d'un vieux livre d'André LaMothe Tricks of the Game Programming Gurus (ISBN: 0672305070), et d'un raycaster Java que j'ai trouvé en ligne, modifié par mon besoin compulsif de tout renommer pour que cela ait un sens pour moi, et par tout le bricolage nécessaire pour que l'ensemble fonctionne bien.

Résultats

Le canvas dans Safari 2.0.1 a étonnement bien marché. Avec le facteur de bloc-itude poussé pour rendre des bandelettes de 8 pixels de largeur, j'arrive à faire tourner une fenêtre en 320 x 240 à 24 images/seconde sur mon Apple mini. Firefox 1.5 Beta 1 est encore plus rapide, j'obtiens 24 images/seconde sur la fenêtre de 320 x 240 avec des bandelettes de 4 pixels. Pas vraiment un nouveau membre de la famille ID software, mais plutôt décent si l'on considère qu'il s'agit d'un environnement entièrement interprété, et que je n'ai eu à m'inquiéter ni de l'allocation mémoire, ni des modes vidéos, ni de coder les routines centrales en assembleur, ni de quoi que soit d'autre. Le code cherche à être très efficace, consultant un tableau de valeurs précalculées, mais je ne suis pas un dieu de l'optimisation, donc les choses pourraient probablement être écrites plus rapides.

De plus, il laisse beaucoup à désirer en tant que tentative d'une espèce de moteur de jeu— il n'y a pas de textures sur les murs, pas de sprites, pas de portes, même pas de téléporteurs pour passer à un autre niveau. Je suis cependant presque certain que toutes ces choses peuvent être intégrées pourvu qu'on en prenne le temps. L' API de canvas supporte la copie d'images par pixel, donc les textures semblent possibles. Je laisse ça pour un autre article, probablement d'une autre personne. =)

Le RayCaster

Les sympathiques personnes ici ont copié mes fichiers manuellement pour que vous puissiez y jeter un coup d'oeil, et pour votre plaisir, j'ai posté le contenu de chacun des fichiers sous la forme de listings de code (voir plus bas).

Vous y voici donc, lancez Safari 1.3+, Firefox 1.5+ ou un autre navigateur supportant l'élément <canvas> et amusez-vous!

input.js | Level.js | Player.js | RayCaster.html | RayCaster.js | trace.css | trace.js

Voir également

Étiquettes et contributeurs liés au document

Contributeurs ayant participé à cette page : Delapouite, VincentN, Fredchat, Planche
Dernière mise à jour par : Delapouite,