Forums Casio - Vos tutoriels et astuces

Index du Forum > Vos tutoriels et astuces > [Tutoriel] La gestion du clavier en C
Lephenixnoir
Hors ligne
Administrateur
Points: 12507
Défis: 136
Message
Posté le 17/02/2016 14:11

[Tutoriel] La gestion du clavier en C :

Pour des questions de pratique ou d'habitude, beaucoup d'entre nous utilisent des fonctions comme IsKeyDown() pour gérer leurs entrées claviers. C'est mal, et voici pourquoi.

Le problème

Le principe d'un programme disposant d'une interface graphique est simple : il travaille quand l'utilisateur lui donne du boulot et le reste du temps il attend patiemment de recevoir des ordres (travailleur acharné, je vous dit), et se met donc en pause pour un temps indéterminé. En clair, il dort.

Seulement voilà, les bons jeux en temps réel donnent au programme du travail à faire régulièrement (comme faire bouger les adversaires sur une map ou faire avancer des animations) et cet ordre ne se donne pas au clavier.

Et là, l'erreur de logique apparaît : au lieu de réveiller le programme régulièrement pour lui rappeler qu'il a du travail, on va plutôt l'empêcher de dormir. « De toute façon il fonctionne tout aussi bien donc autant le maltraiter, ça ne fait de mal à personne », me direz-vous.

