SVG: Alunissage et programmation par but

Démonstration de SVG avec un module lunaire commandé en programmation orienté but.

Sur ce paysage lunaire très stylisé, un module lunaire amorce sa descente sur une piste représentée en vert. Cette démonstration permet de voir comment animer des objets dans une scène grâce à SVG, tout en profitant de la simplicité de l'orientation but pour définir l'objectif et comment l'atteindre.

Vous pouvez à partir du formulaire sous l'animation choisir l'angle initial du module et sa position par rapport à la piste. Cliquez sur Soumettre pour mettre à jour la position du module, et sur Alunir pour amorcer la descente.

Angle (0-180) X (0-500) Y (0-400)

Comment cela fonctionne...

Le module lunaire et la planète terre sont des fichiers SVG qui sont chargé dans la page et ajoutés à la scène. On charge le module dans une iframe car on veut le positionner dynamiquement dans la scène.

<div style="display:none">
<iframe id="ilander" width="100" height="100" src="code/lunar-lander.svg"></iframe>
</div>

On réalise la scène en représentant la surface lunaire et la piste par des rectangles gris et vert, et la Terre est ajoutée avec une balise <image>:

<svg id="moon" width="720" height="600">
<rect id="ground" x="0" y="550" width="720" height="50" style="fill:rgb(245,245,245);" />
<rect id="airport" x="300" y="542" width="160" height="8" style="fill:rgb(0,128,0);" /> <image width="518" height="518" transform="translate(500, 60) scale(.2)" xlink:href="code/globe.svg" />
</svg>

L'image de la terre est réduite à 1/5ème par la propriété scale, et positionnée avec translate.

Puis on ajoute à la scène l'image du module chargée dans une iframe:

function getSVG(oID, gID)
{
  var ifr = document.getElementById(oID);
  var graphics = ifr.contentWindow || ifr.contentDocument;
  return graphics.document.getElementById(gID);
}

function landscape()
{
  var moon = document.getElementById("moon");

  lander = getSVG("ilander", "layer1");
  lander.setAttribute("transform", "translate(100,200) scale(0.1)  rotate(45 50 50)");
  moon.appendChild(lander);
}

La fonction getSVG récupère les images chargées par les balises <iframe>, la fonction landscape positionne ces images dans la scène. Dans l'article Canvas pour SVG : surface de dessin programmée tout ceci est expliqué en détail.

Il nous faut une fonction pour déplacer le module, c'est le rôle de moveLander()

function moveLander() {
  lander.setAttribute("transform", "translate(" + x + "," + y + ") scale(0.1)  rotate(" + angle + " 50 50)");
}

On modifie la valeur translate de la propriété transform avec les coordonnées et l'angle du module. Pour faire bouger celui-ci, on définit les buts et comment les atteindre. Il y a trois but: l'angle du module, sa position x, sa position y.

Voici le code en langage Scriptol.

void land()
  to angle = 0 for 30, 50
    if angle > 0 ? angle - 1
    moveLander()
  /to
	
  to ((x >= 300) and (x <= 350)) for 30, 20
    if x < 300 ? x + 1
    if x > 350 ? x - 1
    moveLander()
  /to
	
  to y = 445 for 30, 20	
    if y < 445 ? y + 1
    moveLander()	 
  /to

return

Le construct to de scriptol définit chaque condition a atteindre, ce sont ici la position x entre 300 et 350 pour la piste, y de 445 pour la hauteur zéro du module et son orientation qui doit être de 0. Le délai maximal imparti est de 30 secondes. Le second nombre est le délai entre deux déplacements.

Cela est converti en ce code JavaScript:

function land()
{
   scriptol.goal(function() { return(angle===0)},30*1000,function(){
      if(angle>0) { angle-=1; }
      moveLander();
   }, 50);

   scriptol.goal(function() { return(((x>=300)&&(x<=350)))},30*1000,function(){
      if(x<300) { x+=1; }
      if(x>350) { x-=1; }
      moveLander();
   },20);

   scriptol.goal(function() { return(y===445)},30*1000,function(){
      if(y<445) { y+=1; }
      moveLander();
   },20);
}

Vous pouvez téléchargez le code source complet de la démo avec la bibliothèque scriptolbrowser.js et les fichiers SVG:

Le fichier landing.html est généré à partir du fichier landing.sol avec la commande: solj -w landing. Voir scriptol.org pour plus de détails.