Wednesday, April 30, 2008

Obey Gravity

Hehe. un autre pas sympathique est franchi: Bilou tombe. Ouais, ouais, je sais, ça n'a l'air de rien comme ça, mais quand il arrive sur le sol, il arrête de tomber.
En clair, le mécanisme des contrôleurs dont je vous parlais l'autre jour, bin ça y est: c'est fait aussi.

Et assez élégamment, je dois dire. On peut coder tous les contrôleurs qu'on veut (ici gravity qui fait tomber et stopper qui remet la vitesse à zéro quand on arrive sur le sol) à l'extérieur du moteur de jeu et simplement les nommer dans la définition de nos états.

Reste donc juste à coder le support des actions et des prédicats à attacher aux transitions (genre, lorsque l'on a fini de tomber "rebondis si vitesse>seuil, sinon atteris"). Et là, ça va être un gros morceau.

Another milestone has been met by my Game Engine today. Bilou's falling. Oh, well, i know, it's hardly impressive, but he also stops falling when hitting the ground. In other words, i'm done with the introduction of controllers that can externally control the behaviour of sprites in the game (in that case, the gravity controller increases the vertical speed periodically and reflect button presses on horizontal speed). Now all i'm left to implement is the support for actions (like 'stop falling' when ground is detected) and predicates (such as 'if speed>200' on a transition towards 'bounce' state in addition to a (default) transition towards safe landing).

Of course, it wouldn't be worth a post if i was to program this for Bilou only (after all, having characters that fall is the most elementary technique of game programming), but i'm trying to build the bricks for an "Ultimate Game Maker" on the DS here ... so i address things a slightly different way to allow edition of behaviours without requiring lines of code to be written...

Alors okay, je vous donne peut-être l'impression de faire tout un fromage d'un truc élémentaire (faire tomber quelque-chose, c'est quand-même le B.A.BA de la programmation des jeux), mais le truc ici, c'est que ne cherche pas juste à faire le jeu "Bilou", évidemment (sinon je ne m'y prendrais pas comme ça), mais plutôt à construire les briques d'un "Ultimate Game Maker" sur la DS.

Tuesday, April 29, 2008

GameObject : public Animator

Bin voilà. Hier soir j'ai fait le point sur tout ce qui tourne autour de ma classe GameObject qui assure la gestion des monstres et compagnie. C'est déjà un peu le méli-mélo, et je dois rajouter là-dessus des objets multi-sprites (pensez à une chenille, et vous êtes dans le bon) et surtout les contrôleurs, capables d'influencer le comportement des monstres en assurant ce que les petits scripts et les machines d'état ne sauraient pas proposer.

Je m'explique.

Prenez un sprite comme le petit ver. Il a principalement deux états (avancer vers la gauche ou avancer vers la droite). Chacun de ces états est lié à une animation (qui entre-autres le fait bouger) et définit les conditions sur les testpoints nécessaires pour rester dans cet état (pas de mur devant lui, et du sol en-dessous). Lorsqu'un des testpoints n'est plus bon, on cherche une transition à appliquer pour passer dans un nouvel état (en l'occurence, il y a une seule transition, vers l'autre état).

En gros, c'est super-simple.

I shoot a picture of my attempt to summarize the OO design of my GameObject class (later on called "GOB" through code and blog) and everything sitting around. Let's see that with a simple example such as the WoodWorm, that simply move forward and backward on platform. The worm has mainly two states depending on its direction. Each state has an associated animation and defines conditions expressed on testpoints that must be met so that we can remain in that state. Namely, when moving to the right, the worm must have some ground behind him and no wall in front of him. When testpoints are no longer valids, we look for a transition that will lead us towards a new (valid) state.

L'appleman, lui, est un peu plus sophistiqué: il se balade également au sol (avec les 2 même états), mais lorsqu'il arrive au bout d'une branche, il peut décider de sauter au sol pour attaquer Bilou si

  1. Bilou est en-dessous de lui
  2. Bilou n'est pas trop loin.
Le contrôleur, dans le cas de l'appleman, est passif: il se contente de lui rapporter sa position relative par rapport à sa "cible" (Bilou) et c'est via les prédicats des transitions (que je n'ai pas encore implémentés :P ) que la décision de faire demi-tour ou sauter se prendra.

More sophisticated GOBs, such as the Appleman, have a behaviour that does not depend only from test points. When reaching the edge of a cliff/platform, the Appleman will either turn back if Bilou is not in its attack range or jump off if Bilou sits below him in attack range. I intend to build that by means of controllers: C++ objects attached to a state that affect either directly (altering speed) or indirectly (indicating the presence of Bilou) the behaviour of GOBs. Even reading the Dpad and moving the hero accordingly can be achieved by a controller.
This should give us flexibility while reducing the amount of CPU power thrown at interpreting scripts.

Si on prend maintenant notre copain AppleBat, il dépend aussi de la position de Bilou pour son déplacement, mais il accélère et suit Bilou. Pour faire ça proprement, je vais laisser à son contrôleur le soin d'ajuster sa vitesse automatiquement pour se dirriger vers la cible. Tout ce que le script aura alors à prendre en compte, c'est le choix de l'image utilisée (pour que l'applebat continue à regarder vers Bilou quand il le dépasse).

Le reste, à mon avis, c'est du détail de bricolage de colle, donc je vous laisse le soin de déchiffrer mes gribouillis en cliquant sur les images si ça vous intéresse.

En d'autres temps, d'autres lieu, tout ça aurait pu faire une bonne autre lettre à Gédéon ;)

edit: partly obsoleted by this post and that post.

Sunday, April 27, 2008

Ca, c'est fait.

runme demo #1 runme & LEDS demo # 2 leds & runme demo #3
runme & LEDS demo # 4Voilà, maintenant runme parvient à me charger des niveaux sur deux plans de tiles, et il scrolle dedans assez allègrement, ma foi. J'en ai profité pour ajuster le code de gestion des ennemis qui se servent du coup du "plan d'informations" (meta-layer) pour savoir s'ils sont dans un mur, sur le sol, dans le vide, etc.

Tout ça a finalement été beaucoup plus facilement que je ne l'avais imaginé ... Et, bande de p'tits veinards, je vous ai fait toute une démo de la chose en vidéo sur youtube pour la postérité, le tout commenté par votre serviteur.

It's not always easy to give you a correct idea of what my game development environment on the DS look like ... and it's certainly not easy to "show" how animations work with ... screenshots. So i decided to take the time to shoot these small videos where i'm doing some simple editions on my demo-level for Bilou's forest, swapping from the game engine (runme) to the level editor and back. It's commented in french, and unfortunately very blurry, but it's there.
And it means i now have dual-plane level scrolling in the game engine, with sprites that use per-tile metadata to tell the level properties (rather than just using tile numbers, obviously allowing secret passages) and animated bonuses ^_^

Bon, ceci dit, tout ça ne nous rendra pas la maison plus en ordre, donc j'vais m'atteler un peu au rangement de tout ce désordre qui s'est accumulé pendant mes scéances de crazy-coding. Restera à faire bouger les pommes ^_^ C'est fait aussi :P

Thursday, April 24, 2008

un peu de patience ...

L'état de mon éditeur de niveau me satisfait pour l'instant. C'est en tout cas suffisant pour reprendre le développement de mon moteur de jeu là où je l'avais laissé en découvrant un petit ver jaune bloqué dans la terre d'un passage secret...

Evidemment, ce n'est pas tout d'avoir une map sur deux niveaux avec des indications sur "qu'est-ce qui est solide, qu'est-ce qui ne l'est pas". Encore faut-il avoir la possibilité de construire un niveau à partir d'une telle map. Et ça, ce n'était pas encore tout à fait prévu dans ma classe GameScript, qui donnait un tileset et une map séparés à chaque plan d'affichage. C'est pas la fin du monde, mais ça demande de me replonger un peu dans le fonctionnement de GameScript, iCamera, iWorld, iLevel, etc.

Vous ne voyez plus trop de quoi je parle ? C'est vrai que ça remonte à décembre. Allez, pourquoi ne pas se faire une rétrospective des progrès sur la "green zone" sur DS ?

Monday, April 21, 2008

Solide ou pas?

00003 Hop. Petite preview rapide de ce que donne l'édition des propriétés du niveau dans LEDS. C'est encore très basique (il faut donner les propriétés tile par tile, à grand coup de stylet), mais ça permet déjà de bricoler.

Bien sûr, à terme, c'est directement sur le tileset que l'on donnera des propriétés (genre, tous les bonus ont le type spécial 0001), et le mode d'édition que je viens de fignoler sera là uniquement pour les retouches, les passages secrets, etc.

Quick news: now i can edit tiles properties with my Level Editor ... well, it's all still very sketchy and unperfect, but it stores 4-bit attributes where they're supposed to go for the Game Engine, and allows maps to be saved/reloaded. I intend to extend the system so that attributes can be defined on blocks in the tileset, rather than only on the map, but an unexpected side-effect of block cut-and-paste allows me to quickly build a big set of blocks that will be solid and refine afterwards.
It's a great tool for building secret passages too ^_^

edit: marrant. Je viens de faire la démo à Cyril et de me rendre compte d'un effet de bord imprévu: quand on repasse en édition "normale" de la map et que l'on copie des blocs pour lesquels on a changé les métadata, on copie en même temps les métadata pour le nouveau bloc. C'est déjà plus viable comme ça ^_^ ...

Sunday, April 20, 2008

Pour quelques lignes de code en plus

Oh, pas grand chose... un p'tit curseur, un peu de transparence, et surtout un changement de gestion des touches qui me permet de retourner dans le menu depuis l'écran d'édition (sans devoir re-télécharger tout l'éditeur ;)

Et surtout, un tout nouveau bouton "save" sur l'écran de menu en question (en supposant que l'utilisateur a donné un nom à sa nouvelle map, ce qui n'est pas vraiment spontané avec l'interface actuelle... gare donc aux "autoexec.map" :)

Bin oui, hier les petits tests du "level editor" se sont fait de plus en plus longs, et les maps devenaient presque intéressantes, au point que j'ai regretté de ne pas pouvoir les sauver. En général, c'est un assez bon indicateur que le soft a atteint un niveau suffisant d'utilisabilité.

J'ai un peu dû chipoter pour autoriser le mode "survol", aussi (un dé-zoom de la map, en quelque sortes), parce que si le hardware de la DS permet effectivement de faire des zooms sur des plans, celà implique que l'on se limite à 256 tiles (or, j'en utilise 1024 dans le Level Editor) :P BG_BMP8_256x256 à la rescouuusse.

J'ai un peu avancé dans les bricoles nécessaires pour pouvoir éditer le "méta-layer" qui décide si les blocs sont solides où non ... mais là, je suis mort-vanné, donc je vais aller faire une souckette dans le divan en attendant que ma fée revienne des 30 d'agriculture Bio à la ferme de son oncle (Albert Counasse, à Chauveheid).

edit: chargements/sauvegardes: c'est réglé. Si vous voulez essayer la version 0.1 beta de mon éditeur de niveaux, servez-vous.

Thursday, April 17, 2008

Level Editor on DS : première photo !

IMG_0507Le voilà! J'ai enfin une photo potable de mon LEvel Editor (dont la plupart des "bêtes bugs" sont maintenant corrigés). Reste à améliorer son ergonomie (parce que là, on choisit son bloc "en aveugle" et pour peu qu'il faille un peu scroller, on attrape vite des crampes avec ces L+<direction>).

At last! Here's the first picture of my Level Editor. Most of the "stupid" bugs have been fixed and all i have to do is adding features (most notably saving your work) and improving the user interface. Switching from sprites to tile for the "available blocks" on the upper screen now allowed me to have up to 144 blocks immediately available (you can also select other 'pages', but page flipping may get annoying).

Btw, building levels on two layers is fun, and allows lot of amusing hacks such as using treetops as bushes in front of (or behind) other objects. I also intend to have a third "virtual" plane for collision information, so whether something is a wall or not is completely independent from whether you see the wall or not (and whether you have something in from/behind it). That means you can build your wall of dirt with the dirt being sometimes behind grass, and sometimes in front of (deeper) dirt. All this with only two planes.

Bon, évidemment, je n'ai pas encore de sauvegarde, donc c'est un peu idiot, mais ça permet déjà de se faire une petite idée. J'aime bien les sommets d'arbres "retravaillés" en buissons, tiens... Reste donc:

  • à pouvoir sauver son travail
  • écrire un petit widget "curseur" pour savoir quel bloc j'utilise
  • passer les blocs de l'avant plan en transparence pendant qu'on édite l'arrière-plan
  • deux modes de dessins : "un bloc à la fois" ou "tout un objet" (en cliquant sur des positions consécutives dans la map, on copie des blocs consécutifs du tileset, plutôt que de répéter tout le temps le même bloc. Ce sera chouette pour les arbres.
  • un mode "survol", pour se déplacer rapidement dans la map ...
Et bien évidemment, il faut que je rajoute la gestion des "méta-données" qui indiquent si un bloc et bloquant ou non, s'il s'agit d'un bonus, etc. Mais c'est déjà un bon début.

Monday, April 14, 2008

A propos ...

        ||///
@ . .
----ooo--( )--ooo----

Ce blog est dédié à mes tests/programmes/jeux(?) sur la console nintendo DS, mais aussi à tout ce qui pourrait me permettre de redonner vie au jeu "Bilou's Adventure".

3eme planète du Système Solaire, un gars bizarre dessine des balles bleues et écrit des programmes ... C'est moi ;) Les copains, si vous m'avez lu, laissez-moi un commentaire de temps en temps, c'est toujours sympa ^_^


Si ça ne satisfait pas encore votre curiosité, je vous invite à dévorer ma fiche parano.be, désormais effacée par l'Ordinateur, ou la petite FAQ du projet "Bilou sur DS", voire (pourquoi pas) vous faire une rétrospective du projet : la green zone et la préparation de la school zone

PS: n'oubliez pas de signer le livre d'or

Level Editor en cours

Allez, j'ai fait ma petite "todo list" des modif à apporter à mon éditeur de niveau (qui sait déjà gérer deux plans séparés pour construire les niveaux depuis vendredi soir). On s'y met pour le code (y'a pas mal de boulot).

  • [done] SpriteSet::Load() and SpriteSet::Save() support for extra datablocks.
  • [done] TileTable that works like SpriteTable widget, but using tiles, not sprites
  • [unlikely] Grid and Palette widgets that use multiple 16-color palettes instead of 256-color palette to reduce the amount of unique tiles needed by the widgets
  • [done] fit all the widgets within 16K Vram *max* (one 'charbase'), including maps. Everything beyond 16K is free for allocation using Engine::allocate(RES_TILES). That would make 16-color ASCII font (8K -- well, i'm unlikely to need extended ascii characters, so i could replace those upper 4K with widget-specific tiles)
  • [done] a cleaner way to manipulate up to two layers in an application-dedicated way (e.g. standard widgets in libgeds will not use these). That means only "standard" layers are background and (ascii) overlay.
  • [wish] SpritePages that can share tiles among many blocs
  • [done] extra tilesets in the file to store animations out of the 64K of tileset VRAM allows.
  • [done] SpriteSet that automatically insert blank tile #0
edit: c'est assez marrant de voir que c'est principalement ce que j'avais marqué comme "souhaité, mais pas vraiment nécessaire" qui s'est quand-même retrouvé implémenté en premier :P

Friday, April 11, 2008

Ravalement de Façade (de donjon)

1. Relooking des couleurs ...
'Faut comparer des choses comparables. A noter déjà qu'il y a 3 teintes dans la plupart des blocs "sols" dans ZLA contre seulement 2 dans OOS. Et avec 2 teintes, on sait juste donner un look 'peinture', pas de relief.
So, I picked a room in "Zelda: Oracle of Seasons" and applied the tail cave look of "Zelda: Link's Awakening DX" on the right. Just that already makes the ZOOS version look flat and dull, with only 2 colours for most floor tiles.
 
2. Un peu plus de relief
Assez facile aussi. Une troisième teinte de mauve, un peu plus désaturée et plus sombre, et je "bumpe" les pavés mauves qui entourent l'escalier. Notez qu'en laissant tomber le contour jaune, je ne consomme en fait pas plus de couleurs que les tiles d'origine.
As a first step, I replaced the "2 purple + 1 yellow" palette with "3 purple", in order to "bevel" more the decorative tiles around the stair.

3. Un peu moins "rectangle".
Cassons les coins de cette salle, que diable. C'est un donjon, quoi, pas une salle de bal. Un gros donjon bien lourd = des gros piliers massifs pour soutenir le toit = des coins pas droits. J'en profite pour épaissir les traits au pied des murs. Ca renforce l'impression de lourdeur (c't'un mur, quoi, pas un bête escalier).
Second step: breaking the corner, to make the room visually more interesting. This was done a lot in ZLA. I also increase the black outline to make the walls more massive-looking (compared to the stairs, for instance)

4. La touche finale
Ces p'tits blocs qui ne servent à rien qu'à décorer et à être dans le chemin. Bin voilà. Mettons-les dans le chemin pour décorer ^_^ (moitié OOS, moitié ZLA, bien sûr).
Next, some decorative obstacles such as those statues (and why not fire lights in the corners, after all ;) That helps giving the room its own "personality" (you could "name" the place to another player without having to rely on a coordinate system), and it makes monsters fighting more interesting, as it it enables hide/seek.

Je ne sais pas vous, mais je trouve que le niveau y gagne en intérêt. Pour être tout à fait juste, j'aurais dû refaire le sol de OOS avec 3 teintes aussi, pour ne pas qu'il reste aussi plat. Mais bof, il ne me convainc de toutes façons pas, donc je le laisse comme ça. Allez, hop, j'ai trouvé la 3eme teinte de "vert-gameboy" sur un switch, elle est plus sombre, donc j'assombris le tout. On note que ça passe mieux avec les murs, du coup. J'ajoute aussi du relief avec la teinte "claire" qui était au départ la plus présente et voilà le résultat: Poison Moth's Lair comme il aurait pu (dû?) l'être si Nintendo n'avait pas essayé de sortir 2 zelda en même temps (?)

Final touch is on the ground. There's a 3rd tint in the yellow palette, as confirmed by a switch tile somewhere further in the dungeon, so I moved the floor to the two darkest shades, and kept the lightest one for selective highlights. That makes "Moth's Lair" as it should (imho) have looked like if Nintendo wasn't trying to have two Zelda games released simultaneously.
That being said, I have no programmable GBC/GBA to check that it would indeed be good-looking on the no-backlit GBC screen ...

Zelda DX vs Zelda OOS

Eh oui. Je me refais (encore) Link's Awakening. Entrée dans le donjon 6 avec l'arc et le boomerang, sortie avec l'épée niveau 2 (déjà). Et je ne suis pas trop dans la dèche. Je crois même que je vais aller m'acheter des tickets pour le concert de Wart. J'emmènerais bien Marine avec moi, tiens, ça lui fera sans-doute plaisir.

Non, sérieusement, ça faisait un moment que je voulais mettre côte à côte un niveau de Link's Awakening et un niveau de Oracle of Seasons), tous deux sur GBC, mais le second me donne l'impression d'être plus "creux" et plus "plat" dans ces donjons que le premier. Bien sûr, je ne peux pas être objectif vis-à-vis de ZLA, vu que c'est mon tout premier Zelda. Quand on découvre le grappin pour la première fois dans un jeu, ça vous marque, bien sûr.

N'empêche, même en faisant abstraction des couleurs (plus pâlote à droite dans OOS), et qui font plus ressortir le contour noir des objets, je trouve qu'il y a beaucoup d'espace inutilisé dans cette map du 3eme donjon par rapport à une surface identique dans le 1er donjon de ZLA. Un choix pour favoriser les combats de groupes plutôt que les combats dans une zone restreinte ? Ce qui est sûr, c'est qu'on perd un peu plus du côté "labyrinthique" des donjons (je trouve). Ils sont moins décorés, aussi. Les salles sont plus rectangulaires et arborent moins de ces petits détails mégalomanes que l'on trouvait dans les donjons de ZLA. Contrainte technique due à un gameplay plus riche, peut-être ?

Difficile à dire, quoi. Et vous, vous en pensez quoi ?

Thursday, April 10, 2008

Buggy Beetle

photo by angela.b, waiting for authorizationun bug vraiment très bête, en fait. Genre, deux lignes inversées dans un module noyau, et vlan, tout plante ...

Je ne suis pas trop rouillé en Assembleur et en noyau linux, heureusement. A partir du crashdump sur le terminal (zd1201_usbrx+0x717), j'ai réussi malgré tout à retrouver le bout du driver pour ma clé wifi USB qui a provoqué un beau gros plantage de Gutsy Gibbon, la release ubuntu installée sur mon nouveau beetle. Il aura fallu attendre le passage à Hardy Heron pour que la correction arrive dans Ubuntu.

Je suis aussi arrivé à la conclusion (après un peu plus de chipotage), que la ligne

 skb->dev->last_rx = jiffies; 
supposée indiquer dans l'état du driver l'instant où le dernier paquet avait été reçu tentait de modifier un "device" qui n'a jamais été initialisé auparavant ("thou shall not follow thee NULL pointer", comme dirait Cyril). J'aurais bien rajouté à la main un "skb->dev = zd->dev", mais j'ai fini par faire une petite recherche google qui m'a appris beaucoup plus rapidement qu'en fait, ce champs-là est initialisé par la fonction appelée juste en-dessous (eth_type_trans, pour les intimes) :P

Le code correct lit donc
  memcpy(skb_put(skb, len), data, len);
skb->protocol = eth_type_trans(skb, zd->dev);
skb->dev->last_rx = jiffies;
zd->stats.rx_packets++;

Bon, par contre, pas trouvé le moyen de recompiler juste le module foireux (voir plus bas). Il est teatime, et je lance ma première recompilation de noyau sur mon dual-c0re tout neuf à 4GB de RAM...

...
1/2 heure plus tard, la recompilation est terminée, mais évidemment, les batteries de ma DS n'ont pas attendu jusque là. 'faudra essayer tout ça demain :P

here's a recompiled zd1201.ko module for the default gutsy kernel reusing local configuration (dual core, just in case). Install in /lib/modules/2.6.22-14-generic/kernel/drivers/net/wireless/ and make sure you have fresh firmware files (available on http://linux-lc100020.sourceforge.net/, to be installed in /lib/firmware/2.6.22-14-generic/)

2.6.22-14-generic/kernel/drivers/net/> md5sum wireless/zd12*
5e109dc87a1fa80d7c67834ce0d7a11c wireless/zd1201.ko
0ed15b4dab3e4f52f978a031ae102e02 wireless/zd1201.ko.original

(i'd suggest that you *don't* replace your wireless/zd1201.ko unless with mine unless you happen to have the same md5 as wireless/zd1201.ko.original)

edit: ça marche. c'est reparti pour le homebrew du temps de midi ^_^
edit+: oh, au fait: tout ça parce que je voulais vérifier que mon installation du dernier devkitpro (r21) était au poil...

edit: Thanks to this post by linuxtilti, i figured out how to make a small Makefile that lets me rebuild just the module i need
obj-m = zd1201.o
KVERSION = $(shell uname -r)

all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean


Okay, that was damn obvious, but i'm always confused by kernel makefiles, somehow. They export all their regular duties to those called builders, just pointing out "here is where i stand". I suspect that only obj-m is then imported by the builder ...

Tuesday, April 01, 2008

Appleman

Petit passage dans le bureau de Cyril avant la pause-café... De temps en temps, quand Cyril n'est pas pret, j'en profite pour gribouiller un peu. Ici, c'est l'appleman de la foret de Greenwoods qui y passe. Une petite version "toute normale" d'abord, puis à force (et c'est tout l'intéret du tableau blanc), je me lache un peu et j'essaie des nouveaux concepts...

Premier dans la série : le parapple, un tantinet inspiré par les parakoopas et autre paragoombas de Super Mario. Tombant des hauteurs des arbres, voilà un appleman plus difficile à éliminer, vu qu'il ne suffit plus de sauter dessus. Enfin, si, mais à condition d'y parvenir. On pourrait meme doser la difficulté en lui permettant d'abandonner subitement son parachute si Bilou passe par-dessous.
On peut voir que je m'étais d'abord orienté vers un parachute "normal" avant de prendre ... une feuille d'arbre. Plus sympa, selon moi.

Poursuivons dans la série des délires. Les chauves-souris jouent un role essentiel dans le level-design de la foret. Le hic, c'est que leur concept à elles n'étaient pas terrible. Les "bubble-bat" en mauve et bleu de la version basic ne sont plus vraiment adaptées au jeu depuis que j'ai laissé tombé le bubble-dragon, la tic-tac-bombe et autre escargot-turbo des premières esquisses de Piet et Pierrick... Bref, en écoutant un morceau (virt+beek) nommé "fruitbat", j'ai eu l'idée de transformer nos pommes aussi en chauves-souris. Evidemment, ça ne volettera pas très bien, mais ça ne me dérange pas.