Showing posts with label newcollide. Show all posts
Showing posts with label newcollide. Show all posts

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.

Monday, December 02, 2013

The art of Blading

For g88 release, carrying bladors was functionally correct, but still a bit cheap, as the carried blador could move through walls, ceilings and such. It would be an acceptable simplification of physic rules in-game if that did not meant you could "throw" it while it overlap solid structures, which would let it "stuck" there as soon as regular physics takes over to let it be thrown away. I want the game to feel professional, and demonstrate that a simple scripting approach does not imply half-baked behaviours. It's thus time to prove it.

Un taille-crayon qui passe à travers tout pour qu'on puisse le lancer n'importe où, ce n'est pas très réaliste, mais c'est acceptable dans un jeu vidéo. Un taille-crayon qui reste bloqué dans un mur quand on le lance, ça, ça fait tache. Surtout quand le joueur aurait théoriquement dû pouvoir le ramasser et l'emporter plus loin. Premier pas pour corriger ça, interdire à mon taille-crayon de passer à travers les murs (ce qui demandait un réglage spécifique du contrôleur freemove). Résultat: Blador suit maintenant Bilou "de son mieux", ce qui amène parfois des résultats curieux comme un saut quantique à travers un mur contre lequel il est resté scotché pendant 15 secondes lorsque Bilou émerge enfin d'un passage secret.

The first step is to make blador using freemove(1) instead of using freemove(0) when carried. Freemove is the controller that allows free movement typical from airborne ennemies such as the berrybat. The only thing it does before validating the desired movement is checking that you cando(m) where m describe some properties of the environment - like being something you can MOVETHRU. 0 is considered as a special case where you can always do what you want -- perfect for ghosts or sparkles that will fall of the screen. So now, blador can't get into walls, but curious things occur when Bilou gets into narrow passages where Blador cannot follow: Blador just sits where it is, and if at some point Bilou reaches a new position where Blador could fit above its head, Blador gets quantumagically teleported to that new location (yes, again).

Pour corriger ça, il faut que Bilou puisse être informé de la situation du Dumblador qu'il transporte. En '97 j'avais donc pensé augmenter mon "ulitmate game maker" d'un système de messagerie entre les personnages. En fait, ici, on va faire beaucoup plus simple: tout comme l'encrier possède une zone-test (hitbox) qui repousse Bilou lorsque celui-ci l'approche, le Dumblador transporté va disposer de murs invisibles qui empècheront Bilou de s'en éloigner de trop tant qu'il le transporte. Eh oui: c'est aussi simple que ça.

Enfin, presque. Il y a quand-même une subtilité dans le cas du saut. Si je me contente de forcer Bilou à faire du sur-place au milieu d'un saut juste parce qu'un taille crayon a la tête dans le plafond, ça fout en l'air la crédibilité de la physique du jeu pour donner un effet Badman/RSD Game-Maker carrément pathétique. Il faudra donc que je traite cette collision aussi du côté de Bilou en forçant une remise à zéro de la vitesse, exactement comme le contrôleur "gravity" l'aurait fait si on s'était vraiment retrouvé directement dans un mur.

I like how Bilou/Blador distance is stretched or squished when colliding the environment, but I need more control over it. And that's just a perfect fit for the "repel" action introduced with solid inkjets. To avoid having Bilou going too far away from the carried Blador in a narrow tunnel, I just need some repelling-areas acting as virtual walls at appropriate distance from its position.
The same approach allows Blador to take some room between Bilou and the ceiling, but here I need some additional action. "Repelling" simply adjusts coordinates and does not affect speed. The result was that Bilou would keep floating along the ceiling as if he virtually kept jumping. Even weirder: he might have resumed moving up as soon as he'd have moved away from what was blocking Blador (just as in Badman II, actually).
To avoid this, Bilou needs to react on the collision and clear vertical speed. Additional tests are needed to ensure the blocking object (active GOB) is indeed over Bilou's head and that he's still moving upwards. The center-to-center distance (dy) is available through GobScript wf variable read and is positive when the active object is above the passive object (and yes, the sign of dx and dy is related to passive/active roles as the distance is defined only once, and then reused in both passive and active objects transitions).


Il me reste donc "simplement" à corriger l'ordre d'affichage de Bilou et du dumblador (tant qu'à faire, prenons-le en mode "hotte de père Noël" plutôt que "Sac de courses devant le nez") et à m'assurer que les mains de Bilou apparaissent sur le taille-crayon pendant qu'on transporte le crayon.

It leaves me with one last aspect to fix: having Bilou's hand properly shown as grabbing the blador while it is carried, knowing that hands will have to be aligned with blador rather than with Bilou if we want to keep stretch/squish.

Monday, June 17, 2013

Spongebop Rodeo

I now have a (partly-)working prototype where Bilou can grab a Sponge bop and stay hooked while swinging, but I have to hard-code the offset between Bilou and the Sponge as arguments of the copycoords controller. Not so elegant. Plus, if I also allow to grab on Bladors (granted, that's a silly idea, but it helped for debugging :), those offsets are no longer correct and we're rather grabbing some point in the air over Blador's top-right corner >_<

Bien. Bilou peut maintenant s'accrocher aux éponges en balance. Il y a encore des soucis non résolus avec l'animation prévue à cet effet (d'où l'absence de démo jusqu'ici) et un désagrément mineur: il m'a fallu ajuster à la main et préciser dans les paramètres du comportement "accroché à X" la position relative de Bilou et de l'éponge. Au moment d'ajouter le comportement "assis dans un encrier", ça me démange un peu.

I initially had plans for making those "grabs" act on an are, and it would make sense to actually state "copycoords(a.bottom=b.top ; a.center=b.center)", but I've just said that accessing GobAreas within a controller isn't practical.
Expressions handling a collision have access to some extra-context variables (wc-wf) which were just involved in that "repel" behaviour that made inkjet "solid".


  • xcontext[0] - wc -- collision flags
  • xcontext[1] - wd -- unused (0)
  • xcontext[2] - we -- X-axis center-to-center distance
  • xcontext[3] - wf -- Y-axis center-to-center distance
  • xcontext[4] -- not in GobScript - X-axis area overlap
  • xcontext[5] -- not in GobScript - Y-axis area overlap
 The idea would be to use some GobScript to compute/force the desired location, possibly record it in some GOB variables and have the CopyCoords controller simply enforce that offset from the GOB variables.

Il y aurait bien des solutions techniques pour automatiser ces coordonnées relatives en "alignement vertical, centrage horizontal", à la façon des éditeurs de diagramme ... il y aurait même un "chemin de moindre résistance" pour construire ça dans le contexte actuel. Mais soyons honnête: ce n'est *pas* un élément nécessaire pour le programme. J'ai un seul objet auquel Bilou puisse s'accrocher de la sorte (l'éponge) et je dois de toutes façon utiliser une autre animation pour Bilou-dans-l'encrier (donc, autre état et autres paramètres). Ce serait donc de la généralisation intempestive et prématurée! Caramba! Ça le ferait pas!

I could thus extend the "interaction opcodes":
  • A[p]: attach [with path] evaluating object to context object (works in hit and found)

  • D: detach evaluating object (works in any transition)
  • R[xy]: repels context object away from the evaluating object (works in hit and found) [only along x/y axis]
  • L[xy]: line up the evaluating object with context object (mirrored repel)
  • C[xy]: center the evaluating object with context object (wish)
  • Now, let's be honest. That's a "wish", not a "todo". I only have one grabbable ennemy so far, and only Bilou grabs it. "hard-coded" offset are just fine in that context, and alternative are "premature generalization". I thought about all this because I'll also need a "copycoords" when Bilou sits in an inkjet, but that will be another animation and another state, so other copycoords offset is just fine.

    Friday, March 08, 2013

    On se lance ?

    Quelques commentaires constructifs sur WoTP (et grâce au croquis animé d'Ymedron que je reprends pour être complet, nd2024), une petite scéance dans AnimEDS et quelques lignes de GobScript en plus ... Voilà des encriers qui ont des yeux, qui font "demi-tour" de manière souple, et -- comble du raffinement -- qui poussent aussi les tailles-crayons (et plus uniquement Bilou).

    the sketch drawn by YmedronNow it gots eyes! and thanks to Ymedron, it also gots a more powerful shooting time! Moreover, both Bilou and dumbladors may now get pushed by the hovering inkjet. I also managed to make the blador's top "solid" so that Bilou can move through a stunned blador horizontally, but not fall through it. I think everything should now be ready for moving platforms.

    After countless iteration on the animations, on the script files and a few bugfixes on the game engine and a good deal of WiFi DS-to-PC transfers, I finally have inkjets that throw decent ink droplets. Here's the byzanz-record. I think that will be it for this week-end: I've got some frying pans waiting in the queue.

    Tuesday, March 05, 2013

    Poussez-vous !


    Push ... push ... push.
    Après quelques "tatillonnages", j'y suis presque: les collisions avec les encriers poussent correctement Bilou, sans le faire se "téléporter" d'un côté à l'autre de l'encrier en cas de contact.
    Ce n'est pas encore parfait: je n'ai par exemple pas de "bloquage horizontal" pendant le mouvement vertical (et vice-versa), et les encriers peuvent enfoncer Bilou dans un mur. L'affaire de rajouter le bon cando() au bon endroit ...

    At last some time to try and add features in the game engine. After several tweaks, I have the right settings, and Bilou no longer goes through inkjets. Neither "normally" nor through quantum leaps. It still need polish, especially to avoid the case where Bilou gets pushed into walls. Most GOBs won't support that. It would be preferred to have a kind of "squish" animation that hurts Bilou when such cases occur. Funny enough, Bilou's code has not changed, except the addition of a simple collision flag. 

    Mais à force de petites touches supplémentaires, ça s'affine. Qui veut donc essayer de jouer les Beta-testeurs pour voir s'il reste des choses para-normales dans cette démo ?

    There's one flaw in the design, though: So far, I had "repels horizontally" or "repels vertically" opcodes, and a "completely solid" area was implented as "RxRy". That just doesn't work: it makes Bilou ridiculously align to the top/bottom edges while he's pushing the inkjet from the sides. What I need here is an independent "Solid" opcode that behaves either has Rx or as Ry depending on the direction that sees the largest center-to-center distance.
    Moreover, when you look at the captured animation, you can notice that something goes wrong when we fall off a inkjet that moves up. Bilou seems to have super-natural speed! That's because all the "repel" opcode do is to trick your coordinates. That's fine on the ground, but it implies they do not alter your speed, so gravity keeps building up Bilou's speed and everything happens as if he was at terminal velocity, falling from high heights. The proper place to fix this is in Bilou's state machine, adding triggers that resets vertical speed in those cases.
    Also, there are two metrics produced out of a collision: center-to-center distance, but also area overlap (signed). The later is used to define by how much pixels we should move one object to separate them. Only one of these metrics is available as "we" and "wf" variables in gobscript, but I'm not sure I was properly inspired when I picked center-to-center for the job, as it depends too much on how large objects are.

    Friday, February 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.

    Thursday, December 06, 2012

    Games of Thrown


    1MB. throwing in action ...
    mises à jour du moteur de jeu terminées: on peut ramasser et lancer des Dumbladors ... puis les re-ramasser et les lancer de nouveau. Enfin, toujours dans la même direction, je le crains, mais lancer quand-même.
    Je vais pouvoir passer à l'implémentation des inkjets, du coup ^_^b

    PS: attendez-vous à un ralentissement brutal et imprévu du rythme des messages de ce blog dans le courant du mois: *deline attend son petit frère j.l.n mi-janvier.

    The game engine now supports throwing of bladors. Pick it up, throw it, repeat. Many things could still be refined including
    • [done] having feet really hidden during the stunned animation.
    • [drawn] having the bouncing feet looking like feet
    • [done]allow the engine to shoot compound gobs too (new feet anim)
    • [done] allow runMe to launch the level as well.
    • [done] avoid one-way platform to corrupt behaviour of bouncing feet
    • [done] throw in both direction, and just drop if you feel so.
    • [wish] blador can stun baddies (and Bilou ?) while falling
    • [done] fix the map
    • [done] use dynamic palette assignment and get rid of those "crosses" marking Bilou feets in jump animations
    • [done] areas that can trigger only one other GOB (or a single foot can be consumed by 2 dumbladors simultaneously)
    • [wish] climb on stunned bladors, but still walk through them. 
    • [done] multi-color that works in runMe too.
    • [done] make sure we restart the level if killed, with colours.
    • [done] allow bladors to recover next to walls.
    • [done] Blador recovers when 2 feet have touched it.
    I'll do my best to get all that sorted out quickly so that I could offer the world a new playable demo for Christmas. Earlier arrival of lil'sson could force me to tolerate some imperfections in that release, though.

    Tuesday, November 20, 2012

    Jongleries ...

    Bon! Il reste encore du travail avant que ces choses rebondissantes puissent être associées aux pieds de DumbBlador qui tentent de retourner auprès de leur maître, mais au moins, elles se dirigent bel et bien vers l'objet qui les a lancées. Le mécanisme d'attachement fonctionne, et le contrôleur associé également. On va pouvoir poursuivre :)

    Neat! Things are thrown when one bops a blador, and once they stop, they'll move back and track the GOB they come from. If there's a wall blocking them, they'll jump higher to pass it. It's far from looking like "feet that go back to their body", but at least the mechanic works.


    Monday, November 19, 2012

    gob->attach(that)

    J'ai trouvé un cas de figure pour tester la fonction "attacher un GOB à un autre" qui doit me servir entre-autres pour transporter Dumblador ou pour faire de SpongeBob une plate-forme mobile.
    Je veux dire, "un cas de figure qui ne dépende *que* de cette nouvelle fonction".

    Starting to work on a set of new features such varied as "grab bladors and throw them onto other ennemies" usually raise the problem of "where do we start". Among all the features (aligning Gobs onto each other, tracking them, etc.), I need a first one that is simple enough and demonstrate the bare bones needed in the code logic: attaching objects at run-time. It seemed that bladors feet could be a candidate. When I draw Bilou bopping a dumblador, blador's feet are stretched away from its body. And when Bilou throws bladors at pendats, the feet are gone, leaving just a large chunk of steel ... a living weapon.

    It would be easy to have feet "thrown away" when blador gets bopped on, but then, what should we do when the blador recovers? It magically rebuilds up wherever its feet are gone, like New Super Mario Bros' drybones ? I'd rather not.

    Actually, I'd rather have feet attached to their blador although they have been thrown, and guided by a controller that pulls them back in place. The blador's body (the initial GOB) would then stay stunned until both feet have returned. Not only that sounds funny to do and play with, but it also means that the terrain surrounding the dumblador will affect how long it will stay stunned if you stomp it, and thus how tricky it is to grab it before it recovers. A nice interplay approach, imho.


    Je m'étais amusé à imaginer Dumblador perdant ses pieds au moment où Bilou lui saute sur la tête ... eh bien, c'est exactement ce dont j'ai besoin. Les pieds deviennent des GOBs autonomes, mais restent "attachés" à leur Dumblador d'origine, ce qui permet de définir des contrôleurs qui les ramènent vers celui-ci. On verra par la suite si celà crée un gameplay intéressant, mais pour l'instant, ça semble un test prometteur.
    • Le mécanisme "pending" qui garanti que l'objet auquel on fait référence a déjà été traité n'est pas encore complètement opérationnel.
    • Lors de la génération des "tirs", ceux-ci sont assimilés aux objets passifs d'une collision alors que le "tireur" est l'objet actif.

    Monday, November 05, 2012

    throwing bladors

    I can be glad I'm done with the "bottom things" of my summer todo list. Now the winter is starting, and what is left is what is more linked to the game logic and the revised collision engine which is waiting to prove its superior capabilities with some dumblador stunning and throwing.
    De temps en temps, ça fait du bien de retourner à une "liste de choses à faire" pour s'assurer que le projet avance effectivment. Bon, des "todo lists", vous devez tout doucement commencer à en avoir une indigestion, mais je parle ici de quelque-chose qui s'approche plus d'un "planning" que des micros-tâches à effectuer sur un temps de midi. Mon dernier planning datait de mi-juin ... voyons où on en est... tous les éléments "du bas" ont été satisfaits, à grand renfort de mises à jour de SEDS et AnimEDS. Je vais donc pouvoir cet hiver attaquer sérieusement les nouveaux types d'interactions entre personnages: assomer, attraper, balancer.

    On dirait que les mois à venir vont être durs, chez les Dumbladors.

    At those "milestones", I can close many former todo lists, by collecting in a new one the items that remains pending but that weren't really linked to the then-going activities. And yes, this is truly a milestone, since I now have fully operational CompoundGobs, including the definition of palettes for individual limbs (altering the palette while playing the animation will be for a next milestone :P)

    • [done] looping move should only be generated for looping animations
    • [done] initial Mx,y statement should be ignored by the game engine (actually, everything that delays the rendering of the first frame of the animation should be skipped). That will partly solve the "landing bug".
    • [todo] most of blador's debugging could have been avoided if we had the state-initialisation expression feature implemented.
    • [done] not detaching an attached GOB when "throwing" it may have weird effects, but I would have liked the display list to be re-ordered so that such side-effects wouldn't have systematically occured.

    Sunday, March 04, 2012

    fusion!

    Well, I owe sepcot a drink for his tutorial on "how to merge a Svn branch back in the trunk". Oh, sure, I could have dug the official documentation and find out by myself... in a few weeks. It's now achieved, and afaik, AppleAssault still works. Why is it of any relevance ? because runme is sticked on the trunk and that runme with the new engine means I'm able to prototype new monsters, new levels and such ... something the school zone will definitely appreciate ^_^

    Grand merci à sepcot pour son tuto. Mes déviations "moteur de collisions" (newcollide) et "moteur d'animation" (companim) sont maintenant intégrées sur le "tronc" de développement, là où se trouve également runme, qui intègre transfers wifi, lancement des éditeurs et petit moteur de jeu pour le prototypage rapide pendant le temps de midi. On va pouvoir attaquer la school zone plus sérieusement ^_^ A commencer par un dumblador qui marche ...

    Tuesday, December 27, 2011

    branch/newcollide : buggy

    Voilà environ 3 mois que j'ai entammé la révision du moteur de collision de Bilou, avec pour objectif de permettre la gestion de blocs, plate-formes et autres. Je n'ai pas avancé très vite, mais le code compile et fait tourner AppleAssault ... enfin, presque. Voyez plutôt ....

    3 monthes to get a first prototype of the new collision engine. I haven't been very quick on that, but at last, Apple Assault mostly work again ... well ... sort of. I'll let you judge that.
    -- btw, I wonder whether desmume-cli --record-movie would be easier to use than byzanz-record for those posts. Please, allow me to debug that on-line:


    # stopped by monster-player collision.
    statW0->statF2 on found1 (v0 ~ :0 200 ~ :1)
    statW1->statF3 on found1 (v0 ~ :0 200 ~ :1)
    Makes the appleman bounce when it hurts Bilou
    #hit
    state4..7->statH15 on hit0
    \\ [wc 1 ? we 0 < &] (256 ~ :1 512 ~ :0 0 :6 x1)
    state4..7->statH16 on hit0
    \\ [wc 1 ? we 0 >= &] (256 ~ :1 512 :0 0 :6 x1)

    The collision halfly works, on the video above: the applemen indeed bounces and the collision is triggered. But Bilou isn't affected. Afaik, that's because something got wrong in the guardian expression (conditions between the square braces) that can no longer be true in the new collision engine. Before we actually take a transition to the "hit-to-left" (H16) or "hit-to-right" (H15) state, one must detect where the collision came from (test on 'we', other dude's variable #14, which holds centrum-to-centrum horizontal distance), and whether it was actually something that hurts (test on 'wc', the other dude's variable that indicates the matching collision bits on both active and passive collisions area). For some reason,
    case OP_GETCTX:
    if (sp>=STACKSIZE-1) return oops("vCTX");
    if (c[1].data==0) return oops("!CTX");
    if ((op&0xf)>=0xc) stack[sp++]=xcontext[op&0x3];
    else stack[sp++]=c[1].data[op&0xf];
    break;

    Did return at the oops("!CTX") line. In that case, the expression is never true. Bilou won't ever got hurt. I must be missing something that swaps contexts in the code that manages collisions, at the root. Some gc[2]=gc[0]; on line 1742 could do the trick...

    that and some silly boolean inversion in the c[1].data =? NULL condition ^^"

    Tuesday, December 20, 2011

    The missing BlockAction

    Here's a scan that discusses a missing abstraction in my model so far, to carry on a "thread" on a map location (as compared to a tileset location). I figured out I was missing it when I tried to implement crumbling floors for the "nut's'blots" intermediate project, in june 2010. It remained a draft sketch all that long.

    An amusing fact: despite this is still missing from the *model*, there is actually creation of a GameObject derivative (BlockArea) so that you can proceed with evaluation of the "block:on hit" expression ... so all it would require would be to capture this derivative for longer than just a collision. I just realised that while investigating why the new collision system no longer works with interactive blocks...


    Un vieux scan de Juin 2010 avec, en Français, le détail des "BlockAction" qui manquent encore à mon modèle de jeu. D'une manière assez amusante, la manière dont les interactions sont gérées vont déjà dans ce sens même s'il n'y a rien au niveau du "gobscript" qui permette d'en exploiter plus largement les possibilités.

    A less amusing fact: this was all coded before we had dynamic gob lists, and it's now trying to de-register a Gob from the game engine several times every frame (especially when the interactive block is not de-activated by the collision). That could explain some performance issues observed in early AppleAssault prototypes.

    edit: finally implemented as MapAnim

    Tuesday, November 29, 2011

    Lake District.

    Infolab216h du mat... si j'ai dormi 4 heures sur la nuit, c'est beaucoup. Le lit est une vraie planche, et si mes voisins de paliers ne sont pas franchement bruyants, l'accoustique du bâtiment ne permet pas d'apprécier leurs tentatives de discrétion à leur juste valeur. Je suis en visite dans le district des lacs pour la semaine ... et je sens que ça va être un longue, très longue semaine.
    Avec du café et des bananes.
    Mais bon, faisons un peu le point. Début de l'année, je me fixais pour objectif de faire une première release publique de l'éditeur de niveau et de passer mes autres outils sous le "nouveau" devkitpro. C'est fait. Je me suis autorisé à faire de nouveaux graphismes pour la School zone, étant donné "qu'un premier jeu a été réalisé avec les graphismes de la green zone". Ils ne sont pas encore au complet (il me manque un décor potable, par exemple, peut-être en transformant la bibliothèque en un vrai campus), mais ils prennent forme. Le prochain jeu d'arcade de Bilou se fera dans la school zone. Ce sera sans doute "deep ink pit", mais il y aura une ou deux "gedsdemo" avant ça, pour tester le comportement des monstres... et m'amuser un peu ^_^
    Ce serait peut-êtr bien le moment, tiens, de mettre le couvert avec les monsstrrrres. Un bien grand mot pour Bop, Dumblador et les encriers que ma petite puce nomme maintenant avec excitation. "Tu vas dessiner Bilou, toi?" me demande-t'elle à chaque allumage de ma DS(i) ... et ces derniers jours la réponse était plutôt "non, ma puce, Papa essaie le jeu de quelqu'un d'autre" (Shantae. On en reparlera). Voyons...

    • Bop, l'éponge, pendue à son fil. Ça demande un contrôleur nouveau, capable de gérer ses oscillations. Je me suis déjà amusé à voir comment faire ça avec de "simples" accélérations autour d'un point... sur le papier, ça tient la route, mais il faudra le coder pour voir.
    • "inkjet", l'encrier. Lui, il attendra sans doute que j'ai une version qui compile du nouveau moteur de collision: il est le candidat idéal pour les alignements de Gobs qui rende possible les poussées, transports et autres plate-formes mobiles.
    • Dumblador. Je devrais probablement commencer par là. En plus, c'est le candidat idéal pour faire quelques tests d'animations modulaire, vu que je ne lui ai pas dessiné de pieds. J'aimerais reprendre les pieds de Bilou, mais en rouge. Solution de facilité ? les recoloriser. Solution idéale ? activer enfin le support multi-palettes, puisque la DS supporte en réalité 32 palettes de 256 couleurs (16 pour les tiles et 16 pour les sprites).
    Je crois que je vais choisir la facilité pour l'instant. Sinon, on risque fort d'en causer encore à Noël. Or, ce serait plus sympa de faire des essais dans gedsdemo-books, à Noël, non ?
    Bon, là-dessus, il est enfin 7h ... je vais aller trainer mes baskets jusqu'au bâtiment où ils servent le petit déj.
    Oh, well. Sorry, english-speaking folks. I was just "thinking out loud" to figure out where to move now. Since I'll have to speak english the whole week (travelling), please allow me not to provide a personnal translation this time :P
    edit: While speaking out loud, I was wondering which of the School Zone ennemies I should implement first and how it would help to validate new game engine features

    Tuesday, October 18, 2011

    branches/newcollide

    So I finally started a new SVN branch with the collision engine modification that I sketched in the train. It's not going to be testable anytime soon, I'm afraid. The current collision engine was already abusing some "setContext(...)" calls to set static variables into GobExpression so that you can e.g. shoot things despites the eval() has no such thing in its argument. With the new "attach" and "align" features I want to develop, that becomes a huge mess of things to capture at various places in the GOB -> GOB -> area -> state -> expression call chain that happens at every collision. I bet the best move will be to extract all this context (including some of the things that are currently plain arguments) into a GobCollision structure which would have temporary lifetime (i.e. allocated on the stack) that would be passed around ...

    Well, that'd be better unless the compiler is able to keep all the arguments in registers otherwise :P

    Je dirais bien "assez causé, implémentons ces fameuses nouvelles collisions". Sauf qu'en fait non. Les petites modif' faites par-ci par-là dans le Boutdlard Express ne compilent pas, et si je fais ce qu'il faut pour qu'elles compilent, ça va être une véritable pagaille dans le code. Genre "la famille araignée en vacances dans une boites de spaghetti géante", voyez? J'ai une petite idée pour rationaliser tout ça sans perdre en souplesse ni (trop?) en performance. Je vous en dis plus après avoir fait le test.

    Thursday, September 29, 2011

    blocking GOBs

    Vous vous souvenez peut-être d'un commentaire de mon frère CJ comme quoi "il faudrait quand-même à un moment donné qu'on puisse avoir des ennemis à travers lesquels on ne passe pas même si Bilou est invincible... une chose que je n'avais pas vraiment prévu de rendre possible dans le moteur de jeu de "Apple Assault": Bilou ne sait pas traverser Funky Funghi simplement parce que dès qu'il le touche, il est blessé et repoussé en arrière. Mais pour les encriers et les plate-formes mobiles, ça risque de causer bien d'autres soucis.

    It may look like Bilou can't walk through Funky Funghi in the released demos so far, but I'm actually cheating. What happens is that every time Bilou touches Funky, he's hurt and slightly bounce backwards. It wouldn't be possible that have an harmless, blocking sprite with the Apple Assault engine ... fairly annoying to implement inkjets in the schoolzone, isn't it ? I't's been a background question for a while now, and many solutions have been dismissed already, but I quite like the latest one: have object-to-object alignment primitives in GobExpressions so that you can say "hero is moved out of inker's area" between "play a 'ding' sound" and "shoot a sparkle"

    Du coup, pourquoi ne pas simplement prévoir quelques actions "de base" d'alignement au niveau des expressions gobScript ? Plus besoin de définir des flags "sprite solide" ou "non-solide", "solide uniquement de haut en bas", pas besoin de venir bricoler les contrôleurs de comportement: on prévoit simplement qu'un des personnages impliqués dans une collision puisse donner l'instruction "repousse l'autre hors de ma zone de collision verticalement" ou "centre l'autre sur ma zone de collision horizontalement". Même la création d'un lien "transporteur/transporté" peut s'y retrouver. Chouettos.

    Personnally, I like how "clean" this approach is. No need to hack something about the collision classes, no need to hard-code some directions of collision, no need to expose more things like absolute location or area properties to the gobScript. Just "block-x, center-x, attach" instructions that will be interpreted in a context where both areas are known by the engine. Just one little detail shows up when reading back the code of the collision engine: only "passive objects" will be capable of using those new operations, because state transitions for the "active object" in a collision are taken after collision tests for that object. Who had collided is no longer known. on found [...] (...) is thus not allowed to use any of the 'extra context' information.

    Par contre, en relisant le code, je me rends compte que seul l'objet "passif" dans une collision aura la possibilité d'ajuster sa position ou celle de l'autre objet. Toutes les notes on found sont donc en réalité impossibles à moins de changer aussi le coeur du système de gestion des collisions: il faut les ramener à on hit[]. On garde les plate-formes passives même si c'est elles qui contiennent le code qui aligne les objets.

    Conséquence: si je veux qu'à la fois l(a plupart d)es ennemis et les personnages puissent déclencher une réaction avec des plate-formes "passives", il me faudra une classe "Solid Moving OBject" en plus de "HERO" et "EVIL".

    That may have some impact on the way we script those objects. Most of the use cases do not cause strong problem, except the "platform that carries both heroes and foes". There, I'd love to make sure that 1) the platform is passive, so that it holds the collision logic 2) I don't end up with O(#foes²) tests in collision tests. It sounds like I'll need a SOLID class in addition to HERO/EVIL, so far...
    Small battle plan:

    1. add a "transported" state. (e.g. standing on platform)
    2. enforce coordinates alignment.
    3. make sure you're free to move when transported
    4. handle disappearing platform.

    Saturday, July 16, 2011

    Implémenter les plate-formes.

    Aah. De vraies vacances, ça fait du bien, même si ce n'est que quelques jours... qui se terminaient par un peu de baby-sitting à un mariage cet après-midi. L'occasion de refaire un peu le point sur les problème des plate-formes mobiles. Le point essentiel, c'est que -- tout comme le transport d'objets par Bilou -- ces plate-formes dépendent de la possibilité de lier un gob à un autre temporairement. Un micro-contrôleur "follow", donc, qui déplace p.ex. l'appleman à l'identique de Bilou.

    At last some day off ... really off. Not even some Bilou thinking until this afternoon "_". And I had no documentation or current code state with me when doing so, which somehow explained why I focused on a fairly remote problem such as moving platforms. The last thoughts came to the conclusion that being carried would involve a dedicated "follow" micro-controller where a Gob is attached to another.

    Be coherent
    Comment s'assurer que la plate-forme aura déjà fait son déplacement au moment de déplacer ce qui s'est posé dessus ? Sans ça, on risque d'avoir des effets de "décalage" chaque fois que la plate-forme modifie sa vitesse, comme ceux qu'on peut observer dans Zool.

    To make that work, however, it is mandatory that the carrying object has moved before the carried object's movement is evaluated. Otherwise, the player will experience zool-like glitches everytime the absolute speed of the carrier is altered. The FollowController must thus be able to detect whether there is an not-yet-processed carrier situation and execute anticipatively the "animation" of that carrier. That will require some more book-keeping at the core of Engine::animate(), but I think it'd be more flexible than pre-encoded priority levels.

    Pour y parvenir, le mieux sera de faire en sorte que FollowController::think() puisse détecter si son objet-cible a déjà été exécuté ou non. On joue là au plus profond du moteur de jeu, qui appelle Animator::play() sur chaque objet qui s'est enregistré via reganim(). J'ai déjà une liste "pending" séparée de "todo", il me reste à noter au niveau de Animator lui-même où on en est. Après ça, il suffira de se faire un petit if (target.state==QUEUED) target.play(). L'objet-transporté voit alors son exécution interrompue le temps que l'objet-transporteur soit mis à jour.

    Thou shall not follow the NULL pointer
    Avec ce mécanisme, je vais introduire pour la toute première fois une référénce directe entre deux personnages du jeu. Jusque là, je passais systématiquement par le tableau GameScript::gob[] ou je me limitais à une interaction éphémère lors d'une collision. Si je ne fais rien de spécial, une plate-forme détruite pourrait amener les objets transportés dans un état incohérent, voire provoquer de sérieux problèmes au gestionnaire de mémoire ou planter sauvagement le jeu.

    The second challenge I addressed is to ensure that we can handle the disappearing of the carrier transparently for the carried object(s). We can do that in different ways, some including list of cross-references, etc. but it looks like the best way around could be to delay actual Animator::DELETE requests by one frame so that the former carrier can be caught in DISCARDED state by FollowController::think() method that would drop then the reference.

    Je pourrais exiger du "programmeur gobscript" qu'il règle ça lui-même en prévoyant des états-tampons ou des collisions de désolidarisation, mais ça signifierait qu'une erreur de script dans la machine d'état d'un objet pourrait se traduire en un dysfonctionnement du moteur lui-même... à proscrire à tout prix. Ca risque donc de me coûter un Engine::animate() un peu plus sophistiqué, mais l'idée est de garantir que tout objet "qui s'en va" sera présent au moins pendant une frame dans l'état "DISCARDED".