Comment j’ai fait Brutal Pico Race – 1ère partie

Brutal pico race utilise un système de rendu, combinant différentes techniques pour la route et pour les vaisseaux. Calcul des sommets de polygone à la volée pour la route, avec une projection “pseudo 3D” comme les anciens jeux type Outrun pour la route, et un rendu basé sur une structure en voxel pour les vaisseaux.

Voici le premier article décrivant comment j’ai implémenté Brutal Pico Race. Je donne quelques détails technique sur le rendu dont le résultat et une bataille entre l’idée d’un jeu de jeu de course et les possibilités (ou les contraintes) de Pico 8.

La prochaine fois je parlerais du rendu des vaisseaux et comment ils ont été intégré à la piste.

L’idée

Inspiration

J’ai eu l’idée de Brutal pico race après que mon subconscient ai combiné différents éléments que j’ai découvert ici et la. La première pièce du puzzle vient du court métrage the running man tiré de Neo Tokyo (pas du film avec Arnold Schwarzenegger !). Le titre Sega Sunset de Lorn colle particulièrement bien à l’ambiance dans ce montage :

Travaux émergent de twitter

Avant de démarrer Brutal Pico Race, j’étais à la recherche d’un outil permettant à mes enfants de découvrir la programmation informatique. J’avais un pico-8 grace à un ensemble de logiciel contenant Voxatron, je pensais que c’était un bon début. Mais finalement, mes enfants n’ont pas trop accroché autant que moi ! En apprenant comment fonctionnait pico 8 j’ai découvert des projets très intéressant et une communauté très active, le piège était refermé !

Si je devais sélectionner uniquement 3 projets, je garderais Zepton, Alone in pico 8 avec son postmortem très détaillé et Lands of Yocta. J’étais stupéfait ! Je me suis dit : On peut faire ça avec Pico 8 ?

Donc après avec découvert the running man du court métrage Neo Tokyo, et après avoir découvert des supers projets Pico 8 je me suis lancé dans la création de ce “demake” de The running man. Première étape la route !

La route

Brutal pico race, first IA test
Brutal pico race, la route…

Structure de données

La route est un tableau de “bloc de route”. Chaque bloc de  route possède ses propre propriétés. Pour dessiner la route, nous avons besoin de coordonnées x,y,z, d’une propriété fx pour les effets de virages, c pour la couleur et t pour le type de route. La coordonnée x a été utilisée dans les premiers prototypes, avant de choisir de modéliser les virages en pseudo 3D (par accumulation de décalage). J’imagine que je pourrais gagner quelques tokens en le retirant ! Donc fx est la propriété utilisée pour simuler les virages, comme dans les vieux jeux de courses sur des machines pas assez performante pour calculer de vrais virages. Et c’est tout ! Dans Brutal Pico Race, un bloc de route fait 64 unités de long, un choix arbitraire. Toutes ces informations sont initialisées dans la function “init_all_road” disponible dans le code source (lien “code” sous la fenêtre pico 8).

Grosso modo, une piste de course est une grande ligne droite qui boucle.

Rendu Hybride

La piste est rendu du bloc de route le plus loin au plus près par rapport à la caméra (Algorithme du peintre), avec une projection simple (weak perspective projection). On passe de coordonnées 3D à une projection 2D grâce à une division.

projection x = 3D X / 3D Z
projection y = 3D Y / 3D Z

Je n’utilise pas de matrice de projection dans ce cas, car cela est très couteux. Je tente de réduire au maximum ce qui est nécessaire. La contre-partie est qu’il n’y a pas de rotation possible pour la piste. Mais cela permet quand même de projeter les 4 sommets d’un bloc de route pour chaque bloque de route. A partir de la, on peut remplir le polygone obtenu en 2D. Le remplissage est réalisé grâce au rasterizer de 163 tokens de @p01 qui est rapide et léger. Au début du projet, j’utilisais une version adapté du rasterizer de Alone In Pico 8.

En appliquant une fonction cos ou sin aux coordonnées X et Y des blocs de route en 3D et en appliquant une translation sur l’axe Z de la caméra, on obtient le résultat suivant (Notez le faible cout du CPU) :

Ci-dessous j’ai épurer le code de rendu de la route pour se concentrer sur l’affichage de la piste, bloc par bloc. Je fais attention de ne jamais réaliser plus d’une fois la même chose, on voit que les sommets ne sont projetés qu’une seul fois chacun. On ne calcul que 2 sommets par bloc de route. La première itération n’affiche rien, il faut attendre la deuxième pour avoir 4 sommets et ainsi un polygone à remplir.

function drawroad(cam,ird,p)
 -- calculating road
 local r,rn,v,vn,vz=
  nil,nil--render info
 -- first partial offset
 local irdn=ird+1
 local irdlast=ird+nb_rb-1
 
 -- ready to draw road
 for i=irdlast,ird-1,-1 do
  v,vn=road[i%#road+1],
   road[(i+1)%#road+1]
  vz,xl,xr,iy,ylgt=
   v.z+flr(i/#road)*trklen,
   v.x-56,v.x+56,v.y,
   lerp(v.y,vn.y,0.5)
  -- clip
  dz=max(vz-cam.z,7)

  prc=(cam.z+7-vz)/rdz
  -- clipping
  if dz==7 then
   --interpolation
   xl=lerp(xl,vn.x-56,prc)
   xr=lerp(xr,vn.x+56,prc)
   iy=lerp(v.y,vn.y,prc)
  end
  -- current part
  fct=scale/dz

  r={
   x1=cx+fct*(xl-cam.x),
   x2=cx+fct*(xr-cam.x),
   y=cy-fct*(iy-cam.y),
  }
  -- drawing road
  if rn~=nil then 
   -- drawing triangles
   otri(r.x1,r.y,r.x2,r.y,rn.x1,rn.y,v.c)
   otri(rn.x1,rn.y,rn.x2,rn.y,r.x2,r.y,v.c)
  end
  -- next
  rn=r
 end
end

Système Half-pipe

Maintenant que l’on peut afficher une ligne droite, sans rotation mais avec une gestion de l’altitude et qu’il n’y a pas de contrainte de forme pour le remplissage des polygones, on peut imager une amélioration de la piste en “demi lune”. J’avais en tête cette forme en demi lune grace au court métrage Neo Tokyo, où les vaisseaux sont collés sur les bords surélevés par la vitesse. Et, c’est chose possible ! En divisant un bloc de route en 6 parties, avec chacune une altitude différente. Ces nouveaux sommets sont calculés à la volée à partir du point centrale du bloc de route (X=0, Y=0, Z=le z de ce bloc de route) en précisant les coordonnées X et Y du système de coordonnées du monde. Ces nouveaux sommets sont ensuite projetés en 2D et rempli et voila la magie :

Ensuite, je voulais voir jusqu’où Pico8 pouvait aller en ajoutant plein de bloc de route de ce type. Donc j’ai complété le premier prototype en affichant une “demi lune” complète. Et pour 30FPS, Pico 8 s’en tire bien ! Je n’ai pas visé le 60 FPS car je voulais donner la possibilité de faire un écran splitté pour du multijoueur, donc avoir le CPU en dessous de 50%, même si il manque encore beaucoup de chose, était déjà très encourageant !

 

Prochaine partie, le rendu des vaisseaux et comment ils ont été intégrés à la piste.

Ressources :

Damien Hostin (aka YouryKiKi)

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *