pjeff
29/07/2008, 12h25
Jour 11 : Charger une map externe créée avec GbaGraphics
par PJEFF
Bonjour. Bienvenue dans la suite des tutoriels consacrés au développement sur PSP.
Pour des raisons évidentes j’ai repris les tutoriels déjà existants pour les adapter à ce qui suivra.
Je ne vais commenter que le code ajouté, pour le reste référez-vous aux anciens tutoriels.
Des commentaires ?
Ce que nous allons voir aujourd'hui c'est comment charger une map en fichier externe créée avec GbaGraphics, ce qui peut-être pratique dans plusieurs situations, cette méthode n'est pas forcement la plus optimisée mais elle fonctionne néanmoins très bien.
Au passage merci à Brunni pour tout ce qu'il a fait et pour les bouts de code qui viennent également de lui.
1) Déclaration générale
Je pense qu'il n'y a pas besoin de commentaire...
Par contre je ne présente plus comment créer une map ni le format de celle-ci, regardez les cours précédents :)
//Taille du tampon temporaire pour les fichiers = 4 Mo
#define TAILLE_MAXIMUM (8<<20)
//déclaration d'un map pour une utilisation temporaire
typedef unsigned long MAP;
1) Fonction utile
//convertion d'une chaîne de caractères Hexa en int (les maps sont enregistrées par défaut en Hexa)
int atox(char *chn) {
int i;
int n;
int v;
char *deb;
deb=chn;
while((*chn>='0' && *chn<='9') || (*chn>='a' && *chn<='f') || (*chn>='A' && *chn<='F'))
chn++;
chn--;
i=1;
n=0;
while(chn>=deb) {
v=*(chn)-48;
if (v>=17+32) v-=39;
if (v>=17) v-=7;
n+=i*v;
i*=16;
chn--;
}
return n;
}
Fonction pour la lecture de la map, peut encore être améliorée mais je n'ai pas eu le temps de lire également les données mises en commentaire pour avoir vraiment toutes les informations utiles.
OSL_MAP *OuvreFichierMap(OSL_IMAGE *img,char *nom_fichier, int tileX, int tileY) {
OSL_MAP *m;
m = (OSL_MAP*)malloc(sizeof(OSL_MAP));
if (!m)
return NULL;
if (!(*nom_fichier))
return NULL;
m->format = OSL_MF_U16;
//Par défaut le premier tile et toujours transparent
m->flags = OSL_MF_TILE1_TRANSPARENT;
int i;
char str[1000];
char tempstr[6];
FILE *f;
//taille max pour le tableau temporaire
unsigned short *tableau=(unsigned short *)malloc(TAILLE_MAXIMUM);
int mapSizeX = 0; int mapSizeY = 0;
int MaxTilesX = 0;
char* p;
char* p2;
char* separateurs = { " .,!" };
//separateur de fin
char* separateurs2 = { "}" };
f=fopen(nom_fichier,"rb");
if (!f)
{
oslWarning("Le fichier map spécifié n'existe pas");
}
while(!feof(f))
{
if (f)
{
fgets(str,sizeof(str),f);
if (feof(f))
break;
if (!str[0])
continue;
i = 0;
for (i=0;str[i];i++)
{
//vérifie si il y a bien un {
if (str[i]=='{')
{
//ok alors on vérifie si il y a bien un 0 pour que ca soient une chaîne hexa
if (str[i+1]>='0')
{
//supprime le { du début
p = strchr(str,'{')+1;
//première séparation renvoie la première valeur en enlevant certaines choses
p = strtok( p, séparateurs );
//pour tous les mots suivants :
while( p != NULL || p != '\0')
{
//sauvegarder ici le premier résultat !!
// dans le atox je fait un +2 pour ne pas mettre le 0x du départ ça c'est juste pour savoir si c'était bien de l'hexa
tableau[mapSizeY*40+mapSizeX] = atox(p+2);
mapSizeX ++;
//chercher la chaîne hexa suivante
p = strtok( NULL, séparateurs );
//vérifie que le suivant et bien toujours un hexa et pas un vide
if (p[0]=='0' && p[1]=='x')continue;
else break;
}
//on casse la boucle for...
break;
}
}
//si pas de { en premier alors on vérifie si c'est pas la suite d'une ligne X du tableau
else if (str[i]=='0')
{
if (str[i+1]=='x')
{
//première séparation renvoi la première valeur en enlevant certaines choses
p = strtok( str, séparateurs );
//pour tous les mots suivants :
while( p != NULL || p != '\0')
{
//vérifie si il y a pas une } qui se ferme et qui ferme la ligne
p2 = strchr(p, '}');
if (p2)
{
p = strtok( p, separateurs2 );
tableau[mapSizeY*40+mapSizeX] = atox(p+2);
MaxTilesX = mapSizeX +1;
mapSizeX = 0;
mapSizeY ++;
break;
}
//ok alors on continue
//sauvegarder ici le premier résultat !!
// dans le atox je fait un +2 pour ne pas mettre le 0x du depart ca c'est juste pour savoir si c'etait bien du hexa
tableau[mapSizeY*40+mapSizeX] = atox(p+2);
mapSizeX ++;
//chercher la chaîne hexa suivante
p = strtok( NULL, separateurs );
//vérifie que le suivant et toujour bien un hexa et pas un vide
if (p[0]=='0' && p[1]=='x')continue;
else break;
}
//on casse la boucle for...
break;
}
}
}
}
}
fclose(f);
m->img = img;
m->map = (void *)tableau;
m->tileX = tileX;
m->tileY = tileY;
m->mapSizeX = MaxTilesX;
m->mapSizeY = mapSizeY;
m->scrollX = m->scrollY = 0;
m->drawSizeX = -1;
m->drawSizeY = -1;
return m;
}
2) L'utilisation
Là vous allez voir, rien de plus simple a utiliser :)
//déclaration de la map ou des maps à utiliser suivant si il y en a plusieurs ou non
OSL_MAP *MapTest;
//déclaration de l'image à utiliser pour les tiles
OSL_IMAGE *image;
//et maintenant à l'endroit ou vous initialisez le tout (c'est a dire où vous voulez)
image= oslLoadImageFile("image/testcarte.png", OSL_IN_RAM, OSL_PF_8888);
//32x32 c'est simplement la taille des sprites en 32x32 lol
MapTest = OuvreFichierMap(image,"carte_sol.c",32,32);
Et voila la map est chargée et utilisable exactement comme avant.
Bon là il n'y a pas de screen ou de fichier source, je pense que de simples copier/coller feront l'affaire vue la taille du code :)
Je ne sais pas si j'ai été suffisament clair dans ce tutorial, si besoin je rajouterais des précisions.
par PJEFF
Bonjour. Bienvenue dans la suite des tutoriels consacrés au développement sur PSP.
Pour des raisons évidentes j’ai repris les tutoriels déjà existants pour les adapter à ce qui suivra.
Je ne vais commenter que le code ajouté, pour le reste référez-vous aux anciens tutoriels.
Des commentaires ?
Ce que nous allons voir aujourd'hui c'est comment charger une map en fichier externe créée avec GbaGraphics, ce qui peut-être pratique dans plusieurs situations, cette méthode n'est pas forcement la plus optimisée mais elle fonctionne néanmoins très bien.
Au passage merci à Brunni pour tout ce qu'il a fait et pour les bouts de code qui viennent également de lui.
1) Déclaration générale
Je pense qu'il n'y a pas besoin de commentaire...
Par contre je ne présente plus comment créer une map ni le format de celle-ci, regardez les cours précédents :)
//Taille du tampon temporaire pour les fichiers = 4 Mo
#define TAILLE_MAXIMUM (8<<20)
//déclaration d'un map pour une utilisation temporaire
typedef unsigned long MAP;
1) Fonction utile
//convertion d'une chaîne de caractères Hexa en int (les maps sont enregistrées par défaut en Hexa)
int atox(char *chn) {
int i;
int n;
int v;
char *deb;
deb=chn;
while((*chn>='0' && *chn<='9') || (*chn>='a' && *chn<='f') || (*chn>='A' && *chn<='F'))
chn++;
chn--;
i=1;
n=0;
while(chn>=deb) {
v=*(chn)-48;
if (v>=17+32) v-=39;
if (v>=17) v-=7;
n+=i*v;
i*=16;
chn--;
}
return n;
}
Fonction pour la lecture de la map, peut encore être améliorée mais je n'ai pas eu le temps de lire également les données mises en commentaire pour avoir vraiment toutes les informations utiles.
OSL_MAP *OuvreFichierMap(OSL_IMAGE *img,char *nom_fichier, int tileX, int tileY) {
OSL_MAP *m;
m = (OSL_MAP*)malloc(sizeof(OSL_MAP));
if (!m)
return NULL;
if (!(*nom_fichier))
return NULL;
m->format = OSL_MF_U16;
//Par défaut le premier tile et toujours transparent
m->flags = OSL_MF_TILE1_TRANSPARENT;
int i;
char str[1000];
char tempstr[6];
FILE *f;
//taille max pour le tableau temporaire
unsigned short *tableau=(unsigned short *)malloc(TAILLE_MAXIMUM);
int mapSizeX = 0; int mapSizeY = 0;
int MaxTilesX = 0;
char* p;
char* p2;
char* separateurs = { " .,!" };
//separateur de fin
char* separateurs2 = { "}" };
f=fopen(nom_fichier,"rb");
if (!f)
{
oslWarning("Le fichier map spécifié n'existe pas");
}
while(!feof(f))
{
if (f)
{
fgets(str,sizeof(str),f);
if (feof(f))
break;
if (!str[0])
continue;
i = 0;
for (i=0;str[i];i++)
{
//vérifie si il y a bien un {
if (str[i]=='{')
{
//ok alors on vérifie si il y a bien un 0 pour que ca soient une chaîne hexa
if (str[i+1]>='0')
{
//supprime le { du début
p = strchr(str,'{')+1;
//première séparation renvoie la première valeur en enlevant certaines choses
p = strtok( p, séparateurs );
//pour tous les mots suivants :
while( p != NULL || p != '\0')
{
//sauvegarder ici le premier résultat !!
// dans le atox je fait un +2 pour ne pas mettre le 0x du départ ça c'est juste pour savoir si c'était bien de l'hexa
tableau[mapSizeY*40+mapSizeX] = atox(p+2);
mapSizeX ++;
//chercher la chaîne hexa suivante
p = strtok( NULL, séparateurs );
//vérifie que le suivant et bien toujours un hexa et pas un vide
if (p[0]=='0' && p[1]=='x')continue;
else break;
}
//on casse la boucle for...
break;
}
}
//si pas de { en premier alors on vérifie si c'est pas la suite d'une ligne X du tableau
else if (str[i]=='0')
{
if (str[i+1]=='x')
{
//première séparation renvoi la première valeur en enlevant certaines choses
p = strtok( str, séparateurs );
//pour tous les mots suivants :
while( p != NULL || p != '\0')
{
//vérifie si il y a pas une } qui se ferme et qui ferme la ligne
p2 = strchr(p, '}');
if (p2)
{
p = strtok( p, separateurs2 );
tableau[mapSizeY*40+mapSizeX] = atox(p+2);
MaxTilesX = mapSizeX +1;
mapSizeX = 0;
mapSizeY ++;
break;
}
//ok alors on continue
//sauvegarder ici le premier résultat !!
// dans le atox je fait un +2 pour ne pas mettre le 0x du depart ca c'est juste pour savoir si c'etait bien du hexa
tableau[mapSizeY*40+mapSizeX] = atox(p+2);
mapSizeX ++;
//chercher la chaîne hexa suivante
p = strtok( NULL, separateurs );
//vérifie que le suivant et toujour bien un hexa et pas un vide
if (p[0]=='0' && p[1]=='x')continue;
else break;
}
//on casse la boucle for...
break;
}
}
}
}
}
fclose(f);
m->img = img;
m->map = (void *)tableau;
m->tileX = tileX;
m->tileY = tileY;
m->mapSizeX = MaxTilesX;
m->mapSizeY = mapSizeY;
m->scrollX = m->scrollY = 0;
m->drawSizeX = -1;
m->drawSizeY = -1;
return m;
}
2) L'utilisation
Là vous allez voir, rien de plus simple a utiliser :)
//déclaration de la map ou des maps à utiliser suivant si il y en a plusieurs ou non
OSL_MAP *MapTest;
//déclaration de l'image à utiliser pour les tiles
OSL_IMAGE *image;
//et maintenant à l'endroit ou vous initialisez le tout (c'est a dire où vous voulez)
image= oslLoadImageFile("image/testcarte.png", OSL_IN_RAM, OSL_PF_8888);
//32x32 c'est simplement la taille des sprites en 32x32 lol
MapTest = OuvreFichierMap(image,"carte_sol.c",32,32);
Et voila la map est chargée et utilisable exactement comme avant.
Bon là il n'y a pas de screen ou de fichier source, je pense que de simples copier/coller feront l'affaire vue la taille du code :)
Je ne sais pas si j'ai été suffisament clair dans ce tutorial, si besoin je rajouterais des précisions.