Sauf que ça fait du mal à la machine, qui d'une part n'apprécie pas de ne jamais pouvoir se reposer (effet similaire à de l'overlock), ce qui use les piles, et la rend peu réceptive aux signaux qu'on lui envoie puisqu'elle est occupée à faire autre chose.

Alors n'en déplaise aux concepteurs de bibliothèques (je pense à input mais cela n'a rien contre Ninestars), les méthodes de gestion du clavier qui ne mettent pas le programme en pause (puisque finalement le clavier c'est l'interface de l'utilisateur pour donner des ordres) ne sont pas propres.

« On a setFps() » me répondrez-vous, mais setFps() utilise Sleep() (de manière un peu barbare d'ailleurs) et Sleep() est une fonction qui ne prend même pas la peine d'endormir le processeur (désassemblez le syscall 0x420, vous verrez, y'en a pour 20 lignes d'assembleur et c'est une horreur), donc c'est du pareil au même.

La solution

Assez parlé, la méthode correcte est donc, si l'on reprend notre analogie, de laisser dormir notre processeur, en lui programmant tout de même un réveil pour qu'il n'oublie pas de faire son boulot. Ça tombe bien, ce réveil s'appelle un timer et c'est probablement la fonctionnalité la moins utilisée de fxlib.

#include "fxlib.h"
#include "timer.h"

void SetTimer(int timer_id, int elapse, void (*callback)(void));
void KillTimer(int timer_id);

Ces fonctions sont très simples d'utilisation. Le timer_id s'écrit ID_USER_TIMERX, avec X variant de 1 à 5. Si vous avez la flemme vous pouvez aussi écrire de 1 à 5, ça fonctionne aussi.

La durée s'exprime en millisecondes mais le résultat est arrondi à un multiple de 25 ms (probablement tronqué en fait). Vous parlez donc en millisecondes mais vous indiquez un multiple de 25.

Si vous n'êtes pas familier avec la notation du troisième paramètre, il s'agit d'un pointeur sur une fonction de la forme « void fonction(void) ». En gros c'est la fonction quoi.

Une fois SetTimer() appelée, le timer se lance et chaque fois que la durée indiquée s'écoule, la fonction que vous avez passée en troisième argument est appelée (et ce quoi que le programme soit en train de faire à ce moment-là). Notez que le timer se recharge automatiquement.

Lorsque vous voulez arrêter le timer, vous faites appel à KillTimer(). N'oubliez pas d'arrêter le timer quand vous quittez votre fonction, vous n'avez définitivement pas envie que vos ennemis continuent à bouger sur l'écran alors que vous êtes revenu au menu principal.

Maintenant que vous avez de quoi réveiller votre processeur, vous allez pouvoir lui octroyer du temps de sommeil avec la fameuse fonction GetKey().

int GetKey(unsigned int *key);

GetKey() endort le processeur jusqu'à ce qu'une pression sur une touche le réveille, excepté qu'aujourd'hui vous avec aussi prévu un timer pour le réveiller. L'argument est l'adresse d'une variable dans laquelle le code de la touche sera stocké en suivant la norme de l'en-tête keybios.h, et la valeur de retour n'intéresse jamais personne. Votre processeur retrouve enfin le sommeil, et le sourire.

Un exemple

Voici un exemple simple permettant d'afficher des animations à deux frames d'une seconde. C'est volontairement exhaustif. Il n'y a pas particulièrement de commentaires à faire, je pense que c'est assez simple. Si vous avez une question, laissez un commentaire.

#include "fxlib.h"
#include "timer.h"

static void draw(void);
static void callback(void);
static int animation_state = 0;

int main(void)
{
    unsigned int key;

    // On dessine une premiere fois le contenu de l'ecran au frame 0
    animation_state = 0;
    draw();

    // On met en place le timer pour une seconde de delai
    SetTimer(ID_USER_TIMER1, 1000, callback);

    while(1)
    {
        // On laisse dormir le processeur \o/
        GetKey(&key);
        if(key == KEY_CTRL_EXIT) break;
    }

    // On arrete le timer avant de quitter la fonction
    KillTimer(ID_USER_TIMER1);
}

static void draw(void)
{
    Bdisp_AllClr_VRAM();

    if(animation_state == 0)
    {
        // Dessiner au frame 0
    }
    else
    {
        // Dessiner au frame 1
    }

    Bdisp_PutDisp_DD();
}

static void callback(void)
{
    // On passe de 0 a 1, ou de 1 a 0
    animation_state = !animation_state;
    // Et bien sur on redessine !
    draw();
}


Le problème du retour au menu

Vous êtes sans doute déjà fou de joie de ces nouvelles connaissances et vous vous apprêtez probablement à les mettre en œuvre avec un enthousiasme renouvelé, et vous vous rendez soudain compte que GetKey() possède quelques fonctionnalités de plus que ses cousines de la famille de IsKeyDown() :

- La capacité de revenir au menu quand on appuie sur MENU
- La modification du contraste avec SHIFT et REPLAY

Le premier vous intéresse peut-être, mais il y a un souci : en effet, lorsque vous revenez au menu, les timers ne sont pas arrêtés. Donc une seconde après votre retour au menu, votre fonction callback() est appelée de nouveau et redessine la map de votre jeu alors que l'utilisateur se trouve bien dans le menu principal de la calculatrice.

Pour cela, il existe une solution (un workaround, en fait) qui consiste à passer par un peu d'assembleur (c'est du syscall en fait, mais les syscalls C sont très peu pratiques à utiliser) mais qui nécessite de vous convertir aux matrix codes.

Les matrix codes, c'est une autre façon de noter les codes des touches. C'est plus intuitif que la liste classique de KEY_CTRL_EXE, KEY_CTRL_EXIT et tout le reste. Observez le tableau suivant :

F1      F2      F3      F4      F5      F6              09
SHIFT   OPTN    VARS    MENU    ←       ↑               08
ALPHA   ^2      ^       EXIT    ↓       →               07
XTT     log     ln      sin     cos     tan             06
ab/c    F↔D     (       )       ,       →               05
7       8       9       DEL                             04
4       5       6       x       div                     03
1       2       3       +       -                       02
0       .       EXP     (-)     EXE                     01
                                                AC      00
06      05      04      03      02      01      00

Vous voulez le code de la touche MENU ? Aucun problème, repérez la colonne... 3, et la ligne... 8. Vous ajoutez 1 (oui, désolé), ça fait 4/9, et vous avez tout de suite le code : 0x0409. EXE est en position 2/1, son code sera donc 0x0302. ALPHA donnera 0x0708. Facile, non ? Libre à vous de refaire des macros ensuite, par exemple :

#define KEY_UP          0x0209
#define KEY_RIGHT       0x0208
#define KEY_DOWN        0x0308
#define KEY_LEFT        0x0309
#define KEY_SHIFT       0x0709
#define KEY_ALPHA       0x0708
#define KEY_EXE         0x0302
#define KEY_EXIT        0x0408
#define KEY_MENU        0x0409

Pour régler le problème du menu, il vous suffit (si vous travaillez avec le fx-9860G SDK, les linuxiens trouveront tous seuls) d'inclure le fichier getkey.src, en fichier joint au tutoriel, à votre projet, et d'utiliser la fonction getkey() qui s'y trouve au lieu de GetKey(). N'oubliez pas de modifier l'extension pour un .src, le site n'accepte pas ce format.

unsigned int key = getkey();

Et là, miracle, la fonction ne vous renvoie plus au menu lorsque vous appuyez sur la touche mais vous renvoie le code de KEY_MENU défini plus haut (0x0409). Notez que cette fonction renvoie systématiquement les matrix codes, donc la touche EXE ne donne plus KEY_CTRL_EXE (30001) mais KEY_EXE (0x0302).

Et alors vous pouvez stopper vous-mêmes vos timers, lancer le menu principal en utilisant la deuxième fonction fournie dans le fichier, et redémarrer vos timers dès que l'utilisateur retourne dans votre application.

key = getkey();
if(key == KEY_MENU)
{
    KillTimer(ID_USER_TIMER1);
    system_menu();
    draw();
    SetTimer(ID_USER_TIMER1, 1000, callback);
}

Notez qu'il est intéressant de redessiner le contenu de votre écran pour éviter à l'utilisateur de contempler le menu princpal encore une seconde avant que votre timer n'arrive à expiration et ne le fasse lui-même.

Je n'ai pas encore de solution viable pour le problème du contraste (SHIFT + REPLAY), n'oubliez pas lorsque vous testez sur émulateur qu'après SHIFT les directions gauche et droite ne répondent plus, ce n'est pas un bug de votre programme.

En conclusion

Si vous avez lu jusqu'ici, vous n'avez plus le droit d'utiliser IsKeyDown(). Rappelez-vous, il n'y a quasiment aucune circonstance atténuante qui justifie que vous maltraitiez votre processeur.

Je terminerai sur une petite citation de Kirafi :
Kirafi a écrit :
Bon c'est bien beau tout ça , mais maintenant faut balancer le tuto sur le Combo Getkey/Timer pour que Phénix arrête de vomir à chaque fois que quelqu'un sort un Add-In ...

Je compte sur vous...


Fichier joint



Pages: 1, 2, 3, 4, 5 | Suivante

-florian66-
Hors ligne
Ancien rédacteur
Points: 2293
Défis: 19
Message
Citer : Posté le 17/02/2016 17:29 | #
Bon tuto ! J'avais déjà essayé de faire un truc du style pour essayer d'imiter 'IsKeyDown' sous Linux ! Mais je ne mettais pas autant penché sur la question
----------------------------------
In Arch, I trust ! And you ?
Kirafi
Hors ligne
Membre
Points: 1999
Défis: 10
Message
Citer : Posté le 17/02/2016 19:44 | #
Oookaaaay c'est parti pour recoder SeaRush ! Par contre j'ai un soucis je galère à initialiser une structure de tableau de structure (je mange et je poste sur le bon topic)...
----------------------------------
iPod
Pour des parties rapides
Jusqu'où pourras-tu aller dans ce jeu "partie rapide" qu'est Dextris (élu Jeu Du Mois)
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
Autres
Franchement ils valent le coups
Deviens l'amiral de la marine dans SeaRush (jeu concours) (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Ninestars
Hors ligne
Membre
Points: 2077
Défis: 22
Message
Citer : Posté le 17/02/2016 20:02 | #
Je suis content que tu fasses un sujet dessus, très bien fait. Cependant j'ai plusieurs questions :
- Lancer un timer commence à compter à partir du moment où la fonction SetTimer est appellée ?

- Comment peut-on gérer plusieurs appuies de touches simultanément étant donné que getkey ne renvoie qu'une seule touche ?

- Un problème se pose du fait que le code ne se déroule pas de façon continue : que se passe-t-il si ma fonction d'affichage est appellée en plein pendant la modification des coordonnées de mon personnage ? (j'ai la réponse : n'importe quoi !!)
Par exemple j'ai
// je viens d'appuyer sur ma touche
personnage.x = 12;
personnage.y = 45;
// fonction finie en attente du timer pour afficher, ok c'est  nickel
Mais cette situation peut très bein se produire
// je viens d'appuyer sur ma touche
personnage.x = 12;
// BOOM timer qui se pointe, ma fonction d'affichage est appellé alors que mes coordonnées ne sont pas à jours
personnage.y = 45;


- Pourquoi ne pas redéfinir Sleep pour vraiment arrêter le processeur et continuer avec les méthodes de gestion de clavier actuelle ?

Cette méthode semble est très bien, mais pour des jeux elle ne me semble pas appropriée. Et le problème 3 m'embarrase beaucoup :/

Ajouté le 17/02/2016 à 20:07 :
- Pourrait-on utiliser les timers pour contourner les Sleep ? Au lieu de faire Sleep(25) on fait SetTimer(1) et dès qu'il se déclenche on relance le programme. Ah ouais mais nan, comment attendre qu'il se déclenche ? ...
----------------------------------
Lephenixnoir
Hors ligne
Administrateur
Points: 12507
Défis: 136
Message
Citer : Posté le 17/02/2016 21:10 | #
Ninestars a écrit :
Lancer un timer commence à compter à partir du moment où la fonction SetTimer est appellée ?

Oui, le timer démarre tout de suite.

Ninestars a écrit :
Comment peut-on gérer plusieurs appuies de touches simultanément étant donné que getkey ne renvoie qu'une seule touche ?

On ne peut pas, GetKey() n'est pas assez évoluée. Je me débrouille pour gérer ça sous gint mais c'est assez compliqué.

Ninestars a écrit :
Un problème se pose du fait que le code ne se déroule pas de façon continue : que se passe-t-il si ma fonction d'affichage est appellée en plein pendant la modification des coordonnées de mon personnage ? (j'ai la réponse : n'importe quoi !!)

Euh... joker ? Il y a 5 millions de cycles par seconde, faudrait vraiment pas être chanceux. Statistiquement ? Une fois toutes les 1400 heures de jeu. Et puis si vraiment ça t'embête tu peux sécuriser le processus en mettant en pause le timer sur des opérations courtes quand tu modifies les données (si vraiment t'es pointilleux quoi). Par contre il faut une API plus évoluée que celle de fxlib (mais c'est facile).

Ninestars a écrit :
- Pourquoi ne pas redéfinir Sleep pour vraiment arrêter le processeur et continuer avec les méthodes de gestion de clavier actuelle ?

Parce que dans le modèle Sleep(), si le programme se met à lagger à un mauvais endroit la boucle principale s'arrête donc les événements aussi. Alors que dans le modèle timer, la régularité d'exécution est assurée.

Ninestars a écrit :
Cette méthode semble est très bien, mais pour des jeux elle ne me semble pas appropriée. Et le problème 3 m'embarrase beaucoup :/

(Les jeux sont faits comme ça, mon ami. Aucun programme informatique réel n'arrête le processeur en plein milieu pour des délais supérieurs à la ms.)

Ninestars a écrit :
- Pourrait-on utiliser les timers pour contourner les Sleep ? Au lieu de faire Sleep(25) on fait SetTimer(1) et dès qu'il se déclenche on relance le programme. Ah ouais mais nan, comment attendre qu'il se déclenche ? ...

Donc utiliser des timers pour faire du Sleep() ? Non, ça revient au même. On n'utilise pas les timers pour le principe, on utilise les timers pour utiliser des fonctions bloquantes. (Renseigne-toi sur l'instruction sleep si vraiment tu veux des détails.)
Au passage je pensais avoir été clair mais un timer de 25 millisecondes c'est SetTimer(25). C'est juste que si le paramètre est pas multiple de 25 il sera arrondi.
----------------------------------
Rise.
Dark storm
En ligne
Administrateur
Points: 10596
Défis: 174
Message
Citer : Posté le 17/02/2016 21:22 | #
Je tiens à préciser quand même que IsKeyUp peut éventuellement être utilisé dans le callback pour savoir si la touche est encore enfoncée après l'exécution d'un getkey. Sinon faut modifier la fréquence de répétion du GetKey, mais c'est pas forcément plus propre si on oublie de remettre les paramètres d'origine à la sortie.

Ajouté le 17/02/2016 à 21:25 :
Et t'ajoutera ça à la liste des tutos de qualité si ce n'est déjà fait.
----------------------------------
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Páranÿe quetë Quendya
Lephenixnoir
Hors ligne
Administrateur
Points: 12507
Défis: 136
Message
Citer : Posté le 17/02/2016 21:28 | #
Dark storm a écrit :
Je tiens à préciser quand même que IsKeyUp peut éventuellement être utilisé dans le callback pour savoir si la touche est encore enfoncée après l'exécution d'un getkey

Pour la mille-et-unième fois, non ! Parce que vous ne connaissez pas la durée d'appuie d'une touche, et vous risquez fort de rater des évènements. Dans le callback ? Tu déconnes, tu ne sais même pas quand il est appelé... surtout pas.
Oui, cette méthode marche, oui, vous pouvez l'utiliser, mais vous risquez de laisser passer des touches assez régulièrement.

Dark storm a écrit :
Sinon faut modifier la fréquence de répétion du GetKey, mais c'est pas forcément plus propre si on oublie de remettre les paramètres d'origine à la sortie.

C'est vingt fois plus propre x)
----------------------------------
Rise.
Dark storm
En ligne
Administrateur
Points: 10596
Défis: 174
Message
Citer : Posté le 17/02/2016 21:39 | #
Je compte plus le nombre de fois où j'ai du restart la machine parce que inutilisable à cause du jeu de je-sais-plus-qui qui modifiait le GetKey. Donc non, ça c'est pas propre.

À l'inverse, dans la théorie un timer unique doit suffire, avec une partie d'action, et une de réaction. La première sert à récupérer les entrées, la seconde à afficher les données. Oui, 99% des jeux n'ont pas besoin de précision supérieure à celle de l'affichage et surtout on besoin de pouvoir gérer efficacement les touches. Avec ça on peut très bien contourner le problème du GetKey. Ok ça revient à utiliser setFps, mais tant qu'on aura pas une fonction bloquante aussi efficace que IsKeyDown, seuls les jeux de stratégie pourront être codés comme ça. Je te met au défi de pondre un moteur de niaiseux proprement sans utiliser IKD/IKU.
----------------------------------
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Páranÿe quetë Quendya
Ninestars
Hors ligne
Membre
Points: 2077
Défis: 22
Message
Citer : Posté le 17/02/2016 21:49 | #
Lephenixnoir a écrit :
Euh... joker ? Il y a 5 millions de cycles par seconde, faudrait vraiment pas être chanceux. Statistiquement ? Une fois toutes les 1400 heures de jeu.

D'accord, en effet ça reste assez peu. Mais si les nombre d'instructions à executer est elevé, les chances augmentes en conséquence.

Lephenixnoir a écrit :
(Les jeux sont faits comme ça, mon ami. Aucun programme informatique réel n'arrête le processeur en plein milieu pour des délais supérieurs à la ms.)

Je ne suis pas convaincu, si les jeux fonctionnaient sur ce principe, les chutes de FPS ne pourraient pas exister. Si on appelle l'affichage toutes les X secondes, c'est constant. Et d'ailleurs si la fonction d'affichage est appellée alors que la précédente n'est pas finie on aurait de gros problèmes. Et d'ailleurs comme il y a toujours une touche pressée (à part quand t'es au toillettes...) cette méthode n'apporte pas d'avantages.

D'ailleurs, GetKey renvoie la touche si elle est pressée, ou quand elle est pressée ? Je veux dire que si on maintient la touche pressée puis on appelle getkey, va-t-il détecter la touche, ou faut-il réappuyer sur la touche ?

Et je vois encore un autre problème :
En m'appuyant sur ton exemple, imaginons que si j'appuie sur la touche droite, mon personnage va une case à droite.
Si j'appuie très rapidement, il va aller rapidement à droite, mais sans aucune limite de vitesse. Et même (selon la réponse à la question précedente) si je maintiens appuyé, il va foncer à droite.
On a un affichage qui est certes régulier, mais on a pas de limite de vitesse pour le reste du code.

(Je développe toutes les idées, c'est une nouvelle méthode interressante, il faut en faire le tour, rien contre toi )
----------------------------------
Lephenixnoir
Hors ligne
Administrateur
Points: 12507
Défis: 136
Message
Citer : Posté le 17/02/2016 21:55 | #
Dark storm a écrit :
Je compte plus le nombre de fois où j'ai du restart la machine parce que inutilisable à cause du jeu de je-sais-plus-qui qui modifiait le GetKey. Donc non, ça c'est pas propre.

Je parle de la méthode, pas de la manière dont certains oublient de dé-configurer... t'as regardé crt0.s ? Il le fait automatiquement.

Dark storm a écrit :
Ok ça revient à utiliser setFps, mais tant qu'on aura pas une fonction bloquante aussi efficace que IsKeyDown, seuls les jeux de stratégie pourront être codés comme ça.

Très bien, voilà un argument de plus pour ceux qui voudraient passer sous Linux -- gint.
Mais je parie (et non sans une certaine déception) que la majorité préférera continuer d'utiliser les méthodes faciles... quelqu'un pour tenir le pari ?

Dark storm a écrit :
Je te met au défi de pondre un moteur de niaiseux proprement sans utiliser IKD/IKU.

----------------------------------
Rise.
Kirafi
Hors ligne
Membre
Points: 1999
Défis: 10
Message
Citer : Posté le 17/02/2016 22:00 | #
Ben ce serait une bonne chose qu'un phénix nous ponde un oeuf de braise contenant une magnifique lib de gestion .
----------------------------------
iPod
Pour des parties rapides
Jusqu'où pourras-tu aller dans ce jeu "partie rapide" qu'est Dextris (élu Jeu Du Mois)
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
Autres
Franchement ils valent le coups
Deviens l'amiral de la marine dans SeaRush (jeu concours) (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Lephenixnoir
Hors ligne
Administrateur
Points: 12507
Défis: 136
Message
Citer : Posté le 17/02/2016 22:01 | #
Ninestars a écrit :
D'accord, en effet ça reste assez peu. Mais si les nombre d'instructions à executer est elevé, les chances augmentes en conséquence.

Comme je l'ai dit, tu peux facilement sécuriser la modification des données avec un verrou quitte à différer des quelques cycles l'exécution du timer.

Ninestars a écrit :
Je ne suis pas convaincu, si les jeux fonctionnaient sur ce principe, les chutes de FPS ne pourraient pas exister.

Ouh là, il y a des subtilités dans le traitement des interruptions, c'est pas si idyllique lorsque le processeur ne suit plus. Même GetKey() a des chutes de fréquences quand le programme fait des bêtises, donc faut pas trop simplifier hein.

Ninestars a écrit :
Et d'ailleurs si la fonction d'affichage est appellée alors que la précédente n'est pas finie on aurait de gros problèmes.

Verrouille si tu veux... mais les interruptions font ça tout le temps, c'est pas comme si ça n'existait pas !

Ninestars a écrit :
Et d'ailleurs comme il y a toujours une touche pressée (à part quand t'es au toillettes...) cette méthode n'apporte pas d'avantages.

Je n'ai pas compris cette remarque, je pense.

Ninestars a écrit :
D'ailleurs, GetKey renvoie la touche si elle est pressée, ou quand elle est pressée. Je veux dire que si on maintient la touche pressée puis on appelle getkey, va-t-il détecter la touche, ou faut-il réappuyer sur la touche ?

Ben tu crois que la répétition des touches c'est quoi ?

Ninestars a écrit :
En m'appuyant sur ton exemple, imaginons que si j'appuie sur la touche droite, mon personnage va une case à droite.
Si j'appuie très rapidement, il va aller rapidement à droite, mais sans aucune limite de vitesse. Et même (selon la réponse à la question précedente) si je maintiens appuyé, il va foncer à droite.
On a un affichage qui est certes régulier, mais on a pas de limite de vitesse pour le reste du code.

Euh... non. Va falloir détailler là.

Ninestars a écrit :
(Je développe toutes les idées, c'est une nouvelle méthode interressante, il faut en faire le tour, rien contre toi )

(Je t'en prie, c'est intéressant )

Ajouté le 17/02/2016 à 22:01 :
Kirafi a écrit :
Ben ce serait une bonne chose qu'un phénix nous ponde un oeuf de braise contenant une magnifique lib de gestion .

Tu crois que gint c'est quoi en fin de compte ?
Va falloir passer sous Linux par contre, mes amis ^^'
----------------------------------
Rise.
Kirafi
Hors ligne
Membre
Points: 1999
Défis: 10
Message
Citer : Posté le 17/02/2016 22:02 | #
Puis au PIRE, pour les jeux, bah on utilise cette méthode juste pour revenir au menu principal et voilà on code salement mais le retour menu est propre ...
----------------------------------
iPod
Pour des parties rapides
Jusqu'où pourras-tu aller dans ce jeu "partie rapide" qu'est Dextris (élu Jeu Du Mois)
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
Autres
Franchement ils valent le coups
Deviens l'amiral de la marine dans SeaRush (jeu concours) (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Lephenixnoir
Hors ligne
Administrateur
Points: 12507
Défis: 136
Message
Citer : Posté le 17/02/2016 22:05 | #
Kirafi a écrit :
Puis au PIRE, pour les jeux, bah on utilise ce cette méthode juste pour revenir au menu principal et voilà on code salement mais le retour menu est propre ...

Coder proprement c'est une question de principe vous savez, vos méthodes fonctionnent très bien en général... elles sont moches, c'est tout

C'est comme si je vous dit qu'on va soutenir une poutre avec un pilier au lieu de remplacer la poutre.
----------------------------------
Rise.
Kirafi
Hors ligne
Membre
Points: 1999
Défis: 10
Message
Citer : Posté le 17/02/2016 22:08 | #
j'aime bien la comparaison !
Enfin bon, je crois que ta méthode dois faire ses preuves avant qu'elle soit assimilé par les habitant de cette planète Casio .
----------------------------------
iPod
Pour des parties rapides
Jusqu'où pourras-tu aller dans ce jeu "partie rapide" qu'est Dextris (élu Jeu Du Mois)
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
Autres
Franchement ils valent le coups
Deviens l'amiral de la marine dans SeaRush (jeu concours) (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Aragorn
Hors ligne
Membre
Points: 806
Défis: 5
Message
Citer : Posté le 17/02/2016 22:10 | #
Lephenixnoir a écrit :
C'est comme si je vous dit qu'on va soutenir une poutre avec un pilier au lieu de remplacer la poutre.

L'avantage d'un pilier, c'est que tu peux y accrocher des cadres pour décorer le tout.
----------------------------------
Mes Programmes
Cliquer pour enrouler
The Legend of CASIO - Basic Quest ( Basic )
Notes ( logiciel qui calcule votre moyenne, basic )
Professeur Layton ( jeu d'énigme en C )
Mario & Sonic Rush ( jeu de course 3D en C )
Projets
Cliquer pour enrouler
Zelda Ancestral Relics ( projet en C )
Projets que je soutient
Cliquer pour enrouler
Pokémon jade de Dodormeur
Jetpack Joyride de Drakalex007
Arcuz de Dark Storm
Casion de Az et Darkysun




Un jeu de course en 3D pour calculatrice :
http://www.planet-casio.com/Fr/programmes/voir_un_programme_casio.php?showid=2773&page=1.
Ninestars
Hors ligne
Membre
Points: 2077
Défis: 22
Message
Citer : Posté le 17/02/2016 22:13 | #
Lephenixnoir a écrit :
Ben tu crois que la répétition des touches c'est quoi ?
Je ne sais pas, je n'utilise jamais GetKey. Qu'est ce que c'est ?
(je répondrai au reste en fonction de cette réponse )

C'est comme si je vous dit qu'on va soutenir une poutre avec un pilier au lieu de remplacer la poutre.
Par moment, une poutre plus résistante coûte trop cher, on va préférer le pilier (Le genre de chose auquel on te sensibilise beaucoup en école d'ingé)

Kirafi a écrit :
Enfin bon, je crois que ta méthode dois faire ses preuves avant qu'elle soit assimilé par les habitant de cette planète Casio
Je suis d'accord
----------------------------------
Lephenixnoir
Hors ligne
Administrateur
Points: 12507
Défis: 136
Message
Citer : Posté le 17/02/2016 22:23 | # | Fichier joint
Aragorn a écrit :
Lephenixnoir a écrit :
C'est comme si je vous dit qu'on va soutenir une poutre avec un pilier au lieu de remplacer la poutre.

L'avantage d'un pilier, c'est que tu peux y accrocher des cadres pour décorer le tout.

Oui, histoire qu'on ne voie pas que t'as mis un pilier à la place de la poutre x)

Ninestars a écrit :
Je ne sais pas, je n'utilise jamais GetKey. Qu'est ce que c'est ?

Dans le menu principal, tu n'as pas besoin de relâcher le touche directionnelle pour que le curseur continue de monter. Ça, c'est géré par GetKey() et il y a un appel de GetKey() par déplacement. Donc évidemment non, GetKey() n'a pas besoin que tu relâches la touche (selon le contexte cependant).

Ninestars a écrit :
Par moment, une poutre plus résistante coûte trop cher, on va préférer le pilier (Le genre de chose auquel on te sensibilise beaucoup en école d'ingé)

Oui mais là on programme des fichiers de 500 lignes, c'est pas comme s'il fallait embaucher 10 professionnels pour utiliser les méthodes propres x)

Ninestars a écrit :
Kirafi a écrit :
Enfin bon, je crois que ta méthode dois faire ses preuves avant qu'elle soit assimilé par les habitant de cette planète Casio
Je suis d'accord

C'est pas ma méthode vous savez... x) Comparez donc les deux méthodes :
→ Laisser tourner le processeur en vérifiant « régulièrement » (le régulièrement étant variable et inconnu) ce qu'il se passe.
→ Prévoir la mise à jour automatique en un temps régulier et laisser le processeur se gérer.
L'industrie n'utilise pas la première, ça me paraît d'une évidence primaire.

Mais si vous voulez des preuves, c'est justifié. Je vous en donnerai. Mais j'espère que vous m'accorderez de travailler avec gint (c'est-à-dire les outils que j'ai moi-même développés) au lieu d'utiliser ceux de Casio qui ne sont pas prévus pour faire des jeux à la base, je le rappelle.

Ajouté le 17/02/2016 à 22:31 :
Dark storm a écrit :
Je te met au défi de pondre un moteur de niaiseux proprement sans utiliser IKD/IKU.

C'est en fichier joint. Il faut appuyer sur une touche fléchée (n'importe laquelle). J'ai ajouté des petits pour éviter qu'on sorte de l'écran.
----------------------------------
Rise.
Ninestars
Hors ligne
Membre
Points: 2077
Défis: 22
Message
Citer : Posté le 17/02/2016 22:45 | #
NineStars a écrit :
En m'appuyant sur ton exemple, imaginons que si j'appuie sur la touche droite, mon personnage va une case à droite.
Si j'appuie très rapidement, il va aller rapidement à droite, mais sans aucune limite de vitesse. Et même (selon la réponse à la question précedente) si je maintiens appuyé, il va foncer à droite.
On a un affichage qui est certes régulier, mais on a pas de limite de vitesse pour le reste du code.
lephenixnoir a écrit :
Euh... non. Va falloir détailler là.
Je voulais dire par là que l'on puisse appuyer deux fois (ou plus) pour déplacer son personnage alors que l'affichage est rafraichi une fois. (ce qui en réalité n'est pas forcement un problème)
Mais si on peut gérer le temps d'attente entre deux touches avec Bkey_Get_RepeatTime, ça me va

lephenixnoir a écrit :
→ Laisser tourner le processeur en vérifiant « régulièrement » (le régulièrement étant variable et inconnu) ce qu'il se passe.
→ Prévoir la mise à jour automatique en un temps régulier et laisser le processeur se gérer.
L'industrie n'utilise pas la première, ça me paraît d'une évidence primaire.
Je suis d'accord
----------------------------------
Lephenixnoir
Hors ligne
Administrateur
Points: 12507
Défis: 136
Message
Citer : Posté le 17/02/2016 22:49 | #
Ninestars a écrit :
Je voulais dire par là que l'on puisse appuyer deux fois (ou plus) pour déplacer son personnage alors que l'affichage est rafraichi une fois. (ce qui en réalité n'est pas forcement un problème)
Mais si on peut gérer le temps d'attente entre deux touches avec Bkey_Get_RepeatTime, ça me va

Ok, j'ai compris de quoi tu parlais. C'est effectivement la solution, et c'est ce que j'ai fait dans le niaiseux pour Darks
----------------------------------
Rise.
Dark storm
En ligne
Administrateur
Points: 10596
Défis: 174
Message
Citer : Posté le 18/02/2016 12:22 | #
C'est en fichier joint. Il faut appuyer sur une touche fléchée (n'importe laquelle). J'ai ajouté des petits pour éviter qu'on sorte de l'écran.

J'ai pas testé, mais si ça marche je m'excuse, je pensais que Bkey_Set_RepeatTime arrondissait elle aussi à 25ms. Du coup ça marche très bien comme ça
----------------------------------
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Páranÿe quetë Quendya

Pages: 1, 2, 3, 4, 5 | Suivante

Index du Forum > Vos tutoriels et astuces > [Tutoriel] La gestion du clavier en C

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2018 | Il y a 39 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire indépendant, géré bénévolement et n'est donc pas affilié à Casio | Toute reproduction de Planète Casio, même partielle, est interdite
Les fichiers, programmes et autres publications présents sur Planète Casio restent la propriété de leurs auteurs respectifs et peuvent être soumis à des licences ou des copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd