SVG: Moon landing and programming by goal

SVG demo of a lunar module move with goal-oriented programming.

In this stylized lunar landscape, a lunar lander begins its descent on a track shown in green. This demonstration shows how to animate objects in a scene with SVG, while enjoying the simplicity of the goal orientation to define the objective and how to achieve it.

You can from the form below the animation choose the initial angle of the module and its position relative to the track. Click Submit to update the position of the module, and Land to start the descent.

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

How does it work ...

The lunar module and planet earth are SVG files that are loaded into the page to be added to the scene. Le module is loaded in a iframe because we want put it dynamically in the scenery.

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

The scenery is achieved by representing the lunar surface and the track by gray and green rectangles, and the Earth is loaded by the <image tag>:

<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" />

The image of the Earth is reduced to 1/5th scale by the scale property, and positioned by translate.

Then we add to the scene the images image of the module loaded in 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)");

The getSVG function retrieves images loaded by the <iframe> tags, the landscape function put these images in the scene. In the article Introduction to SVG: making a scenery all this is explained in detail.

We need a function to move the module, it is the role of moveLander():

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

We modify the translate value of the transform property with the coordinates and angle of the module. Then to move it, we define the goals and how to reach them. There are three goals: the angle of the module, the position x, the position y.

Here is the code in Scriptol language:

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


The construct to of scriptol define a condition to be achieved: Here there are the x position between 300 and 350 for the track, the y height from 445 to zero and the orientation of the module that must be 0. The maximum time allowed is 30 seconds. The second number is the delay between two moves.

This is converted in JavaScript in the following code:

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

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

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

You can download the complete source code of the demo with the scriptolbrowser.js library and SVG files:

The landing.html file is generated from the landing.sol file written in Scriptol with the command: solj -w landing.