samedi, février 23, 2013

Premier encrier.

Enfin! le premier encrier qui se promène dans le jeu de Bilou. Je n'étais jamais arrivé jusque là dans la version "BASIC". Voyez vous-même (.nds homebrew).
Maintenant, on va *vraiment* pouvoir commencer. L'encrier doit pousser Bilou, le repousser en cas de collision en l'air, mais aussi emporter Bilou.
Inkjet floats around, special blocks (not yet invisible, for debugging reasons) guide the path followed... I'm ready to start with the "new collision" mechanisms. And I'm curious to know how many times you manage to jump over the 48-pixel pencil in a row.

(Et si vous allez vous promener à la gauche de la map, vous pouvez essayer de sauter par-dessus le crayon de 48 pixels pour remplir le Quizz de la semaine.)

edit: bon, bin c'était pas franchement le poll qui ait attiré le plus de participation, mais avec la puissance du saut de Bilou revu légèrement à la hausse, les obstacles de 48 pixels de haut devraient maintenant offrir juste le bon dosage de difficulté.

jeudi, février 21, 2013

cleaning up a git repository ...

That's just some misluck: your git push is taking ages to complete. By checking it out later on, you realise you have pushed videos that do not belong there. git rm Videos/* is merely placing a curtain over a broken window: videos are still in the repository, they still make any clone über-huge.
Take your TARDIS and go erase any evidence of your mistake before someone else clone your repository! But before doing that, a git pull is required so that you're sure you're operating on a fresh space-time.

gitk

with this tool, find the revision where your Videos come from. Then grab the commit-id (sha1 hash) of the commit just before. Let's say you messed up on commit deadbeef and that cafebabe was your commit just before.

the command we want to execute on every commit between cafebabe and now is

git rm --ignore-unmatch -f Videos/*

The way to travel through time on cafebabe..HEAD to enforce that is

git filter-branch --tree-filter "git rm --ignore-unmatch -f Videos/*" cafebabe..HEAD

I bet you want to update gitk's view and explore commits to check all signs of your videos are indeed gone. Good.

Now, let's really cover our tracks:

mv .git/refs/original /tmp/refs-original-git
git reflog expire --expire=now --all
git gc --prune=now
git gc --prune=now --aggressive

If you were lucky and realised your mistake before the push, you're now done. If you had it pushed to the master repository, you still need to push these fixes ahead:

git push -f

And if you have a second clone of the master (at home?) where the videos still exist and that you want it as clean as the master,

git pull --rebase --verbose

(ooh, I wish so hard it had a "--dry-run" mode. Maybe you're better to clone your @home repository, and give the command a shot on the clone first so that you can check it has no undesired side-effects. The man pages claim that pull --rebase is potentially dangerous as it may affect your history. This is precisely what I want, but if for some reason your control on the master repository is weaker (i.e. someone else could alter its state between push -f and pull --rebase), you may want to follow the manpage advice and read git-rebase manpage first.)

mercredi, février 20, 2013

Quelle taille de crayon ?

Once again, I'm stopped at a development cross-roads. Mostly due to IRL, admittedly, but stopped anyway. I decided to move back SEDS update to "not-a-priority" level as soon as I realised that I had no gameplay idea relying on slope angles variations in the school zone.
I have a "thread" of activity that insist on bringing life to the inkjet. Pixel art is ready, fundamental parts of the behaviour "should work", but it's not operational yet.


Par où continuer ? Les pentes supplémentaires, ce n'est pas franchement une priorité. J'ai bien progressé sur inkjet, j'ai du pixel art qui est prêt, mais ça chipotte un peu au niveau du GobScript. J'ai regardé de plus près le coup de la "corde qui pendouille" et couvert 2 ou 3 pages de formules et de schémas UML, mais pour le rendu, j'aurai certainement besoin du support 3D.

I invested some time into sorting out that "animated rope" thing, and I now have about 3 pages covered with UML diagrams, mathematicae formulae, code snippets and occasionally a gag featuring Bilou and Bouli. So the model and controller aspects are mostly solved. Yet, I haven't figured an obvious way to view the bookmarks that Bilou will hang on, so it starts depending on 3D layer as well, which in turn asks for pendats to come to live.

Alors, quitte à se taper la partie "3D", autant en profiter pour enfin amener le crayon-soldat sur le terrain, non ? Le hic c'est que mes dernières tentatives pour animer côte à côte Bilou et un de ces crayons n'ont pas franchement été convaincantes. Au point que j'hésite même sur la taille à donner au crayon. 40 pixels de haut, Bilou pourra sans trop de problèmes passer par-dessus. 48, c'est peut-être mieux, mais aussi peut-être trop haut pour les capacités actuelles de Bilou

So I converted gbatek into an epub and started studying the options offered by NDS 3D rendering yesterday evening. That opens the door to some pendats, the long-awaited monsters that took over the Owl School. Meanwhile, I did some 2D attempts to animate a pendat, both in AnimEDS and later in flipnote studio, and I realised that I had no clear idea of the size pendat should have compared to Bilou. So far, Bilou should be able to clear a 40-pixels-high ennemy with a regular jump, and I don't know about a 48-px one, especially one like the pendat who cannot be jumped on.

There are only few scenes in Bilou's Book where Bilou faces a pendat directly. And none (iirc) with the desired proportions, neither for Bilou nor for the pendat. Yet, sketches suggest that Pendat.height > 2 Bilou.height
Curieusement, je n'ai pas énormément de croquis de références. Dans tous, un pendat fait entre 2 et 3 Bilous de haut. Par contre, s'il est possible de passer par-dessus un pendat qui charge, mais de justesse, ce qui demande un timing quasi-parfait. L'idée étant évidemment d'encourager le joueur à se servir des dumbladors pour assommer les crayons ou de profiter d'un obstacle plus haut en bout de chemin de ronde.

Bref, le mieux, ce sera encore de faire le test: combien de fois parvenez vous à passer par-dessus le crayon, à gauche de la map avant de mourir (SchoolTest.nds)

In my design documents, I clearly want that it is possible to clear a jump over a charging pendat, but also that it is tricky to do, requiring near-perfect timing when on flat ground.

So let's try it out. Can we clear a jump over a 3-tile-high static pencil ? Is it interesting to have Bilou jumping slightly higher when he walks(/runs?) like in Super Mario Bros ? If so, is it interesting to have Bilou unable to jump over a pendat unless he walk-jump it ?

mardi, février 12, 2013

Swinging Ropes in Pharaohs Return

I love those "dark" places of the Web where you can hear about other people's pet project and see them progressing. I developed a particular sympathy towards Lazycow's "Pharaohs' Return" project, a revival of Pharaohs Curse with state-of-the-art C64 programming.

Il paraît que les forums, c'est la "matière noire" d'Internet. Obscure, insaisissable, insondable. L'antimatière d'un blog/wiki, en somme. Et pourtant, j'adore la façon dont on peut y rencontrer des gens qui ont des intérêts proches des miens. Par exemple, Lazycow nous prépare depuis fin Mai l'exhumation ultime pour "Pharaohs Curse". De nombreuses salles, des couleurs et des décors réalistes, une pléthore d'actions, d'items et des animations à couper le souffle.
Pour sûr, son projet n'a pas à rougir des dernières sorties homebrew sur cette machine telles que Get'em, Mayhem in Monsterland ou Soulless. Superpositions de sprites, reprogrammation à la volée pour doubler le nombre de sprites visibles à l'écran, mélange entre caractères monochrome et multicolores ... tout y est! Même les boss démesurés.

Mixing multicol and monochrome tiles, swapping the color registers on horizontal bands for larger color sets, doing the same with sprites to go way beyond the 8 sprites/screen original limit...  I like it. But what really baffled me was his animation for rope action.

Mais ce qui m'a le plus épaté, c'est cette animation que Lazycow a postée où son explorateur attrape une corde au vol. J'avais toujours classé ce genre de détails dans la catégorie "sympa, mais clairement pas prioritaire". Mais s'il le fait sur C64, je me dois de ne pas être en reste sur la DS, pas vrai ? Grimper aux signets des livres fait partie des éléments de level design que j'avais explorés au moment de reprendre le travail sur Bilou ... Difficile maintenant de me contenter d'un signet rigide même si celà faciliterait le développement.

rope-actionClimbing on ropes wasn't that easy in the original game, and we used to make fun of friends as they were trying to do it with the joystick. Although functionally, the moving rope doesn't bring that much in terms of gameplay (given the limited angle it allows), it's one of those little details that makes a revamp look worth of it and show the love and care that the developer put in it.

When I asked Lazycow whether he had a tutorial on that, he keenly handed me the snippet of his source code that handles the rope action. I noted so far two sub-behaviours: the rope "above" the hanging character simply follows the shortest straight line between the hook and the hero.

for i=1 to heroheight:
   s[i]=i*herodelta/heroheight
The segments below try to align over the preceding segment with delta=s[i-1]-s[i], increasing the segment's speed so that it moves back towards the previous segment, then enforcing "integrity" of the rope by avoiding exagerated offset between segments.

Note that there's a small simplification here, as the rope doesn't shorten as it moves left or right. An alternative would be to assume that sin(x)=x and thus that it shortens by the amount it deviates from the straight vertical line (a fair estimate until you approach x=30°)

vendredi, février 08, 2013

Gare aux taches d'encre ...

Au-delà des pentes plus ou moins pentues et des personnages en 3D, il y a un "monstre" supplémentaire qui attend de rejoindre la school zone et qui n'en est plus qu'à quelques pas: "inkjet", l'encrier tacheur.

Petit tour d'horizon sur la façon de le réaliser, à l'ancienne sur une feuille quadrillée avant d'aller dormir... Chose amusante, je me rends compte qu'en réalité les 2 formes d'encrier ("volant" ou "poussable") présentés ici pourraient très bien être 2 GOBs aux machines d'état totalement distinctes.

As the real life gets a bit more quiet, I managed to find half an hour with pencils and paper ... just enough to make a quick list of what should be done in order to bring inkjets to life. A first one would be "turn back" special blocks that floating inkjets use to change (progressively) their direction (as opposed to an "invisible wall" that would immediately stop the inkjet).

Parmi les "petits défis techniques" posés par Inkjet, j'ai recensé le "demi-tour de plate-forme mobile", nécessitant un contrôleur adapté.
Rien de particulier pour que Bilou puisse être transporté par un inkjet, en revanche: ce sera entièrement dans le code de Bilou que ça se passera.

As far as "carrying" is concerned, nothing special should be needed in inkjet.cmd file -- except a special flag assigned to some hitbox. Bilou's state machine is fully responsible of the additional "carried" state. What we might want is a "throw up" state that allows a hitbox to cancel the droplets generation, so that droplets are created *only* if no character was carried (and thrown up).

Envoyer Bilou en l'air s'il est présent et lancer des gouttes d'encre dans le cas contraire ? C'est possible. Il suffit d'une zone de collision associée à l'animation "projeter". Si elle rencontre un personnage compatible (transition "found"), elle interrompt l'animation (et le projette). Les gouttes d'encre ne seront générée que si l'animation prend fin naturellement (transition "done" dans ma machine d'état).

Interestingly enough, all this is independent to what would happen to the "standing" inkjet (on the ground) and the transitions used to allow it to be pushed by Bilou.

Pour l'encrier au sol, je devrai procéder en 2 temps. Tout d'abord, m'assurer qu'il est effectivement "solide" pour les marcheurs, qui fasse faire demi-tour aux dumbladors et force Bilou à passer en mode "pousser".

Ensuite seulement, une 2eme collision dans le sens inverse force l'encrier à se déplacer.

Bon, là-dessus, je vais m'installer pépère dans un fauteuil et faire quelques petites animations supplémentaires dans SEDS...

Checklist:
  • [check] special block digits are read horizontally first, then vertically
  • [oops!] 1xxx is for "interacts with monsters" "interacts also with monsters", 2xxx is for "doesn't trash graphics while removing properties" "doesn't disappear when touched", but we could use "on hit [0] ()" in block description to prevent it.
  • [oops!] "block 1002 {" effectively encode properties of block using digits 1,0,0,2 on the level editor and not some other funny 0x1002 value that wouldn't make sense. (block 82 is required.)
  • [ok] states doesn't prevent collisions to be detected.
  • [fixed] decrease controller can cannot be used as expected.
  • [bugfix] GameScript::content() should allow \t tabulations in cmd files.

mardi, février 05, 2013

Rope it up!

Paul's tutorial on ladders was on my "readme" list for the Cybook last night. I liked how he motivated them as a way to introduce discontinuity in control mechanics and physics response. It sounded "Eureka" in my mind and I wanted to go further, so I asked Bilou and Bouli to illustrate the other concepts of the article.

In my game engine, such discontinuity can be handled naturally as I can attach different control chains to the different player states.
(Note that I will consider that ropes are just an visual alternative to ladders, that do not bring significant gameplay difference -- i.e. you can't swing ropes yet).


J'aime beaucoup la façon dont Paul Firth introduit les échelles dans son tutoriel. "Rompre la continuité du gameplay". Forcer le joueur à utiliser temporairement d'autres règles de déplacement que celles du platformer, et donc l'obliger à se défaire d'une part de son "confort" de marcheur. Rien à voir, donc, avec le grillage ou Mario se déplace librement dans le château d'Iggy.
La bonne nouvelle, c'est que ce genre de dualité est parfaitement prévue dans mon modèle de "machine d'états" pour la gestion des personnages. Pas besoin, donc, de rajouter des booléens dans tous les sens et des tests tous côtés.

En outre, dans un niveau largement fourni en "plateformes à sens unique" (p.ex. un empilement de livres ;), les cordes et échelles peuvent aussi être un moyen d'offrir localement au joueur la possibilité d'aller "à contre courant". Une seconde bonne raison de ne pas se contenter du moteur de jeu actuel, donc.

Another think that ladders/ropes bring is that they introduce platforms that can be "climbed down". Platforms that let you jump through but not fall through is pretty common in platformers, and they let you build levels where the player is denied to move backwards. A rope is an escape path in that way.

Now let's move to the technical part. The walk/climb transition is not so obvious to set. In Paul's approach, it involved the introduction of several sub-states and sub-tiles type to be processed properly. This is typically the kind of thing that I've learned to be bug-prone and that rather quickly limits the addition of new mechanics to your character.

Ideally, it must be possible to let the game engine align the character to the rope/ladder so that climbing animation works. As mentioned in a former post, this require the combination of the cando(F_LADDER) property on the tiles occupied by the character and dpad&KEY_UP guardian expression.


Il me faut donc un "micro-contrôleur" de personnage capable de s'aligner sur une échelle (align_flag), un capable de créer un évènement lorsque le personnage passe à un endroit où un nouveau mouvement est possible (detect_flag), et évidemment, un comportement pour monter/descendre à l'échelle. Le reste n'est plus qu'affaire de mettre le bon contrôleur au bon endroit, et à filtrer les évènement générés par detect_flag en fonction de la direction prise par le joueur.

It may also happen that you insist on your player to release DPAD left/right before he can climb. This is more likely to be the case to climb down: pressing DOWN will first force Bilou to duck. Only in that "duck" state, we check for ladders. The "align-to-[F_LADDER]" behaviour controller can then be affected to the "getting down" non-cancellable animation.