Économiseur d'écran ou décors stellaire d'un
jeu d'action... en tous cas notre animation ne pèse pas lourd
(6 Ko). Il faut dire que sa distribution ne contient qu'un seul
acteur bitmap 1 bit de 4 pixels !
Un seul acteur et aussi... un peu de Lingo.
Commençons. On dispose notre acteur fusée 90 fois
sur la scène. Le principe de l'animation que l'on doit leur
donner et le suivant : Initialement regroupés, les sprites
doivent s'éloigner en des directions opposées et s'estomper
afin de simuler un éclatement. Nos fusées se verront
toutes attacher le même comportement. On y déclare
d'abord leur propriétés communes. Parmi celles-ci,
deux incréments de déplacement (pPasHorizontal, pPasVertical)
qui déterminent l'orientation ou l'angle de chaque fusée
lors de l'explosion. Si le pasHorizontal est identique au pas vertical,
l'orientation est de 45°.
C'est en modifiant de façon aléatoire ces valeurs
lors de l'instanciation que nous obtiendrons que chaque sprite parte
dans un sens différent. Une dernière propriété
pMouvement servira de "flag" ou d'indicateur afin de distinguer
les sprites immobiles (pMouvement = false).
Le comportement attaché à chacun des 90 sprite est
rédigé ainsi :
Le gestionnaire "initialisationDe" sera envoyé à
chaque sprite afin d'amorcer un éclatement. Et ce, seulement
si nécessaire (if pMouvement=true). Deux paramètres
devront être passés au gestionnaire : un lieu
de regroupement (début de l'explosion) et une couleur.
on initialisationDe me, ou, quelCouleur
if pMouvement then exit
-- on arrête là si le sprite est
déjà en mouvement sinon :
pMouvement= true
sprite (the currentSpriteNum ).loc = ou
pPosH = sprite (the currentSpriteNum ).loc[1]
pPosV = sprite (the currentSpriteNum ).loc[2]
sprite(the currentSpriteNum).foreColor = quelCouleur
sprite(the currentSpriteNum).blend =100
Afin de simuler un réel éclatement, les sprites doivent
s'estomper peu à peu. Nous utiliserons pour cela la propriété
"blend". On doit aussi donner aléatoirement une direction
dans l'espace à chacun d'entre eux. Ici un petit rappel de
mathématique est toujours utile : La position horizontale
d'un point sur un cercle est égale au cosinus de l'angle
multiplié par le rayon. Illustration.
Malheureusement, lingo ne parle qu'en degrés radians 360°
= ³*2 radians. Nous effectuons une petite conversion.
x = random(360)
-- on choisit un angle quelconque
x = x* pi()/20
-- en radians
-- et nous calculons en conséquence le pas.
-- la fonction random() permet de modifier le rayon
-- du cercle fictif et ainsi de faire aller notre fusée
plus ou moins loin.
Afin que les sprites soient animés après initialisation,
nous ajoutons à leur comportement un gestionnaire prepareFrame.
Rappelons que ce gestionnaire sera appelé continûment
à chaque nouveau tableau ou frame.
on prepareFrame me
if not pMouvement then exit
-- on arrête là si le sprite doit rester
immobile
-- c'est le cas avant instanciation ou à la fin du
mouvement
if sprite(the currentSpriteNum).blend > 5 then
-- s'il est encore visibles seulement, on le
déplace d'un incrément
pPosH = pPosH + pPasHorizontal
pPosV = pPosV + pPasVertical
sprite(the currentSpriteNum).loc = point(pPosH, pPosV)
-- et on les estompe un peu (blend - 3)
sprite(the currentSpriteNum).blend = sprite(the currentSpriteNum).blend
- 3
else
-- s'il est inutile de le déplacer alors
-- on place le sprite hors la scène
sprite(the currentSpriteNum).loc = point(-50,-50)
-- et on indique sa disponibilité pour une
nouvelle instanciation (
pMouvement = false
end if
end
Chaque sprite est donc doté d'un gestionnaire prepareFrame
qui le déplace si nécessaire, c'est à dire
si sa propriété pMouvement est égale à
false. Encore faut-il, pour que notre feux d'artifice commence,
que cette propriété soit changée répétitivement.
C'est sur le script de tableau cette fois que nous plaçons
le code requis. Parce qu'il s'agit d'éviter un mouvement
trop "mécanique", la fonction random va être fortement
sollicitée.
on prepareFrame
if random(2) - 1 then exit
-- Grâce à cette ligne, le gestionnaire
-- ne sera pas toujours exécuté
-- mais seulement aléatoirement
-- Rappel : 0 est équivalent à false
On souhaite animer un premier groupe de 20 sprites. Il nous faut
juste pour cela leur faire parvenir un message d'initialisation
(qui ne sera exécuté que s'il y a lieu - voir plus
haut). L'instruction "initialisationDe" - on l'a vu - requiert deux
arguments, un lieu de départ et une couleur.
Le lieu de départ doit être situé dans les
limites de la scène et même mieux, dans une zone plus
réduite.
x = random(260)+20
-- ainsi x est compris entre 20 et 280 (la scène fait 320
pixels de large)
y = random(180)+10
endroit = point(x,y)
couleur = random(175)
-- on dispose de 255 couleurs dans la palette mais les dernières
références
-- donnent des couleurs trop sombres pour notre but.
repeat with n = 1 to 20
sendSprite(n, #initialisationDe, endroit, couleur)
end repeat
En l'état notre script peut être testé déjà.
Mais nous voulons que de temps en temps, d'autres groupes de sprites
soient également animés. On reprend donc le même
code en le modifiant un peu.
if random(2) - 1 then exit
-- Grâce à cette ligne, la suite du gestionnaire
-- ne sera pas toujours exécuté
x = random(260)+20
y = random(180)+10
couleur = random(175)
repeat with n = 21 to 30
sendSprite(n, #initialisationDe, point(x,y),
couleur)
end repeat
if random(2) - 1 then exit
--- un paquet de 40 sprites de même couleur (le bouquet
?)
x = random(280)+10
y = random(180)+10
couleur = random(175)
repeat with n = 51 to 90
sendSprite(n, #initialisationDe, point(x,y),
couleur)
end repeat
if random(2) - 1 then exit
x = random(260)+20
y = random(180)+10
couleur = random(175)
repeat with n = 31 to 40
sendSprite(n, #initialisationDe, point(x,y),
couleur)
end repeat
x = random(260)+20
y = random(180)+10
couleur = random(175)
repeat with n = 41 to 50
sendSprite(n, #initialisationDe, point(x,y),
couleur)
end repeat