Parachute HD (META)

Parachute hd meta


**Version en cours de réalisation**
  • Reprise du jeu G&W Parachute de Nintendo en 1981.
  • Le joueur contĂŽle la barque afin de la positionner sous les parachutistes afin de les rĂ©cupĂ©rer avant qu’ils ne tombent dans l’eau et se fassent dĂ©vorer par les requins.
  • Le joueur perd une vie Ă  chaque fois qu’un parachutiste tombe Ă  l’eau.

Point sur le développement. Je me suis approprié le squelette de programme de Steph et incorporé les sprites et le fond de Parachute.

J’ai commencĂ© Ă  implĂ©menter le mĂ©canisme du jeu (dĂ©placement du bateau, lancement et dĂ©scente des parachutistes, chute dans l’eau et dĂ©placement du noyĂ© et du requin)
Le score, la pause (Appuie sur A ou sur B), la fin de partie.
Il me reste à ajouter quelques sons, les vie bonus lorsque l’on atteind certains scores si on en a perdu, la correction d’un bug d’affichage de “Pause” et “GameOver”
Si je peux, j’ajouterais peut ĂȘtre la gestion des hi-score, un menu, un Ă©cran de remerciements, un Ă©cran des meilleurs scores

Le programme est quasi fini, si vous voyez des améliorations à y faire, je suis preneur.

See more

1 Like

Cool :). Bon courage pour la suite du dev !

Am looking forward to trying it out.

1 Like

Pas mal le principe de la HD.
L’animation peut ĂȘtre amĂ©liorer par rapport Ă  l’original ?
le rameur avec des animations au niveau du visage ?
des couleurs diffĂ©rentes entre l’hĂ©lico, les parachutistes et la barque.
une petite animation de l’eau et des feuilles des palmiers ?
Ă  moins que tu veuilles ĂȘtre conforme Ă  l’original

Je n’ai pas encore bien compris le code pour faire de la HD, je te fĂ©licite pour cette prouesse :wink:

Bon développement


Bonjour et merci Lysandre. Oui, lĂ  l’idĂ©e c’est vraiment de coller Ă  l’original. Pour le moment, le jeu n’est pas fini. Je vais m’y mettre un peu ce soir. Je vais essayer d’ajouter l’affichage du score avant de me coucher. Donc non, il n’y aura pas d’animation de l’eau ou des feuilles dans cette version.
Par contre les pales de l’hĂ©lico vont bouger, il y aura un Ă©cran de dĂ©marrage et un menu avec lancer le jeu, le rependre, sauvegarder ou consulter les high score et peut ĂȘtre des options plus tard. Un Ă©cran de pause est prĂ©vu mais ce sera peut ĂȘtre le menu ou l’écran des high score Ă  la place.AprĂšs il y aura aussi des miss qui disparaiteront quand on atteint certains score et pareil l’augmentation de la vitesse sera diffĂ©rente de l’original. AprĂšs on verra si j’ai oubliĂ© quelque chose mais surtout je passerais Ă  un autre. On pourra toujours faire d’autre version plus tard.
Sinon pour la HD, j’utilise la structure faite par Steph, sa structure de programme est trĂšs simple et tu n’as pas Ă  rentrer dans la mĂ©canique de la HD, juste Ă  dire quel sprite tu veux afficher. C’est du caviar et tu peux l’utiliser pour beaucoup de type de jeux. De mon cĂŽtĂ©, je n’ai pas trop de temps et je joue Ă  d’autres jeux qui me bouffent du temps alors je ne vais pas me lancer dans trop de choses diffĂ©rentes avant d’avoir programmĂ© quelques un de mes game & watch prĂ©fĂ©rĂ©, mais je ne les ferais pas tous, comme ça quelqu’un qui veut voir comment ça marche pourra en prendre un des nombreux restant et faire son adaptation du programme avec les bon graphiques en adaptant le code. :wink:

@LYSANDRE pour te resituer le contexte concernant la HD
 parce-qu’il faut rendre Ă  Cesar ce qui est Ă  Cesar
 et que les rĂ©fĂ©rences originales se perdent trop souvent dans les nimbes des discussions si elles ne sont pas rappelĂ©es correctement in situ.

Le tout premier Ă  nous avoir ouvert les portes de la HD dans cette communautĂ© est Andy (aoneill), avec son article High Resolution without gb.display (qui date du mois de novembre 2018). Cet article fournit les routines magiques pour pouvoir utiliser le contrĂŽleur DMA avec un mĂ©canisme parallĂšle Ă  double tampons pour le calcul d’un rendu graphique. Cette technique n’utilise pas les routines graphiques fournies par la bilbiothĂšque officielle avec l’API gb.display, mais directement l’API de bas niveau gb.tft qui Ă©tablit un pont avec la bibliothĂšque originale d’Adafruit pour la gestion de l’écran de la META.

Lorsqu’Andy a sorti son article, il y a prĂšs d’un an maintenant, je lui ai immĂ©diatement emboĂźtĂ© le pas pour essayer de comprendre la technique qu’il exposait (et Ă  laquelle bien peu se sont intĂ©ressĂ©s manifestement
). J’ai dĂ©cortiquĂ© son article et ai eu l’idĂ©e de mettre en application ce que j’en avais compris sur un petit exercice qui consiste Ă  effectuer le rendu d’une scĂšne de jeu en travaillant sur l’éclairage de la scĂšne par un jeu d’ombre et de lumiĂšre. J’ai alors souhaitĂ© en faire profiter la communautĂ© en rĂ©digeant un tutoriel complet sur la technique d’Andy et la rĂ©alisation d’un moteur de rendu HD pour la META. LĂ  aussi
 peu de personnes se sont vraiment intĂ©ressĂ©es Ă  ces techniques Ă  en croire le peu de commentaires recueillis
 si ce n’est Alban qui a, par la suite, sorti son Project 88.

Il y a quelques mois, j’ai rĂ©digĂ© un autre tutoriel trĂšs complet sur la rĂ©alisation de jeux de type Platformers en exploitant la HD avec la META. Ce travail n’est, Ă  ce jour, pas terminé  mais devant le manque d’activitĂ© flagrant de la communautĂ©, j’ai suspendu ce chantier
 et c’est bien dommage. Mais je ne sais pas si je trouverai le courage de le reprendre. Entre temps, je suis passĂ© Ă  bien d’autres choses de mon cĂŽté  toujours dans le domaine de la programmation sur microcontrĂŽleurs.

Et puis @jicehel est revenu Ă  la charge avec son projet de rĂ©lisation de jeux de type Game & Watch de Nintendo, nĂ©cessitant la HD 
 puisque les 80x64 pixels offerts par l’API gb.display ne sont pas suffisants pour ce type de jeu. Je lui ai donc proposĂ© un embryon de code lui permettant de s’attaquer Ă  ce type de jeu, en mettant en place tout ce qui concerne la technique de rendu graphique et la maniĂšre d’exploiter une spritesheet pour en extraire les postures adĂ©quates des diffĂ©rents personnages Ă  l’oeuvre dans le jeu. Ce code est disponible sur mon GitHub, et tu peux t’en inspirer librement pour tes propres rĂ©alisations. Comme le dit @jicehel, il a peu de temps
 et un coup de main pour l’implĂ©mentation de quelques Game & Watch serait le bienvenu :wink:

Je tenais Ă  rappeler cet historique, parce-que la communautĂ© ne doit pas oublier que si, aujourd’hui, certains sont en mesure d’exploiter la HD sur la Gamebuino META, c’est bien grĂące Ă  Andy ! Et je trouve que, d’une maniĂšre gĂ©nĂ©rale, les contributeurs ont ici souvent tendance Ă  oublier de citer leurs sources en donnant des rĂ©fĂ©rences prĂ©cises sur les travaux antĂ©rieurs qui leur ont permis d’aboutir


1 Like

Dommage que la discussion initiale ait Ă©tĂ© clĂŽturĂ©e, j’aurais pu la complĂ©ter directement
 alors tant pis, je le fais ici :slight_smile:

En fait, je souhaitais revenir sur un point crucial que j’ai complĂštement oubliĂ© d’évoquer dans ma proposition initiale. L’usage de l’API gb.tft avec la technique d’Andy n’est nĂ©cessaire que si l’on souhaite exploiter pleinement l’espace colorimĂ©trique RGB565 avec une rĂ©solution de 160x128, du fait de la limitation mĂ©moire de la META.

En effet, il est tout Ă  fait possible de s’en tenir Ă  l’usage standard de l’API gb.display dans la mesure oĂč on se restreint Ă  un espace colorimĂ©trique de 16 couleurs. Il suffit pour cela d’utiliser le mode d’affichage spĂ©cifique DISPLAY_MODE_INDEX de la META, qui correspond Ă  une rĂ©solution de 160x128 en 16 couleurs indexĂ©es. Ce paramĂ©trage doit ĂȘtre fixĂ© dans le fichier config-gamebuino.h accompagnant le croquis de l’application avec la ligne suivante :

#define DISPLAY_MODE DISPLAY_MODE_INDEX

J’ai mis Ă  jour mon dĂ©pĂŽt GitHub de dĂ©mo qui intĂšgre dĂ©sormais les deux approches :wink:

DĂ©solĂ©, je ne pensais pas que tu souhaiterais ajouter quelque chose comme tu avais dĂ©jĂ  livrĂ© le squelette demandĂ©. J’ai remis ton texte dans l’autre post. Normalement, je pense que tu as les droits pour ouvrir et fermer un sujet. J’ai fermĂ© l’autre sujet comme il Ă©tait rĂ©solu et qu’il n’y avait pas Ă  priori de choses Ă  y ajouter. Je ne sais pas si c’est utile de fermer les sujets. C’était aussi pour tester la fonctionnalitĂ© que j’ai dĂ©couverte en voulant modifier le titre pour y faire figurer que la demande Ă©tait rĂ©solue.
Tiens pendant que tu es lĂ , je ne l’ai pas fait mais je vais sans doute afficher le score en allumant / Ă©teignant des sprites reprĂ©sentant les sĂ©gments (comme pour les afficheurs 7 sĂ©gments) mais sinon, si l’on veut afficher un message avec ton moteur, pour toi, quelle serait la solution la plus simple ?

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: