SVG: Moon landing and targeted programming
Demonstration of SVG with a lunar module controlled by goal-oriented programming.
On this highly stylized lunar landscape, the lunar module begins its descent down the runway, shown in green. This demonstration shows how to animate objects in a scene using SVG, while using the simplicity of goal orientation to define a goal and how to achieve it.
The shape below the animation can be used to select the starting angle of the module and its position relative to the runway. Click Submit to update the position of the module and Land to start the descent.
How does it work...
The lunar module and planet Earth are SVG files that are loaded into the page and added to the scene. We load the module into an iframe because we want to position it dynamically in the scene.
<div style="display:none">
<iframe id="ilander" width="100" height="100" src="code/lunar-lander.svg"></iframe>
</div>
We create a scene by representing the lunar surface and runway with gray and green rectangles, and the <image> tag is added to the Earth:
<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>
The image of the Earth is scaled to 1/5 using the scale property and positioned using translate.
Then add the themodule image loaded into the 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);
}
The getSVG function extracts images loaded with <iframe> tags, and the landscape function places these images in the scene. All this is explained in detail in the article Introduction to SVG: Programmatic Drawing Surface.
We need a function to move the module; this is the moveLander () role
function moveLander() {
lander.setAttribute("transform", "translate(" + x + "," + y + ") scale(0.1) rotate(" + angle + " 50 50)");
}
We change the translate value of the transform property using the coordinates and angle of the module. To move it, we determine the goals and ways to achieve them. There are three purposes: the angle of the module, its x position, and its y position.
Here's the code in 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
The scriptol to construct defines each condition to be met. Here, these are the x position between 300 and 350 for the track, y of 445 for the zero height of the module, and its orientation, which must be 0. The maximum delay allowed is 30 seconds. The second number is the delay between two moves.
This is converted to this JavaScript code:
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);
}
You can download the full source code of the demo with the scriptolbrowser.js library and SVG files:
The landing.html file is generated from the landing.sol file with the command: solj -w landing.