La Place des Développeurs [Fusion-C] Comment créer une map
Bonjour à toutes et tous !!
Je suis bloqué pour déssiner la map sur l'écran. J'ai défini un tilemap et un tileset et je n'arrive pas à le peindre sur l'écran en screen 5.
Voici les variables que j'utilise pour créer la map et les tiles :
Que-ce qui m'échappe ?
Merci !! Edité par DarkNekros Le 04/06/2021 à 16h45
Je suis bloqué pour déssiner la map sur l'écran. J'ai défini un tilemap et un tileset et je n'arrive pas à le peindre sur l'écran en screen 5.
Voici les variables que j'utilise pour créer la map et les tiles :
Code C :
#define TILEMAP_WIDTH 20 #define TILEMAP_HEIGHT 18 #define TILESET_TILE_COUNT 97
Que-ce qui m'échappe ?
Merci !! Edité par DarkNekros Le 04/06/2021 à 16h45
aoineko
Membre non connecté
Conseiller Municipal
Le Screen 5 est un mode graphique "bitmap" et non pas à base de tuile (tiles-based).
Tes données ressemblent plus à ce qu'on utiliserait en Screen 1, 2 ou 4 et ou tu enverrais les données de ta structure TILEMAP (numéros des tuiles) à l'adresse de la VRAM ou se situe ta "Pattern Names Table" et le contenu de TILESET (masque 1-bit) vers la "Pattern Generator Table".
Je ne sais pas quel compilateur C tu utilises, mais avec SDCC, unsigned int représente un entier 16-bits.
Je déconseille toujours d'utiliser les int qui selon la norme C, n'ont pas une taille fixe (elle est laissé au choix du compilateur).
Les types entiers à taille fixe sont :
- char : 8-bits
- short : 16-bits
- long : 32-bits
Si tu veux absolument utiliser le Screen 5, il faudrait que tu remplisses l'écran de façon manuel.
Pour ce faire, il faudrait :
- Faire une boucle pour chaque bloc (8x8 pixels par ex.) sur la largeur et la hauteur de l'écran ,
- Pour chaque bloc, récupérer le numéro de la tuile via TILEMAP et trouver tes données correspondantes dans TILESET,
- Ensuite tu dessines le bloc à la main dans la VRAM à l'endroit du bloc dans la "Pattern Names Table" (qui un bitmap dans ce mode).
Si les données de tes tuiles sont au format du Screen 5 (chaque octet représente 2 pixels consécutif : chaque couleur sur 4-bits), alors tu as juste besoin de faire une copie avec la commande VDP : HMMC .
Sinon, tu peux utiliser le format de ton choix (comme ceux des Screen 1, 2 ou 4) et faire le décodage à la main.
Bon courage
Tes données ressemblent plus à ce qu'on utiliserait en Screen 1, 2 ou 4 et ou tu enverrais les données de ta structure TILEMAP (numéros des tuiles) à l'adresse de la VRAM ou se situe ta "Pattern Names Table" et le contenu de TILESET (masque 1-bit) vers la "Pattern Generator Table".
Je ne sais pas quel compilateur C tu utilises, mais avec SDCC, unsigned int représente un entier 16-bits.
Je déconseille toujours d'utiliser les int qui selon la norme C, n'ont pas une taille fixe (elle est laissé au choix du compilateur).
Les types entiers à taille fixe sont :
- char : 8-bits
- short : 16-bits
- long : 32-bits
Si tu veux absolument utiliser le Screen 5, il faudrait que tu remplisses l'écran de façon manuel.
Pour ce faire, il faudrait :
- Faire une boucle pour chaque bloc (8x8 pixels par ex.) sur la largeur et la hauteur de l'écran ,
- Pour chaque bloc, récupérer le numéro de la tuile via TILEMAP et trouver tes données correspondantes dans TILESET,
- Ensuite tu dessines le bloc à la main dans la VRAM à l'endroit du bloc dans la "Pattern Names Table" (qui un bitmap dans ce mode).
Si les données de tes tuiles sont au format du Screen 5 (chaque octet représente 2 pixels consécutif : chaque couleur sur 4-bits), alors tu as juste besoin de faire une copie avec la commande VDP : HMMC .
Sinon, tu peux utiliser le format de ton choix (comme ceux des Screen 1, 2 ou 4) et faire le décodage à la main.
Bon courage
On est toujours ignorant avant de savoir.
Merci pour la réponse et les explications.
Merde, et pour le Screen 8 ? J'ai cru comprendre que le Screen 5 c'est pour les jeux avec des sprites et le Screen 8 pour les images (l'intro du jeu, par exemple).
J'utilise SDCC v3.6 pour pouvoir utiliser la lib Fusion-C d'Eric. Je vois qu'avec SDCC, les choses changent par rapport à du C dit classic.
C'est que je craignais :'(
Merci !! Edité par DarkNekros Le 05/06/2021 à 00h25
aoineko :
Le Screen 5 est un mode graphique "bitmap" et non pas à base de tuile (tiles-based).
Merde, et pour le Screen 8 ? J'ai cru comprendre que le Screen 5 c'est pour les jeux avec des sprites et le Screen 8 pour les images (l'intro du jeu, par exemple).
aoineko :
Je ne sais pas quel compilateur C tu utilises, mais avec SDCC,unsigned int représente un entier 16-bits.
Je déconseille toujours d'utiliser les int qui selon la norme C, n'ont pas une taille fixe (elle est laissé au choix du compilateur).
Les types entiers à taille fixe sont :
- char] : 8-bits
- short : 16-bits
- long : 32-bits
Je déconseille toujours d'utiliser les int qui selon la norme C, n'ont pas une taille fixe (elle est laissé au choix du compilateur).
Les types entiers à taille fixe sont :
- char] : 8-bits
- short : 16-bits
- long : 32-bits
J'utilise SDCC v3.6 pour pouvoir utiliser la lib Fusion-C d'Eric. Je vois qu'avec SDCC, les choses changent par rapport à du C dit classic.
aoineko :
Si tu veux absolument utiliser le Screen 5, il faudrait que tu remplisses l'écran de façon manuel.
C'est que je craignais :'(
aoineko :
Bon courage
Merci !! Edité par DarkNekros Le 05/06/2021 à 00h25
aoineko
Membre non connecté
Conseiller Municipal
DarkNekros :
Merde, et pour le Screen 8 ? J'ai cru comprendre que le Screen 5 c'est pour les jeux avec des sprites et le Screen 8 pour les images (l'intro du jeu, par exemple).
Les modes écrans classiques pour les jeux sont :
- Screen 2 / 4 : Tuiles 8x8 (2 couleurs par ligne d'une tuile) + Sprites MSX1 / 2
- Screen 5 : Bitmap 4-bits (16 couleurs) + Sprites MSX2
Tu peux aussi utiliser les sprites MSX2 avec le Screen 8 (mode bitmap 8-bits : 256 couleurs).
La seule restriction avec ce mode c'est qu'un écran prend beaucoup de place en VRAM et que les copies sont plus lentes (plus d'octets à traiter).
En fait, tout dépend du jeu que tu veux faire.
Pour un jeu d'échec par ex., ou tu as pas besoin d'une grande réactivité, tu pourrais très bien prendre le Screen 8.
Si tu souhaites du scrolling par ex., les modes avec tuiles peuvent être plus efficace (et encore, ça dépend du jeu car le MSX2 permet un scrolling vertical assez efficace même avec les mode bitmap).
Le Screen 5 est un bon compromis car il offre pas mal de souplesse pour une taille mémoire raisonnable.
DarkNekros :
J'utilise SDCC v3.6 pour pouvoir utiliser la lib Fusion-C d'Eric. Je vois qu'avec SDCC, les choses changent par rapport à du C dit classic.
C'est la norme C qui est censé être respecté par tous les compilateurs (et c'est le cas de tous ceux que je connais).
Le type int a une taille "libre" choisi par le compilateur (il permet l'interopérabilité). Ca pourrait être 8, 16, 32, voir 64-bits (je ne connais que des 16 et 32-bits perso).
Par contre, un char sera toujours 8-bits, un short toujours 16-bits et un long toujours 32-bits.
Vu que la taille des entiers est très importante pour les performances en général, et encore plus quand on parle d'ordi 8-bits comme le MSX, je recommande donc vivement de ne jamais utiliser les int , quelque soit le compilateur.
Quand je créé un nouveau programme, je commence toujours par redéfinir mes types de bases (cf. "Basic types" dans https://github.com/aoineko-fr/CMSX/blob/master/cmsx/src/core.h).
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
@DarkNekros
Pour répondre à ton MP, et au reste.
Peut importe le type de mode écran que tu veux utiliser, tu peux utiliser des Tiles graphiques dans tous les modes.
L'affichage sera plus lent qu'avec des tiles de caractères c'est tout.
Il y a quelques année j'ai fait un jeu en mode Screen 12, qui tourne sur Turbo-R ou MSX2+
J'avais à l'époque codé mon propre éditeur de niveaux, mais j'aurais tout aussi bien pu utiliser Tiled pour éditer les niveaux.
Le principe est le suivant : Tu as sur la page 1 (ou autre)de ta VRAM une images correspondant aux objets/tiles que tu veux utiliser pour constituer ton niveau qui se s'affichera en Page 0 de la VRAM.
Comme ceci par exemple
Chaque element ici présent est défini par ses coordonnées x,y , sa largeur et sa longueur.
Il faut donc constituer des tableaux de valeurs correspondant à chaque objet affichable.
par exemple
Ensuite quand tu lis ton tableau représentant ton niveau , celui-ci doit correspondre aux n°d'objets que tu as précisé dans les tableaux précédents.
Si tu lis '2' dans level_1, alors tu sais que les coordonnées à utiliser pour copier l'objet de la page 1 vers la page 0 sont obj_X[2] et obj_Y[2]
J'espère que ca répond à ta question ? Edité par ericb59 Le 05/06/2021 à 14h12
Pour répondre à ton MP, et au reste.
Peut importe le type de mode écran que tu veux utiliser, tu peux utiliser des Tiles graphiques dans tous les modes.
L'affichage sera plus lent qu'avec des tiles de caractères c'est tout.
Il y a quelques année j'ai fait un jeu en mode Screen 12, qui tourne sur Turbo-R ou MSX2+
J'avais à l'époque codé mon propre éditeur de niveaux, mais j'aurais tout aussi bien pu utiliser Tiled pour éditer les niveaux.
Le principe est le suivant : Tu as sur la page 1 (ou autre)de ta VRAM une images correspondant aux objets/tiles que tu veux utiliser pour constituer ton niveau qui se s'affichera en Page 0 de la VRAM.
Comme ceci par exemple
Chaque element ici présent est défini par ses coordonnées x,y , sa largeur et sa longueur.
Il faut donc constituer des tableaux de valeurs correspondant à chaque objet affichable.
par exemple
Code C :
char obj_X[]={0,24,48,72, ....}; char obj_Y[]={2,26,50,74, ....};
Ensuite quand tu lis ton tableau représentant ton niveau , celui-ci doit correspondre aux n°d'objets que tu as précisé dans les tableaux précédents.
Code C :
char level_1[]={0,1,1,1,2,2,2,2,1,1,1,3,...};
Si tu lis '2' dans level_1, alors tu sais que les coordonnées à utiliser pour copier l'objet de la page 1 vers la page 0 sont obj_X[2] et obj_Y[2]
J'espère que ca répond à ta question ? Edité par ericb59 Le 05/06/2021 à 14h12
aoineko :
Les modes écrans classiques pour les jeux sont :
- Screen 2 / 4 : Tuiles 8x8 (2 couleurs par ligne d'une tuile) + Sprites MSX1 / 2
- Screen 5 : Bitmap 4-bits (16 couleurs) + Sprites MSX2
- Screen 2 / 4 : Tuiles 8x8 (2 couleurs par ligne d'une tuile) + Sprites MSX1 / 2
- Screen 5 : Bitmap 4-bits (16 couleurs) + Sprites MSX2
Merci pour l'explication. Je vais de moment faire du Screen 5 et je verrai par la suite si j'ai besoin du Screen 8 ou pas.
aoineko :
C'est la norme C qui est censé être respecté par tous les compilateurs (et c'est le cas de tous ceux que je connais).
Le type int a une taille "libre" choisi par le compilateur (il permet l'interopérabilité). Ça pourrait être 8, 16, 32, voir 64-bits (je ne connais que des 16 et 32-bits perso).
Le type int a une taille "libre" choisi par le compilateur (il permet l'interopérabilité). Ça pourrait être 8, 16, 32, voir 64-bits (je ne connais que des 16 et 32-bits perso).
Ah, je croyais que c'était le char qui avait une taille "libre" Merci pour la clarification !!
aoineko :
Quand je créé un nouveau programme, je commence toujours par redéfinir mes types de bases (cf. "Basic types" dans https://github.com/aoineko-fr/CMSX/blob/master/cmsx/src/core.h).
Merci pour l'astuce, je vais jeter un œil
ericb59 :
Pour répondre à ton MP, et au reste.
Peut importe le type de mode écran que tu veux utiliser, tu peux utiliser des Tiles graphiques dans tous les modes.
L'affichage sera plus lent qu'avec des tiles de caractères c'est tout.
J'espère que ca répond à ta question ?
Peut importe le type de mode écran que tu veux utiliser, tu peux utiliser des Tiles graphiques dans tous les modes.
L'affichage sera plus lent qu'avec des tiles de caractères c'est tout.
J'espère que ca répond à ta question ?
Merci pour l'explication je vais voir comment faire ces tableaux avec Tiled et je vous dis. Par contre, je ne sais que-ce que tu veux dire avec tiles graphiques et tiles de caractère
Sinon, j'ai une autre question :
Il faut aussi un tableau avec les tiles bloquantes et les tiles sur lesquels on peut passer, non ?
aoineko
Membre non connecté
Conseiller Municipal
Les modes écrans 0, 1, 2 et 4 du MSX fonctionnent avec un mode "tuile" automatisé (on peut parler de tile ou de character, ça revient au même).
L'idée c'est que dans la VRAM, il y a un espace de stockage pour les dessins des tiles/characters (la Pattern Generator Table) et un autre espace qui stock un tableau représentant l'écran comme une grille et détermine pour chaque case de cette grille, quelle tuile va être affiché (c'est la Pattern Names Table).
Le programmeur n'a rien d'autre à faire que remplir ses deux zones en VRAM ; le processeur graphique du MSX (le VDP) s'occupant à chaque frame, de composer une image à partir des tuiles sélectionnés et de leur dessin stocké.
Certains appellent ces modes, des "modes textes" (même si les tuiles peuvent avoir n'importe quelle forme, pas uniquement des lettres).
Avec le mode écran 5, c'est très différent. Le VDP construit l'image à l'écran en lisant les informations de couleur dans une seule zone mémoire (c'est le "bitmap"). Chaque pixel de l'écran est codé sur 4-bits (16 couleurs). Il y a donc 2 pixels pour 1 octet et pour afficher une image 256x212 (résolution max du Screen 5), il faut donc un espace mémoire de 128x212 octets.
Il n'y a aucune gestion automatique par le VDP des tuiles dans ce mode. Il faut donc que le programme le fasse lui même pour composer l'image qui sera affiché. Le plus simple c'est de stocker dans la VRAM (à un endroit non visible à l'écran) toutes les images de tes tuiles au format Screen 5 (4-bits par pixel) et au moment de composer ton image, avoir coté CPU une grille avec le numéro des tuiles à chaque emplacement de l'écran et de faire la copie manuellement de la zone de stockage de tes tuiles vers la zone visible de la VRAM.
Pour les collisions, le plus simple et de tout avoir dans ton numéro de tuile.
Il suffit par ex. de dire que les numéro de tuiles de 0-127 sont sans collision et de 128-255 avec.
Ainsi, quand tu checks la tuile avec laquelle ton personnage va collisionner, tu regardes juste si son numéro est plus grand que 127 (ou plus rapide, tu regarde si le 8e bit du numéro de tuile est à 1).
EDIT : Tu peux aussi jeter un œil à cette discussion ou je donnais un exemple de comment coder différentes informations dans le numéro des tuiles => http://msxvillage.fr/forum/topic.php?id=3515&pt=4#m85245
Peut-être que tu pensais aux wchar_t qui peuvent être 16 ou 32-bits en fonction du compilateur (et de ses options).
Par contre, l'aspect signé ou non-signé des types de nombres entiers n'est pas standard (char peut être unsigned char ou signed char).
D'où l'importance de bien redéfinir ses types.
L'idée c'est que dans la VRAM, il y a un espace de stockage pour les dessins des tiles/characters (la Pattern Generator Table) et un autre espace qui stock un tableau représentant l'écran comme une grille et détermine pour chaque case de cette grille, quelle tuile va être affiché (c'est la Pattern Names Table).
Le programmeur n'a rien d'autre à faire que remplir ses deux zones en VRAM ; le processeur graphique du MSX (le VDP) s'occupant à chaque frame, de composer une image à partir des tuiles sélectionnés et de leur dessin stocké.
Certains appellent ces modes, des "modes textes" (même si les tuiles peuvent avoir n'importe quelle forme, pas uniquement des lettres).
Avec le mode écran 5, c'est très différent. Le VDP construit l'image à l'écran en lisant les informations de couleur dans une seule zone mémoire (c'est le "bitmap"). Chaque pixel de l'écran est codé sur 4-bits (16 couleurs). Il y a donc 2 pixels pour 1 octet et pour afficher une image 256x212 (résolution max du Screen 5), il faut donc un espace mémoire de 128x212 octets.
Il n'y a aucune gestion automatique par le VDP des tuiles dans ce mode. Il faut donc que le programme le fasse lui même pour composer l'image qui sera affiché. Le plus simple c'est de stocker dans la VRAM (à un endroit non visible à l'écran) toutes les images de tes tuiles au format Screen 5 (4-bits par pixel) et au moment de composer ton image, avoir coté CPU une grille avec le numéro des tuiles à chaque emplacement de l'écran et de faire la copie manuellement de la zone de stockage de tes tuiles vers la zone visible de la VRAM.
Pour les collisions, le plus simple et de tout avoir dans ton numéro de tuile.
Il suffit par ex. de dire que les numéro de tuiles de 0-127 sont sans collision et de 128-255 avec.
Ainsi, quand tu checks la tuile avec laquelle ton personnage va collisionner, tu regardes juste si son numéro est plus grand que 127 (ou plus rapide, tu regarde si le 8e bit du numéro de tuile est à 1).
EDIT : Tu peux aussi jeter un œil à cette discussion ou je donnais un exemple de comment coder différentes informations dans le numéro des tuiles => http://msxvillage.fr/forum/topic.php?id=3515&pt=4#m85245
DarkNekros :
Ah, je croyais que c'était le char qui avait une taille "libre" Merci pour la clarification !!
Peut-être que tu pensais aux wchar_t qui peuvent être 16 ou 32-bits en fonction du compilateur (et de ses options).
Par contre, l'aspect signé ou non-signé des types de nombres entiers n'est pas standard (char peut être unsigned char ou signed char).
D'où l'importance de bien redéfinir ses types.
On est toujours ignorant avant de savoir.
aoineko
Membre non connecté
Conseiller Municipal
Ma remarque concernait le type char seul. En fonction du compilateur, il peut être interprété comme un nombre signé ou comme un nombre non-signé (il faut donc faire attention à ça aussi).
Si le programmeur précise signed char ou unsigned char, dans ce cas pas de soucis, tous les compilateurs les interpréteront comme voulu.
Voila un résumé des cas problématiques :
D'où l'importance de redéfinir ses types de base.
Dans mon programme, quand j'utilise un type u16 par ex., je suis sûr de manipuler un entier 16-bits non-signé ; ce qui n'est pas le cas si j'utilise un int.
Si le programmeur précise signed char ou unsigned char, dans ce cas pas de soucis, tous les compilateurs les interpréteront comme voulu.
Voila un résumé des cas problématiques :
D'où l'importance de redéfinir ses types de base.
Dans mon programme, quand j'utilise un type u16 par ex., je suis sûr de manipuler un entier 16-bits non-signé ; ce qui n'est pas le cas si j'utilise un int.
On est toujours ignorant avant de savoir.
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie