Tuesday, February 20, 2018

Ideas for a handwriting recognition on DS


Il y a un moment que je retourne l'idée dans ma tête : un système permettant d'écrire librement (du code, pour l'éditeur de comportements) sur DS. Le système serait basé sur une grille 3x5 visible par l'utilisateur. Parce que les claviers virtuels, c'est pénible et qu'un système qui autorise l'utilisateur à écrire n'importe où et n'importe comment, ça n'aura aucune chance de marcher avec 66MHz


That is another idea that has been laying on paper for a while. I lack text and script editors at the NDS.  I don't want to go for a virtual keyboard, because they are really too slow to work with. I can't afford a complex recognition system, and even Google's handwriting system would suck on code expressions.

But I feel like it would be easy to recognize letters when they have been written on a grid. A bit like if we were painting a low-resolution font.


Every letter drawn corresponds to a 15-bit map that can be quickly tested against a small database of features and suggest letters to pick when the decision is fuzzy.

 Additional features could be the starting and terminating coordinates, as well as the number of strokes.

Cette petite grille fait que chaque lettre tracée correspond à un code sur 16 bits unique. A partir de ce code, on pourrait rapidement identifier un groupe d'entrées dans une petite base de données qui traduit les traîts en lettre (p.ex. à partir de la position du point d'origine et du nombre de traits). Je ne veux pas me limiter aux lettres, évidemment. L'idée est de reconnaître l'ensemble des caractères ASCII pour pouvoir éditer du code n'importe où le plus facilement possible. 

I hope the result will be an interesting compromise between
- early PDA "one-weird-stroke-to-write-them- all" (Palm's Graffiti system)
- sharp Zaurus "Free-letters-one-by-one"
- OCR from scanned text.


I know segmenting is a complex task in letters recognition. With pre-drawn grids, the user is guided to start a new segment or stay in the current one. We can also tell apart uppercase and lowercase Eg. "p", punctuations, etc. locally rather having to rely on some line-level calibration. And we can naturally move to the next space for the next letter.



Avec cette grille, je m'affranchis d'un des problèmes les plus costauds de la reconnaissance de caractères (la segmentation) tout en permettant d'utiliser le plus naturellement possible l'espace disponible (sur Zaurus, on devait presque toujours revenir au même endroit pour tracer la lettre suivante ou le mot suivant). Et c'est toujours plus pratique à apprendre (encore qu'on pourrait essayer d'apprendre de nouvelles écritures à la DS) d'écrire "comme Pype/Zaurus" plutôt que "comme en Grafiti", même si grafiti avait le bon goût de ne demander qu'un trait par caractère.

Granted, the hand script writing I use when I want maximum readability already separates letters a lot and uses only one stroke for most lowercase. Because I reformatted my writing for the Zaurus already. But it's not like I had a huge user base to take into account ^^".

The granularity of the grid should help making tricky characters like braces-versus-digits-versus-C easier to deal with.

Saturday, February 17, 2018

Histoire d'encre

Eh bien, le fait de se déplacer dans un encrier n'est décidément pas intuitif pour le joueur lambda de School Rush. J'en prends pour témoin les réactions des membres de "e-magination" à mon screenshot:

Le pot d'encre dans lequel sauter, tu l'amènes comme ça dans le [Level Design] ? Parce que j'aurais pas envie de sauter dessus personnellement, il ressemble trop à un piège  ...

Peut-être qu'il faudrait rendre l'encrier plus amical ? Perso avec ce regard, je lui ferais pas confiance. ^^

Another person commenting on the fact that jumping into an inkjet to use it as a bumper/platform is far from straightforward. They aren't wrong, of course. The secondary question was 'how is that introduced in the level design'. I've got a good answer for that one: a not-yet-aggressive inkjet is featured on the intro screen, and the player is invited to jump on/into it to start the game.

Ce serait une approche assez classique du problème, c'est vrai. Mais l'encrier n'est pas amical, sans être pour autant fondamentalement méchant.
Il s'agit d'un gardien, et d'un gardien face à une invasion. il ne sait pas de quel côté est Bilou. Il ne cherche pas à l'aider quand il le projette, juste à s'en débarasser. Il est dangereux (à cause de ses gouttes d'encre plutôt toxiques), pas franchement engageant (parce que entrainé à être gardien), mais peut être utile si on sait s'y prendre. C'est une dimension que j'aime bien (les carapaces de koopa, notamment) et que j'ai envie de développer dans mon jeu.

The easy way out would of course to make the inkjets look friendly, but they aren't. They aren't "evil" either. They're warders. Guardians facing invasion times (from the pendats). They don't know which side Bilou is. They don't try to help when they throw him up, just to get rid of him. Inkjets are dangerous (ink is rather toxic), not welcoming nor appealing (but well, they aren't stewards), but if you manage to work around properly, they can prove useful. I hope this echoes the harmful/useful duality of the koopa shells, which is one dimension of gameplay I especially enjoy and want to dig deeper.

Friday, February 16, 2018

typedef u16 pageno_t

J'avoue que quand j'ai fait ma transition de l'assembleur vers le C, je faisais une mimique assez cocasse à la vue de uint32_t et size_t. Quoi, c'est un 'dword' (double-mot, jargon intel dans les assembleurs). Pourquoi aller lui donner un nom à coucher dehors pareil ? Bref, j'étais pas un fan de typedef, à part pour éviter de devoir écrire "struct" devant le nom de mes structures. Alors rajouter un #include<stddef.h> ...

Mais sur l'année écoulée, j'ai eu droit à plusieurs situations du genre int bitrate. Ah oui? en quelle unité, s'il vous plait, le bitrate ? bit/seconde ? kilobit/seconde ? megabit/seconde ? Et dans le code de mon moteur de jeu, int x ou int width est à peu près pareil. Est-ce que x est une coordonnée absolue (dans le niveau) ou relative (à l'écran) ? est-ce qu'elle est exprimée en pixels ? en tiles (si, si, souvenez vous, les petits pavés élémentaires de graphisme) ? en 256eme de pixel pour les calculs de déplacement avant affichage ?

Alors bien sûr, on peut tenter int kbps, int x_in_tiles, etc. Mais pourquoi. Pourquoi faire rentrer dans le nom de la variable une information (l'unité de mesure) qui dénote plutôt de son type (on peut additionner deux valeurs en kbps entre elles, mais pas des Mbps et des kbps sans faire une conversion au préalable). Bref, j'ai pris l'habitude de construire des types qui expriment des unités de mesure. Beaucoup. Au point que je me méfie presque maintenant du code qui annonce juste un "int" parce que dès qu'on va commencer à intégrer des morceaux de code qui viennent d'horizon différents, on aura aucun moyen de se souvenir si le * 1000 qui est là dans l'appel de fonction est justifié ou non.

Et comme je viens d'atteindre le point ou la branche "revisite pour cause de tutoriel" de mon moteur de jeu est prête à recevoir le code servant à charger des fichiers .spr, ce serait peut-être le bon moment pour y introduire des types comme "numéro de page, numéro de bloc, numéro de tile", etc.

Sunday, February 11, 2018

It's Cube Time!

Among all the hidden anti-cubes of fez, the four ones to collect at the clock tower were clearly the less interesting one. As soon as you've learned how to read your world map aud made your way up to the tower, you know you're missing something and that it isn't in a hidden room.

Parmi tous les anti-cubes de Fez, il y en a 4 à récolter autour de l'horloge, et selon moi, ils sont malheureusement les moins intéressants du jeu. Une fois qu'on a appris à "lire" la carte du monde, on sait qu'on a raté un truc à cet endroit (la petite icône ne disparaît pas), et on sait aussi qu'il n'est pas dans une salle cachée (l'icône est sur le noeud de la tour lui-même, pas un noeud annexe).

You have likely disovered that there is more to do in the game than hunting for cube bits. Some anti-cubes are revealed by moving/stacking blocks, some by reading hints in the levels and turning them into secret codes to input through your game controller, konami-style.
All of these mechanics have been introduced over the "normal" gameplay, through switches, levers to manipulate .and doors with cryptic engraving. Granted, the d-pad language isn't easy to grasp and decode, but it is introduced with simple sequences of turn left/turn right.


Au moment où vous en arrivez là, vous vous serez très certainement rendu compte que la chasse aux petits cubes dorés ne représente qu'une petite partie du jeu. On trouve des anti-cubes en déplaçant des blocs, ou en lisant des indices pour exécuter des "cheat codes" à la manette. Le plus souvent, ces mécaniques ont été enseignées à travers des manoeuvres "normales" pour activer des interrupteurs ou des portes au inscriptions mystérieuses.

The clock anti-cube work like no other in the game. One of them had appeared with no apparent reason, then disappeared before I could grab it. Then I noticed one of the clockish hand was moving and predicted time where the anti-cube Pops. Then the moving hand disappeared as I grabbed the anti-cube.
you will barely notice that all the four hands move, Imho. Not unless you stay idle, not even rotating the world for a few minutes. But why would you? There is a wrapper portal just above the clock and absolutely nothing to keep you thinking nearby. (not even script to translate). The odds that you see another cube pop there while passing by is 1/30 at best. And that map is no hub. You're never returned there. it's not as if it was the village's clock...


