Tuesday, August 31, 2021

Pyramid mechanics

Jusque là, j'avais prévu de me servir des "blocs poilus" pour servir de blocs destructibles dans la pyramide, mais je crois bien que j'ai trouvé mieux. Et tout simple, avec ça: des pots. Eh oui. Ils peuvent être brisés, ils peuvent libérer des trucs, ils peuvent bloquer le chemin de Bilou.

Bilou peut naturellement ramasser des trucs. Les pots aussi, mais on peut faciement dire que seuls ceux qui n'ont rien par-dessus. On peut construire plein de scènes sur cette base-là, où un 'mur' de pots bloque un accès, qu'on ne saura libérer qu'avec une carapace de scorpion.

What can play the role of breakable blocks in the pyramid ? I once thought it could be furry blocks, and possibly I'll keep them in some places ... but building walls with them ? or large structures like SMB3 "pyramidal stack" ? I finally found something that could work better. Okay, lifting up jars and throwing them against walls to get goodies isn't exactly an original mechanics, but it would work fine with the pyramid setup as well as with a shell from a scorpio.

On peut en imaginer des 'intacts' qui font faire demi-tour à la carapace et d'autres déjà fendus qui laissent passer d'un coup.

Enfin, on peut ranger des pots sur une étagères, on peut les faire tomber en cognant l'étagère ... bref, ils peuvent servir de 'briques en l'air' qu'on casse en tapant dedans par le bas.

L'autre truc qui ne me branchait pas, c'est les lanceurs de flèches. J'avais une note proposant 'des statues de chat pour les boules de feu, des statues d'aigle pour propulser vers le haut'. Mais des piafs embusqués qui tentent de becquer Bilou et dont on peut utiliser le cou comme tremplin-à-la-Ori, ça serait sans doute nettement mieux.

One other thing needed more thoughts: wall hasards. Like arrow throwers or spears pointing out and coming back. I loved the idea of them being helpful to climb up with the right timing, but we've been served the cliché of climbing up spears stuck into walls after you dodged them so many times ... It wasn't too clear what would throw them either.

But given how birds are expected to play a major role in the last world of "Bilou Dreamland", I thought "why not long-neck beaked baddies trying to snap Bilou and then getting stuck into the wall facing them, so we can use their neck to climb up ?

Monday, August 30, 2021

Trouver le thread fautif

Bon, ce coup-ci, j'étais sur un autre cas de figure: le programme fautif est toujours occupé à tourner, mais un de ses threads est mort, causant une attente infinie dans un autre. Je sais demander un .dmp au Task Manager, ouvrir le .dmp en question sur la machine de dev avec les bons chemins pour les serveurs de symboles (eh oui, moi du futur: tu as oublié mais sous Windows, il n'y a pas de .elf de debugging: les symboles de debug sont d'office dans un fichier séparé) et parcourir la liste des threads en espérant y voir apparaître KERNELBASE!UnhandledExceptionFilter dans la pile d'appels correspondante. 

Ce n'est pas trop dur de repérer l'adresse du crash, mais c'est une autre histoire de connaître l'état des registres au moment du plantage.

Il devrait y avoir une extension de windbg pour gérer ça, mais le site qui la proposait a disparu dans les limbes du temps. Par contre si je parviens à deviner où elle se trouve, la structure EXCEPTION_POINTERS devrait nous fournir toutes les infos nécessaires pour continuer à debugger.

Eh bien voilà: cette structure est produite dans le stack frame (les variables locales, NdT) de ntdll!_C_specific_handler (encadré en rouge dans la capture ci-contre) et référencée dans le stack frame de UnhandledExceptionFilter. J'ai utilisé les adresses renseignées par la colone 'Child-SP' et retracé ça à la main dans Gimp, hein. Ici, un seul candidat: 0x16bee7c0.

Reste à s'assurer que c'est bien la bonne adresse. Je peux utiliser la commande windbg dt 0x16bee7c0 EXCEPTION_POINTERS pour le coup: si je suis dans le bon, elle me donnera deux pointeurs valides

En cliquant sur le 'exception record', on devrait avoir un code valide (type 0xc000000*) et une adresse qui correspond à notre fonction fautive (aussi renseignée comme adresse de retour pour KiUserExceptionDispatch, soit ici à l'intérieur de MoveSmall).

Thursday, August 26, 2021

Trouver un core dump ...

bin oui, parce que coder, c'est aussi chercher pourquoi un programme s'est planté. Linux est assez sympa sur ce coup-là avec son ulimit -c unlimited qui permet d'autoriser la production de 'core dumps' dans le répertoire courant pour un shell donné sans que tout le système ne se mette à saturer le disque dur en cas de dysfonctionnement. Après, on ouvre le dump dans un débuggeur et en avant pour l'autopsie.

Mais là, pas'd'bol, je suis sous Windows. Le boulot, vous comprenez. Le frangin de Jigé me proposait de faire clic-droit-debug dans le gestionnaire de tâches (onglet 'détails' de préférence, apparemment) et hop youpi, visual studio prendrait en marche le programme fautif. ça m'arrangerait assez bien vu qu'il est appelé depuis du python au bout d'une séquence de 3 ou 4 programmes histoire que la caméra à l'autre bout du fil soit dans les bonnes dispositions pour les tests. 

Mais re-pas'd'bol, quand je fais ça, j'ai juste droit à "not responding" sur Visual Studio puis les deux programmes qui s'arrêtent avec pas plus d'infos. ça marchait mieux avec "create dump file", mais ce n'est pas ce qu'il me faut aujourd'hui.

Pour le coup, je vais devoir refaire appel à devenv /debug dans une console VSpéciale et croiser les doigts pour être dans les bonnes conditions pour reproduire le crash. 

  • c'est apparemment normal d'être accueilli dans un Visual Studio qui fait semblant de ne pas savoir ce que vous voulez. Debug>Start Debugging devrait nous mettre en route
  • ça devrait aussi être normal que la fenêtre qui s'ouvre quand le programme est démarré (après tous les téléchargements de symboles depuis les servers MS) se ferme automatiquement en cas d'arrêt du programme. On va mettre un p'tit breakpoint sur exit pour calmer un peu tout ça;
  • ne pas oublier le .exe à la fin du nom du programme. Faute de quoi, VS ne le trouvera pas et proposera juste un bouton 'Attach...' au lieu du bouton 'Start' !
  • bon, par contre j'ai beau torturer ma ligne de commande, pas moyen de reproduire le crash dans cet environnement-là. Il va falloir trouver autre chose.

Et le plus agaçant, c'est que je sais que Windows peut le faire. Sur tant d'autres machines, il m'a saoûlé avec ses boîtes de dialogues ok/cancel/debug... ça pourrait être parce que Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug est vide, mais non: il me fait l'effet d'avoir bien tout ce qu'il faut là où il faut.

Ahmaisattends ... le programme de test mélange une bibliothèque C++ et du code compilé avec GHC, et le runtime haskell a un flag supplémentaire +RTS --generate-crash-dumps -RTS. On peut toujours essayer d'utiliser ça pendant notre debugging VS... Ah ? ... Bingo ?

On transfère bien son .pdb sur la machine de test ... Et voilà: j'ai un nom de fonction et un numéro de ligne. La méditation va pouvoir commencer.

Ah oui, il y a aussi le Windows Error Reporting (WER) system, et ses fichiers "planqués" dans C:\ProgramData\Microsoft\Windows. C'est ce qui ressemble le plus à mon ulimit. il faut créer la clé HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps et y définir "DumpType"=dword:00000002 (et plus si affinités. Attention, ça change le répertoire utiliser pour les dumps :-P)

Il y aura aussi procdump -e à tester, tiens.

Monday, August 23, 2021

walking kritter

A large part of the 'walk' effort is to have characters' feet sticking on the ground while walking. It may not always be a good idea but I always grimace when I see walking characters half-sliding on the ground in games with no obvious reason. At least for monsters, it should almost never occur.

In my current engine, this is achieved by hints in the animation sequence about how much pixels the character would travel with the new frame. Animator code then ensures the game character has already accumulated that much 'deferred moves' before switching simultaneously to both the next frame and the next position.

Quand je fais marcher un personnage, j'aime généralement mieux qu'il soit bien ancré dans le sol. Ce n'est pas toujours forcément une bonne idée, mais les personnage qui donnent l'impression de patiner au lieu de marcher alors qu'ils ne portent pas de patins, ce n'est pas ma tasse de thé. Du coup, mon moteur de jeu est prévu pour des animations qui contiennent des indices sur le nombre de pixels (plutôt que de frames) à attendre entre deux images.

But checking the walk cycle for the 'Kritter' monster in DKC makes me realise that there might be an easier approach, in which the motion speed for the character is constant while its animation still features a 'natural' motion where it speeds up and down: just offset the monster graphics within the buffer. This might sound like advice from a nightmare from a one-hardware-sprite-per-object point of view, where pixels would have to be effectively shifted in video memory to accomodate for the partly-moved object, but for a SNES-like sprite that re-codes the relative OAMs positions with every frame anyway, it could be nice to have.

Now there's a catch: the hitbox for your character will move at constant speed and your graphics will not. That might be source of other (Infogramesque) collision issues.

ça a aussi l'avantage de fonctionner avec des cycles de marche qui ne sont pas uniformes. Les boîteux, les excessifs, les discrets ... toutes catégories de personnages qui viendraient sans problème peupler l'univers de Bilou. Et où regarder après un exemple de ce genre de persos mieux que dans la série Donkey Kong Country ?

J'avais donc repris l'animation d'un Kritter et choisi un point de référence qui devrait rester ancré au sol (un orteil) pour voir comment il se déplaçait de frame en frame. Chose assez intéressante: on est souvent autour de la même valeur de 5 pixels par frame d'animation, mais pas tout le temps. Et vu les faibles déviations, vu aussi que l'image doit de toutes façon être reconstituée à partir de plusieurs sprites hardware, on pourrait probablement ici avoir un game object qui avance à vitesse constante et avoir un léger décalage sur la gauche ou la droite de l'image par rapport à la hitbox. Attention quand-même à ne pas pousser ça trop loin sous peine de créer des situations infogramesques.

Monday, August 16, 2021

DJLN.cmd

Faire des niveaux sur papier, ce n'est définitivement pas une activité à proposer à mon fiston. Au mieux, je peux lui proposer de me dicter un niveau que je ferais moi sur papier.

Par contre, prendre la Nintendo DS de papa et ajouter des blocs ici et là, ça ça lui plaît bien. Mais pas de chance, la branche "newmap/newmeta" n'est pas encore stabilisée au point qu'on puisse tenter de jouer au niveau ainsi construit.

Assez surprenemment, mon nouvel écran de patching m'indique que l'erreur se trouve sur la première ligne de pyram.spr, CMAP n'étant pas une commande valide pour les scripts. Enfin, ça c'est sur émulateur après avoir récupéré les fichiers présents sur DS avec le wifi remis en service.

En fait, ce serait la commande spr.more "pyram.spr" qui n'a pas été comprise par l'éditeur de niveau. Du coup, au moment de sauver, il en fait un input "pyram.spr" Si j'en crois les numéros de version, le bug a déjà été patché, c'est juste que la DS n'avait pas pu profiter de la nouvelle version. C'est J.L.N qui va être content...

  • invoking autoexec.cmd with the [run] button does not seem to allow PatchWindow to be invoked.

Saturday, August 14, 2021

Ultimate Game Maker

 There has been references to Ultimate Game Maker here and there in this blog, but if I want to explain what the project was, I'll need to detail a bit what I was doing just before.

Most of it was working on the early Clicker project, which was mostly meant to be a GUI library and desktop environment over a DOS extender, by then. It was also a mix between Nowan's C code and my assembly code so I had been defining every possible widget with a bit-level memory layout of how they would be managed as if the GUI handling code was a co-processor.

Meanwhile, I was more or less done with the RSD Game-Maker. It had too many limitations for the games I wanted to make. Games that could match Super Mario World.

Unlike Nowan, I had little interest in replacing Ms-Word with something better, but quite quickly, I started to use Clicker GUI project to revise the Game Maker I knew. There was little depart from RSD editor at that point. We see that on the 'monsters editor' screen that still has a grid to define monsters 'walking path'. But it already had a few critical extensions like "Monster is affected by gravity (needed for Bilou)" and "Monster can shoot" (needed for Badman III).

Ultimate Game Maker started while I was waiting for over 1 hour every morning for my university courses to start, and before the distance between Internet and classrooms shrunk.

I then started to cover a good deal of pages with a sort of class hierarchy starting with 'sprites' (purely decorative entities) up to playable characters (PERSO depicted here). Each of these class of game entity comes with a detailed set of "registers" and code pointers. They can detail things like attack and defence levels (inherited from RSD), invincibility frame counters, but also position and frame identifier within animation tables.

Like I did with Clicker, each of these 'registers' is carefully assigned an 8-, 16- or 32-bit size and the size of each set of registers is accounted. All of this is of course completely obsolete.

I also draw from Clicker's fonts rendering the idea that it is best to have generated code used to pset some pixels while others are left untouched on those pre-MMX, low-bandwidth video adapters.

That idea extended quite naturally to the fact that most characters in Bilou are meant to be made of small sprites. They are called 'blobs' in this work, and you'll have some 'registers' that identify the first and last 'blob' in the list that can receive hits and first/last blob that can give hits.

There is one hiatus, however, that will never be resolved: those strict hierarchies with pre-defined roles (a bonus - which can be collected - is not an object - which can be picked up) will never accomodate with koopas that switch roles between pick-me-up shell and self-moving ennemies.




Tuesday, August 10, 2021

NUC en maintenance...

Mon beau-frère a beau trouver que je le sous-exploite, ces 2 mois sans accès à mon NUC auront été douloureux. C'est qu'après le passage du technicien WiFi, il n'était plus sur le bon réseau (le gars m'ayant mis un SSID tout en MAJUSCULEs. Eh oui). Et avec d'autres paramètres de sécurité.

