Planète Casio - Vie communautaire - Flux RSS http://www.planet-casio.com Programmes Casio, Jeux, Cours pour Calculatrices Casio fr-FR https://www.planet-casio.com/images/logo.gif Planète Casio - Vie communautaire - Flux RSS http://www.planet-casio.com 55 50 Programmes Casio, Jeux, Cours pour Calculatrices Casio. Tue, 13 Apr 2021 16:09:00 GMT Tue, 13 Apr 2021 16:09:00 GMT contact@planet-casio.com (Planet Casio) contact@planet-casio.com (Planet Casio) 5 TDM #XX : Les animations et les structures de données https://www.planet-casio.com/Fr/forums/topic16659--.html 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 les structures de données 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 ! ;) Voici le résultat final : https://i.imgur.com/vp1ExtA.gif Durant ce tutoriel, j'utiliserai les frames suivants : https://i.imgur.com/l4L09nY.png Frame idle https://i.imgur.com/GhsLSYF.png Frame de marche Sommaire : 1) Qu'est ce qu'une animation ? 1.1) La boucle principale d'un jeu vidéo 2) Animation et boucle principale 2.1) Premières idées 2.2) L'utilité du sinon 2.3) L'apparition de la variable "frame suivant" 3) La POO (Programmation Orientée Objet) 3.1) Definition 3.2) L'exemple du catalogue d'animaux 4) S'inspirer de la POO pour les animations 4.1) Premières idées 4.2) Détection du clavier 5) Les structures de données en C 5.1) Equivalent des classes 5.2) Equivalent des objets 5.3) Affichage 5.4) Lire les entrées du joueur 5.5) Continuer l'animation précédente 5.6) Le code entier 6) Conclusion 7) Liens utiles 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 ? La boucle principale d'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 , 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 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 Premières idées 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 : https://s3.amazonaws.com/media-p.slid.es/uploads/paulcayon/images/417448/spaghetti.jpg 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. L'utilité du "sinon" 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 , 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 ? L'apparition de la variable "frame suivant" 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 s'inspirait de... 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... Définition 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. L'exemple du catalogue d'animaux 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 } 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... S'inspirer de la POO pour les animations Premières idées 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. Détection du clavier 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... Les structures de données en C 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 ? Equivalent des classes En C, la POO n'existe pas , mais il existe une solution similaire : les "structures". Pour définir l'équivalent d'une classe, rien de plus simple : struct name_of_class { int variable1; long variable2; } Equivalent des objets Pour définir l'équivalent d'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 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; Affichage 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(); Lire les entrées du joueur 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; } Continuer l'animation précédente 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à ! Le code entier 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)) { //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, celle ci normalement : https://i.imgur.com/vp1ExtA.gif Conclusion Vous avez appris dans ce tutoriel les bases des animations, la POO et son équivalent en C, les structures de donnés et comment utiliser ces dernières 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 ! Merci à Lephenixnoir et à Dark storm pour leur aide qui m'a été précieuse ! Si vous avez des questions, lâchez vous en commentaires ! Liens utiles :here: Voir le TDM précédent : Comprendre et utiliser le path sous Linux :here: Consulter l'ensemble des TDM Wed, 10 Feb 2021 18:25:53 +0100 Press Shift #5 - Mipjabok (Louloux) https://www.planet-casio.com/Fr/forums/topic16632--.html À tour de rôle, les rédacteurs de Planète Casio présentent un jeu innovant, drôle, beau ou bien conçu. Blockbuster ou trésor oublié, venez (re)découvrir des jeux d'une qualité remarquable ! Aujourd'hui, nous allons voir... Mipjabok de Louloux ! Ceci est mon 1er Press Shift ! Le projet Bonjour et bienvenue dans ce 5ème Press Shift ! Aujourd'hui nous allons parler de Mipjabok, un très bon jeu de Louloux ! Il s'agit d'un jeu de plateforme, on l'on incarne un spectre, ou plutôt des spectres, puisque l'on peut incarner plusieurs personnages. De façon générale, c'est le spectre Mipjabok que l'on incarne, mais lui même peut incarner plusieurs personnages, comme Banshy, Bobby, Quadry ou Bluggy. Mais on peut aussi créer nos personnages, ce qui va nous permettre de mieux passer les obstacles. Mais commençons tout de suite avec... Un jeu de plateforme très complet Mipjabok est un jeu très complet, avec ses 22 niveaux, ce qui en fait selon son créateur, Louloux, " le plus grand jeu de plateforme de l'histoire de la programmation sur calculatrices". Pour ma part, je n'ai pas vérifié ! Ces 22 niveaux sont longs, ce qui en fait un jeu très complet ! Le but du jeu : trouver les 22 clés des 22 niveaux, et ce ne sera pas une mince affaire ! Les personnages Dans Mipjabok, nous avons le choix entre différents personnages. Le dernier est un peu particulier puisque c'est un personnage entièrement personnalisable, il coûte 2000 pièces. Dans ce menu (Menu principal → Magasin), descendez jusqu'en bas puis (pas besoin d'acheter le personnage modifiable pour le modifier, par contre il faut l'avoir acheté pour l'utiliser), vous allez voir... Vous arrivez devant cela : https://i.imgur.com/eOcfQLn.jpg Là, rien de plus simple, pour changer l'état d'un "pixel", les flèches pour se diriger et pour sortir. Si vous avez assez d'argent, vous pouvez acheter ce personnage, c'est . Mais justement, comment gagner l'argent ? A chaque partie, vous amassez de l'argent présent dans les niveaux, et lorsque vous avez assez, vous pouvez acheter un personnage. Sans plus tarder passons à la suite... Le système de jeu Niveau gameplay, rien de plus simple : pour sauter, et les flèches pour se diriger, comme dans beaucoup de jeux sur calculettes d'ailleurs ! ;) Les blocs sont variés : il y a les blocs "basiques", mais d'autres plus complexes, comme les ascenseurs. Ces derniers permettent de monter, ou de descendre (selon le sens de l'ascenseur, pour la montée le personnage est attiré vers le haut, l'inverse pour la descente). Nous pouvons aussi trouver les pics, sur lesquels il ne faut pas tomber sous peine d'un Game Over, écran de Game Over d'ailleurs très stylé (des pixels noirs remplissent peu à peu l'écran), les pièces, dont nous avons vu l'utilité précédemment, les portes (activées par une commande que je ne révèlerais pas, je crois que c'est une sorte d' "easter egg" ;) ), les trampolines, permettant de sauter plus haut, et les clés, qui signent la fin du niveau. J'ai aussi trouvé les champignons, et autres blocs "décoratifs". Je ne sais pas si je dois dire ce qu'il se passe à la fin, donc je le mets en spoiler : A la fin des 21 niveaux, votre personnage arrive devant Dracofeu, qui vous pose une énigme, dont je ne donnerais pas la réponse ;) . Vous êtes alors redirigé vers un niveau "bonus", qui vous permettra de finir le jeu. A la fin du jeu, un texte de fin défile expliquant une histoire, pas super claire j'avoue :lol: , entre le bien et le mal. Le jeu est à présent terminé, mais vous pouvez toujours jouer aux autres niveaux, pour débloquer les personnages qui ne le seraient éventuellement pas encore ;) Ce Press Shift est à présent terminé, Mipjabok est en tout cas un très bon jeu, et après l'avoir fini 2 fois je ne m'en lasse pas ! Un grand bravo à Louloux, à bientôt pour un nouveau Press Shift, et... Enjoy ! ... et à bientôt sur planet-casio ! Le Press Shift précedent : Press Shift #4 - Aventura, le Royaume Poudingue (Drak) Fri, 15 Jan 2021 19:13:36 +0100 Liste des jeux qui ne marchent pas sur Prizoop https://www.planet-casio.com/Fr/forums/topic16595--.html Bonjour ! Je crée ce topic suite à celui là. Ici, vous pourrez donc prévenir dans les commentaires si un jeu ne marche pas sur Prizoop. Je commence avec... Liste : - Les jeux créés sur GB Studio. Un message a d'ailleurs été mis au développeur de Prizoop, sans réponse. Sun, 20 Dec 2020 18:45:41 +0100 Que faites vous là ? https://www.planet-casio.com/Fr/forums/topic16503--.html Non c'est pas un article, désolé j'ai pas le temps en ce moment C'est vrai ça ! Ça fait longtemps que je n'ai pas demandé quelque chose ici, ça me manquait un peu, alors voilà ce nouveau sujet : C'est une question qu'on ne pose pas souvent, certaines personnes ici on même tellement été présent qu'ils en on oublié leurs but initial de venir sur le forum ! Mais comme toute chose, pour venir ici, il faut le chercher ! Alors : Que faites vous là ? Bah non mais c'est vrai, pourquoi tu es là derrière ton écran ? Quand on y pense, avant de venir ici on avait forcément un but, une envie de trouver quelque chose ! Et en continuant, on peut se demander que faisons nous ici maintenant, pourquoi rester ici ? :) Comme à mon habitude, je commence : Pourquoi être venu ici initialement ? Et bien étonnamment, je pense ne pas être venu pour la première fois au lycée. Je pense que c'était bien au collège. Je commençais à vouloir m'amuser avec ce que j'avais, et j'étais tombé sur des vidéos de tricks sur calculatrice. Je pense que c'est la première fois que je suis venu sur ce forum : Pour voir des tricks sur calculatrice Puis après je suis repassé par ici pour apprendre comment fonctionnait le menu de programmation sur ma 35+E Et enfin, je suis resté ici depuis ce jour là. Maintenant, je pense que je peux dire que je reste pour la communauté, je n'ai plus besoin d'apprendre des choses sur calculatrice, mais je reste pour écrire et pour parler sur notre chère Shoutbox. Je continue bien sûr certains projets parce que la calculatrice est une plateforme qui m'intéresse beaucoup. Mais je reste surtout pour vous en fait :love: Hop, séquence émotion : check En tout cas, je me rend compte que c'est pas une question si simple à répondre, bonne chance pour ceux qui sont là depuis beaucoup trop d'années, va falloir vous souvenir de votre but initial :E C'est à vous ! Racontez donc ce que vous faites ici :) Et bientôt un article, faut bien que je retrouve une activité ici moi ! Sat, 17 Oct 2020 23:27:25 +0200 Je rends vos avatars moches https://www.planet-casio.com/Fr/forums/topic16486--.html J'adore GIMP. Et je l'utilise souvent pour rendre mon style enfantin encore plus moche. Alors quand l'occasion s'est présentée de remixer des avatars, évidemment, j'ai sauté sur l'occasion. https://bible.planet-casio.com/cakeisalie5/avatars_moches/lephe.png Lephenixnoir (référencé dans le DTC) https://bible.planet-casio.com/cakeisalie5/avatars_moches/breizh.png Breizh_craft https://bible.planet-casio.com/cakeisalie5/avatars_moches/filoji.png Filoji https://bible.planet-casio.com/cakeisalie5/avatars_moches/flamingkite.png FlamingKite https://bible.planet-casio.com/cakeisalie5/avatars_moches/eragon_v2.png Eragon https://bible.planet-casio.com/cakeisalie5/avatars_moches/hackcell.png Hackcell https://bible.planet-casio.com/cakeisalie5/avatars_moches/darks.png Dark storm https://bible.planet-casio.com/cakeisalie5/avatars_moches/redcmd.png Redcmd https://bible.planet-casio.com/cakeisalie5/avatars_moches/tituya.png Tituya https://bible.planet-casio.com/cakeisalie5/avatars_moches/eltoredo.png Eltoredo https://bible.planet-casio.com/cakeisalie5/avatars_moches/kirafi.png Kirafi https://bible.planet-casio.com/cakeisalie5/avatars_moches/totoyo.png Totoyo https://bible.planet-casio.com/cakeisalie5/avatars_moches/massena.png Massena https://bible.planet-casio.com/cakeisalie5/avatars_moches/ado.png Ado https://bible.planet-casio.com/cakeisalie5/avatars_moches/neotux.png Ne0tux Si vous voulez figurer dans cette liste, proposez-le et mouillez votre doigt, parce qu'il faut que je n'aie pas la flemme et ça c'est pas évident. :D Tue, 29 Sep 2020 23:35:20 +0200 Projet Vhex (Kernel pour les calculatrices Casio) https://www.planet-casio.com/Fr/forums/topic16469--.html Comme vous l'avez peut-être remarqué au cours de mes dernières activités sur PC, j'ai commencé à toucher pas mal au bas niveau ainsi qu'à faire des essais de projet ambitieux. Seulement, ces derniers jours, je me suis rendu compte que je bossais en sous-marin sur plusieurs projets en même temps et qu'ils mériteraient peut-être d'être mis en lumière (mais dans le pire des cas, les idées présentées serviront bien à quelqu'un, un de ces quatre :E ) C'est pourquoi j'ai créé ce topic, qui me permet de vous montrer ce que j'aimerais mettre en place et aussi pour voir si le projet pourrait potentiellement intéresser des personnes. Globalement, j'aimerais mettre en place plusieurs projets qui sont tous plus ou moins "interconnectés" entre eux et qui ont pour objectif principal de fournir un kernel UNIX-likeet libre pour les calculatrices Casio. Par contre, je préfère mettre les choses au clair dès le début, le projet n'a pas pour but d'être un kernel révolutionnaire, si vous avez envie de faire un OS meilleur que celui de Casio pour lancer des super-jeux en 3D, connecter votre calculatrice à Internet, ou encore avoir une interface plus jolie que ce bon vieux menu de nos Casio, ce n'est PAS le but premier du projet. C'est juste un projet qui me permet d'apprendre sur plein de domaines différents. Mais le temps commence à me manquer et j'aimerai laisser au moins une petite trace de mes idées avant que tout finisse sous le tapis. Vous avez ici la vue d'ensemble des projets : |----------------------------------------------------------| | Kernel / OS | Librairies | |-------------------------|--------------------------------| | fxBoot (bootloader) | fxlibc (C standard librairies) | | |-- FixOS (OS) | fxCompositor (windows manager) | | `-- Vhex (kernel) | fxGUI (graphical librairies) | | |-- GladOS (OS) | | | `-- testOS (OS) | | |----------------------------------------------------------| Chaque partie que vous voyez la sera indépendantes pour permettre à quiconque le souhaite de participer au projet. Petite description des projets : FxBoot: (bootloader) C'est un bootloader qui permettra de charger les noyaux sur la machine (mais aussi les addins). C'est une des parties les plus importantes du projet et j'aimerais qu'il ait suffisamment de souplesse pour arriver à charger des OS qui n'ont pas été pensé pour être loader (par exemple FixOS). FixOS: (OS) Un OS pour les calculatrices SH3 développé par Kristaba il y a quelques années maintenant. Il ne fait pas partie du projet mais c'est juste pour indiquer que Vhex ne sera probablement pas porté sur SH3 pour des raisons techniques (et matériel car je n'ai pas de SH3 fonctionnel sous le coude). Vhex: (kernel) La pièce maitresse du projet. C'est mon kernel que j'ai développé cette année et qui étais presque arrivé au stade de FixOS. Cependant, l'architecture ne me plait pas (monolithique non-modulaire) et j'aimerais que chaque fonctionnalité du noyau puisse être chargé sur demande (via des modules kernel, qui seront probablement des librairies dynamique). Un topic sera créé (ou je récupèrerais l'ancien topic de Vhex comme thread principal ?) pour vous tenir au courant des dernières avancées et pour vous permettre de me proposer des correctifs ou des features que vous aimeriez bien voir sur le noyau (je ne vous promets pas de les réaliser ceci-dit :E ) GladOS: (OS s'appuyant sur Vhex) C'est mon premier prototype de kernel que j'avais commencé à réaliser il y a plus d'1 an maintenant. Il a toujours pour objectif de remplacer Casio de la machine mais il se basera sur Vhex pour fonctionner (et non un truc custom). Il permettra d'utiliser la machine à son plein potentiel (driver USB, gestion de la mémoire virtuelle, EEPROM, ...). TestOS: (OS s'appuyant sur Vhex) C'est un "OS" qui, actuellement, se base sur un fork de Vhex et qui me permet de tracer l'OS de Casio pas-à-pas, faire des tests hardware, analyser la RAM. C'est un truc absolument pas stable mais très utile pour faire de la rétro-ingénierie directement sur la calculatrice. Il se basera entièrement sur Vhex à l'avenir. Par contre, je ne pense pas donner les sources avant de l'avoir sécurisé un minimum (car le code manipule beaucoup de choses dangereuses pouvant casser la calculatrice si on ne sait pas ce qu'on fait. (si vraiment vous les voulez, je peux vous les donner hein? Faites juste gaffe avec)). fxlibc: (librairie standard C pour les calculatrices Casio) C'est un projet que j'ai commencé hier et qui a pour but de fournir une libraire standard pour les calculatrices et qui pourra être configurable (par exemple pour permettre de choisir l'ABI que l'on souhaite (Casio, Vhex ou FixOS), le format, ...). Elle sera utilisée pour la plupart des projets liés au noyau. fxGui: (libraire graphique) Ce sera une librairie qui fournira un moyen pour les gestionnaires de fenêtres "composite" de communiquer directement avec les applications graphiques ainsi que le matériel vidéo. fxCompositor: (compositing window manager) Ce sera un gestionnaire de fenêtres de Vhex (un logiciel chargé de l'affichage et du placement des fenêtres d'applications) qui reprendra le fonctionnement de Wayland. Elle sera basée sur les libs "bopti" et "topti" de Lephenixnoir (je pense). Ou est-ce que ça en est aujourd'hui ? Je suis encore en train de mettre sur papier la nouvelle architecture du noyau histoire de voir toutes les possibilités qui pourraient être implémentées. Mais je suis confronté à plusieurs problèmes techniques assez complexes à résoudre proprement, notamment concernant le chargement des modules kernel (sans rentrer dans les détailles, la toolchain utiliser ne permet pas de générer des librairies dynamiques qui sont essentielles pour charger des bouts de code "à-la volée") ce qui est fort cocasse étant donnée que la nouvelle architecture du noyau repose dessus :E . Aussi, je suis en train de documenter la machine le plus possible avant de me replonger dans le développement des projets. J'ai plusieurs cibles notamment : * Fugue, le "nouveau" système de ficher propriétaire utiliser par les "nouvelles générations" de calculatrice Casio. * Le driver USB de Casio. Grâce à Lephenixnoir, on a pu certifier que le module hardware qui gère l'USB et pratiquement le même que sur le SH7724 mais je n'arrive toujours pas avoir les infos sur le bus ainsi que de notifier l'hôte que je suis connecté. * l'ABI de la Graph90+E, qui n'est pas aussi biens connu que sur monochrome. À part ça, j'ai commencé à créer la fxlibc, la librairie C standard que j'utiliserai pour mes projets. Je sais que Memallox a porté newlib sur la calto mais j'ai besoin d'avoir quelque chose de suffisamment modulaire pour choisir quel ABI je veux utiliser (CASIOABS, Vhex ou FixOS) ainsi que le format de la librairie (statique '.a' ou dynamique '.so'). J'ai encore quelque hésitation sur le comment architecturer tout ça mais je ferrai un topic quand j'aurais à nouveau du temps devant moi. Dites-vous que le prototype est quasiment finis, il manque juste énormément de fonction (que j'ajouterai au fur et à mesure de mes besoins) ainsi que de l'optimisation sur toutes les fonctions. J'ai aussi commencé à poser sur papier les features du bootloader ainsi que sa documentation. Une fois le prototype de la fxlibc finie ce sera ma priorité. Là aussi je ferrais un topic quand j'aurais commencé a dev quelque chose. Tous ce que je peux dire pour l'instant c'est qu'il reposera uniquement sur les fonctionnalités de l'OS de Casio pour faciliter son portage. Au passage, ce projet a été passer en projet "Hub" à Epitech (mon école), ce qu'il signifie qu'il me permettra de valider une partie de mon année si j'arrive à le finir. Je sais d'avance que cette année ainsi que l'année qui arrive risque d'être compliqué pour continuer ces projets. C'est pourquoi, si vous avez envie de participer, vous êtes les bienvenus ! Prévisions avant juin 2021 J'aimerai avoir : * un prototype correct du bootloader pouvant tourner sur toutes les calculatrices Casio qui supporte les addins. * la libc supportant l'ABI de Vhex ainsi que la création de librairies dynamique. * une documentation / organisation correcte pour que n'importe qui puisse continuer. * un "prof-of-concept" de Vhex en version modulaire. J'espère sincèrement que le projet prendra vie et arrivera à maturité. Dans tous les cas, de tous les projets annoncés, j'ai déjà réalisé des "profs of concept" qui traine de mon côté, je peux donc vous affirmer que le projet serait réalisable ! Le challenge va être d'organiser et maintenir tout ça dans le temps. Fri, 18 Sep 2020 23:23:09 +0200 PANNE - tools.planet-casio.com https://www.planet-casio.com/Fr/forums/topic16338--.html Bonjour, le sous domaine tools.planet-casio.com est inaccessible, dont le générateur de cours. je vous signale la panne en espérant que vous puissiez la régler avant que mon concours arrive :'( Merci Tue, 16 Jun 2020 13:41:23 +0200 Thèmes shoutbox https://www.planet-casio.com/Fr/forums/topic16300--.html Vu qu'on est plusieurs à utiliser des thèmes customs sur la shoutbox, je vous propose de les partager ici (plutôt que sur une page random d'un topic random). Pour les utiliser, il faut installer une extension de navigateur. Je recommande Stylus, disponible pour la majeure partie des navigateurs (Firefox + Chrome et ses dérivés). Créez un style pour la page `https://www.planet-casio.com/Fr/shoutbox*`, puis copiez le contenu du style. Essayez de mettre des screenshots avec le code. :) Thu, 14 May 2020 10:42:45 +0200 Je reçois des notifications e-mail pour les réponse au sujets de discussion que je n'ai jamais suivi https://www.planet-casio.com/Fr/forums/topic16283--.html Je reçois des notifications e-mail pour les réponse au sujets de discussion que je n'ai jamais suivi. Par exemple, j'ai répondu au topic de Bust-a-Move en laissant l'option "Me prévenir par email lorsqu'une réponse est postée" désactivée, et je reçois des e-mail quand même. De plus, ces e-mails ne contiennent aucun lien pour se désabonner. Sat, 02 May 2020 21:09:37 +0200 Odyssée : Question pour la réunion de demain https://www.planet-casio.com/Fr/forums/topic16264--.html Voici la liste des questions auxquelles nous devront répondre pendant la réunion de demain (mettez les en commentaire pour que je les ajoutes) : X = absolument nécessaire → Choisir la plateforme (étudier les différentes caractéristiques des calculatrices) X → Définir le système de map (précisement !) X ⇒ map avec ou sans scrooling ? ⇒ La taille de la map attendue → Définir le nombre de niveau de tiles ainsi que leur tailles X → Réfléchir au textures actuelles, ainsi que aux prochaines → Voir si l'on utilise la tileset de Pokémon (ou une autre si vous en connaissez) → Définir le système de sauvegarde (de manière globale) → Est-ce que les maps sont continues (eg. Pokémon) ou ont des zones de transition ? ________ | | → Définir le système d'interaction (PNJs, coffres, objets etc...) | | → Definir le système d'évènement (déclenchement de combats, cutscenes, etc...) | | → Savoir si ces deux systèmes sont liés à la map ou indépendant |________ Encore une fois, n'oubliez pas de mettre les vôtres en commentaire. Vous pouvez également exposer vos réponses avant la réunion. Tue, 21 Apr 2020 13:50:00 +0200