Sunday, July 21, 2024

map poked!

map.poke is done. Okay, it doesn't read "map.poke" in the level script but rather block (coordinates) = (hex) so that it mimmics the block (hex) { ... } definition. And that makes it specific to special blocks.

But there it is. After some branches untangling and more commits weaving, I could use it to add a secret exit in the trunk of the 'greent' room without having to go through the now-clumsy steps of patching the level on NDS while editing code on the PC.

Bon, je crois qu'il n'y a pas besoin que je vous dise que quelque-chose n'a pas marché, hein ? vous vous en doutez rien qu'en regardant l'image... En mars, j'avais évoqué la possibilité de reprendre les vieilles maps pour étoffer un peu "Dreamlands" (ou à tout le moins, proposer un peu plus de contenu pour la démo "3 rooms"). Et bonne nouvelle, j'avais fini par retrouver les maps en question. Je m'étais donc rajouter un peu de script qui dise "alors, le bloc de type 11, c'est une sortie secrète, et dans le niveau greent (le nouveau), si on la touche, tu charges le niveau greeny (l'ancien)". Sauf que pas moyen de tester, évidemment, parce que sur greent.map, il n'y a aucun bloc de type 11...

C'était donc l'occasion de se bouger un peu et de coder le mécanisme dénommé "map.poke", à savoir permettre au script d'aller modifier les propriétés d'un bloc du niveau sans rien demander à personne (et en particulier pas à l'éditeur de niveaux ;P). Et oui, la vie est telle qu'il m'aura fallu un bon mois pour que ces malheureuses lignes de code finissent compilées sur le PC qui avait aussi le fichier greeny.map ce matin. Tout ça pour se rendre compte qu'avant de pouvoir faire une "release" avec la vieille map n°1, je vais devoir lui faire un sérieux ravalement de façade pour l'adapter au nouveau tileset ^^"

Oh I presume you don't really recognize the big tree of my so old two-levels demo: since I re-structured the tileset, there are quite some editing to happen there before you can actually enjoy anything :P

Friday, July 19, 2024

Soudliers (encore)

 mais cette fois ci, je suis aux manettes :P

Le jeu est de toute beauté, et je dois dire que le level design me convient assez bien. J'avais un peu joué en fin de soirée, j'avance tranquillou (je me suis en mode "exploration", pas fou), mais je trouve prenant en ayant suivi un tunnel pour me retrouver dans une chute d'eau tout en sachant que j'ai laissé une autre route derrière moi avec cette sensation de "mais alors ? qu'est-ce qu'il y avait de l'autre côté ?_?

Je joue l'archer, aussi. Le jeu a la réputation d'être crapuleusement dur alors fort de mon expérience dans Shantae, je prends un perso qui peut attaquer à distance.

Deux boutons d'attaque - une flèche instantanée mais qui nécessitera un recovery plus tard, une attaque tournoyante de portée plus faible et qui nous prive de tout autre attaque jusqu'à ce qu'elle soit finie mais qui peut être enchainée à l'infini - un bouton d'esquive pour contourner un adversaire - que pour une fois je parviens à utiliser pas trop mal - et bien sûr un bouton de saut. Un panel de mouvements qui n'est pas sans rappeler le combat dans HoB, soit dit en passant. Tout le reste sera sur les gâchettes ou les entrées directionnelles supplémentaires des joy con. Et du reste, il y en a, comme le lancer de bombes que j'ai dû remapper parce que je le déclenchais à chaque fois que je voulais utiliser le bouclier (qui pare entièrement les assauts mais qui fait baisser la barre de statut mauve.

Il n'y a pas à dire, les mécaniques de gameplay sont riches, plutôt bien équilibrées. Mon seul coup de gueule c'est cette "roue des compétences" qui me permet pour l'instant de choisir entre les armes de base et les armes de feu (ouh, J.L.N va adorer, ça) qui est mappée sur le stick directionnel de droite et que j'accroche donc accidentellement quand je tente un combo "sauter/tirer" trop souvent à mon goût.

Les niveaux sont immenses, mais un mécanisme de téléportation entre points de sauvegarde est proposé d'entrée de jeu ... heureusement. Seul point noir, le temps nécessaire pour les sauvegardes et les téléportations (ou les changements de maps, d'ailleurs).

edit: je suis arrivé dans la pyramide qui m'intéresse lors du premier week-end de jeu. Le mode "explorer" porte bien son nom, même si je dois quand-même sortir une potion de soin de temps en temps...

edit++: au bout de 8h30 de jeu, un boss atypique dans le fond de la pyramide me met finalement game over en boucle. Il m'aura fallu un moment d'étude de let's play et beaucoup de chance pour le vaincre.

Tuesday, July 16, 2024

How GEDS scrolling works

The scrolling routines of InfiniMap weren't as well documented as I hoped. Not even when I blogged that "yeah, it finally works". And while trying to document them, I noted some undesired difference between what the code does and what I claimed it does in the comments. So here it goes. First this is the full level map, stored as a 2D array of tiles. Within them, we define an area of world coordinates (xmin,ymin)-(xmax,ymax) that is guaranteed to be present in the video memory as well. That is the "invariant", the condition that was true on the first line of a scroll_*() call and that must be restored before we leave the function.

if (py < ymin + WH / 2)
do { up_scroll(); } while (py < ymin + WH / 2);
else if (py + WH / 2 > ymax)
do { down_scroll(); } while (py + WH / 2 > ymax);
if (px < xmin + WW / 2) left_scroll();
else if (px + WW / 2 > xmax) right_scroll();

WWxWH is the dimension of the validty area. We will never let xmax - xmin < WW happen. To decide whether scrolling routines should update the contents of video memory, the scrolling code compares the position of the camera (i.e. the center of the viewport) with the coordinates of the area. If it gets too close to one edge of the 'validity area', video memory contents will be updated and that edge will be moved, possibly dragging the opposite edge along (since we have fixed-dimension video memory)

void right_scroll() {
unsigned xoff = (xmax - xmin) / TL;
// compute target position in video memory
u16 *src = dataview + xoff;
xmax += SQ; // new validity window will end 64 pixels on the right.
if (xmax - xmin > 512) {
xmin += SQ;
xview = (xview + SQ / TL) & 63;
dataview += SQ/TL;
}
// copy from src to video memory
// so we fill the expanded area with valid tiles. 

Then, this is the video memory. The hardware reads it as a 2-dimensional wrapping array, that is if it cannot read more at the right, it goes back reading on the leftmost column. The (xview,yview) reference point corresponds to "where in the video memory is (xmin,ymin)" (that was the part that needed a patch).

Note that only a part of that valid area will show up on screen (highlighted here).

Note that whatever happens, xmin always shifts by 64 pixels. That's the horizontal copy granularity SQ (because it was meant to be square), and no, I never checked it led to better performance than 32. We must have ScreenWidth + 2*SQ < VramWidth, though.
 

Saturday, July 06, 2024

Test tile type from state transition

As I update an old post to explain that yes, cando() finally managed air/water transition I note that the whole blog is still missing a key explanation of how this was made possible. It happens in state machine transition expression (in the predicates, actually) and says "tell me the properties of the world n pixels above my hotspot".

$FALL->$INWATER on fail [2 H WATER ?]
                        (v1 v5 + 2 / :1 0 :5);

$INWATER->$RBOUNCE on event0 [D_FOOT 8 H AIR ? &]
                        (800 ~ :1);

You see it there. H is the new OP_HOTTILE for the GobExpressions. it picks the value on top of the stack, the constant 2 or 8 here. We can then test bits against the constants WATER or AIR with the ? operator.

Without that, the trick about a slice of tiles that are both water and air is useless, because you couldn't make the difference between falling into water and falling on the ground anyway.

(and yeah, I still have to add those get-worldwide-flag and set-worldwide-flag opcodes as well as the roll-the-dice opcode)

Tuesday, June 25, 2024

Baies pas mûres

 

Eh si, il me reste encore des gribouilles du 1er Janvier 2022 à poster ... dont cette idée d'un berry-bat pas encore mûr qui essaie de se s'attaquer à Bilou mais qui reste attaché à sa branche ... qui a bien fait rire les gens qui l'ont vu, d'ailleurs.

Mais pourquoi, me direz-vous peut-être ? Eh bien outre son rôle de bow-wow rigolo, ces baies encore vertes sont plus dures et pourraient donc rester à trainer sur le sol une fois assommées par un saut. Quelque-chose qui pourrait se révéler utile dans les montagnes, par exemple, où les Applemen ne poussent pas...

There are sketches in a notepad, which were drawn on new year's day two years ago and that haven't been blogged yet. This is one of them. J.L.N and I were revisiting the green zone baddies and came up with a variant of the berrybat that isn't ready to leave the vines. 

It would play a bit like a bow-wow, it would be green, to show it isn't matured, and it will likely be a challenge to animate, especially if I want the vines to be a bit flexible (at least, flexible enough to justify they cannot suport Bilou's weight). But they would be harder than their matured, flying counterpart, meaning that they would stay around once stunned, could be picked up and thrown on things to stun them.

