Accueil > QBasic > QBasic – Les types personalisés

QBasic – Les types personalisés

This entry is part 20 of 30 in the series QBasic - Tutoriel
  1. Introduction sommaire à l’animation
  2. Définition du type
  3. Les types et les tableaux
  4. Types dans types
  5. Note sur les nombres aléatoires

QBasic est loin d’être un langage de programation orienté objet. Cependant, il permet quand
même à l’utilisateur de définir ses propres types de variable.

Créer un type peut être très utile dans des cas de programme très complexes (jeux ou autres)
et permet de n’avoir que quelques variables dans son code.

Pour expliquer ce qu’est un type, nous allons détailler un exemple de programme en utilisant.
But : faire rebondir une balle (ou plutôt un cercle) sur les 4 cotès de votre écran.


Introduction sommaire à l’animation


Avant d’attaquer les types, vous devez savoir que pour animer un objet (ici, ce sera notre
balle), il faut :

  • Effacer cet objet, c’est à dire le dessiner aux même coordonnées, mais avec la couleur
    d’arrière plan.

  • Le redessiner à ces autres coordonnées.


Dans notre exemple, l’objet se limitant à un cercle, nous utiliserons cette technique. Mais
nous verrons plus tard une autre technique pour animer des dessins plus complexes.


Définition du type


Tout d’abord, nous devons définir les propriétés de notre balle :

  • Rayon : vu que l’instruction CIRCLE requiet un rayon et non un diamêtre, cette
    propriété le définira.

  • X : les coordonnées X du centre du cercle sur l’écran.

  • Y : les coordonnées Y du centre du cercle sur l’écran.

  • CX : pour déplacer la balle, nous allons ajouter aux coordonnées X, ce
    coefficient.

  • CY : de même, nous allons ajouter ce coefficient au coordonnées Y pour déplacer
    le cercle.

Comme pour les boucles, on peut comparer un type à un Big-Mac : deux tranches de pain et le
reste au milieu. Le reste, ce sera nos propriétés que nous avons défini ci dessus :


TYPE TBalle ‘ Le nom de notre type est TBalle
Rayon AS INTEGER ‘ Propriété Rayon, du type INTEGER
X AS SINGLE ‘ Propriété X, du type SINGLE
Y AS SINGLE ‘ Propriété Y, du type SINGLE
CX AS SINGLE ‘ Propriété CX, du type SINGLE
CY AS SINGLE ‘ Propriété CY, du type SINGLE
END TYPE ‘ Fin du type

Pareil que pour les boucles, il est conseillé d’observer un retrait.

Cette fois notre type est créé. Il est désormais utilisable comme n’importe quel autre type
(INTEGER, SINGLE, LONG, DOUBLE, STRING).

Nous allons donc déclarer une variable ‘Balle‘ du type ‘TBalle‘ :

TYPE TBalle ‘ Le nom de notre type est TBalle
Rayon AS INTEGER ‘ Propriété Rayon, du type INTEGER
X AS SINGLE ‘ Propriété X, du type SINGLE
Y AS SINGLE ‘ Propriété Y, du type SINGLE
CX AS SINGLE ‘ Propriété CX, du type SINGLE
CY AS SINGLE ‘ Propriété CY, du type SINGLE
END TYPE ‘ Fin du type

DIM Balle AS TBalle ‘ Déclaration de la variable Balle du type TBalle


Puis, nous allons initaliser d’une part l’écran :

TYPE TBalle ‘ Le nom de notre type est TBalle
Rayon AS INTEGER ‘ Propriété Rayon, du type INTEGER
X AS SINGLE ‘ Propriété X, du type SINGLE
Y AS SINGLE ‘ Propriété Y, du type SINGLE
CX AS SINGLE ‘ Propriété CX, du type SINGLE
CY AS SINGLE ‘ Propriété CY, du type SINGLE
END TYPE ‘ Fin du type

DIM Balle AS TBalle ‘ Déclaration de la variable Balle du type TBalle

SCREEN 12 ‘ Mode d’écran 12
CLS


Et d’autre part, les propriétés de ‘Balle‘. Pour accéder à ces propriétés, il suffit d’écrire
le nom de la variable, un point (.) et le nom de la propriété :

TYPE TBalle ‘ Le nom de notre type est TBalle
Rayon AS INTEGER ‘ Propriété Rayon, du type INTEGER
X AS SINGLE ‘ Propriété X, du type SINGLE
Y AS SINGLE ‘ Propriété Y, du type SINGLE
CX AS SINGLE ‘ Propriété CX, du type SINGLE
CY AS SINGLE ‘ Propriété CY, du type SINGLE
END TYPE ‘ Fin du type

DIM Balle AS TBalle ‘ Déclaration de la variable Balle du type TBalle

SCREEN 12 ‘ Mode d’écran 12
CLS

Balle.Rayon = 10 ‘ Rayon de 10 pixels
Balle.X = 320 ‘ Au centre de l’écran
Balle.Y = 240 ‘ Au centre de l’écran
Balle.CX = .05 ‘ Coefficient de départ
Balle.CY = .05 ‘ Coefficient de départ


Il ne nous reste maintenant plus qu’à l’animer. Pour cela, nous allons utiliser la technique
énoncée plus haut et une boucle :

TYPE TBalle ‘ Le nom de notre type est TBalle
Rayon AS INTEGER ‘ Propriété Rayon, du type INTEGER
X AS SINGLE ‘ Propriété X, du type SINGLE
Y AS SINGLE ‘ Propriété Y, du type SINGLE
CX AS SINGLE ‘ Propriété CX, du type SINGLE
CY AS SINGLE ‘ Propriété CY, du type SINGLE
END TYPE ‘ Fin du type

DIM Balle AS TBalle ‘ Déclaration de la variable Balle du type TBalle

SCREEN 12 ‘ Mode d’écran 12
CLS

Balle.Rayon = 10 ‘ Rayon de 10 pixels
Balle.X = 320 ‘ Au centre de l’écran
Balle.Y = 240 ‘ Au centre de l’écran
Balle.CX = .05 ‘ Coefficient de départ
Balle.CY = .05 ‘ Coefficient de départ

DO
CIRCLE(Balle.X, Balle.Y), Balle.Rayon, 0 ‘ On efface la balle
Balle.X = Balle.X + Balle.CX ‘ Calcul de la nouvelle coordonnée X
Balle.Y = Balle.Y + Balle.CY ‘ Calcul de la nouvelle coordonnée Y
CIRCLE(Balle.X, Balle.Y), Balle.Rayon, 14 ‘ On dessine la balle
LOOP


Maintenant, pour la faire rebondir, on va utiliser deux conditions. Pour les bords horizontaux,
on va inverser le coefficient CY dès que le cercle va rencontrer un des deux. Pareil pour les
bords verticaux, mais avec CX :

TYPE TBalle ‘ Le nom de notre type est TBalle
Rayon AS INTEGER ‘ Propriété Rayon, du type INTEGER
X AS SINGLE ‘ Propriété X, du type SINGLE
Y AS SINGLE ‘ Propriété Y, du type SINGLE
CX AS SINGLE ‘ Propriété CX, du type SINGLE
CY AS SINGLE ‘ Propriété CY, du type SINGLE
END TYPE ‘ Fin du type

DIM Balle AS TBalle ‘ Déclaration de la variable Balle du type TBalle

SCREEN 12 ‘ Mode d’écran 12
CLS

Balle.Rayon = 10 ‘ Rayon de 10 pixels
Balle.X = 320 ‘ Au centre de l’écran
Balle.Y = 240 ‘ Au centre de l’écran
Balle.CX = .05 ‘ Coefficient de départ
Balle.CY = .05 ‘ Coefficient de départ

DO
CIRCLE(Balle.X, Balle.Y), Balle.Rayon, 0 ‘ On efface la balle
Balle.X = Balle.X + Balle.CX ‘ Calcul de la nouvelle coordonnée X
Balle.Y = Balle.Y + Balle.CY ‘ Calcul de la nouvelle coordonnée Y
IF Balle.X – Balle.Rayon < 0 OR Balle.X + Balle.Rayon > 640 THEN
‘ Gestion du rebond horizontal
Balle.CX = -Balle.CX
END IF
IF Balle.Y – Balle.Rayon < 0 OR Balle.Y + Balle.Rayon > 480 THEN
‘ Gestion du rebond vertical
Balle.CY = -Balle.CY
END IF
CIRCLE(Balle.X, Balle.Y), Balle.Rayon, 14 ‘ On dessine la balle
LOOP


Vous remarquer que l’on a pris en compte le rayon de la balle dans les conditons de rebond. En
effet, sans cette précaution, la balle aurait rebondit sur son centre et nom sur ces bords.


Les types et les tableaux


Il est tout à fait possible de définir un tableau d’un type personalisé. Ainsi on aurait pu
avoir plusieurs balles sur l’écran, sans pour autant compliquer le programme. On utilise
simplement des boucles FOR…NEXT :

TYPE TBalle
Rayon AS INTEGER
X AS SINGLE
Y AS SINGLE
CX AS SINGLE
CY AS SINGLE
END TYPE

DIM Balle(10) AS TBalle ‘ Un tableau de balles

SCREEN 12
CLS

FOR i = LBOUND(Balle) TO UBOUND(Balle) ‘ Remarquer l’utilisation de LBOUND et UBOUND
Balle(i).Rayon = 10
Balle(i).X = 320
Balle(i).Y = 240
Balle(i).CX = .05
Balle(i).CY = .05
NEXT i

