Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.

Forum Casio - Autres questions


Index du Forum » Autres questions » Programmer un addin directement sur une calculatrice
Potter360 Hors ligne Rédacteur Points: 665 Défis: 0 Message

Programmer un addin directement sur une calculatrice

Posté le 11/10/2020 20:06

CECI EST UNE EBAUCHE POUR UN TDM

TDM #21 : Les animations et les structures

Le Tutoriel du Mercredi (TDM) est une idée proposée par Ne0tux, qui recouvre tous les usages de la calculatrice - des applications de Casio à la conception de jeux en passant par la production artistique.

Aujourd'hui, nous allons voir les animations en C/gint et leur rapport avec la POO (Programmation Orientée Objet)
Niveau : ★★★★☆
Tags : Animations, gint, POO

Bonjour et bienvenue dans ce TDM #21 !

Aujourd'hui nous allons parler des animations en C pour calculatrices et de comment les créer avec les structures !
Je précise que ce tutoriel contient des codes en C pour gint de Lephenixnoir, mais le code doit être facilement convertible pour le SDK "officiel" avec un poil de jugeote !

Commençons sans plus tarder par des révisions :

Qu'est ce qu'une animation ?

La question paraît bête : oui, je sais ce qu'est une animation : c'est une suite d'images passées très vite qui donne une impression de mouvement !

Oui, effectivement, bravo !
Mais dans un jeu vidéo ?

Vous savez peut être qu'un jeu vidéo est, en général, constitué d'une boucle principale. Par exemple, pour détecter si l'utilisateur appuie sur la touche [EXE], il va y avoir une boucle principale, dans laquelle le jeu détecte si l'utilisateur appuie sur la touche. En algorithmique ça donne ca :
Répéter ∞ fois {
Si touche [EXE] est pressée : {
//faire l'action
}
}


et, en C/gint on a approximativement ca :

int main void(){
    while(True){
        if(getkey().key == KEY_EXE){
             //faire l'action    
        }
    }
}

Mais...attendez...une boucle qui change selon l'environnement et qui va très vite...ça ne vous rappelle pas quelque chose ?

Oui, les animations !

Animations et boucle principale


Prenons par exemple une "boucle" d'animation (une animation qui se répète toutes les 3 images par exemple).
On pourrait organiser un truc comme ça : on crée une boucle, et les images s'affichent chacune une répétition de la boucle sur 3.
On pourrait alors imaginer un truc du genre :

A la première répétition : afficher image1
A la deuxième répétition : afficher image2
A la troisième répétition : afficher image3

Puis on recommence au début !

C'est un bon moyen de faire une animation, mais comment la réaliser ?
Avec une variable, du genre :

Nouvelle variable nommée "a" = 1

Répéter ∞ fois : {
si a = 1 alors afficher la première image
si a = 2 alors afficher la deuxième image
si a = 3 alors afficher la troisième image

si a = 1 alors mettre la variable "a" à 2
sinon si a = 2 alors mettre la variable "a" à 3
sinon si a = 3 alors mettre la variable "a" à 1


}

?

En soi cela marche mais ce code est long et n'est pas très lisible, il faut de la concentration pour le comprendre.


Et puis, imaginez que vous vous retrouvez avec une animation contenant 3 images (que je vais appeler dorénavant des "frames"), le code serait complexe et illisible : on appelle cela un code spaghetti

Voici la représentation mathématique d'un code spaghetti :


C'est pas beau à voir, hein ?.
Le second problème, c'est que tous les "si ... alors ... sinon ..." sont placés dans le sinon du premier "si ... alors ... sinon ...", ce qui pose des problèmes : si le premier "si ... alors ... sinon ..." a un problème faisant que le "sinon" ne sera jamais exécuté, tout le reste est à l'arrêt.

On appelle cela les dépendances : certaines lignes de code sont dépendantes d'autres lignes, et cela peut poser problème, et peut créer l'effet domino : en effet, imaginons que dans un code toutes les lignes sont dépendantes (ce qui est très peu probable), un problème qui ne concerne que la ligne 1 va arrêter la ligne 2 car elle est dépendante de la ligne 1, la ligne 2 va arrêter la ligne 3, la 3 va arrêter la 4 etc...

Mais alors, pourquoi mettre tout le code dans des "sinon" ?