Mais les anti-cubes de l'horloge ne sont définitivement pas de ce genre. Tout d'abord parce que pour la seule fois du jeu, il y en a un qui apparaît, comme ça, sans prévenir. puis qui disparaît avant qu'on ne puisse s'en saisir. Je me rends compte qu'il se synchronise sur la seule aiguille qui bouge. je me synchronise aussi, je m'en empare. Par contre, chapeau à celui qui aura remarqué que les autres aiguilles bougent elles aussi (nettement plus lentement, il faut bien dire). Si au moins il y avait eu quelque-chose à faire ... une inscription à traduire .. n'importe. Mais non. Le portail pour le retour est juste au-dessus ... Et il aurait fallu être retardé plusieurs minutes. Et on est pas sur un noeud central, mais en "bout de branche": on ne reviendra pas là par hasard.

Your best hint comes from Dot, actually. But by then, you've learned not to pay attention to Dot's comments. Dot doesn't remember, she's afraid of owls, etc. She's only helpful for basic stuff like knowing what is interactive. When Dot says "it is cube time", its sounds like cheap humour.
And even then, she never says "it is quarter to Cube" nor "half past cube". The link is static, not flowing as the time.
If only that clock was behaving differently from our regular clocks, et with the "hours" hand doing one full revolution over Gomez's day and night cycle, giving you some more chance to understand that you are not expected to find anything to do there, just meet the date...


Notre meilleur indice (sur le fait que les couleurs de l'horloge n'ont rien à voir avec les couleurs des boutons de la manettes et qu'il ne faut pas essayer de lire des chiffres sur l'horloge, etc) nous vient de Dot, le cube volant qui nous accompagne. "C'est l'heure du cube" semble plaisanter Dot. Mais le joueur aura appris -- une fois la phase tutorielle passée -- à ne plus tenir compte de ses remarques. Dot ne sait pas, a oublié, n'aime pas les hiboux, etc. Peut-être aurais-je été plus attentif si Dot avait annoncé qu'il est "cube moins le quart" ou "cube et demie" selon la position des aiguilles ...

Non. Rien de tout celà. Le joueur qui passe une à deux minutes dans cette partie du tableau a entre une chance sur 30 et une chance sur 60 de voir apparaitre le deuxième des quatre anti-cubes de l'horloge. Pour le dernier, il faudra que je repasse mardi, entre 1h30 et 2h30 du matin. Et non, ça n'est pas drôle. Quitter puis relancer le jeu après avoir changé l'heure de la playstation une demi-douzaine de fois non plus. Si au moins les aiguilles avaient avancé "plus vite" (une 'heure' de 10 minutes, une journée d'une heure, etc). Et peut-être un moyen d'entrer dans la tour pour modifier l'heure actuelle sans quitter le jeu ?


Finally, even if all that had been clear, understanding that the anti-cube I need to beat the game will show up next Tuesday between 1 AM and 2 AM is no fun. I really missed some way to enter the clock and start messing with its gears to force the last two cubes to my convenience. That would have felt awesome and fun.

Tuesday, February 06, 2018

gource and reDS

C'est un outil super: gource. Transformer les fichiers logs d'un gestionnaire de versions en une animation interactive où les développeurs deviennent des jardiniers taillant, soignant, élagant, greffant...

Et facile à utiliser, en plus! Bon évidemment, ici c'est assez moyennement intéressant puisque je suis tout seul sur le projet depuis le début ...

Mais au moins, ça met bien en valeur les efforts pour restructurer le code et permettre à d'autres (au cas où) de faire des projets à base du moteur de jeu GEDS plus facilement.
Au passage, j'ai franchi un cap avec le code d'AnimEDS. Les "modèles" sont maintenant activés. Je regrette un peu d'avoir quand même dû passer par l'émulateur et une exécution pas à pas pour corriger les bugs introduits lors du refactoring alors que j'avais des programmes de tests pour l'architecture native juste à côté... mais bon, les erreurs étaient dans le setup des objets, pas dans leur logique.
Maintenant, il reste à sortir la gestion des "callback" hors de la classe "Engine" (je les verrais bien en gestion autonome, avec un objet complètement interne qui assure la gestion et qui est caché derrière les méthodes "register" et "unregister" de la classe-maîtresse). edit: c'est fait.

this is the right place for quickstuff