Tableaux de tableaux de pointeurs
Posté le 30/05/2023 19:55
Dans mon jeu j'ai des tableaux de pointeurs que j'ai mis dans un autre tableau pour pouvoir changer de skin (garçon ou fille) et d'animation (sauter ou courir).
Les tableaux sont définis comme ça
/* Ne vous plaignez pas, je les ai mis dans l'ordre alphabétique ... */
extern unsigned char* boy_jump;
extern unsigned char* boy_run;
extern unsigned char* girl_jump;
extern unsigned char* girl_run;
unsigned char** player_sprites[] = {
&boy_jump,
&boy_run,
&girl_jump,
&girl_run
};
extern unsigned char* alpha_boy_jump;
extern unsigned char* alpha_boy_run;
extern unsigned char* alpha_girl_jump;
extern unsigned char* alpha_girl_run;
unsigned char** player_alpha[] = {
&alpha_boy_jump,
&alpha_boy_run,
&alpha_girl_jump,
&alpha_girl_run
};
et j'y récupère une image comme ça :
(*player_alpha[game->player.skin * 2 + game->player.action])
[game->player.anim.anim_frame]
Le truc c'est qu'à mon avis je suis en train de faire de la grosse merde avec les pointeurs mais je ne sais pas comment faire mieux.
Ps : faudrait uniquement autoriser de resize en vertical les textarea de création d'un topic.
Citer : Posté le 30/05/2023 20:02 | #
Si tu veux utiliser le sprite tu as juste besoin de connaître boy_jump, pas &boy_jump - le second n'aurait du sens que si tu voulais en plus modifier la variable boy_jump. Mais ce n'est pas le cas, tu veux juste l'utiliser. Moralement tu as donc envie de faire un tableau comme ceci :
boy_jump,
boy_run,
girl_jump,
girl_run
};
Ça ça ne marche pas parce que la valeur de boy_jump (qui est un pointeur) n'est pas connue par le compilateur et donc il ne peut pas initialiser le tableau. Mais on est d'accord que dans l'idée c'est ça.
Maintenant ce que je soupçonne c'est que tes sprites il sont en fait définis comme ça :
Ce qui change tout parce que dans ce cas le type c'est pas unsigned char *, c'est unsigned char [<la taille>], et c'est pas du tout le même type. En l'occurrence, contrairement à la valeur d'un pointeur à l'instant, l'adresse du tableau est elle acceptable comme initialiseur, du coup tu peux écrire :
extern unsigned char boy_run[];
extern unsigned char girl_jump[];
extern unsigned char girl_run[];
unsigned char* player_sprites[] = {
boy_jump,
boy_run,
girl_jump,
girl_run
};
Et ensuite t'en servir comme ça :
draw(un_sprite);
J'ai pas compris ce que faisait le frame en plus, sans doute que du coup il y a subtilité que j'ai ratée.
Citer : Posté le 30/05/2023 20:45 | #
au hasard l'animation à plusieur frame ?
Citer : Posté le 30/05/2023 20:47 | #
Bien sûr. Ce que je voulais dire c'est qu'à partir de sa question je n'arrive pas à inférer la disposition mémoire qu'il a choisi pour ces animations.
Citer : Posté le 30/05/2023 21:07 | #
Maintenant tout pointe au même endroit, bon, donc il y a encore un truc a résoudre ...
J'ai pas compris ce que faisait le frame en plus, sans doute que du coup il y a subtilité que j'ai ratée.
C'est parce que c'est un tableau de sprite coder qui contient plusieurs sprites, comme ça :
0x7f, 0xfe,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x80, 0x1,
0x7f, 0xfe,
};
const unsigned char spikes[]={
0x0, 0x0,
0x18, 0x18,
0x18, 0x18,
0x18, 0x18,
0x18, 0x18,
0x2c, 0x2c,
0x2c, 0x2c,
0x2c, 0x2c,
0x2c, 0x2c,
0x46, 0x46,
0x46, 0x46,
0x46, 0x46,
0x46, 0x46,
0x3e, 0x3e,
0x38, 0x38,
0x7c, 0x7c,
};
const unsigned char allowchange[]={
0xf, 0xf0,
0x10, 0x8,
0x20, 0x4,
0x40, 0x2,
0x80, 0x1,
0x80, 0x1,
0x81, 0x81,
0x83, 0xc1,
0x82, 0xc1,
0x81, 0x81,
0x80, 0x1,
0x80, 0x1,
0x40, 0x2,
0x20, 0x4,
0x10, 0x8,
0xf, 0xf0,
};
const unsigned char* tiles[]={
block,
spikes,
allowchange
};
libMicrofx : https://www.planet-casio.com/Fr/forums/topic17259-2-libmicrofx-remplacez-fxlib-pour-faire-des-add-ins-tres-legers.html !
Racer3D : https://www.planet-casio.com/Fr/programmes/programme4444-1-racer3d-mb88-jeux-add-ins.html
Citer : Posté le 30/05/2023 21:56 | #
Du coup maintenant mes tableaux qui contiennent tout les pointeurs sont comme ça
extern unsigned char boy_jump[];
extern unsigned char boy_run[];
extern unsigned char girl_jump[];
extern unsigned char girl_run[];
unsigned char* player_sprites[] = {
boy_jump,
boy_run,
girl_jump,
girl_run
};
extern unsigned char* alpha_boy_jump[];
extern unsigned char* alpha_boy_run[];
extern unsigned char* alpha_girl_jump[];
extern unsigned char* alpha_girl_run[];
unsigned char* player_alpha[] = {
alpha_boy_jump,
alpha_boy_run,
alpha_girl_jump,
alpha_girl_run
};
libMicrofx : https://www.planet-casio.com/Fr/forums/topic17259-2-libmicrofx-remplacez-fxlib-pour-faire-des-add-ins-tres-legers.html !
Racer3D : https://www.planet-casio.com/Fr/programmes/programme4444-1-racer3d-mb88-jeux-add-ins.html
Citer : Posté le 30/05/2023 22:45 | #
Dans ton message initial tu nous parles de boy_jump et player_sprites mais ton extrait de code utilise alpha_sprites. Ensuite tu nous présentes un alpha_sprites d'un type différent de player_sprites avec un alpha_boy_jump dont on pourrait penser qu'il est de même type que boy_jump sauf que non. Et tu nous justifies ça en nous montrant des sprites block, spikes et un tableau tiles dont tu ne nous montres pas comment ils sont utilisés.
On ne comprend rien à tes données, Mb, on est obligés de deviner. Prends le temps de nous montrer tout le code qui définit et utilise les sprites jusqu'à la création de player_sprites et son utilisation, tout le code qui fait pareil jusqu'à la création de alpha_sprites et son utilisation, et là on pourra te dire ce qui ne va pas.
Citer : Posté le 30/05/2023 22:55 | #
J'ai tout mis sur gitea
libMicrofx : https://www.planet-casio.com/Fr/forums/topic17259-2-libmicrofx-remplacez-fxlib-pour-faire-des-add-ins-tres-legers.html !
Racer3D : https://www.planet-casio.com/Fr/programmes/programme4444-1-racer3d-mb88-jeux-add-ins.html
Citer : Posté le 31/05/2023 00:09 | #
Du coup il y a un niveau de pointeurs en plus que ce que j'avais compris ; on a bien des choses comme
Note que tu dois toujours, toujours garder la cohérence entre la définition et toutes les déclarations externes. Si tu change le type entre les deux ça va péter et tu n'auras pas de warning donc c'est vraiment important de surveiller ça.
Comme précédemment, boy_jump et affiliés étant des tableaux, on peut toujours les utiliser directement comme initialiseurs (un pointeur vers le tableau est alors généré).
extern unsigned char* boy_run[];
extern unsigned char* girl_jump[];
extern unsigned char* girl_run[];
unsigned char** player_sprites[] = {
boy_jump,
boy_run,
girl_jump,
girl_run
};
Il est important de comprendre la progression des types ici. Au début, tu as une image dans le style de
C'est un tableau de unsigned char, et quand on utilise bj_s0 comme initialiseur durant la définition de boy_jump, le tableau s'affaiblit implicitement et devient un pointeur vers le début de la séquence, ie. un unsigned char *. Des pointeurs comme ça y'en a 9 (de bj_s0 à bj_s8) et donc on les stocke dans un tableau :
bj_s0,
/* ... */
bj_s8
};
Il est important de voir que dans le type de boy_jump, l'étoile c'est ce qu'il reste du [] de bj_s0 à bj_s8, et le [] on vient de le rajouter en créant un nouveau niveau de tableau.
De la même façon, quand boy_jump est utilisé comme initialiseur dans player_sprites, il s'affaiblit automatiquement en un unsigned char **, et du coup quand on écrit :
boy_jump,
boy_run,
girl_jump,
girl_run
};
La deuxième * c'est ce qu'il reste du [] de bj_s0 à bj_s8, la première * c'est ce qu'il reste du [] de boy_jump qui s'est fait affaiblir implicitement, et le [] on vient de le rajouter en créant un nouveau niveau de tableau.
Encore une fois, il est super important de ne jamais mentir entre une définition de variable et ses déclarations externes, et donc en particulier dans assets.h il faut absolument utiliser le bon type au caractère près, à savoir :
extern unsigned char** player_alpha[];
Et ça s'utilise comme tu l'imagines, comme un double tableau de sprites, ie. exactement comme tu le fais.
Citer : Posté le 31/05/2023 13:32 | # | Fichier joint
Merci beaucoup pour l'explication très complète de comment résoudre le problème, mais ça marche toujours pas : tout pointe vers le même endroit ...
libMicrofx : https://www.planet-casio.com/Fr/forums/topic17259-2-libmicrofx-remplacez-fxlib-pour-faire-des-add-ins-tres-legers.html !
Racer3D : https://www.planet-casio.com/Fr/programmes/programme4444-1-racer3d-mb88-jeux-add-ins.html
Citer : Posté le 31/05/2023 14:17 | #
Je n'ai pas ma calto sous la main pour tester mais je note que dans ton dernier commit tu as écrit
extern unsigned char** player_alpha;
Ce qui n'est pas le bon type.
Tu as d'ailleurs un warning à ce sujet, mais après avoir pull je ne l'ai pas vu, il a fallu que je fasse une recompilation complète pour que player.c soit recompilé (!!). Tu as donc un énorme red flag, à savoir un système de build qui parfois mélange des anciennes versions des fichiers sans recompiler ce que tu écris. Le protocole dans ce cas c'est tu lâches tout et tu ne fais plus confiance à ton code tant que tu n'es pas sûr que le g1a que tu obtiens est bien représentatif de ce qu'il y a dans ton code C.
La raison de ce problème est assez évidente, tu as la dépendance $(BUILD)/%.o: src/% mais tu n'as rien pour prendre en compte les headers. Le faire dans make est assez compliqué, tu es libre de te lancer dedans, de toujours tout recompiler, ou de changer de système de build (CMake le fait automatiquement par exemple), mais je si peux me permettre un conseil ne reste surtout pas avec un Makefile défaillant.
Citer : Posté le 31/05/2023 14:34 | #
J'aime bien meson, mais je pense que c'est pas pratique avec, car il faut un fichier cross-compile, et c'est assez chiant de devoir passer un argument à chaque fois. Merci beaucoup pour l'aide, maintenant le sprite s'affiche \o/
Par contre je déteste cmake donc je pense que je corrigerai le makefile.
libMicrofx : https://www.planet-casio.com/Fr/forums/topic17259-2-libmicrofx-remplacez-fxlib-pour-faire-des-add-ins-tres-legers.html !
Racer3D : https://www.planet-casio.com/Fr/programmes/programme4444-1-racer3d-mb88-jeux-add-ins.html
Citer : Posté le 31/05/2023 14:37 | #
Cool !
J'aime bien meson, mais je pense que c'est pas pratique avec, car il faut un fichier cross-compile, et c'est assez chiant de devoir passer un argument à chaque fois.
Oh tu sais rien ne t'empêche de faire un Makefile où "make" ça appelle meson/ninja avec le bon argument