Très bonne question. Pour y répondre je vais prendre un exemple de code en algorithmique que j'appelle " l'interrupteur " : un texte est affiché à l'écran, "1" ou "0", et quand l'utilisateur appuie sur une touche, disons [EXE], l'état du texte change : si "0" était affiché on affiche maintenant "1" et vice-versa.
Cela donne :

Répéter ∞ fois : {
Afficher la variable "a"
Si la touche EXE est pressée alors :
Si la variable "a" = 0 alors mettre la variable "a" à 1
Sinon mettre la variable "a" à 0
}

Le sinon est indispensable : réfléchissons. Imaginons que l'on ne le mette pas, on a ça :
Répéter ∞ fois : {
Afficher la variable "a"
Si la touche EXE est pressée alors :
Si la variable "a" = 0 alors mettre la variable "a" à 1
Si la variable "a" = 1 alors mettre la variable "a" à 0
}

La suite imagine que a = 0 au départ : lorsque EXE est pressé on a cette ligne : Si la variable "a" = 0 alors mettre la variable "a" à 1
Or a = 0 donc ce if s'exécute et a = 1.
Ensuite : Si la variable "a" = 1 alors mettre la variable "a" à 0
Depuis la ligne précédente a = 1 donc ce if s'exécute donc a = 0.
Au final, a n'a pas changé, le code ne marche pas.
Le sinon ne vérifie pas la condition avant de s'exécuter mais avant d'exécuter le if, donc ici cela marche.

Attends... j'ai une idée... pourquoi ne pas créer une variable framesuivant pour chaque image ? Et dans le code on dit : affiche le frame actuel et met le frame actuel au frame suivant !


