Parachute HD (META)

En ce qui concerne le score, dont la construction symbolique est dynamique, je m’appuierais sur une simple spritesheet incluant tous les chiffres nécessaires. Par exemple celle-ci (qu’il faudra adapter à la taille des chiffres que tu souhaites) :

7-segments

Nul besoin de t’embêter à afficher chacun des segments !.. Sauf si l’exercice t’amuse :joy:

En ce qui concerne les messages… tout dépend de leur nature :

  • S’ils sont syntaxiquement construits de manière dynamique, tu devras employer la mĂŞme technique que pour le score et prĂ©voir une spritesheet avec l’alphabet nĂ©cessaire, et ce sera Ă  toi de prĂ©voir une fonction de rendu spĂ©cifique qui prend une chaĂ®ne de caractères en entrĂ©e et qui calcule le rendu graphique de la chaĂ®ne sur le framebuffer (très amusant comme exercice aussi…).
  • S’ils sont prĂ©dĂ©finis, et qu’il n’y en a pas plus que de raison, prĂ©vois simplement un sprite par message :wink:

OK. Je vais regarder. J’insérerais les chiffres sur une des planches actuelles car j’utilise 4 planches déjà: Ecran de titre, le fond, la planche_A et la planche_B.
J’avais ajouté un écran de pause mais là, trop gourmand, il n’y avait plus de mémoire.
Après, il faudrait voir s’il est possible de charger des écrans dans une des images, ça pourrait être pratique d’avoir des images ou des spritesheet qui peuvent changer.
Par exemple, on aurait une image “écran” que l’on chargerait avec la page de titre, l’écran de pause ou celui des scores. Pareil, si l’on avait un jeu qui permettait de choisir quel jeu G&W on voulait lancer, on chargerait l’écran de titre, le fond et les planches correspondantes.
Bon en tous cas, merci pour les pistes, je vais voir ce que je mets en oeuvre.
Il faudrait quand même se trouver une solution sympa je pense pour pouvoir “générer” les sprites à afficher pour du texte, ça pourrait servir pour d’autres types de jeux, mais bon ce n’est pas utile dans mon cas. On verra bien quand le besoin se présentera. Pour le moment, je ne suis pas bloqué, je dois juste prendre un peu de temps pour bien finir ce jeu et après je m’attaquerait à Fire, puis comme tu as déjà fait une partie du boulot, je pense que je ferais Donkey Kong Jr. Bon ça fait déjà un bon petit programme, je vais essayer de faire ça avant d’en rajouter d’autres :wink:

Pour cette histoire de sujet clos, effectivement je ne trouve pas qu’il soit très utile de fermer les sujets personnellement. Meme si ta demande ou ta question a trouvé une réponse ça peut etre bien de laisser la possibilité à la discussion d’évoluer ;), d’autres peuvent se servir du sujet pour poser leur propre question, la réponse peut évoluer, etc…

Bon courage pour la suite de ton dev en tout cas, ça a l’air chouette !

Oui après réflexion, je suis d’accord, j’ai déverrouillé. Ce n’est en effet pas utile.

1 Like

Encore une question. Peut-on changer le mode d’affichage en cours dynamiquement pour passer du mode Haute définition à Basse résolution quand on en a besoin (Par exemple pour afficher un écran de remerciements ou un tableau des scores sans trop consommer de mémoire et en plus, autant je peux avoir un écran à charger pour les remerciements mais je dois trouver un moyen de gagner de la mémoire car j’occupe déjà tout, autant je ne peux pas prévoir de sprites pour le tableau des scores, alors je pense au plus simple qui serait d’utiliser les bons vieux print). A moins qu’il y ait d’autres solutions auxquelles je ne pense pas.

