[ST MAG] Programmation avancée en gfa (II) BMOVE

[ST MAG] Programmation avancée en gfa (II) BMOVE

Messagede tomchi » Sam 18 Oct 2008 15:19

...............................................................
PROGRAMMATION AVANCEE EN GFA BASIC (II)
par DENEB of FANTASY et JEDI of SECTOR ONE from THK

Nous allons ce mois ci étudier l'instruction BMOVE et ses
nombreuses applications, telles que : le "big sprite", les
distorsions, les rouleaux et les effets précalculés.

Voyons avant tout l'instruction BMOVE elle-même. Son rôle est
de copier une partie de la mémoire à une autre adresse. Elle
s'utilise comme suit:

BMOVE adresse source, adresse objet, taille du bloc à transfèrer

Les possibilités de cette instruction sont nombreuses mais nous nous
intéresserons ici qu'à ses applictions graphiques. Pour effectuer
nos animations, nous placerons préalablement notre sprite dans
une zone réservée de la mémoire, puis nous le copierons
directement en mémoire écran. L'intérêt (car il y en a un) de
cette instruction est d'être beaucoup plus rapide que les
commandes traditionnelles du GFA à savoir GET, PUT, RC_COPY et
même BITBLT.

L'AFFICHAGE

Pour un affichage rapide il faut transférer tout le bloc en
continu. Compte tenu de l'organisation de la mémoire écran, nous
serons tenu d'afficher les lignes entières donc de gérer des
blocs d'une largueur de 320 pixels. La copie ligne à ligne (qui
permet d'avoir des sprites d'une longueur quelconque) reste
cependant possible mais provoque un ralentissement notable de la
vitesse d'exécution. Malgré tout cette opération demeure
nécessaire dans le cas de distorsion de motifs. La copie
s'effectuant d'une traite tous les plans seront pris en compte.
Transférer un bloc quelque soit le nombre de plans qu'il occupe,
prend le même temps. Le contenu de l'adresse objet étant
intégralement remplacé par l'image que nous copions, il est
impossible de laisser transpararaitre un fond, ce qui n'est pas
nécessairement un inconvient. En effet, il est ainsi possible
d'effacer les traces de l'animation précédente.

LE PREDECALAGE

La mémoire vidéo est constituée de blocs de 8 octets,
représentant 4 plans de 16 pixels. Pour ne pas décaler les plans
de notre motif, les adresses sources et objets devront être
multiples de 8, donc décalés à l'écran par pas de 16 pixels
horizontalement. Or, il est peut esthétique d'avoir un
déplacement aussi grossier qui serait soit trop rapide, soit
saccadé. Pour y remédier, nous allons donc avant la boucle
principale de notre programme, copier 16 fois de suite notre
sprite dans un Buffer en le décalant à chaque fois d'un pixel par
rapport à sa position précédente, (ceci de façon très classique
avec l'instruction RC_COPY). Ce qui va nous permetre de
réaliser l'affichage au pixel près en combinant l'adresse
multiple de 8 et le motif prédécalé correspondant (se reporter à
l'article précédent pour les formules nécessaires aux
conversions). Le problème ne se pose pas en vertical puisqu'un
déplacement par pas de 160 octets permet une précision d'un pixel.

Nous allons maintenant vous proposer plusieurs applications
directes des BMOVE pour réaliser un "big sprite", une distorsion,
un rouleau et pour finir un effet précalculé.

...............................................................
LE BIG SPRITE

Le "big sprite" est l'application directe de la technique du
prédécalage. Voyons ici l'organisation du programme "BIG SPRITE"
qui a pour effet de déplacer un sprite (qui est en fait toute une
image) selon une courbe paramétrée. Le programme commence par
charger une image au format néochrome (.NEO) et par effacer une
bande de 16 pixels de hauteur en haut de l'écran puis une autre
en bas. Ces espaces serviront en fait à "auto effacer" l'ancienne
image au moment de l'animation. Le sprite (qui n'est autre que
l'image entière) et ensuite prédécalé dans un buffer
préalablement alloué. Mais voilà, un tel sprite (qui prend la
bagatelle de 32 Ko), prédécalé sur 16 positions demande 16*32 Ko,
soit 512 000 octets. Ce qui est beaucoup trop pour un 520 ST, vu
qu'il faut également caser en mémoire le code du programme, les
diverses allocations, le GFA etc... Le sprite est donc prédécalé
sur seulement 8 positions ce qui ne prend que 256 Ko et n'altère
aucunement la fluidité de notre sprite. Il faut alors copier 8
fois le sprite dans buffer de 256 Ko en le décalant de 2 pixels à
chaque fois.
La courbe est précalculée et préconvertie (en décalage et en
adresse multiple de 8) pour gagner un maximum de temps lors de
l'affichage. A noter que la courbe est volontairement limitée en
Y car étant donné la taille du sprite il faut éviter d'écraser
des données lors des sorties d'écran.
Ce programme une fois compilé tourne en un peu moins d'une VBL.
Mais pour disposer d'un peu plus de temps machine, il est tout de
même préférable d'avoir des sprites de hauteur plus modeste...


Code: Tout sélectionner
.*************************
.*       BIG SPRITE      *
.*  par DENEB (FANTASY)  *
.*************************
.
.CE PROGRAMME DOIT ETRE COMPILE POUR TOURNER EN 1 VBL
.
HIDEM                         ! la souris se cache...
OUT 4,18                      ! ...pour se suicider
xb%=XBIOS(2)                  ! Sauve l'‚cran xbios(2)
RESERVE 30000                 ! R‚servation
a%=MALLOC(256000)             ! Buffer du pr‚d‚calage
c%=MALLOC(1000)               ! Buffer de la courbe
im%=MALLOC(40256)             ! Ecran de synchro
i1%=AND(im%,&HFFFFFF00)+7936  ! Un ‚cran ...
i2%=XBIOS(3)                  ! Et un autre ...
ON BREAK GOSUB fin            ! en cas d'arret
@load
@sin
.
.BOUCLE PRINCIPALE
.
DO
  e%={ADD(c%,pe%)}            ! Calcul de la position
  o%=ADD({ADD(c%,po%)},i1%)   ! Calcul du d‚calage
  BMOVE e%,o%,32000           ! Affichage du sprite
  @sync                       ! Synchro
  ADD pe%,8                   ! Pointeur de position
  po%=ADD(pe%,4)              ! Pointeur de pr‚d‚calage
  IF pe%>lon&                 ! bouclage de la courbe
    pe%=0
    po%=0
  ENDIF
LOOP UNTIL PEEK(&HFFFC02)=57  ! Press space ?
@fin                          ! C'est la fin ...
.
.
PROCEDURE load
  .
  .Proc‚drue de chargement d'une image .NEO
  .et de pr‚d‚calage du sprite
  .
  BLOAD "*.neo",XBIOS(2)-128  ! Charge image
  ~XBIOS(6,L:XBIOS(2)-124)    ! Restaure palette
  DEFFILL 0                   ! Remplit en couleur 0
  PBOX 0,0,320,16             ! Efface 16 pixels en haut...
  PBOX 0,184,320,200          ! ...et en bas
  DIM pr%(8)                  ! Adresse des sprites d‚cal‚s
  FOR i%=0 TO 7               ! Pr‚d‚calage ...
    RC_COPY XBIOS(2),0,0,320,200 TO a%+i%*32000,i%*2,0
    pr%(i%)=a%+i%*32000
  NEXT i%
RETURN
.
PROCEDURE sin
  .
  .Proc‚dure de calcul et de conversion
  .de la courbe du sprite.
  .
  lon&=1430                   ! Longueur courbe
  FOR i%=0 TO lon&/8          ! calcul de la courbe ...
    ADD n%,2
    SUB j,1.783
    x%=640+160*COSQ(n%)*COSQ(n%*2)+j ! ... en X
    y%=20*SINQ(n%*2)                 ! ... et en Y
    x%=DIV(x%,2)*2                   ! Pr‚d‚calage de 16/2
    SUB x%,MUL(320,DIV(x%,320))      ! Si d‚bordement ...
    .
    .calcul de l'adresse d'affichage et du d‚calage
    .
    {c%+i%*8+4}=ADD(MUL(y%,160),SHR(x%,1) AND 248)
    {c%+i%*8}=pr%(DIV(x%,2) AND 7)
  NEXT i%
RETURN
.
PROCEDURE fin
  VOID XBIOS(5,L:xb%,L:xb%,-1)! Restoration xbios(2)
  ~MFREE(a%)                  ! On lib‚re la memoire...
  ~MFREE(c%)                  ! ... l… aussi ...
  ~MFREE(im%)                 ! ... encore une fois ...
  ~MFREE(imm%)                ! ... et une autre ...
  OUT 4,8                     ! la souris est l… !!
  EDIT                        ! Et hop … l'editeur...
RETURN
.
PROCEDURE sync
  SWAP i1%,i2%                ! Echange les ‚crans
  ~XBIOS(5,L:i1%,L:i2%,-1)    ! Initialisation des ‚crans
  VSYNC                       ! Attend la prochaine VBL
RETURN


...............................................................
LES DISTORSIONS HORIZONTALES

L'effet de distorsion est assez facile à réaliser et produit un
effet toujours apprécié, c'est pourquoi il est tant utilisé dans
les démos. Le principe est très simple et pourrait être assimilé
à celui des "big sprites" à la différence que l'affichage ne se
fait non pas en bloc, mais ligne à ligne. Essayez d'observer
longuement l'une de ces distorsions; vous remarquerez une sorte
de vague remontant lentement le long du logo. Ce phénomène est
particulièrement visible avec des objets de taille importante. En
fait, le motif est soumis à une courbe gènèrale, mais chacune des
lignes qui le compose se déplace avec un retard régulier sur
celles qui les précèdent. Techniquement parlant, nous allons
recourir à un buffer contenant la courbe précalculée. Soit pnt%
le pointeur sur l'adresse de la position dans la courbe à un
instant donné. Nous décalerons la première ligne selon le contenu
de pnt%, la seconde selon pnt%+1, la troisième selon pnt%+2 et
ainsi de suite. Le transfert ayant été fait, nous n'ajouterons
qu'une unité à pnt%. De fait, la première ligne aura,lors de
l'appel suivant, un décalage similaire à celui de la seconde lors
de la VBL précédente. Idem pour le reste du logo, d'oû
l'impression de vague.
La première étape nécessaire à la programmation d'une distorsion
est le calcul de la courbe que va suivre cette dernière. Le
format que nous avons arbitrairement adopté est le suivant :
- Offset par rapport au début du buffer contenant le logo
prédécalé ( 1 mot long )
- Offset par rapport à l'origine horizontale de l'écran ( 1 mot )
Une simple addition permettra ainsi de trouver directement
l'adresse du bloc à transferer; une seconde déterminera celle de
la cible. A noter que, le motif se déplacant horizontalement, il
faudra reserver des espaces le précédent et le suivant afin
d'effacer les traces laissées par celui-ci. Dans les listings
proposés ici, nous avons seize pixels supplémentaires de chaque
coté, ce qui devrait être suffisant pour des vitesses de courbe
raisonnables. Le programme calculant le mouvement vous demandera
au départ un certain nombre de paramètres tels que la largeur et
la hauteur du logo. Si vous conservez le petit dessin crée par le
programme principal, ces valeurs devront être respectivement 160
et 50. Les paramètres suivants agiront sur la forme de la courbe
qui sera représentée graphiquement sous vos yeux ébahis. Notez
que le centrage est automatique. Vous remarquerez l'ajout
systématique de la valeur quinze à la largeur du dessin avant le
AND destiné à en faire un multiple de seize ( voir article
précédent pour plus de détails sur cette opération ). Le but de
cette opération est d'obtenir un arrondissement par excès sans
lequel le motif serait tronqué en cas de longueur non multiple de
seize. Le SHR sur la valeur obtenue permet ensuite d'obtenir un
équivalent en nombre d'octets. Vous remarquerez un nombre
supplémentaire de positions, correspondant à la hauteur du
dessin. Ceci permet un bouclage correct de la courbe car il ne
faut pas oublier qu'un offset est rajouté au pointeur à chaque
ligne.


Code: Tout sélectionner
.*************************************
.* Calcul d'une courbe de distorsion *
.*+ transformation X->Offset par Jedi*
.*************************************
.
SETCOLOR 0,0
SETCOLOR 15,1911
HIDEM
CLS
INPUT "Largeur du motif ";largeur%
INPUT "Hauteur du motif ";hauteur%
yahoo:
INPUT "Coefficient 1 : ";coef1%
INPUT "Coefficient 2 : ";coef2%
INPUT "Coefficient 3 : ";coef3%
INPUT "Offset 1 ";offset1%
INPUT "Offset 2 ";offset2%
INPUT "Offset 3 ";offset2%
.
.La largeur doit etre multiple de seize
largeur%=AND(ADD(largeur%,15),65520)
rayon=SUB(319,largeur%)/2
centrage=largeur%/2
CLS
PRINT "Visualisation de la courbe"
FOR angle%=0 TO 359
  x=rayon*COSQ((angle%+offset1%)*coef1%)
  MUL x,SINQ((angle%+offset2%)*coef2%)
  MUL x,COSQ((angle%+offset3%)*coef3%)
  ADD x,rayon
  x%=ROUND(x+centrage)
  VSYNC
  BMOVE XBIOS(2)+16160,XBIOS(2)+16000,15840
  PSET x%,198,1
NEXT angle%
PRINT "Okay pour la forme ? ( O/N )"
REPEAT
  key$=UPPER$(INPUT$(1))
UNTIL key$="O" OR key$="N"
IF key$="N"
  CLS
  GOTO yahoo
ENDIF
CLS
FILESELECT "A:\*.WAV","",nfichier$
IF nfichier$=""
  EDIT
ENDIF
.
.Largeur du motif+espaces en octets
largeur%=ADD(SHR(largeur%,1),24)
.
.Taille d'un bloc pr‚d‚cal‚
une_phase%=MUL(largeur%,hauteur%)
OPEN "o",#1,nfichier$
FOR angle%=0 TO ADD(359,hauteur%)
  x=rayon*COSQ((angle%+offset1%)*coef1%)
  MUL x,SINQ((angle%+offset2%)*coef2%)
  MUL x,COSQ((angle%+offset3%)*coef3%)
  ADD x,rayon
  x%=ROUND(x)

  .Calcul de l'offset n‚cessaire pour
  .trouver l'adresse du bloc-source
  adrblok%=AND(x%,15)
  MUL adrblok%,une_phase%
  .
  .Calcul de l'offset sur ‚cran
  adrscrn%=SHR(AND(x%,65520),1)
  .
  .On ‚crit tout ‡a dans le fichier...
  PRINT #1,MKL$(adrblok%)+MKI$(adrscrn%);
NEXT angle%
CLOSE #1
 


La seconde étape est plus complexe. Il faut bien songer au fait
que les BMOVE servant à effectuer le transfert seraient du type:
BMOVE debut du buffer+LONG{pnt%},... puis
BMOVE debut dubuffer+longueur d'une ligne+LONG{pnt%}, BMOVE debut du
buffer+longueur de deux ligne+LONG{pnt%},...
Or, il se trouve que les expressions "debut du buffer+xxx" sont des constantes qui ne
variront jamais. Or‚ effectuer sans cesse ces additions ne serait
par conséquent qu'une perte de temps ( machine ! ). Nous allons
donc chacune les remplacer par une seule et même variable
équivalente au résultat. Il y aura de fait autant de variables
que de lignes qui composent le logo. Toutes les définir
représenterait un horrible travail dactylographique, c'est
pourquoi nous allons réutiliser un principe abordé le mois
dernier: un programme génerant un petit programme. Ce dernier
devra ensuite être inseré gràce à la commande MERGE au sein du
listing principal.


Code: Tout sélectionner
.***************************************
.* Generation de la liste de variables *
.*destin‚e … la distorsion horizontale.*
.***************************************
INPUT "Hauteur du motif : ",hauteur%
INPUT "Largeur du bo dessin : ",stephanie%
.
.-> Largeur en octets ( blancs compris )
stephanie%=AND(ADD(stephanie%,15),65520)
largeur%=ADD(SHR(stephanie%,1),24)
FILESELECT "a:\*.LST","",nfichier$
IF nfichier$=""
  EDIT
ENDIF
OPEN "O",#1,nfichier$
FOR delphine%=0 TO PRED(hauteur%)
  PRINT #1,"precalc";delphine%;"%";
  PRINT #1,"=precalc%+";delphine%*largeur%
NEXT delphine%
CLOSE #1   


Le transfert gràce à un nombre affolant de BMOVE soulève le même
problème. Nous allons donc recourir à un second programme qui va
quant à lui calculer la routine d'affichage. Le fichier généré
devra lui-aussi être inclu dans le programme principal.


Code: Tout sélectionner
.*************************************
.*  Calcul de la routine principale  *
.* de transfert pour une distorsion  *
.*  par le grand Jedi de sector one. *
.*************************************
SETCOLOR 0,0
SETCOLOR 15,1911
HIDEM
CLS
INPUT "Largeur du motif : ",largeur%
INPUT "Hauteur : ",hauteur%
largeur%=AND(ADD(largeur%,15),65520)
largeur%=SHR(largeur%,1)
ADD largeur%,24
DEC hauteur%
FILESELECT "A:\*.LST","",nfichier$
IF nfichier$=""
  EDIT
ENDIF
OPEN "O",#1,nfichier$
FOR ace%=0 TO hauteur%
  PRINT #1,"BMOVE ADD(precalc";ace%;"%,";
  PRINT #1,"LONG{pnt%+";ace%*6;"}),";
  PRINT #1,"ADD(ADD(ecran%,";160*ace%;"),";
  PRINT #1,"CARD{pnt%+";4+ace%*6;"}),";
  PRINT #1,largeur%
NEXT ace%
CLOSE #1
EDIT

Toutes les opérations préalables ayant été réalisées, nous
pouvons enfin nous pencher sur le programme proprement dit. Notez
tout d'abord l'utilisation de BMOVE afin de transferer l'image
décalée dans le buffer. Le reste du programme ne devrait pas
poser de problèmes. L'indispensable méthode de la synchronisation
sur deux écrans a été réemployée. Au niveau de la gestion de la
courbe, la variable pnt% contient en permanence l'adresse du
décalage correspondant à la première ligne affichée. Lorsque
celle-ci dépasse la 359ème position, on reboucle au début du
buffer. Vous constaterez avec horreur que la hauteur maximale que
pourra atteindre le motif avoisine les 64. Pourquoi un tel
ralentissement comparé au "big sprite" ? Un désassemblage de
l'instruction BMOVE explique clairement ce phénomène. Cette
instruction décompose l'opération en plusieurs transferts
successifs. Elle a tout d'abord lieu par paquets de 352 octets,
puis de 96, de 32, de 16, de 8, de 4, de 2, et en copie un dernier si
nécessaire. Un déplacement de 32000 groupes de huit bits comme
c'était le cas avec le "big sprite" utilise principalement le
premier type de transfert, qui est de loin le plus rapide. En
revanche, l'affichage d'une simple ligne au moyen de la même
instruction nécessite l'utilisation de nombreux petits blocs,
d'où l'absence de proportionalité entre les deux opérations.
BMOVE reste cependant l'instruction de transfert de lignes en
quatre plans la plus rapide et la plus simple d'emploi.


Code: Tout sélectionner
.**************************************
.* Routine de distorsion en GfA-Basic *
.* par Jedi of Sector One from T.H.K. *
.**************************************
SETCOLOR 0,0
SETCOLOR 15,1911
HIDEM
CLS
SPOKE &HFFFFFC02,&H12 ! Bloque la souris
.
.On fait un boooooooo dessin...
GRAPHMODE 2
DEFFILL 2,4
PRBOX 0,0,159,49
RBOX 0,0,159,49
COLOR 4
RBOX 1,1,158,48
COLOR 5
RBOX 2,2,157,47
DEFTEXT 3,1+8,,16
TEXT 6,30,"GFA IS GOOD 4 U"
GRAPHMODE 1
.
.Sa taille: 160x50
largeur%=160
hauteur%=50
largeur%=AND(ADD(largeur%,15),65520)
.
.On compte 8 octets suppl‚mentaires
.bikoz le pr‚d‚calage vers la droite
largeur%=ADD(SHR(largeur%,1),8)
taille_du_buffer_necessaire%=ADD(largeur%,16)
MUL taille_du_buffer_necessaire%,hauteur%
.
.Il faut pr‚voir les seize phases
MUL taille_du_buffer_necessaire%,16
RESERVE FRE(0)-taille_du_buffer_necessaire%
precalc%=MALLOC(taille_du_buffer_necessaire%)
rose%=precalc%
COLOR 0
.
.
.------------------------------------------
.- Mergez ici la d‚finition des variables -
.------------------------------------------
.
.
.Precalculation proprement dite
FOR phase%=0 TO 15
  FOR li%=0 TO PRED(hauteur%)
    .
    .Espace pr‚cedent le motif
    LONG{rose%}=0
    LONG{rose%+4}=0
    ADD rose%,8
    adresse_sur_l_ecran%=XBIOS(2)
    ADD adresse_sur_l_ecran%,colonne%
    ADD adresse_sur_l_ecran%,MUL(li%,160)
    BMOVE adresse_sur_l_ecran%,rose%,largeur%
    ADD rose%,largeur%
    .
    .Espace post-motif
    LONG{rose%}=0
    LONG{rose%+4}=0
    ADD rose%,8
  NEXT li%
  GET 0,0,318,PRED(hauteur%),nathalie$
  PUT 1,0,nathalie$
  LINE 0,0,0,PRED(hauteur%)
NEXT phase%
CLS
OPEN "i",#1,"*.wav"
courbe$=INPUT$(LOF(#1),#1)
CLOSE #1
.
.Reserve 32K pour le second ‚cran
ecran2$=STRING$(32255,0)
.
.Mieux vaut faire un FRE(0) avant de
.d‚clarer des pointeurs sur l'adresse
.de variables.
~FRE(0)
eclipse_sct1%=XBIOS(2) ! Mem.video originale
.
.Adresses relatives … la courbe
debut_de_la_courbe%=V:courbe$
pnt%=debut_de_la_courbe%
fin_de_la_courbe%=debut_de_la_courbe%
ADD fin_de_la_courbe%,LEN(courbe$)
SUB fin_de_la_courbe%,MUL(hauteur%,6)
ecran1%=XBIOS(2)
ecran2%=AND(ADD(V:ecran2$,255),&HFFFFFF00)
.
.Vide l'‚cran que nous venons de reserver
BMOVE ecran1%,ecran2%,32000
.
.Boucle principale
DO
  ~XBIOS(5,L:ecran1%,L:ecran2%,-1)
  VSYNC
  SWAP ecran1%,ecran2%
  .
  .Il faut retirer 8 octets en raison
  .de l'espace pr‚c‚dent le motif
  ecran%=ADD(ecran2%,152)
  .
  .
  .-------------------------
  .- Mergez ici les BMOVEs -
  .-------------------------
  .
  .
  ADD pnt%,6                 ! Pos. suivante
  IF pnt%>=fin_de_la_courbe% ! Courbe finie ?
    pnt%=debut_de_la_courbe% ! => boucle
  ENDIF
LOOP UNTIL INKEY$=" "
~MFREE(precalc%)
~XBIOS(5,L:eclipse_sct1%,L:eclipse_sct1%,-1)
SPOKE &HFFFFFC02,8
EDIT


L'EFFET CYLINDRIQUE

Cet effet donne l'impression d'une image enroulée horizontalement
autour d'un axe. Ne croyez pas que chaque pixel qui la compose
est calculé en temps réel en trois dimensions. La technique est
en effet on ne peut plus simple. Il s'agit là aussi d'un
transfert ligne à ligne. Cependant ce dernier ne va pas être
réalisé avec une progression identique pour la source et la
destination. Observons une image plaquée sur un cylindre à
l'oeil nu. Nous remarquons qu'elle a tendance à se rétrécir en
fuyant vers le haut ou le bas, et à conserver son échelle
originale au centre. Cette progression ayant tout l'air d'être
sinusoidale, nous pourrions effectuer la projection en adoptant
une copie dont la source serait traitée ligne à ligne;
l'affichage sur écran se ferait donc selon une sinusoide. Soit X
l e compteur utilisé pour définir la ligne qui va être recopiée et
Y celle de l'endroit où elle va être réecrite. Seule une courbe
sur 180° nous interesse, l'arrière du rouleau restant invisible.
L'angle sur lequel le sinus ( ou plutôt le cosinus ) va
s'appliquer est tout naturellement défini par : A=Hauteur du
bloc source/PI*X. D'où la relation : Y=Hauteur du bloc source-
Rayon du cylindre*cos(A). Un effet de rouleau est donc réalisable
à l'aide de cette formule, mais toutes les lignes du motif devant
être prises en compte, plusieurs copies successives à la même
adresse auront lieu. Nous serions plutôt interessés par le
remplissage complet du cylindre sur l' écran. Ceci nous amène à
calculer le numéro de la ligne source et à gerer un transfert
régulier,ce qui revient encore à calculer A en fonction de Y :
A=Hauteur du bloc source/PI*ArcCos((Rayon du cylindre-Y)/Rayon du
cylindre). En pratique, nous allons utiliser cette formule pour
créer une succession de BMOVE réalisant directement l'effet que
nous souhaitons quelle que soit la ligne de départ, les offsets
restants identiques. C'est d'ailleurs l'objet du listing suivant
( Comme quoi le hasard fait bien les choses... ) .


Code: Tout sélectionner
.********************************
.* Calcul des offsets des BMOVE *
.* lors d'un effet cylindrique. *
.*   par Jedi/Sector One/T.H.K  *
.********************************
SETCOLOR 0,0
SETCOLOR 15,1911
HIDEM
CLS
INPUT "Hauteur de la bande : ",oterol%
INPUT "Hauteur du cylindre : ",hauteur%
DEC oterol%
DEC hauteur%
rayon=hauteur%/2
FILESELECT "A:\*.LST","",nfichier$
IF nfichier$=""
  EDIT
ENDIF
OPEN "O",#1,nfichier$
.
.D‚termination des offsets n‚cessaires
FOR y%=0 TO hauteur%
  .
  .Merci … Ziggy Stardust !
  a%=ROUND(oterol%/PI*ACOS((rayon-y%)/ROUND(rayon)))
  PRINT #1,"BMOVE ADD(pnt%,";a%*160;"),ADD(ecran%,";
  PRINT #1,y%*160;"),160"
NEXT y%
CLOSE #1
EDIT

Ceci étant calculé, nous n'avons plus qu'à faire varier l'origine
du bloc source pour donner l'impression de rotation. Le programme
suivant vous permet de charger une image Degas ou Neochrome, puis
la balaye sur toute sa hauteur en l'affichant gràce au module
crée précédemment.


Code: Tout sélectionner
.******************************************
.*       Effect cylindrique en GfA        *
.* par Jedi/Sector One/The Heavy Killers  *
.******************************************
CLS
ALERT 2,"| | Format de l'image ? |",1,".PI1|.NEO",a%
SELECT a%
CASE 1     ! Degas
  FILESELECT "A:\*.PI1","",nfichier$
  IF EXIST(nfichier$)=0
    EDIT
  ENDIF
  OPEN "I",#1,nfichier$
  SEEK #1,2
  palette$=INPUT$(32,#1)
  ~XBIOS(6,L:V:palette$)
  scn$=INPUT$(32000,#1)
  CLOSE #1
CASE 2     ! Neochrome
  FILESELECT "A:\*.NEO","",nfichier$
  IF EXIST(nfichier$)=0
    EDIT
  ENDIF
  OPEN "I",#1,nfichier$
  SEEK #1,4
  palette$=INPUT$(32,#1)
  ~XBIOS(6,L:V:palette$)
  SEEK #1,128
  scn$=INPUT$(32000,#1)
  CLOSE #1
ENDSELECT
SPOKE &HFFFFFC02,&H12
.
.Hauteur de la bande repr‚sent‚e dans le rouleau
hauteur%=96
RESERVE FRE(0)-32255
ecran1%=XBIOS(2)
ace_of_sct1%=ecran1% ! Sauvegarde
maverick_of_sct1%=MALLOC(32255)
ecran2%=AND(ADD(maverick_of_sct1%,255),&HFFFFFF00)
.
.Copie l'‚cran actuel dans l'‚cran reserv‚
.( Efface donc ce dernier )
BMOVE ecran1%,ecran2%,32000
CLR ang%
.
.Centrage de la courbe
ace_of_sct1=SUB(199,hauteur%)/2
.
.Routine principale
DO
  ~XBIOS(5,L:ecran1%,L:ecran2%,-1)
  SWAP ecran1%,ecran2%
  VSYNC
  ysource%=ROUND(ace_of_sct1+ace_of_sct1*SINQ(ang%))
  ADD ang%,2
  IF ang%=360
    ang%=0
  ENDIF
  .
  .Origine du bloc source
  pnt%=ADD(V:scn$,MUL(ysource%,160))
  ecran%=ecran2% ! Adresse destination
  .
  .
  .------------------------------
  .- MERGEZ ICI LE SOURCE AYANT -
  .-      GENERE LES BMOVE      -
  .------------------------------
  .
  .
LOOP UNTIL INKEY$=" "
~MFREE(maverick_of_sct1%)
~XBIOS(5,L:ace_of_sct1%,L:ace_of_sct1%,-1)
SPOKE &HFFFFFC02,8
EDIT


...............................................................
LE BMOVE PRE CALCUL E

Le principe des blocs précalculés aurait pu être abordé avant les
"big sprites", les distorsions et les rouleaux car cet effet est
de loin le plus simple à réaliser; mais il présente un certain
nombre d'inconvénients: d'une part la limitation de la durée de
l'animation et d'autre part la taille mémoire nécessaire à la
sauvegarde des blocs précalculés. Le programme suivant propose
une distorsion verticale de motifs. Le programme va tout d'abord
sauvegarder un bloc de seize sur seize pixels qui sera le motif
de base. Puis nous allons calculer une courbe cyclique dans un
bloc de 320 pixels de large sur 32 de haut. Les courbes ainsi
obtenues seront copiées dans un buffer en sauvegardant leurs
adresses respectives. Il ne restera plus qu' à afficher ( dans la
boucle principale ) les différentes courbes précalculées les unes
à la suite des autres à l'aide d'un simple BMOVE. Pour multiplier
la courbe à l'écran, nous copierons plusieurs fois notre bloc
avec la même instruction.


Code: Tout sélectionner
.***************************
.*   BMOVES  PRECALCUL S   *
.*   par DENEB (FANTASY)   *
.***************************
.
SETCOLOR 0,0                  ! Couleur 0
SETCOLOR 13,15                ! Couleur 13 (si!)
xb%=XBIOS(2)                  ! Sauve adresse ecran
OUT 4,18                      ! Il tue la souris ...
HIDEM                         ! ...et cache le corps
RESERVE 30000                 ! R‚servation
a%=MALLOC(5120*33)            ! Buffer pr‚calc
im%=MALLOC(32256)             ! Ecran de synchro
i1%=AND(im%,&HFFFFFF00)       ! Un ‚cran ...
i2%=XBIOS(3)                  ! Et un autre ...
ON BREAK GOSUB fin            ! En cas d'arret
@init                         ! Initialisation
.
.BOUCLE PRINCIPALE
.
DO
  FOR i%=0 TO 32
    BMOVE ad%(i%),i1%,5120           ! Copie 1
    BMOVE i1%,ADD(i1%,5120),5120     ! Copie 2
    BMOVE i1%,ADD(i1%,10240),5120    ! Copie 3
    BMOVE i1%,ADD(i1%,15360),15360   ! Copie des 3
    sync                             ! Synchro
  NEXT i%
LOOP UNTIL PEEK(&HFFFC02)=57         ! Press space?
@fin                                 ! C'est la fin
.
PROCEDURE init
  .
  .Procedure de calculs et sauvegarde memoire
  .des blocs pr‚decales.
  .
  DEFFILL 15,4,4              ! Choix couleur et logo
  PBOX -1,-1,15,15            ! Affiche logo
  GET 0,0,14,14,p$            ! Prend logo
  DIM ad%(35)                 ! Adresses des blocs
  co%=15                      ! Genre courbe
  FOR i%=0 TO 32              ! Il y a 33 blocs
    CLS                       !  ...cls...
    FOR ii%=0 TO 20           ! Affichage des 20 logos
      ADD t,0.52              ! Variable de calcul
      y%=9+9*SINQ(t+ii%*co%)  ! Calcul de la courbe
      PUT ii%*16,y%,p$        ! Affichage des logos
    NEXT ii%
    BMOVE xb%,a%+i%*5120,5120 ! Copie Ecran -> Buffer
    ad%(i%)=a%+i%*5120        ! Sauvegarde des adresses
  NEXT i%
  CLS                         ! Ho ! qu'il est beau...
  BMOVE XBIOS(2),i1%,32000    ! Efface l'‚cran cach‚
RETURN
.
PROCEDURE fin
  VOID XBIOS(5,L:xb%,L:xb%,-1)! Restauration xbios(2)
  ~MFREE(a%)                  ! On lib‚re la memoire...
  ~MFREE(im%)                 ! On re-libŠre
  OUT 4,8                     ! La souris est en vie !!!
  EDIT                        ! Et hop … l'‚diteur...
RETURN
.
PROCEDURE sync
  SWAP i1%,i2%                ! Echange les ‚crans
  ~XBIOS(5,L:i1%,L:i2%,-1)    ! Initialisation des ‚crans
  VSYNC                       ! Attend la prochaine VBL
RETURN

..............................................................
DER ABSCHLUSS

Les exemples proposés ici ne sont qu'un échantillon des nombreux
effets réalisables gràce à cette instruction. A vous d'en trouver
d'autres... Le mois prochain, nous continuerons d'étudier les
sprites, mais cette fois de tailles plus modestes et qui feront
appel à une technique totalement différente de celle que nous
venons d'aborder. Si vous avez des questions ou des propositions
dont vous voudriez nous faire part, passez donc par l'inimitable
3615 STMAG et laissez nous un message en bal DZC.
Avatar de l’utilisateur
tomchi
Administrateur du site
 
Messages: 342
Inscription: Mer 15 Oct 2008 20:51

Retourner vers Gfx/Démo

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité

cron