Thursday, April 24, 2025

"Why am I doing this?"

It's not unusual to ask yourself the question among indiedev. What struck me is that the question was raised this time by someone who's been interviewed by Pix'n'Love and makes games with his son: Dale Coop.

There are moments when I wonder, “Why am I doing all this?” It takes so much time, few people care, and it brings nothing in return. The majority of people don’t even know it exists. Should I just move on to something that makes more sense for my life and family? That’s where I am today 😔 -- Dale Coop

I know that feeling. I relate it to those time where you feel the urge to eat, but nothing you eat seems to quiet it. Because actually, I need to eat something different (sometimes more fruity, sometimes more crunchy, ...) Sometimes gamedev is satisfying, sometimes we need something else.

What tend to make me wonder "why am I ..." is the overall dsgametools approach. 20 years past the introduction of the NintendoDS, and despite my first game on the system is now about 15 years old, none of my relatives have really picked up the tools and start making their own PPP games with them. It is heartwarming to read veteran artist say "your tools are perfect and tailored to your needs", yet

  • basic *EDS tools apparently feel repulsive to friends and nephew and will be lacking to professionals
  • conversion tools are so tricky to use, you'd better consider them inexistant
  • I've got nice IRL chat sessions with my son about the game design overall, but pencil drawing is none of his hobbies so I'm left with all the job anyway
  • mixing script and C++ code in the engine doesn't feel that useful when I'm the only developer anyway. It makes many debugging sessions more complicated that they should because you can't really single-step the GobExpressions

I've got something running, but it is far from perfect and it gives me the feeling that I've made my own life overcomplicated. Nobody would use scripted state machines in a platformer. Or if you really want editable behaviour, you'd go for something like Fury of the Furries

Nobody ?

Well, I've encountered some github project to decompile the original Rayman title on PSX. I was looking for the code of that tricky-to-beat bandlands bug, and I got intrigued by some of the GO_SPEED, GO_LEFT, etc. you could find in the "top" function DO_MIT_COMMAND. No reference to that anywhere else in the codebase. I was also puzzled by the "skipToLabel();" calls. Digging through references, I end up with just one big "load" function filling all the commands together with other loads for the level... So they're not just some data part of the game engine.

I couldn't find anything like "Rayman Level Format" as I hoped, but I found Ray1Map ... the website that pretends to be a Rayman 1 level editor, and that's nearly as good as far as I'm concerned.

And there, we can view the commands for each individual enemy in the game. Some of them will be delivered to per-enemy handler (like LEFT % and RIGHT %), many will affect variables that those handlers can check and manipulate (especially enemy state), but there's also a whole set of flow control instructions for loops, branches, and even subroutine calls. And as you can see, the programs are already quite sophisticated. But that was used, and not only by that game (and its numerous ports), not only for other Rayman games (like the designer kit or the Junior series), but for dozens of unrelated platformers until the GBA era... or so does the Readme.md file suggests.

So well ... let's say that for 32-bit consoles, that approach makes sense, and recreating a game engine that deals with such abstract code at runtime isn't a bad idea. I just need to give myself better tools to address the debugging aspects... like presenting the whole thing as the debugger for a virtual machine that does not exists ?

Wednesday, April 23, 2025

appleman 2.0.1