DO
FOR i = LBOUND(Balle) TO UBOUND(Balle)
CIRCLE(Balle(i).X, Balle(i).Y), Balle(i).Rayon, 0
Balle(i).X = Balle(i).X + Balle(i).CX
Balle(i).Y = Balle(i).Y + Balle(i).CY
IF Balle(i).X – Balle(i).Rayon < 0 OR Balle(i).X + Balle(i).Rayon > 640 THEN
Balle(i).CX = -Balle(i).CX
ENDIF
IF Balle(i).Y – Balle(i).Rayon < 0 OR Balle(i).Y + Balle(i).Rayon > 480 THEN
Balle(i).CY = -Balle(i).CY
END IF
CIRCLE(Balle(i).X, Balle(i).Y), Balle(i).Rayon, 14
NEXT i
LOOP


Que remarquez-vous ? Rien a changé, si ce n’est la vistesse d’execution. C’est parcequ’on à
définit des coordonnées communes à toutes les balles. Elles sont donc confondues et leurs
déplacements passent inaperçus.

Pour remédier à ce problème, nous allons faire intervenir l’aléatoire avec RND.
Souvenez-vous, c’est cette instruction qui permet d’obtenir un nombre alétoire entre 0 et 1.
Donc, pour avoir un nombre entre 0 et 10, on le multipliera par 10, pour en avoir un entre 0
et 421, on le multipliera par 421 :

TYPE TBalle
Rayon AS INTEGER
X AS SINGLE
Y AS SINGLE
CX AS SINGLE
CY AS SINGLE
END TYPE

DIM Balle(10) AS TBalle ‘ Un tableau de balles

SCREEN 12
CLS

FOR i = LBOUND(Balle) TO UBOUND(Balle) ‘ Remarquer l’utilisation de LBOUND et UBOUND
Balle(i).Rayon = RND * 10
Balle(i).X = RND * 640
Balle(i).Y = RND * 320
Balle(i).CX = RND
Balle(i).CY = RND
NEXT i

DO
FOR i = LBOUND(Balle) TO UBOUND(Balle)
CIRCLE(Balle(i).X, Balle(i).Y), Balle(i).Rayon, 0
Balle(i).X = Balle(i).X + Balle(i).CX
Balle(i).Y = Balle(i).Y + Balle(i).CY
IF Balle(i).X – Balle(i).Rayon < 0 OR Balle(i).X + Balle(i).Rayon > 640 THEN
Balle(i).CX = -Balle(i).CX
END IF
IF Balle(i).Y – Balle(i).Rayon < 0 OR Balle(i).Y + Balle(i).Rayon > 480 THEN
Balle(i).CY = -Balle(i).CY
END IF
CIRCLE(Balle(i).X, Balle(i).Y), Balle(i).Rayon, 14
NEXT i
LOOP


Cette fois, ça marche. On aurrait put les faire s’entrechoquer, mais ce n’est plus le sujet
de cette démonstration sur les types.


Types dans types


On peut tout à fait inclure des types personalisés dans d’autres types personalisés et ainsi
de suite. Il suffit de pouvoir s’y retrouver.

Par contre, en QBasic, on ne peut pas définir un tableau dans un type.


Note sur les nombres aléatoires


Comme certains le soutiennent (et j’en fais parti), le hasard n’existe pas. L’informatique (
et donc QBasic) n’echappe pas à cette rêgle. Ainsi, pour simuler le hasard, l’ordinateur
utilise une liste de nombres classés selon un ordre bien prècis.

Or, à chaque fois que vous lancez le programme, cette liste est remise à son point de départ
(pour simplifier).

Conséquence : si on ne fais rien contre, la chance ne va jamais tourné, puisque ce sera
constament les mêmes nombres qui seront « tirés ».

Pour remédier à ce problème crucial, il existe une instrution magique : l’instruction
RANDOMIZE.

RANDOMIZE va initialisé le générateur de nombres aléatoires à la position spécifiée. Exemple :

RANDOMIZE 5′ Initialisation à 5
PRINT RND

Seulement, voilà : dans cette exemple, le nombre tiré sera toujours le même puisqu’on à
initialisé la liste avec une constante (5), qui justement, ne varie pas.

Là aussi, pour remédier à ce problème, il existe deux solutions :

  • Laisser le choix du nombre de départ à l’utilisateur. Pour cela, il suffit de ne pas
    spécifier de chiffre de départ et il sera automatiquement demandé :

    RANDOMIZE ‘ On laisse le choix à l’utilisateur
    PRINT RND

  • On utilise l’horloge du PC pour calibrer la liste, grâce à la fonction TIMER.
    TIMER renvoie le nombre de secondes écoulées depuis minuit. Le chiffre change donc toutes
    les secondes. Il faudrait une remarquable coïncidence pour que l’on retombe plusieurs
    fois sur la même liste :

    RANDOMIZE TIMER ‘ Le PC décide pour nous
    PRINT RND

Series Navigation«QBasic – Les tableauxQBasic – L’organisation des données»
Categories: QBasic Tags:
  1. Yves-Henri
    16/04/2002 à 15:12 | #1

    Le type de leçon pédagogique: on commence très simple et on complique peu à peu avec des commentaires.

  1. Pas encore de trackbacks