Wednesday, December 31, 2014

Ciao 2K14.

Pour ce qui est du blog, 2014 fut certainement une année un peu maigre. Inévitable, j'imagine, suite à mon changement de boulot, et surtout la contraction du temps de midi. C'est un boulot qui me plaît, avec des registres, des modules kernel et des transferts DMA, ce qui veut dire aussi que je suis moins en manque de code à la fin de la journée de travail.

I hope you haven't been deceived by the lowered posting rate in this year. I changed to a job with more registers, more kernel drivers and DMA transfers. The environment gives less room for lunchtime-hobby-coding, but I enjoy it a lot. Hopefully, the list of things to adapt to have daily tasks flowing in this new chapter of life reaches completion.

Du point de vue de l'aventure de Bilou, toute l'année aura tourné autour de la transformation -- sur la proposition de Pierrick -- d'un niveau d'essai en jeu d'arcade du type "cours vite!" avec l'encre qui monte. J'ai eu le feedback de Kirby Kid qui a attiré mon attention sur l'importance d'un règlage plus fin des paramètres pour ajuster les monstres et les niveaux.
J'atteins aussi des interactions nettement plus sophistiquées (enfin ;) notamment avec les dumbladors empilables sur lesquels on peut grimper. 

Bilou's anniversary level has been converted into an "arcade" game currently featuring 3 levels, with a target, a challenge and a "game over". I got precious feedback from gameplay expert Richard "Kirby Kid" Terrel. I'm doing my best to proceed with tuning issues he pointed out. I'd like to have a 4th level before I come with a neoflash release (if neoflash ever resume doing coding competitions). Rushing pendats, stacking bladors, stunned inkjets, raising ink swamp, floating spongebops ... Nothing like "deep ink pit" has appeared, but things are definitely shaping towards something that better fits the levels I designed for the School Zone.

Il n'y aura pas eu beaucoup de progrès du côté des éditeurs -- la panne de mon cybook au début de l'été n'y est certainement pas étrangère. LEDS s'en tire un peu mieux avec un mode de prévisualisation sympa pour les blocs spéciaux mais qui, en pratique, est peu utilisé (les descripteurs de blocs ne sont pas présent dans tous les niveaux :P). Le système de "copier/coller" d'écrans entier s'est avéré bien utile pour les nouveaux niveaux de SchoolRush. Par contre, le mécanisme prévu pour éliminer les objets hors-cadre lors d'un redimensionnement de niveau n'est arrivé nulle part.

This time, there hasn't been much evolution to my edition tools, I'm afraid. They barely adapted to the new needs identified for the game conversion. I reached a data size where WiFi transfer are impractical and I use the emulator much more than earlier in the project. RunME isn't really following up all those game engine/character behaviour evolution. I'm truly focusing on producing the next game, although it's not going fast.

Oh, granted, I may have played more others' game, too. With two Zelda games to discover, a good deal of Fez and some backlog of Nintendo 3DS games. Washing up sessions tend to be longer since I discovered AfterBit and Speed Game vlogs... And I hope another 3DS game will be tested soon, although it's an old friend.



Avec un nouveau Zelda, la découverte de WindWaker, les documents d'origine de Rick Dangerous et les sources de Commander Keen, j'ai été gâté. J'espère pouvoir faire bientôt le point sur le cadeau inattendu reçu à Noël.

Sunday, December 28, 2014

Keen ClipToSprite()

This is the code snippet for the ClipToSprite() action that results in pushing monster/keen interaction when the monster stands on the left. The code adapts characters expected motion (which differs from its computed speed and is transient) so that intersections between characters hitboxes remains empty.

The condition highlighted with yellow puzzled me at first. In fact, we'll note that leftinto == xmove (the difference between characters speeds) when they were exactly side by side at the previous tick. Would there be 1 pixel distance between them at the previous tick, we'd end up with leftinto == xmove -1. So what it really implies is that we won't get pushed at high speed if we fall down just on the left of a carrot running to the right with a large leftinto value (e.g. if we fall on carrot's head and move down through it).

Une seule fonction -- ClipToSprite -- permet à Keen de s'aligner sur d'autres objets en définissant un nouveau mouvement qui s'exécute en plus du mouvement prévu par la fonction think(). Le principe de base est de calculer de combien de pixels les deux personnage s'interpénètre et de repousser celui qui n'est pas solide par un déplacement opposé.

Il est important pour comprendre ce code de se souvenir que le moteur de jeu travaille en plusieurs passes et que tous les personnages ont déjà leur nouvelles coordonnées quand les tests de collision ont lieu. Les valeurs originales de xmove et ymove ont donc déjà été appliquées. Par la "condition jaune" (leftinto <= delta_xmove), on s'assure que Keen ne sera repoussé par le bord d'un objet que s'il n'avait pas déjà dépassé ce bord à l'étape précédente (mais sans que la collision n'ait lieu parce qu'il était au-dessus du chariot, par exemple).

The ID keen engine is multi-pass. That means when ClipToSprite() is invoked as result of keen/courier contact, setting keen.ymove=0 doesn't prevent keen from falling, because he already moved down in the previous step. Instead, it prevents him from moving down again as result of the carrot collision. This design avoids issues with moving platforms without requiring a re-ordering of the objects evaluation.
This is also made possible because objects have a separate react() function to align against level structures.


Pour les plate-formes, des tests verticaux font suite aux tests horizontaux également présents dans les "monstres pousseurs" comme la carotte véloce. S'il est surprenant que le déplacement horizontal de Keen soit exactement celui de sa plate-forme (et pas Keen.xspeed + Cart.xmove comme le voudrait la physique), c'est qu'un premier mouvement a déjà eu lieu. Il ne reste plus qu'à appliquer le mouvement de la plate-forme à Keen, le repousser vers le haut et surtout s'assurer qu'au moment de l'appel à KeenAirReact, la logique du jeu pense qu'il y avait un bloc solide sous Keen. C'est le rôle de la variable hitnorth qui conserve le type de tile qui a interrompu le personnage lors de la phase de déplacement.

Characters that push you but you can't ride ends after those horizontal tests. For carts, platforms and Keen4e's bouncing red ball, you'll also process the "bottominto" test. Note that since we already moved Keen according to the direction keys, setting keen.xmove=cart.xmove and invoking ClipToWalls() again -- which includes applying (xmove,ymove) to (x,y) coordinates of Keen -- combines cart's move with Keen's own move as expected. Hacking the hitnorth member will make KeenAirReact() function believe that some solid ground was found during move/clip step.

Tuesday, December 23, 2014

Kirby 3D

Du sympa et *beaucoup* de récup dans ce nouvel opus de la chiquelette rose la plus populaire du monde Nintendo... Variante simple mais efficace des power-up centimes de vie à récolter: la couleur indique la valeur (comme les rubis d'Hyrule) et de mignonnes petites fleurs dévoileront un bonus quand on passe devant.... Allez, bonne nuit :)

I completed tonight the Kirby 3DS game I borrowed to my brother a couple of month ago. Quite cute, as one could expect. The depth exploring system doesn't add much to typical 2D gameplay (not more than offering 2 screens, at least) but it doesn't ruin the experience either. They put effort in the boosted vacuum mechanic, that's quite obvious. Using the colour of 'coins' to indicate they have higher value worked better than glueing 10 coins together. Taking note ...

Par contre, avec ses interactions avant-plan/arrière plan, son gameplay 2D dans un environnement 3D et sa structure très géométrique (contrairement à Donkey Kong Returns, beaucoup plus organique), Kirby Triple Deluxe est certainement le jeu qui vous donne la meilleure approximation de ce que j'avais en tête quand j'ai commencé à étudier le phong shading pour faire un Bilou à base de 3D, en 1998. Et les pieds de Kirby qui ne se plient pas quand il bouge vous donne aussi une bonne idée de pourquoi je n'ai pas continué dans cette voie-là après les premiers essais de rendu dans un modeleur.

Monday, December 22, 2014

Keen's Inception

Coincé entre deux générations de "game engine" de la série commander keen, on trouve un jeu étrange, faisant presque figure de "lost levels": Keen Dreams. Une grande part du design global de l'excellente série "Goodbye Galaxy" est présent: décor en perspective cavalière, personnage de 40 pixels de haut, environnements variés et son SoundBlaster. En revanche, keen se promène en pijama et en pantoufle et ne dispose ni de son neurolaser, ni de son célèbre pogo. A la place, Keen peut lancer en cloche des mines transformant les ennemis en fleurs à leur contact. Le gameplay demande donc beaucoup plus de précision que dans les autres épisodes, d'autant plus que les ennemis ne resteront pas transformés éternellement. Ça n'est pas sans rappeler le lancer de taille-crayon dans Bilou, je l'avoue, mais si je vous en parle, c'est surtout à cause de ses sources, ajoutées sur github début septembre, et que je suis occupé à analyser. Les sources sont essentiellement en C avec quelques blocs d'assembleur en ligne, chose plutôt rare pour l'époque.

Bien sûr, j'aurais préféré que Javier et Chuck nous proposent le code de Goodbye Galaxy, notamment à cause de l'absence de pogo dans cet opus, mais c'est le premier Keen à proposer des pentes, ce qui n'est déjà pas si mal.

Keen Dreams' source code has been released last September. I wish it was the code for one of the Goodbye Galaxy episodes, of course, as it is one of the games I played the most, and the one with the richest features set -- pogo, gun, moving platforms and shooting ennemies -- which isn't crippled with clipping bugs. Anyway, Keen Dreams has slopes and shooting/pushing ennemies. The map design with its "info layer" suggests that most of the engine has been kept between Keen Dreams and Goodbye Galaxy. The character's moves (jump, run and pole-climbing) are direct translation of GG spritesheet. The pogo is missing, and I will have to define how the lone "canteloupe cart" can be ridden. 

Rather than stunning gun, Keen throws "flower power" seeds that are affected by gravity somehow like my dumbladors. Gameplay-wise, I cursed that decision quite often. Aiming for those fast-moving, aggressive vegetables with something that follows an arced curve, bounce on the ground and only stuns for a limited amount of time made imho this episode almost the hardest of the series. So far, I haven't found arced curve of bladors that hard to use, but on the other hand, monsters in Bilou's Schoolzone don't kill you instantly on contact.

N² with high N could turn Nightmare.
En plus de leur calques "graphiques", les niveaux possède une couche "info" qui indique quels monstres créer au chargement du niveau (scaninfoplane et HandleInfo). Les monstres de l'ensemble du niveau sont conservés dans une liste liée, mais seuls sont "actifs" ceux qui sont assez proche dans l'écran. Leurs collisions sont gérées par un parcours imbriqué de la liste (N²) -- rien d'équivalent à mon système de "castes", donc --  mais vu le nombre réduit de monstres par écran dans le level design, celà ne pose pas de réelle difficulté, sauf peut-être dans le niveau des vignes.

Compared to my own engine, code for managing collisions looks quite simple. There is no Hero/Ennemy casts, nor collision masks. The engine checks every pair of "objects" for intersection of axis-aligned bounding-boxes. That could easily turn into programmatic nightmare in a game with heavy number of monsters like Apple Assault (up to 10,000 checks per frame), but here, the test is skipped as soon as one of the monsters is off-screen (active is false), and there quite little places where the screen shows more than a handful of ennemies at once. 

Funny enough, although everything may have its own contact() function and both are invoked when two objects come in contact, there is no passive/active role... yet, monsters typically don't use their contact() function at all, and whether Keen should die or be granted more points is all encoded in Keen's own contact() function, and contact() function for the flower-power seeds has knowledge of which monster can be stunned and which object shouldn't be affected.

Casts make it linear and scalable
On a une fonction "contact()" pour chaque monstre qui régit les changements en cas de collision. Pas non plus de notion de "actif/passif" mais une organisation où "PowerContact" (pour l'arme de Keen) transforme tous les objets en fleurs et KeenContact() mêne à la mort de Keen presque systématiquement. Ces fonctions contact ont la possibilité de faire n'importe quels tests (on est dans du code C), y compris aller tester l'étape d'animation de l'objet avec lequel on est entré en contact ... ce qui permet de concentrer toute la logique de collision dans quelques objets. Pour les monstres, il n'y aura en fait aucun code pour les contacts.

Ça vaut aussi la peine de regarder de plus près le système des "ticks" qui règle le comportement des personnages. Ce type de code est le plus souvent absent sur console. La vitesse du CPU est connue et la mise à jour de l'image à l'écran assez rapide vu la structure choisie pour le processeur graphique. Mais on est ici sur (vieux) PC, avec une vitesse quelque part entre 6 et 40MHz pour le processeur principal et un système de rafraîchissement de l'écran passablement complexe. Le jeu ne tournera certainement pas à 60 images par secondes, ni même à 30 ou à 12. On aura plus que probablement un temps de rendu (entre l'instant où la logique du jeu a fini sa mise à jour et le moment où la nouvelle image est effectivement visible à l'écran) variable.

The game logic is built around the notion of time ticks, which are a virtual equivalent to video frames on a game console like the Nintendo DS. However, unlike a console, the PC (ranging from 6 to 40MHz by that time) cannot guarantee we'll have a new frame rendered every 1/60th of second -- maybe not even every 1/12th of second. It's much more likely that the framerate will be irregular, depending on bus availability for memory transfers and complexity of the current scene. ID software developers thus measure how much time elapsed since the last rendered image and deduce how much game logic _ticks_ corresponds to this time. The StateMachine() function then compensates by stepping the characters by (xspeed,yspeed) the appropriate number of time, invoking the think() function when needed. Rather than experiencing slow downs, we'd experience a drop in the frame rate, but no kid on earth would complain about that from a shareware

The code logic deciding whether think() should be called or not is quite complex, allowing some part of monster behaviour code to indicate "do not think for N ticks, and slide me at constant speed" or "only invoke think() when time is ready for the next animation frame", etc. The benefit is that most of the code that accommodates for "process N ticks at once" is in that generic logic, and the monster-specific code remains as simple as updating speeds, not moving coordinates. Another function will then react() to the new position of the character on the level (does it still has ground under its feet ?)

L'idée (toujours présente dans les Quake modernes, pour ce que j'en sais) consiste à mesurer le temps qui s'est écoulé depuis la dernière demande d'affichage et à exécuter k "pas" (les ticks) de la logique de jeu, où k * durée_d'un_pas = temps_écoulé. Ainsi, la fluidité varie mais le timing du jeu reste constant et on ne perçoit pas de réel "ralentissement". Ce qui témoigne de la qualité du design, c'est le fait que le code du comportement des personnages peut être écrit sans devoir se soucier de ce mécanisme: les fonctions DoActor et StateMachine prennent intégralement ce comportement en compte et sont capables de gérer une transition d'état au milieu du laps de temps à simuler sans pour autant faire N appels aux fonctions think() des personnages. Autre élément qui se retrouve aussi dans les FPS d'ID software: la fonction "think" n'est pas forcément appelée à chaque moment. Selon les besoin, elle peut être invoquée sur les étapes d'animations, à intervalle régulier ou aléatoire.

Dernier traît intéressant dans les grandes lignes de l'organisation du code: la fonction think() d'un personnage ne se préoccupe généralement pas des collisions avec les murs. Elle se contente de lire l'état du jeu et de décider de la direction/vitesse/animation à suivre. Une deuxième fonction, react(), associée elle aussi aux états du personnage, sera appelée après que le déplacement ait eu lieu et s'occupe d'aligner un personnage qui aurait rencontré un mur. J'y reviendrai dans le volet prochain.

Saturday, December 13, 2014

Amélioration Spongebop ...

Je me suis amusé l'autre jour à imaginer comment les SpongeBops pourraient être plus interactives dans le jeu. Les faire flotter sur l'encre, bien sûr, mais aussi les transporter comme les dumbladors. Et pourquoi pas s'en servir également comme d'un "parapluie" contre les jets d'encre ?

So far, we can grab spongebops while they're swinging, and use them to reach higher places ... but that requires significant learning of the game mechanics. Dumbladors can be used to detach them but so far, it doesn't bring much difference. I wanted to add "carrying" and floating, which is now ongoing. I'd also love to make carried sponge a protection against falling ink droplets...

  • [done] pick up and throw spongebop
  • [done] spongebop floats on ink
  • [done] ink droplets stops on spongebop
  • [done] pendat turns back when walking into a spongebop.
  • [todo] floating makes spongebop move up and down
  • [done] stands on floating spongebop. Don't bounce.
  • [done] better physics when thrown
  • [done] Bilou stays hung when Spongebop is jammed.
  • [done] blador-like virtual walls to avoid Bilou holding the spongebop from far away.

Tuesday, December 09, 2014

Leçon de tuning: la théorie


 
Tune it well ...
Animating a running pendat within restricted pixel space turned out better than I initially expected. Now, I have to tune that additional move to ensure it improves the gameplay. The speed at which it moves, the distance from which Bilou is detected and the acceleration were all arbitrarily picked while writing the script. They work rather well, but they can surely be tuned for maximal results.

Bien. J'ai rajouté une animation pour que le crayon-soldat puisse charger Bilou quand il l'aperçoit. Reste du coup les questions de tuning à régler:
  • à quelle vitesse doit-il courir ?
  • à quelle distance peut-il "sentir" Bilou ?
  • combien de temps doit-il mettre pour atteindre sa vitesse maximale ?
L'enjeu de ces règlages ? faire en sorte que les réflexes puissent continuer à tirer le joueur d'affaire et éviter de se retrouver dans une situation à la Rick Dangerous où le joueur doit mémoriser tout le parcours pour pouvoir jouer.
Bilou and Pendat positions over time
The issue with arbitrary values is that they can twist the gameplay towards a state where players can no longer react to what happens and have to memorize the level just to complete them. I have been convinced by Kirby Kid's blog that this is not the way platformers should be built and that they should instead allow to be "played while reading" once we mastered core skills (estimate trajectories, press buttons, read timings) and learnt game's physics. As our player has reaction time to the walk/rush transition of the pendat (a) and that Bilou needs some time e.g. to reach a height where collision no longer occurs (b) -- and possibly only keeps that height for some time (c), values exists where player cannot possibly escape. These must be avoided.

Je me suis donc donné deux cas d'étude: "Bilou tombe devant le pendat et doit s'échapper en courant" et "Bilou doit passer par-dessus le crayon en sautant". A partir de là, on peut représenter la distance Bilou-crayon au cours du temps et voir s'il y a ou non risque d'avoir une collision.

T_player_reacts + T_Bilou_reaches_speed < T_pendat_clears_distance
T_player + T_Bilou < Pendat_Detection_Distance / Pendat_max_speed

A sa vitesse actuelle, le pendat met 81 frames (1" 36 centièmes) pour aller de sa position actuelle à celle de Bilou. Bilou, lui, met 30 frames (1/2 seconde) à atteindre sa hauteur maximale (b) et on peut compter qu'il y reste 20 frames (c), pendant lesquelles le Pendat aura avancé de 30 pixels ... Assez pour se croiser sans accroc. J'ai vu la plus jeune testeuse de la S-team réussir ce saut d'instinct. Celà signifie qu'elle a un temps de réaction d'au plus 600ms ... Hmm ... Oui, le pendat actuel est loin de demander des efforts de réactivité puisqu'on estime à 200ms un bon temps de réaction à un stimulus, pouvant descendre près des 100ms pour un sportif entrainé. Et puisque Bilou est quasiment au centre de l'écran, celà signifie que si on voit le pendat quand il fait demi-tour, il nous attaque sitôt qu'il se retourne. Rétrécir la distance de détection et la compenser par un "sursaut" du crayon pourrait améliorer la situation

While my testing-nephews were giving it a try, I went through to "escape case" -- run away or jump over -- to map where would time go. Not even the youngest player had issues with the original timings, which left a generous 600ms to the player to dodge the rush. That's about 3 times the delay usually presented for fast reaction. It "turned" out that direct rush of the pendat is not the most dangerous -- so I can easily shorten the detection distance and have pendat entering the screen walking and only start chasing Bilou when at a distance close to 1/3 of the screen width. What is truly dangerous is that bounce when he enters a wall, and then quickly turns back. It means if you're waiting for him at the top of that wall, your window to sneak behind is small. In fact, the thing that may prove more stressful is to shoot him down with a blador. But that should simply tease you to get the straight-throw power-up ;)

En fait, le rebond contre le mur est beaucoup plus piégeux. J'imagine que c'est dû à la cassure du mouvement, plus difficile à estimer. Et l'atteindre avec un taille-crayon affecté par la gravité sera plus délicat, mais pas trop quand-même puisque le crayon a le bon goût de rester dans la zone active du taille-crayon pendant sa courbe. Ouf.

Avec tout ça, le "croco-désagrafeur" retombe dans l'oubli ...

Sunday, December 07, 2014

Super State Bros.

Une tentative de mesurer la complexité du comportement de Mario dans Super Mario World, avec l'idée de le comparer à celui de Rayman, histoire de mieux comprendre comment ce genre de chose peut monter à 15K de code source. Par comparaison, le code de Bilou prend 900 lignes de script et pas loin de 20K ... La partie des "micro-contrôleurs" qui définissent les actions élémentaires combinées dans la machine d'états prend pas loin de 1300 lignes de code, soit presque 40K caractères. C'est mesuré à la grosse louche vu qu'il y a aussi parmi ces contrôleur du code qui ne concerne que SpongeBop (pour l'instant), etc. et surtout une bonne dose d'annotations pour InspectorWidget.

How complex is a platformer character behaviour ... let's say Super Mario in Super Mario World ? Does that help me understand whether 15KB of code for Rayman Origins is compact, regular or stunning -- as it looked to Pasta Games developers who converted it into Jungle Rush game ? To figure out, I tried to depict a state-machine-like representation of all the states Super Mario can take, where a different state implies different reaction to player input.

'What is a "state" ?' might you ask, and why don't we see small-vs-big or fire Mario here ? A state is not a costume it is an identifiable part of the behaviour that is distinct from a gameplay perspective. "Jump" and "Run" are different states because Mario behaves differently (gravity, friction) and because some actions are only possible while jumping while others aren't.

In figures, that sums 21 different states for Mario, 6 of them working only with specific level elements and 6 others requiring a power-up. To my surprise, Rayman Origins accounts for a quite similar number of states, mostly because punching and kick'ing suspend some actions and can be cancelled like in a fighting game, therefore asking for a dedicated state while Super Mario's fireball can be spawned without cancelling any other move. The original Rayman on PSX had much simpler behaviour, with only 11 distinct states.


En chiffres: 9 états de base pour Mario ("soulignés"), 6 états supplémentaires pour interagir avec des éléments précis des niveaux (entre parenthèses) et 6 autres états qui ne sont disponibles qu'à travers un power-up. Graphiquement, la "sprite sheet" de Super Mario World est plus vaste, mais je n'ai pas répliqué ici "saute, saute avec un champignon, saute avec une fleur de feu, saute avec une plume, saute avec yoshi" parce que tous sont identiques au niveau du code de comportement: ils réagissent de façon identique au commandes du joueur.

En comparaison, je n'ai compté que 11 états dans le comportement du premier Rayman sous DOS/PSX, dont 5 doivent être débloqués au cours de la progression du joueur. Bien moins complexe qu'un SMW, donc. Mais les baffes (qui affectent la vitesse de Rayman), les attaques-rodéo et autres glissades, les rebonds et la nage de Rayman Origins.

Le personnage de Xargon en est à 10K symboles (389 lignes de code)... Ah, oui ... il faudra que je regarde d'un peu plus près le code de Keen Dreams.

Sunday, November 30, 2014

Le Tuning

La première remarque de Kirby Kid concernant le jeu "School Rush" m'avait un peu décontenancé. Je ne voyais pas bien ce qu'il entendait par "des problèmes de tuning" (non, quand-même pas au point d'aller acheter des néons bleus, mais pas loin).
A rediscuter par la suite, je me dis que les fleurs-piranha de Super Mario Bros sont certainement le meilleur exemple de gameplay bien tuné -- appelons ça "accorder les personnages du jeux" comme on accorderait ses cordes de violon ? -- que l'on puisse donner.

It took me time to figure out what sort of "tuning" Kirby Kid expected me to bring in. I finally realized that one of the best example of gameplay tuning is the way Piranha plants grow and shrink in Super Mario Bros. If you try and speed-run the game like in the first series of pictures, you'll see the plants active during almost all the time their pipe is visible on-screen. If you rather progress forward without stopping, but without running, chances are that the plant will be retracting while you reach the pipe but you've been warned as the plant was out when it entered the screen. If you happen to experience difficulties approaching the pipe (due to a tedious jump ?) chances are that you'll be threatened by the second raise of the plant.

Hopefully enough, when you're on the pipe, the plant are too shy to pop out and gnap you.


La première série d'image vient d'un speedrun du jeu. On approche donc les deux plantes carnivores à la vitesse maximale de Mario. Les plantes sont ici ouvertes dès leur apparition à l'écran mais ne vont se rétracter que quelques blocs avant de quitter l'écran.

La deuxième série d'images vient d'une vidéo de type "let's play" avec un joueur non entraîné, qui prend le temps d'éliminer les goombas avant d'arriver au tuyau. Avec une vitesse de marche normale, on arrive sur l'obstacle juste au moment où celui-ci va se rétracter. 20 ans (au pif, hein) avant fl0w, voici déjà un premier exemple de jeu qui adapte sa difficulté au niveau du joueur, puisqu'il y en aura davantage pour celui qui fonce tête baissée que pour celui qui avance modérément...

Saturday, November 22, 2014

Les tiles ... du C64 à la NDS

Chose plutôt inhabituelle, après pas loin d'un an de bidouille, mon premier article sur le site de la BilouCorp est finalement en ligne. J'avais envie d'y faire une rétrospective sur ce qui a fait de certaines machines des plate-formes assez merveilleuses pour la programmation de jeux vidéos et de jeter un coup d'oeil à la façon dont leur caractéristiques techniques ont formatté les jeux qui ont tourné dessus. Le premier jet, c'est donc sur les les tiles, ces petits pavés graphiques qui m'ont accueilli sur le C64 dans "Space Mission" et que je reprogramme dans SEDS pour vous faire les jeux de Bilou. Bonne lecture.

Some of us read and listen to English fairly fluently. For those, watching a video like the making of ROM city rampage gives a nice overview of what happens inside an 8-bit, tiled game. Mechanism within 16-bit and even 32-bit tiled games are essentially the same, with variations on the limits. For those who don't, I took the time to write down a cover of essential mechanisms like palettes, MAP area and the like and have it hosted at BilouCorp website.

Tuesday, November 18, 2014

Economiser des pixels

Imaginons un instant que je tente de faire l'animation du crayon-soldat qui court derrière Bilou juste en pixel art ... Il me faudrait avant tout gagner assez de place sur mes planches de sprites. Heureusement, les "1002/1024 tiles used" sont un peu surfaits. Si je visualise le contenu de la VRAM, les sprites colorés en rouge sont ceux dont je n'ai en fait aucun besoin. Ceux en vert sont ceux qui pourraient bénéficier du système d'animation par copie qui est à la base de l'encre-qui-monte.

This is the current content of the 64K of sprite sheet in the School Rush game. Sprites in red are unused and could be dismissed. Sprites in green are those who could benefit from the streaming technique (updating VRAM content as the frames advance. Given that I used only 6 16x16 blocks for the pendat so far, I could have the room for a pixel art running pendat, after all ...

Wednesday, November 12, 2014

L'histoire de Rayman

*deline, très fière, vous présente le nouveau livre de Rayman.
Très chouette ouvrage de Michaël Guarné que nous offrent là les éditions Pix'n'Love. Plus aéré et aussi plus détaché que l'histoire de Mario mais quand heureusement plus consistant que le trop graphique "histoire de Sonic", je ne regrette pas ma pré-commande. Bien sûr pour celui qui avait déjà la bio de Michel Ancel et le mook contenant le dossier Rayman, il y aura des redites, mais l'intervention de nouveaux collaborateurs -- chose rendue possible puisqu'on s'intéresse ici à une série, donc avec les anciens épisodes vus sous différents angles.

Mais il y a tout de même quelques belles perles pour l'amateur de game design que je suis, à commencer par une double page dédiée à la "bible du game design", ce cahier graphique de Michel Ancel rédigé dans l'idée de faire passer son jeu au mieux auprès des frères à la tête de Ubisoft. Ça me rappelle très fort le genre de documents que mon frangin plaquait sur ma table à dessin entre '93 et '94, avant qu'on ne mette la main sur notre game-maker.

http://critical-gaming.com/blog/2010/12/31/about-that-indie-feel-pt2.html
"Mario Can't Grab" (Kirby Kid)
J'ai halluciné en découvrant le nombre de 15,000 caractères de code pour le comportement de Rayman dans Rayman Origins. S'il y a une bonne dose de mouvements dans ce jeu, on est quand-même pas dans un jeu d'échec non plus... Puis je suis retombé sur une petite image de Kirby Kid à propos de Super Mario Bros. Ici, pas de roulé-boulé ni de wall-kick, mais on retrouve déjà la petite différence entre un jeu qui a été discuté entre testeurs et joueurs ou un jeu fait "en aveugle": si un petit coup d'anti-gravité permet de continuer un mouvement plus à même d'aider le joueur, alors on donne cette anti-gravité.

Saturday, November 08, 2014

Missing monster ?

Pendats dropping Power-ups, bladors stunning inkjets, all this had the objective to address Kirby Kid's most critical statement:
Most enemies are just things to avoid (lacking interplay). When I see enemies I don't get exciting to avoid them or take them out.
Most enemies were built around the idea that they are not aggressive, but still dangerous. This is built deep within the genome of Bilou's world: there is no invasion army we fight against, rather wild beast not appreciating that you disturb their business. Yet, it turns out that for a time attack side-scroller, we're missing something that would have wider range and somewhat chase Bilou (60px/sec when walking). I needed something that's mostly on the ground and dismissed with primary mechanic, but that moves faster than pendat (16px/sec) or dumblador (8px/sec).

Making Pendats Run?
That would be the easy way out. or should be. Design documents from 2004-2005 show pendats that charge Bilou with their spears. Even earlier, the comic show them knocking down stacks of books. Yet, this is hard to achieve -- if ever possible -- with today's pixel art pendat. To reach that, I will need the hybrid vector/bitmap animation editor I intended to use for BangBash.

Bangbash wouldn't help.
He's more than just dangerous. He's dangerous and quick to anger. Maybe that's not yet what makes you excited about facing an opponent, but at least, that should build up some tension.

Something a la Blues Brothers ...
That game from Titus is one where I could feel engaged in dispatching enemies. They weren't very developed, either shooting, wandering or wandering-and-shooting-if-spotting-you, but they were moving about as fast as yourself. If they weren't as smart as the pendat described above, they'd usually have a "knock you down" animation when they hurt you. They're also quite fast. If you find yourself out of crate, think twice before you revert direction because every pixel between you and the bad guy count. You won't outrun them as easily as a goomba.

So if you haven't guessed from the size-test picture, I'm opting for a staple remover. These things look hazardous enough in real-life, it's not a wonder why you can find some customized into T-Rex heads. I've endured countless buzzing of Nintendo's "Donkey Kong Jr." game-over as I got my feet chunked into bits by those living wolf traps and their klap trap derivative. It doesn't turn very easy to pixel, however.


Friday, October 31, 2014

Les p'tits trucs du monde 16 bits ...

Je trouve assez instructifs les commentaires de Tool-Assisted Speedrun de Coeur de Vandale, RealMyop et leurs invités. Dans sa présentation, le jeune Got4n nous explique par exemple que dans son portage GBA, le moteur du premier Rayman ne teste pas toutes les collisions à chaque frame. Les collisions entre Rayman et les ennemis ne seront évaluées qu'une frame sur 4 alors que les zones plus larges (sortie de niveaux et autres déclencheurs) se relaient et sont évalués une fois toutes les 7 frames. Une ruse élégante pour continuer à faire tourner un jeu conçu pour PC à 90MHz sur un processeur ARM 33MHz (le hardware graphique du GBA permet de sauver pas mal de temps, mais tout de même ...)

About one year ago, a colleague pointed me towards a video where two French guys comment a tool-assisted speedrun completing Super Mario World in a couple of minutes. It is not quite "abusing game rules" where you'd play Megaman as if you were Neo in the Matrix. No. It's looking much more a hacker exploit where you force the program to jump to some place where you can distort content of the code memory. There is no limit to what you can achieve once you reach such a point. You can immediately launch "you won" credits, you can replace any monster's behaviour with some machine code of yours ... you can even play Snake rather than Super Mario.

Since then, I keep an eye on speedruns and tool-assisted speedruns as a way to pleasantly discover the little tricks inside major games. Things like "given maximum speed is 8px/frame, you only need to test for collision with block-size spikes once every 4 frames (Rayman GBA). Or that all the dungeons of Zelda: LTTP are located in the same map and that you can move from one to another provided that you can drill hole between them.


Dans les autres découvertes sympas, saviez-vous que tous les donjons de Zelda: Link to the Past partageaient la même map, et qu'il est donc possible de passer d'un donjon à l'autre en s'y prenant comme il faut ? Eh oui. Quand on doit faire la première grande aventure sur une cartouche 8Mbit, tous les coups sont permis ;)

http://www.explodingrabbit.com/forum/threads/whats-needed-to-finalize-the-current-flash-version-of-smbc.15500/page-3
A la base d'un Tool-Assisted Speedrun, il y a un émulateur dont on utilise à fonctions d'inspection de la mémoire pour trouver où sont conservées les vitesses, les zones de collisions et tous ces petits détails croustillants qui permettent de définir la trajectoire idéale. On s'autorise aussi à envoyer à la console n'importe quels signaux d'entrée, même quand ils ne sont pas humainement possible avec une manette normale et des (gros?) doigts, comme relacher le bouton et le réenfoncer en 1/30 de seconde précisément avant de faire faire Gauche+Droite au D-Pad dans le 60ème de seconde suivant.

Allez, la prochaine fois, je vous explique comment on manipule les boss.

Tuesday, October 28, 2014

Couper les cheveux en quatre ?

J'hésitais à introduire le contrôle des boîtes de collisions dans mon éditeur d'animations. J'hésitais encore plus à ce qu'on puisse activer ou désactiver certaines de ces boîtes au fil de l'animation. Tout ça me semblait plutôt relever de la machine d'états et des gardiens de transitions. Et puis Shantae m'a fait changer d'avis.

So far, I have been able to keep hitboxes on a per-state basis. Anything more subtle was resolved either by spawning new GOBs (like the punch attack in Apple Assault) or splitting the animation (inkjet). I was growing the conviction that it wouldn't be enough for new grab-in-the-air mechanic, Shantae's move pushed the definitive argument: *any* punch or kick-like move has build-up and recover phases, and the hitbox shouldn't be active by then. Splitting the animation in such cases ? That would quickly turn into a nightmare!

At this point, not adding edition of hit boxes in the animation editor would strongly reduce my chance to have form-fit-function ...


Lors de l'animation d'un coup, on peut distinguer trois phase: la préparation, l'action et le retour. Idéalement, seule l'action correspond à une hitbox offensive. Selon la longueur de la préparation et du retour, enfreindre cette règle (qui dérive du "form fits function"), c'est produire des effets incohérents et du coup rendre beaucoup plus complexe l'apprentissage du système par le joueur. Je n'ai pas eu le problème dans Apple Assault parce que les coups de poing étaient en réalité des sprites indépendants. J'ai contourné le problème avec inkjet en tronçonnant l'animation en deux parties et en faisant en sorte que Bilou ne puisse réagir qu'au moment précis de la transition entre les deux tronçons. Mais soyons clairs: faire la même chose avec tous les mouvements "power-up" prévus serait un véritable cauchemar.

Saturday, October 25, 2014

GobAnim::isJedi()


jump, twist and roll!
That's quite amazing, how I manage to postpone an upgrade of the game engine for days and then have two of them implemented in a couple of hours simply because I used doxygen-on-cybook to brief myself on what's around and what is the most straightforward path for implementing them. I have now a way to instruct that a specific transition animation has priority over the running one, which is mandatory for your "air-grab" to have any visible effect when you're turning back or reaching the top of your jump -- in a word, for a consistent behaviour. It also allowed me to give "float-land" a first attempt.

Et voilà: j'ai pu indiquer que certaines animations peuvent "forcer" la main à certaines animations de transitions, comme prévu, mais plus facilement grâce à mon cybook-qui-garde-mon-code-sous-la-main. Comme quoi, je ne regrette pas son passage par le service-après-vente ;). Du coup, on peut déclencher l'animation "attraper en l'air" à n'importe quel moment. Je me suis aussi amusé à modifier l'autre "pirouette en l'air" pour lui donner un aspect de "je descend en planant", même si on ne peut pas dire que Bilou soit un très bon planeur jusqu'ici. Il faudra voir ce que ça donne avec une vraie DS en mains, par contre. Au clavier desmume, c'est assez moyen et on commence à bien s'embrouiller entre la course, le saut, le grab et la pirouette/vrille...

Allez, si ce n'est pas encore fait, profitez-en pour voter pour votre power-up préféré ;-)

Automated OAMs management

Over the summer, I crafted plans for managing larger levels, that would use more than 128 hardware sprites (the OAMs in DS parlance) for all the monsters. Some of those plans use the notion of a "Gob Group", that could be used to spawn several objects at once, at level-specific locations by having them statically placed (unlike shoot-able "dyngobs") but wouldn't be active unless their group is enabled.

Browsing through the game engine code for another purpose on my cybook, it struck me that it would be so easy to have lazy allocation of the hardware sprites as we approach on-screen area and early recycling of those OAMs when we're going far enough from that area. It's now coded. Funny enough, it doesn't affect activation and movement of GOBs in any way: only whether they have hardware sprites assigned to them or not.

done: find a way for Bilou to keep its priority (displays over monsters)

Monday, October 20, 2014

catch this!

A new animation and a good deal of "sprtools" to merge pixels drawn on "lime" DS and animations built on the DSi ... Unfortunately that will not be enough. There's one "dead" moment where you cannot see the "grab-in-the-air" animation whatever you do: when Bilou reaches the top of his jump. The reason is that there's already a "transition animation" running at this time, and that there is no way so far to cancel such an animation for another. I may have to fix that before I can proceed any further: it will likely be very important for super powers.

Une nouvelle animation, quelques coups de sprtools pour fusionner les pixels dessiner sur l'une des DS et les animations présentes sur la DSi. Eh pas de bol: ça ne suffit pas pour avoir un mouvement 'attraper en l'air' qui rendrait le gameplay de SchoolRush plus fluide. En fait, ça marche presque tout le temps sauf lorsque Bilou est au sommet d'un saut. La faute à l'animation de transition qui s'active à ce moment là: le moteur de jeu n'a pour l'instant aucun moyen 'd'annuler' une animation de ce genre. Je vais aller corriger ça, parce que ça risque d'être critique pour les coups spéciaux.

  • [done] "force" flag to override transition animations
  • [done] make "grab" a dedicated state
  • [done] edit areas directly in AnimEDS
  • [done] import AnimEDS areas in GOB states
  • [done] selectively activate/deactivate areas in AnimEDS

Sunday, October 12, 2014

Énergie Scolaire ...

Vous aurez peut-être noté le nouveau sondage de ce blog: quels power-ups ajouter au jeu "Bilou: School Rush" ? Ces power-ups seront essentiellemt détenus par les crayons-soldats, histoire de rendre les affrontements avec ces derniers plus excitants. Voilà donc ce à quoi vous pourriez vous attendre:

If you feel so, and especially if you have played Bilou: School Rush a few times, I'd love you to vote for the following nominated power-up candidates. Writing them down, and given the short length of the game, it would likely be cheap if these were permanent power-ups. I rather see them as "consumable" powers, e.g. you could have 3 throws, 5 float and 1 pound left.

Straight throw: fini le lancer en cloche. Comme dans les esquisse, le super-throw lance l'objet droit devant vous. Il reste actif jusqu'à ce qu'il sorte de l'écran ou heurte un mur. De quoi rendre plus aisé l'assomoir d'encriers.
Default throw fits physical laws by making bladors fall. Bilou throws them at an angle of 45°, making it a mid-range weapon that's demanding to aim, like Worms' grenades or DK barrels. Straight Throw switches instead to Blues Brothers' like weapons, where the blador is moving faster, perfectly horizontally, and at constant speed until it gets off-screen. The counter-part is that when you miss your target, your weapon is gone for good nonetheless.

Air dash: Le bon vieux mouvement aérien qui permet de se tirer d'affaire en nous soustrayant un instant à la gravité pendant qu'on part à toute vitesse. On le retrouve dans Giana Sisters, par exemple.

Air Dash and Ground Pound allows you to reclaim control from gravity. You should have fallen, but you're allowed for a short distance to follow a straight line by pressing a single button. You should have been waiting to reach terminal velocity but you get it instantaneously, and get rid of that annoying horizontal speed for an accurate land. Wall Kick, finally, is a twisted version of Air Dash, that can be chained (more open along time), but is restricted in space (only along walls). 

Ground Pound est son complémentaire direct, qui annule toute vitesse horizontale pour passer directement à une chute en vitesse terminale. (cf. les 2 derniers 'super pouvoirs' sentis pour la "version GBA" du jeu).

Wall Kick, la désormais célèbre technique de ninchat du jeu de plate-forme ne serait que moyennement utile dans ce type de jeu, à moins de bien l'ajuster pour qu'elle permette de compenser un saut un poil trop court.

Big Punch, l'attaque niveau 2 de Apple Assault, qui serait capable d'incapaciter crayons et gommes (voire encriers) à courte distance. Le seul avantage sur un lancer de taille-crayon serait ici ... qu'il n'y a pas besoin de disposer d'un taille crayon. Peut-être moins marrant que dans le jeu d'exploration puisqu'il perdrait en grande partie son intérêt de "brise-craie".

Remember Apple Assault ? "Big Punch" is the intermediate weapon you could receive, that dispatched apples at safe distance, with a massive move. Here, it could stun pendats and recto-verso jumping erasers without requiring you to carry bladors around.

Float-Land, lui aussi, agit directement sur la gravité. Il s'agirait de doter
Super Powers as sketched in Summer 2014.
Bilou de l'équivalent des cheveux de Rayman ou de Dixie, voire d'une feuille-mojo pour planer un peu et atterir en sécurité quand il s'avère que le saut est trop court.
Maybe you'd rather float safely to that next book rather than rely on a timed jump ? That power-up is for you, raccoon friend ;)

Last one, the Wide Grab, is for all those who'd love to catch big air with a spongebop, but typically miss their (B) timing. Wide Grab would double your grabbing hit box. How couldn't you love that ;)


Wide Grab permettrait d'élargir la distance à laquelle Bilou peut se saisir d'un taille-crayon ou d'une éponge, sans aller jusqu'à lui faire don d'une "main-lasso". Cette marge de manoeuvre supplémentaire permettrait soit un gameplay plus "nerveux" (assomer et attraper un blador en un seul mouvement) mais aussi donnerait plus de chance aux joueurs de faire du rodéo sur les éponges.

Restera un choix crucial: celui d'octroyer un pouvoir semi-permanent (p.ex. jusqu'à la prochaine blessure) ou des "munitions" pour le pouvoir en question (mais autorisant de cumuler plusieurs pouvoirs). Vu le côté "arcade" de School Rush, je pencherais plutôt pour la 2eme option.

Saturday, October 11, 2014

Palette Sonore : CJ à la rescousse!

Un point sur lequel je peux facilement donner raison à Kirby Kid, c'est le désert sonore dans lequel on évolue dans le jeu. Un petit "p'tcha!" quand Bilou se fait toucher, un "bop" quand on rebondit sur un monstre et un 'ting' quand on chope un bonus. Et c'est tout. Le lancer de taille-crayon, les encriers qui se préparent, les éponges qui bougent ... tout celà est aussi silencieux que si vous étiez sur Mars.

Kirby Kid also pointed out the lack of sound in the game. Especially, the fact that you don't hear anything when you jump makes it a curious jump-and-run game. I tried converting more of CJ's samples into sound effects, but it didn't really took off. I'll need dedicated samples so that we clearly hear the jump as not being a part of the background music. I also want dedicated sounds when you stun something, when you 'hap' in the air trying to grab something, when you bounce on a pink eraser or when you're interacting with an inkjet.

All this also stems for some code refactoring. As of writing, there is a limited palette of 16 special effects (including sound effects) you can use in the level. It is close to 75% of use, and the major problem comes from the fact that it is _global_. Much like each .cmd file now has its own palette of animations, I need to give dedicated effects palette to each character.


Il est donc grand temps que j'appelle CJ à la rescousse. Mais ça ne suffira pas. Actuellement, je suis limité à 16 effets spéciaux pour l'ensemble du jeux. Celà reprend les sons mais aussi les créations d'ennemis comme les petites étoiles qui indiquent que Bilou s'est fait assomer ou les pieds des Bladors quand on les assomme. Si je veux pouvoir proposer des bonus quand on dégomme un crayon ou une gomme sauteuse, il faut que je fasse d'abord disparaître cette limite.

Ah, par contre:
  • étourdir les encriers à coup de dumblador: ça marche;
  • moduler la force du lancer de taille-crayon par la vitesse de Bilou: mauvaise idée

Btw, I allowed bladors to stun inkjets but turned away from "blador are thrown faster when Bilou moves faster" -- this is just a nightmare for aiming.

Thursday, October 02, 2014

Kirby Kid's Advice: Inconsistent Spongebop

Inconsistent interactions with yellow things. The yellow swinging enemies are neat looking and they have neat physics to them. But interacting with them is very inconsistent and too complicated. It's hard to stay on top of them. It's hard to get the big jump off of them. And the momentum of their swing doesn't transfer to the player at all.
Let's first see what "inconsistent" means in this context. Kirby Kid validated the two definitions I formulated as below:

A mechanic is consistent with regards to 2 object if
  • applying it the same way on the two objects leads to the same result. E.g. slashing something with the sword breaks it into bits in Zelda series. That works on bushes, jars, skulls and even rocks in some games.
  • when it leads to different result, the objects shall be sufficiently different so that the player can easily tell what result it will get from passive analysis of the object. E.g. Jumping on an ennemy in SMB always attacks the ennemy unless the ennemy has spikes on his head. Moreover, the ennemy will always be defeated unless it is shelled.
A gameplay element (applying mechanic A on object B) is self-consistent if
  • it always produce the same result (e.g. bounce by 3 blocks height)
  • when producing different result, the player can relate the cause of this difference to visible difference of state. E.g. a spring that may be loose or compressed will throw you higher if compressed.

Pour corriger mon éponge-qui-se-balance, aussi connue sous le nom de "Spongebop" ou "Bop, l'éponge", je vais avoir un peu plus de mal. Kirby Kid lui a diagnostiqué un problème de manque de cohérence, ce que je peux traduire de la façon suivante: il n'existe pas de manière claire de savoir quel sera le résultat d'un rebond ou d'un balancer qui fait intervenir l'éponge. Kirby Kid mentionnait aussi le fait qu'il est difficile de déterminer si l'éponge va nous repousser vers le côté où si on va pouvoir atterrir dessus. La difficulté principale sera psychologique: dès les premiers coups de crayons, "Bop, l'éponge" est un personnage (et pas une plate-forme) au comportement erratique. Il sera utile, mais il faudra s'en méfier.

From the start I have designed spongebop to be somewhat chaotic, which makes it appear mostly only on the "hard path" of School Rush game. But chaotic must not mean "totally unpredictable". There are two moves that are expected with a sponge bop. The first is to use it to gain height, the other is to clear a larger distance with a jump. Both are based on the fact that, when you press A while un-grabbing a SpongeBop, its current velocity is added to the one of your jump.

Initially, I thought Kirby Kid was mostly criticizing the difficulty to do the first move -- gain height -- because when SpongeBop is  almost idle, the only moment when you can "jump off" is when it moves upwards. But getting that is more a matter of luck than skill: because oscillations of Spongebop across its equilibrium are small and that the "auto-bounce" that happens when you "land" on it can hardly be controlled, the best you can do is to try again and again until it works. You cannot even spam the JUMP button because you'll have to hold it down once successfully bouncing off if you don't want to cancel your jump.


Voyons un peu les interactions que permettent Spongebop:
  • SB peut pousser Bilou bas d'une plate-forme ou l'interrompre dans son saut si le contact est latéral. Incohérence: c'est un rectangle qui nous repousse alors que SB est un patatoïde protubérant.
  • Bilou peut rebondir sur SB s'il tombe dessus et rebondir plus haut s'il appuie sur (A) avec justesse. Incohérence: il est difficile de déterminer la hauteur qu'aura le saut effectué dans la plupart des cas.
  • Bilou peut s'accrocher à SB pour franchir plus facilement un trou. Incohérence: il n'est possible de s'accrocher que lorsqu'on tombe, et pas juste après un rebond malencontreux.
  • Bilou peut faire un long saut en avant en appuyant sur (A) au moment précis où l'on lache l'éponge. Incohérence: rien n'indique pour celui qui n'a pas encore suivi de cours de balistique (ou fait trop peu de balançoire) que la fin du mouvement est un mauvais moment pour cette manoeuvre-là.

 I've been more surprised to see Pierrick failing to clear a large jump by using SpongeBop's swinging speed. He was persistantly trying to jump *at the end* of the swing, but physically speaking, bop's momentum is nul at this time. So indeed, it doesn't transfer to your character.

The way Spongebop behaviour lacks consistency can be summarized as such: when you jump off a Spongebop, the velocity you have will depend on Spongebop's instant velocity. Due to its physics, Spongebop velocity is constantly changing in 2 dimension, meaning that it takes some careful study (or prior knowledge) to pick the moment where you'll get the desired behaviour.


    Saturday, September 27, 2014

    Kirby Kid's Advice: Inkjet interplay


    Here's another one stripped out from Kirby Kid's precious feedback:

    the double ink jar obstacle could be tuned better so that the player waits less. the rhythm/timing challenge here is pretty complex (two objects moving and attacking at different rate). Also when the ink rises jumping into these jars is difficult when they go under the ink.
    Pas évident, hein, les doubles encriers ? Selon Kirby Kid, ça vaudrait la peine d'en ajuster le rythme pour que le joueur ait moins besoin d'attendre. Effectivement, si on essaie de passer en force ou en vitesse ce genre d'obstacle, ça se finit généralement dans une mare d'encre. Même pour moi. Dommage pour un jeu de course ?

    Yeah, that's quite true, I have to admit. Whenever I fail myself at *deline's level, that's in the only part she has not been involved in: the double inkjets. Same for the later level. I hadn't bother this far because I'm not that good at video game, so it sounds natural to me when there's some place where I often fail.

    Now, there's one easy way I could increase the chance the player goes through such challenge: allow him to undermine it. If only Bilou had the opportunity to stun inkjets by throwing him a dumblador, that would ease moving through. You wouldn't need to time your jumps because inkjet would stay in-place.

    Mais je coince un peu: je ne vois pas bien à quels ajustements procéder. Permettre de simplifier le challenge, ça oui. Il me suffit de permettre au joueur d'assomer les encriers qui resteraient alors gentiment sur place, sans plus jeter d'encre. On redescend à un mode plus simple avec un encrier immobile et un mobile, une seule source de goutelettes. Mais est-ce bien à ce genre de solution que Kirby Kid pensait ?



    You wouldn't have to fear droplets either. Of course, when there's two of them, only one would be disabled that way, but that would still be better than trying to hop here and there to dodge droplets.

    L'autre explication possible, c'est qu'avec leur façon de monter et descendre depuis le début du niveau, mes encriers se trouvent dans un état trop imprévisible au moment où le joueur les rejoints. Le moindre petit retard accumulé et il n'y a plus moyen de se fier à sa mémoire: il faut obligatoirement observer les encriers, repérer le rythme de leurs tirs (qui dépend de la distance qu'ils parcourent) et se faufiler entre les gouttes.

     
    Now, the point I cannot solve is whether that would be solving the "tuning" issue mentioned by Richard. But what could I tune better ? Inkjet's speed doesn't seem too fast, they typically throw once moving up and once moving down. The moment when they'll prepare their blow is constant related to the moment where they turn back, so you *can* learn it from observing, but it will be harder to use this knowledge from one inkjet to the next, since the position of your platform compared to their turn-back position is variable.

    Comparativement, tous les Marios sur 8 et 16 bits n'auraient activé le comportement des encriers qu'après que Bilou s'en soit suffisamment approché. En dosant la vitesse à laquelle il avance, le joueur peut alors "manipuler" leur comportement et les forcer à adopter un schéma qui est plus à son avantage. J'avoue, c'est surtout une technique de speedrunner, et j'aurais tendance à la trouver plus perturbante qu'amicale, mais au moins ça donne une possibilté de contrôle bienvenue dans ce genre de situation.

    One thing that differs from typical Mario games, is that inkjets are active as soon as the level starts. In comparison, all 2D Mario games built before 1995 were technically limited to a dozen of active sprites. Anything that was moved offscreen from a sufficient distance was "deactivated" and monsters -- but also moving platforms -- start activating when the screen approach them. Here, the player will see them at a random initial position because their position depends on the number of frames spent to get there. Comparatively, in Mario, you'd see them at a position that only depend on how fast you were moving when approaching them. Is this what I'm missing ? 
    The ink is interesting to avoid in the air. Once it hits the ground, the player has successfully dodged. If the ink hurts on the ground, the player just waits around for the coast to clear.
    This has been easily fixed. Now the ink only hurts in the air, no longer on the ground. For the "rush" type of game, this is definitely not deconstructing any of the challenge.

    Sunday, September 21, 2014

    Kirby Kid's advice: Where's my momentum ?

    I've been expecting Kirby Kid's "tuning list" like a kid expecting his birthday, checking my mailbox every now and then until I finally got his feedback on the two-level edition of "Bilou: rush to completion". I've got many items to review, so I won't try to give you all of that at once, but I'll rather reveal them once at a time as I address them.My major action point here will be to harmonize things.

    input, moving

    If there's a run button it either needs to be a dash like MegaManX or a constant state like Super Mario. Having to repress the button every landing and every turn around is annoying.
    Where is my momentum going [related to air control]? Sometimes I get to move forward smoothly and continue moving. Other times jumping off of things and even landing kills all my momentum. Momentum is so very important in a game like this especially because the movement and fall speed is very slow/floaty.

    Kirby Kid m'avait annoncé une 'liste de choses à améliorer' dans Rush to Completion (2 niveaux), et j'avoue que j'attendais ça excité comme un gamin la veille de Saint-Nicolas. Je l'ai enfin reçue, et il y a vraiment plein de choses dedans. Je ne vais donc pas essayer de faire tout en un seul post. Ici, on va se concentrer sur les déplacements de Bilou.

    Premier point faible, la course de Bilou. Pas tout à fait un dash qui se déclenche d'une simple pression de bouton, ni un état permanent tant qu'on garde un bouton enfoncé à la Mario. Enfin, si, il y a un bouton à la SMB: le bouton R. Mais il y a aussi un mécanisme de course à la Kirby, et lui je dois admettre qu'il fonctionne bizarrement. Et bien sûr, s'il y a deux moyens de se mettre à courir, les deux devraient fonctionner de la même manière, pas demander qu'on ré-active la course après chaque aterrissage ni à chaque demi-tour.

    Well, funny enough, there *is* a Super Mario constant state running: the R button. But the most straightforward way to RUN -- double-tapping the DPAD -- indeed works weirdly. Anyway, whether you activate it with a double tap on the DPAD or holding the R button shouldn't matter: the mechanic should work the same. Why has my mind so far accepted that people using double-tap dash should get a more annoying RUN than people holding the R button, who would keep constant speed upon landing ? Meditate on that I will. Meanwhile, I'll fix the code so that you can keep running as you land even with the double-tap.

    Kirby Kid pointe aussi un contrôle en l'air qui casse toute l'inertie horizontale. C'est le cas quand on se fait jeter d'un encrier (enfin, je suppose que c'est ce qui lui arrive). J'avais voulu limiter la marge de manoeuvre du joueur dans ce cas-là (et aussi quand on rebondit sur une gomme), mais visiblement j'y ai été trop fort.

    I will have some more tuning on the "thrown up" move, I guess. I thought it would be nice to restrict how much control you have over your trajectory when you take big air with a pink-bumper or a inkjet. That stresses the player to gain momentum first (on the ground), jump, and then bounce to clear the jump. It was already a tricky thing to achieve in the anniversary level, but it apparently turns into a nuisance in this game.