Projets 8 Bits Cireza

Ca en jette.

Soirée pixel-art, c’est un peu ma récréation le pixel-art quand c’est comme ça ^^

Afin d’avoir des ennemis relativement jolis, avec des dégradés sympas, et malgré la limite plutôt faible des 10 couleurs possibles, je me suis un peu cassé la tête et j’ai choisi de faire une palette commune à plusieurs ennemis. C’est le seul moyen de pouvoir mélanger les ennemis tout en utilisant un maximum de couleurs à la fois.

Voici le résultat sur le lot des 6 premiers ennemis du jeu, que je pourrais donc mélanger de toutes les façons possibles car ils sont tous sur la même palette de 10.

Capture

Plusieurs idées me sont passées par la tête, comme utiliser ces 10 couleurs pour faire 3 dégradés de 3 couleurs, et cela aurait permis d’avoir par exemple des ennemis :
bleu+vert
vert+orange
bleu+orange

Cela aurait donné l’illusion de plus variété, mais le problème c’est que ça limite fortement les dégradés. On ne se rend pas compte, mais les monstres de Phantasy Star II (jeu de 1989) utilisent quasiment tous 16 couleurs (et en plus ils étaient animés !). Gros boulot de la part de SEGA à l’époque sur leur réalisation. Réduire cela à 10, c’est compliqué. Devoir en plus les ramener sur une même palette, ça complique encore davantage les choses.

Du coup, se retrouver avec seulement 3 couleurs c’est IM-POS-SI-BLE. Par exemple la grenouille, il faut absolument 5 couleurs minimum pour faire le dégradé, sinon elle devient horrible.

En bref, le choix a donc été le suivant :
blanc
noir
dégradé en 5 couleurs
dégradé en 3 couleurs

L’avantage du noir et du blanc est que ce sont des jokers pour ajouter deux couleurs au dégradé. Autre avantage de cette approche structurée, c’est que je pourrai facilement pousser une nouvelle palette et me retrouver avec 6 nouveaux ennemis.

Tout n’est que compromis, mais c’est aussi la beauté de travailler au plus près des contraintes de la machine. Ce que les développeurs de notre époque ne font absolument plus…

Côté code, j’ai réussi à pousser conformément à ce que j’avais imaginé au départ un décor en mémoire afin de faire clignoter les ennemis. En gros, chaque ennemi prend le double de place en mémoire : la première partie est celle qui contient l’ennemi fusionné avec le décor, et l’autre celle qui contient juste le décor. Pour faire le clignotement, j’alterne très rapidement entre la zone mémoire avec l’ennemi et celle sans l’ennemi (numéroté 1 et 2 pour le premier, et 3 et 4 pour le second). Je suis obligé de dupliquer très précisément le décor derrière l’ennemi pour obtenir cette instantanéité.

Comme vous pouvez le voir, la VRAM est ras la gueule.

Capture

4 « J'aime »

Je suis en train de bosser pour faire un bonhomme et faire scroller l’écran : c’est l’enfer. Je me prends la tête un truc de malade (sur le scrolling, le pixel-art j’adore ça). J’avais implémenté une solution que je trouvais super et qui faisait le taf, sauf qu’il y avait un rafraichissement de l’écran qui était visible.

Malheureusement ma méthode, bien que plutôt maligne (je pense qu’elle était, sans voulait paraître prétentieux :slight_smile: ) n’est pas adaptée. Et je dois faire autrement, et visiblement c’est ainsi que tous les jeux font donc c’est la bonne méthode, mais je galère à mort… Des nouvelles bientôt, je l’espère.

En attendant voici mon Rolf en 16x16 pixels, il est pas choupi ?

Capture

Et Nei, à terminer :
Capture

J’ai aussi enrichi le décor de Mota, extérieur :

Capture
Deux couleurs de plus, donc ajout d’éléments de décor sur les bords, et des nuages !
J’ai aussi créé une seconde bande d’herbe, ça passe un peu inaperçu mais ça aide beaucoup, surtout à la moitié de l’écran, pour que la symétrie ne soit plus flagrante (on la voit toujours un peu, mais je suis satisfait du résultat).

Note : merci pour les « like » que vous mettez, c’est très sympa :+1:

8 « J'aime »

Chapeau. C est enorme ce que tu arrives a faire

2 « J'aime »

J’adore le rendu SD des sprites.
J’y connais rien en programmation donc je me rends mal compte de la difficulté, mais ça a l’air coton de contourner les limites du système.

1 « J'aime »

Bon nouveau coup dur :confused:

Je suis arrivé à charger ma carte en mémoire et à implémenter le scrolling avec mise à jour dynamique de la zone à afficher (en gros il faut streamer les bandes suivantes de l’écran en mémoire, juste en dehors de la zone visible). Et bien sûr on peut se déplacer avec les boutons. Je ne vous raconte pas la galère pour faire ça, c’était bien trop compliqué pour rien.

Seulement mon code a atteint la limite incroyable (ironie) de 32 Ko, et j’arrive à une limite technique de la machine… Il faut faire des banks, à savoir découper le code en paquets etc… Ça devient ultra compliqué. Au stade où j’en suis, je n’ai encore aucune logique du jeu de codée, pas de gestion de collision sur la carte, pas d’évènements… Rien quoi.

C’est vraiment super frustrant. C’est un mur de contraintes technique après l’autre, et ça devenait déjà un peu décourageant récemment, et je m’étais accroché quand même. Mais là, le code par bank, en gros devoir gérer manuellement une organisation complexe de la rom, ça va me gonfler. Ça doit quand même rester un plaisir un peu (je fais ça sur mon temps libre) et là je passe la frontière où ça ne m’amuse plus…

J’irai jeter un œil, mais bon je ne suis pas optimiste.

Extrait de la gestion des banks…

ADVANCED: How to use more than 32KiB of code in your SMS/GG ROM (‹ banked code ›):

SDCC 4.x supports banked code and this means that it’s now possible to page in and out code in a transparent manner. To achieve this, banked code should be written in separate source files that have to get allocated in separate code banks. Upon calling a banked function the code will trigger a slot-1 bank change (using trampolines that are ‹ hidden › in bank 0 code) and will restore the previous bank upon returning from called function. This means that only code in bank 0 won’t ever be paged out, but that means that total code won’t be restricted to the 32 KiB maximum size.

You need to:

  • put banked code in separate source files, marking banked functions as such using the __banked SDCC keyword, as in
void some_function (void) __banked {
  //  your code here 
}
  • compile each banked code source file into a specific separate code segment, for instance as in:
  sdcc -c -mz80 --codeseg BANK1 banked_code_1.c
  sdcc -c -mz80 --codeseg BANK2 banked_code_2.c
  • use the provided crt0b_sms.rel as the first module in your linker call
  • instruct the linker to place all the banked code at address 0x4000 + the virtual address of the bank, which is banknumber×2¹⁶ (so code segment BANK1 goes at 0x14000, code segment BANK2 goes at 0x24000 and so on…) and the compiled banked code modules in ascending order as in:
  sdcc -o your_program.ihx -mz80 --no-std-crt0 --data-loc 0xC000 -Wl-b_BANK1=0x14000 -Wl-b_BANK2=0x24000 crt0b_sms.rel SMSlib.lib main.rel banked_code_1.rel banked_code_2.rel
  • use the newer makesms tool to convert the ihx output to the sms file instead of the ihx2sms tool, as this works in a different way. Usage is very similar:
  makesms your_program.ihx your_program.sms

PUTAIN j’ai réussi à utiliser les banques de données ! Pas pour pousser plus de code, mais pour dégager tout ce qui est assets visuels dans des banques dédiées.

Et mon scrolling fonctionne parfaitement maintenant.

Cet ascenseur émotionnel :sweat_smile:

Edit : mon jeu ne fonctionnait plus sur la vraie console… J’ai passé un bon moment à comprendre pourquoi, mais j’ai finalement réglé le truc. Ouf !

2 « J'aime »

C’est pour des moments comme ça que j’aurais aimé avoir appris la programmation jadis. :duh:

1 « J'aime »

« 4 jours d’emmerdes pour 15 secondes de plaisir », et autres joyeusetés du dev :naka:
Chapeau l’artiste, je passe voir l’avancement de ton projet régulièrement, et y a pas à dire, je suis admiratif du travail abattu :+1:

1 « J'aime »

Pas trop de nouvelles ces temps-ci avec Elden Ring et je me refais les saisons d’X-Files sur ma cathodique lol.

Mais j’ai regardé comment transposer les visuels des villes du jeu MegaDrive, et si je peux récupérer quelque chose de très proche de l’original, ça ne me plaît pas. J’aimerai mieux utiliser la palette de la console, et j’aimerai aussi réduire l’échelle des éléments. Les maisons ça va, elles sont petites, mais les tours et autres éléments de décor sont trop grands. Quand on passe sur une résolution faible comme celle de la Game Gear, il faut réduire les espaces sinon le joueur est vite perdu par manque de visibilité.

Je vais sûrement m’orienter sur quelque chose d’un peu différent et redessiner des trucs. J’ai fait une petite étude de la variété des éléments visuels aussi, et je dirai que sur les décors je suis vraiment large. Je peux mettre un maximum de choses et gaver la VRAM, vu que j’aurai peu de sprites à afficher (juste les PNJ).

J’ai aussi constaté que plusieurs RPGs avaient tendance à afficher les textes d’une manière qui ne me plaît pas, et j’ai peur de découvrir encore une contrainte bien pourrie. Plutôt que de mettre à jour la Tilemap en faisant pointer vers les lettres en VRAM, ils réservent des bandes pour la fenêtre et mettent à jour la VRAM pour afficher le texte dedans. Je vais essayer de procéder de ma façon en tout cas.

2 « J'aime »

Voici le premier jet. On reconnait bien les villes de PS2, tout est authentique en terme de pixel-art. J’ai simplifié les murs en bleu car je n’aime pas du tout leur design d’origine, et j’ai refait les logos des magasins.

On a perdu le dégradé de rouge, mais en contrepartie, j’ai ajouté deux maisons : une verte et une marron.

J’ai posé à l’arrache les gros éléments de décor sur la droite. Ils sont trop gros je trouve. Il faut que je fasse un essai d’une manière générale, et voir si on n’est pas trop perdu sur Game Gear avec une carte qui a des éléments à cette échelle.

Une subtilité que j’ai ajoutée aussi, c’est le fait que tout soit décalé de 8 pixels vers le haut. En gros ça permettra de donner l’impression aux personnages qu’ils sont devant les choses, ce qui est un gros plus. Car sinon, vu que les personnages sont en 16x16 pixels, à savoir un carré, ils n’apparaîtraient jamais devant rien (murs, maisons etc…) et ça serait un peu tristounet.

Il me manque clairement des couleurs pour l’eau et le rendu n’est pas très probant. Je n’aime pas le damier (sol) d’origine. Je vais surement le refaire, et simplifier si possible.

Capture

Je suis à 328 tiles différentes (8x8) ça fait beaucoup, je vais simplifier des trucs.

Edit : j’ai rationalisé les choses et redessiné d’autres. Il y a désormais 276 tiles différentes, c’est plus raisonnable. J’ai dégagé le vert le plus clair pour ajouter un bleu, ça permet de faire de l’eau correcte. J’ai ajusté tous les arbres et l’herbe en conséquence.

Capture

4 « J'aime »

J’ai bien avancé sur mon chipset pour faire les villes et je suis allé chercher un outil pour dessiner les cartes avec une fonction d’export au format image (Tiled), car tout faire avec un éditeur d’image est une source d’erreur en plus de prendre une éternité.

Voici un premier jet pour Paseo, la première ville du jeu.

Capture

Je l’ai refaite à mon goût, tout en réduisant la taille, mais en laissant les éléments clefs à leur emplacement. Pour référence, voici la ville sur MegaDrive.

Capture.PNG

Il faut que je réussisse à l’importer sur Game Gear maintenant. J’ai vu que l’outil permettait de sortir des images, donc ça va m’aider. Par contre il me pète ma palette de couleur, je serai obligé de refaire, mais bon ça n’est pas catastrophique.

Bon mon fichier pour la carte est trop gros ça ne compile pas :confused:

5 « J'aime »

Bon je suis tombé sur un épineux problème qui me contraint à user de compression d’une façon ou d’une autre. Ça va forcément rendre le travail encore plus compliqué, et ça me décourage un peu.

Il y a moyen de compresser les tiles et tilemaps. Le nerf de la guerre, ce ne sont pas les tiles (à savoir toutes les pièces de puzzles différentes en 8x8, celles qui constituent le dictionnaire en quelque sorte) mais plutôt les puzzles. Chaque ville est un puzzle, la carte du monde est un puzzle, chaque étage d’un donjon est un puzzle. A savoir, un assemblage des pièces venant du dictionnaire.

Chaque pièce faisant 8x8 pixels, pour la ville que je vous montre ci-dessus, le puzzle fait 80 pièces de long et 60 pièces de haut. Ça fait 4800 pièces. Chaque pièce a besoin d’être un entier, c’est le numéro de la pièce. Un entier fait 2 octets. La simple description de ma ville fait donc 9600 octets, à savoir 9,375 Ko. La taille maximum d’une banque dans la cartouche est de 16 Ko, donc ça pourrait passer. Mais le souci c’est que c’est quand trop gros.

Si on se projette un peu, en supposant que j’ai 200 puzzles à faire, même si j’arrive à en mettre deux par banque, il me faut 100 banques. Avec la cartouche maximale de 1 Mo, j’aurai au mieux 64 banques… Et il faut en enlever au moins 2, surement 3 pour le code, et il y a d’autres choses à mettre dans la cartouche évidemment… Les monstres, les personnages, les musiques et bruitages…

En bref, ça devient un vrai casse-tête.

Il est possible d’utiliser de la compression. Soit en utilisant un algo qui va compresser tout ça, et il faudra décompresser à la volée. Je ne suis pas fan, on perd vraiment la main sur la donnée.

Soit sinon, je dois faire une compression logique. A savoir, réduire mes puzzles en faisant des « grosses pièces ». Je peux partir sur des pièces de 16x16, je n’utilise de toute façon rien de moins. Mais sinon, quand on regarde le jeu MD, il utilise clairement des morceaux de 32x32, et j’ai envie d’essayer ça. Le problème, c’est que mon outil qui me génère les tilemaps fait du 8x8 et je ne vais plus pouvoir l’utiliser.

Et je ne sais pas comment je vais m’y prendre. Si je dois bricoler une solution moi-même, ça va nécessiter pas mal de temps et ce n’est pas vraiment ce que j’ai envie de faire… :confused:

Je vais voir si j’arrive à faire des trucs, mais je ne suis pas très optimiste.

Avec du 32x32, ma carte passerai de 80x60 à 20x15. Et je pourrai peut-être bien passer sur des char au lieu des entiers. Donc il y a un bon gain à faire, mais beaucoup de travail à mettre en place.

Edit : bon j’ai passé toutes mes tiles en 32x32 et j’ai refait la carte. Le résultat me parait satisfaisant, mais maintenant le problème c’est de coder ce bazar…

Capture

Bon j’ai réussi à sortir au propre un modèle organisé à grand coup d’expressions régulières et d’excel…

Ici, la définition des tiles :
Capture

Ensuite, la définition des meta tiles :
Capture
Ce sont des carrés de 32x32, donc 4x4 tiles. Logique !

Enfin, la définition de ma ville avec les meta tiles :
Capture

Ouf ! J’ai un procédé qui marche bien au moins pour ça. Il ne me reste plus qu’à coder tout ça… Ça ne va pas être le plus simple, mais le gain en espace mémoire dans la ROM devrait être conséquent. J’aimerai greffer une gestion de collision à mes meta tiles en plus, quelque chose de basique (dire pour chaque carré de 16x16 pixel si on peut passer ou non dessus). Et je ne sais pas comment je vais gérer mes évènements encore…

Quoiqu’il en soit, je pense qu’il faut que je dessine toutes les villes d’un coup pour éviter d’avoir des surprises plus tard. Car si je me rends compte que je dois changer une tile, je risque de devoir tout ré-exporter ensuite, et ça ne serait pas cool du tout.

2 « J'aime »

J’ai mis en place le code pour les metatiles mais j’ai un problème que je n’arrive pas à résoudre. Certaines tuiles s’affichent correctement, d’autres on des soucis par endroits et ne référencent pas les bonnes tiles en 8x8. Je ne sais pas encore pourquoi. C’est la galère…

J’essaye d’écarter les problèmes. Je pense que mon code pour l’affichage est bon, sinon il n’y aurait pas certaines tuiles complexes qui seraient valides à 100%. Ce qui veut dire que c’est plutôt la donnée qui est KO, donc ma façon de définir les metatiles. Pourtant je revérifier toutes celles qui sont problématiques, et j’ai bien strictement ce que me sort l’outil qui sert à les concevoir… Je ne veux pas incriminer l’outil, le souci est surement chez moi quelque part…

Capture

Rolf est monté sur le toit, c’est pour profiter de la vue.

Edit : léger progrès… Visiblement j’ai des problèmes quand j’écris trop loin en VRAM, peut-être que j’empiète sur la partie sprite et que ça ne marche pas bien pour X raisons…

Capture
(c’est une map de test ça)

3 « J'aime »

Ça a l’air délicat. :confused:

En tout cas c’est très cool de te suivre dans tes galères. On se rend mieux compte des difficultés qu’ont pu rencontrer les dev à l’époque. :mrgreen:
Sans avoir à les vivre nous même.

J’ai résolu la plupart des problèmes ce soir (la solution m’est venue pendant le boulot lol) et j’arrive désormais à afficher ce que je veux.

Capture

Par contre la zone mémoire virtuelle est trop petite vers le haut et je n’ai pas la place de charger une metatile de plus. Ce qui est embêtant car hors de l’écran, j’ai juste une bande de 8 pixels. Or quand je me déplace, je me déplace de 16 pixels. Par conséquent la bande noire sera visible. Ça veut dire que je dois réussir à charger quelque chose dans tous les cas. Je ne sais pas exactement comment je vais m’y prendre…

Une fois que tout ça marchera, il faudra que j’implémente le fait de charger la carte dynamiquement selon les déplacements. Je l’avais déjà fait avant, mais vu que je suis passé en metatiles, je dois le refaire par paquets de 4 lignes/colonnes.

3 « J'aime »

Bon j’ai vraiment de gros problèmes avec les metatiles en 32x32. C’est trop compliqué.

Avec des metatiles en 16x16, mon bonhomme occupe forcément une metatile. C’est très simple, il est en plein milieu et sa position est strictement la même que la metatile.

Avec du 32x32, mon bonhomme en 16x16 peut se trouver à 4 endroits différents.

XO
OO

OX
OO

OO
XO

OO
OX

En gros mon repère commence à la position 0x0, ou 0x16, ou 16x0 ou 16x16 (je dois décaler d’autant de pixels). Et le souci c’est que derrière je dois me trainer le bon décalage pour les mises à jour de la zone visible lors des déplacements : infernal.

Et sa position relative fait que je ne dois pas charger les choses à la même position en VRAM. Ça complexifie beaucoup les choses. Cependant, d’un point de vue de la mémoire, je crois que j’ai absolument besoin de cette compression x32. Car si je repasse sur des metatiles en 16x16, mes cartes vont devenir 4x plus grandes. Il y a 100 maps dans Phantasy Star II, dont certaines immenses. Je vais vite remplir la mémoire.

C’est vraiment un problème difficile :confused:

Je vais changer de stratégie et essayer de faire encore autrement, mais pas ce soir. Il faut que je me change les idées… Quand je pense que Sonic streame en temps réel des metatiles en 32x32 à la vitesse du jeu et ça reste fluide (quelques ralentissements tout de même) les mecs étaient de sacrées brutes.

Edit : finalement j’ai pris la décision suivante :

  • repasser sur des metatiles en 16x16
  • j’avais mis des bords sur mes cartes pour ne pas avoir à balader le sprite sur les bords de l’écran, en gros le héros est toujours parfaitement au centre et seul le décor défile : je vais supprimer ces bords sur les cartes, qui prennent une place folle, et essayer de remplir dynamiquement avec la tile « par défaut », c’est à dire de l’herbe. Il y a beaucoup d’espace mémoire à gagner
  • pour mes jeux de tiles initiaux, je vais me limiter à 256 max, cela me permettra de définir mes metatiles avec des char au lieu des entier (divise par 2 l’espace pris)

Dans ce but, j’ai retravaillé mon chipset de la ville pour du 16x16. L’avantage c’est que je vais récupérer la liberté de construction de la ville que j’avais un peu perdue. J’espère que j’aurai assez de mémoire pour tout faire cependant…

Capture

J’ai pas mal grappillé. Déjà sur la grande tour, que j’ai réduite car elle prenait une place folle. J’ai enlevé la porte de l’hôpital. J’ai ajusté d’autres trucs pour gagner une tile par-ci par-là. Je suis actuellement à 254, mais normalement j’ai tous les éléments pour toutes les villes de Mota. Il faudra refaire un jeu différent pour Dezo à cause du fond neigeux. Il y a assez peu de symétrie car ça rend vite les choses moches, d’où la volonté de ne pas en mettre. Ça détruit systématiquement les jeux d’ombres.

2 « J'aime »

tu devrais demander de l’aide sur le forum smspower, ils pourraient peut être partager avec toi des trucs de programmation sur la machine.

C’est pas mon style. Je suis quelqu’un qui trouve tout seul ou qui ne trouve pas :slight_smile:

J’ai finalement réussi ce soir à dérouler toutes les étapes qui j’avais prévues précédemment. J’ai rebasculé mes metatiles sur 16x16, ça permet de faire une carte de Paseo plus variée (car pas contrainte par des tiles en 32x32) donc c’est un bon point.

Voici à quoi elle ressemble au final :

Capture

D’après mes estimations je pourrai mettre une dizaine de cartes dans cette banque, donc c’est raisonnable sachant qu’il y a en plus toutes les tiles et metatiles dedans. J’ai aussi rempli un tableau pour la gestion de collision. Je pense que cette dernière sera plutôt facile à implémenter.

L’autre bonne nouvelle c’est que mon scrolling est désormais parfaitement fonctionnel. Je peux me balader dans la ville et tout fonctionne à la perfection.

J’ai également gagné en mémoire en dégageant les bandes d’herbe sur les bords. Désormais si on sort des coordonnées de la ville, ça affiche par défaut la première tile, donc de l’herbe dans ce cas.

Le fait de repasser sur des tiles en 16x16 a vraiment simplifié les choses et j’ai beaucoup progressé en me prenant des murs ces derniers jours. Ca reste quand même très complexe de streamer la carte en temps réel sachant que les variables à prendre en compte sont très nombreuses, entre la position du personnage dans la map, la position de la scroll screen, la position où écrire en mémoire… Mais bon c’est fait, et ça scrolle de manière fluide en plus.

Capture

J’ai commencé à jouer à Lunar sur Game Gear pour me changer les idées. Le jeu est plutôt rigolo pour l’instant, rien de transcendant cela dit.
Lunar patch-220309-130153 Lunar patch-220309-132624 Lunar patch-220309-223855 Lunar patch-220309-224342 Lunar patch-220309-230648

Je ferai peut-être un article !

3 « J'aime »

Bon j’ai un truc qui marche à peu près, je ne suis pas certain d’aller au bout des choses mais bon… J’avance quand même encore un peu.

Mon problème actuel, c’est que je n’aime pas les graphismes des villes, qui sont une transposition du jeu MegaDrive. Je trouve les choses trop grandes par rapport au personnage et ça me dérange un peu.

Mes personnages sont un poil petits, je devrais les écraser plus, mais je trouve que le rendu n’est plus aussi authentique « Phantasy Star » si je fais ça… Je vais changer la ville pour réduire l’échelle des choses, qu’on ait le sentiment de voir la ville de plus loin. Ensuite, je verrai si je dois aussi retoucher mes sprites.

Je suis assez bluffé par Lunar en ce moment. Les mecs sont des génies de la palette de 16 couleurs… Ils ont une unique palette avec laquelle ils font tous les sprites, tous les portraits et tous les décors de combats. Ce sont les 16 mêmes couleurs tout le temps. Sacré talent.

Voici un premier jet de tous les personnages sur la même palette :
Capture

Je n’avais pas la place pour faire deux rouges et deux violets, alors je me suis débrouillé avec 3 couleurs à la place, en faisant un entre-deux. Je suis aussi sorti des couleurs flashy de la MD qui m’horripilent en ajoutant des composantes mineures à toutes les couleurs.

3 « J'aime »