IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Turbo Pascal Discussion :

[TP]Problème dans la gestion des touches d'un tetris


Sujet :

Turbo Pascal

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 10
    Points
    10
    Par défaut [TP]Problème dans la gestion des touches d'un tetris
    Bonjour,
    j'ai programmé un tetris sous turbo pascal 7, il fonctionne bien, il est en mode graphique, mais il n'est pas très jouable, j'ai un problème avec la gestion des touches.
    Tout le jeu est dans une boucle while, et je vérifie une seule fois dans la boucle s'il y a appui sur une touche :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    (*Gestion des touches*)
          If keypressed then
             begin
             tch:=readkey;
     
             If ord(tch)=52 then (*appui sur flèche gauche*)
                begin
                 (*on fait aller la bloc vers la gauche*)
                end;
     
             If ord(tch)=54 then (*appui sur flèche droite*)
                begin
                 (*on fait aller le bloc vers la droite*)
                end;
     
             If ord(tch)=53 then (*appui sur 5, rotation du bloc*)
                begin
                (*on fait tourner le bloc*)
                end;
     
             If ord(tch)=50 then (*appui sur flèche bas*)
                begin
                (*on fait chuter le bloc plus vite*)
                end;
     
             end;
     
          VideTamponClavier; (*dans l'unité disponible sur developpez.com*)
    j'utilise le pavé numérique car j'ai un peu de mal avec les flèches (touches étendues...)
    J'utilise la procédure VideTamponClavier de l'unité clavier.tpu, car sinon il y a un problème (par exemple le bloc est contre le bord droit et on reste appuyé sur la flèche droite, lorsque le nouveau bloc arrive, il va a droite, désolé j'essaye d'être clair mais ce n'est pas évident )

    Une fois par boucle, j'incrémente les ordonnées du bloc pour le faire descendre. Comme je vérifie l'appui sur les touches une seule fois dans la boucle, le bloc ne peut faire qu'une seule chose à la fois , exemple :

    premier passage dans la boucle:
    va vers la droite
    descend
    deuxième passage dans la boucle :
    va vers la droite
    descend
    troisième :
    tourne
    descend

    Ce n'est donc pas très jouable, on devrait pouvoir par exemple, le faire tourner 5-6 fois avant qu'il descende d'un cran, ou le faire aller tout à droite en un temps très court.
    Je sais que c'est parce que je ne vérifie qu'une seule fois si il y a un appui sur une touche dans la boucle , j'ai essayé de vérifier plusieurs fois dans la boucle les touches appuyées et d'afficher mon tableau après, ça a provoqué des bugs et je doute que ce soit la bonne solution.

    Dans les autres tetris que j'ai regardé on peut faire ce que je viens de dire (le faire tourner 5-6 fois avant qu'il descende d'un cran, ou le faire aller tout à droite en un temps très court) mais comment font-ils ?? quelle est leur formule magique : Vérifient-il 10000 fois l'appui sur les touches dans la boucle ?? (ce qui m'étonnerait)
    Voilà, merci d'avance
    a+

  2. #2
    Rédacteur/Modérateur
    Avatar de M.Dlb
    Inscrit en
    Avril 2002
    Messages
    2 465
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2002
    Messages : 2 465
    Points : 4 312
    Points
    4 312
    Par défaut
    Je pense que tu peux détourner une interruptions pour gérer ça correctement... Si tu détournes l'interruption 9h, qui est l'interruption du clavier, tu devrais pouvoir gérer ça assez simplement...

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 10
    Points
    10
    Par défaut
    aïe aïe aïe, je redoutait une réponse de ce genre (enfin merci quand même hein )
    J'imagine que cela veut dire qu'il faut que j'ajoute un peu de programmation bas niveau dans mon programme, mais je ne connais rien à tout ça.., j'ai une vague idée de ce qu'est une interruption mais sans plus.
    j'ai regardé la source de clavier.tpu, il y a de l'assembleur un peu partout... j'en ai fait un tout petit peu en cours (je suis en bts informatique de gestion), mais seulement mov, add et sub (qui servaient d'exemple de commandes, pour comprendre le fonctionement d'un processeur), et les modes d'adressage, en clair je ne sais rien faire en assembleur.
    Détourner une interruption signifie récupérer la touche pressée ?
    tu devrais pouvoir gérer ça assez simplement...
    Hmm même en sachant que mes notions en assembleur sont très floues ?

  4. #4
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Comment gères-tu le temps de descente de ta pièce ?

    Parce que je suppose que dans ta boucle tu n'as que 2 parties : un partie qui fait descendre la pièce en un certain temps et une partie qui permet à l'utilisateur d'interagir avec le jeu. Je pense que le problème vient plutôt de la première partie que de la seconde. (CQFD)

  5. #5
    Rédacteur/Modérateur
    Avatar de M.Dlb
    Inscrit en
    Avril 2002
    Messages
    2 465
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2002
    Messages : 2 465
    Points : 4 312
    Points
    4 312
    Par défaut
    Citation Envoyé par Loceka
    Comment gères-tu le temps de descente de ta pièce ?

    Parce que je suppose que dans ta boucle tu n'as que 2 parties : un partie qui fait descendre la pièce en un certain temps et une partie qui permet à l'utilisateur d'interagir avec le jeu. Je pense que le problème vient plutôt de la première partie que de la seconde. (CQFD)
    Tu peux être plus précis ??

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 10
    Points
    10
    Par défaut
    Merci pour ta réponse, ma boucle se déroule ainsi : (tout se passe dans une matrice (ou tableau) en 2D de 10 sur 15)

    while .....
    s'il y a un nouveau bloc à faire il arrive dans le tableau ou s'il y a un rotation de bloc il tourne

    j'efface le bloc dans le tableau

    j'incrémente les ordonnées des 4 carrés formant le bloc pour le faire descendre

    je gère les touches:
    s'il y a appui sur flèche droite, si c'est possible le bloc va vers la droite
    s'il y a appui sur flèche gauche, si c'est possible le bloc va vers la gauche
    s'il y a appui sur 5 le bloc tourne si c'est possible
    s'il y a appui sur flèche bas je réduit le délai de temporisation de la boucle pour faire descendre plus vite le bloc
    je vide le tampon du clavier (VideTamponClavier de l'unité clavier haypo)

    je rentre dans le tableau la nouvelle position du bloc

    j'affiche le tableau

    delai de temporisation

    je vérifie si un bloc arrive en bas ou s'il va rencontrer un autre bloc
    si oui je vérifie s'il y a une ligne de faite et je vérifie si le prochain bloc a la place pour apparaitre, sinon j'arrête la boucle et j'affiche "perdu"
    fin de la boucle.
    voilà !

  7. #7
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Citation Envoyé par wormful_sickfoot
    Tu peux être plus précis ??
    Ben dans tétris il y a seulement deux actions à effectuer, du moins tant que la pièce est "en l'air" :
    • faire descendre la pièce avec une vitesse constante (suffisament lente pour que le joueur puisse faire quelque chose), donc il faut gérer cette vitesse.
    • recueillir les informations fournies par le joueur (droite, gauche, bas, rotation).


    S'il n'y avait que les informations du joueur à recueillir, une simple boucle suffirait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    repeat
    tch:=readkey;
    if tch =... then ... etc.
    "vérification de la position de la pièce"
    until "la pièce est en bas"
    Le problème doit donc venir de la vitesse de la pièce : le "délai de temporisation" : plus il est long, moins le joueur peut faire de coups.

    Ce qu'il faudrait, je crois, c'est faire plus de tours de boucle dans le même temps : il suffirait de descendre la pièce d'un cran tous les 5 ou 6 tours de boucle par exemple.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    tant que i<=6 et que "la pièce n'est pas en bas" faire :
    incrémenter i
    interagir avec le joueur
    regarder la position de la pièce
    introduire un délai de temporisation
    recommencer.
    A moins que je n'ai pas compris le principe de ta boucle ça devrait être resolvable(?) de cette manière.

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 10
    Points
    10
    Par défaut
    Impeccable ça marche !!!! Un ENORME merci loceka !! j'avoue que je n'y avais pas du tout pensé merci merci et merci

  9. #9
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Bah, faut dire que j'en ai passé des heures (de cours ) sur tétris, alors forcément ça aide.

    Pense au tag [Résolu] par contre parce que sinon...

  10. #10
    Rédacteur/Modérateur
    Avatar de M.Dlb
    Inscrit en
    Avril 2002
    Messages
    2 465
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2002
    Messages : 2 465
    Points : 4 312
    Points
    4 312
    Par défaut
    En fait si j'ai bien compris, tu détectes 6 fois les touches tapées avant de déplacer la pièce ? Ca veut dire que le jeu ne prendra pas en compte les touches qui sont tapées après ?

    Y'a peut-être un problème dans ce cas...

  11. #11
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Où est-ce que tu vois un problème ?

    Une partie de Tétris se déroule comme suit :
    Une pièce arrive en haut de l'écran (mettons que l'écran fait 15 cases de haut et la pièce 2). Dès qu'elle apparaît, le joueur a la possibilité de la bouger (ou non). Quoi qu'il fasse, la pièce descend à vitesse constante (sauf s'il appuie sur "bas"), mettons d'une case toute les secondes. Donc au bout de 14 secondes elle arrive en bas. Une fois qu'elle touche le bas, on ne peut plus la bouger et une autre pièce apparaît en haut de l'écran.

    Le code qu'il a écrit (si on a la même logique) doit donc faire ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    1. Positionne la pièce en haut
    2. <répète>
    2.1. <boucle tant que i<=6 > 
                  a) regarde si une touche est saisie
                  b) si elle est saisie alors on regarde à quoi elle correspond
                  c) on laisse s'écouler 1/6 de seconde
                  d) incrémente i
         </boucle> : fin de la boucle lorsque i = 6
    2.2. si i>6 alors i=1
    2.3. regarde la position verticale actuelle de la pièce
    2.4. déplace la pièce "telle quelle" d'un rang vers le bas si possible
       <tant que la pièce n'est pas en bas >
    3. Recommence au début
    Je ne vois pas bien où il pourrait y avoir un problème, à moins que tu ne pensais à un oublie du "reset" de "i", mais bon ça se corrige assez rapidement ce genre de choses.

  12. #12
    Rédacteur/Modérateur
    Avatar de M.Dlb
    Inscrit en
    Avril 2002
    Messages
    2 465
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2002
    Messages : 2 465
    Points : 4 312
    Points
    4 312
    Par défaut
    Et si l'utilisateur appuie sur 8 touches pendant que la pièce est "suspendue" ? ou 12 ? Une partie des informations est perdue...

    Bon d'accord, la perte est peut-être négligeable mais elle existe... Quoiqu'il en soit, on perd de la synchronisation, car les effets des touches est décalé, il faudra attendre que la pièce soit déplacée verticalrment pour que les modifications prennent effet...

  13. #13
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Eh bien c'est simple, au lieu de faire une boucle avec 6 possibilités de déplacement et un temps d'attente de 1/6ème de seconde, tu fais une boucle avec 20 possibilités (ou autant que tu veux, mais de façon à être sûr que le joueur ne puisse pas saisir ce nombre dans ce laps de temps) et tu fixe le temps d'attente à 1/20ème de seconde !

    Bien sûr la vitesse de descente de la pièce peut être différente de une case par seconde mais, là encore, il suffit d'ajuster.

    Bien entendu, c'est pas très esthétique comme solution, je suis bien d'accord, mais c'est la seule que je vois, étant donné que le programme ne peut pas effectuer 2 actions simultanément (déplacer la pièce et lire les données envoyées par le joueur) ou, si c'est possible, ça ne relève pas de mon niveau ni de mes connaissances actuels en pascal.

    Si tu vois une solution qui serait plus correcte, je crois que Guile0 serait d'accord pour que tu la lui propose, moi aussi d'ailleurs, ça m'intéresserais beaucoup.

  14. #14
    Rédacteur/Modérateur
    Avatar de M.Dlb
    Inscrit en
    Avril 2002
    Messages
    2 465
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2002
    Messages : 2 465
    Points : 4 312
    Points
    4 312
    Par défaut
    En utilisant les interruptions, c'est faisable Il suffit de détourner l'interruption 9h pour gérer le clavier, et l'interruption 1C en reprogrammant un peu le PIC, pour gérer l'attente de 1 seconde (ou un peu plus ou un peu moins). Ainsi c'est synchronisé, pour gérer toutes les touches et l'affichage qui se modifie toutes les secondes...

  15. #15
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Tu peux mettre un exemple s'il te plaît, parce que j'ai jamais touché aux interruptions (apparement Guile0 non plus) et que je ne sais pas du tout comment on s'y prend.

  16. #16
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    7 946
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 7 946
    Points : 59 453
    Points
    59 453
    Billets dans le blog
    2
    Par défaut
    Bonjour !

    Le détournement de l'interruption clavier pourrait donner quelque chose comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    Var AncienneInt09 : Procedure;
     
    ...
     
    (* Nouvelle interruption clavier *)
    Procedure NouvelleInt09; interrupt;
    Var Touche : Byte;
    Begin
      Touche := Port[$60];
      case Touche of
        75 : ...   (* Flèche gauche *)
        77 : ...   (* Flèche droite *)
        80 : ...   (* Flèche bas *)
      end;
      (* Appel de l'ancienne interruption *)
      asm pushf end;
      AncienneInt09;
    End;
     
     
    BEGIN
      ...
      (* Détournement de l'interruption clavier *)
      GetIntVec($09,@AncienneInt09);
      SetIntVec($09,Addr(NouvelleInt09));
     
      ...
     
      (* Fin du détournement *)
      SetIntVec($09,Addr(AncienneInt09));
      ...
    END.
    La nouvelle interruption clavier teste le contenu du port clavier 60h. Il s'agit en fait du scan-code de la dernière touche pressée ou relâchée (le scan-code d'une touche relâchée vaut le scan-code de la touche pressée + 128).

  17. #17
    Membre expert
    Avatar de Eric Sigoillot
    Inscrit en
    Mars 2002
    Messages
    1 212
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 212
    Points : 3 369
    Points
    3 369
    Par défaut
    Un exemple de détournement d'interruption est disponible ici : http://pascal.developpez.com/cours/artint/ (l'exemp;e relatif au clavier est en bas, mais tout le reste est intéressant. à lire ).

    Sinon, pour info, il n'est pas nécessaire de connaître l'assembleur pour détourner une interruption. Le Pascal standard arrive à se suffir à lui-même dans de nombreux cas.

    @++

  18. #18
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Si j'ai bien compris le tutorial, on remplace les fonctions usuelles attribuées à certaines touches du clavier par des fonctions définies dans notre programme. Puis, une fois celui-ci terminé, on réattribue au clavier ses fonctions usuelles, c'est bien ça ?

    C'est pas un petit peu risqué si jamais le programme plante avant d'arriver à la fin ? Les touches modifiées ne seront-elles pas inutilisables après ça ?

    Enfin merci pour les liens. Je crois que je m'y mettrais un jour, quand j'aurais lu (et compris surtout) plus de choses là dessus !
    J'avoue avoir un peu peur de bousiller quelque chose de façon irréversible juste pour approfondir mes connaissances (je préfère être totalement sûr de ce que je fais avant).

  19. #19
    Rédacteur/Modérateur
    Avatar de M.Dlb
    Inscrit en
    Avril 2002
    Messages
    2 465
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2002
    Messages : 2 465
    Points : 4 312
    Points
    4 312
    Par défaut
    Citation Envoyé par Loceka
    Si j'ai bien compris le tutorial, on remplace les fonctions usuelles attribuées à certaines touches du clavier par des fonctions définies dans notre programme. Puis, une fois celui-ci terminé, on réattribue au clavier ses fonctions usuelles, c'est bien ça ?
    En fait, le principe est de remplacer le gestionnaire du clavier par notre propre gestionnaire : toutes les touches seront donc gérées par nous ! Seulement comme il n'est pas utile de toutes les gérer des fois, donc on ne gère que celles qui nous intéresse (que les touches directionnelles par exemple).

    Citation Envoyé par Loceka
    C'est pas un petit peu risqué si jamais le programme plante avant d'arriver à la fin ? Les touches modifiées ne seront-elles pas inutilisables après ça ?
    Si, mais c'est ca qui est fun Comme le gestionnaire est chargé en mémoire lors du lancement de l'ordinateur, du système d'exploitation (selon le système d'exploitation), il suffit de redémarrer l'ordinateur pour avoir le gestionnaire d'origine, au cas où il y a un problème...

    Citation Envoyé par Loceka
    Enfin merci pour les liens. Je crois que je m'y mettrais un jour, quand j'aurais lu (et compris surtout) plus de choses là dessus !
    J'avoue avoir un peu peur de bousiller quelque chose de façon irréversible juste pour approfondir mes connaissances (je préfère être totalement sûr de ce que je fais avant).
    Bousiller du matériel, c'est un risque minime... Mais en général avec un clavier, t'as pas grand chose à bousiller vu que c'est un périphérique d'entrée... Par contre avec un disque dur, ou une carte graphique, là c'est un peu plus délicat D'où la nécessité d'avoir une bonne doc : la "Ralf's Brown Interrupt List" sur http://pascal.developpez.com/outils/ , ca ne fait jamais de mal

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Incohérences dans la gestion des comptes
    Par Hibou57 dans le forum Windows XP
    Réponses: 5
    Dernier message: 04/10/2007, 11h28
  2. [Upload] Perdu dans la gestion des images
    Par thewaawshow dans le forum Langage
    Réponses: 9
    Dernier message: 19/09/2007, 14h32
  3. Réponses: 2
    Dernier message: 06/06/2007, 22h04
  4. [VBA-E] Dysfonctionnement dans la gestion des erreurs
    Par Choco49 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 14/06/2006, 11h44
  5. Réponses: 2
    Dernier message: 11/05/2005, 13h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo