Showing posts with label physics. Show all posts
Showing posts with label physics. Show all posts

Saturday, March 01, 2025

Pas si circulaire ...

Bon, j'essaie de mettre au point le fait de s'accrocher aux racines, et ça malgré le fait que j'ai noté quelque part "oui, ça ne marche pas parfaitement, mais c'est amplement suffisant pour faire le tour des niveaux sans ce prendre la tête".

C'est sans doute ce que je ferai dès demain, mais il faudra que j'y revienne et que je corrige un peu tout ça. Un composant "reste dans le cercle" avec un comportement cahotique, c'est marrant pour SpongeBop à cause de son élastique ... mais pour les lianes qui pendent ? les signets ? les ponts ? les boss ?

Technically, it would be nice to have Bilou reusing the "stay within radius" behaviour of SpongeBop when he's hanging at a root. Just have a smaller radius, show his hands grasping the root and voilà (oh, and remove the white polygons, please). That would work if that RadiusController wasn't randomly jerking up. Jerky monster with funny tik-tokking eyes is fun. But a jerky bookmark ? A jerky vine ? that looks suspiciously close to a bug to me

I had already fixed a more serious bug last week, and somewhere on some note book, I wrote down that "jerkiness shouldn't hinder levels traversal. Keep it as is and keep going". And yet there I am. Maybe this number shouldn't be that high ? Maybe that thing is wrong ... What does it look like in DDD?

Je vous ajoute deux petites capture-gif pour que vous vous rendiez compte si vous n'êtes pas allés vous promener sur mastodon ces derniers temps ... une où ça va pas trop mal (ci-dessous) et une ou ça part dans tous les sens (ci-contre)

Dans les deux cas, je ne donne aucunes consignes avec la manette. c'est juste "l'énergie de départ" qui est hors contrôle ... ou un problème d'arrondis qui s'accumulent ... ou quelque-chose de plus fondamental.

J'ai fini par rajouter un printf("%vx,vy + %corr_vx,corr_vy @%extra_radius") dans le code et faire cracher des tonnes de chiffres pendant que ça partait dans tous les sens (le debugging step-by-step, sur un problème comme ça ne donnait rien). Contrairement à ce à quoi je me serais attendu, on a très peu de "brusque augmentation du vecteur-vitesse" ... par contre, on a régulièrement un vecteur plutôt important (correction d'1 ou 2 pixels) parfois pendant 2 frames d'affilée. Dans un setup où la gravité met 8 frames à augmenter d'1px/frame, ça veut dire que Bilou va facilement nous faire un petit bond de la taille d'un caillou quand ça se produit.

The 2 screenshots above show the state as of ScreenshotSaturday, 5PM. I guess I don't have to convince you that it would look broken, if the game was doing that while you're not even pressing any button of your DS. I added print statement, revealing adjustments performed to stay within the radius (step-by-step debugging doesn't really work for such use cases), and even shooting a video of those lines so that I could time-travel and see what were the causes of sudden bumps... Except that there were no "sudden huge speed". Instead, there were multiple frames with 1 or 2 pixel-per-frame corrections, but that was already fairly strong for 1/8th-of-a-pixel-per-frame gravity. At 8PM, I had given up: it would require a complete rewrite to get stable behaviour, for sure.

Alors voilà ... j'ai copié le code de RadiusController::think dans un carnet pour pouvoir le comprendre et l'annoter ... j'ai voyagé dans le temps avec les captures .gif et analysé les chiffres que mon print avait produit et ça me donne le sentiment un peu désagréable qu'il n'y a rien de corrigeable dans ce code, parce que l'impact sur la vitesse persiste plus longtemps. Peut-être faudrait-il corriger directement la position, mais alors on perdrait la transformation de la chute en un mouvement de balancier...

edit: vous l'avez lu, j'étais sur le point de jeter l'éponge ... puis le lendemain matin, j'ai voulu tenter quelque-chose quand-même: et si les valeurs dx et dy que j'utilise pour vérifier si dx²+dy²<radius² n'étaient pas exprimées en pixels mais en subpixels ... pas en 256èmes comme la vitesse parce qu'il faudra quand-même les multiplier et que ça ne déborde pas ... mais des 16èmes de pixels ? Eh bien, avec ça, ça donne quelque-chose de beaucoup plus convaincant... je vous remet une mini-animation sur le côté. Il y a un peu de vibration résiduelle mais rien de vraiment choquant. Et ça malgré que Bilou partait avec un mouvement du genre à faire des bonds dans tous les sens au commit précédent.

But as I started my Sunday, I wanted to try something before rolling back to where I was on Friday: adjust the algorithm so that it would work with sub-pixel precision. 16th of pixels, to be precise, just the intermediate between pixel coordinates and current 256th of pixels used for speeds and entity positions by the engine. And ... well ... it turns out I now have something that converges towards a stable state. It's a bit sad for Spongebop... I'll have to try and find a way to turn of stabilization for them ^^".

Il me reste à trouver un moyen de rendre ça paramétrable, des signets qui ne soient pas élastiques et des spongebop qui le soient (la pauvre, obliger de circuler le long d'un parfait arc de cercle, c'est vraiment la dictature de SquareRoot ... je ne le lui souhaite pas).

edit²: le changement d'échelle (subpixel 12.4) suffit à lui seul pour avoir une éponge qui suit une trajectoire toute circulaire ... mais pour Bilou qui peut débarquer avec un vecteur-vitesse quelconque, il faut bien tous les petits ajustements. ça sent le code split, parce qu'il n'y aura rien à paramétrer ...

Tuesday, January 29, 2019

Loco Roco ... enfin!

A force de faire des brocantes, mon frère a fini par mettre la main sur une PSP et une petite collection de disques de jeux, parmi lesquels Loco Roco, le jeu que j'avais envie d'essayer depuis près de 10 ans. Un concept de jeu assez sympa, mais avec un mode de contrôle que je trouve lassant au bout. de quelques niveaux.



20181228_133722.jpg
Le principe de base me fait penser à Soul Bubble : suivre un parcours, trouver des petites cachettes et faire gaffe à ses points de vie.

Là où Soul Bubble semblait se battre contre le hardware de la NDS, Loco Roco offre un graphisme tout en finesse et fluide à souhait. Les structures mobiles sont particulièrement réussies, mais malheureusement trop souvent utilisées comme des mini-cinématiques.

Même impression pour le mécanisme "fracturer Loco Roco en plein de petites boules": il est presque toujours équivalent à un "démarrer la cinématique"... Et là où Soul Bubble offrait une mini-map du niveau et un indice sonore à proximité des zones secrètes, on navigue beaucoup plus en aveugle sur ce titre. Et trop souvent sans possibilité de faire marche arrière.

Bon, venous-en an coeur du problème: on ne contrôle pas son personnage. On peut seulement incliner le niveau dans un sens ou l'autre. Et pour sauter, maintenir les deux gâchettes pour "charger" le saut puis relâcher. Le résultat est imprécis, il y aura beaucoup d'erreurs. Il faudra réessayer encore et encore. C'est le genre de chose qui devrait pouvoir se travailler, mais j'avoue ne pas avoir l'impression de m'en sortir mieux après une dizaine de niveaux. Je crois que je vais en rester là.

Tuesday, April 09, 2013

Circularity

Spongebop monster design was a way to convert the (imho) funny and interesting spider monsters of prehistorik 2 into Bilou's world. As such, they won't simply move up or down, or track Bilou while sliding (as suggested in the 20-year-old proposal), but also rock and roll, hanging by a thread. Another conversion of dangerous-but-useful NPC rather than an evil ennemy.

Une éponge qui se balance au bout de sa corde ... une idée de monstre sympa et qui ouvrait pas mal de perspectives dans la "School Zone", mais techniquement plus délicate à réaliser qu'un "simple" monstre sauteur ou marcheur, en particulier avec les contraintes techniques de la DS. Depuis l'automne dernier je dois bien avoir gribouillé 3 ou 4 techniques succeptibles de rendre la chose possible sans jamais être allé jusqu'au stade de l'expérimentation. Mais maintenant que je peux attacher un objet à un autre au niveau du script, il est temps de monter un prototype.

Now, it's time to turn this "nice idea" into some real code. Physically speaking, spongebop will act as a pendulum bob, oscillating as the result of gravity and counter-force originating from thread tension. We're taught that when 17 at school. There's just two major drawback to a "straight coursebook implementation":
  • it's full of angles, sin(x) and cos(x), which are pretty heavy for our 66MHz processor
  • It assumes a rigid, fixed-length rod between bob and pivot.


Conservation de l'énergie, mouvement circulaire ... ce ne sont pas les approches qui manquent, mais chacune a aussi ses hypothèses de travail (notamment la présence d'un axe fixe que je ne désire pas). J'étais au départ prêt à utiliser une variante des algorithmes à la bresenham pour les cercles, mais la multiplication n'est en fait pas si coûteuse en terme de temps de calcul que je ne l'aurais cru. Je peux donc exploiter assez librement l'équation x²+y²<=r qui décrit tous les points à l'intérieur d'un disque. Dès que les la distance entre SpongeBop et son point d'attache ne valide plus cette contrainte, c'est qu'il tire trop sur la corde.
     Bilou would pretty much love that sort of predictable and massive pendulum platform, but spongebop's thread is instead fairly elastic and landing with excessive velocity triggers a rodeo session, says the comic concept art.
    In other term, I would like something more flexible, that can constraint Spongebop to stay within a certain circular area, but still allow Lissajous-like patterns when drawn away from its equilibrium path, as I explained this lunch-time to Cyril. So fundamentally, Spongebop's behaviour is defined by two controllers:
    • gravity, that takes care of the "free riding" when x²+y²<r²
    • radius detects situations where x²+y²>r². As soon as that occurs, we use a 'unit' vector that points towards the pivot position and iteratively move spongebop back into the allowed area.

    Ce qui est assez amusant, c'est que si je parviens à faire en sorte que SpongeBop ne puisse allonger exagérément sa corde, j'aurai le mouvement de balancier par simple application du même contrôleur gravity que celui qui sert pour les sauts de Bilou. Je rejoins alors le "scénario BD" qui prévoit un comportement plus cahotique lorsqu'on atterit trop violemment sur le dos d'une éponge. J'utilise donc le vecteur "attache-éponge" pour définir une "direction de rappel" et ajouter un déplacement vers le centre tant que Bop est hors de son cercle de repos.

    Ideally, energy preservation should keep the sponge oscillating as long as the level runs, but there's something that looks very much like friction in the digital world: precision loss. Since we're working with fixed-point arithmetic here, we're losing some speed in rounding coordinates and angles, so that after about 3 cycles, there isn't much movement left. It's compensated by a refreshing impulsion generated everytime Spongebop arrives just below the pivot point, as if it had some muscles that helps it control its movement. That part is handled by some gobscript and the controller merely report "you're at (0,ymax)" through an event.

    it's a sponge bob ^_^

    MUL instruction on ARM9 merely takes 2 cycles. As a result, I ended up dropping my initial idea of using (x+1)²=x²+2x+1 and simply re-compute (x+a)*(x+a) whenever needed.
    I have at most one division per frame (per instance), to define the centripedic 'unit' (1/16th of pixel) vector. Yet, division isn't handled by the CPU, but by some extra software (the support library coming along with devkitpro's flavour of GCC). I think I'll live with it unless it turns out that I'm over my cycles-per-frame budget.


    Le résultat est plutôt satisfaisant. Ce n'est pas un arc de cercle parfait et je dois "relancer" le mouvement régulièrement, les erreurs d'arrondi en virgule fixe ayant tendance à l'amortir trop rapidement. Je m'en sors donc avec une division (software) par éponge et par frame au prix d'une progression itérative pour recentrer Bop lors de ses déviations. C'est plus erratique que le pendule du cours de physique, mais ça colle plutôt bien au personnage. Reste à maîtriser la 3D pour tracer l'élastique et le co-processeur mathématique de la DS pour avoir accès aux divisions et aux racines carrées la prochaine fois.

    Agreed, the trajectory followed by SpongeBop on the animation above is not quite a circular arc, but for some dizzy sponge on an elastic string, I think it does the trick. Now it's time I allow Bilou to "land" on SpongeBop, because solely bopping over is pretty tricky.


    Hmm ... tracing a GL_LINE between the spongebop and its pivot (not yet visible) would be a nice use case to introduce 3D support in the mix ...

    PS: all this was the last idea of a long list of dropped approaches. Maybe I'll discuss alternatives later on.
    PPs: of course, although the ARM processor on the DS has no support for division/square roots, the DS itself has extra hardware for such functions.  Since it says "square root takes 13 cycles", it could be worth to use the sqrt(dx²+dy²)/sqrt(R) ratio to properly compute the pullback force rather than relying on iterations here. (that's still an occurence of premature optimisation, imho)

    Thursday, September 15, 2011

    run, you fools!

    Mario, Sonic, Rayman ... chacun d'eux peut courir, mais l'impact sur le gameplay est chaque fois différent. Voilà un petit dessin-du-dimanche pour refaire le point. L'élément intéressant (pour un platformer) n'est pas tant qu'on va plus vite en courant, mais plutôt la manière dont on va exiger plus de maîtrise de la part du joueur quand il doit affronter "un saut plus compliqué".

    It's not that much about going faster, but rather about clearing longer holes with a jump. In most platformers, this is achieved through the RUN mechanics ... but not all. Check out my scribbled notes for details ^_^

    Dans SuperMario, il faudra gagner en vitesse, donc essentiellement contrôler l'absence d'obstacles. Le "triple saut" des épisodes du nouveau millénaire poussent cette contrainte encore plus à l'extrème.

    Rayman, en comparaison a un bouton de course "binaire". Un seul bloc suffit à faire un saut long. Par contre, le jeu est beaucoup plus pointilleux sur le timing du saut (point-test unique contre deux tests pour Sonic, peut-être ?).

    Keen, lui ne court jamais (ou tout le temps, c'est selon), mais l'activation du pogo permet de faire des sauts plus longs (mais ici aussi, il faut faire d'avantage attention au timing et à l'environnement). Fury est un peu un mélange de Keen et Sonic: on court de plus en plus vite, et on saute d'autant plus haut qu'on enchaine les sauts (il suffit de garder le bouton enfoncé).

    Sunday, July 31, 2011

    Sonic Camera Management

    Le suivi de Sonic par la caméra fonctionne donc sur le principe d'une "zone" de focus dans laquelle le centre de Sonic est confiné. Selon qu'il est au sol ou non, la taille de la zone change, mais surtout, dès qu'il en sort, la caméra se déplace d'autant qu'il faut pour y ramener Sonic (avec tout de même une vitesse limite qui permet parfois à Sonic de "larguer" la caméra... et le joueur).

    La grande différence avec le code dans Bilou, c'est que jusqu'ici, quand Bilou sortait de la zone de la caméra, j'accélérais le déplacement de la camera, pour ne le décélérer que si Bilou débordait à nouveau de l'autre côté, ce qui amenait des "oscillations" particulièrement gènantes en cas de saut, car l'écran allait continuer à monter de plus en plus vite alors que Bilou commençait déjà à redescendre.

    Voyons un peu si ça colle avec mes "désidératas".

    A state-dependent "allowed onscreen window" and a speed limit. That's all you need to get sonic-perfect scrolling. That is, the area of the screen where your character is allowed to appear vary depends on whether you're on the ground or on-airborn. I cross-checked with my requirement list for an ideal scrolling, and everything is there (further translation to come soon).

    Centré au sol et sur la chute
    Presqu'automatique si la zone de tracking est "applatie" à une seule coordonnée lorsque le personnage est au sol. La caméra enchaînera "presqu'immédiatement" pour suivre la chute si le bas de la zone autorisée pendant une chute est très proche de cette position de référence au sol.
    My first requirement is that the camera tracks precisely Bilou (vertically) when he's walking so that climbing slopes happens smoothly, but that it starts scrolling down quickly when a fall starts. This achieved by a very narrow Y windown for "on-ground" state, and keeping bottom limits close to each other when falling.

    garder un oeil sur ce que l'on évite en sautant
    Ce sera le moyen n° 1 de se sortir d'une situation délicate dans un "platformer": sauter par-dessus. Ce mouvement doit pouvoir se faire sans déconcentrer le joueur. On doit pouvoir passer de plate-forme en plate-forme (alignées horizontalement) au-dessus d'une mare de lave sans attraper le tournis. Simple aussi : il faut qu'un saut tienne en entier dans la hauteur de la "zone de non-scrolling" à partir de la position de repos (au sol). Ce n'est qu'en enchaînant les sauts que l'on parvient en haut de l'écran (et donc que l'on active le scrolling), mais dès qu'on retombe d'un de ces sauts, le scrolling cesse de monter jusqu'au saut suivant (objectif #5).
    Jumping is the #1 action in a platformer like Bilou (that is, where the hero has no weapon). It must be possible to hop from one platform to the next one without having the scrolling "bounce over and over" as well (which would give the player nausea). That's achieved with a fairly high "top limit" when the player is "on air". Yet if the player is "climbing up", he'll be kept on-screen. always.


    Recentrer sans à-coups
    De nouveau, ça tient au fait que le scrolling va ajuster la position de la caméra à la position du héros mais avec une vitesse limitée. Quand Bilou arrive au sol, on "rétrécit" à une ligne la zone de tolérance verticale de la caméra. Celle-ci va donc recentrer Bilou, mais en donnant une vitesse verticale maximale relativement basse (de 6px/fr pour Sonic alors que la limite horizontale est de 16px/fr), ce recentrage semble plus naturel.
    Now, that's okay to have the scrolling "keeping an eye on the danger from below", but when the action "moves on" on the new platform, it's annoying to press UP or DOWN just to move yourself back in the center of the screen. This can be safely achieved by a narrow "on-ground" Y window, but a slow speed limit on the camera (in my case, "slow" will be 1px/frame).

    Chouette. Tout y est. Plus qu'à coder tout ça. GravityController ou WalkingController auront donc la responsabilité de définir la "fenêtre autorisée" et la vitesse maximale, la caméra s'occupe du reste. Andiamo!

    Tuesday, July 26, 2011

    Sonic Physics Guide

    ça faisait un moment que je n'étais plus tombé sur de la lecture chouette comme celle-là. "pentes & blocs à pousser", "collisions", "gestion de la camera", etc. Ca va me faire de la lecture ... Attendez-vous à ce que je vous en dise d'avantage dans les prochains jours.

    A neat pick: the Sonic physics Guide starring handling of slopes, curves, camera movement ... knowledge likely generated from years of hacking the good'old Sonic 1 and Sonic 2 roms (for SEGA Genesis). Expect some more detailed posts when I'll be done with my readings. 

    TODO: make a small executive summary of it. You may use https://twitter.com/bigevilboss/status/1164309035270754306 as a starting point.

    Saturday, May 22, 2010

    Jump!

    Quelque-chose me dérangeait dans la manière dont j'ajuste la hauteur du saut de Bilou au timing du bouton de saut. Je passe les "classiques" en revue:

    • Sonic, qui ne semble avoir que deux hauteurs de saut et fera son saut maximal même si le bouton ne reste pas enfoncé
    • Mario, à l'opposé, peut faire de petits bonds ou de long sauts. Il faudra alors tenir le bouton enfoncé jusqu'au bout ... ou courir.
    • Giana Sister (version DS), peut comme Mario interrompre son saut, mais l'arrêt est alors plus brutal.
    Tout ça pour constater que le problème vient très probablement du fait que le changement de direction, aussi bien que le relâchement du bouton de saut, provoque la fin du saut de Bilou :P

    Wednesday, February 24, 2010

    I said *jump* !

    Mettez un commentaire sur un de vos posts dev-fr, en précisant que c'est pas vraiment une release, juste que vous avez la flemme de refaire un gif animé, et bardaf, le monde entier s'en empare. Ceci dit, ça valait la peine puisque Morukutsu (qui planche sur la suite d'Inside the Machine) a pu ainsi me pointer du doigt deux ou trois choses que j'ai encore à arranger.

    morukutsu says: J'ai vraiment du mal à sauter par dessus (ou passer par dessous) des champignons violets. J'ai du me résoudre utiliser le tremplin pour passer par dessus eux après avoir être mort 5 ou 6 fois.
    Y'a un tremplin dans mon jeu ?? où ça ??

    En discutant un peu, je me rends compte que c'est toujours le même problème qui fait qu'un champignon rouge censé servir uniquement de plate-forme est interprété comme un tremplin par le joueur: tant que le joueur garde le bouton X enfoncé, Bilou enchaîne saut sur saut...

    As long as you hold the 'jump' button pressed in the current demos, Bilou keeps jumping and jumping everytimes he lands. This led some beta-testers to mis-interprete platforms into bumpers recently. I'd prefer to keep this "jump frenzy" as a later power-up and require the player to press the button again at every jump.

    C'est assez simple à arranger dans l'absolu, mais je veux en profiter pour revisiter la gestion du DPAD et permettre de tenir compte du timing des entrées. L'idée ultime étant que lorsque Bilou "rebondira" sur la tête d'un monstre, il y ait moyen de doser la hauteur de ce rebond en appuyant sur le bouton le plus proche possible de la collision. Je prépare donc un peu le terrain pour "deep ink pit".

    At the root, it is not so complicated, but I want to make it ready for further development. Especially, sooner or later, I would like to use "bouncing on monsters" as a technique to access hidden or alternate areas of a level, in an attempt to have layered level design. To allow this, I plan to have timers associated with each button so that we can estimate how long the button is pressed, and e.g. adjust the bouncing impulse to the elapsed time since button press. If the delay is long enough, it's like you hadn't pressed anything.

    Par contre, toutes ces commandes supplémentaires pour effacer certains boutons lors d'une transition vers l'état "Stopper" ne me convainquent pas. Il me faudrait peut-être une variante de "think()" qui permette de "préparer le contrôleur" quand on arrive dans un nouvel état.

    Friday, May 22, 2009

    Moon walk ?

    As seen in former post: Scripting Sunday:

    TODO: moving Bilou through the animation isn't the right way to go. Maybe "delay x" in the animation sequence to have the next frame triggered only when we move to the next pixel would be better
    Faire marcher un personnage est loin d'être une tâche facile et en particulier, ça demande une synchronisation parfaite entre le déplacement du sprite et son animation. Le moindre décalage et le joueur aura l'impression que le personnage "glisse" sur le sol au lieu de marcher. En clair, le pied en contact avec le sol doit rester au même endroit par rapport au sol jusqu'à ce qu'il se lève. Ce genre de défaut était assez fréquent dans les jeux de mon enfance (hein, Eric ;). Une manière assez simple d'y remédier est évidemment de faire courir le personnage, de préférence "à la supermario"

    La solution que je pensais y apporter était relativement simple: intégrer les déplacements dans l'animation à coup de "move x y" entre deux images. C'est comme ça que je déplace le wooworm et ça réussit plutôt bien. Le hic, c'est de combiner ça avec une vitesse éventuellement variable et le test des collisions qui a été ramené dans le contrôleur (qui ignore tout de l'animation en cours).

    I've never been satisfied by typical game-making animation tool that just let you define a constant moving speed (e.g. one pixel per frame) and an walking animation that you try to match that. It always gave me the feeling that the hero is "sliperring" on the ground or walks with rollers. I initially planned to fix this by integrating moves to the animation itself (i.e. 'show frame A, then wait for 2 frames, move by 2 pixels horizontally and show frame B'). That's how woodworm works, but i couldn't simply extended to Bilou's walk... Not until a friend of mine suggested that i could also delay the animation _until sufficient movement has been accumulated to 'hop' two pixels away_. Here comes the specific code that does that (only when the animation is "self-moving", which would be typical from ladder climbing, walking and other "friction-based" moves.

    C'est Pierrick qui m'a donné la solution a mon problème en racontant comment du temps du CPC il faisait faire des sauts "réalistes" à son petit bilou en modifiant la durée d'affichage à chaque emplacement vu qu'il lui était impossible de placer le bilou (eh oui, c'était lui) entre deux tiles (pas de sprites en CPC basic ?). Plutôt que de chercher midi à 14 heures (du genre "modifier la vitesse d'écoulement du temps pour que Bilou coure plus vite"), j'ai juste changé l'interprétation de "move x y" en "ne passe à l'étape d'animation suivante qu'une fois que le contrôleur aura 'accumulé' le décalage suffisant. Traduit en code, ça donne :

    inline bool trymove(int dx, int dy) {
        forcechecks=false;
        if (selfmove) {
            int cflags  = cast==HERO?F_PLAYERTHRU:F_MONSTERTHRU;
            bool notyet = (dx>0 && cdata[4]<dx) || (dx<0 && cdata[4]>dx)
                       || (dy>0 && cdata[5]<dy) || (dy<0 && cdata[5]>dy);
            if (notyet) return false;
            if (cando(dx,dy, cflags)==cflags)  {
                x+=dx; cdata[4]-=dx;
                y+=dy; cdata[5]-=dy;
                return true;
            } else {
                cdata[4]=0; cdata[5]=0;
                return setstate(state->dochecks(x>>8,y>>8,world, cdata));
            }
        } else {
            x+=dx;
            y+=dy;
            return true;
        }
    }
    • selfmove est défini par état : true pour monter à l'échelle, false pour tomber, etc.
    • cdata[STEPX] et [STEPY] accumule les valeurs de cdata[XSPEED] et cdata[YSPEED] (vitesses définies par le contrôleur) en mode "selfmove" (normalement, on a directement x+=cdata[0])
    • trymove(dx,dy) est appelé lorsqu'une étape d'animation utilse la commande "MOVE"
    • condloop et check permettent de vérifier les testpoints sur des frames données (p.ex. quand le personnage a de nouveau les pieds au sol).
    Voilà. J'avais envie de démystifier ça. J'espère que ça sera utile à l'un ou l'autre.

    A pair of per-object variables (cdata[])will thus be used to accumulate some intended move until that "step" size becomes large enough for the move x y instruction found in the animation list. The trymove(dx, dy) tells whether such a move is possible right now or must wait until more motion has been accumulated.

    edit: De manière étonnante, Miyamoto avait lui fait le choix délibéré, dès Donkey Kong, de casser le lien entre animation et déplacement parce qu'il jugeait qu'une animation de marche réaliste "ne collait pas à l'action frénétique d'un jeu vidéo" (l'Histoire de Mario, p.240)

    2024 #choice reality check: It is still there, and I like how it makes many character feel like they're in contact with the ground. But let's be honest, it makes the code a bit more complicated every year. It makes it possible to have characters whose motion accelerates and decelerates over one step with a constant average speed, but offseting the graphics for a truly-constant-speed could achieve something similar, and that wouldn't even be complicated for a compound sprite. So there I am. Maybe this was not a good choice, but I haven't replaced it yet.

    Friday, March 20, 2009

    ça descentote ...

    Je me faisais un petit tour de jeux SNES rapidos pendant que ma fée écoute Cedra... En retombant sur Twinbee, je me rends compte d'un élément intéressant: le perso peut rester sur une pente même si un seul pixel s'y trouve.

    Autre élément: dans ce jeu, une pente "repousse" automatiquement le joueur vers le bas. Si vous marchez le long de la pente, arrivé au bord formé par un mur celui-ci vous "éjecte" avec une vitesse presqu'exclusivement horizontale.

    Un système de contrôle original, qu'il faudra que je compare avec le comportement de SuperMario et autres Rayman the Hedgehog Commander ...

    As i was busy converging my data to a new USB backup drive, I gave another try to some of my favourite platformers. Twinbee (rainbow island adventures) caught my attention with its slope management. First, slopes always "push" the character downwards, so you cannot "stand still" on a slope. If you walk down a slope, you'll get "thrown" horizontally when you go past the edge. Interestingly, you can stay "on the edge" of a slope, as shown on the screenshot, hanging in the air (i haven't checked whether it also happens when walking down the slope or only when being "pushed backwards when you stop walking up the hill").

    I'll investigate that deeper, comparing the physics of slope-walking in Twinbee, Fury of the Furries, Mario, Keen and Rayman, and possibly some Sonic game if i manage to locate some. My feeling is that gameplay of slopes should prevail on accuracy of physical behaviours to make the game fun. Slopes are not just a way to have your character elevating as he moves: in a platformer, they should be used to tune the difficulty of basic moves (jump or stun ennemies).

    Konami's decision to have Twinbee "pushed backwards" when halting on a slope clearly makes anything above a slope harder to reach precisely, yet the fact that you're stopped at the edge of the cliff compensate by not throwing you into hazards. Of course in Twinbee, slopes also play an important deflecting role when you're flying with your boosters, but that's a different story.


    New Super Mario Bros. : pratiquement aucune pente en bord de plate-forme dans ce jeu. Les seuls emplacements où j'ai pu le détecter, c'est soit dans le niveau des glaces ou pour des plates-formes spéciales (champignons mobiles, leviers ...), pour lesquels le bord est carrément arrondi et où Mario suit l'arrondi. La friction est parfaite : hormis sur les pentes enneigées, Mario tient en place sur les pentes.
    No real slope-edge to report in that game, except for some special objects (moving mushrooms, levers, falling rocks ...).

    Commander Keen : dès que le test-point central de commander Keen n'est plus sur le sol, Keen tombe et se fait "repousser" par le mur. A noter que, compte-tenu de la faible largeur de Keen, il y aura ajustement de deux pixels à peine. En saut, il y a moyen de voir Keen "atterir presque" sur le bord d'une pente et se faire soudain repousser. Dans le mouvement, l'ajustement en X donnera aussi l'impression que Keen "saute" vers l'avant en quittant la pente en marchant. Idem: friction parfaite.
    As soon as the "hot spot" test-point of Commander Keen leaves the slope, keen falls and is "pushed" by the wall. Given the small width of Keen, this is merely a 2-pixels extra move that you'll barely detect unless you try to land "not quite" on the edge of the slope.

    Rayman : les pentes sont toujours terminées par un bord horizontal. La seule exception que j'aie relevé à cette règle, c'est dans le pencil pentathlon où au bout d'une course effreinée, Rayman passe le long de 3 crayons inclinés. Ceci dit, les crayons en question sont terminés par des gommes-bumper, et donc on a pas vraiment la physique d'un "bord incliné" comme les plate-formes de Commander Keen. A noter que, du coups, Rayman sait s'accrocher à tous les bords, alors que les bords inclinés ne permettent pas à Keen de se suspendre dans Goodbye Galaxy. Ils ont bien tenté de lever cette interdiction dans "Alien Ate my Baby-Sitter", mais c'est la source de bugs innombrables dans ce jeu.
    Virtually all slopes are terminated by a horizontal edge. The only exception i could spot is the Pencil Pentathlon, but there are bumpers at the edge of those pencils, so it's not exactly what you'd call an edge.

    Mario World: 4 angles de pentes différents dans ce jeu. Pas de doute : on cherchait à démontrer la supériorité de la nouvelle SNES ... A noter qu'il y a deux types de "bord de pente" : celui qui donne sur un mur solide, et celui qui n'est qu'un bord de plate-forme. Dans le cas "bords de mur" (comme avec le beetlebug), je ne note que des pentes possédant un rebord horizontal.
    Four different slopes! That's what i call "technically amazing" for introducing the new (back then) Super Famicom. Two kind of slopes here: those who are merely platforms (side picture), and those who are the edge of a solid area (bottom picture). In first case, mario will fall as soon as the test point is no longer on the slope (like Keen), and in the second, there is usually a horizontal edge after the slope (like Rayman).

    Sur les pentes à moins de 45°, friction parfaite. Les pentes à 45° et plus repoussent Mario vers le bas. En clair, il sera impossible de s'y arrêter et difficile d'y contrôler sa vitesse. Une pente comme celle représentée sur l'image du haut correspond donc à une double difficulté : on tombe plus tôt (des que le test-point a quitté la surface) et on ne sait pas s'arrêter. En revanche, c'est bien un "test de boîte" qui a lieu pour les surface horizontales.
    Also note that friction differs from the slope: over 45°, the slope is slippery and you cannot stop, while slope below 45° behaves like plain horizontal ground.

    Kirby (squeak squads): c'est le jeu idéal pour ce genre d'observation car l'animation de Kirby est différente selon qu'il est à l'arrêt sur une pente ou sur une surface horizontale. De plus, comme dans Keen, la friction est parfaite quelle que soit la pente (un jeu pour gamins, quoi, mais j'adore). A noter qu'à l'inverse d'un personnage comme Keen, Kirby se prète plutôt mal à un mécanisme de "test-point" unique, puisque sa base au sol est particulièrement large.
    Interesting game to study as there are two different idle frames depending on whether Kirby stands on a slope or on a horizontal area. Here we can observe an additional "horizontal" move after the hot spot has left the slope, but while kirby cannot "fall" yet due to the wall (box-cando test).

    Phénomène intéressant, dans le cas d'un "bord pentu descendant" comme sur la photo ci-contre, on observe un comportement "horizontale - pente - horizontale - chute". Dès que le "test-point" qui sert à suivre une pente a quitté la pente, Kirby a donc le choix entre deux actions: continuer à avancer à l'horizontale ou tomber. Il ne tombera pas tant qu'une partie de sa base reposera sur le bord du mur (d'où la deuxième phase horizontale). Du point de vue du code, ça pourrait se traduire par:

    • test = cando(FALL, x+dx , y+1);
    • if (test&FALL) return switch_state(falling);
    • if ((test&SLOPE) && testpoint_on_slope(x+dx,y+1)) return align_slope(x+dx, y+1);
    • if (cando(WALK, x+dx, y)) return simply_move(x+dx,y);

    Thursday, February 05, 2009

    Xargon : may the source be with you ...

    Vous ne connaissez pas Xargon ? pensez à Jill of the Jungle avec un chromosome Y et vous ne serez pas loin... Vous ne connaissez pas Jill of the Jungle non plus ? Ah. Bin probablement que votre PC n'avait pas encore de carte SoundBlaster ou d'écran VGA en 1992. C'est vrai que ça coûtait un peu cher, à l'époque.

    Quoi qu'il en soit, si je vous en parle, ce n'est pas parce que les 3 épisodes de Xargon sont disponibles sur classicdosgames.com. Non, c'est parce que le code source de Allen Pilgrim est également disponible. C'est du code C, mode réel pour le DOS, mais suffisamment propre pour que tous les aspects "hardware" soient extrait de la logique du jeu -- et croyez moi, sur PC, c'est un exploit majeur.

    Ce n'est pas la bibliothèque d'abstraction du hardware qui m'intéresse, bien sûr. Même si c'était impressionnant à l'époque, le scrolling des jeux de plate-forme Epic ne pouvait concurrencer celui du moteur de John Carmack (commander Keen & autres), le player de fichiers CMF (adlib/midi) était bien connu, mais je n'ai jamais vu d'éditeur correspondant, et si l'on se laissait impressionner par un "yeeaaah" en ramassant un gros bonus, le mixage des effets sonores était en réalité peu convaincant (voire absent).

    I'm currently studying the game logic of Xargon from Allen Pilgrim's sources. I hope that giving a look on someone else job will help me to overcome that "analysis paralysis" in my own game engine. I know i tend to overcomplicate things ... The management of objects-to-world collision has already shown enlightening... more to come. And, by the way, if anyone of you is interested into porting Xargon to the DS (or whatever other system), you may want to give a look to information gathered on the game modding wiki at shikadi.net in addition to the source code. Personnally, it's not in my to-do list :P

    Non, ce qui m'intéresse c'est la logique du jeu. Et quelque-part, cette logique me crie le maître-mot de Mollusk: "ne vous posez pas de question: codez". C'est vrai quoi. Je me prends la tête avec mes test-points alors qu'en fait, ce n'est qu'une optimisation bancale que je traîne depuis l'age du BASIC, renforcée par l'étude d'un jeu NES. La gestion des collisions perso-monde dans Xargon est bien plus simplement basée sur les possibilités de l'ensemble des tiles recouverts et l'affectation de propriétés sur chacune de ces tiles.

    int cando (int n, int newx, int newy, int ourflags) {
     int x,y,temp;
     int flagor, result;
     int startx, endx, starty, splity, endy;
    
     startx=newx/16;
     starty=newy/16;
     endx=(newx+objs[n].xl+15)/16;
     endy=(newy+objs[n].yl+15)/16;
     splity=(objs[n].y+kindyl[objs[n].objkind]+15)/16;
    
     flagor=f_notstair;
     result=0xffff;
     for (y=starty; y<endy; y++) {
           if (y>=splity) flagor=0;
           for (x=startx; x<endx; x++) {
             temp=(info[board(x,y)].flags|flagor)&ourflags;
             result&=temp;
           };
     };return (result);
    };


    Comme disait Colomb en quittant le Portugal "Il suffisait d'y penser": le tout est de concevoir les propriétés des tiles de manières à ce qu'elles "s'additionnent" bien. Un personnage ne peut se déplacer vers un nouvel endroit que si tous les tiles possèdent les bonnes propriétés ("pas un bloc", ce que Allen appelle f_passthru. Celà demande parfois un peu de jonglage mental. f_water est évident, f_climbable aussi. f_not_stairs un peu moins...


    int trymove (int n, int newx, int newy) {
     int ourflags;
     ourflags=f_playerthru;
    
     if (newy>objs[n].y) ourflags|=f_notstair;
     if (cando (n,newx,newy,ourflags)==ourflags) {
        moveobj (n,newx,newy);
        return (1); // successfully made it to new location.
     } 
     else if (cando (n,objs[n].x,newy,ourflags)==ourflags) {
        moveobj (n,objs[n].x,newy);
        return (2); // could only move vertically
     }
     else if (cando (n,newx,objs[n].y,ourflags)==ourflags) {
        moveobj (n,newx,objs[n].y);
        return (4); // could only move horizontally
     };
     return (0);    // couldn't move at all.
    };


    J'aime bien aussi la manière dont il a réussi à capturer les comportements de déplacement simples Il faudra que je tente d'en faire autant. Bion. Je vous en dirai sans doute plus. Malgré tout, la routine de gestion du personnage principal fait quand-même 7 pages, et je n'ai pas encore tout lu.

    Friday, May 16, 2008

    Faut que je repense les test-points

    Bon, Bilou saute, il tombe, il rebondit ... tout ça c'est bien joli, mais il a tendance à se retrouver un peu trop souvent dans les murs à mon goût. Et en plus, son comportement devient un peu trop complexe à exprimer dans mon modèle de machines d'état. Pensez un peu. Rien que pour le saut, il me faudrait pas moins de 10 états si je veux que Bilou se "souvienne" de la dernière direction dans laquelle il est allé :P

    Great. Bilou jumps, Bilou falls and bounce. It's all nice and funny, but he ends up into walls a bit too often to my tastes. Moreover, it's getting too complicated to express his behaviour only through that state machine approach: only jumping takes up to 10 states if we want to remember the last direction Bilou has been leading to ^^"

    One of the reason why it's getting so complicated is that when jumping forward, there are additional testpoints to be checked, while these testpoints are disabled when jumping simply "upwards". The solution would be relatively straightforward: i need a new class of testpoints that would be conditionnal on horizontal speed.
    Une des raisons de toutes ces complications, c'est que lorsqu'il saute vers l'avant, Bilou doit vérifier deux testpoints de plus (pour éviter de rentrer dans un mur) mais que ces testpoints ne sont pas souhaités lorsque le saut est simplement vertical (sinon, on ne peut pas sauter le long d'un mur ^^"). La solution est relativement simple, heureusement, il suffit de créer une nouvelle "classe" de points-test qui ne serait active que lors d'un déplacement horizontal. Cyril avait bien proposé le passage à un moteur physique plus complet (avec gestion de la friction, de l'élasticité des chocs et tout -- vous savez comment est Cyril ;) mais je préfère garder ça au niveau du script pour l'instant.

    Autre petite modif' en cours: varier les types de blocs possibles. C'est joli, un éditeur de niveau qui vous propose toutes sortes de pentes, de blocs réactifs et ce genre de choses, mais si le moteur de jeu voit juste "ciel" et "roc", on est pas avancé. Enfin, ça, ça peut prendre encore un moment.

    Wednesday, April 30, 2008

    Obey Gravity

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

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

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

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

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

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

    Tuesday, January 01, 2008

    "Je vous présente les bordures!"

    Je viens de retomber sur une lettre -- datée du 8 janvier 1900 -- que je n'ai jamais envoyée à son destinataire, Gédéon (qui signe de temps en temps un commentaire du nom de 'Ged' sur ce blog). Il faut dire qu'après la Inscene '99 et la collaboration de CJ à son jeu "insane bugs" (une sorte de remake de micromachines), on avait entamé une correspondance sur des sujets traitant de la réalisation de jeux vidéos, que j'illustrais assez abondamment de mes Bilous, évidemment.

    edit 2021: finally translated.

    A cette époque, en pleines études, je codais surtout pour les TP de l'université, mais je n'avais pas énormément le temps de mettre en oeuvre tout ce à quoi je réfléchissais pour mon "Ultimate Game Maker"

    Voilà ce que celà disait:

    Hello, Gédéon.

    Je crois bien que j'ai trouvé un truc cool pour modéliser les niveaux dans Bilou! un truc plus smart que ces "tests de couleurs" puants que j'ai utilisé dans la version BASIC du jeu!... Je te présente les bordures.
    L'idée est la suivante: tes sprites possèdent un certain nombre de "testpoints" et les déplacements ne sont possibles que pour certaines valeurs de ces test-points (pas question de faire marcher Bilou dans le vide, hein!)

    D'autre part, tu plaques un peu partout dans ton niveau des bordures. Ces bordures sont des éléments logiques qui ne correspondent à aucun affichage. Elles sont liées logiquement de telle manière que l'on peut facilement savoir quelle bordure est située à gauche, droite, au-dessus ou en-dessous d'une bordure donnée. Les bordures sont également séparées en 4 classes: plancher, plafond, mur-gauche et mur droit.

    Ca va, je ne vais pas trop vite ?

    Bon. Voyons comment ça marche. Lorsqu'un sprite crèe ses test-points, il leur fournit à chacun une classe correspondant à la classe de bordure avec laquelle ils réagissent. Du coup, on s'empresse de lier chaque test-point à la bordure de même classe la plus proche (euh, ça ne devrait pas être trop sorcier).

    Voilà un aperçu de la chose en cours ... tu peux facilement savoir si tu es "dans le mur" ou pas: il suffit de regarder de quel côté de la ligne le point se trouve. Dès que ton point sort du "champs d'action" de sa bordure, on cherche quelle est la nouvelle bordure et on y relie le testpoint (après quoi on effectue le test habituel).

    C'est-y-pas merveilleux, tout ça ?

    Allez, une dernière idée qui m'est venue comme ça, en écrivant cette lettre (pour être sûr que tu n'arrives pas à dormir cette nuit ;-)
    Au lieu des testpoints, tu pourrais faire des "bordures" pour les sprites aussi (en fait, à partir de la bounding box), mais tu risquerais d'avoir plus de calculs à faire ...)

    Enfin, ça m'éviterais d'avoir des bugs à la "Crazy BriX".
    Allez,

    Bion, depuis, l'eau a coulé sous les ponts. Le coup des "bordures" était bien alléchant, il permettait de passer à la 3D avec moins de prise de tête que si on doit procéder pixel par pixel (c'était le cas dans Bilou en Basic, comme je le mentionnais dans la lettre), mais par contre je n'ai jamais trouvé le véritable "truc pas trop sorcier" pour déterminer quel est la prochaine bordure du même type, en particulier lorsqu'il y a plusieurs plate-formes les unes au-dessus des autres (classique dans un jeu de plate-forme, évidemment).

    Pour la version "DS", je me rabats principalement sur des tests "tile par tile" (et prout pour la 3D), et les "bordures" serviront principalement pour des plate-formes mobiles, nuages, et autres joyeusetés ... Une sorte de manière de passer outre les limitations typiques des jeux "game maker".

    Voilà. Bonne année à tous.

    Monday, March 05, 2007

    Vous courriez ? J'en suis fort aise! Eh bien, Sautez, maintenant...

    Je discutais DS et bilous avec Dider, mon beau-frère informaticien, et je me rends compte que des techniques que j'ai apprises "sur le tas" avec mon Bilou's Adventure en QuickBasic peuvent parfois être pas si évidentes que ça pour des personnes qui ne baignent pas dedans depuis 15 ans ^_^

    Outre les aspects techniques qui font que les images du jeu s'affichent convenablement, une question-clé était "mais comment programmes-tu les murs, les sauts, etc." Rappelons-nous tout d'abord que sur une console de jeu, l'écran (en tout cas pour les modes 2D) ressemble plus au carrelage d'une salle de bain qu'à n'importe quoi d'autre. Vous avez de jolis pavés (parfois appelés "tiles" ou "blocs" selon les cas) sur lesquels vous avez amoureusement dessiné des bouts de livre, d'encrier, de crayon, etc. Chacun porte un numéro et il suffit d'inscrire son numéro dans une grande grille pour construire l'image voulue.



    Bion. Maintenant qu'on sait ça, on voudrait pouvoir détecter s'il y a ou non un sol en-dessous de Bilou, histoire de s'avoir s'il doit tomber ou rester sur place. Rien de plus simple: on va calculer les coordonnées d'un "point-test" situé juste en-dessous de Bilou et regarder le numéro du pavé au-dessus duquel il se trouve. S'il s'agit d'un crayon, d'une latte, etc. on ne bouge plus! Sur PC, j'avais traduit ça en une division des couleurs du jeu en deux sous-ensembles: les couleurs "solides" (pour dessiner les livres, etc) et les couleurs "de fond" (pour dessiner le fond. warf.), mais sur une console comme la DS, on a généralement plusieurs plans de décor, et pour commencer, on peut tout à fait décider que tout ce qui n'est pas "solide" set sur un autre plan: lors du calcul du "point-test", on verra soit le pavé #0 (du vide), soit un autre pavé, qui indique qu'on a affaire à du sol.





    Bien sûr, ce que je fais avec Bilou et ses points-test peut être généralisé à tout le reste du jeu: les éponges, les crayons, les gommes, les gouttes d'encre et tout le tintouin. Il suffira de programmer les routines de déplacement de chaque élément du jeu pour qu'il fasse ses propres tests et réagisse en conséquence (passage de l'état 'sur le sol' à l'état "dans le vide", par exemple). Avec ça, vous ne devriez pas avoir trop de mal à vous construire un petit perso qui tombe quand il n'y a pas de sol et qui avance quand il est au sol.
    Maintenant, quid des sauts et compagnie ? Bon, si vous avez déjà suivi un petit cours de physique, vous savez qu'un objet qui bouge a un vecteur-vitesse. En clair, si Bilou avance vers la droite, son vecteur-vitesse vaut p.ex. (5,0), c'est à dire qu'à chaque "tranche de jeu" (ou 'tic'), il sera 5 pixels plus loin sur la droite mais qu'il ne monte pas et qu'il ne descend pas. A l'inverse avec un vecteur-vitesse (0,5) Bilou descend comme s'il était sur un ascenseur. Pour donner l'impression qu'il tombe, il suffit d'augmenter la vitesse verticale à chaque tic. Mieux, même, si je démarre avec (0,-5) et que je garde la politique "augmente la vitesse verticale à chaque tic tant qu'il n'y a pas du sol en-dessous de Bilou", il va faire un gentil saut sur place.

    Avec un petit calcul niveau secondaire-sup, vous pouvez même calculer la vitesse initiale à donner à Bilou lorsque le joueur appuie sur le bouton de saut pour qu'il puisse (par exemple) faire un saut suffisant pour grimper par-dessus un obstacle de 64 pixels de haut. Facile: il faudra au moins une vitesse initiale de 11. Et c'est là que le bas blesse: on vient de dire que 8 était un maximum :-/ Résultat,

    • on pourrait diminuer la gravité (se dire que tomber d'un pixel tous les 1/60 secondes, c'est un peu beaucoup: vous avez traversé 1/3 de la hauteur de l'écran en seulement une seconde)
    • on pourrait ajuster nos routines de tests pour qu'une vitesse de plus de 8 pixels sur 1/60 secondes ne pose pas de problème technique
    • on pourrait revoir le modèle du saut et "tricher" un peu avec les lois de la physique...


    En pratique, si vous regardez sauter Mario, vous vous rendrez compte qu'on a pas vraiment respecté les bonnes vieilles lois de Newton dans les sauts, et pour cause: le joueur doit pouvoir doser son saut, et la manière la plus naturelle de le faire, c'est de relâcher plus ou moins tard le bouton de saut. Dans la réalité, bien sur, ça ne correspond à rien: une fois que vous êtes lancés, vous ne pouvez plus décider que "oups, non, finalement, il faudrait que je saute un peu moins loin si je ne veux pas me tordre la cheville en retombant".

    On pourrait faire comme dans ninji & zarbi et demander au joueur de laisser le bouton enfoncé d'autant plus longtemps qu'il veut sauter loin (mimant alors une "accumulation d'énergie" avant le saut) et ne faire le saut que lorsque le joueur relâche le bouton, mais je vous laisse imaginer sauter de passerelle en passerelle sur ce principe.
    Non, ce que l'on va faire, c'est considérer que l'énergie dont notre Bilou dispose pour le saut n'est pas consommée complètement en un instant pour lui donner la vitesse (0,-11), mais plutôt que pendant une première phase du saut, Bilou conserve une vitesse verticale plus basse, mais n'est plus soumis à la pesanteur (en gros, il monte à vitesse constante) aussi longtemps que le joueur garde le doigt sur le bouton de saut. Avec un bon dosage de la durée max de cette "phase ascenseur", on pourra atteindre la hauteur souhaitée sans dépasser la vitesse qu'on s'est fixée.

    Reste le coup du saut pendant la course. Le premier jeu bilou était assez déroutant dans ce sens. J'avais voulu obtenir un effet "à la Sonic" ou le personnage saute d'autant plus haut et loin qu'il avait pu prendre de la vitesse. L'ennui, c'est que je passais simplement de (v,0) à (v,-v) au moment du saut. Si vous faites le calcul, ça veut dire que au moment où le jouer appuie sur le bouton, c'est comme si l'énergie de Bilou était subitement doublée ... d'où un saut qui n'a rien à voir avec la vitesse de Bilou à ce moment-là. Idéalement, j'aurais plutôt du prendre quelque-chose comme (sqrt(v),sqrt(v)) pour conserver sa quantité d'énergie ...

    On testera tout ça...
    Sorry non-frenchy folks, this one is a big too large for inline translation. i might come with a dedicated post with translation when i'll have a bit more free time... and implemented the stuff ^_^ Meanwhile, i suggest that you read Gregg Iz-Tavares and Dan Chang's article on M.C. Kids for the NES, which basically covers the same kind of topic.