Ajouter une nouvelle touche impulse

Écrit le 18/10/2004 par Kurim
Dernière mise à jour : 06/02/2006

Introduction

Il faut déjà savoir qu'on distingue deux comportements pour une touche :
- l'impulsion : quand une touche est enfoncé, elle envoie une information qui permet d'exécuter une fois une fonction, et qui ne réagira pas une seconde fois avant que la touche ait été relâché, puis ré-enfoncé.
- la gestion de l'état : a tout moment, on vérifie l'état de la touche (enfoncé, relâché...). En comparant avec l'état précédent de la touche, on peut savoir si elle vient d'être enfoncé, si elle est maintenu enfoncé, ou si elle vient d'être relâché, et obtenir des comportements différents selon le cas. Par exemple, pour tirer, on amorce un tir au moment ou elle est enfoncé, et on le maintient jusqu'à ce que la touche soit relâché.

Dans notre cas, on va ajouter une touche à impulsion (le cas le plus simple) qui, une fois qu'elle sera enfoncé, affichera un texte "impulsion de la touche".

Il faut savoir qu'apparemment, il est difficile (voir impossible) d'ajouter une commande quelconque au code du jeu, il faut donc passer par les commandes qui existent et qui sont inutilisés. C'est donc ce que l'on va faire. On va ensuite l'ajouter au menu pour qu'elle puisse être configuré. Ce petit tutorial va simplement nous montrer ou intercepter l'impulsion d'une touche, et comment modifier les menus avec les fichiers .gui et les strings.

Ajout de la touche dans le code

Dans le fichier UsercmdGen.h sont définis un certain nombre de variables, les "IMPULSE_xx", qui correspondent chacune à une touche impulsive. Comme on peut le voir, un certain nombre est inutilisé, comme par exemple l'IMPULSE_16. On va donc utiliser celui-ci.

const int IMPULSE_16            = 16;            // <unused>

On peut éventuellement changer le commentaire (ici ça sert à rien mais si vous faites un mod, il est toujours utile de pouvoir retrouver à quel impulse correspond tel touche).

const int IMPULSE_16            = 16;            // notre action

Ensuite, rendez-vous dans le fichier Player.cpp. C'est ici que sont traités les commandes impulse du joueur. La classe du joueur, idPlayer, contient une fonction qui est appelé à chaque frame et qui permet d'exécuter du code en fonction de la valeur de l'impulse. Cette fonction s'appelle PerformImpulse( int impulse ) (ligne 5500 du fichier à peu près). Ajoutez alors ce cas dans le switch :

         case IMPULSE_16: {
            gameLocal.Printf( "Impulsion de la touche !\n" );
            break;
        }

Voilà, c'était très simple en fait, il suffit juste quand vous voulez programmer une touche, de remplacer ce code par un appel à la fonction que vous souhaitez (une fonction que vous coderez vous même par exemple). Vous pouvez par exemple coder une touche qui permet de retirer le chargeur de l'arme, en vous basant sur le code du Reload. (mais il faudra sans doute toucher aux scripts des armes et autre, c'est pour ça que je ne traite pas d'exemple concret dans ce tut).

Ajouter la touche dans les menus

Voilà, cette partie est presque l'intérêt principal de ce petit tutorial, puisqu'elle va nous montrer qu'on peut très facilement entièrement customiser l'interface. On va ajouter notre touche ici :

http://www.game-lab.com/images/tuts/doom3_bind/img1.jpg