Il était aussi question de s'en servir pour faire enfler certains piafs et s'en servir comme plate-forme.

Saturday, June 22, 2024

map.poke

I will try to get energy again for DS development. Not that I have dropped any Bilou-related activity, but I would like it to lead to code, and not just sketches. One of the last notes I wrote were about live-patching the map from scripts. That was before going on short vacation and no, I did not have my source code along this times (kids have grown up ;)

I know I've been tempted to dismiss it as "not so important", "low priority", but then I realised: if I want to start working on new controllers like "hanging" or "between", I will likely need special tiles to use them. And if I have to go for a full power- NDS- wifi stick- NUC- emulator cycle every time I need a new tile somewhere, I'll never be done. (proof: it's been two month and I haven't done that a single time).

I already have methods in the FlatWorld class that could take care of updating graphics and physics layers as needed. The thing that has been holding me back so far is the fact that this class isn't reachable from ScriptParser.

But well, things aren't as bad as I thought: GameScript keeps a physWorld reference to the objetct that has the desired interface. We're just one getWorld() call away from being able to implement map patching...

Once I'll have the a tile flagged as "hang here", I'll give a try to a new Hanging state ... Even without fancy swinging animation, it should already take us much closer to the gameplay I want for "dreamland"...

edit: just as I was checking the state of my working folders, I found the old maps I had considered merging into the current demo. So I went on and coded a 'secret exit' special block that could send us to one such old map ... And haven't tried it yet because I of course don't have any block of that type on my map ^^"

SMBW: comme dans le jeu du blob

J'ai bien souri quand j'ai vu la gelée quelque part dans les mines fongiques de Super Mario Wonder: un clin d'oeil bien vu à une mécanique jusque là unique d'un niveau de Super Mario Land 2.J'ai souri encore quand Mario s'est vu changé en blob à son tour, collant aux plafonds (comme avec le très réussi power-up foreuse) et suivant le parcours sur les murs ...

Vous pensez bien que quand J.L.N est arrivé là-dedans, il est parti dans un "wouahh. C'est génial! On peut aller Partout!", parce que évidemment, la mécanique est entièrement neuve dans la série Mario. Enfin, il y avait quand-même un peu de ça avec la super-étoile dans Yoshi's Island et il a joué à des niveaux de Rayman où on court sur les murs, mais dans les deux cas, si on s'arrête, on tombe, alors qu'ici on a tout le loisir d'explorer le niveau pendant qu'on colle au mur...

Mais moi, ça m'a surtout rappelé une vignette dans un vieux magazine de l'époque Amiga. Sauf que pas moyen de me rappeler son nom pour vérifier. j'y avais repensé au moment ou "the blob" est sorti, quoi qu'en réalité le gameplay serait plutôt à rapprocher de Super Morph auquel je n'ai pas joué non plus (mais j'aurais bien voulu).

Ce n'était pas non plus Super Putty, toujours dans la catégorie "plate-forme avec un blob bleu", mais bien Globdule, un jeu de Psygnosys (!) tout en rampes et en arrondis avec un blob bleu qui est mauve, apparemment... tout en glissades et en adresse.

Et si j'ai finalement remis le doigt dessus, c'est parce qu'un internaute maîtrisant le japonais a un jour décidé de faire un recensement de tous les jeux 8-bit et 16-bit où on contrôle un blob. Eh oui. C'est ça aussi Internet...