Bon, je l'avoue, je suis intrigué par la quantité d'"éléments spéciaux" présents dans un jeu aussi vieux que "Manic Miner" contient, et la difficulté que j'ai à trouver une manière convaincante de réaliser la même chose dans mon moteur de jeu actuel. Du coup, j'ai mis la main sur une ré-implémentation du jeu en Visual Basic. Voyons donc comment les blocs-qui-disparaissent-quand-on-reste-dessus ont été gérés ...
Block types are encoded in a separate array, with one byte per 8x8 tile. One such type is "crumbling floor". Other block types include B_AIR, B_FLOOR, B_WALL, B_CONVEYOR and B_NASTY (two of them) and B_SPARE (for switches). Jet Set Willy only has one B_NASTY type, and the other one is converted into B_SLOPE. This is consistent with my own engine.' block type constants Private Const B_CRUMBLINGFLOOR As Byte = 2
Carles a construit son moteur de Willy de manière à réutiliser les données du jeu telles quelles -- sans être le code original sous Z80, ça donne malgré tout une bonne idée de ce qui aurait pu être fait. En l'occurence, par exemple, la structure de chaque niveau est donnée par un tableau de la taille de l'écran, indiquant quels graphismes utiliser, mais aussi le type de chaque bloc entre 0 et 7.
B_CRUMBLINGFLOOR est celui qui nous intéresse. En cherchant "crumbling" plus loin dans le code, je tombe donc sur la fonction DoWilly (extrait ci-dessous) qui gère toutes les interactions entre Willy et le monde qui l'entoure. DoConveyors ne fait qu'animer des blocs, de même que DoGuardians se contente de déplacer les monstres. Ce sont les sous-fonctions de DoWilly qui détectent les collisions et altèrent le déplacement du personnage. Exactement le genre d'approche que j'utilisais dans Calimero et Bilou en QuickBasic.
What's interesting (for me :-) in Carles' approach of redoing Willy's world is that he operates directly from the tape file of the spectrum, so not only it has the "readability" of modern BASIC (i'm not that much into Z80 assembly ^^") but it still explains the logic of the original game (how switches, witches and stuff are encoded).
The DoWilly() sub shown above proceed step by step, handling interaction of Willy with every item "present" in the game. That is, we have DoConveyors or DoGuardians as well, for sure, but they merely perform animation and movement job. WillyCheckConveyor makes sure conveyor pushes Willy. That's the real job.If (.mode = [eWalk]) Then If Not (WillyCheckFeet()) Then ' code for falling stripped out ... End If Call WillyCheckConveyor(keys) Call WillyCheckCrumblingFloor End If
Let's thus have a look at WillyCheckCrumblingFloor just below ...
Voyons donc
WillyCheckCrumblingFloor
dont le code est ci-dessous. Après s'être assurée qu'il y a bien un bloc friable sous les pieds de Willy, elle va utiliser FXCrumblingBlock pour procéder à l'animation (décalage du tile d'un pixel vers le bas) et transforme les propriétés du bloc donné en "B_AIR" si FXCrumblingBlock lui dit de le faire à travers la variable f
.o = .x + (.y \ 8 + 2) * 32 For c = 0 To 1 If (m_RoomBlock(o + c) = B_CRUMBLINGFLOOR) Then Call FXCrumblingBlock(m_DIBBack, 8 * (.x + c), .y + 16, CAPaper(m_RoomData(o + c)), f) Call FXCrumblingBlock(m_DIBMask, 8 * (.x + c), .y + 16, I_BLACK, False) If (f) Then m_RoomBlock(o + c) = B_AIR Call FXRect(m_DIBBack, 8 * (.x + c), .y + 16, 8, 8, CAPaper(m_BlockCA(0))) End If End If Next
FXCrumblingBlock
will not be shown here, because it's a pretty dirty function that mixes up game logic, tile animation and rendering engine commands. What I can tell you is that everytime it is invoked, it scroll downs the data of that specific tile, and insert a "blank" line at the top. Once this is done, it scans the whole tile again and sets the "cleared" flag (variable f
) to false if it found any non-blank pixel. That's precisely what triggers transformation of B_CRUMBLINGFLOOR into B_AIR.As the tile "crumbles" exactly one pixel per frame and Willy walks one pixel per frame, it means if you simply walk on crumbling floor, it will be completely crumbled when you're done walking.
Pour moi, c'est là que le bât blesse: FXCrumbblingBlock mélange allègrement rendu vidéo, manipulation des animations et logique du jeu. Je ne la reprend donc pas ici, sachez juste qu'elle décide si oui ou non l'animation est finie en parcourant les pixels qui viennent d'être édités. Si tous les pixels sont "transparents", c'est qu'il n'y a plus du tout de sol et on peut remplacer
B_CRUMBLINGBLOCK
par B_AIR
.Là-dessus, je vous laisse bras-dessous: il est temps que je prépare ma pitchounette à aller rechercher ma fée à Belle Ile. Ciao.
...j'ai toujours appelé mon fidèle mineur "Manic Miner" et non Willy...sur ZX Spectrum 48 k s'entend...
ReplyDeleteah. Bin moi, j'appelais le dromadaire mutant de "Revenge of the mutant camels" 'super-chameau'. La page wikipédia m'avait donné l'impression qu'il s'appelait génériquement "miner willy".
ReplyDelete