Posté le 27/11/2019 15:12
Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 245 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 04/11/2021 21:24 | #
"concaténer"? Que veut dire ce mot?
Citer : Posté le 04/11/2021 21:26 | #
Fusionner deux chaine de caractère
Ajouté le 04/11/2021 à 22:30 :
Par contre j'ai un autre problème, quand je fais ce code là :
int nb = 3;
static unsigned char str[20];
sprintf((char*)str, "%d", &nb);
PrintMini(1,1,str,1);
la machine m'affiche -2013118684 ce que je ne veut pas évidement
Albert Einstein
Citer : Posté le 04/11/2021 22:31 | #
nb tout seul. &nb c'est quand tu fais sscanf().
Citer : Posté le 04/11/2021 22:35 | #
Haaaa ok !
Merci
Praticule Verison Stable coming soon
(Genre vraiment, avec docu en plus, il reste plus que quelques blocks à faire avant qu'elle soit prête)
Ajouté le 08/11/2021 à 21:04 :
Petite question, est que je suis obligé de mettre en static la liste TempLst ou pas la peine dans le cas ci dessous ?
class ClassTest {
public:
int* Datas;
ClassTest() {
};
};
void Prog(){
ClassTest* object1 = LoadSys();
(suite du programme...)
}
ClassTest* LoadSys(){
ClassTest* object1 = new ClassTest();
int TempLst[ ] = {0,1,3};
object1->Datas = TempLst;
return object1;
}
Albert Einstein
Citer : Posté le 08/11/2021 21:22 | #
Le code est en effet invalide actuellement, puisque le tableau {0,1,3} est sur la pile donc il disparaît quand la fonction se termine. Deux options ; le mettre en static, ou (mieux) l'allouer dans le tas.
Citer : Posté le 08/11/2021 21:53 | #
D'accord, c'est bien ce que je pensais.
Et du coup ça serait quoi la syntaxe si je veux allouer (la deuxième proposition) ?
ça serait ça ?
ClassTest* LoadSys(){
ClassTest* object1 = new ClassTest();
int *TempLst = new int[3];
TempLst[0] = 0;
TempLst[1] = 1;
TempLst[2] = 3;
object1->Datas = TempLst;
return object1;
}
Albert Einstein
Citer : Posté le 09/11/2021 07:09 | #
Oui c'est ça ! Et delete[] pour libérer (dans le destructeur de ClassTest probablement). Note que si le tableau n'a que 3 éléments tu peux mettre un int Datas[3], et s'il peut en avoir un nombre variable peut-être que tu as besoin de noter la longueur quelque part.
Citer : Posté le 09/11/2021 11:49 | #
Merci beaucoup pour ces clarification.
Concernant la taille c'est déjà pris en compte et la taille de la liste est variable mais merci pour ces rappelles
Albert Einstein
Citer : Posté le 09/11/2021 13:20 | # | Fichier joint
Lephenixnoir excuse moi encore te déranger, mais il y a un truc que je comprend pas, c'est que le jeu fonctionne mais pas dans la durée, c'est à dire que au bout de quelques minutes il plante sans même que j'ai appuyé sur une touche.
Est-ce que tu peux jeter un coup d'oeil s'il te plait.
Le principale du code se trouve dans ParticuleEngine.h, je penses que c'est une erreur de mémoire.
(Les images sont stocké dans Ressources.h)
Tu vas remarqué que je n'ai pas toujours mis les delete, c'est parce que j'ai peur qu'il supprime des éléments qui sont en communs car tout est interconnecté, notamment les Texture, donc si tu pouvais me donner ton avis dessus.
Autre chose aussi, les lignes 949 à 960 qui sont des choses comme ça
j'aimerai les mettre à l'extérieur à la ligne 882 par exemple, car sinon il est rappelé plusieurs fois, le soucis c'est que ça compile mais il y a une erreur de mémoire, j'ai beau mettre en static rien n'y fait.
Une dernière chose c'est les List<...>, je ne sais pas si il faut en faire un pointer ou pas, genre Lis<int>*
Merci d'avance, comme c'est le moteur de Particule, ça m'embêterai de publier un code mal fait.
(Si tu as d'autre remarque sur le code que ceux que j'ai énoncé je suis preneur)
Albert Einstein
Citer : Posté le 09/11/2021 14:02 | #
C'est très gros donc je ne peux pas tout lire, mais voilà au moins quelques retours.
this->name = (unsigned char*)name;
this->ID = (unsigned char*)UUID;
}
~Object() {
delete name;
delete ID;
}
Tu n'as pas copié le nom et l'ID donc tu ne peux pas les delete (moralement c'est pas toi qui en es le propriétaire). En particulier un const char * ça peut être un littéral comme "x" (entre guillemets) auquel cas personne n'en est le propriétaire. Dans un programme complexe comme ça il est capital d'avoir une politique très rigoureuse de «propriété» qui indique qui doit libérer quoi et quand, sinon tu t'exposes à beaucoup d'ennuis.
Aussi concernant Object, il y a un adage de C++ qui est qu'une classe virtuelle doit avoir un destructeur virtuel. C'est logique quand on y pense, sinon tes méthodes virtuelles héritées vont manipuler la classe mais ensuite le destructeur de base va libérer les données, ce qui ne peut pas bien marcher. Ton destructeur n'est pas virtuel actuellement, ce qui veut dire que les champs spécifiques aux classes héritées, comme Component::tag, ne sont pas détruits dans les contextes polymorphes.
Je sais pas avec quoi tu compiles, mais si tu supportes du C++ moderne tu peux mettre override sur les méthodes virtuelles héritées au lieu de virtual ; comme ça si tu te trompes en écrivant le nom le compilateur te donne une erreur au lieu de croire que tu ajoutes une nouvelle méthode à la hiérarchie virtuelle.
Tu as beaucoup, beaucoup de triggers et ça fait des tables virtuelles très grandes ; peut-être que ce serait plus simple de les créer à la demande. (Je suis pas sûr, c'est juste une suggestion.)
(Le pluriel de "child" c'est "children")
const unsigned char None[] = { 0x0 };
textureData = (unsigned char*)None;
this->width = 0;
this->height = 0;
};
Ici None est créé sur la pile, tu ne peux pas faire ça (ça fait fuiter un pointeur vers la pile qui se met à pointer vers n'importe quoi). Il suffit de faire textureData = "". De tes questions précédentes tu sembles penser que les char * et les unsigned char * sont des choses différentes. En fait ça ne fait aucune différence, la seule chose qui change c'est la valeur que tu obtiens quand tu convertis un des octets de la chaîne en int (dans un cas l'octet est lu comme un entier signé, dans l'autre c'est lu comme un entier non signé). Mais en termes de données ça ne change rien. Si t'as des warnings tu peux cast genre (unsigned char *)"Hello World" et c'est bon.
Cela dit quand t'as pas de texture je suggère de mettre NULL, parce que si tu es rigoureux de toute façon ton code ne doit pas dépasser les bornes du tableau, et comme width=height=0 le tableau est de longueur 0 donc tous les accès sont interdits.
Allouer un new Vector2() sur le tas c'est franchement inutile, tu paies 4 octets pour stocker le pointeur + un accès mémoire supplémentaire à chaque usage de la donnée + 8 octets dans le tas pour stocker le vecteur mais aussi 4/8 octets d'overhead de malloc(), et tu perds de la localité ; mets-le directement dans la structure, eg. Vector2 Rigidbody::velocity.
Je devine qu'une partie du contrôleur du joueur est générée automatiquement ?
Ton header ne contient pas le moindre template ; le code devrait être dans un fichier C++.
-
C'est l'intuition que j'ai aussi : tu ne libères pas ta mémoire donc au bout d'un certain temps tu épuises le tas et là c'est la catastrophe.
La bonne solution (la seule solution) c'est de gérer tes objets jusqu'au bout et de les delete quand tu n'en as plus besoin. Tes craintes par rapport à l'interconnexion des objets sont on ne peut plus justifiées : c'est un problème très sérieux et on ne peut pas le résoudre à l'improviste. Personnellement je découple méticuleusement les références pour éviter les pointeurs quand c'est possible, et limiter les connexions directes. Je peux aussi suggérer un trick consistant à marquer les objets pour suppression mais à attendre la fin du frame pour les supprimer réellement, le temps que l'information sur la suppression soit détectée par les objets connectés. Parfois ça aide.
Tu ne peux pas ; si les objets étaient statiques tu pourrais, mais ça ne résoudrait que la moitié du problème. La raison pour laquelle tu ne peux pas c'est que le new + le constructeur c'est du code, et tu n'as le droit d'exécuter du code quand dans des fonctions (ou via des constructeurs pour des objets statiques).
À mon sens, la vraie "solution" c'est d'avoir une procédure d'initialisation quelque part que tu prends bien soin de n'appeler qu'une seule fois.
Quand c'est des arguments de fonctions, le plus élégant en général c'est de les passer par référence ; list<int> & si on veut la modifier, const list<int> & sinon.
Quand c'est des attributs dans des classes, il n'y a aucun intérêt à en faire des pointeurs ; tu vas les créer/stocker de toute façon.
-
Voilà voilà j'espère que ça aide
Citer : Posté le 09/11/2021 14:54 | #
Donc pour Object je devrais mettre ça ?
delete name;
delete ID;
}
Mais du coup comment je fais pour les attribuer le nom et l'ID comment tu as dit ?
Car en gros les noms et les IDs des objets sont de simple guillemets qui sont donner vers la fin du code de ParticuleEngine.h, mais ces nom peuvent changer durant l'execution, donc ça serai quoi la meilleure solution ?
ça serait de retirer le const char * ou de copier la variable ?
Pour le destructeur, est-ce que les destructeur mère sont appelé aussi par les destructeur fille.
Par exemple Component qui hérite de Object, est-ce que le destructeur appelle aussi celui de Object ?
Je suppose que tu appelles les trigger les lignes de code du style :
Si c'est ça, c'est voulu totalement.
Il faut que les class fille puisse avoir les mêmes noms.
(Eventuellement je ferai un tris pour réduire le nombre)
children corrigé du coup
Idem pour Texture
En effet, j'ai pas mal fait de C# mais pas suffisement de C ou de C++, c'est vraiment nouveau pour moi donc je suis pas très à l'aise avec les pointer, les adresses, les références ainsi que libéré la mémoire.
C'est pour ça que les types unsigned char* et char* c'est un peu confu dans ma tête.
Et ce projet et aussi une occasion pour moi d'apprend le C++.
Pour les Vector2 ils vont varié plus tard (je l'ai pas encore codé c'est pour ça)
En effet, le PlayerController est généré par Particule ainsi que toutes les lignes de codes qui suivent.
C'est pour ça qu'il y a des choses qui se répètent.
Mais s'il y a des lignes qui sont fausses j'aimerai bien être au courant pour que je puisse le rectifier dans Particule
Je vois pas trop l'utilité des template dans mon code.
Et vois pas non plus plus l'utilité d'un fichier .cpp
(en fait comme Particule génère du code, j'évite de lui demander d'écrire à plusieur endroit)
Je prend note des référence, je vais voir si je peux arranger ça
Du coup pour les List<> dans mon code, c'est correct j'ai pas à modifier si j'ai bien compris?
En tout cas merci d'avoir pris le temps de regarder
Albert Einstein
Citer : Posté le 09/11/2021 15:06 | #
Oui le virtual devant le destructeur c'est ça. (Bien sûr une fois que tu auras enlevé les delete il n'y aura plus rien.)
Ne pas détruire les noms et les ID ça ne veut pas dire que tu ne peux pas les changer. Ce qu'il faut voir c'est que là tu fais ça :
delete nom;
Ce qui est incroyablement faux (tu ne peux/dois delete que ce qui a été alloué par new). La solution est simple : tu décides que la classe Object n'est pas propriétaire des données pointées par name et ID, donc elle peut les lire, mais elle n'y écrit pas, et elle ne les libère pas. Le code qui crée l'objet se débrouille pour que (1) le nom et l'ID soient alloués, et (2) le nom et l'ID restent en vie tant que l'objet est en vie ; et les deux considérations sont triviales puisque les chaînes sont littérales.
Par exemple Component qui hérite de Object, est-ce que le destructeur appelle aussi celui de Object ?
Oui.
Tant qu'ils ne font que 8 octets (ce qui semble probable) la remarque s'applique
Et vois pas non plus plus l'utilité d'un fichier .cpp
(en fait comme Particule génère du code, j'évite de lui demander d'écrire à plusieur endroit)
Le code C++ doit aller dans un fichier .cpp ; les en-têtes n'existent que pour les définitions de classes (sans le code), et les templates (parce les templates ça peut pas se compiler à part). Si tu n'as pas besoin des classes dans d'autres fichiers alors tu peux juste renommer .cpp et ça ira tout seul. Mais tu ne dois pas faire de #include sur un fichier comme ça.
Oui c'est bon
Citer : Posté le 09/11/2021 15:36 | #
J'ai pas compris pour la fin, mais du coup si je le renomme je peux pas l'utiliser dans Tutoriel.cpp ?
Albert Einstein
Citer : Posté le 09/11/2021 15:43 | #
Pourquoi tu ne pourrais pas ? Tu laisses dans un fichier .hpp les définitions des classes (ie. la liste des propriétés/méthodes) et tu mets le code des méthodes dans un fichier .cpp. Sinon dès que tu #include dans deux fichiers différents tu te retrouves avec beaucoup de problèmes (eg. du code en double).
Citer : Posté le 09/11/2021 16:02 | # | Fichier joint
Mais ce code là il est pas bon et pourtant j'ai suivis tes indications (voir fichier join)
Albert Einstein
Citer : Posté le 09/11/2021 16:28 | #
D'abord tu devrais laisser les définitions des enums dans le header ; en plus de ça, les listes d'initialisation ne vont que côté source et les valeurs par défaut que côté header :
Component(const char* name, GameObject* gameObject, const char* UUID = NULL) : Object(name, UUID);
// .hpp OK
Component(const char* name, GameObject* gameObject, const char* UUID = NULL);
// .cpp faux
Component(const char* name, GameObject* gameObject, const char* UUID = NULL) : Object(name, UUID) {
// .cpp OK
Component(const char* name, GameObject* gameObject, const char* UUID) : Object(name, UUID) {
Et surtout tu ne remets pas la classe entière dans ton .cpp, que les définitions des méthodes :
// Le "Transform::" indique qu'on est dans la classe Transform
void Transform::SetParent(Transform* transform) {
if (parent != NULL) {
parent->children.Remove(this);
}
transform->children.Add(this);
parent = transform;
}
Un bon tutoriel de C++ t'enseignera toute la syntaxe nécessaire ; même si les notions sont proches de C# tu ne peux pas trop passer à côté.
Citer : Posté le 09/11/2021 16:42 | #
Du coup je suis obliger de refaire toute la syntaxe, on peux pas juste copier coller malheureusement.
Bon bah en tout cas merci beaucoup pour toutes ces explications
Ajouté le 12/11/2021 à 18:42 :
Est-ce que c'est normal que quand je quitte le programme que j'ai fait en retournant sur le menu de la calculatrice, je ne peux plus le relancer, ou que ça me fait une erreur quand je le relance ?
J'ai remarqué que ce bug était aussi sur d'autres jeux d'ici
Albert Einstein
Citer : Posté le 12/11/2021 19:56 | #
C'est pas trop normal non. Si tu quittes avec GetKey(), tu dois pouvoir rerentrer. Si tu finis main(), c'est normal que tu ne puisses plus rerentrer.
L'émulateur a aussi un bug où si tu n'utilises pas du tout GetKey() dans l'add-in, il plante quand tu lances une autre application du menu après avoir quitté. (Les vieilles SH3 aussi.) C'est anecdotique.
Citer : Posté le 12/11/2021 21:50 | #
Ha ok, bon bah je vais voir ce que je peux faire, merci pour l'info.
Ajouté le 05/02/2022 à 19:09 :
Est-ce qu'il y a moyen avec Gint de faire un agrandissement (en plus de la découpe) de l'image avec un dsubimage ?
Albert Einstein
Citer : Posté le 05/02/2022 20:48 | # | Fichier joint
Non. Mais tu peux créer une copie agrandie d'une image, exemple ci-joint.
Citer : Posté le 05/02/2022 20:59 | #
Ok merci !
Ajouté le 06/02/2022 à 18:47 :
Il y a une limite de taille pour un Addin, pour Graph 90 ?
Car je veux mettre beaucoup d'image
Albert Einstein