Posté le 15/07/2017 13:54
Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 132 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements
Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd
Citer : Posté le 28/12/2018 09:09 | #
Les fonctions imbriquées ont pas mal de défauts. Je t'en cite quelques-uns :
* Ce n'est supporté que par GCC.
* Tu ne peux pas les utiliser en-dehors de leurs fonctions parentes pour des raisons fondamentales, donc tu ne peux pas les renvoyer.
* Pour les appeler il faut exécuter du code sur la pile, ça ouvre la voie à un vecteur d'attaque classique.
Si tu arrives à utiliser une structure sans que ça soit trop lourd, je pense que c'est plus viable. Et rassure-toi, j'étais debout à minuit pour d'autres raisons.
Citer : Posté le 29/12/2018 00:13 | #
Bonsoir, j'ai refait une vraie fonction pour la gestion d'input.
Je te montre tout ça pour avoir un avis sur les possibles améliorations
J'ai créé un type "keyboard_t" pour stocker toutes les données du clavier :
Ensuite la fonction pour enregistrer tout le buffer : tout simplement
volatile uint8_t *p = keyboard_stateBuffer();
for(int i = 0; i < 10; ++i) kb->k[i] = p[i];
}
Enfin une fonction booléenne qui renvoie vrai si les deux touches en arguments sont poussées (ça gère aussi des cas particuliers):
if(!k1) k1 = k2;
if(!k1) {
for(int i = 0; i < 10; ++i) if(kb->k[i]) return 0;
return 1;
}
if(k1 == k2) k2 = 0;
//the first digit of k1 is the position in the kb array. We must get it with k1%0x10.
//the second digit of k1 is the bit position in kb[x] where we can see if the key is down.
//we get this second digit with k1/0x10. To check if the bit = 1, we shift the whole number by the second digit then we compare it with &1.
if(
(( kb->k[k1%0x10] >> (k1/0x10) ) & 1)
&&
(!k2 || (( kb->k[k2%0x10] >> (k2/0x10) ) & 1))
) return 1;
return 0;
}
J'ai fait des commentaires en anglais histoire de mon anglais de robot
Comme t'as écrit la biblio t'as peut être fait des outils pour simplifier la tâche
En application cela donne :
keyboard_t clavier;
gclear();
//input
keyboardRead(&clavier);
if(inputReader(&clavier, KEY_LEFT, KEY_SHIFT)) pak->choix = KICK;
else if(inputReader(&clavier, KEY_LEFT, 0)) pak->choix = GAUCHE;
else pak->choix = RIEN;
//traitement
switch(pak->choix) {
case GAUCHE:
spriteRun(0, 30, &img_jintrun, XJINT, YJINT, JRUNF, &(pak->frame));
break;
case KICK:
spriteRun(0, 30, &img_jintkick, XJINT, YJINT, JKICKF, &(pak->frame));
break;
default:
spriteRun(0, 30, &img_jint, XJINT, YJINT, JIDLEF, &(pak->frame));
}
gupdate();
}
Donc tout cela marche
Citer : Posté le 29/12/2018 09:51 | #
C'est pas mal, mais alors pas mal du tout !
Je n'ai que des remarques à ajouter pour préciser comment tout cela fonctionne.
keyboard_stateBuffer() renvoie toujours la même adresse, celle d'un tableau qui se comporte exactement comme tu le veux. Tu n'es pas obligé de le copier, par contre comme il change tout seul pendant que tu travailles il faut ajouter volatile devant sinon le compilateur sera confus.
k1/0x10 peut s'écrire k1>>4 et k1%0x10 peut s'écrire k1&0xf. Je pense que GCC est assez intelligent pour l'optimiser donc pas de problème comme ça, mais tu peux te souvenir qu'une division ou un modulo c'est environ 70 cycles processeur, tandis que les décalages et les masques ça se compte en quelques cycles.
Bravo
Citer : Posté le 29/12/2018 12:29 | #
Ok super merci pour les conseils Par question de goût je préfère travailler avec une copie complète du clavier, ça servira peut être plus tard
Ajouté le 29/12/2018 à 20:08 :
Salut, cette fois c'est une suggestion pour la biblio. As tu pensé à faire un dimage/gimage qui affiche le sprite en miroir ? Sans une telle fonction ça oblige à cloner ses sprites dans mon cas Même si je vais carrément adapter le game design pour éviter que mon perso tourne la tête
Citer : Posté le 29/12/2018 21:44 | #
Eh bien, oui, mais c'est purement et simplement impossible ! Mon format d'images est assez compliqué et optimisé pour effectuer les rendus très (très) vite. Entre autres limitations, tu ne peux pas envisager d'inverser la gauche et la droite. (Tu pourrais, par contre, inverser le haut et le bas, s'il me venait l'idée d'implémenter un truc pareil...)
Je pense qu'avoir plusieurs sprites est une bonne idée pour deux raisons :
* D'abord ça ne coûte pas grand-chose en espace, et tu maintiens des perfs' élevée avec dimage()
* Ensuite, ça t'incite à ajouter de la variation entre les deux côtés de ton personnage
Le premier argument me paraît convaincant pour le programmeur, et le second convaincant pour le game designer, mais je te laisse en juger...
Citer : Posté le 01/01/2019 00:21 | #
Rien à voir avec Gint là c'est un problème de C, ce code compile pas :
int x;
perso_t nom;
};
struct map {
struct pnj pnj[3];
};
struct map map1;
map1.pnj[0].x = 64;
map1.pnj[0].nom = PNJ_VIEUX;
map1.pnj[1].nom = PNJ_RIEN;
et ce bon vieux gcc me dit :
map1.pnj[0].x = 64;
^
../src/game.c:37:5: error: expected '=', ',', ';', 'asm' or '__attribute__' before '.' token
map1.pnj[0].nom = PNJ_VIEUX;
^
../src/game.c:38:5: error: expected '=', ',', ';', 'asm' or '__attribute__' before '.' token
map1.pnj[1].nom = PNJ_RIEN;
Je ne vois pas du tout le problème
J'ai tenté ça :
map1.pnj->x = 64;
map1.pnj->nom = PNJ_VIEUX;
(map1.pnj+1)->nom = PNJ_RIEN;
même délire avec le symbole qui manque avant le point. Je comprends pas.
Citer : Posté le 01/01/2019 00:28 | #
C'est moi ou tu as mis du code en-dehors d'une fonction ?
Citer : Posté le 01/01/2019 12:01 | #
Certes en effet ah ah ah ma crédibilité en prend un coup
Je peux tout expliquer monsieur
(bordel mais n'importe quoi j'en oublie les bases)
Ajouté le 03/01/2019 à 20:12 :
Salut mon cher,
j'essaye de gérer des fichiers avec Bfile sauf que j'ai un drôle de bug... J'ai tout refait simplement avec un petit addin pour voir d'où venait le bug mais impossible de savoir.
Voici le code de l'addin :
#include <keyboard.h>
#include <bfile.h>
#include <stdio.h>
#define STORAGE "\\\\fls0\\"
#define SDCARD "\\\\crd0\\"
void strToPath(char *str, uint16_t *fc, char *p) {
while(*p) *fc++ = *p++;
while((*fc = *str)) fc++, str++;
}
int main(void)
{
uint16_t path[15];
int f, buffer;
char str[15];
strToPath("test", path, STORAGE);
f = BFile_Open(path, BFile_ReadOnly);
if(f < 0) {
BFile_Close(f);
return 0;
}
BFile_Read(f, &buffer, sizeof(int), -1);
BFile_Close(f);
sprintf(str, "%d", buffer);
dclear();
dtext(0, 0, str);
dupdate();
getkey();
return 0;
}
Donc on peut voir que je cherche à voir quel est l'entier qui se cache dans "test", le fichier je le crée avec du vrai C d'ordinateur :
int main() {
FILE *f = fopen("test", "wb");
int a = 25;
fwrite(&a, sizeof(int), 1, f);
fclose(f);
return 0;
}
Donc moi sur la casio, je veux voir "25" sauf que j'ai un sale nombre à la place. Aurais-tu une piste ? Pour info mon fichier fait 4 octets.
Citer : Posté le 03/01/2019 20:49 | #
Alors, c'est facile : ton ordinateur est en little-endian alors que la calculatrice est en big-endian. Je peux donc affirmer sans hésiter que le nombre que tu vois à l'écran est 419430400.
Utilise htobe16() et htobe32() de <endian.h> (_DEFAULT_SOURCE) sur ton ordinateur pour convertir en big-endian avant d'écrire la valeur dans le fichier.
Deux trucs pendant que j'y pense :
* N'écris jamais un nombre impair d'octets avec Bfile_WriteFile() ;
* Tu peux utiliser dprint(0, 0, "%d", buffer) si tu veux éviter le sprintf().
Citer : Posté le 03/01/2019 21:46 | #
Ah super merci, et t'as bien deviné c'est ce sale nombre qui est affiché. Je compte pas écrire dans des fichiers via la casio mais ça m'intéresse de savoir pourquoi on peut pas écrire par octets impairs
Citer : Posté le 03/01/2019 22:04 | #
Ah, l'histoire des écritures de longueur impaire ? C'est une limitation de Bfile que j'ai découverte par hasard, mais qui avait déjà été connue avant. SimLo écrit notamment au sujet du syscall Bfile_WriteFile() :
SDK Bfile_WriteFile directly calls 0x0435 when HANDLE & 0x0F000000 <> 0
This is true with fls0- or crd0-handles.
0x0435 must not be used to write to a main memory handle!
Never write an odd number of bytes (size). Never use the flash directly as source memory (*buf).
Citer : Posté le 17/01/2019 15:44 | #
Salut cher ami, c'est juste pour quelques précisions sur l'utilisation du timer. Dans la boucle du jeu je dois le stopper pour ouvrir un dialogue, je fais comme ceci :
char output[40];
int offset_x, offset_y, i;
timer_stop(timer);
text_configure(&pol_police, color_black);
while(*str) {
if(*str != '\n') {
str++; //pour eviter %
gclear();
switch(*str) { //detection du perso qui parle
case 'j':
offset_x = 0;
offset_y = 35;
break;
case 'p':
offset_x = 35;
offset_y = 0;
break;
default:
gtext(0, 0, "Erreur");
gupdate();
getkey();
return;
}
}
str++;
i = 0;
do {
output[i++] = *(str++);
} while(*str != '%' && *str != '\n' && *str != '\0');
output[i] = '\0';
gimage_part(DWIDTH-TAILLE_AVA, DHEIGHT-TAILLE_AVA, &img_ava, 0, 0, TAILLE_AVA, TAILLE_AVA); //affichage jint
gimage_part(0, 0, &img_ava, 0, p*TAILLE_AVA, TAILLE_AVA, TAILLE_AVA); //affichage pnj
gtext(offset_x, offset_y, output);
gupdate();
getkey();
}
timer_start(timer);
}
Comme tu peux le voir, je le réactive à la fin de la fonction, sauf que ça me donne un comportement très étrange du coup je me demande si ça en est la cause avant de me plonger plus profondément sur l'algo.
Citer : Posté le 17/01/2019 16:04 | #
En principe ça doit fonctionner, même si je reconnais que je n'ai pas testé ce cas de figure car dans un jeu je n'aurais pas opté pour l'arrêter.
Essaie avec un cas de test minimal, (type juste stop suivi immédiatement de start), si ça ne marche pas alors il y a un bug à corriger.
Citer : Posté le 17/01/2019 17:47 | #
Je ne m'y connais pas trop mais il me semble qu'il est plus simple de programmer avec Gint qu'avec les commandes de base du SDK ? Et puis si je ne m'abuse, il faut quelques connaissances sur le fxSDK pour utiliser Gint ?
-Planétarium 2
Citer : Posté le 17/01/2019 18:13 | #
Niveau complexité, aucun n'est plus difficile par principe, mais si on prend en compte l'environnement et la doc, je pense que gint est un peu plus difficile à utiliser : il faut compiler son GCC (sauf Arch Linux), utiliser les outils des Linux en ligne de commande, et me consulter en cas de problème. Le SDK est plus "propre" d'aspect général.
Le fxSDK et gint sont liés d'une façon très forte. Le fxSDK fournit certaines commandes en compilation qui sont appropriées pour développer des add-ins, notamment avec gint. Et surtout, le fxSDK fournit les outils de conversion d'images et de polices qui sont utilisés par gint.
Cela dit le fxSDK est un petit ensemble avec quelques outils et peu d'options, donc on peut à peine parler de "connaissances sur le fxSDK". Il n'y a pas grand-chose à creuser.
Citer : Posté le 17/01/2019 18:23 | #
J'ai isolé le problème, je précise que c'est dans la fonction callback que le timer appelle :
gclear();
gprint(0, 0, "%s", "Ceci est un test");
gupdate();
getkey();
timer_start(pak->timer);
avec ça je peux voir le message et continuer à jouer ensuite. Le problème c'est que dès que je quitte l'addin, la calculette pète des câbles (glitch dans les menu, et crash quand je veux entrer dans une appli) je suis obligé de l'éteindre.
Citer : Posté le 17/01/2019 19:22 | #
Eh bien. C'est très dérangeant, on est d'accord. Il faut explorer plusieurs pistes et s'assurer qu'on trouve le problème.
La plus évidente est que tu n'as pas le droit d'appeller getkey() dans un callback, c'est illégal. La raison est que le callback est exécuté pendant la gestion de l'interruption, et donc les interruptions sont coupées, alors que getkey() s'appuie très fort dessus... ça ne peut pas marcher bien à long terme.
Vois le timer handler comme une fonction très rapide qui fait un job simple, met à jour des variables et s'en va. Dessiner à l'écran est acceptable, mais gérer le clavier, c'est vraiment limite.
En plus qu'est-ce que tu penses qu'il va se passer quand tu lances getkey() dans le handler ? Étant donné que ton callback est appelé plusieurs fois par seconde, tu veux que getkey() se lance plusieurs fois « en parallèle » ? Ça n'existe pas : ce qui se passe c'est que ton getkey() bloque tout le reste du programme, y compris l'arrivée de prochaines interruptions.
Citer : Posté le 17/01/2019 20:43 | #
Bah je m'étais dit comme je stop le timer c'est le tapis rouge pour faire ce que je veux Je pense que je vais devoir passer par la structure pak pour sauvegarder l'état du dialogue Je pense que c'est pour le mieux je pourrai avoir le contrôle des fps pendant le dialogue.
Citer : Posté le 17/01/2019 20:58 | #
Bah je m'étais dit comme je stop le timer c'est le tapis rouge pour faire ce que je veux
Presque ! Pour dérouler le tapis rouge il faut quand même que tu quittes le callback. C'est peut-être possible en théorie de faire autrement, mais je ne suis pas sûr de vouloir essayer parce que ça pose des problèmes architecturaux un peu subtils...
Je pense que tu peux juste utiliser le callback pour changer des variables qui disent « au prochain frame, lance le dialogue » et le faire dans ton programme principal.
JBerben Invité
Citer : Posté le 13/05/2019 08:38 | # | Fichier joint
I'm really sorry that I can't communicate in French, but I've been following the development of Gint and fxsdk for a little while now. And I'm trying to write a 3D rendering engine in C, but I don't have access to any of the math.h functions. I set up the GCC toolchain with newlib as well, but I can't make sense of how to use newlib's math library rather than Gints', because whenever I #include <math.h>, it always includes Gint's math header file first.
Any help would be much appreciated!
Merci!
Citer : Posté le 13/05/2019 09:16 | #
There's no problem, really! Thanks for your interest in this project.
This behavior is annoying. Since newlib is there now, the next major version of gint (found here because we are migrating the forge, but not production-ready yet) will drop support for whatever standard functions it currently has. Also, all headers are installed in a gint/ directory so that includes are always #include <gint/*.h>.
For now, we can rely on GCC developers who fortunately know this situation can happen, and provide a #include_next directive to include another header with the same name. So you should be able to do:
#include_next <math.h> /* Includes newlib's version */
Let me know if that works as expected.