Comme vous pouvez le voir, il y a 2 lignes vides dans le menu, nous allons ajouter notre touche à la place de l'avant dernière. Copiez le fichier de Doom 3 base/guis/mainmenu.gui dans le dossier de votre mod mymod/guis/mainmenu.gui, puis éditez le avec un éditeur quelconque (wordpad de préférence, et faites attention à bien le sauvegarder sans formatage après, au format texte). Faites une recherche sur "PDA / SCOREBOARD" pour trouver l'emplacement de la case précedente, celle qui attribue une touche pour le PDA. Vous devriez tomber sur ce code :

     //PDA / SCOREBOARD
            windowDef CA10 {
                rect        0, 207, 320, 16
                windowDef CA10L {
                    rect        0, 0, 8, 16
                    background    "gui/mainmenu/select_edge"
                    matcolor    0, 0, 0, 1
                    noevents    1
                }
                windowDef CA10M {
                    rect        8, 0, 304, 16
                    background    "gui/mainmenu/select_border"
                    matcolor    0, 0, 0, 1
                    noevents    1
                }
                windowDef CA10R {
                    rect        312, 0, 8, 16
                    background    "gui/mainmenu/select_angle"
                    matcolor    0, 0, 0, 1
                    noevents    1
                }
                windowDef CA10Title {
                    rect        1, 1, 180, 14
                    text        "#str_04066"
                    font        "fonts/bank"
                    textscale    0.25
                    textaligny    -6
                    forecolor    1, 1, 1, 1
                }
                bindDef CA10Primary {
                    rect        121, 1, 195, 14 //200
                    bind        "_impulse19"
                    font        "fonts/bank"
                    textscale    0.25
                    textaligny    -6
                    forecolor    0.6, 0.8, 0.8, 1
                }
            }

    //FILLER
            windowDef CA11 {
                rect        0, 230, 320, 16
                windowDef CA11L {
                    rect        0, 0, 8, 16
                    background    "gui/mainmenu/select_edge"
                    matcolor    0, 0, 0, 0.2
                    noevents    1
                }
                windowDef CA11M {
                    rect        8, 0, 304, 16
                    background    "gui/mainmenu/select_border"
                    matcolor    0, 0, 0, 0.2
                    noevents    1
                }
                windowDef CA11R {
                    rect        312, 0, 8, 16
                    background    "gui/mainmenu/select_angle"
                    matcolor    0, 0, 0, 0.2
                    noevents    1
                }
            }

"FILLER" signifie que la case est vide et défini un fond de remplissage. Modifiez le comme ceci, en vous inspirant de celui du dessus :

     //FAIRE UNE ACTION
            windowDef CA11 {
                rect        0, 230, 320, 16
                windowDef CA10L {
                    rect        0, 0, 8, 16
                    background    "gui/mainmenu/select_edge"
                    matcolor    0, 0, 0, 1
                    noevents    1
                }
                windowDef CA10M {
                    rect        8, 0, 304, 16
                    background    "gui/mainmenu/select_border"
                    matcolor    0, 0, 0, 1
                    noevents    1
                }
                windowDef CA10R {
                    rect        312, 0, 8, 16
                    background    "gui/mainmenu/select_angle"
                    matcolor    0, 0, 0, 1
                    noevents    1
                }
                windowDef CA11Title {
                    rect        1, 1, 180, 14
                    text        "#str_07184"
                    font        "fonts/bank"
                    textscale    0.25
                    textaligny    -6
                    forecolor    1, 1, 1, 1
                }
                bindDef CA11Primary {
                    rect        121, 1, 195, 14 //200
                    bind        "_impulse16"
                    font        "fonts/bank"
                    textscale    0.25
                    textaligny    -6
                    forecolor    0.6, 0.8, 0.8, 1
                }
            }

Remarquez que je n'ai pas mis de texte pour le titre du bouton, mais "#str_07184". Cela signifie qu'il va aller chercher le fichier de référence de la langue qu'utilise le joueur, puis trouver la chaîne portant cette identifiant, pour remplacer le texte. Pour mieux comprendre le principe, ouvrez le fichier base/strings/votre_langue.lang. Toutes les chaînes de caractères utilisés dans le jeu y sont référencés, et ce pour permettre un de traduire plus facilement votre mod. Copiez votre(vos) fichier(s) de langue dans le même dossier, mais dans votre mod, puis tout en bas, ajoutez, par exemple pour l'anglais, dans english.lang :

     "#str_07184"    "Do an action"

Faites attention de le mettre avant l'accolade de fermeture.

Voilà, maintenant on obtient ca dans le menu :

http://www.game-lab.com/images/tuts/doom3_bind/img2.jpg

Et maintenant, vous n'avez plus qu'a binder une touche, puis a tester dans le jeu : chaque fois que vous appuierez sur la touche, une ligne "Impulsion de la touche !" apparaîtra dans la console (ctrl-alt-² pour la voir).

Bon, ce tutorial vous donne simplement un petit aperçu de comment ajouter une touche simple. A vous après d'adapter la touche a l'action que vous souhaitez implémenter.