Tuesday, August 07, 2018

Air Control

Bon, voyons un peu ces histoires de contrôle aérien, maintenant. Je sais qu'il y a des effets que je veux éviter et d'autres auxquels je tiens. Et ce à quoi je tiens par-dessus tout, c'est que le joueur ait la sensation qu'il tombe lorsque la gravité reprend le dessus. Pas question donc que le déplacement horizontal puisse devenir plus rapide que le déplacement vertical si ce n'était pas le cas au moment de commencer à sauter.

En fait, en l'absence de vent, et si on peut tomber suffisamment longtemps, ça ne devrait même tout simplement pas être possible: la friction de l'air est la même dans tous les sens. La seule chose qui peut faire qu'on se déplace plus vite horizontalement qu'on ne peut tomber, c'est le fait de planer. Et ça, j'ai déjà un power-up pour le gérer.

Maintenant, soyons honnètes: je viens de me repasser des vidéos de Super Meat Boy et de N+ jusqu'à plus-de-vaisselle-à-essuyer ce week-end et je n'ai jamais pu mettre en évidence ce "point d'inflexion" ou la vitesse horizontale accélèrerait plus vite que la vitesse verticale. Par contre, la gravité est tellement basse qu'on peut difficilement dire qu'on a l'impression de tomber.

Deuxième élément: la portée du saut doit être prévisible. Si Bilou se déplace à sa vitesse maximale au sol (soit en courant, soit en marchant), il n'y a aucune raison qu'il se mette à accélérer une fois en l'air. Si on met exactement 1 seconde à franchir N blocs en marchant, alors on prendra 1 seconde à franchir ces N blocs en sautant pendant la marche et on saura les franchir si et seulement si le saut dure au moins une seconde.

L'exception à ce principe, c'est le saut depuis l'arrêt. Ici, on ne sait pas conserver l'énergie d'origine du personnage. Par contre, il me semble important que le joueur ne puisse pas atteindre la vitesse de course à partir d'un saut-à-l'arrêt.
Jusqu'ici, on va plutôt dans le sens de garder ce qui a déjà été développé. Une chose que je voudrais améliorer, par contre, c'est le tuning du saut à plus grande vitesse.

Le simple fait de relacher la direction "avant" lors d'un saut permet dans Bilou de retomber à une vitesse horizontale nulle. Par contre, si la vitesse retombe en-dessous de celle de la marche, il est impossible de remonter de nouveau à une vitesse plus élevée...
J'aimerais mieux pouvoir moduler la vitesse en relachant puis ré-enfonçant le pad. On pourrait du coup avoir n'importe quelle vitesse
entre la marche et la course.

Grosse difference par rapport au contrôle de Super Mario, donc, où si on veut si arrêter son saut, il faudra faire demi-tour avant d'avoir atteint la hauteur maximale.

Mais pour être franc, je dois admettre que j'aurais du mal à me séparer du comportement actuel. En particulier parce que ça donne la possibilité d'annuler un saut si jamais je n'avais pas assez de vitesse. un confort que Mario n'offre qu'aux plus ratons d'entre-nous.



Friday, August 03, 2018

Rolling Random Number.

I decided to map every known token of the GobExpressions onto the ASCII charset some other day. And it struck me that there was a pattern like "upper case for mostly side-effect actions" and "lower case for mostly functional actions". To some extent, the 'x' being used to call eXtra functions such as spawning new game objects, triggering sound effects and the like should be replaced by X. Tracking that in all the command files won't be trivial, though.

It could be tempting to use S(for score) as a function since we have i(ncrement counter) and d(ecrement counter), but unlike game counters, the score cannot be read again. It's more a side effect to change it than really some functional extension to the core arithmetics.

So where should "roll a dice to get a random number" go ? likely 'r'. What should be used to "get/set game state bit %n". That could be 'g' and 's'. Pretty handy map.

Et dans Wordpress ?

Peut-être qu'un jour je devrai migrer tout ceci hors de blogger. Avec google, qui peut savoir ? Ce qui est sûr, c'est que blogger depuis une tablette, c'est décevant. Et depuis un boox qui tourne un vieil androïd 4, c'est encore pire. Comme je suis tombé sur un autre bloggueur de homebrew sur wordpress et que je me suis rendu compte qu'il y avait une fonction "notification pour les (réponses aux) commentaires", j'ai voulu vérifier si le passage blogger->wordpress était possible. Un p'tit compte gratuit, un coup d'oeil dans les FAQs et en avant.

Côté PC, l'interface est assez chouette. Plus fonctionnelle et réactive la version dont je me souvenais pour l'avoir fait tourner sur le serveur de l'Université. Rien que les miniatures dans la liste des posts, c'est chouette et sympa.

Côté tablette, c'est un peu moins réussi. les miniatures sont devenues des images énormes: il y a à peine deux articles accessibles par écran. Aucun contrôle pour changer l'ordre, filtrer ni rien de ce genre ... Il faudrait scroller et scroller encore (avec la vitesse de rafraîchissement de l'écran à encre électronique qui ferait passer les pluies sahariennes pour un coup de karcher :-/). Et pour ne rien arranger, les posts brouillons sont mis en avant, dans un ordre que je peine encore à définir. Et des brouillons, j'en ai. 158. Enfin, au moins ça devrait m'encourager à en mettre plus au net.

Et la bonne nouvelle, c'est que le texte de tout ce petit monde semble avoir été téléchargé dans la tablette et que je peux donc éditer à l'envi tout ça du fond du jardin. Enfin, à condition de ne pas être rebuté par l'éditeur en version Andröid qui semble penser que juste de l'HTML brut, c'est assez pour tout le monde :-/

Mais bon, je peux le faire au stylet, écriture manuscrite et sans écran. Et ça, c'est présssscieux.

Mais le plus impressionnant dans l'aventure c'est sans doute que wordpress a ré-importé automatiquement les 500+ illustrations du blog. Difficile évidemment de s'assurer qu'elles y sont bien toutes, mais c'est déjà un énorme travail d'évité. Et la galerie fonctionne aussi sur tablette (à condition d'être connecté. 'faut pas trop en demander quand-même: 7.5% de 3Go, ça fait son poids dans la gestion de mémoire cache du boox.

Mais il doit en manquer parce que l'album google "photos de votre blog" en comptait pas loin de 1240...

Tuesday, July 31, 2018

Please define 'casual'

Is the NintendoDS retro ? will it ever be ? the question raised on twitter. Thinking about it, how it was launched and how different the titles available at launch were from other now-definitely-retro consoles (including SNES, PS1, and even GBA),
I'd say the NDS will have harder time to feel retro in general (although some games certainly will). The reason is that, by the time the Nintendo DS came out, the kind of games we played had changed significantly. GBA games play much like slightly simplified versions of SNES games all over the life time of the console. And they play themselves much like more refined versions of the NES games. The reason for all this is the controller.

To me, holding an SNES controller is a well-known feel. I don't have to think about where X or A stands. It is immediate. And it definitely wasn't the case when the SNES cames out: SMW gave me a hard time compared to the 1-button + dpad games I was used to (okay, I pressed SML B button from times to times). And for most games on those devices, it was frequent that you'd need to train yourself to the core mechanics and grow your controller skills before you could proceed further than world 1.

The DS, instead, came up in the world of casual games. Not games that you happen to play casually (as opposed to competitively), but those explicitly designed so that you don't really need training to experience their core gameplay. Zoo Keeper, for once, perfectly fits that line of titles targetted at bejeweled players. They're built around more intuitive and direct actions (thanks to the stylus). Any grown up can start playing them even when they have almost no training with gaming devices. They don't require players to know that they should hunt for 1-UPs or stock power-ups if they want to stand a chance against the end-of-world boss. Really, these are games that Hudson Hawk could have enjoyed despite he's been in jail since Pong is out.

That doesn't mean that there are no retro-like games on the system, but they were pretty rare gems compared to the avalanche of stylus-driven titles. And chances are that the youngster who had a DS as her first gaming system will have nostalgy towards titles that no longer plays like a DPAD+buttons retro game.

Will the NDS ever be retro ? of course. But it might have to wait until we no longer use touch screen as our primary model to design games. When virtual/augmented reality games become the norm, maybe.

Thursday, July 26, 2018

Madness? this is refactory !

Maybe you remember this picture, the first one I scanned with my iris mouse. Maybe you remember the times where I mentioned some more things in the collision engine needed a revision. At last, I'm at it.

When two objects collide, they need to have access to each other for some times until all the rules of their state machine have been evaluated. To do this, I used a "GobCollision" object, linking to the related objects, script variables and hit boxes (GobAreas). That was a nice first step towards clean design, but it still has some drawbacks, like using weird arrays of so-called "GobCollision" that each captured only one side of the collision, and copies into the array to somehow "swap" orders when the collision initiator finally runs the 'found' rule with the collided object as "other" (while it just was 'other' for the 'hit' rule on the collided object).

But I had a small extra "Swap()" call dangling around. With some odd effects on the game, as you can see. But hopefully, I just got it sorted out. Now I'll be ready to be gone with the "collision-specific variables" telling how much hitboxes overlap each other, which is currently stored as a game-wide static array, while it should really belong to the new, real collision state object.

Saturday, July 21, 2018

Junko Ozawa's Secrets

(re?-)Bienvenue à Upsilandre dans la blogosphère! Quel plaisir de pouvoir découvrir en détail ses analyses des techniques ancestrales de programmation assis confortablement avec ma liseuse. Son analyse de la "basse sunsoft" et l'utilisation du canal 'triangle' pour faire les drums (plutôt que le canal d-PCM comme dans SMB3) était un vrai délice. Du coup, j'ai envie de ressortir cette série de snapshot de l'interview de Junko Ozawa, responsable son et musique sur les jeux arcade Namco.

Très tôt déjà, alors que les générateurs simplistes de la NES semblaient riches en possibilités et que la FM faisaient ses premiers balbutiements, les machines NAMCO travaillaient déjà avec des échantillons. Enfin presque. Le hardware était capable de rejouer du contenu par modulation d'amplitude (PCM) sur 16 niveaux (4 bits) mais extrêmement courts ... disons 16 à 32 points par son. Plutôt que d'y envoyer par DMA un son enregistré en live de basse ou de trompette, Madame Ozawa va s'en servir pour comme d'un SID avec des ondes programmables. Des sons totalement synthétiques mais avec une signature unique. Pendant que Myamoto retranscrivait sur des petits carreaux les traits de Donkey Kong pour faire du pixel art, Madame se livrait au même travail à partir d'un son visualisé à l'oscilloscope pour faire reproduire à son soundchip une "trompette pixelisée" ou un "violon pixelisé".


La puissance, la tonalité, la rondeur, tout est personnalisable. Ecoutez donc Tower of Duaga de 1984. On est à des années-lumière de la sonorité d'une console atari! et la NES est encore sur Pluton.

Sa bibliotèque de sons, c'est le trésor de Mme Ozawa. Elle les conserve dans un cahier, vu l'absence d'éditeur numérique pour ce genre de choses. Et il faudra bien longtemps avant qu'un synthé ne puisse interpréter en direct les sons imaginés pour le Namco WSG.

[Les wave tables], c'est la base notamment du son PC-Engine dès 87, mais on retrouve ca aussi dans le Famicom Disk en 86 (y a qu'un seul canal mais de bonne résolution, 64x64), dans la Gameboy ou on a une wavetable 32x16 qui remplace le triangle wave de la NES (j'aurais aimé la même chose pour la NES), aussi dans le soundchip SCC de Konami qu'on retrouve dans les cartouches MSX de Konami tel que Contra.
Effectivement, je n'avais pas fait le rapprochement, mais c'est bien la même technique qui permet à la version "Famicom Disk System" de Legend of Zelda d'avoir quelques sons inédits par rapport à sa version NES (dixit Nathan dans "I AM ERROR"). Et on voit bien les patterns un peu exotiques tout en étant très clairement des ondes simples dans la séquence de fin de Link's Awakening.  


Bref, de mon côté (et surtout vu que je suis assez fan des sonorités de Coryoon et Soldier Blade sur PC-Engine), ça me donne furyeusement envie de coder un petit Wave Editor for DS ...


Friday, July 13, 2018

whipseey

A lovely setting, charming character, platforming action in pixel art, and above all, a "whip/ninja rope" mechanics I'm in love with since Fury of the Furries and Mickey Magical Quest. You bet I'm following @whipseey in his quest recovering the Lost Atlas ^_^. And the fact it is drawing inspiration from the legendary Mr. Gimmick is just the perfect spice to complete the gift.

Yet, while watching I realised that one of the sceneries had an issue that also existed in Bilou School Rush and that was pointed out by Kirby Kid when he gave feedback on the early version of the game: one-block-wide pillars.

You have a lot of "one block wide" or "character width wide" platforms. I find this irritating. They put a lot of stress on the mechanics and they also slow down the gameplay a lot. Open the platform spaces up some more.

 For the untrained player, these will put strong stress on the player's knowledge of the game engine's intimacy, like how much exactly gravity and momentum there is, so that one can land her favourite pink avatar on such a tiny spot.

One think I like to do on Twitter is to dream how I'd approach those short video  sequences myself. Preferably in the original character's abilities set, a bit like how Myamoto and his team decided to make Popeye be able to jump over barrels in the early prototypes of Donkey Kong as it was the most natural thing to do if it wasn't a videogame.

And what would be the most natural thing to do if you barely missed a jump to a pillar while carrying a magical yoyo/whip/rope thing ? Well I bet I'd try to wrap the rope around the pillar to be safe again.

That in turn raised the question of "how would I do such a thing for Bilou in my own engine?"  Should the 'whip' be an extension of the player's gob (that is, the internal software element ruling the sprite's behaviour) or be a gob of its own ? Should the pillar be made of special tiles or would the whip-end object (if any) be able to detect a pattern of solid-but-small-enough area ? Both approaches would be valid in each question, but as you may have guessed from the way I ask (or read in the sketches), I'd rather opt for the second answers if I was immediately ready to introduce that ;-)



Tuesday, July 10, 2018

contretemps

Non, ce n'est pas juste de la procrastination, ni juste des hunger games, ni de la démotivation ni juste ma déclaration d'impôts. Pas même une diablite mundialesque.

C'est le fichier de l'été. Tendinite à soigner. La semaine dernière, tenir un crayon était une torture. ça va un peu mieux.

Friday, June 29, 2018

Grand nettoyage de printemps ?

Bon, j'ai presque fini avec la révision des "évènements" provenant des contrôleurs de comportement (juste encore un peu de cleanup). Les histoires de signe sont réglées, Bilou fait à nouveau ses pirouettes comme il faut... et oui, j'ai encore fait du débugging avec des p'tits dessins.

Le dernier sur la liste des "grands nettoyages de printemps" devrait être l'élimination de GobExpression::xcontext, et je devrais avoir quelques notes là-dedans sur mon boox.

Après ça, il sera temps de tourner la page (parce que ça devient limite trop long, comme "printemps") vers de nouvelles aventures. J'ai bien progressé dans les recherches sur l'évolution du langage de scripting. Suis-je prêt pour attaquer le "behaviour editor on DS" ?

Tuesday, June 26, 2018

Guru Meditation again

Bon, je me suis retrouvé après avoir fait quelques essais du nouveau système de gestion des évènements de mon moteur de jeu avec un bel écran bleu. Sur DS uniquement, évidemment. Après quelques tentatives infructueuses de régler ça en une demie-heure, j'ai fini par profiter du fait que ma fée était en réunion pour me faire une soirée "guru méditation" à l'ancienne.

Papier quadrillé, désassemblage des fonctions impliquées (au moins, la position dans le programme était correcte), déduction de quel registre contient quelle variable (pour pouvoir exploiter le contenu de l'écran bleu) et structure physique des différents objets impliqués à grand coup de ddd en comparant le contenu "brut" de la mémoire et des affichages haut-niveau.

Vu que le crash se produit à cause d'un accès à la mémoire via quelque-chose qui n'a rien à voir avec un pointeur, j'étais prêt à rajouter des "nombres magiques" ça et là pour pouvoir reconnaître une transition, un état, une expression, etc. Mais en réalité, je n'ai besoin de rien de tout cela. Tous mes objets critiques ont au moins une méthode virtuelle, ce qui signifie que je peux utiliser la référence vers la vtable pour déterminer directement si une zone de mémoire donnée contient toujours un objet d'un type donné ou si elle a été écrasée.

A partir de là, c'est de la navigation dans la mémoire de la DS en suivant les pointeurs retrouvés sur l'écran bleu pour reconstruire l'état des objets impliqués dans le crash. Et au terme de tout ce sudoku-géant je finis par trouver deux indices troublant:
- l'adresse d'une des transitions à tester en cas d'évènement est un anagramme de l'adresse qui a causé le crash
- l'adresse de la liste de transitions correspondante n'est pas multiple de 4 alors que toutes les adresses ont une taille de 4 (bytes, mon cher Wattson).

L'émulateur voyant cet accès étrange aura "redresser" l'adresse, ignorant les bits les plus faibles. Parce que, oui, la machine sait que je veux prendre 32 bits quand-même. Le CPU de la DS, lui ... eh bien, il m'a sorti une variante mélangée des 32-bits se trouvant à l'adresse utilisée par l'émulateur. Les 8 bits "les plus à droite" de la valeur en mémoire se sont retrouvés à gauche pendant que tous les autres étaient décalés vers la droite.

Friday, June 22, 2018

deep blue InfiniMap

CommonMap revision changed the lookAt/scrollTo interface of background layers to take unsigned positions. After all, it shouldn't be possible to set the center of the screen into negative coordinates when the top-most corner is (0,0).

But I will need to keep internal computation of signed integers anyway. else I get blue meditation screens...

The core of the problem is that processors have two main way to understand numbers: one where the top bit of the number has no special meaning (we call them 'unsigned' numbers and they're all positive), and one where it tells whether the number is positive or negative (with some tweaks, and we call them 'signed' numbers). And among the operations the CPU can perform on number one behaves very differently on signed and unsigned numbers: division. Divide an unsigned number by two, and you'll always have to insert a zero in the top bit. Divide a signed number by two and the top bit remains sticky.

If you mess with the numbers signedness (issue unsigned operations when you should have used signed operations) and you may easily turn a small, negative number into a big, positive number during a division. That's what I did with my update ... this is what I have to fix now... hmm... tomorrow. It's time I give my eyes and brain some rest.

once upon a skunny

Ok, il y a les jeux qui vous motivent à les imiter, puis il y a les jeux qui vous motivent à faire mieux qu'eux pour prouver que c'est faisable. D'aussi loin que ça remonte, Skunny in the Wild West appartient à cette deuxième catégorie. Alors qu'on rêvait de pouvoir faire nos preuves sur Super Nintendo dans Bubsy, mon frangin ramène une diskette du supermarché avec la version shareware de Skunny. Une sorte de Mr Nutz pour PC ?

côté graphismes, Skunny nous démontre par l'absurde l'importance de la cohérence du style au sein d'un jeu. Un grand nombre des principes que je me suis juré de suivre du point de vue du pixel art vienne d'une négation de ce qui se passait dans ce jeu
- Tu ne numérisera pas des photos pour mettre dans ton jeu
- tu n'utilisera pas des lignes noires pour le contour de tes personnages.
- tu n'abusera pas des dégradés ni des tramages automatiques.

Rien que sur la séquence d'intro, Skunny fait tout l'inverse

Alors oui, ce dégradé pour le ciel est superbe. Et le canyon rend pas trop mal du tout pour du 256 couleurs. L'ennui, c'est que ça ne correspond absolument pas aux personnages ni au terrain du jeu. Exactement comme si vous preniez les playmobils des gamins et que vous les mettiez devant la peinture à l'huile de mamy pour tourner un mini-film avec des arbres en pâte à modeler.

Les personnages aux lignes noires (qui tuent le contraste et les applatissent) donnent un effet grotesque et décalé, style "bip-bip et le coyote". Le jeu devrait donc être humoristique et pris au second degré. Mais le décor, lui, est réaliste et avec perspective et profondeur, ce qui induit une forme de dramatisme. Au final, le mélange a un goût d'artifice. Comme un tour de magie dont on verrait le truc.

Autre exemple, le sol suggère que le les plate-formes se rétrécissent sur les bords gauche et droite. Un peu comme si on était sur un de ces plateaux circulaires. Mais la partie "verticale" de ce même sol reste elle parfaitement plate, sans aucun effet de luminosité ou de torsion de la texture pour soutenir ce que suggère la partie horizontale.

Alors oui, quand Morris dessine son "Canyon Apache", il utilise de l'encre de chine noire pour les traits. Mais l'épaisseur de trait par rapport à la surface du personnage n'a rien avoir avec du pixel art en 320x200. Et il n'a pas non plus besoin de faire de l'anti-aliasing. D'ailleurs, si on zoome sur une des cases de la BD, on se rend compte que les traits ne sont plus noirs, une fois la numérisation accomplie. Ils se sont mélangés avec la couleur de ce qu'ils entourent. Pour donner du brun le plus souvent. Et la résolution des sprites de skunny est 3 à 4 fois plus faible.

Je tente donc d'appliquer ça rapidement au screenshot de skunny. Et j'en profite pour essayer de corriger le dernier problème: l'équilibre entre le contraste de l'avant plan et de l'arrière plan. Les structures sur lesquelles ont doit se déplacer sont extrêmement délavées dans le jeu original, alors que le décor lui est dans des tonalités chaudes.

Or notre oeil à l'habitude que la distance "bleuisse" les choses et atténue les contraste. Il faudrait donc faire l'inverse: pousser le contraste et la saturation de l'avant-plan (et le ramener vers le rouge) tout en atténuant le contraste de l'arrière plan, diminuant également sa saturation en couleur (aller plus vers du pastel, quoi) et le décaler légèrement vers les bleus. Je n'ai pas touché au ciel lui-même: il est suffisamment en-dehors de la zone de jeu.

Et bien sûr, on s'abstient de faire pareil avec les masques gauche et droite. Ils avaient le gros défaut d'utiliser à peu près les même couleurs que le sol dans l'image originale, ce qui augmente encore la confusion.

Bon, ça ne sauverait pas le jeu dont le gameplay est infogramesque au possible (n'espérez pas ramasser plus d'une demi-douzaine de mouton lors de votre première partie), mais au moins on y verrait plus clair.

Bon, en dépit de tout ça, je dois reconnaître un sacré talent de programmation sur le moteur de jeu. Du scrolling parallaxe en 256 couleurs et fluide avec des sprites de cette taille-là, en 1994, j'aurais aimé en voir plus souvent. Et si la musique est répétitive, elle est présente et entraînante comme il se doit. Je ne peux pas m'empêcher de me demander ce que ça aurait donné si j'avais disposé de cette technologie pour réaliser Badman et Bilou... parce que le jeu est Belge! eh oui!

Saturday, June 16, 2018

iris mouse to the rescue

It is pretty handy to have the boox to draw sketches, but I don't find them as nice as the one I draw on paper. . Plus, when I'm using the boox to read the code, I can't update notes too. If I ever try, I'll have to face a near-minute swapping time every time.

So as I found the 'IRIScan Mouse' near my boarding gate, I just bought it. It's pretty funny. It's a hand-moved scanner (like the very first one I had) but fit into a mouse, and it can do both ... on Windows at least.

So it won't really make the USB printer/scanner obsolete at home, but it will certainly be helpful at the office. it has pretty nice rendering of my tiny handscript, avoids doing JPEG-by-default (afaik) and makes export of captured files pretty easy.

Or well, it should have been useful. Unfortunately, plugging the dongle into my Windows7 workstation didn't let me use the scanner feature. The mouse remains unreachable through the WiFi.

On my Linux laptop, all I see is a USB device with vendor ID 274f (Systech Electronics, according to dmesg) and product ID c001 (Zcan Wireless). no text identification of the device. The "mouse" feature does work, though. but I don't get an additional WiFi interface. So what is in the dongle exactly ? Some forum post suggests it is using the uvcvideo driver. It indeeds gets loaded. It doesn't seem like the USB device offers multiple

The dongle could be featuring just one NRF LU1P16 chip (there's one additional 1101GE marking), possibly made by NORDIC, although I couldn't find such a chip in their catalog.

But the original manufacturer's manual is clear:
Scan function requires Wi-Fi connection between computer and Zcan Wireless directly. Please add a Wi-Fi adapter (802.11 n is recommended) if Wi-Fi function is not available in your computer
my workstation at the office doesn't have any WiFi, and the dongle won't provide it. It also explains why scanning would fail on the office's laptop I've used so far when I had wifi enabled. When I'm actually connected to a network with my WiFi, the scanner can no longer reconfigure the WiFi interface to communicate with the mouse. Looks like I'll have to do some more shopping ...

Sunday, June 10, 2018

simplifying events engine

I want to get rid of some static pointers in the management of events. The idea turned cleaner as I was flying over Denmark. But the result isn't convincing yet.
- you can't jump out of inkjets anymore (event from dpad controller is ignored - apparently because TrackAttached produced an event too -- although it has no corresponding transitions)
- you might get pushed away from spongebops when you try to grab them -- weird things still occur here with my best solution for inkjets.
- if Bilou starts swimming up, he'll keep swimming up forever -- that's fixed with swapped-priorities
- the little stars shining around you when you pick a health bonus keep shining forever. -- seems fixed with swapped-priorities too.

The thing is, when I want to combine the "thoughts" of two controllers, only one events list can survive. And of course, things don't get fixed if I swap the order in which they are produced (unless I swap them properly, that is). Weird things remains with that swapped-priorities, though. Like why don't we play the 'roll-in-the-air' animation anymore when Bilou's direction is changed while jumping ? I'll have to re-activate InspectorWidget and use the combined powers of InspectorWidgets and DDD to find out.

By the way, did you know that we could have methods, operators overloading and constructors for unions ?

Friday, June 08, 2018

GameObject::useEvent() should go away.

https://sourceforge.net/p/dsgametools/hg/ci/refactory-engine/tree/libgeds/include/GameObject.h#l175
That shouldn't happen. The way controllers fire an event is not satisfying. A static pointer set by class X so that it is used by class Y with no restriction on who does what and that merely works because we know X calling ::useEvent() and Y checking *::doevents happens to take place with the right timing ? No.

I mean, look at the documentation: "assumes no re-entrance until gobRunController". That has turned false the minute I introduced 'attach-to-other-game-object' feature where you might have to run the object you're attached to before you can run yourself.

I'd like to convert {NONE, FAIL, EVENT}  enum into something else that allow "EVENT" to carry the list of transitions to check by itself.

Sunday, June 03, 2018

bubsy

I think I was 20 years younger the last time I need a SNES gamepad to press start on Bubsy title screen. After a month of training, I was able to reach world 4 and found a few 2"continues". I couldn't beat the level 3 last week-end, but at least I got the confirmation that Bubsy "claws encounters" is a fun game.

It might be the only fun thing made with that character (I do not expect much of Black Forrest's "woolies strike back"), it may have arguable pixel art, the tunes are catchy, the atmosphere is playful, the character is fun, and there is enough variety in the level design to keep us entertained.


It is clearly difficult and sometimes even frustrating without becoming utterly unfair or boring. As far as I've played it, it is challenging.


It is far from being a masterpiece in terms of game mechanics, though. The air control is sometimes a bit awkward, Packing precision, - and the "GLIDE" mechanics isn't always sufficient to save the day, But what really seem broken is what happen when you jump off a slope. First, you don't move purely upwards (if standing), but slightly backwards on a climbing slope. You'll have to compensate that with more air control. I've never seen that happening to any mammal in the real world, presumably because we feel the slope and compensate when jumping. But I can accept it: it makes sense from a pure physics perspective, and it echoes a similar mechanics in Sonic. What is broken is that if you then release the directions pad, you will find yourself pushed backwards again!

Saturday, May 19, 2018

Un p'tit bug?

Dans l'éditeur d'animation, dernière mouture ? Je m'explique, je voulais prendre quelques captures d'écran pour expliquer comment se faire un petit personnage à partir de "composants" simple, puisque la "branche tutoriel" sur github est maintenant capable de gérer aussi bien les personnages simples que composés.

Malheureusement, un des widgets (normalement sur la gauche) n'affiche plus rien. Particulièrement ennuyeux puis qu'il s'agit en fait de la "palette de composants" qui permet de sélectionner un pied, la tête, le corps, etc.

J'ai du louper quelque-chose lors du refactoring.



Doing some bug-hunting on AnimEditor so I could do a 'setup your compound character' tutorial for the github tutorials series. Some flat facts:
- the thumbnails are on the "sub" screen, the timeline and sprite pages preview are on the main screen.
- the 'limb table' is actually rendered, but only on BG3, which appears to be hidden.
- clicking limbs properly switch sprite pages
- clicking the sprite page does weird things with the cursor on the top (sub) screen.
Oddly enough, if the layer with limbs table is hidden, how comes we see the sprite page ?


Somehow, it looks like the widget I'm using to show what is selected when clicking on the sprite page was hard-wired to the sub-screen, instead of letting the window creating it telling which resource to use. That's easy to fix.

It also looks like AnimEditor didn't get its dedicated LayersConfig, and still use the default layers setup combined with some custom register programming. That doesn't help. And we still see the SpritePage because, unlike the limbs table, this one is truly made of sprites.

Finally, it looks like the 'limbs table' is initially empty. It only fills when I drop new sprites there. It should be pre-loaded with the animation's skeletton when I load an animation.

So, some more flat fact:
- in the old approach, fill_anim_thumbs_16() is the code that copies pixels from the spriteset into a spritesheet used by the limbsTable. Exactly one 'block' of data per limb.
- only other calling site fill_anim_thumbs_16() is AnimWindow::restore().

Q: do we still call fill_anim_thumbs_16() on FileWindow::event() ?
A: yes.

Q: what is the target spritesheet then ?
A: one pointing to main-screen background tiles.

Q: did loading an anim changed the limbs table in medsgama.nds ? 
A: no. Only "opening" the animation on the AnimWindow did. And it still does. With a spritesheet using some main-screen BG memory.

Friday, May 18, 2018

Tuto branch update.

A few weeks ago, I found myself pressing the direction pad of my DS to keep
that little character onscreen. It had the most basic behaviour could think of because its sole purpose was to demonstrate how we control things in my game engine. Somehow, it felt a bit like an empty level in Space Taxi.
today, that same character moves around a place that comes from the level editor, with blocking tiles effectively blocking you. What it misses is a target. Snake-like pellets, if you want.

That requires me to revise:
- collisions between Gobs
- counters
- in-game level changes.

Monday, April 30, 2018

Même pas peur

J.l.n a grandi. 5 ans maintenant. Il ne se contente plus de regarder papa raconter des Zelda comme si c'était un livre interactif. Il a envie de prendre la manette. Oh, bien sûr il a déjà un peu chipoté dans Rayman Origins ou New Super Mario Bros Wii, mais surtout en mode "bac à sable" ou en mode "ouhla, ça devient dur, j'me mets en bulle".

Son premier vrai jeu est donc Boing! Docomodake un petit jeu mignon qui m'avait été recommandé par Pierrick, à mi-chemin entre lemmings et Rick Dangerous à la sauce bisounours (comprenez, sans les pics qui sortent du sol, et sans que les lemmings n'avancent sans vous). Tout à fait adapté à son niveau, même si moi, perso, le jeu m'avait lassé très rapidement tellement tout était lent dedans.

Pourtant, niveau interactions, c'est assez riche. On bouge avec la croix, on fait apparaître des petits champignons qu'on déplace pour faire des ponts, des échelles, des contre-poids, etc. on bouge encore. On en ramasse pour les lancer sur les (rares) ennemis. Il avance pas trop mal.

Puis l'autre jour il fait un blocage "papa, il faut que tu tires sur la libellule". Papa gribouillait, il encourage le fiston à essayer lui-même "tu te prépares, tu vois, tu t'avances". Rien n'y fait. "mais j'ai peur"!

Et là, j'ai compris la grande puissance du jeu vidéo pour affronter ses peurs. "Regarde, le jeu il est là. Toi tu es ici. Tu es en sécurité: il ne peut rien arriver. Au pire, il y a des petits pixels qui vont un peu changer de couleur, mais tu ne risque rien. Allez, c'est l'occasion parfaite pour apprendre à être plus fort que ta peur".

Beaucoup plus difficile pour lui, par contre, c'est de faire face à la frustration quand il se rend compte qu'il a loupé un coffre (généralement en fin de niveau) et qu'il est impossible de faire marche arrière parce que le développeur a voulu que seul celui qui réfléchit et planifie puisse l'avoir. Là, au bout d'un quart d'heure de concentration pour passer tous les obstacles et récupérer les pièces d'or, ça peut facilement éclater en crise de pleurs qui confirmeront qu'il est temps de jouer à autre chose...

Sunday, April 29, 2018

definition files in geds3

The refactoring keeps going. I'm about to show the "load a map" feature, and then I'll have to show "how characters interact with the ground through properties".

Meanwhile, I'm digging what sort of additional definitions a "Behaviour Editor on DS" should read, and how that would be translated into .h files that convert the "level 2" scripts into plain "level 0 scripts" that can be parsed by the runtime engine on the DS. I'd allow e.g. BEDS to do more lookups in symbol tables while all symbols should normally be translated into values or expressions in level 0 when loading levels in a game.

Maybe you wonder "but what is level 1?" ... well, level 1 is what I'm doing right now with Bilou School Rush, with the C pre-processor expanding symbols for us so that I can write "$RUNLEFT->$RUNRIGHT on eDpad [D_RIGHT]" instead of "statl12->statr13 on event0 [v2 $20 &]".

Sunday, April 22, 2018

to $(AR) or not to $(AR)

During the preparation of the "controllers" tutorial, I faced a weird linking problem. I wanted to split the huge "controllers.cxx" file so that every controller would be in a sub-file that could be compiled separately and no longer depend on the code from other controllers unless there is a good reason for that. And all of suddens, I had no more factories registered.

Just before that, I had reviewed the factory registering system so that it was enough to just write "MomentumFactory mf("momentum");" as a top-level declaration to get everything up and running. But that meant there was no more reference from the main .o files of the game/demo that would require .o files with the factory code (and instance declaration), so they wouldn't be packed in, and certainly wouldn't be initialized either.

So I started thinking about weird mechanisms invoking bool pointers to dummy variables, or no-code functions, and even why not "UsingPlatformer" empty class that would extend UsingMomentum, UsingDpad and others... Then I realized that all this happened because the .o files (compilation output, that is. Equivalent of your *.OBJ if you're on MS-DOS) are packed into a static library and only pulled to populate the .NDS file on-demand at link-time. If instead I explicitly say "link Demo/*.o Controllers/*.o", they are put into the binary and no trick is needed anymore.

Wednesday, April 18, 2018

shell functions

For so long, I have been creating aliases for my shell. "dir" would be "ls -la" and things like that. TCSH even had ways to retrieve some attributes to the aliases. building 20 student programs and testing them would have merely required me to type N (for next), B (for build) and T (to launch simple tests). Do I need to fix something to better evaluate their program ? B again, then T again.

But it had its drawbacks, and it was pretty ugly to code. Nowadays, I'd do that with shell function instead. Rather than trying to rewrite the statement, it truly allows me to extract all the arguments (either separately or together) and then calling one or more commands

cl()
{
    color.pl $* | less -R
}


One last place here I used aliases is with the "quick cd" tool I use to keep my brain sane and my screen not-excessively-cluttered
#!/usr/bin/bash

export CITY=$(pwd)
echo "You are in the City. $CITY"
echo "You can set 4 locations. North, South, East and West."

alias setN='export NORTH=$(pwd)'
alias setW='export WEST=$(pwd)'
alias setE='export EAST=$(pwd)'
alias setS='export SOUTH=$(pwd)'
alias setC='export CITY=$(pwd)'

alias N='cd $NORTH'
alias S='cd $SOUTH'
alias E='cd $EAST'
alias W='cd $WEST'
alias C='cd $CITY'

And yes, it pretends that you're running an old-fashioned, text-based adventure game instead of crawling directories. Because i found it easier to thing of thinks as "west", "north", etc. rather than trying to remember what letter I used for "gstreamer" and what letter was for "alsa".

Saturday, April 14, 2018

Dear ImGUI,

I hope you enjoyed the week-end. It sure was a pleasure to have you around, and getting some pixels rendered without having to bother with ./configure, plugging events into sockets or any kind of new classes.

Sure, I wish you had time to stay for tea and I would have shown you my SpritePages, but I suppose that can be kept for another encounter. I'm pretty sure you and I are meant to meet each other pretty soon.

Everyone was amazed when you just returned "true" in the line of code that painted a new button. Imagine the face they'll have next time when we'll show them GobState representations live and pop up new windows as one explore the state machine...

Stay Safe,
/PypeBros.

PS: okay, the unit-tester requiring 32-bit (so that DS registers addresses are out of the .text segment) and SDL requiring 64-bit won't simplify early integration tests ... we'll find some workaround.

Monday, April 09, 2018

Tutorial revision goes on.

I reached the point where you can write very simple scripts and have them processed on the "tutorial" branch. Of course there isn't much follow-up at the moment despite the 3 forums on which I comment stuff. That doesn't really matter, although I'd love to get feedback on whether it reads well.

What is really interesting here is that it forces me to get rid of many odd things. Hopefully, that will lead to a code base that will be easier to extend. Things like "rules.gam", for instance.

Being busy reviewing the expressions system, for instance, make it obvious that some static array could be gone now that I have the gob collision structure. the "game counter al so cry for a refactoring out of the GameScript class. And making the 'guns/controllers' system easier to understand (esp. by automating the registration system) made it obvious that I need to re-think the way classes access the Camera object.