É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