Non… Tu dois, dès le départ, déterminer quel sera le mode d’affichage avec lequel tu souhaites travailler.

  • Soit tu utilises l’API standard gb.display en haute dĂ©finition (160x128) (en dĂ©finissant la macro DISPLAY_MODE avec la valeur DISPLAY_MODE_INDEXED dans le fichier config-gamebuino.h). Et Ă  ce moment lĂ , tu peux bĂ©nĂ©ficier de toutes les fonctions prĂ©dĂ©finies par cette API comme gb.display.drawImage(), gb.display.print(), etc. Mais tu es limitĂ© Ă  16 couleurs au total.

  • Soit tu tournes le dos Ă  l’ensemble de cette boĂ®te Ă  outils et tu te retrousses les manches pour effectuer tes tracĂ©s bit par bit sur des framebuffers partiels (les fameuses tranches horizontales qui sont calculĂ©es une Ă  une pour effectuer le rendu global de la surface de l’écran) avec l’API de bas niveau gb.tft. Mais dans ce cas, tu profites des 65 536 couleurs que t’offre l’espace colorimĂ©trique RGB565.

Dans ton cas, la première solution est sans doute la plus simple, d’autant plus qu’avec 16 couleurs t’es déjà laaaarge pour faire du Game & Watch ! Par contre, si tu rencontres des limitations mémoire, il faudra optimiser tes ressources graphiques pour limiter au maximum l’occupation de la RAM au moment d’invoquer la fonction gb.display.drawImage(). Tu noteras au passage, que dans le code que je t’ai proposé, je n’instancie les objets Image qu’à l’intérieur de la fonction qui effectue le rendu de l’élément graphique concerné… De cette manière, l’objet Image n’occupe de la place en RAM que pendant la durée de l’exécution de la fonction ! En effet, tous tes éléments graphiques sont déclarés comme des tableaux d’entiers constants. Ils seront donc hébergés dans la mémoire Flash. C’est seulement au moment où tu crées une instance de Image que les données sont copiée en RAM. D’où l’intérêt de ne pas les faire subsister trop longtemps, sinon tu atteindras rapidement la limite de la mémoire disponible…

En jonglant correctement avec l’hébergement volatile de tes ressources graphiques en RAM, tu devrais pouvoir gérer tous les écrans que tu souhaites sans problème !

En aucun cas il ne faut déclarer tes instances de Image comme des variables globales !!!..

J’espère que je suis assez clair dans mes explications :blush:

Si tu ne l’as pas déjà fait, regarde attentivement le code que j’ai ajouté sur mon GitHub, dans le dossier with-gb-display. Si tu l’as déjà fait, relis-le avec plus d’attention :wink:

OK, bon de toute façon, je continue un peu à coder ce soir et je posterais mon code. Comme ça tu pourras jeter un œil si tu as le temps et me dire si je peux améliorer des choses.
Pour le moment, du coup, je vais essayer de faire le jeu simplement et on verra après si on peut améliorer avec tout ceux qui veulent regarder et qui voudront m’aider à faire mieux. Dans un premier temps, il faut que je termine cette partie du code (le score) et ajouter la fin de partie et le regain de vie a certains scores pour finir le jeu avant de partager le code pour l’améliorer.

OK, version source MAJ sur Github - je fais une MAJ de la création avant d’aller dormir.
La version inclue la gestion de la Pause par A ou B, l’affichage du score et du Game Over.
Bon, il y a un petit bug sur la procédure d’affichage de Pause et GameOver mais pas très gênant et comme il est tard je rechercherais la prochaine fois sauf si quelqu’un trouve entre temps.

Voilà, si vous regardez le code et voyez des améliorations à faire, je prends… :wink:

Hello @jicehel ! Et désolé de te répondre si tard…

Bon, globalement c’est pas mal du tout ! Le rendu est plutôt satisfaisant :wink:

Pour pinailler un peu … je trouve que tu te compliques un peu la vie au niveau du code et qu’on peut le simplifier… mais c’est déjà très bien que tu aies réussi à surmonter les difficultés (surtout d’ordre mathématiques et logiques) liées au calcul de rendu sur les framebuffers partiels !

Je ne vais pas reprendre tout ton code, mais je voudrais néanmoins t’apporter un éclairage sur le bug d’affichage des messages “PAUSE” et “GAME OVER”.

Il a fallu que je fasse un peu de reverse-engineering sur tes spritesheets (car les assets de ton dépôt ne correspondent pas tout à fait aux tableaux d’entiers 16-bits que tu utilises dans ton code). J’me suis fait un p’tit script rapidos pour reconstruire l’image originale que tu as transcodée pour obtenir ton tableau SPRITESHEET_A, que voici (agrandie 2x) :

Pour l’affichage des textes, la méthode de calcul du rendu diffère légèrement de celle utilisée pour isoler les autres sprites. En effet, les sprites sont déjà positionnés sur la spritesheet à l’endroit où ils sont censés apparaître à l’écran. Mais ça n’est pas le cas pour les textes… d’où la nécessité d’appliquer une autre méthode de calcul. Pour cela, j’ai écrit une nouvelle fonction drawText() en modifiant légèrement ce que j’avais fait pour la fonction drawSprite(). Cette nouvelle fonction drawText() vient remplacer ta fonction drawSpriteXY() (que tu peux fouttre à la poubelle du coup :joy:).

En premier lieu, j’ai relevé une petite erreur de positionnement (en y) de ton texte Sprite_pause. Tu peux corriger la ligne 124 ainsi :

Sprite Sprite_pause = { SC_A, 1, 9, 28, 7 }; // y = 9 et pas 8...

Ensuite, modifie la ligne 445 ainsi :

// remplace :
drawSpriteXY(Sprite_gameOver, sliceY, buffer, 53, 60);
// par :
drawText(Sprite_gameOver, sliceY, buffer, 53, 60);

MĂŞme chose Ă  la ligne 456 :

// remplace :
drawSpriteXY(Sprite_pause, sliceY, buffer, 66, 60);
// par :
drawText(Sprite_pause, sliceY, buffer, 66, 60);

Puis remplace ta fonction drawSpriteXY() Ă  la ligne 577 par la nouvelle fonction drawText() :

void drawText(Sprite sprite, uint8_t sliceY, uint16_t* buffer, uint8_t x, uint8_t y) {
  if (sliceY < y + sprite.h && y < sliceY + SLICE_HEIGHT) {
    uint8_t xmin = x;
    uint8_t xmax = x + sprite.w - 1;
    uint8_t ymin = y < sliceY ? sliceY : y;
    uint8_t ymax = y + sprite.h >= sliceY + SLICE_HEIGHT ? sliceY + SLICE_HEIGHT - 1 : y + sprite.h - 1;

    uint8_t  px, py, sx, sy;
    uint16_t color;

    for (py = ymin; py <= ymax; py++) {
      sy = py - y + sprite.y;
      for (px = xmin; px <= xmax; px++) {
        sx = px - xmin + sprite.x;
        color = SPRITESHEET_A[sx + sy * SCREEN_WIDTH];
        if (color != TRANS_COLOR) {
          buffer[px + (py - sliceY) * SCREEN_WIDTH] = color;
        }
      }
    }
  }
}

Tu vois que le calcul est légèrement différent pour aller chercher les bons pixels sur la spritesheet.

Tu peux recompiler et exécuter ton code sur ta META, tu verras que cette fois, les textes “PAUSE” et “GAME OVER” sont correctement reproduits :wink:

D’une manière plus générale sur le rendu global du jeu, plutôt que de multiplier les “écrans” et les personnalisations ostensibles, j’aurais personnellement préféré que tu essaies de reproduire le plus fidèlement possible la planche LCD originale :

Fais du Game & Watch jusqu’au bout :wink:

Mais globalement, c’est un bon résultat pour une première virée dans la dark side of gb.tft…

Cool. Pour la planche unique c était compliqué car les rectangles qui entouraient les sprites se recouvraient alors j aurais pu les réduire mais je voulais garder les sprites le plus gros possible

Merci pour la correction de la fonction. J aurais dĂ» y passer du temps je pense et pour le moment je ne m y suis pas encore remis.

Je fais la man et j ai pensé à une solution: recréer la fonction print en intégrant les caractères et quelques ponctuations. Ca permettrait de générer facilement l ecran de menu et de remerciements. Une fois le jeu fini dans sa première version, j essayerais.
Merci pour ton aide et n hésites surtout pas pour les conseils comme de toute façon je passerais plus de temps sur ce premier g&w les prochains allant réutiliser bcp des mêmes fonctions

Je t’avais déjà apporté une réponse concernant la possibilité d’utiliser une spritesheet unique…

Pour les sprites dont l’enveloppe rectangulaire a une intersection non vide avec celles de ses voisins, il suffisait simplement d’utiliser une autre couleur pour les distinguer. Dans tous les cas, au moment du rendu, le code couleur à utiliser pour écrire dans le framebuffer sera le noir 0x0000, donc tu peux te permettre d’ajouter une propriété à la structure Sprite qui correspond à la couleur qui le caractérise sur la spritesheet de manière à pouvoir l’identifier facilement au moment de sa copie lors du calcul de rendu.

Quant à la fonction de rendu d’une chaîne de caractères, c’est un bon exercice auquel se frotter :wink:

Oui, j’avais lu ta solution mais après avoir fait les 2 planches, comme les sprites étaient fait et que c’est un peu long, je ne l’ai pas refait mais c’est noté pour les prochains jeux, c’est une méthode que j’essayerais.

Aaa. Now it’s my turn to test a new game. We will see how it works :slight_smile:

1 Like

Great! Nearly like the original game. Any option planned to save highscores or have more of this (like octopus or DK Junior?)

Hello, atm has Steph had made a part of the job and that he will continue it in a tuto, he will make Donkeykong Jr. Me i planned to adapt Fire as the game already exist in normal res, i’ll take a part of it to manage the gameplay but i’ll change some things first to use the same structure that the one Steph made because i like it and because i have my own vision of the game… :wink: Else i manage to port Judge and Ball 2 old G&W games.
I planned no other game atm as if i planned too many, it’s will take time and as Steph will make a tuto, some will probably take some of these old cool games to port them (octopus is a good example, but there are alot).
For the game, i have to make some clean on the program and wait for steph tuto to see if i have some things to change / add and since i wait, i’ll try to add a function to be able to print on screen, for a highscore screen. Else in the options, i will add ability to turn the sound off from the start screen by pressing b. I’ll add a music on titlescreen (that button b will turn off too), but i don’t know yet wich music.
Else i saw on Arduboy forum the idea to make the game states class and but in the function. The idea is fine and if the tuto isn’t done before, it’s probable that i’ll try to do it.
When this game will be completed, then i’ll pass to fire, ball and judge but i think it’s will be quick then as the structure of the program will be clean and easy to adapt.

2 Likes

Looking forward to see more of those classics :slight_smile:

1 Like

thanks for your answer - looking forward then for whatever will follow!

Ok. Tested. Nice game. Is speed increase during game progress? Because I didn’t notice it during gameplay. Very good Implementation. :slight_smile:

1 Like

J’suis un peu perdu dans tes dépôts :joy:
Quelle est la version qu’on doit tester ?

  1. https://github.com/Jicehel/Parachute_Meta
  2. https://github.com/Jicehel/Parachute_Meta_V2

Je préfèrerais directement tester celle qui est la plus à jour et la mieux optimisée…

En fait, c’est la META_V2 mais elle est en cours. Comme je bidouille dessus, je ne communique pas dessus, mais bon, je n’ai rien fais depuis une semaine… Je retravaillerais le source encore avant d’en parler, c’est pour ça que je n’ai pas du tout communiqué sur la V2…
Parachute_Meta et actuellement la version officielle, celle qui est sûr de fonctionner alors que sur la V2, rien ne garanti qu’il n’y ait pas de problèmes par moment.
Je mettrais à jour la création dès que je serais satisfait du code de la V2 (et je vais sans doute aussi prendre des idées dans ton code pour le modifier et le compléter)