VII. Joystick▲
VII-A. Introduction▲
La bibliothèque Allegro 5 fournit le nécessaire pour utiliser un ou plusieurs joysticks simultanément dans un programme. Un joystick peut être constitué de plusieurs « sticks ». Le stick est une manette qui permet d'orienter manuellement quelque chose à l'écran. Pour ce faire, chaque manette peut disposer d'un ou plusieurs axes : horizontal, vertical, profondeur, gauche-droite, bas-haut, etc. selon la complexité du joystick. Le joystick dispose également d'une panoplie de boutons disposés de façon très diverse selon les modèles.
VII-B. Prise en main simple▲
VII-B-1. Principales fonctions▲
Pour que le programme puisse disposer d'un joystick, c'est comme pour le clavier et la souris, il faut commencer par installer le joystick avec un appel à la fonction :
bool al_install_joystick
(
void
)
Cette fonction installe un pilote pour le joystick et retourne true si succès et false en cas d'échec. Si un driver a déjà été installé, elle retourne true immédiatement.
Ainsi au départ nous avons :
if
(!
al_install_joystick
(
))
erreur
(
"
al_install_joystick()
"
);
Ensuite des fonctions nous permettent d'identifier le ou les joysticks branchés à l'application :
La fonction al_get_num_joystick :
int
al_get_num_joysticks
(
void
)
Retourne le nombre de joysticks effectivement branchés sur l'ordinateur. La fonction retourne 0 s'il n'y a pas de joystick ou que le driver n'est pas installé. Exemple d'appel :
int
nbjoy =
al_get_num_joysticks
(
);
printf
(
"
nombre de joysticks : %d
\n
"
, nbjoy);
Par ailleurs, le branchement des joysticks peut être géré dynamiquement et un joystick peut être ajouté ou retiré. Si le nombre de joysticks est modifié, il faut alors un appel à la fonction al_reconfigure_joysticks pour que la modification soit prise en compte (la gestion dynamique des joysticks est abordée dans la section suivanteUtilisation des événements).
La fonction al_get_joystick :
ALLEGRO_JOYSTICK *
al_get_joystick
(
int
num)
La fonction retourne un pointeur sur le joystick dont le numéro est passé en paramètre. Attention, les différents joysticks sont numérotés de 0 à n et l'indice du dernier joystick branché est obtenu avec l'expression :
al_get_num_joystick
(
)-
1
S'il n'y a aucun joystick, la fonction retourne NULL .
Le numéro n'est pas un identificateur du joystick. Il correspond uniquement à sa position dans la liste. Si un joystick est retiré ou ajouté, les positions des autres s'en trouvent modifiées et leurs numéros d'ordre peuvent changer. Ce qui permet d'identifier un joystick c'est son adresse mémoire, un pointeur ALLEGRO_JOYSTICK* .
Exemple d'appel :
ALLEGRO_JOYSTICK*
joy ;
(
...)
joy =
al_get_joystick
(
0
); // le premier dans la liste
La fonction al_get_joystick_name :
const
char
*
al_get_joystick_name
(
ALLEGRO_JOYSTICK *
joy)
Retourne le nom du joystick dont l'adresse est passée au paramètre joy . Exemple d'appel :
ALLEGRO_JOYSTICK*
joy ;
(
…)
joy =
al_get_joystick
(
0
); // le premier dans la liste
const
char
*
nom =
al_get_joystick_name
(
joy);
printf
(
"
JOYSTICK 1, nom : %s
\n
"
, nom);
La fonction al_get_joystick_num_sticks :
int
al_get_joystick_num_sticks
(
ALLEGRO_JOYSTICK *
joy)
Retourne le nombre de manettes (sticks) dont dispose le joystick joy donné en paramètre. Une manette peut contrôler un ou plusieurs axes (horizontal, vertical, profondeur, etc.). Le nombre maximum des manettes est actuellement limité à huit. Exemple d'appel :
ALLEGRO_JOYSTICK*
joy ;
(
…)
int
nbsticks =
al_get_joystick_num_sticks
(
joy);
printf
(
"
\t
%d sticks, noms :
"
, nbsticks);
La fonction al_get_joystick_stick_name :
const
char
*
al_get_joystick_stick_name
(
ALLEGRO_JOYSTICK *
joy, int
stick)
Retourne le nom de la manette stick sur le joystick joy donné en paramètre. La manette est identifiée par un numéro. L'ensemble des manettes d'un joystick constitue un tableau et ce numéro correspond à son indice dans le tableau (la numérotation des indices commence à 0). Si la manette n'existe pas, la valeur NULL est retournée. Exemple d'appel :
ALLEGRO_JOYSTICK*
joy ;
(
...)
int
nbsticks =
al_get_joystick_num_sticks
(
joy);
for
(
i =
0
; i <
nbsticks; i++
){
const
char
*
nom =
al_get_joystick_stick_name
(
joy, i);
printf
(
"
%s,
"
, nom);
}
La fonction al_get_joystick_num_axes :
int
al_get_joystick_num_axes
(
ALLEGRO_JOYSTICK *
joy, int
stick)
Retourne le nombre total d'axes contrôlés par la manette passée au paramètre stick sur le joystick joy donné en paramètre. L'ensemble des manettes d'un joystick constitue un tableau et le numéro passé au paramètre stick correspond à son indice dans le tableau (les indices commencent à 0). Si la manette n'existe pas, la valeur 0 est retournée par la fonction. Le nombre maximum des axes est actuellement limité à trois. Exemple d'appel :
ALLEGRO_JOYSTICK*
joy ;
int
nbaxes;
(
...)
int
nbsticks =
al_get_joystick_num_sticks
(
joy);
for
(
i =
0
; i <
nbsticks; i++
){
nbaxes =
al_get_joystick_num_axes
(
joy, i);
printf
(
"
\t\t
sticks %d, %d axes :
\n
"
, i, nbaxes);
}
}
La fonction al_get_joystick_axis_name :
const
char
*
al_get_joystick_axis_name
(
ALLEGRO_JOYSTICK *
joy, int
stick, int
axis)
Retourne le nom de l'axe axis sur la manette sticks pour le joystick joy passé en paramètre. L'ensemble des manettes d'un joystick constitue un tableau et pour chaque manette, l'ensemble des axes constitue également un tableau. L'ensemble des axes est actuellement limité à trois. Les numéros pour identifier manettes et axes correspondent à leurs indices dans leur tableau respectif (commencent à 0). Si l'axe n'existe pas, la valeur NULL est retournée. Exemple d'appel :
ALLEGRO_JOYSTICK*
joy;
int
nbaxes[3
] =
{
0
}
; // trois axes maximum
(
...)
int
nbsticks =
al_get_joystick_num_sticks
(
joy);
// pour chaque stick le nombre d'axes
for
(
i =
0
; i <
nbsticks; i++
){
nbaxes[i] =
al_get_joystick_num_axes
(
joy, i);
printf
(
"
\t\t
sticks %d, %d axes :
\n
"
, i, nbaxes[i]);
// le nom de chaque axe
for
(
j =
0
; j <
nbaxes[i]; j++
){
const
char
*
nom =
al_get_joystick_axis_name
(
joy, i, j);
printf
(
"
\t\t\t
%s
\n
"
, nom);
}
}
La fonction al_get_joystick_num_buttons :
int
al_get_joystick_num_buttons
(
ALLEGRO_JOYSTICK *
joy)
Retourne le nombre de boutons sur le joystick joy passé en paramètre. Le nombre total des boutons est actuellement limité à trente-deux. Exemple d'appel :
ALLEGRO_JOYSTICK*
joy;
(
...)
int
nbbtn =
al_get_joystick_num_buttons
(
joy);
printf
(
"
\t
%d boutons, noms :
\n
"
, nbbtn);
La fonction al_get_joystick_button_name :
const
char
*
al_get_joystick_button_name
(
ALLEGRO_JOYSTICK *
joy, int
button)
Retourne le nom d'un bouton sur le joystick joy passé en paramètre. Les boutons sont rassemblés dans un tableau et le bouton est identifié avec le paramètre button par son indice dans le tableau (commence à 0). Exemple d'appel :
ALLEGRO_JOYSTICK*
joy;
(
...)
int
nbbtn =
al_get_joystick_num_buttons
(
joy);
for
(
i =
0
; i <
nbbtn; i++
){
const
char
*
nom =
al_get_joystick_button_name
(
joy, i);
printf
(
"
\t\t
%s
\n
"
, nom);
}
La fonction al_get_joystick_state :
void
al_get_joystick_state
(
ALLEGRO_JOYSTICK *
joy, ALLEGRO_JOYSTICK_STATE *
ret_state)
Retourne par référence la structure ret_state remplie avec les valeurs du joystick joy au moment de l'appel. Exemple d'appel :
ALLEGRO_JOYSTICK_STATE etatjoy;
ALLEGRO_JOYSTICK*
joy=
NULL
;
(
...)
do
{
(
...)
if
(
joy !=
NULL
){
al_get_joystick_state
(
joy, &
etatjoy);
(
...)
}
}
while
(
... );
VII-B-2. Expérimentation en mode texte▲
Le programme ci-dessous affiche dans une fenêtre console toutes les informations d'un joystick unique préalablement branché. Il affiche également toutes les valeurs prises par le joystick s'il est manipulé. Chaque bouton est appuyé ou pas. C'est une valeur entière de 0 s'il n'est pas appuyé, et supérieure à 0 s'il est appuyé. Les positions de chaque axe sont données en valeur flottante comprise entre -1 et +1. Le coin en haut à gauche des deux axes horizontal et vertical correspond aux coordonnées (-1,-1).
Si aucun joystick n'est branché le programme indique 0 et attend pour quitter (touche [Echap]).
Nos affichages se font dans la fenêtre console Windows qui accompagne toutes nos applications dans cet ouvrage. Sous un autre système, il faudra peut-être utiliser la console Allegro native ou bien la console en vigueur dans l'autre système.
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_image.h>
#include <time.h>
#include <stdio.h>
#define SCREENX 640
#define SCREENY 480
ALLEGRO_DISPLAY*
init_allegro
(
);
void
erreur
(
const
char
*
txt);
/**
***************************************************************
****************************************************************
*/
int
main
(
)
{
ALLEGRO_DISPLAY*
display;
ALLEGRO_KEYBOARD_STATE key;
// tester le joystick
ALLEGRO_JOYSTICK_STATE etatjoy; // état joystick
ALLEGRO_JOYSTICK*
joy=
NULL
; // le joystick
int
nbjoy; // nombre de joysticks
int
nbsticks; // nombre de manettes (8 max)
int
nbaxes[3
] =
{
0
}
; // nombre d'axes par manette (3 max)
float
val[8
][3
] =
{
0
}
; // valeur du joystick pour chaque
// manette par axe
int
nbbtn; // le nombre de boutons (32 max)
int
i,j;
display =
init_allegro
(
);
// le nombre de joystick
nbjoy =
al_get_num_joysticks
(
);
printf
(
"
nombre de joysticks : %d
\n
"
, nbjoy);
if
(
nbjoy){
// le premier joystick et son nom
joy =
al_get_joystick
(
0
);
const
char
*
nom =
al_get_joystick_name
(
joy);
printf
(
"
JOYSTICK 1, nom : %s
\n
"
, nom);
// nombre de sticks du joystick
nbsticks =
al_get_joystick_num_sticks
(
joy);
printf
(
"
\t
%d sticks, noms :
"
, nbsticks);
// les noms des sticks
for
(
i =
0
; i <
nbsticks; i++
){
const
char
*
nom =
al_get_joystick_stick_name
(
joy, i);
printf
(
"
%s,
"
, nom);
}
putchar
(
'
\n
'
);
// pour chaque manette le nombre d'axes
for
(
i =
0
; i <
nbsticks; i++
){
nbaxes[i] =
al_get_joystick_num_axes
(
joy, i);
printf
(
"
\t\t
sticks %d, %d axes :
\n
"
, i, nbaxes[i]);
// le nom de chaque axe
for
(
j =
0
; j <
nbaxes[i]; j++
){
const
char
*
nom =
al_get_joystick_axis_name
(
joy, i, j);
printf
(
"
\t\t\t
%s
\n
"
, nom);
}
}
// nombre de boutons
nbbtn =
al_get_joystick_num_buttons
(
joy);
printf
(
"
\t
%d boutons, noms :
\n
"
, nbbtn);
// les noms des boutons
for
(
i =
0
; i <
nbbtn; i++
){
const
char
*
nom =
al_get_joystick_button_name
(
joy, i);
printf
(
"
\t\t
%s
\n
"
, nom);
}
}
printf
(
"
\n
------------------------------
\n
"
);
do
{
al_get_keyboard_state
(&
key);
if
(
joy !=
NULL
){
al_get_joystick_state
(
joy, &
etatjoy);
for
(
i =
0
; i <
nbbtn; i++
) // 32 max
if
(
etatjoy.button[i] >
0
)
printf
(
"
bouton %d presse
\n
"
, i);
for
(
i =
0
; i <
nbsticks; i++
){
// 8 max
for
(
j =
0
; j <
nbaxes[i]; j++
){
// 3 max
if
(
val[i][j] !=
etatjoy.stick[i].axis[j]){
val[i][j] =
etatjoy.stick[i].axis[j];
printf
(
"
stick %d, axe %d = %f
\n
"
, i, j, val[i][j]);
}
}
}
}
}
while
(!
al_key_down
(&
key, ALLEGRO_KEY_ESCAPE));
al_destroy_display
(
display);
return
0
;
}
/**
***************************************************************
****************************************************************
*/
ALLEGRO_DISPLAY*
init_allegro
(
)
{
ALLEGRO_DISPLAY*
display;
if
(!
al_init
(
))
erreur
(
"
al_init()
"
);
if
(!
al_install_keyboard
(
))
erreur
(
"
al_install_keyboard()
"
);
// pour disposer du joystick
if
(!
al_install_joystick
(
))
erreur
(
"
al_install_joystick()
"
);
display =
al_create_display
(
SCREENX, SCREENY);
if
(!
display)
erreur
(
"
al_create_display()
"
);
return
display;
}
/**
***************************************************************
****************************************************************
*/
void
erreur
(
const
char
*
txt)
{
ALLEGRO_DISPLAY*
d;
d =
al_is_system_installed
(
) ? al_get_current_display
(
) : NULL
;
al_show_native_message_box
(
d, "
ERREUR
"
, txt, NULL
, NULL
, 0
);
exit
(
EXIT_FAILURE);
}
/**
***************************************************************
****************************************************************
*/
Attention de ne pas oublier l'appel à la fonction d'installation du driver joystick avant l'utilisation d'un joystick dans la boucle du programme.
Une structure ALLEGRO_JOYSTICK_STATE réunit trois ensembles qui sont trois tableaux :
- le tableau des boutons,
- le tableau des manettes,
- pour chaque manette, le tableau des axes.
Nous pouvons accéder à chaque bouton de la façon suivante :
ALLEGRO_JOYSTICK_STATE etatjoy;
(
...)
int
valbtn =
etatjoy.button[num_bouton];
et pour chaque manette aux valeurs de chacun de ses axes :
float
valaxe =
etatjoy.stick[num_manette].axis[num_bouton];
L'implémentation de cette structure est détaillée dans la section qui suit.
VII-B-3. Structure de données pour l'état d'un joystick▲
La structure de données pour l'état d'un joystick est un tableau de manettes et chaque manette est elle-même un tableau d'axes qui contient des valeurs flottantes. Ce pourrait être un tableau de float à deux dimensions, par exemple :
float
JOYSTICK[NBMANETTES][NBAXES];
En effet un tableau à deux dimensions est un tableau de tableaux. C'est suffisant pour les manettes mais il manque les boutons. Nous pourrions avoir une structure du type :
typedef
struct
{
float
manette[NBMANETTES][NBAXES] ;
int
bouton[NBBOUTONS] ;
}
JOYSTICK ;
Mais à l'utilisation il n'est pas aisé de dissocier de façon explicite les manettes et les axes. C'est toujours une manette qui est désignée. Par exemple :
JOYSTICK j;
j.manette[0
][1
] =
0
.5
; // accès manette 0 axe 1 du joystick j
De plus il est alors impossible d'ajouter des informations qui concerneraient chaque axe, par exemple le nom. Pour ces raisons déjà, et il y en a peut-être d'autres, les développeurs d'Allegro 5 ont procédé autrement. Chaque dimension du tableau est encapsulée dans une structure ; en simplifiant, cela donne pour les manettes et les axes :
struct
{
float
axes[NBAXES]; }
manettes[NBMANETTES];
Ici nous avons un tableau de structures dont chacune contient un tableau d'axes. Nous pouvons écrire par exemple :
manette[0
].axes[1
] =
0
.5
; // accès manette 0 axe 1 du joystick j
Cette écriture est plus claire mais a surtout l'avantage de permettre le cas échéant de compléter les informations relatives aux manettes et aux axes. Ainsi la structure de données pour ALLEGRO_JOYSTICK_STATE est définie de la façon suivante dans le fichier source « joystick.h » de la bibliothèque :
typedef
struct
ALLEGRO_JOYSTICK_STATE ALLEGRO_JOYSTICK_STATE;
struct
ALLEGRO_JOYSTICK_STATE
{
struct
{
float
axis[_AL_MAX_JOYSTICK_AXES];
}
stick[_AL_MAX_JOYSTICK_STICKS];
int
button[_AL_MAX_JOYSTICK_BUTTONS];
}
;
Les tableaux ne sont pas dynamiques et leurs dimensions maximum sont définies dans le même fichier par les macros constantes suivantes :
#define _AL_MAX_JOYSTICK_AXES 3
#define _AL_MAX_JOYSTICK_STICKS 8
#define _AL_MAX_JOYSTICK_BUTTONS 32
C'est là que sont définis les nombres maximum de manettes, d'axes et de boutons.
VII-C. Utilisation des événements▲
VII-C-1. Types d'événements▲
Rappelons qu'un joystick peut générer quatre types d'événements (la structure des événements joystick est détaillée dans le chapitre sur les événementsÉvénements) :
ALLEGRO_EVENT_JOYSTICK_AXIS : un axe a changé de valeur.
ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN : un bouton est pressé.
ALLEGRO_EVENT_JOYSTICK_BUTTON_UP : un bouton est relevé.
ALLEGRO_EVENT_JOYSTICK_CONFIGURATION : un joystick est branché ou débranché.
VII-C-2. Expérimentation en mode texte▲
Ce programme permet de brancher ou débrancher un joystick. En principe il peut accueillir plusieurs joysticks simultanément.
Chaque événement du joystick est détaillé dans la fenêtre console : quel joystick, quelle manette, quel axe, quel bouton appuyé ou quel bouton relevé :
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <stdio.h>
#define SCREENX 800
#define SCREENY 600
ALLEGRO_DISPLAY*
allegro_init
(
ALLEGRO_EVENT_QUEUE**
queue);
void
affiche_joysticks
(
void
);
void
affiche_pos_manette
(
ALLEGRO_JOYSTICK_EVENT*
j);
void
affiche_bouton
(
ALLEGRO_JOYSTICK_EVENT*
j, int
val);
void
erreur
(
const
char
*
msg);
/**
***************************************************************
****************************************************************
*/
int
main
(
)
{
ALLEGRO_DISPLAY*
display;
ALLEGRO_EVENT_QUEUE*
queue;
int
fin =
0
;
display =
allegro_init
(&
queue);
affiche_joysticks
(
);
while
(!
fin){
ALLEGRO_EVENT event;
al_wait_for_event
(
queue, &
event);
switch
(
event.type){
// EVENEMENTS JOYSTICK
// mouvement sur un axe
case
ALLEGRO_EVENT_JOYSTICK_AXIS:
affiche_pos_manette
(&
event.joystick);
break
;
// bouton appuyé
case
ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN:
affiche_bouton
(&
event.joystick, 1
);
break
;
// bouton relevé
case
ALLEGRO_EVENT_JOYSTICK_BUTTON_UP:
affiche_bouton
(&
event.joystick, 0
);
break
;
// branchement ou débranchement d'un joystick
case
ALLEGRO_EVENT_JOYSTICK_CONFIGURATION:
al_reconfigure_joysticks
(
);
affiche_joysticks
(
);
break
;
// pour quitter
case
ALLEGRO_EVENT_DISPLAY_CLOSE:
fin =
1
;
break
;
case
ALLEGRO_EVENT_KEY_DOWN:
if
(
event.keyboard.keycode ==
ALLEGRO_KEY_ESCAPE)
fin =
1
;
break
;
}
}
al_destroy_display
(
display);
al_destroy_event_queue
(
queue);
return
0
;
}
/**
***************************************************************
****************************************************************
*/
ALLEGRO_DISPLAY*
allegro_init
(
ALLEGRO_EVENT_QUEUE**
queue)
{
ALLEGRO_DISPLAY*
display;
if
(!
al_init
(
))
erreur
(
"
al_init()
"
);
if
(!
al_install_keyboard
(
))
erreur
(
"
al_install_keyboard()
"
);
// pour utilisation joystick
if
(!
al_install_joystick
(
))
erreur
(
"
al_install_joystick()
"
);
display =
al_create_display
(
SCREENX, SCREENY);
if
(!
display)
erreur
(
"
al_create_display()
"
);
*
queue =
al_create_event_queue
(
);
if
(!*
queue)
erreur
(
"
al_create_event_queue()
"
);
al_register_event_source
(*
queue,
al_get_display_event_source
(
display));
al_register_event_source
(*
queue,
al_get_keyboard_event_source
(
));
// enregistrement événements joystick
al_register_event_source
(*
queue,
al_get_joystick_event_source
(
));
return
display;
}
/**
***************************************************************
****************************************************************
*/
void
affiche_joysticks
(
)
{
int
j,m,a;
int
nbjoy =
al_get_num_joysticks
(
);
printf
(
"
nombre de joysticks : %d
\n
"
, nbjoy);
for
(
j =
0
; j <
nbjoy; j++
){
ALLEGRO_JOYSTICK*
joy =
al_get_joystick
(
j);
printf
(
"
JOYSTICK %d : %s
\n
"
, j, al_get_joystick_name
(
joy));
// les manettes du joystick
int
nbmanette =
al_get_joystick_num_sticks
(
joy);
for
(
m =
0
; m <
nbmanette; m++
){
const
char
*
nom_manette =
al_get_joystick_stick_name
(
joy, m);
printf
(
"
\t
Manette %d : %s
\n
"
, m, nom_manette);
// les axes par manette
int
nbaxe =
al_get_joystick_num_axes
(
joy, m);
for
(
a =
0
; a <
nbaxe; a++
){
const
char
*
nom_axe =
al_get_joystick_axis_name
(
joy, m, a);
printf
(
"
\t\t
Axe %d : %s
\n
"
, a, nom_axe);
}
}
printf
(
"
-------------------------------------
\n
"
);
}
}
/**
***************************************************************
****************************************************************
*/
void
affiche_pos_manette
(
ALLEGRO_JOYSTICK_EVENT*
j)
{
// le joystick activé
printf
(
"
JOYSTICK : %s
\n
"
, al_get_joystick_name
(
j->
id));
// la manette activée
const
char
*
nom_manette =
al_get_joystick_stick_name
(
j->
id, j->
stick);
printf
(
"
\t
Manette %d, %s :
\n
"
, j->
stick, nom_manette);
// l'axe concerné
const
char
*
nom_axe =
al_get_joystick_axis_name
(
j->
id, j->
stick, j->
axis);
printf
(
"
\t\t
Axe %d, %s :
"
,j->
axis, nom_axe );
// sa valeur
printf
(
"
valeur : %.2f
\n
"
, j->
pos);
printf
(
"
------------------------------
\n
"
);
}
/**
***************************************************************
****************************************************************
*/
void
affiche_bouton
(
ALLEGRO_JOYSTICK_EVENT*
j, int
val)
{
const
char
*
nom_bouton =
al_get_joystick_button_name
(
j->
id, j->
button);
printf
(
"
Bouton %d, %s = %d
\n
"
, j->
button, nom_bouton, val);
}
/**
***************************************************************
****************************************************************
*/
void
erreur
(
const
char
*
txt)
{
ALLEGRO_DISPLAY*
d;
d =
al_is_system_installed
(
) ? al_get_current_display
(
) : NULL
;
al_show_native_message_box
(
d, "
ERREUR
"
, txt, NULL
, NULL
, 0
);
exit
(
EXIT_FAILURE);
}
/**
***************************************************************
****************************************************************
*/
Évidemment l'affichage n'est pas terrible surtout si le joystick n'est pas absolument stable avec des microvariations sur ses axes par exemple. Cela empêche de bien lire les informations dans la console. Éventuellement il y a la possibilité d'effacer la console avec l'appel :
system
(
"
cls
"
) ;
Ce bout de code est néanmoins intéressant parce qu'il permet de bien voir comment récupérer les valeurs du joystick directement à partir de l'union ALLEGRO_EVENT .
VII-C-3. Expérimentation graphique▲
Cette expérimentation est inspirée d'un exemple fourni avec la bibliothèque. Il est écrit par Peter Wrang, l'un de développeurs de la bibliothèque. Voici le code commenté :
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_primitives.h>
#define SCREENX 800
#define SCREENY 600
#define NOIR al_map_rgb(0, 0, 0)
#define BLEU al_map_rgb(0, 255, 255)
#define ROUGE al_map_rgb(255, 0, 0)
#define VERT al_map_rgb(0, 255, 0)
#define MAXMANETTES 8
#define MAXAXES 3
#define MAXBTN 32
// les données d'un joystick :
int
nbmanettes=
0
; // nombre de manettes
int
nbaxes[MAXMANETTES] =
{
0
}
; // nombre d'axes par manette
float
valaxes[MAXMANETTES][MAXAXES] =
{
0
}
;// valeur des axes
int
nbbtn=
0
; // nombre de boutons
int
valbtn[MAXBTN] =
{
0
}
; // valeur des boutons
ALLEGRO_DISPLAY*
allegro_init (
ALLEGRO_EVENT_QUEUE**
queue);
void
init_joystick (
ALLEGRO_JOYSTICK*
joy);
void
affiche_joystick
(
void
);
void
dessine_axes (
int
x, int
y, int
manette);
void
dessine_bouton (
int
btn, int
val);
void
erreur (
const
char
*
msg);
/**
***************************************************************
****************************************************************
*/
int
main
(
)
{
ALLEGRO_DISPLAY*
display;
ALLEGRO_EVENT_QUEUE*
queue;
int
fin =
0
;
display =
allegro_init
(&
queue);
init_joystick
(
al_get_joystick
(
0
));
while
(!
fin){
ALLEGRO_EVENT event;
// si la file est vide afficher
if
(
al_is_event_queue_empty
(
queue))
affiche_joystick
(
);
al_wait_for_event
(
queue, &
event);
switch
(
event.type){
// EVENEMENTS JOYSTICK
// mouvement sur un axe
case
ALLEGRO_EVENT_JOYSTICK_AXIS :
valaxes[event.joystick.stick][event.joystick.axis] =
event.joystick.pos;
break
;
// bouton appuyé
case
ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN:
valbtn[event.joystick.button] =
1
;
break
;
// bouton relevé
case
ALLEGRO_EVENT_JOYSTICK_BUTTON_UP:
valbtn[event.joystick.button] =
0
;
break
;
// branchement ou débranchement d'un joystick
case
ALLEGRO_EVENT_JOYSTICK_CONFIGURATION:
al_reconfigure_joysticks
(
);
init_joystick
(
al_get_joystick
(
0
));
break
;
// pour quitter
case
ALLEGRO_EVENT_DISPLAY_CLOSE:
fin =
1
;
break
;
case
ALLEGRO_EVENT_KEY_DOWN :
if
(
event.keyboard.keycode ==
ALLEGRO_KEY_ESCAPE)
fin =
1
;
break
;
}
}
al_destroy_display
(
display);
al_destroy_event_queue
(
queue);
return
0
;
}
/**
***************************************************************
****************************************************************
*/
ALLEGRO_DISPLAY*
allegro_init
(
ALLEGRO_EVENT_QUEUE**
queue)
{
ALLEGRO_DISPLAY*
display;
if
(!
al_init
(
))
erreur
(
"
al_init()
"
);
if
(!
al_install_keyboard
(
))
erreur
(
"
al_install_keyboard()
"
);
if
(!
al_init_primitives_addon
(
))
erreur
(
"
al_init_primitives_addon()
"
);
// pour utilisation joystick
if
(!
al_install_joystick
(
))
erreur
(
"
al_install_joystick()
"
);
display =
al_create_display
(
SCREENX, SCREENY);
if
(!
display)
erreur
(
"
al_create_display()
"
);
*
queue =
al_create_event_queue
(
);
if
(!*
queue)
erreur
(
"
al_create_event_queue()
"
);
al_register_event_source
(*
queue,
al_get_display_event_source
(
display));
al_register_event_source
(*
queue,
al_get_keyboard_event_source
(
));
// enregistrement événements joystick
al_register_event_source
(*
queue,
al_get_joystick_event_source
(
));
return
display;
}
/**
***************************************************************
****************************************************************
*/
void
init_joystick
(
ALLEGRO_JOYSTICK*
joy)
{
ALLEGRO_JOYSTICK_STATE etatj;
int
i, j;
if
(
joy ==
NULL
)
return
;
// état du joystick
al_get_joystick_state
(
joy, &
etatj);
// récupération des valeurs des manettes
nbmanettes =
al_get_joystick_num_sticks
(
joy);
for
(
i =
0
; i <
nbmanettes; i++
){
nbaxes[i] =
al_get_joystick_num_axes
(
joy, i);
for
(
j =
0
; j <
nbaxes[i]; j++
)
valaxes[i][j] =
etatj.stick[i].axis[j];
}
// récupération des états des boutons
nbbtn =
al_get_joystick_num_buttons
(
joy);
for
(
i =
0
; i <
nbbtn; i++
)
valbtn[i] =
(
etatj.button[i] >
0
) ? 1
: 0
;
}
/**
***************************************************************
Affichage graphique de toutes les données d'un joystick, axes et
boutons. Les affichages sont centrés et répartis à l'écran de façon
proportionnelle à leur nombre
****************************************************************
*/
void
affiche_joystick
(
)
{
// récupère la bitmap de destination courante
// supposée être l'écran ou la fenêtre avec sa taille
ALLEGRO_BITMAP *
page =
al_get_target_bitmap
(
);
int
tx =
al_get_bitmap_width
(
page);
int
ty =
al_get_bitmap_height
(
page);
int
i;
// fond noir
al_clear_to_color
(
NOIR);
// les manettes
for
(
i =
0
; i <
nbmanettes; i++
){
// centrer
int
posx =
(
i +
0
.5
)*
tx /
nbmanettes;
int
posy =
ty /
2
;
dessine_axes
(
posx, posy, i);
}
// les boutons
for
(
i =
0
; i <
nbbtn; i++
){
dessine_bouton
(
i,valbtn[i]);
}
// voir à l'écran
al_flip_display
(
);
}
/**
***************************************************************
Une manette correspond à une position dans un espace selon au
maximum trois axes correspondants chacun à une dimension :
horizontale, verticale, profondeur (x,y,z).
Il y a deux dessins à faire : la surface totale et dans cette
surface, de façon proportionnée, le voyant indicateur de la
position de la manette. L'affichage de la manette est centré
autour de de la position passée en paramètre.
****************************************************************
*/
void
dessine_axes
(
int
posx,int
posy, int
manette)
{
const
int
taille =
30
; // pour zone affichage (rayon)
const
int
bord =
5
; // bord
const
int
total =
taille +
bord; // total
int
x, y; // position horizontale et verticale de la manette
// rectangle de la surface totale d'affichage
al_draw_filled_rectangle
(
posx -
total, posy -
total,
posx +
total, posy +
total, ROUGE);
// pourtour en bleu clair dans la zone totale
al_draw_rectangle
(
posx -
total +
0
.5
, posy -
total +
0
.5
,
posx +
total -
0
.5
, posy +
total -
0
.5
,
BLEU,0
);
// pourtour hors zone
al_draw_rectangle
(
posx -
total , posy -
total ,
posx +
total , posy +
total ,
BLEU, 0
);
// calcul de la position des axes horizontal et vertical
x =
posx +
valaxes[manette][0
] *
taille;
y =
posy +
valaxes[manette][1
] *
taille;
// position de la manette
al_draw_filled_rectangle
(
x -
5
, y -
5
, x +
5
, y +
5
, ROUGE);
// si l'axe z de profondeur existe il est affiché à part
if
(
nbaxes[manette] ==
3
){
// calcul position
int
zx =
posx +
total +
bord *
2
;
int
z =
posy +
valaxes[manette][2
] *
taille;
// rectangle de la surface totale d'affichage
al_draw_filled_rectangle
(
zx -
bord, posy -
total,
zx +
bord, posy +
total, ROUGE);
// contour
al_draw_rectangle
(
zx -
bord +
0
.5
, posy -
total +
0
.5
,
zx +
bord -
0
.5
, posy +
total -
0
.5
,
BLEU,0
);
// position de la manette
al_draw_filled_rectangle
(
zx-
5
, z-
5
, zx+
5
, z+
5
, VERT);
}
}
/**
***************************************************************
****************************************************************
*/
void
dessine_bouton
(
int
btn, int
val)
{
ALLEGRO_BITMAP*
page =
al_get_target_bitmap
(
);
int
posx =
al_get_bitmap_width
(
page);
int
posy =
al_get_bitmap_height
(
page);
// position du bouton (32 boutons possibles : 4 lignes de 8)
posx =
posx /
2
-
120
+
(
btn %
8
) *
30
;
posy =
posy -
120
+
(
btn /
8
) *
30
;
// rectangle bouton
al_draw_filled_rectangle
(
posx, posy, posx+
25
, posy+
25
, ROUGE);
// pourtour bleu
al_draw_rectangle
(
posx +
0
.5
, posy +
0
.5
,
posx +
24
.5
, posy +
24
.5
,BLEU,0
);
// si pressé intérieur en vert
if
(
val >
0
)
al_draw_filled_rectangle
(
posx +
2
, posy +
2
,
posx +
23
, posy +
23
, VERT);
}
/**
***************************************************************
****************************************************************
*/
void
erreur
(
const
char
*
txt)
{
ALLEGRO_DISPLAY*
d;
d =
al_is_system_installed
(
) ? al_get_current_display
(
) : NULL
;
al_show_native_message_box
(
d, "
ERREUR
"
, txt, NULL
, NULL
, 0
);
exit
(
EXIT_FAILURE);
}
/**
***************************************************************
****************************************************************
*/
Obtenir ce livre▲
Ce document est une retranscription autorisée du livre Allegro 5 - Programmation de jeux en C et C++ écrit par Frédéric DROUILLON. Initialement publié aux éditions ENI, vous pouvez commander le livre sur le site de l'éditeur. |