Effectivement, c'est la solution, mais... comment faire ?
Les variables sont multipliées par 2 ; pour 3 frames on a ces variables : frame1 ; frame1next ; frame2 ; frame2next ; frame3 ; frame3next.
Et cela en fait 6 !
Encore là, c'est acceptable, mais imaginez une animation de 60 frames : on a 120 variables !
Et si en plus chaque frame a une position x et une position y, ce qui est plus propre, chaque frame a 4 variables ; pour le frame 1 ces variable sont : frame1 (l'image) , frame1next, frame1posx , frame1posy.
Pour une animation de 60 frames, cela représente tout de même 240 variables !
Cela impacte en premier lieu le développeur, qui ne s'y retrouvera pas dans ses variables, mais aussi la machine, car les variables prennent de la RAM, et l'utilisateur, qui va voir le programme ralenti.

Ha, j'ai une idée ! Et si on... heu... ha non...heu...


Bon, j'ai la solution, ne cherchez pas.
Et si on utilisait...

La POO (Programmation Orientée Objet)

On m'informe dans l'oreillette que j'ai dit un mot compliqué...
Ne vous inquiétez pas, je vais expliquer.
Je demande juste aux programmateurs pointilleux de ne pas me cracher dessus : je vais résumer un max.

Résumons... nous aurions besoin de plusieurs variables par frames...
La programmation orientée objet est un style d'écriture du code, et Wikipédia dit ici que :
Dans ce style, le code source est une suite de descriptions de classes ou de prototypes, avec la description de leurs caractéristiques ( propriétés ) et de leurs comportements ( méthodes ).


Ne paniquez pas.
En POO, on crée des objets, et les variables ont des "états" en fonction de ces objets.
Prenons un exemple : je veux faire un programme simple dans un langage quelconque qui demande à l'utilisateur le nom de l'animal et la caractéristique, et le programme donne le résultat (Exemple : le programme demande le nom de l'animal, l'utilisateur répond "Chien", il demande la caractéristique, l'utilisateur rentre "Cri" et le programme renvoie "Wouf !").
Pour cela on pourrait faire un truc du genre : (en algorithmique)
Afficher : "Quel animal ?"
Attendre la saisie de l'utilisateur et la stocker dans la variable "animal"
Afficher : "Quelle caractéristique ?"
Attendre la saisie de l'utilisateur et la stocker dans la variable "caractéristique"
Si animal = "chien" : {
Si caractéristique = "Cri" : {
Afficher "Wouf !"
}
Si caractéristique = "Poids" : {
Afficher "Le poids moyen se situe entre 15 et 25 kg."
}
Si animal = chat : {
Si caractéristique = "Cri" : {
Afficher "Miaou !"
}
Si caractéristique = "Poids" : {
Afficher "Le poids moyen se situe entre 4 et 6 kg."
}
}

Vous le voyez, ce code est long et il faut du temps pour le comprendre.
L'inventeur de la POO a trouvé ce problème embarrassant, et voici sa solution : on crée deux variables : Cri et Poids.
On crée deux "objets" : chat et chien, et pour chaque objet une "version" différente de la variable est crée : par exemple il existe deux versions de la variable Cri : celle du chat et celle du chien.

Voici une partie du code amélioré avec la POO :

Nouvelle variable "Cri"
Nouvelle variable "Poids"
Nouvel objet "Chien" : {
    Sa version de "Cri" = "Wouf !"
    Sa version de "Poids" = 20
}
Nouvel objet "Chat" : {
    Sa version de "Cri" = "Miaou !"
    Sa version de "Poids" = 4
}

(J'ai indenté pour la lisibilité)
Oui, c'est perturbant mais vous allez vous y faire.
Tous mes objets sont des animaux, mais imaginons que je veuille créer un objet "fourmi", pour laquelle je veux enlever la variable "cri".

Facile : on ajoute au code précédent :
Nouvel objet "Fourmi" : {
    Sa version de "Poids" = "150 milligrammes"
}
!


En soi oui. Mais la programmation est pleine de règles, et on ne peut pas choisir de mettre ou non une variable. C'est un peu comme pour un livre : si tu écris un roman mais que tu ne trouves pas de nom, tu ne peux pas décider de ne pas en mettre.

Il va falloir créer des "types" d'objets. On va par exemple créer le type "Animal", dans lequel on va créer les variables "Poids" et "Cri", et créer le type "Insecte" dans lequel on va créer la variable "poids" ; en programmation on appelle ces types des "classes". On peut alors obtenir un truc du genre :
Nouvelle classe "Animal" : {
    Elle contient la nouvelle variable "Cri"
    Elle contient la nouvelle variable "Poids"
}
Nouvelle classe "Insecte" : {
    Elle contient la nouvelle variable "Poids"
}
Nouvel objet "Chien" de type "Animal" : {
    Sa version de "Cri" = "Wouf !"
    Sa version de "Poids" = 20
}
Nouvel objet "Chat" de type "Animal" : {
    Sa version de "Cri" = "Miaou !"
    Sa version de "Poids" = 4
}
Nouvel objet "Fourmi" de type Insecte : {
    Sa version de "Poids" = "150 milligrammes"
}


On touche au but ! Mais, pour les entrées de l'utilisateur ?
En POO, on peut récupérer la "version" d'une variable via cette syntaxe : (la plus courante)
[Nom_de_l'objet].[nom_de_la_variable]
Par exemple, dans notre cas, écrire dans mon programme Afficher Fourmi.Poids affichera "150 milligrammes", ou écrire Afficher Chien.Cri affichera "Wouf !".
On pourrait donc faire ca :

Afficher : "Quel animal ?"
Attendre la saisie de l'utilisateur et la stocker dans la variable "animal"
Afficher : "Quelle caractéristique ?"
Attendre la saisie de l'utilisateur et la stocker dans la variable "caractéristique"
Nouvelle classe "Animal" : {
    Elle contient la nouvelle variable "Cri"
    Elle contient la nouvelle variable "Poids"
}
Nouvelle classe "Insecte" : {
    Elle contient la nouvelle variable "Poids"
}
Nouvel objet "Chien" de type "Animal" : {
    Sa version de "Cri" = "Wouf !"
    Sa version de "Poids" = 20
}
Nouvel objet "Chat" de type "Animal" : {
    Sa version de "Cri" = "Miaou !"
    Sa version de "Poids" = 4
}
Nouvel objet "Fourmi" de type Insecte : {
    Sa version de "Poids" = "150 milligrammes"
}
Afficher Animal.Caractéristique

Et on arrive au résultat souhaité !

Mais les animations dans tout ca ?
Ca arrive...

POO et animations

On pourrait par exemple faire un truc comme cela pour relier les 2 sujets...

Nouvelle classe "frames" : {
    Nouvelle variable "Image"
    Nouvelle variable "Nextframe"
    Nouvelle variable "Posx"
    Nouvelle variable "Posy"
}
Nouvel objet "Frame1" de type "frames" : {
    image = image_frame1
    nextframe = "Frame2"
    Posx = 1
    Posy = 10
}
Nouvel objet "Frame2" de type "frames" : {
    image = image_frame2
    nextframe = "Frame3"
    Posx = 1
    Posy = 10
}
Nouvel objet "Frame3" de type "frames" : {
    image = image_frame3
    nextframe = "Frame1"
    Posx = 1
    Posy = 10
}
Nouvelle variable "FrameActuel" = Frame1
Répéter ∞ fois : {
   Afficher FrameActuel.image
   Attendre 25 ms
   FrameActuel = FrameActuel.nextframe
}

On commence à y arriver !
Ici, on a une animation qui fonctionne, mais qui ne s'arrête pas.
Il faudrait créer une variable de type boolean isAnimated, la mettre à true si on appuie sur le bouton permettant d'avancer, et l'animation se fait seulement si isAnimated est à true.
Et pour savoir quand l'animation est finie, on crée une variable AnimateTime, sorte de décompte avant la fin du frame.
On a ce code :
Nouvelle classe "frames" : {
    Nouvelle variable "Image"
    Nouvelle variable "Nextframe"
    Nouvelle variable "Posx"
    Nouvelle variable "Posy"
}
Nouvel objet "Frame1" de type "frames" : {
    image = image_frame1
    nextframe = "Frame2"
    Posx = 1
    Posy = 10
}
Nouvel objet "Frame2" de type "frames" : {
    image = image_frame2
    nextframe = "Frame3"
    Posx = 1
    Posy = 10
}
Nouvel objet "Frame3" de type "frames" : {
    image = image_frame3
    nextframe = "Frame1"
    Posx = 1
    Posy = 10
}
Nouvelle variable "FrameActuel" = Frame1
Répéter ∞ fois : {
   Si touche avancer est pressée : {
        Mettre isAnimated à true
        Mettre AnimateTime à 3
        //3 car il y a 3 frames avant la fin de l'animation
   }
   Si isAnimated = true : {
        Afficher FrameActuel.image
        Attendre 25 ms
        FrameActuel = FrameActuel.nextframe
        Enlever 1 à AnimateTime
        Si AnimateTime = 0 : {
             //l'animation est terminée
             Mettre isAnimated à false
        }
   }
   Sinon : {
        //Idle est l'image de la position inactive
        Afficher Idle
   }
}

Bon, on a la base, maintenant...

POO en C/gint

Bon, super, nous avons le code en algorithmique !
Mais je vous rappelle que gint, lui, est en C !
Alors comment passer de l'un à l'autre ?

En C/gint, les mots "classe" et "objet" n'existent pas : ils sont remplacés par les "structures".
Pour définir l'équivalent d'une classe, rien de plus simple :
struct name_of_class {
int variable1;
long variable2;

}

Pour définir un objet, c'est plus compliqué. Je vais d'abord donner la syntaxe d'un objet faisant partie de la classe "name_of_class" crée précédemment :
struct  name_of_class name_of_object[2] {
{12,14}
//Dans l'exemple précédent, la valeur de la variable variable1 pour l'objet name_of_object[1] est 12 et la valeur de la variable variable2 pour l'objet name_of_object[1] est 14  
{20,41}
}

Alors, je sais que c'est difficile à comprendre, mais chaque objet créé est une liste d'objets.
Mais en soi cela peut être une bonne idée : on crée une "liste d'objets" pour chaque animations, et chaque objet est un frame.
Concrètement, voyons le code de la classe anim (ou plutôt de la structure anim), je vous le donne et vous explique après :
struct anim {
     bopti_image_t *img;
     int duration;
     struct anim *next;
};

La 1ère variable, bopti_image_t *img; est la variable contenant l'image.
La 2ème, duration, contient le nombre de frames sur lesquels l'image va rester avant de passer à une autre animation
La 3ème, struct anim *next;, est un pointeur.
C'est une variable qui envoie vers une autre variable. Ici, elle contient le frame suivant, qui est aussi de type struct.
Voici donc ce qu'on obtient pour l'animation de marche :
struct anim anim_walk[2] = {
    { &img_personnagemarche, 3 , &anim_walk[1] },
    { &img_personnage, 3, &anim_walk[0] },
};

Pour la facilité du code on va ajouter une animation idle :
struct anim anim_idle[1] = {
    { &img_personnage, 1, &anim_idle[0] },
};

Et voici finalement tout le code des structures, à mettre avant int main(void) :
struct anim {
     bopti_image_t *img;
     int duration;
     struct anim *next;
};

struct anim anim_idle[2] = {
    { &img_personnage, 40, &anim_idle[1] },
    { &img_personnage2, 40, &anim_idle[0] },
};
struct anim anim_walk[2] = {
    { &img_personnagemarche, 3 , &anim_walk[1] },
    { &img_personnage, 3, &anim_walk[0] },
};


Pour créer la variable current_anim, sachant que celle ci est un pointeur, il faut faire :
struct anim *current_anim = &anim_idle[0];



&anim_idle[0] est l'animation par défaut, sachant qu'en arrivant sur l'add-in le personnage est normalement en position idle.

Et voici toutes les variables à définir avant la boucle :


    struct anim *current_anim = &anim_idle[0];
    int current_anim_time_left = 0;
    extern bopti_image_t img_personnage;
    extern bopti_image_t img_personnagemarche;
    /* État du personnage : 0=arrêté, 1=marche */
    int state = 0;
    /* État du personnage au frame précédent */
    int previous_state = 0;
    

Pour l'affichage de notre animation, rien de compliqué : on affiche aux positions x et y de current_anim l'image de current_anim comme ceci :
dclear(C_WHITE);
dimage(current_player->x,current_player->y, current_anim->img);
dupdate();

Ensuite on va lire les entrées du joueur ; et pour cela nous allons utiliser keydown qui nécessite un clearevents(); qui va effacer les évènements précédents.
Lors de l'appui sur une touche il va falloir changer d'animation : pour faire cela proprement, on va créer 2 variables : state, qui va contenir l'état de notre personnage (si la touche permettant d'avancer est pressée, state = 1) et previous_state, qui contient le state du frame précédent.
Si state = 1 mais que previous_state = 0, on vient de commencer à marcher, et on peut donc passer à l'animation de marche, et vice-versa.
Ca donne : (entrées + test des variables state et previous_state)
clearevents();
state = 0;
if(keydown(KEY_RIGHT))
      state = 1;
if(previous_state == 0 && state == 1)
{
      /* On vient de commencer à marcher */
      current_anim = &anim_walk[0];
      current_anim_time_left = current_anim->duration;
}
else if(previous_state == 1 && state == 0)
{
      /* On vient de s'arrêter */
      current_anim = &anim_idle[0];
      current_anim_time_left = current_anim->duration;
}


Bon, ca c'est si on vient de commencer à marcher, ou de s'arrêter, mais si il n'y a aucun changement ?
Et bien, on enlève 1 à current_anim_time_left et, si il est égal à 0, on met current_frame au frame suivant
et current_current_anim_time_left à current_anim_time_left = current_anim->duration !
Voici le code : (à placer après le bout de code précédent, le else correspond à " if(previous_state == 0 && state == 1) ")
        else
        {
            /* On continue l'anim précédente */
            current_anim_time_left--;
            if(current_anim_time_left <= 0)
            {
                current_anim = current_anim->next;
                current_anim_time_left = current_anim->duration;
            }
        }

Puis, si state = 1, on ajoute 1 à x pour que le personnage avance comme ceci :

if(state == 1)
        {
                x = x+1;
     }
        
        }

Enfin, on met le délai d'attente, puis on met previous_state à state :
        /* Délai */
        sleep_us(25000);

        /* Préparation des invariants du frame suivant */
        previous_state = state;

Et voilà !

Voici le code entier :

#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/clock.h>
extern bopti_image_t img_personnage;
extern bopti_image_t img_personnagemarche;

struct anim {
     bopti_image_t *img;
     int duration;
     struct anim *next;
};

struct anim anim_idle[2] = {
    { &img_personnage, 40, &anim_idle[1] },
    { &img_personnage2, 40, &anim_idle[0] },
};
struct anim anim_walk[2] = {
    { &img_personnagemarche, 3 , &anim_walk[1] },
    { &img_personnage, 3, &anim_walk[0] },
};
int main(void)
{
    struct anim *current_anim = &anim_idle[0];
    int current_anim_time_left = 0;
    extern bopti_image_t img_personnage;
    extern bopti_image_t img_personnagemarche;


    /* État du personnage : 0=arrêté, 1=marche */
    int state = 0;
    /* État du personnage au frame précédent */
    int previous_state = 0;

    while(a != 1)
    {
        /* Affichage */
        dclear(C_WHITE);
        dimage(current_player->x,current_player->y, current_anim->img);

        dupdate();
        /* Lecture des entrées ; si on n'appuie sur rien, state=0 */
        clearevents();
        state = 0;


        if(keydown(KEY_RIGHT))
            state = 1;

        /* Exécution des animations */

        if((previous_state == 0 && state == 1) || (previous_state == -1 && state == 1))
        {
            /* On vient de commencer à marcher */
            current_anim = &anim_walk[0];
            current_anim_time_left = current_anim->duration;
        }
        else if(previous_state == 1 && state == 0)
        {
            /* On vient de s'arrêter */
            current_anim = &anim_idle[0];
            current_anim_time_left = current_anim->duration;
        }
        else
        {
            /* On continue l'anim précédente */
            current_anim_time_left--;
            if(current_anim_time_left <= 0)
            {
                current_anim = current_anim->next;
                current_anim_time_left = current_anim->duration;
            }
        }

        /* Simulation du monde */
              
        if(state == 1)
        {

          xref = xref-1;
        
        
        }    

        /* Délai */
        sleep_us(25000);

        /* Préparation des invariants du frame suivant */
        previous_state = state;
    }

    getkey();
    return 1;
}


On a à présent une belle animation !

Conclusion

Vous avez appris dans ce tutoriel les bases des animations, la POO et comment l'adapter en C/gint !

J'espère que ce TDM vous aura aidé dans la réalisation de vos animations, j'ai été très content de le faire !

Si vous avez des questions, lâchez vous en commentaires !
Liens utiles
Voir le TDM précédent : Comprendre et utiliser le path sous Linux


Massena Hors ligne Rédacteur Points: 1660 Défis: 11 Message

Citer : Posté le 11/10/2020 20:07 | #


Non.
Mais je laisse l'honneur à quelqu'un qui s'y connait mieux que moi t'expliquer ça
Kbd2 Hors ligne Membre Points: 239 Défis: 0 Message

Citer : Posté le 11/10/2020 20:07 | #


Not until someone ports a C compiler to the calculator, which is very unlikely considering the size of a compiler and its backend.
Potter360 Hors ligne Rédacteur Points: 665 Défis: 0 Message

Citer : Posté le 11/10/2020 20:08 | #


Kbd2 a écrit :
Not until someone ports a C compiler to the calculator, which is very unlikely.


Ok, thank you !

...

My english is very bad...
Hop là... toi qui lis cette signature... tu pourrais aussi aller voir mon projet Elphorina, un jeu de RPG-building !
Lephenixnoir Hors ligne Administrateur Points: 19546 Défis: 142 Message

Citer : Posté le 11/10/2020 20:37 | #


Il y a WSC et FVM qui sont une sorte d'interpréteur C, mais ça ne va (et n'ira jamais) très loin. Y'a pas de linker en particulier donc tout add-in de taille moyenne à grande doit se faire sur un PC. Compte tenu de la puissance des outils disponibles, c'est aussi infiniment plus productif. Mais bon, tout le monde n'a pas accès à un PC :x
Yatis Hors ligne Membre Points: 547 Défis: 0 Message

Citer : Posté le 11/10/2020 21:25 | #


Avec mon début d'expérience avec Vhex (un kernel UNIX-like), j'arrivais à porter mes projets Epitech (écrit en C) sans toucher aux sources. Je n'ai vraiment pas beaucoup de connaissances avec le "comment GCC s'auto-build" mais si l'interface POSIX est bien respectée on devrait pouvoir porter GCC (et ses outils) dessus. (en théorie hein? Je ne connais pas la taille que pourrait avoir GCC si on prend juste le strict nécessaire mais ça devrait tourner aux alentours de 300 Mo(?), ce qui est assez pour y mettre sur une carte SD ).
Lephenixnoir Hors ligne Administrateur Points: 19546 Défis: 142 Message

Citer : Posté le 11/10/2020 21:29 | #


En-dehors de la taille nécessaire, on n'a juste pas assez de puissance proco, pas d'environnement C suffisant, pas d'environnement C++ suffisant (en particulier pas de lib standard C++), on n'a pas de système de fichiers assez propre pour installer GCC (la carte SD est une option mais il n'y quasiment que toi qui as une calto avec carte SD ^^"), et je ne sais pas quelles restrictions de BFile pourraient encore s'appliquer. Déjà binutils serait un challenge je pense.
Potter360 Hors ligne Rédacteur Points: 665 Défis: 0 Message

Citer : Posté le 11/10/2020 21:31 | #


Ok je vois...
Merci !
Hop là... toi qui lis cette signature... tu pourrais aussi aller voir mon projet Elphorina, un jeu de RPG-building !

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2021 | Il y a 33 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