Algoid - Environnement de programmation éducatif pour enfants et débutants

Présentation du langage de programmation AL et tutoriels

Yann Caron

Présentation d'Algoid et de son langage AL, un langage de programmation éducatif destiné au jeune public et à toute personne désireuse d'apprendre la programmation (de 7 à 77 ans) :

- présentation de son IDE ;

- fondements de son langage ;

- liste des tutoriels pédagogiques.

Commentez cet article. ?

- Titre : Algoid - Environnement de programmation éducatif pour enfants et débutants

- Auteur : Yann Caron

- Parution : 24 juin 2013

- Mise à jour : 24 juin 2013

- Public visé :

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Yann Caron. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. AL

- I-A. Principe

- I-B. Syntaxe

- I-C. Concepts avancés

- II. Intérêt d'Algoid

- II-A. Multiplate-forme

- II-B. Fonctionnalités

- II-C. Fun

- II-D. Installation

- II-D-1. Android

- II-D-2. Windows / MacOS / Linux

- II-D-3. Raspberry Pi

- II-D-3-a. Soft-Float

- II-E. Portabilité

- II-F. Performances

- III. Matériels pédagogiques

- III-A. Communautaire

- III-B. Tutoriels

- III-B-1. Partie I : Apprendre la programmation avec la tortue

- III-B-2. Partie II : Programmation structurée

- IV. Remerciements

- V. Annexes

I - AL

AL est un langage éducatif conçu pour les plus jeunes (à partir de 10 ans), mais s'adressant plus généralement à tout débutant désireux d'apprendre la programmation.

AL est conçu comme un langage d'introduction aux langages professionnels. Il simplifie certains aspects et syntaxes. AL est au C / Java / Python ce que Logo est au Lisp.

Il donne également la possibilité d'explorer un large panel de mécanismes, donnant l'opportunité aux développeurs chevronnés d'explorer des terrains qui ne sont pas forcément disponibles dans tous les langages.

Ses IDE, Algoid et AlgoIDE, ont été conçus pour être simples à installer et à utiliser ; ils incluent en un seul logiciel : l'IDE, le langage, le debugger, le stepper, les librairies de haut niveau dont celle permettant de créer ses premiers jeux vidéo.

Algoid est également l'environnement parfait pour faire ses premiers pas. Tout y est sécurisé, les accès aux ressources de l'ordinateur ont été limités afin que le système ne puisse pas être endommagé.

I-A - Principe

AL est fondé sur un constat simple. Il existe aujourd'hui un très grand nombre de langages de programmation destinés à l'apprentissage, mais :

- soit ils sont simples, mais se cantonnent à un seul paradigme (comme le SmallBasic ou le très célèbre Logo) ;

- soit ils sont très complets, mais leur installation, leur syntaxe, leurs idiomes et leur mise en place sont difficiles à acquérir et à comprendre.

AL tente de réconcilier ces deux opposés en proposant une syntaxe simple (20 mots clés) tout en étant multiparadigme.

L'organisation des paradigmes est pensée pour être aussi progressive que possible ; d'abord par les structures impératives, puis l'utilisation des fonctions et du fonctionnel. AL introduit ensuite l'objet et grâce à la MOP, des notions d'orienté aspect.

De plus AL est un langage de haut niveau. Toutes les considérations, telles que le typage, les pointeurs, le garbage collector, sont à la charge du langage.

I-B - Syntaxe

La syntaxe AL a été imaginée pour être la plus proche possible des standards utilisés par les professionnels. C'est-à-dire les langages issus du C.

- Parce qu'apprendre une nouvelle syntaxe prend du temps, autant en apprendre une qui soit la plus proche de ce qui est utilisé dans l'industrie.

- Parce que cette syntaxe est concise, moins de mots à taper sur de petits écrans, comme les smartphones.

On pourrait reprocher à la syntaxe C d'être rebutante et difficile à appréhender par les plus jeunes. Mais il n'est pas certain que de remplacer des accolades par des mots clés comme begin / end facilite réellement l'apprentissage d'un langage. Ce sont les mécanismes du langage et les aspects de bas niveau qui représentent une vraie difficulté.

Pour faciliter cette approche, AL dispose de différentes simplifications.

- La structure de contrôle Loop a été rajoutée à l'ensemble disponible en C. Cette structure permet d'introduire les boucles sans nécessairement connaître les conditions et l'incrémentation comme l'oblige la structure for :

loop

loop (10) {
// répète 10 fois
}

- La syntaxe est conçue pour être mnémotechnique ; toutes les structures se déclarent de la même façon et ont la même logique, seuls les mots clés changent :

structures

set n = 0 ;

set f = function () {} ;

set o = object () {} ;

set a = array {} ;

- Toutes les structures sont anonymes de façon à simplifier leur imbrication et leur utilisation.

anonymes

set o = object () {

set p = object () {

set f = function () {} ;

} ;

} ;

o.p.f() ;

- L'exemple ci-dessus montre une autre simplification du langage. En AL, les classes ne sont pas définies, mais ce sont les objets qui le sont. Chaque objet référence son prototype, ce qui lui permet d'être cloné n'importe où dans un programme.

prototype

set q = new o ;

- Le point-virgule, bien que conseillé, est rendu optionnel.

- Le typage est implicite, mais les opérateurs déterminent le transtypage local, limitant ainsi les ambiguïtés (comme c'est le cas du + en JavaScript) :

Opérateur par type

set a = "7" + "7" // = 14
set s = 7 .. 7 // = "77"

I-C - Concepts avancés

Pour les plus chevronnés, voici l'idiome clé du langage AL.

AL est régi par l'idiome suivant :

- en AL, tout est expression, même array, function et object ;

- or, en AL, toute expression est un objet ;

- donc AL dispose de : meta-array, meta-function et meta-object (MOP).

AL offre donc la possibilité de modifier toute structure déjà définie.

Bref, AL est un langage d'apprentissage qui n'est pas réservé aux plus jeunes. Il peut accompagner l'apprentissage d'algorithmes complexes.

II - Intérêt d'Algoid

II-A - Multiplate-forme

Deux IDE sont disponibles pour apprendre à programmer en AL : Algoid sur plate-forme Android et AlgoIDE sur desktops (Windows, MacOS, Linux et Raspberry Pi).

Ils sont conçus comme le langage AL, simples, mais complets.

II-B - Fonctionnalités

Ces deux IDE mettent à disposition un éditeur avec coloration syntaxique, autocomplétion et code-snippets.

Ils offrent également un débogueur, un explorateur de portée et un mode d'exécution pas à pas. Ces derniers sont des outils indispensables à la compréhension du cheminement d'un programme au travers du code source.

Debogueur

Explorateur de portée

AlgoIDE débogueur et explorateur de portée

II-C - Fun

Algoid s'inspire du projet Logo. Il permet aux débutants, à partir de fonctions simples et d'un référentiel relatif, de mouvoir la petite tortue.

Une fois les notions de base acquises, comme les boucles, les branchements, les fonctions et les objets, il est possible de masquer la petite tortue et de programmer ses premiers jeux vidéo.

Algoid met à disposition une librairie graphique 2D simplifiée :

Breakout

Space invaders

Note : une librairie axée sur les sprites et permettant la gestion des animations et du son est en cours de réalisation.

II-D - Installation

Algoid et AlgoIDE sont des applications écrites en Java et donc très simples à installer et portables.

II-D-1 - Android

Algoid est une apk Android. Pour la télécharger, il suffit de se rendre sur le play store à l'adresse suivante.

II-D-2 - Windows / MacOS / Linux

AlgoIDE est le portage de l'app android sur PC. Il est exécutable comme applet directement depuis un navigateur web à l'adresse suivante (rien à installer autre que Java).

Pour une utilisation offline, algoIDE est également disponible sous forme de jnlp Java WebStart à l'adresse suivante. Il suffit de double-cliquer pour la lancer, comme toute application standard. Les applications WebStart ont pour avantage de toujours maintenir à jour la version du logiciel si l'ordinateur est connecté à Internet.

II-D-3 - Raspberry Pi

Une version optimisée d'AlgoIDE est maintenant disponible sur le Pi Store à l'adresse suivante.

Le programme d'installation se charge de tout.

II-D-3-a - Soft-Float

Si vous possédez une distribution Soft-Float de Raspbian, l'installation nécessitera celle de l'openJDK :

open-jdk

sudo apt-get install openjdk-7-jre

Une fois le JRE ou le JDK installés, il vous suffit de télécharger le jar ici, puis de le lancer avec la commande suivante :

lancement AlgoIDE

java -jar AlgoIDE-release.jar

II-E - Portabilité

Seul l'IDE et l'environnement d'exécution ont été réécrits entre les plates-formes Android, desktop et Raspberry Pi, ce qui signifie que les programmes ont le même comportement d'une plate-forme à l'autre. Seuls les événements dus aux périphériques sont différents. Lors du portage d'un script entre Algoid et algoIDE, il faut veiller à modifier les événements.

Par exemple, algo.onTouch devient algo.onDrag sur PC, algo.onTap devient algo.onClick, etc.

II-F - Performances

AL a pour but d'être ludique et quoi de plus ludique que de créer ses propres jeux vidéo ? Les jeux sont des programmes gourmands en calculs et bien que développé dans le langage Java, AL a été optimisé pour afficher des performances similaires aux autres langages interprétés.

Le benchmark suivant a été réalisé en comparaison à JavaScript et à Python sur un Mac :

Note : afin d'améliorer davantage les performances, un analyseur sémantique est à l'étude.

Ces performances permettent d'imaginer toute sorte de programmes dont le calcul est central, tel un mini-moteur 3D, par exemple :

cube 3d

splines 3d

III - Matériels pédagogiques

III-A - Communautaire

À l'heure où tout l'Internet s'invite dans nos foyers, sur nos ordinateurs, nos tablettes et notre smartphone, il serait dommage qu'un logiciel éducatif ne tire pas parti de cette abondante connectivité.

Algoid met en place différents outils communautaires pour faciliter les échanges entre les participants : un forum, accessible depuis l'application, permet d'échanger du code source entre l'IDE et les pages en un seul clic. Le forum est accessible à cette adresse.

Des outils de partage par mail, Facebook ou Google+ sont également disponibles via la plate-forme de partage Android.

Un blog sur Google+ permet également de suivre l'évolution du logiciel. Àcette adresse-ci.

III-B - Tutoriels

AL dispose aussi d'une documentation complète en français et en anglais ici.

Des tutoriels sont également disponibles ici.

Ces tutoriels et exercices ont été inspirés par les travaux de Docteur Stéphane Ducasse, auteur de nombreux livres dont Squeak: Learn programming with Robots.

Ils font l'objet d'une traduction et d'une mise en page pour le site developpez.com qu'il n'est pas nécessaire de présenter ici.

En voici la liste (mise à jour régulièrement).

III-B-1 - Partie I : Apprendre la programmation avec la tortue

- 1.1 Qu'est-ce qu'un programme ?

- 1.2 Fonctionnalités graphiques

III-B-2 - Partie II : Programmation structurée

En cours de rédaction.

Pour accélérer la documentation, le projet Algoid recrute. Alors si vous avez un peu de temps à consacrer à de la rédaction, correction ou traduction, n'hésitez pas à me contacter sur CyaNn74 (at) gmail (dot) com

IV - Remerciements

Je tiens à remercier toute ma petite famille qui ferme les yeux sur ma geek attitude et me pardonne mon manque de présence… Du moins parfois.

Tout particulièrement mon fiston Tony de 12 ans qui m'a inspiré cette belle aventure le jour où il m'a posé la question suivante : « Papa, c'est quoi la programmation ? »

Je tiens également à remercier M. Stéphane Ducasse de m'avoir autorisé à m'inspirer de ses travaux et de ses exemples extrêmement bien choisis.

Un grand merci au Dr. Didier Besset et à Jérôme Layat, qui ont été d'un grand soutien durant ce long projet.

Merci également à toute l'équipe du forum developpez.com pour leurs lectures patientes, leurs corrections (plus que patientes) et leurs encouragements très appréciés. Tout particulièrement Feanorin et Thierry Leriche Dessirier pour leur relecture technique avisée et f-leb pour ses promptes corrections orthographiques.

Vos retours nous aident à améliorer nos publications. N'hésitez donc pas à commenter cet article sur le forum : Commentez

V - Annexes

Voici certains des codes sources des illustrations de ce tutoriel.

La rosace :

rosace

set poly = function (size, n) {
loop (n) {
algo.go (size);
algo.turnLeft (360 / n);
}
};

ui.showAlgo();

loop(20) {
poly (70, 10);
algo.turnLeft (360 / 20);
}

Note : les codes sources ci-dessous sont assez longs, c'est pourquoi ils sont masqués. Pour les voir, cliquez sur la petite double flèche à droite de la zone de code.

Le jeu Breakout :

breakout

/*
Breakout clone.
Written by Yann Caron at 13-05-2013

enjoy this mini game
*/
// ---- stamps
set brickBlueST = algo.stamp.clone (array {
{-1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, -1},
{ 1,  1,  9,  9,  9,  9,  9,  9,  9,  9,  9,  1},
{ 1,  9,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1},
{ 1,  9,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1},
{-1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, -1}}, 7);

set brickRedST = algo.stamp.clone (array {
{-1,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4, -1},
{ 4,  4, 12, 12, 12, 12, 12, 12, 12, 12, 12,  4},
{ 4, 12,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4},
{ 4, 12,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4},
{-1,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4, -1}}, 7);

set brickMagentaST = algo.stamp.clone (array {
{-1,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, -1},
{ 5,  5, 13, 13, 13, 13, 13, 13, 13, 13, 13,  5},
{ 5, 13,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5},
{ 5, 13,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5},
{-1,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, -1}}, 7);

set ballST = algo.stamp.clone (array {
{-1, -1,  3,  3, -1, -1},
{-1,  3, 11, 11,  3, -1},
{ 3, 11,  3,  3,  3,  3},
{ 3, 11,  3,  3,  3,  3},
{-1,  3,  3,  3,  3, -1},
{-1, -1,  3,  3, -1, -1}}, 5);

set racketST = algo.stamp.clone (array {
{-1,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, -1},
{ 3, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,  3},
{ 3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3},
{-1,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, -1}}, 7);

// ---- objects
// stage object
set stage = object() {
set w = 470;
set h = 720;

set top = - h / 2;
set left = - w / 2;
set right = w / 2;
set bottom = h / 2;

set draw = function () {
algo.goTo(0, 0);
algo.rect(w, h);
};

set collide = function (ball) {
if (ball.x + ball.hw >= right || ball.x - ball.hw <= left ) {
ball.velX = -ball.velX;
} elseif (ball.y - ball.hh <= top) {
ball.velY = -ball.velY;
} elseif (ball.y + ball.hh >= bottom) {
// you loose
}
};

};

// brick object
set brick = object () {
set stamp;
set x;
set y;
set remain;
set hw;
set hh;

// constructor
set clone = function(x, y, stamp) {
set o = new this;
o.x = x;
o.y = y;
o.stamp = stamp;
o.hw = stamp.width / 2;
o.hh = stamp.height / 2;

// eval brick live left
if (stamp == brickRedST) {
o.remain = 4;
} elseif (stamp == brickMagentaST) {
o.remain = 2;
} else {
o.remain = 1;
}

return o;
};

// methods
set draw = function () {
algo.goTo (x, y);
stamp.draw();
};

set collide = function (ball) {
if (ball.y + ball.hh >= y - hh && ball.y - ball.hh <= y + hh && ball.x + ball.hw > x - hw && ball.x - ball.hw < x + hw) {
if (ball.y <= y - hh && ball.y >= y + hh) {
ball.velX = -ball.velX;
} else {
ball.velY =- ball.velY;
}
remain --;
if (remain == 2) {
stamp = brickMagentaST;
} elseif (remain == 1) {
stamp = brickBlueST;
} elseif (remain == 0) {
return true;
}
}
return false;
};

};

set ball = object() {
set x;
set y;
set stamp = ballST;
set velX = 10;
set velY = -10;
set hw = stamp.width / 2;
set hh = stamp.height / 2;

// methods
set draw = function () {
algo.goTo(x, y);
stamp.draw();
};

set anim = function () {
x += velX;
y += velY;

// manage collisions
stage.collide (ball);
racket.collide (ball);

if (y - hw <= collideThreshold) {
bricks.each(function (item, i) {
if (item.collide (ball)) {
bricks.remove (i);
}
});
}
};
};

set racket = object() {
set x;
set y;
set stamp = racketST;
set hw = stamp.width / 2;
set hh = stamp.height / 2;

// methods
set draw = function () {
algo.goTo(x, y);
stamp.draw();
};

set collide = function (ball) {
if (ball.y + ball.hh >= y - hh && ball.y - ball.hh <= y + hh && ball.x + ball.hw > x - hw && ball.x - ball.hw < x + hw) {
ball.velY =- ball.velY;
ball.velX = (ball.x - x) / 5;
}
};
};

// sprites level
set brickStamps = array {
{brickBlueST, brickBlueST, brickBlueST, brickBlueST, brickBlueST},
{brickBlueST, brickMagentaST, brickBlueST, brickMagentaST, brickBlueST},
{brickMagentaST, brickRedST, brickMagentaST, brickRedST, brickMagentaST},
{brickBlueST, brickMagentaST, brickRedST, brickMagentaST, brickBlueST},
{brickBlueST, brickBlueST, brickMagentaST, brickBlueST, brickBlueST},
{brickBlueST, brickBlueST, brickBlueST, brickBlueST, brickBlueST}
};

// bricks array
set bricks = array {};
set collideThreshold = stage.top;

// ---- functions
set drawLevel = function () {
stage.draw();

bricks.each(function (item) {
item.draw();
});

ball.draw();
racket.draw();
};

// get the number of element to draw simultaneous
set countStamps = function () {
set count = bricks.length(); // bricks
count += 1; // ball
count += 1; // racket
count += 1; // border
return count;
};

set run = function () {
algo.setStack(countStamps ());
ball.anim();
drawLevel();
};

// create bricks array from brickStamps
set initBricks = function () {
brickStamps.each(function (rowItem, itemY) {

// calculate center on x
set ix = (rowItem.length() - 1) * (rowItem[0].width + 7) / 2;
// set y initial position
set iy = -300;

rowItem.each (function (item, itemX) {
// calculate positions
set x = itemX * (item.width + 7) - ix;
set y = itemY * (item.height + 7) + iy;
bricks.add(brick.clone (x, y, item));
collideThreshold = math.max (collideThreshold, y + item.height / 2);
});
});
}

set init = function () {
// init
ui.showAlgo();
algo.hide();
algo.clear();

// init ball
ball.x = 0;
ball.y = stage.bottom - 100;

// init racket
racket.x = 0;
racket.y = stage.bottom - 70;

// draw bricks
initBricks();
};

// main program
init ();
util.pulse (run, 30);

set racketClearance = stage.right - racket.hw;

algo.onMove (function (x, y) {
if (x < -racketClearance) {
racket.x = -racketClearance;
} else if (x > racketClearance) {
racket.x = racketClearance;
} else {
racket.x = x;
}
});

Le jeu Space invaders :

space invaders

/*
Space invaders inspire from Tomohiro Nishikado 1978 game
Written by Yann Caron at 23-05-2012
*/

// constant
set COLUMNS = 5;
set ROWS = 3;
set GRID = 75;
set TOTAL = COLUMNS * ROWS;
set CENTER_X = - COLUMNS * GRID / 2;
set CENTER_Y = - GRID * 5;

// declaring stamps
set invader1 = algo.stamp.clone (array {
{-1, -1, 10, -1, -1, -1, -1, -1, 10, -1, -1,},
{-1, -1, -1, 10, -1, -1, -1, 10, -1, -1, -1,},
{-1, -1, 10, 10, 10, 10, 10, 10, 10, -1, -1,},
{-1, 10, 10, 12, 10, 10, 10, 12, 10, 10, -1,},
{10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,},
{10, -1, 10, 10, 10, 10, 10, 10, 10, -1, 10,},
{10, -1, 10, -1, -1, -1, -1, -1, 10, -1, 10,},
{-1, -1, -1, 10, 10, -1, 10, 10, -1, -1, -1}}, 5); // invader 1

set invader2 = algo.stamp.clone (array {
{-1, -1, 10, -1, -1, -1, -1, -1, 10, -1, -1,},
{10, -1, -1, 10, -1, -1, -1, 10, -1, -1, 10,},
{10, -1, 10, 10, 10, 10, 10, 10, 10, -1, 10,},
{10, 10, 10, 12, 10, 10, 10, 12, 10, 10, 10,},
{10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,},
{-1, 10, 10, 10, 10, 10, 10, 10, 10, 10, -1,},
{-1, -1, 10, -1, -1, -1, -1, -1, 10, -1, -1,},
{-1, 10, -1, -1, -1, -1, -1, -1, -1, 10, -1}}, 5); // invader 1 anim

set gun1 = algo.stamp.clone (array {
{-1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1,},
{-1, -1, -1, -1, 11, 11, 11, -1, -1, -1, -1,},
{-1, -1, -1, -1, 11, 11, 11, -1, -1, -1, -1,},
{-1, 11, 11, 11, 11, 11, 11, 11, 11, 11, -1,},
{11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,},
{11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}}, 5); // gun

set bulletUp = algo.stamp.clone (array {{11}, {11}, {11}, {11}}, 5); // bullet up
set bulletDown = algo.stamp.clone (array {{12}, {12}, {12}, {12}}, 5); // bullet down

// declaring
set invader = object () {
set anim = 0;
set gridX = 0;    set gridY = 0;
set x = 0;    set y = 0;
set sprite = array {invader1, invader2};

set init = function (id) {
gridX = id % COLUMNS;
gridY = math.ceil(id / COLUMNS) - 1;
gridX *= GRID;
gridY *= GRID;
};

set applyPath = function (path) {
x = CENTER_X + gridX + (path.x * GRID);
y = CENTER_Y + gridY + (path.y * GRID);
};

set hit = function (bX, bY) {
if (math.diagonal(x - bX, y - bY) < 35) {
return true;
}
return false;
};

set draw = function () {
anim = (anim + 1) % 2;
algo.goTo(x, y);
sprite[anim].draw();
};

};

set gun = object () {
set x = 0;
set GUN_Y = 4 * GRID;
set sprite = gun1;

set draw = function () {
algo.goTo(x, GUN_Y);
sprite.draw();
};
};

set bullet = object () {
set sprite;
set way;
set x;
set y;

set init = function (up, x, y) {
x = x;
y = y;
if (up) {
sprite = bulletUp;
way = -20;
} else {
sprite = bulletDown;
way = 20;
}
};

set isIn = function (objs) {
set l = objs.length() - 1;
return y.between (objs[0].y, objs[l].y);
};

set hit = function (objects) {
set h = false;
if (isIn (objects)) {
objects.each (function (item, i) {
if (item.hit(x, y)) {
h = true;
objects.remove(i);
}
});
}
if (y < -algo.getHeight() / 2) {
h = true;
}
return h;
};

set draw = function () {
y += way;
algo.goTo(x, y);
sprite.draw();
};
};

set path = object () {
set W = 3;
set H = 5;
set step = 1;
set x = -2;
set y = 0;
set end = false;

set next = function () {
x += step;
if (x >= W || x <= -W + 1) {
step *= -1; // invert step
x += step;
y++;
}

if (y >= H) {
end = true;
}
};

};

set loops = 0;
set invaders = array {};
set bullets = array {};

set setStack = function () {
set i = 1;
i +=  invaders.length();
i +=  bullets.length();
algo.setStack(i);
};

TOTAL.loopFor (function (i) {
invaders[i] = new invader;
invaders[i].init(i+1);
});

// run
set runGame = function () {
setStack();
gun.draw();
bullets.each (function (item, i) {
item.draw();
set b = item.hit(invaders);
if (b) {
bullets.remove(i);
}
});

if (loops == 0) {
path.next();
invaders.each (function (item) {
item.applyPath(path);
});
}
loops = (loops + 1) % 5;

invaders.each (function (item) {
item.draw();
});

};

set action = function (x, y) {
gun.x = x;
set b = new bullet;
b.init(true, x, gun.GUN_Y);
bullets[bullets.length()] = b;
};

// initialize
ui.showAlgo();
algo.hide();

// events
algo.onClick(action);
util.pulse(runGame, 100);

Celui du moteur 3D spline :

3d

/*
3d sample code.
Written by Yann Caron at 27-05-2012
*/

// the point 3d object
set pt3d = object () {
set x;    set y;    set z;
set px = 0; set py = 0; set FOCAL = 1000;

// clone constructor
set clone = function (x, y, z) {
set o = new this;
o.x = x;
o.y = y;
o.z = z;
return o;
};

// rotate on X axis
set rotateX = function (a){

// calc rotation
set ca = math.cos(a);
set sa = math.sin(a);

// rotate on X
set ty = y * ca - z * sa;
set tz = y * sa + z * ca;

// apply
y = ty;
z = tz;

};

// rotate on Y axis
set rotateY = function (a){

// calc rotation
set ca = math.cos(a);
set sa = math.sin(a);

// rotate on Y
set tx = x * ca + z * sa;
set tz = x * -sa + z * ca;

// apply
x = tx;
z = tz;

};

set transformPersp = function () {
set pers = FOCAL / (FOCAL - z);
px = x * pers;
py = y * pers;
return pers;
};

};

// the face object
set face = object () {
set pts;

set clone = function (pts) {
set o = new this;
o.pts = pts;
return o;
};

// render line to viewport
set render = function () {
set curveArray = array{};

pts.each (function (item) {
item.transformPersp();
curveArray.add(item.px);
curveArray.add(item.py);
});

algo.setColor(7);
algo.setAlpha(0.25);
algo.curvedPoly(curveArray);

algo.setAlpha(1);
algo.curve(curveArray);

algo.setColor(3);
algo.setAlpha(0.25);
algo.path(curveArray);

};

};

set line = object() {
set pts;

set clone = function (pts) {
set o = new this;
o.pts = pts;
return o;
};

set render = function () {
set curveArray = array{};

pts.each (function (item) {
item.transformPersp();
curveArray.add(item.px);
curveArray.add(item.py);
});

algo.setColor(3);
algo.setAlpha(0.25);
algo.path(curveArray);
};
};

// the cube points
set pts = array {
pt3d.clone (0, -200, 0),
pt3d.clone (50, -100, 0),
pt3d.clone (250, 0, 0),
pt3d.clone (50, 100, 0),
pt3d.clone (0, 200, 0),

pt3d.clone (35, -100, 35),
pt3d.clone (176, 0, 176),
pt3d.clone (35, 100, 35),

pt3d.clone (0, -100, 50),
pt3d.clone (0, 0, 250),
pt3d.clone (0, 100, 50),

pt3d.clone (-35, -100, 35),
pt3d.clone (-176, 0, 176),
pt3d.clone (-35, 100, 35),

pt3d.clone (-50, -100, 0),
pt3d.clone (-250, 0, 0),
pt3d.clone (-50, 100, 0),

pt3d.clone (-35, -100, -35),
pt3d.clone (-176, 0, -176),
pt3d.clone (-35, 100, -35),

pt3d.clone (0, -100, -50),
pt3d.clone (0, 0, -250),
pt3d.clone (0, 100, -50),

pt3d.clone (35, -100, -35),
pt3d.clone (176, 0, -176),
pt3d.clone (35, 100, -35),

};

// the cube faces
set faces = array {
face.clone(array {pts[0], pts[1], pts[2], pts[3], pts[4]}),
face.clone(array {pts[0], pts[5], pts[6], pts[7], pts[4]}),
face.clone(array {pts[0], pts[8], pts[9], pts[10], pts[4]}),
face.clone(array {pts[0], pts[11], pts[12], pts[13], pts[4]}),
face.clone(array {pts[0], pts[14], pts[15], pts[16], pts[4]}),
face.clone(array {pts[0], pts[17], pts[18], pts[19], pts[4]}),
face.clone(array {pts[0], pts[20], pts[21], pts[22], pts[4]}),
face.clone(array {pts[0], pts[23], pts[24], pts[25], pts[4]})
};

set a = -2;
set b = 0.5;
set ax = 0;
set ay = 0;

// count the number of element to draw
set count = function () {
set i;
i += faces.length () * 3;
return i;
};

// render loop
set render = function () {
pts.each(function (item) {
item.rotateX(-b);
item.rotateY(a);
});

faces.each (function (item) {
item.render();
});
};

set anchor = function (x, y) {
ax = x;
ay = y;
};

// rotate on touch event
set rotate = function (x, y) {
a = (x - ax) % 20;
b = (y - ay) % 20;

render();

ax = x;
ay = y;
};

// program
ui.showAlgo();
algo.hide();
algo.setStack(count());

util.pulse(render, 40);
algo.onClick(anchor);
algo.onDrag (rotate);

Tous ces codes d'exemples sont directement accessibles depuis l'application. Les algorithmes présentés s'étendent des plus simples aux plus complexes (comme les jeux présentés ici).