A little bit of work on the Appleman last week-end (at last, you could add and I wouldn't blame you). I've got the "shocked" animation revised, added "carried" animations and gathered infos about where these are in green.spr.

I'll still need to see why there is no "bounce" when it is shocked (reason: it's just using stopper and the animation is supposed to do the job) and patch the greent.cmd level script on the SD card of DarkneSs, because it still show the appleman with big purple punches instead of feet. (appleman.cmd must be correct, since level 2 doesn't seem to have any similar issue).

Voilà donc enfin le moment que je prends pour compléter les animations et le comportement de l'Appleman pour le projet Dreamland. J'ai corrigé l'animation "étonné", j'ai ajouté les animations "transporté", tout ça attend dans un petit fichier green.spr le prochain passage du WiFi. Je note au passage que le fichier "greent.cmd" qui décrit le premier niveau des "3 salles" a besoin d'un petit rectificatif pour ne plus me montrer un appleman aux poings mauves ^^".

La prochaine étape sera d'ajouter les animations des "pieds perdus". J'ai aussi retiré la commande de boucle pour l'animation "assommé", mais j'arrive trop tard: c'était bon pour compléter le comportement "Apple Assault" où les applemen se réveillent seuls, mais c'est inutile pour le comportement construit à partir du fichier "blador.cmd". Car oui, le nouvel appleman est plus ou moins la fusion des deux.

So let's add tonight "undead feet" animations, check a "do not loop stunned animation" that must be over 1 year old in my notebook. I've got another notebook where I've written down blador's behaviour ... let's merge that into appleman's script and we'll cleanup the resulting code mess once the home mess is tidied up.

edit: adding the wandering feet turned out extremely annoying. They're one-sprite objects, unlike most of the things I animate with AnimEDS, and it seems the software still handle that in a very different manner: touching an sprite in the side panel adds a frame with that item, rather than changing the current frame. It also breaks relationship between timeline, frame editor and buttons in general. I'll have to get that fixed: it really breaks the user experience...

edit': pick up works, stun works, wandering feet work. Apple/water interaction is a catastrophy, throwing only work from times to times, and there's something odd when you stomp on a stunned apple (blador acted as a platform there, appleman won't). That feels like it should roll instead ... A good thing animation 2.0 freed some frames ;)
 

Saturday, April 19, 2025

I want to try your editors so much!

How could I resist to such a quote ?

Adeline Venture (hehe) in Shadow Of The Temple The puzzle platformer I really, really want to make some day.

I want to try your editors so much! But in order to finish, I will have to do it in an engine I already know well. Probably construct3 -- CastPixel

It made me want to pack a set of my dsgametools with contents of Castpixel's mockup pre-digested into a .spr file so that she could directly toy with the level editor ... perhaps also convert the tutogit scripts so that she'd get something playable!

So first thing to know is that SEDS works with 16x16 blocks. There is a perl script that can convert the mock-up into tiles but if used directly, it will be a complete mess as game assets.

  1. ensure things are aligned on the 16x16 grid as much as possible. That means the ladder half-way over pillar must be shifted. A few other things needs similar shifting on the mockup.
  2. SEDS shows you 64-pixels slices at once. The scripts *can* handle wider pictures, but at the moment, they'll scan e.g. first row of 256x16 pixels and output 4 64x16 rows in the first page, then another 4x64x16 chunk etc. The result is barely usable, again, because many objects bigger than 16x16 will be de-aligned and will need to be re-aligned in the DS editor.
  3. So instead, you may want to turn the mockup into a 64x* image where things are where you want. Todo: imlib2spr.pl should be able to scan the image in 64px-wide columns itself, so that this step becomes useless and the mockup remains readable.
  4. The script may remove the background color, but when it does so, it also deletes fully background blocks from the output file. This is nice to avoid redundant data, but again, it screws up alignment on such a mockup. You can scribble something on those blocks or you may turn off the background color by giving another one with --bgcolor=ff00ff. Todo: have the imlib2spr.pl tool inject empty slots on the sprite page when it encounters such full-background blocks, to preserve alignment
  5. B u t if I use --bgcolor=some-color, the tool will inject a fully-transparent block as block 0. This is required for proper operation of the game engine and the level editor, but this is useless on the sprite pages. And worse, having block 0 editable led to corrupted files in the past. todo: patch the tool so that the empty block is never used by the generated pages (and never allocated by the editor :P)

With all that taken into account, with a 64x* png file with the content of the mockup aligned on a 16x16 grid as often as possible, conversion is performed with 

SpriteEditor/bin/imlib2spr.pl cast-a-venture2.png venture.spr --nomap --nopack --blocksize=16

And the reverse operation to see how things went is

SpriteEditor/bin/spr2png.pl venture.spr /tmp/venture.png && display /tmp/venture.png

Once that looks fine, copy the venture.spr file on your SD card in the /moving/ directory, make sure you have SpriteEditor for DS at the root of your SD card and launch it.

  • once launched, press START to enter the FILE screen
  • click the |/_/ browse button to show the contents of /moving/
  • if venture.spr doesn't show up, hold L trigger and touch the "UV" button on the alphapad to filter the list of files. (holding L lets you enter the second letter of each "button").
  • touch the "venture.spr" name to load the file, then press START again to return to the edition grid.

 

Wednesday, April 16, 2025

climbing ... manuscript notes.

Quelques notes qui datent de février 2013 et qui refont surface pendant les habituelles chasses de paperasse de début juillet: comment s'y prendre pour que Bilou puisse se balancer aux signets de la school zone.

J'y note la recommandation que les morceaux de signets soient passifs dans la collision et un peu de math pour déterminer si une zone de collision classique croise ou non une "ligne" de collision, qui conviendrait mieux pour les cordes qui pendouillent.

Par contre, je ne sais pas trop dire si j'avais prévu que le signet soit fait d'un seul Gob avec une zone de collision pour chaque élément ou de plusieurs gobs ... la pages avec les lapins vont plutôt dans le sens "un seul gob", chose que le moteur "Dreamland" ne saura pas encore gérer, je dirais.

On y trouve un

state% : 3D.% {
  using RopeController;
  segment [*] F_ROPE;
}

pour un nouveau type d'objet basé uniquement sur du rendu 3D. Le fait qu'on indique des collision pour chaque segment renforce l'hypothèse d'un seul GOB composite d'un nouveau genre. On lit d'ailleurs, sur la première page

foreach (@segments):
   if (b.ymin > s.ymax || b.ymax < s.ymin) continue;
   if (s.dx * s.dy >= 0) {
     // depending on the rope's direction, there's 2 corners of the bbox to check
   } else {
     // test the other two, I presume :P
   }
   

Et une observation que "bah, peut-être qu'une verticale plutôt qu'une ligne oblique, ça ne gènerait pas tant que ça dans la plupart des cas. 

Bref: c'est confus, même pour moi, mais je veux l'avoir sous la main dans le même tag que les autres

Hi English readers. These are manuscript notes from about 12 years ago, when I first tried to figure how to deal with swinging bookmarks that you could catch and climb to. They're a bit confused and I'm unsure even I understand what's being said there. But I've got bookmarks and climbing goal revived for Bilou's Dreamland, so I'd rather have these notes around when I'll think about it. The code snippets I typed above suggests that bookmarks were intended to be a new type of segmented 3D object, which has been dismissed for the Dreamland engine

Tuesday, April 15, 2025

gravity.flow ?

Je voulais faire tout autre chose, mais au moment de prendre le code en main, je me rends compte que j'ai une série de modifications qui n'ont pas encore eu droit à leur commit ... et que je ne sais plus trop à quoi elles correspondent.

Il s'agissait en réalité de deux modifications liées à l'eau: animer la surface (nager si bien avec un miroir en guise de surface, c'est un peu dommage ...) et faire en sorte qu'on puisse placer un jet d'eau dans une grotte. Parce que vous ne ça n'aura pas manqué de vous faire tiquer: il y a une sorte de rectangle moche au pied du geyser sur l'image ci-contre/dessus. C'est lié au fait que le geyser (tout comme la cascade) est obtenu en par une combinaison des deux couches de décor: l'une avec une animation de type "palette cycling" et l'autre avec une animation conventionnelle. Et donc pour mettre le geyser dans une grotte, il me faut deux nouveaux blocs "décor de geyser fusionné avec le décor de grotte".

After a fairly busy week and significantly busy Saturday, I wanted to try updating the Appleman behaviour, but I found my homebrew directory with different files uncommitted and changes involving binary files like maps. So I started by running the current code first on the emulator, and visit those maps to see whether there were any changes. And oh, of course. First change was animating the water line (see the mastodon video below). Second was an extra water jet in the second green map.

Quand je dis "je ne sais plus à quoi elles correspondent" (y compris une modification du code qui assure le palette cycling), comprenez "il a fallu que je fasse tourner le .nds pour m'en souvenir". Ce qui m'a donné envie d'en faire des petites captures (un jour après le ScreenshotSaturday ... pas de chance ^^"), et sur une de ces captures, on remarquait quand-même fort que le haut du geyser reste en permanence au même emplacement. Moi, j'aimerais qu'il monte et qu'il descende, pour ajouter un peu de dynamisme à la scène, et appeler à l'interaction.

See on that level editor, waterfalls and geysers are made of two layers of tiles combined. But that means you can't put a geyser over a dirt wall unless you've got tiles showing that in first place. Plus I'm using another palette slot for the dirt wall than the default one, meaning the cycling code had to be updated. That was ready for some screen-shotting

J'aurais peut-être pu utiliser le contrôleur "grid" de furblock, mais tôt ou tard, il faudra aussi que Bilou soit propulsé vers le haut par le geyser. Plan B: utiliser le même mécanisme de "flow" dans le contrôleur gravity que celui codé pour swim. Je profite donc que tout le setup wifi est là pour modifier le niveau et je définis un nouveau type de tile (les ^ mauves). ça donne des résultats rigolos avec Bilou, mais en réalité, ça ne marche pas: Bilou est bien ralenti quand il arrive dans le haut du geyser, il peut même remonter légèrement, mais au final, la gravité lui donne une vitesse suffisamment élevée (on peut aller jusqu'à 6px/frame) pour qu'il redescende, puisque le geyser le fait monter à une vitesse constante de 2px/frame. Bref, c'est bien pour des tapis roulants mais pas pour des geysers.

But then, the top of the geyser was very static ... I want it to wave up and down a bit. There are different ways I could do that in my engine, but only a few where not only the geyser top but also Bilou is lifted up when in contact with the stream. That implies a mechanism similar to the water flow designed last year, except this new special physics tile will define a property for the gravity controller instead. It will still be an "AIR" tile, though: we can fall through geyser, not swim them. (I hope to avoid nasty corner cases that way).

Unfortunately it didn't work the way I wanted. Lifting Bilou by 2 pixels (cyan lines on the diff) is fine as long as the vertical speed is lower than 2 pixels/frame downwards. It gives a nice boost when jumping and catches you when you're "stomping" the geyser, but while you're being stopped, your intended velocity keeps increasing, and at some point, you'll be fast enough to reach the ground again. Exactly as you start sprinting backwards on a conveyor belt.

So I ended up using the yellow code instead: directly change the polarity of the gravity based on the sign of the terminal velocity stored as a per-tile-type property. Not perfect, but close enough for now.

Mais en fait, il n'y a pas tant à changer que ça: plutôt que de déplacer Bilou, on va utiliser l'information stockée pour contraindre la vitesse maximale ... et tant qu'à faire, inverser la poussée si la vitesse maximale est négative. J'ai pris des vitesse identiques pour la gravité et le jet d'eau pour le "petit nuage" en haut du geyser, ce qui lui donne un mouvement symétrique alors que pour Bilou, la gravité lui permet d'acquérir une vitesse jusqu'à 3 fois plus grande, et il a donc tendance à s'enfoncer plus dans le jet d'eau. ça suffira pour le premier jet ;-)

edit: valeur maximale -2px/frame validée: il suffit de garder le bouton de saut enfoncé pour décoller bien au-dessus du geyser. Et si on tombe du sommet, on ne redescend pas trop bas.
 

Post by @PypeBros@mastodon.social
View on Mastodon

Saturday, April 12, 2025

Gamebrew / platformers

Somebody on gbatemp surprised me back in 2016 claiming (about School Rush)

HOLY CRAP! I'm surprised to see an actual game here, because usually most DS Homebrew is just shitty abandoned tech demos. Nice job on this! I'll check it out soon.

I dug that one again not so lately after School Rush finally got its Gamebrew Wiki entry and it felt hard to believe given the 1394 other entries the wiki has just for NDS games. There had been some unfinished titles for sure that had just enough contents to rank fairly in seasonly "coding" competitions, but there had also been brilliant titles. It was just after I ran into some "7 best DS games" that would only mention a few FPS and then non-game homebrews... I can't review all 1394 games, but I sure could give the "platformers" category a spin

"Sonic, the game" defines quite well the first category: graphics ripped from various 2D titles in Mario and Sonic series, unfinished physics and uninspired level design and no sound whatsoever. At least it demonstrates scrolling in large levels with parallax effect for the background layer.

Monky. One-screen collect-and-progress game. You'll have to backtrack if you missed some letters on the way. You'll lose all the collected bananas if you get hit. 1 monster type, 4 levels (as far as I can tell). (Unrelated) background music featuring a mod player and a few sound effects.
A nice tech demo using PaLib and graphics ripped from DK Jungle climb GBA game, but not very inspired as far as game and level design goes.

I did not pass level 1 on first play. I missed a key gamedesign element: as you keep moving forward, you'll enter a sort of "run state" where you jump higher. There seems to be 4 worlds of 5 levels each ... that would be worth playing more before rating the quality of level design. You've got sound and music, but if you've played some pinball titles on the Amiga, you'll immediately recognize the style and honestly, it doesn't quite fit the coconut plains of the first levels. 

Temple Topple could have been featured in our "Biloutris" project, I guess. Block falls, they disappear if they line up, but you can't move them (at least, I don't think so). You do have to avoid getting crushed, though. Don't expect much variety as you play. None of the little things that can make such a "climbing" game really funny.

Starting a game has a significant chance of being unfair. Once you're one or 2 screens away from the bottom, there's little chance of getting crushed, and in between, there's a good chance you'll have to wait for the next jump option to show up. I gave up around 1300 pixels high, out of boredom. I would bet on looped WAV/MP3 sample for the background music. It might have been the author's hands-on title for DS Game Maker...

I tried Epic Caveman, too, and understood why the wiki entry only lists the title screen. The title is an endless runner, somehow akin to the "running zilla" game offered when a chrome browser cannot connect to the internet. But here obstacle are quite large, right form the start, requiring very precise timing to clear the jump over them. You can't jump "on" them either, which doesn't seem to make sense in this context. An there will be sudden speed up, requiring you to adjust the tediously learnt timing on the fly. Not even between series of blocks but *within* a series.

There's some sound but nothing really impressive. I'd put it in the category "mini-game of an afternoon, to check you've understood how to use assert import and can structure your project with different screens around the main game screen. Good for a programming tutorial if you had the source, but hardly interesting as a game, although - unlike "sonic the game" - there is coherency and care to detail here.

edit: okay, this is what "sonic the game looks like. and you don't see the fact that if you nearly land on a "platform", it will push you backwards so you can safely fall down instead of remaining balancing on a few pixels. That reminds me why the real sonic has *two* vertical sensors, and not just one. 

(yeah, I hesitated to dedicate 280KiB of blog storage to show that, and I certainly didn't want it to become the post's thumb picture)
 

Sunday, April 06, 2025

Ressortir la supercard ?

Rédiger ce post à propos de Kirby and the Amazing Mirror, ça m'a de nouveau donné envie d'y rejouer évidemment. Et pourquoi pas sur SuperCard, au fait ? après tout, ça a plutôt bien marché pour Goodboy Galaxy et le jeu "Professor Sinister" de Simian Zombie il y a quelques années ? Et pour pas mal de titres dont Prehistorik Man avant que je ne me lance dans le développement NDS (et que je n'achète mes premiers jeux NintendoDS) ...

Mais à l'époque, j'avais un vieux Windows en plus de mon système Linux, et je pouvais y faire tourner le patcheur de ROM du constructeur (Supercard, donc). Pendant des années, plus moyen de convertir des ROMs et donc plus moyen de jouer à des jeux officiels à travers mon linker GBA. Mais en creusant hier, je note qu'il y a finalement une version open-source tournant sous systèmes UNIX du patcheur en question!

Voilà près de 20 ans que j'essaie de le trouver en boutique de seconde main et qu'on me répond "ah, très bon jeu, mais on ne le voit presque jamais ici" ... donc je tente...

Une fois patchée, la ROM tourne bel et bien ... j'ai omis d'ajouter le patch permettant de relayer les sauvegardes, donc si la cartouche est laissée hors-tension un peu trop longtemps, elle perd la partie en cours. Plutôt gênant pour ce jeu précis. Plus problématique encore, le jeu souffre de ralentissement. Je suis tombé sur un article qui explique assez bien le problème: dans la supercard il y a une RAM à la place de la ROM des cartouches classique, qui fait le "tampon" entre la console et la flash (il faut compter pas loin d'une minute pour charger le jeu depuis la flash) mais elle n'est pas aussi rapide que les meilleures ROM gba. Pour compenser, le patcheur va forcer le CPU à attendre le nombre maximum de cycles d'horloge à chaque lecture sur la cartouche. Et ça, avec Kirby, ça se traduit par des chutes à 30 fps trop souvent. Le jeu n'a évidemment pas été conçu pour ça et l'action est donc ralentie plutôt que saccadée.

On se dirait bien que "bah, ça laise quand-même la possibilité de faire du pixelstudy" ... sur DS peut-être. Sur l'écran de la Gameboy Advance SP que j'ai utilisé, franchement, ... c'est trop petit ^^"

 

Saturday, April 05, 2025

#20games part 4

Okay, I've covered all the games that had influenced me before I started working on Bilou ... I've covered those who influenced me while I was working on the BASIC edition. Now let's see those games who have influenced me reviving the project: those at the roots of the NDS revival.

The first of them all has to be Pixel's Cave Story ... The game that opened my eyes showing me that, yes, a single person could be crafting a whole game (not a mere 3-levels demo) that feels and plays like a game with original contents. All you need to do is stay modest on the technical side (2D, no realistic shading, SNES-like physics) and artistic side (pixel art, tracked music, possibly even chiptune).

Not only I could make it, but there was a huge community enjoying and creating around it.

On a fait le tour des jeux qui ont influencé la conception de Bilou et ceux qui ont eu un impact sur le développement de la version BASIC. Attaquons-nous à ceux qui sont à l'origine de son reboot. 

Heureusement que je l'avais bloggé, parce que sans ça, je n'aurais jamais retrouvé que la découverte de Cave Story s'était faite à un moment ou je trempais déjà dans le développement NDS, mais encore rien de décisif. Juste quelques éditeurs. Mais de découvrir qu'un gars écrivant tout seul un petit jeu "comme il aurait voulu pouvoir y jouer étant jeune" est parvenu à créer un phénomène mondialement reconnu en travaillant dessus 5 ans ... juste à condition de travailler à la frontière de sa zone de confiance ... ça fait réfléchir. Et le mois d'après, je suis tout à coup occupé à parler de BilouDS ...

But before I discovered Cave Story, I was playing Kirby's Amazing Mirror, and that sure had an impact on how I approached larger game, with suspended power-ups that could use to unlock secret paths later on. Okay, Kirby's Dreamland had an impact back in '93, although limited since Bilou's formula had been defined when I got my hand on the game. But as far as game design was concerned, K:AM will remain my personal reference possibly forever. How you use treasures to unlock new moves for your abilities ... how a few locations are revisited to find routes to new areas ... it is almost impressive that it features Kirby at all, given how deep the adventure is. And it works so much better than Megaman approach of a complex world ...

Like Rayman did, Kirby has also a "negative" influence, in that Bilou must remain distinct from Kirby. Does Kirby wear hats when he changes power ? well, Bilou will have to do something else.

Mais le jeu qui avait captivé mon attention juste avant que je ne me lance dans le développement DS, c'était Kirby and the Amazing Mirror ... la perle introuvable. Je serais curieux de mettre la main sur une map de l'ensemble des "routes" possibles dans le jeu tellement j'ai tourné dans ce labyrinthe des miroirs, à tenter de conserver un des power-ups suffisament longtemps pour pouvoir débloquer les chemins que je n'avais pas encore exploré. C'est de là que vient l'approche actuelle des power-ups pour Bilou, même si le fait de jouer à Megaman X m'avait donné la conviction que l'idée "un bouton pour passer d'un pouvoir à l'autre, des jauges d'énergies à remplir pour s'en servir" ne marcherait pas terriblement.

A l'opposé de Cave Story, on pourrait trouver Shantae: Risky's Revenge sur DSi. Le jeu qui rassemble des talents comme Henk Nieborg dont le pixel art me sidère depuis Lomaxx et Virt dont la musique me scotche depuis bzam/zzap : '01. Le jeu est sorti en 2010, le travail sur Bilou a déjà pas mal avancé ... Mais les éléments de décor sont énorme, le jeu se permet du multi-plan avec pré-visualisation de ce qui nous attend pour la suite, un panel d'objet complémentaire qui n'a rien à envier à un R-Type ... le moteur de jeu a certainement besoin de ruses de demoscèneur pour animer tout ça et gérer les va-et-vient dans la mémoire vidéo. Une référence, certes, mais une référence inateignable. Une étoile polaire plus qu'un phare d'Alexandrie ^^"

One last key game from that period was Shantae: Risky's Revenge. The game I wanted to have because it was the work of talented artist I'd been admiring for over a decade. Even more than the first Rayman, it is a game I have no way to immitate. The level of detail in the graphics, the quality of the animation, the soundtrack, the technical level of the programming, with that multi-plane platforming where you hop into the background and back to find your way out of a maze... I know if I want to have a game finished some day, that implies accepting that it will not beat Shantae. And to some extent, it isn't an issue: you don't need your game to beat another one as long as it is interesting in itself.