Connaissez-vous le Brainf***? C’est un langage de programmation ultra-minimaliste inventé par un compatriote helvétique dans le but avoué de torturer les neurones des programmeurs de tous poils.
J’ai profité de quelques instants libres pour travailler un peu mon C++ en écrivant un énième interpréteur pour ce langage. Il se veut standard, sans fioritures, et donc sans intérêt par rapport aux nombreuses alternatives déjà disponibles, mais après tout, c’était à but purement éducatif.
Fractale de Mandelbrot générée en Brainf***
Vous trouverez une solution Visual Studio 2008 contenant du C++ tout ce qu’il y a de plus ANSI à cette adresse. De plus, le script permettant de générer cette jolie fractale est disponible par ici. D’ailleurs, plein de scripts et d’outils liés à ce merveilleux langage sont disponibles sur ce site.
Ce week-end, j’ai fait mes premiers pas en utilisant Python. J’avais évidemment entendu parler de nombreuses fois de ce langages au cours de diverses discussions et dans le domaine professionnel (notamment parce que je bosse avec Trac), mais je n’avais jamais mis les mains dans le cambouis pour voir quel tronche ça avait.
En lisant The Pragmatic Programmer, je suis tombé sur une recommendation du style « étudiez au moins un langage par an », et ça m’a motivé. Du coup, voilà. Et ben putain, j’aurais du faire ça plus tôt. C’est carrément ultime. Syntaxe simple, légère, peu capricieuse mais forçant la lisibilité, documentation bien foutue, tutos poussés vraiment intéressants, vitesse d’execution excellente, grande quantité de bibliothèques, …
Je me réjouis vraiment d’utiliser ça dans un contexte un peu plus serieux que dans ma petite sandbox. Allez, je suis sûr qu’il va bien falloir deux ou trois moulinettes à coder dans la semaine qui arrive… Histoire de me mettre dans le bain et de passer en revue le langage rapidement, j’ai réimplémenté un algo que l’on utilise sur Dofus pour la génération des noms de personnages, et qui est accessoirement ultra-connu: les chaînes de Markov.
Z’allez voir, c’est que du bonheur.
Lire la suite…
Tout le monde aura déjà écrit un code de ce genre :
var ldr : Loader = new Loader();
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
ldr.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
ldr.load(new URLRequest("http://www.bidon.com/trucmuche.jpg"));
Ca marche bien. Mais il se trouve que dans mon projet, on a tendance à avoir besoin de beaucoup, beaucoup de loaders. Je me suis donc dit « Allons, Tyn, utilise donc un pool ! » Ce qui marche également bien. On a un gain de plus de 1000% en utilisant un pool de Loader
plutôt que d’en créer de nouveaux à chaque fois.
Mais qui dit pool dit nettoyage d’objet, et rendu dudit objet au pool après son utilisation. Hors, dans ce cas précis, j’ai un gros soucis: je ne peux pas récupérer mon objet Loader
dans mon callback onIOError
! C’est quand même très, très con. Ca signifie que je perds un élément de mon pool à chaque URL foireuse, ce qui est un leak inacceptable.
Voici donc un contournement foireux pour récupérer son objet Loader
depuis un callback où LoaderInfo.loader
n’est pas encore renseigné:
package net.tynambule.exp {
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import flash.utils.Dictionary;
public class IOErrorCallbackWithLoader extends Sprite
{
private var _loaders : Dictionary = new Dictionary(true);
public function IOErrorCallbackWithLoader()
{
var ldr : Loader = new Loader();
ldr.contentLoaderInfo.addEventListener(Event.INIT, onInit);
ldr.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
// Feinte ici :
_loaders[ldr.contentLoaderInfo] = ldr;
ldr.load(new URLRequest("existe-po.png"));
}
private function onInit(e : Event) : void
{
trace("Trop bien, le fichier existait!");
// Ne pas oublier d'effacer ma référence, histoire que mon Loader puisse
// être garbage collecté.
delete _loaders[e.target];
}
private function onIOError(ioe : IOErrorEvent) : void
{
trace("Le fichier existait pas, mais j'ai toujours mon loader!");
trace("Le voici :" + _loaders[ioe.target]);
// Ne pas oublier d'effacer ma référence, histoire que mon Loader puisse
// être garbage collecté.
delete _loaders[ioe.target];
}
} }
Et hop. C’est quand même bien crade. Si un gentil développeur de chez Adobe passe par ici (sait-on jamais), c’est quand même con que le Loader
ne soit pas accessible depuis l’objet LoaderInfo
en cas d’erreur de chargement alors qu’il est disponible avant le chargement. Allez, salut.
En AS3, on peut faire un chouette truc tel que décrit dans le billet sur les balises embed, à savoir ceci :
package net.tynambule.exp {
import flash.display.Sprite;
[Embed(source="assets/test.swf", symbol="test")]
public class PrivateEmbed extends Sprite
{
public function PrivateEmbed()
{
}
}
}
(Pour les détails, se référer au billet sur la métadonnée embed.)
Maintenant, imaginons que dans notre symbole « test », on aie un TextField
qui se nomme « _tfFoo
« . Dans notre classe décrivant ce symbole, on en aura certainement besoin. Tout naturellement, je l’aurais ajouté en faisant :
package net.tynambule.exp {
import flash.display.Sprite;
import flash.text.TextField;
[Embed(source="assets/test.swf", symbol="test")]
public class PrivateEmbed extends Sprite
{
internal var _tfFoo : TextField;
public function PrivateEmbed()
{
}
}
}
Sauf qu’en fait non. Si on fait ça, le compilateur gueule :
ReferenceError: Error #1056: Impossible de créer la propriété _foo sur net.tynambule.exp.PrivateEmbed. at flash.display::Sprite/flash.display:Sprite::constructChildren() at flash.display::Sprite$iinit() at net.tynambule.exp::PrivateEmbed$iinit()[Y:\Code\Workspace\Exp\src\net\tynambule\exp\PrivateEmbed.as:11] at net.tynambule.exp::PrivateEmbedContainer$iinit()[Y:\Code\Workspace\Exp\src\net\tynambule\exp\PrivateEmbedContainer.as:12]
Pourquoi? Parce que les éléments placés sur la scène dans un symbol embed ne sont pas internal
(ni private
, ni protected
), mais… public
. Ce qui m’oblige à réécrire :
public var _tfFoo : TextField;
Et là, ça marche. Sauf que moi, j’aurais bien aimé que mon joli TextField
ne soit pas accessible depuis n’importe où dans mon code, vu que je préfère quand l’interface est planquée dans son coin et qu’elle n’a rien à voir avec la logique.
Voili voilou, c’est pas très joli et c’est un peu prise de tête de piger pourquoi ça foire. J’me demande pourquoi Adobe a fait ça. Snif. Allez, salut.
Parfois, avec Flash, il faut savoir réinventer la roue. Par exemple, lorsque l’on veut coder un moteur d’animation qui s’intègre au sein d’un système de rendu isométrique complexe, on aimerait à la foi pouvoir disposer d’un framerate le plus élevé possible, tout en jouant les animations au framerate dans lequel elles ont été réalisées.
Pour se faire, il faut obligatoirement passer par l’indispensable case du calcul du framerate en cours. Il existe peut-être des mondes merveilleux ou la valeur que l’on a entrée dans le champ « Nombre d’images par secondes » de l’IDE Flash est tout le temps vraie, mais il ne s’agit pas du notre.
Voyons différentes approches pour calculer un framerate.
Lire la suite…
Commentaires récents