Membre inscrit |
 |
Hors-ligne |
|
Inscription : 01 sept. 2008 19:07
|
| |
|
|
Pour le jour où vous reprendrez la programmation, je vous donne un conseil supplémentaire.
En mode SCREEN 2 pour PONG, vous pouvez vous inspirer de l'exemple pour PUT (graphique) donné dans l'aide de QuickBASIC 4.5. Il s'agit d'afficher une image plus grosse que l'objet à représenter afin de recouvrir le dessin précédent. Cela évite d'effacer, rend l'animation rapide, sans clignotement et l'image est presque stable. Cependant, il faut utiliser un timer pour cadencer l'animation sinon la vitesse sera proportionnelle à celle du processeur.
Si vous voulez allez plus loin, je peux vous présenter une méthode d'animation sans contrainte de palette mais plus gourmande en mémoire.
Une animation consiste à afficher une image un certain laps de temps puis à l'effacer avant de l'afficher ailleurs mais à proximité, ce qui crée l'illusion du mouvement. L'organisation de la mémoire vidéo fait qu'on manipule le rectangle capable de l'image à l'écran. Les pixels non significatifs ont alors une valeur nulle.
C'est pourquoi l'affichage d'une image avec XOU impose un fond uni, c'est-à-dire, constitué de pixels nuls aussi. Cependant, une carte EGA dispose de 16 registres de couleur programmables, celui numéroté 0 déterminant la couleur de fond. Pour pouvoir ajouter des pixels blancs (étoiles), on attribue la couleur blanche au registre 1 et on regroupe les 14 registres de couleur suivants deux à deux ; il n'y a plus que 8 couleurs sur 16 affichées à l'écran : celle du fond, le blanc brillant et les 7 couleurs correspondant aux 14 derniers registres. Le principal avantage de XOU (OU EXCLUSIF) est qu'il est réversible, deux mêmes copies s'annulent ce qui facilite l'effacement.
Pour afficher une image devant un arrière-plan sans restriction de couleurs, il faut mettre à zéro les pixels de l'arrière-plan à remplacer par ceux de l'image avant la copie avec OU -- INCLUSIF, EXCLUSIF peu importe.
Pour cela, on applique un masque grâce à l'opérateur ET logique. Vu qu'on travaille en mode 16 couleurs, il sera constitué de deux attributs : 15 et 0. Le premier préserve, le second annule.
xxxxxxxxb (val. orig.) xxxxxxxxb (val. orig.)
ET 11111111b (15 ou Fh) ET 00000000b (0)
----------- -----------
= xxxxxxxxb (val. orig.) = 00000000b (0)
|
Enfin, pour effacer, on restitue l'arrière-plan préalablement sauvé, ET logique n'étant pas réversible.
En conclusion, au lieu de travailler avec une seule image comme précédemment, on manipule aussi son masque et une copie de l'arrière-plan modifié, tous trois nécessitant la même quantité de mémoire. Le masque utilise la possibilité du ET logique de forcer un bit à zéro, le sprite, la possibilité contraire du OU logique.
En pratique, toutes ces copies sont longues à effectuer et il faut travailler en dehors de la mémoire vidéo avant d'afficher. Surtout que la mémoire vidéo des vieilles cartes sur connecteur ISA est lente. Malheureusement sous BASIC, il est plus facile de travailler en mémoire vidéo. En revanche, on peut avoir recours à deux pages vidéos, une sur laquelle on travaille les sorties et une utilisée pour afficher à l'écran.
Voici quelques informations à détenir :
SCREEN 7 SCREEN 8 SCREEN 9 SCREEN 10
(MODE MONO)
EGA 64 Ko : 2 pages 1 page 1 page N/A
16 coul./16 16 coul./16 4 coul./64
EGA 128 Ko : 4 pages 2 pages 1 page 1 page
16 coul./16 16 coul./16 16 coul./64 4 attributs/9
EGA 256 Ko : 8 pages 4 pages 2 pages 2 pages
16 coul./16 16 coul./16 16 coul./64 4 attributs/9
|
Voici un exemple :
1 ' Animation dirigée au clavier en mode EGA 320 x 200 16 couleurs.
2 ' Utilise un masque ET logique avant copie par OU INCLUSIF et
3 ' deux pages : une à l'écran et une de sortie échangeables.
4 ' Requiert : - GW-BASIC 3.2x supportant les codes BREAK du clavier
5 ' (éviter la v.3.20 pour Olivetti) ou IBM BASICA 3.20 minimum ;
6 ' - carte vidéo compatible EGA ;
7 ' - écran couleur.
8 ' Compilation : QuickBASIC 2.0 ou BASCOM 3.0 (/E/W/X) minimum.
9 :
100 ON ERROR GOTO 1000 ' Aller à TRAITEMENT D'ERREUR si erreur
110 DRAPEAUX% = 0 ' Variable initialisée (facultatif)
200 GOSUB 2000 ' Appeler DEBUT
300 GOSUB 3000 ' Appeler BOUCLE
699 ' ----- QUITTER -----
700 ' Mode texte avec menu des touches de fonction.
710 WIDTH 80: SCREEN 0: KEY ON ' WIDTH avant SCREEN si page <> 437
720 ' Restaurer l'état du clavier.
730 DEF SEG = &H40
740 IF DRAPEAUX% THEN POKE &H17, DRAPEAUX%
750 DEF SEG
760 ' Afficher message d'erreur s'il y a lieu.
770 PRINT MESSAGE.ERREUR$
780 ' Arrêter l'interception d'erreur.
790 IF MESSAGE.ERREUR$ = "" THEN CLEAR ELSE ON ERROR GOTO 0
900 END ' Ou SYSTEM pour quitter aussi l'interpréteur.
990 :
999 ' ===== T R A I T E M E N T D ' E R R E U R =====
1000 IF ERR = 5 AND ERL = 31060 THEN 10000 ' Dessin hors limites
1100 ' Mode d'écran invalide
1110 IF ERR = 5 AND ERL = 23000 THEN MESSAGE.ERREUR$ = "Carte vidéo couleur non compatible EGA ou PC/BASIC antérieur à la version 3.20": RESUME 700 ' Aller à QUITTER
1200 ' Autres erreurs
1210 MESSAGE.ERREUR$ = "Erreur" + STR$(ERR) + " à la ligne" + STR$(ERL) + " : avertir l'auteur du programme."
1220 RESUME 700 ' Aller à QUITTER (on s'embête pas)
1990 :
1999 ' ===== D E B U T =====
2000 ' Préparer les données, l'écran et l'interception des touches du curseur.
2100 GOSUB 21000 ' Initialisation variables
2200 GOSUB 22000 ' Sauvegarde état clavier
2300 GOSUB 23000 ' Initialisation écran, base tableaux, hasard
2400 GOSUB 24000 ' Fond
2500 GOSUB 25000 ' Création sprite et masque
2600 GOSUB 26000 ' Make et break touches fléchées
2700 GOSUB 27000 ' Surveillance touches fléchées
2710 PCOPY PAGE.S%,PAGE.E% ' Copier page à l'écran sur page de sortie.
2900 RETURN
2990 :
2999 ' ===== B O U C L E =====
3000 ' La boucle principale est celle qui gère l'affichage.
3010 WHILE TOUCHE$ <> CHR$(27)
3100 GOSUB 31000 ' Animer dessin
3110 SWAP PAGE.S%, PAGE.E%
3120 SCREEN , , PAGE.S%, PAGE.E%
3800 TOUCHE$ = INKEY$
3810 WEND
3900 RETURN
9990 :
9997 ' -------------------
9998 ' Dessin hors limites
9999 ' -------------------
10000 IF DESSIN.X1% < 0 OR DESSIN.X1% > DESSIN.XMAX% THEN DESSIN.X1% = DESSIN.X%
10010 IF DESSIN.Y1% < 0 OR DESSIN.Y1% > DESSIN.YMAX% THEN DESSIN.Y1% = DESSIN.Y%
10900 RESUME
20900 :
20997 ' ----------------------
20998 ' Initialisation valeurs
20999 ' ----------------------
21000 ' Adressage d'écran.
21010 ECRAN.X% = 319: ECRAN.Y% = 199
21020 '
21030 ' Variables de boucle et flags.
21040 I% = 0 : J% = 0: COULEUR% = 0
21050 FLAG% = 0: TOUCHE$ = ""
21060 '
21070 ' Paramètres de l'animation.
21080 DESSIN.PAS.X% = 1: DESSIN.PAS.Y% = 1 ' Pixel par pixel.
21090 PAGE.S% = 0: PAGE.E% = 1 ' Pages : sortie et écran.
21100 '
21110 ' Dimensions, vecteurs, coordonnées et taille du dessin à déplacer.
21120 DESSIN.LARGEUR% = 20: DESSIN.HAUTEUR% = 20
21130 DESSIN.VX% = 0 : DESSIN.VY% = 0
21140 DESSIN.X% = 0 : DESSIN.Y% = 0
21150 DESSIN.X1% = DESSIN.X% : DESSIN.Y1% = DESSIN.X%
21160 DESSIN.X2% = DESSIN.X1% + DESSIN.LARGEUR% - 1
21170 DESSIN.Y2% = DESSIN.Y1% + DESSIN.HAUTEUR% - 1
21180 DESSIN.XMAX% = ECRAN.X% - DESSIN.LARGEUR% + 1
21190 DESSIN.YMAX% = ECRAN.Y% - DESSIN.HAUTEUR% + 1
21200 DESSIN.TAILLE% = (4 + INT((DESSIN.LARGEUR% + 7) / 8) * DESSIN.HAUTEUR% * 4) / 2
21210 '
21220 ' Tableaux où sont stockés le dessin, son masque et son arrière-plan.
21230 OPTION BASE 1 ' Les tableaux commencent par 1 au lieu de 0.
21240 DIM DESSIN.FOND%(DESSIN.TAILLE%)
21250 DIM DESSIN.SPRITE%(DESSIN.TAILLE%)
21260 DIM DESSIN.MASQUE%(DESSIN.TAILLE%)
21270 '
21280 ' Message d'erreur.
21290 MESSAGE.ERREUR$ = ""
21900 RETURN
21910 ' **********************************************************************
21920 ' Le mode 320 x 200 16 couleurs comporte 4 plans et 4 bits par pixel.
21930 ' 4 + INT((largeur * bit par pixel par plan + 7) / 8) * hauteur * plan
21940 ' = taille du tableau en octets (un entier comporte deux octets)
21950 ' **********************************************************************
21997 ' -----------------------
21998 ' Sauvegarde état clavier
21999 ' -----------------------
22000 ' On manipule la mémoire à partir du segment 0040h.
22010 DEF SEG = &H40
22020 ' On ignore les touches Crtl, Alt ou Maj (poids faible) avant de sauver.
22030 DRAPEAUX% = PEEK(&H17) AND &HF0
22040 ' Désactiver le pavé numérique et le verrouillage majuscule (bits 6 & 7).
22050 POKE &H17, DRAPEAUX% AND &H9F
22060 ' On restitue absolument le segment BASIC par défaut.
22070 DEF SEG
22900 RETURN
22997 ' ------------------------------
22998 ' Initialisation écran et hasard
22999 ' ------------------------------
23000 SCREEN 7 ' EGA 320 X 200, 16 couleurs.
23010 CLS: KEY OFF
23020 PAINT (0, 0), 1 ' Une façon de colorier sans connaître les limites.
23030 RANDOMIZE TIMER ' On initialise la liste des nombres pseudo-aléatoires
23900 RETURN ' grâce à l'horloge.
23997 ' ----
23998 ' Fond
23999 ' ----
24000 ' Ciel étoilé de confettis (16 couleurs).
24010 FOR I% = 1 TO 2000
24020 PRESET ((ECRAN.X% + 1) * RND, (ECRAN.Y% + 1) * RND), 15 * RND + 1
24030 NEXT I%
24900 RETURN
24997 '--------------------------
24998 ' Création sprite et masque
24999 '--------------------------
25000 GET (DESSIN.X1%, DESSIN.Y1%)-(DESSIN.X2%, DESSIN.Y2%), DESSIN.FOND%
25010 '
25020 FLAG% = 0 ' 0 : flag pour dessin.
25030 GOSUB 53000 ' Afficher soit dessin soit masque
25040 GET (DESSIN.X1%, DESSIN.Y1%)-(DESSIN.X2%, DESSIN.Y2%), DESSIN.SPRITE%
25050 LOCATE 25, 1
25060 PRINT "Dessin utilisé...";
25070 WHILE INKEY$ = "": WEND
25080 '
25090 RESTORE
25100 FLAG% = -1 ' -1 : flag pour masque.
25110 GOSUB 53000 ' Afficher soit dessin soit masque
25120 GET (DESSIN.X1%, DESSIN.Y1%)-(DESSIN.X2%, DESSIN.Y2%), DESSIN.MASQUE%
25130 LOCATE 25, 1
25140 PRINT "Masque utilisé...";
25150 WHILE INKEY$ = "": WEND
25160 '
25170 PUT (DESSIN.X1%, DESSIN.Y1%), DESSIN.FOND%, AND
25180 PUT (DESSIN.X1%, DESSIN.Y1%), DESSIN.SPRITE%, OR
25190 LOCATE 25, 1
25200 PRINT "Animation avec masque ET et sprite OU.";
25900 RETURN
25997 ' ------------------------------
25998 ' Make et break touches fléchées
25999 ' ------------------------------
26000 ' CHR$(0) signifie pavé numérique et verrouillage majuscule désactivés.
26010 ' ... + CHR$(&H80 + scancode) : code de relâchement d'une touche.
26020 KEY 15, CHR$(&H0) + CHR$(&HC8) ' &HC8 = &H80 + &H48, haut
26030 KEY 16, CHR$(&H0) + CHR$(&HCB) ' &HCB = &H80 + &H4B, gauche
26040 KEY 17, CHR$(&H0) + CHR$(&HCD) ' &HCD = &H80 + &H4D, droite
26050 KEY 18, CHR$(&H0) + CHR$(&HD0) ' &HD0 = &H80 + &H50, bas
26060 ON KEY(11) GOSUB 51000 ' Aller à MAKE HAUT
26070 ON KEY(12) GOSUB 51200 ' Aller à MAKE GAUCHE
26080 ON KEY(13) GOSUB 51400 ' Aller à MAKE DROITE
26090 ON KEY(14) GOSUB 51600 ' Aller à MAKE BAS
26100 ON KEY(15) GOSUB 52000 ' Aller à BREAK HAUT
26110 ON KEY(16) GOSUB 52200 ' Aller à BREAK GAUCHE
26120 ON KEY(17) GOSUB 52400 ' Aller à BREAK DROITE
26130 ON KEY(18) GOSUB 52600 ' Aller à BREAK BAS
26900 RETURN
26997 ' -----------------------------
26998 ' Surveillance touches fléchées
26999 ' -----------------------------
27000 FOR I% = 11 TO 18
27010 KEY(I%) ON
27020 NEXT I%
27900 RETURN
30990 :
30997 ' -------------
30998 ' Animer dessin
30999 ' -------------
31000 PUT (DESSIN.X%, DESSIN.Y%), DESSIN.FOND%, PSET ' Efface avant-dernier.
31010 GET (DESSIN.X1%, DESSIN.Y1%)-(DESSIN.X2%, DESSIN.Y2%), DESSIN.FOND%
31020 LET DESSIN.X% = DESSIN.X1%
31030 LET DESSIN.Y% = DESSIN.Y1%
31040 LET DESSIN.X1% = DESSIN.X1% + DESSIN.VX% ' LET A=A+X mieux que A=A+X
31050 LET DESSIN.Y1% = DESSIN.Y1% + DESSIN.VY%
31060 PUT (DESSIN.X1%, DESSIN.Y1%), DESSIN.MASQUE%, AND ' Risque hors limite.
31070 PUT (DESSIN.X1%, DESSIN.Y1%), DESSIN.SPRITE%, OR
31080 LET DESSIN.X2% = DESSIN.X1% + DESSIN.LARGEUR% - 1
31090 LET DESSIN.Y2% = DESSIN.Y1% + DESSIN.HAUTEUR% - 1
31900 RETURN
49990 :
50000 ' Pas de REM (commentaires) dans les routines MAKE : pas de diagonales.
50997 ' ---------
50998 ' Make haut
50999 ' ---------
51000 REM DESSIN.VX% = 0
51010 DESSIN.VY% = -DESSIN.PAS.Y%
51090 RETURN
51197 ' -----------
51198 ' Make gauche
51199 ' -----------
51200 DESSIN.VX% = -DESSIN.PAS.X%
51210 REM DESSIN.VY% = 0
51290 RETURN
51397 ' -----------
51398 ' Make droite
51399 ' -----------
51400 DESSIN.VX% = DESSIN.PAS.X%
51410 REM DESSIN.VY% = 0
51490 RETURN
51597 ' --------
51598 ' Make bas
51599 ' --------
51600 REM DESSIN.VX% = 0
51610 DESSIN.VY% = DESSIN.PAS.Y%
51690 RETURN
51997 ' ----------
51998 ' Break haut
51999 ' ----------
52000 IF DESSIN.VY% < 0 THEN DESSIN.VY% = 0
52090 RETURN
52197 ' ------------
52198 ' Break gauche
52199 ' ------------
52200 IF DESSIN.VX% < 0 THEN DESSIN.VX% = 0
52290 RETURN
52397 ' ------------
52398 ' Break droite
52399 ' ------------
52400 IF DESSIN.VX% > 0 THEN DESSIN.VX% = 0
52490 RETURN
52597 ' ---------
52598 ' Break bas
52599 ' ---------
52600 IF DESSIN.VY% > 0 THEN DESSIN.VY% = 0
52690 RETURN
52997 ' --------------------------------
52998 ' Afficher soit dessin soit masque
52999 ' --------------------------------
53000 ' FLAG% = -1 (var. booléenne non nulle donc VRAIE) : masque sinon dessin.
53010 FOR J% = DESSIN.Y1% TO DESSIN.Y2%
53020 FOR I% = DESSIN.X1% TO DESSIN.X2%
53030 READ COULEUR%
53040 IF FLAG% THEN IF COULEUR% THEN COULEUR% = 0 ELSE COULEUR% = 15
53050 PSET (I%, J%), COULEUR%
53060 NEXT I%, J%
53900 RETURN
60990 :
60999 ' Dessin 20 x 20 pixels pour palette 16 couleurs par défaut.
61000 DATA 00,00,00,00,00,00,00,00,00,02,02,00,00,00,00,00,00,00,00,00
61010 DATA 00,00,00,00,00,00,00,00,02,02,02,02,00,00,00,00,00,00,00,00
61020 DATA 00,00,00,00,00,00,00,00,02,02,02,02,00,00,00,00,00,00,00,00
61030 DATA 00,00,00,00,00,00,00,02,02,02,02,02,02,00,00,00,00,00,00,00
61040 DATA 00,00,00,00,00,00,00,02,02,02,02,02,02,00,00,00,00,00,00,00
61050 DATA 00,00,00,00,00,00,02,02,02,04,04,02,02,02,00,00,00,00,00,00
61060 DATA 00,00,00,00,00,00,02,02,04,10,10,04,02,02,00,00,00,00,00,00
61070 DATA 00,00,00,00,00,00,02,02,02,02,02,02,02,02,00,00,00,00,00,00
61080 DATA 00,00,00,00,00,00,00,02,02,06,06,02,02,00,00,00,00,00,00,00
61090 DATA 00,00,00,00,00,00,00,00,02,02,02,02,00,00,00,00,00,00,00,00
61100 DATA 00,00,00,00,00,00,00,00,00,02,02,00,00,00,00,00,00,00,00,00
61110 DATA 00,00,00,00,00,00,00,00,05,05,05,05,00,00,00,00,00,00,00,00
61120 DATA 00,00,00,00,11,11,11,07,07,07,07,07,07,11,11,11,00,00,00,00
61130 DATA 00,07,07,07,07,07,07,07,07,07,07,07,07,07,07,07,07,07,07,00
61140 DATA 07,07,07,07,07,07,07,07,07,07,07,07,07,07,07,07,07,07,07,07
61150 DATA 08,08,08,08,08,08,08,08,08,08,08,08,08,08,08,08,08,08,08,08
61160 DATA 00,08,08,08,08,08,08,08,08,08,08,08,08,08,08,08,08,08,08,00
61170 DATA 00,00,00,00,08,08,08,08,08,08,08,08,08,08,08,08,00,00,00,00
61180 DATA 00,00,00,00,00,00,00,00,08,08,08,08,00,00,00,00,00,00,00,00
61190 DATA 00,00,00,00,00,00,00,00,00,08,08,00,00,00,00,00,00,00,00,00
|
Les procédures du programme ont été tapées en partie sous un éditeur de texte puis mis en forme sous GW-BASIC. On remarquera que les versions 3.xx permettent de traiter les erreurs sans arrêter les interceptions d'événements.
Il faut ajouter la ligne suivante pour la synchronisation verticale sous QuickBASIC 4.5 et sous IBM BASICA :
3130 WAIT &H3DA, 8 ' Synchro verticale après échange de pages.
|
A noter que le message de la ligne 1110 ne s'applique pas à la version 3.21 d'IBM qui est un GW/BASIC 2, et que le Compaq BASIC 3.20 considère LOCATE 25 comme une erreur, même après KEY OFF.
P.S. : la synchronisation verticale doit s'effectuer après l'échange d'écran et avant les différentes manipulations vidéo afin d'éviter que le dessin animé ne disparaisse à certaines hauteurs d'écran -- phénomène à prendre en compte pour les processeurs les moins rapides capables d'assurer une animation fluide.
Dernière modification par gm86 le 09 oct. 2012 21:12, modifié 91 fois.
_________________ C:\ONGRTLNS.W95
|
|