Travailler avec les clôtures lexicales
dans Powershell (1/2)

Certaines procédures inscrites au cœur de la création d'un jeu vidéo suggèrent souvent l'utilisation de langages de script. Qu'il s'agisse d'aménager un processus de compilation ou plus simplement de générer des Assets, ces langages apparaissent définitivement utiles.

Dans cette perspective, une approche intéressante (que d'aucuns qualifieront peut-être de marginale) consiste à se tourner vers Powershell, une solution développée et éditée par Microsoft. Construit par dessus l'écosystème .net, Powershell repose sur une bibliothèque riche en fonctionnalités. Il est bien entendu laissé à l'appréciation du développeur de le substituer à d'autres outils plus conventionnels tels que Node.js ou Python.

Généralement comprise dans la boite à outils du développeur, la clôture lexicale (ou en anglais : function closure) est une technique à tonalité fonctionnelle souvent impliquée dans des pratiques de programmation originales. Transposer cette technique vers Powershell n'est cependant pas trivial et va demander une certaine gymnastique pour y parvenir. Un exercice simple consiste à prendre pour exemple ce code Javascript:

/* Javascript */
let $bar = 820;
label: { let $bar = 23; var $foo = () => ++$bar; }
$foo(); // affiche "24"
$foo(); // affiche "25"
$bar; // affiche "820"

Par deux fois dans le code, une variable $bar est déclarée. D'abord, à titre global et, enfin, au sein du bloc étiqueté label. Dans le bloc label, la variable est privée et a la durée de vie de la fonction $foo qui la capture. La portée d'une variable Javascript est dite lexicale. Une tentative inspirée mais erronée de transposer vers Powershell pourrait ressembler au code suivant:

<# Powershell #>
[int32]$bar = 820;
$foo = & {
  [int32]$bar = 23;
  Return { set -scope 1 'bar' ($bar+1) ; $bar }
}
& $foo; # affiche "821"
& $foo; # affiche "822"
$bar; # affiche "822"

Le code exécuté fait apparaître des différences immédiatement perceptibles. Powershell adopte la méthode de portée dynamique où la durée de vie d'une variable dépend de la position de sa création dans la pile d'appels. Dans l'exemple, la seconde variable $bar, à laquelle a été assignée la valeur 23, n'est plus disponible dans l'étendue dynamique au moment d'appeler le bloc d'instructions $foo. La portée appelante intervient dans un niveau parent de l'étendue où la liaison originelle a disparu. L'acheminement d'une variable dans la chaîne d'appels s'illustre simplement ci-dessous:

<# Powershell et portée dynamique de variable #>
$foo = { ('«',$bar,'»' -join '') }
& { $bar = 'Hello'; & $foo } # affiche "«Hello»"
& { $bar = 'World'; & $foo } # affiche "«World»"

Cette manière de composer, sans doute peu ordinaire, présente des perspectives de conception intéressantes lors d'un développement. Point d'ancrage utile qui permet de se diriger, à l'occasion du prochain billet, vers une mise en œuvre concrète de la clôture au sein du langage.

Le cycle Jour-Nuit au service du gameplay
dans Castlevania 2

Au rythme d'une aventure à monde ouvert, Castlevania 2 Simon's Quest invite le joueur dans une quête centrée sur l'exploration. Le titre, conçu pour la première Nes et sorti en 1990 sur le vieux continent, puise son originalité dans la dynamique de jeu inspirée par l'utilisation du cycle Jour-Nuit. Une mécanique intéressante qui dénote, à l'époque, un certain renouveau.

Pétries de limitations techniques, les premières générations de consoles sont néanmoins honorablement représentées par l'ingéniosité saisissante de certains créateurs de jeux vidéo. Parvenir à extirper l'innovation d'un environnement technologique difficile peut sembler hors sujet aujourd'hui mais c'est un exercice censé, peut-être, nous interpeller.

Des griffes dans la nuit

Chaque nuit, dans Simon's Quest, comme pour rappeler la tonalité horrifique du titre, les environnements succombent à des teintes de couleurs inquiétantes. Mais les effets ne sont pas seulement visuels et interviennent, par ailleurs, sur l'expérience de jeu en révélant des monstres plus dangereux et résistants la nuit tombée.

L'ambiance nocturne n'épargne pas non plus les villes dont les rues (globalement accueillantes en journée) sont alors infestées de zombies. Affronter les dangers que la nuit réserve précise les chances de terminer l'aventure avant que Dracula (l'antagoniste principal de la série) n'ait définitivement étendu son influence sur le monde.

En ville, les
  ténèbres se joignent à la nuit.
En ville, les ténèbres se joignent à la nuit.

Castlevania 2 aménage le gameplay autour d'un concept simple mais riche en possibilités. Ici, les développeurs sont parvenus à faire preuve de créativité tout en réduisant leur dépendance aux technologies. Une source d'inspiration définitivement utile pour le créateur.