Et le truc, c'est que depuis son installation d'origine, le NUC était en mode "cube numérique dans son coin douillet à côté de la chaîne HiFi". soit je communiquais avec par SSH, soit par un p'tit service web perso pour trier les playlists au fur et à mesure qu'on les joue, que ce soit par tablette, laptop ou smartphone-de-ma-fée.

Pour une raison inconnue, les gars de chez Intel ont pensé qu'une prise HDMI n'aurait pas tenu sur la face multimédia de l'engin et donc j'avais un câble mini-HDMI <-> HDMI au chaud dans un tiroir et un adaptateur miniHDMI:M->HDMI:F qui m'avait servi lors du setup initial sur le setup Raspberry de mon filleul. J'avais d'ailleurs racheté le même adaptateur HDMI->VGA que lui (on le voit sur la droite de la photo).

Fort heureusement, j'ai aussi chez moi un apparail auquel j'ai programmé un mode "forward HDMI". Je peux donc y faire passer mon signal pour éviter de devoir brancher deux câbles HDMIs l'un avec l'autre.

sudo modprobe zd1201 ap=1 # /etc/modprobe.d/wlan did not seemed to have effect before reboot.
sudo iwconfig enx00cafe00babe essid "bilou"
sudo ifconfig enx00cafe00babe 192.168.7.1 netmask 255.255.255.0
sudo vim /etc/udhcpd.conf # fix 'interface', 'start' and 'end'.
sudo vim /etc/default/udhcpd # set DHCPD_ENABLED
sudo touch /var/lib/misc/udhcpd.leases
sudo service udhcpd reload
sudo service udhcpd restart

Et *enfin*, mes consoles DS ont pu recevoir une addresse IPv4 et transférer des fichiers vers/depuis le NUC avec server.pl et sink.pl... Par contre, pa encore moyen de faire les mises à jour automatique (de runMe, qui devrait recevoir son nouveau mécanisme de rapport de iScriptException) parce que ils ont été configurés pour contacter 192.168.0.11 et rien d'autre.

Donc on va commencer par ajuster EXTRAFLAGS et recompiler tout ça ...

  • [done] /etc/modprobe.d/wlan.conf instead of /etc/modprobe.d/wlan allowed ap=1 to be auto-assigned
  • [todo] trying to reload the module while stick is plugged in fails to upload firmware with ETIMEDOUT (-110) errcode
  • [done] wireless_essid under iface enx00cafe00babe inet in /etc/network/interfaces allows to define SSID properly.
  • [done] I had to manually ifup enx00cafe00babe until the interface was added to the auto list of /etc/network/interfaces
  • [done] using Ubuntu HWE allowed the TPLink USB stick to be supported on my laptop
  • [done] nmcli dev wifi connect "bilou" ifname wlx00deca00fbad let my laptop connect to the bilou wifi as well.
  • [todo] looks like nmcli has to be re-done when I plug the TPLink stick again...
  • [todo] uploading purposely buggy greent.cmd could trigger the PatchWindow, but J.L.N's level still produces a *** cannot parse line*** diagnose halt instead.

Friday, August 06, 2021

Testpoints and borders

 Testpoints are the oldest check technique I've been using to implement collisions in my games. From Calimero to Bilou and even Crazy Brix. The idea was simply to check the color of a specific point on screen to decide whether it is solid or not. In Calimero, white was solid, and black was not. In Bilou (QuickBasic), pixels with all their 4 lower bits set were non-solid. Everything else was.

But by 2000, it was no longer sounding sufficient. I had a long technical discussion with Gedeon by then, who was enthusiast about Crazy Brix, but pointed out that ball/bricks collisions were imperfect. I had found (by browsing and floppy-swapping- and printing and reading) mask-based techniques for sprite-to-sprites collisions through shifting and masking. But I was still missing a way to do the same for ground and walls.

Then I came up with a paradigm shift: instead of doing checks on a bitmap, I could have a vector-based description of the level boundary and wrote a letter to Gedeon to present him how I'd do it.

There are still testpoints associated with sprite positions, but now they can be attached to the closest level boundary. They can be split in 4 casts depending on whether they should block as floor, ceiling or walls. Once a testpoint is associated with one border, checking whether we're in or out is trivial. One test, and that's it.

My idea was that we could build a graph or a network of boundaries for each cast, so we can switch from one boundary to its neighbour.

I had high hope to use that in my Ultimate Game Maker, but it although I said to Gedeon that navigating the 'network' shouldn't be that hard, just having a Mario-pipe in the level and falling below its height would make our 'right wall' (initially far away) become very near, and possibly skipping many other obstacles that are "shadowed" by the pipe.

edit: by re-typing this on 2021, it turns out that the solution to boundaries network might simply be to use something inspired by the 'portals' used in 3D engines (Ogre ?): above my Mario-pipe, you'd have an "empty" right-wall. That means when you're jumping and have no walls in front of you, the scanning is halted by a 'right-portal' that just serves the purpose of saying 'there's a pipe right below me'. Only when you go past the horizontal position of the pipe, you unlock the wall-boundaries that are further away.

Ah. Bin c'était supposé être un post de traduction d'un vieux post pour le tag-de-la-semaine et à y re-réfléchir, j'en viens à me dire que la clé, pour pouvoir utiliser ces bordures, c'est de rajouter des bordures-portail pour prolonger les bordures réelles. ça conserve le potentiel de décrire la structure du niveau avec moins de données qu'une tilemap, mais par contre il risque d'y avoir du travail pour l'édition de niveaux...

Et en cherchant un peu (autre chose), je retombe sur des illustrations qui doivent dater d'après la lettre à Gédéon, mais d'avant la tentative de moteur 3D pour Bilou.





Yono

Yono, c'est en quelque sorte le chaînon manquant entre Zelda et Sokoban. A priori, on pourrait le croire plus proche de Zelda, avec son vaste monde, ses personnages secondaires, ses coffres, sa monnaie et ses monstres.

Sauf qu'en réalité il y a dans tout ça énormément d'habillage (sympathique au demeurant) autour d'une mécanique de jeu très fortement empruntée à ce jeu qui figure parmi les tout premiers auxquels j'ai pu m'essayer sur PC: Sokoban.

Mais si, souvenez-vous: ce jeu où il faut pousser des caisses pour les placer sur des dalles précises malgré un level design encombré. Allez, Adree nous en avait même fait une version DS.

Bref, ici pas de manutentionaire, mais un éléphant aventureux. Choix de personnage qui valide immédiatement un gameplay assez "rigide" où il ne sera pas question d'essayer de sauter par dessus un bloc. Mais notre éléphant peut aussi participer à des puzzles basés sur les éléments air/feu/eau, tirer des cacahuètes pour exploser les balons et j'en oublie si je ne me fais pas un schéma de toutes les interactions que J.L.N et *deline ont rencontrées pendant leurs partie.

Mais du coup, fallait-il s'encombrer de tous ces éléments annexes ? un menu de sélection de niveau et un design "à l'essentiel" n'aurait-il pas fait l'affaire ? Eh bien aussi étrange que ça puisse vous paraître, je dirais "pas forcément". Je dois admettre que ces petits interludes où on défonce un peu des monstres ou explore des villes offre un relâchement bienvenu de la tension et que mes têtes blondes sont allées plus loin dans Yono que je ne suis jamais allé dans Sokoban.

Notez aussi au passage le design "cubique" des niveaux et l'omniprésence d'un motif "en damier" au sol, qui permet de toujours pouvoir se repérer dans la grille de déplacement des caisses malgré une vue isométrique (qui passe sans problème avec les stick analogiques des joy-cons). Le seul hic du jeu, c'est cette physique supplémentaire pour certains objets à faire tomber (entre-autre les clés) et qui peut nous troller en projetant une clé à un endroit inaccessible à la fin d'une énigme. ça n'arrive heureusement pas trop souvent, mais c'est bien pénible quand ça nous tombe dessus.

Wednesday, August 04, 2021

In a cubical world ...

Clay-Zulah did what I had dismissed: a side-viewed, ortho-thing-ic 3D rendering of a 2D game. With a fairly nice result, I must add. The selection of objects is quite well done and there's some Kirby's Adventure vibe in the color and "textures" that manage to make us forget they are all cubes.

The perspective effect is a bit excessive to my taste, but once in motion, I must admit the result is one of the best I've seen so far for such things.

Dans la série des jeux indés dont je suis le développement sur Twitter, il y a le titre de Clay-Zulah, qui a justement opté pour un rendu orthochosique d'un monde 2D en 3D avec des objets très cubique. L'option que j'avais écartée pour un Bilou 3D à la fin du siècle dernier, donc. Et je dois dire qu'avec sa palette et son style "Kirby's Adventure", il s'en sort assez bien.