I. Présentation du jeu
Adobe Flash (anciennement Macromedia Flash) est un logiciel multimédia utilisé pour créer du contenu interactif pour les sites Internets, des jeux vidéo,
des animations, etc.
Cet article est destiné à toute personne souhaitant développer des jeux vidéo en Flash.
Il présente une étude expliquant la création d'un jeu de serpent en ActionScript2.0.
I-A. Principe du jeu
Je suppose que vous connaissez déjà le principe du jeu.
Il s'agit d'un serpent qu'on peut déplacer avec les touches de direction du clavier. Le serpent augmente de taille s'il croise l'un des deux types d'objets suivant qu'on peut appeler des bonus.
La taille du serpent augmente d'un élément.
La taille du serpent augmente de deux éléments.
Si le serpent dépasse les quatres extrémités de la surface du jeu ou fait une collision avec lui même, alors le jeu se termine.
Le déplacement du serpent peut se faire dans les huit directions :

Il s'agit d'un serpent qu'on peut déplacer avec les touches de direction du clavier. Le serpent augmente de taille s'il croise l'un des deux types d'objets suivant qu'on peut appeler des bonus.


Si le serpent dépasse les quatres extrémités de la surface du jeu ou fait une collision avec lui même, alors le jeu se termine.
Le déplacement du serpent peut se faire dans les huit directions :

I-B. Aperçu du Jeu
Voici un aperçu de la surface du jeu.


I-B-1. Essayer le Jeu▲
Vous pouvez essayer le jeu à cette adresse : ftp://ftp-developpez.com/slim-boukettaya/sources/Snake.swf
Au début, cliquez avec la souris sur l'animation pour lui donner le focus et utilisez ensuite les touches directionnelles du clavier pour jouer.
Au début, cliquez avec la souris sur l'animation pour lui donner le focus et utilisez ensuite les touches directionnelles du clavier pour jouer.
II. Notions à maîtriser avant de commencer
II-A. Classe Array
D'après la documentation officielle, la classe Array vous permet d'accéder aux tableaux indexés et de les manipuler. Un tableau indexé est un objet dont les propriétés sont identifiées par un nombre représentant leur position au sein de celui-ci. Ce nombre est appelé index. Tous les tableaux indexés sont basés sur zéro, ce qui signifie que le premier élément du tableau est [0], le deuxième est [1], etc. Pour créer un objet Array, utilisez le constructeur new Array(). Pour accéder aux éléments d'un tableau, utilisez l'opérateur d'accès au tableau ([]).
Exemple :
Parmi les méthodes de la classe Array qu'on va utiliser dans la suite de l'article, on cite la fonction push() :
qui ajoute un ou plusieurs éléments à la fin d'un tableau et renvoie la nouvelle longueur du tableau.
Exemple :
Et la fonction splice() :
qui supprime des éléments dans un tableau.
Exemple :
Exemple :
Sélectionnez
var
oneArray:
Array
=
new
Array
("
a
"
,
"
b
"
,
"
c
"
);
var
twoArray:
Array
=
oneArray;
//
Les
deux
variables
array
se
rapportent
au
même
tableau.
twoArray[
0
]
=
"
z
"
;
trace
(oneArray);
//
Renvoie
:
z,b,c.
Sélectionnez
push
(value:
Object
) :
Number
Exemple :
Sélectionnez
var
myPets_array:
Array
=
new
Array
("
cat
"
,
"
dog
"
);
var
pushed:
Number
=
myPets_array.
push
("
bird
"
,
"
fish
"
);
trace
(pushed);
//
Affiche
4.
Sélectionnez
splice
(startIndex:
Number
,
[
deleteCount:
Number
]
,
[
value:
Object
]
) :
Array
Exemple :
var
myPets_array:
Array
=
new
Array
("
cat
"
,
"
dog
"
,
"
bird
"
,
"
fish
"
);
trace
(myPets_array.
splice
(1
));
//
Affiche
dog,bird,fish.
trace
(myPets_array);
//
cat
II-B. Classe MovieClip
Lorsqu'on veut insérer une animation dans la scène principale, on peut dès lors utiliser la classe MovieClip. Chaque objet Movieclip admet une barre scénarios (time-line) indépendante de celle de la scène principale ce qui permet de faire toute sorte de traitement dans un objet MovieClip.
Vous trouvez plus d'information à cette adresse : http://help.adobe.com/fr_FR/FlashPlatform/reference/actionscript/2/help.html?content=Part2_AS2_LangRef_1.html
Parmi les méthodes de la classe MovieClip qu'on va utiliser, la méthode hitTest() :
qui évalue le clip pour savoir s'il recouvre ou recoupe la zone active identifiée par les paramètres de coordonnées target.
Cette méthode sera utilisée pour tester les collisions du serpent avec les bords de la surface du jeu.
Une deuxième méthode à utiliser est removeMovieClip() qui permet de supprimer une occurrence de clip créée avec l'une des méthodes suivantes :
On va utiliser pour notre jeu la méthode :
qui sélectionne un symbole dans la bibliothèque identifiée par le paramètre id correspondant au nom de liaison d'un clip de la bibliothèque et l'associe au clip défini par le paramètre name à un niveau de profondeur depth.
Vous trouvez plus d'information à cette adresse : http://help.adobe.com/fr_FR/FlashPlatform/reference/actionscript/2/help.html?content=Part2_AS2_LangRef_1.html
Parmi les méthodes de la classe MovieClip qu'on va utiliser, la méthode hitTest() :
hitTest
(target
:
Object
):
Boolean
Cette méthode sera utilisée pour tester les collisions du serpent avec les bords de la surface du jeu.
Une deuxième méthode à utiliser est removeMovieClip() qui permet de supprimer une occurrence de clip créée avec l'une des méthodes suivantes :
Sélectionnez
duplicateMovieClip
(),
MovieClip
.
duplicateMovieClip
(),
MovieClip
.
createEmptyMovieClip
()
MovieClip
.
attachMovie
().
Sélectionnez
attachMovie
(id:
String
,
name
:
String
,
depth:
Number
,
[
initObject:
Object
]
) :
MovieClip
II-C. Classes personnalisées
On peut créer des classes en ActionScript 2.0. Chaque classe doit être définie dans un fichier externe qui porte le nom de la classe avec l'extesion.as.
Pour créer une classe en Flash, il faut suivre ces étapes :
Pour créer une classe en Flash, il faut suivre ces étapes :
- Sélectionner le menu Fichier ;
- Commande Nouveau ;
- Fichier ActionScript ;
- Valider avec Ok.
Sélectionnez
class
HelloWord
{
var
chaine :
String
;
//
function
constructeur
public
function
HelloWord (message
:
String
)
{
chaine =
message
}
}
II-D. Classe key
Pour créer des applications interactives qui exécutent des traitements suite aux appuis des utilisateurs sur les touches du clavier, il faut avoir recours à la classe key et utiliser ses fonctions et ses propriétés. Exemple :
Sélectionnez
if
(Key
.
isDown
(key.
RIGHT
))
{
//
traitement
qui
sera
exécuté
dés
l'appui
sur
la
flèche
Droit
}
else
if
(Key
.
isDown
(key.
LEFT
))
{
//
traitement
qui
sera
exécuté
dés
l'appui
sur
la
flèche
Gauche
}
else
if
(Key
.
isDown
(key.
UP
))
{
//
traitement
qui
sera
exécuté
dés
l'appui
sur
la
flèche
Haut
}
else
if
(Key
.
isDown
(key.
DOWN
))
{
//
traitement
qui
sera
exécuté
dés
l'appui
sur
la
flèche
Bas
}
III. Création du jeu
III-A. Création de la surface du jeu
Au début, il faut commencer par la création de la surface du jeu :

On doit choisir une taille pour la surface du jeu :
j'ai opté pour les dimensions 500x300 qui est en fait un choix personnel.
Pour tester si le serpent a dépassé les limites, j'ai pensé à placer quatre rectangles graphiques sur les bornes de la surface.
Ces rectangles sont intitulés : mur_haut, mur_bas, mur_droit, mur_gauche.
Chaque rectangle est un clip, ce qui permet par conséquent d'utiliser la méthode hitTest() dans la fonction collision_mur() pour tester les collisions :
Cela pourra se faire autrement si on compare les cordonnées de la tête du serpent avec les cordonnées x et y de chaque mur.
Par exemple on pourra écrire cette instruction :

On doit choisir une taille pour la surface du jeu :
j'ai opté pour les dimensions 500x300 qui est en fait un choix personnel.
Pour tester si le serpent a dépassé les limites, j'ai pensé à placer quatre rectangles graphiques sur les bornes de la surface.
Ces rectangles sont intitulés : mur_haut, mur_bas, mur_droit, mur_gauche.
Chaque rectangle est un clip, ce qui permet par conséquent d'utiliser la méthode hitTest() dans la fonction collision_mur() pour tester les collisions :
Sélectionnez
function
collision_mur
()
{
//
tete_snake
est
le
clip
qui
présente
la
tête
du
serpent.
if
( tete_snake.
hitTest
(mur_haut) or
tete_snake.
hitTest
(mur_bas) or
tete_snake.
hitTest
(mur_gauche) or
tete_snake.
hitTest
(mur_droit))
return
true
;
else
return
false
;
}
Par exemple on pourra écrire cette instruction :
Sélectionnez
if
( tete.
snake.
_x
=
=
mur_haut.
_x
and
tete_snake.
_y
=
=
mur_haut.
_y
)
//
le
serpent
a
dépassé
la
limite
d'en
haut.
III-B. Ajout d'une image de fond
On peut ajouter une image de fond pour décorer un peu plus notre jeu.
Cette image doit être placée sur un calque et ne doit pas couvrir les rectangles correspondants aux murs des bords.

Cette image doit être placée sur un calque et ne doit pas couvrir les rectangles correspondants aux murs des bords.

III-C. L'objet serpent
Le serpent est composé de trois parties :
En fait, pour un clip, on peut récupérer son abscisse, son ordonnée et par conséquent, on peut le déplacer si on change les valeurs de ces cordonnées.
Chaque élément sera donc représenté par un clip, et on aura besoin d'un premier pour la tête, un deuxième pour la queue et de plusieurs clips représentant le corps suivant le nombre de bonus obtenus par le serpent.
- La tête.
- Le corps.
- La queue.
En fait, pour un clip, on peut récupérer son abscisse, son ordonnée et par conséquent, on peut le déplacer si on change les valeurs de ces cordonnées.
Chaque élément sera donc représenté par un clip, et on aura besoin d'un premier pour la tête, un deuxième pour la queue et de plusieurs clips représentant le corps suivant le nombre de bonus obtenus par le serpent.
III-D. Préparation du corps du serpent
La tête peut être un cercle colorié par un dégradé pour donner l'effet 3D. J'ai voulu donner un peu de réalisme au jeu c'est pourquoi j'ai essayé d'utiliser des images pour créer le serpent.
Si vous êtes graphiste, vous pouvez dessiner les objets graphiques du jeu avec un logiciel dédié comme Adobe Illustrator, et les importer dans la bibliothèque.
Mes recherches sur Google m'ont donné ces deux images :
et avec quelques modifications de l'image de l'élément du corps, on obtient la queue :

Finalement, pour créer ces trois éléments, il faut créer trois clips vides dans la bibliothèque et mettre dans chacun l'une de ces trois photos.
La tête du serpent va être placée manuellement avec un glisser-déposer sur la scène (ca peut se faire aussi d'une façon dynamique), par contre la queue et les éléments constituant le corps seront ensuite intégrés dynamiquement à la scène avec du code ActionScript en utilisant la méthode attachMovie(). Comme on a vu au début de l'article, cette méthode crée sur la scène une occurrence d'un clip de la bibliothèque. Elle s'utilise de la façon suivante :
Il faut attirer l'attention ici sur le paramètre 'nom du clip dans la bibliothéque' qui doit être le nom de liaison du clip de la bibliothèque qu'on peut spécifier dans cette fenêtre :

et qui est obtenu après avoir cliqué avec le bouton droit de la souris sur le clip concerné et avoir choisi la commande "liaison".
Voilà donc, chacun de ces trois clips doit avoir un nom de liaison pour pourvoir être placé sur la scène avec la méthode attachMovie().
Si vous êtes graphiste, vous pouvez dessiner les objets graphiques du jeu avec un logiciel dédié comme Adobe Illustrator, et les importer dans la bibliothèque.
Mes recherches sur Google m'ont donné ces deux images :

et avec quelques modifications de l'image de l'élément du corps, on obtient la queue :

Finalement, pour créer ces trois éléments, il faut créer trois clips vides dans la bibliothèque et mettre dans chacun l'une de ces trois photos.
La tête du serpent va être placée manuellement avec un glisser-déposer sur la scène (ca peut se faire aussi d'une façon dynamique), par contre la queue et les éléments constituant le corps seront ensuite intégrés dynamiquement à la scène avec du code ActionScript en utilisant la méthode attachMovie(). Comme on a vu au début de l'article, cette méthode crée sur la scène une occurrence d'un clip de la bibliothèque. Elle s'utilise de la façon suivante :
Sélectionnez
contenant.
attachMovie
("
nom
du
clip
dans
la
bibliothèque
"
,
"
nom
à
donner
à
l'occurrence
du
clip
"
,
profondeur) ;

et qui est obtenu après avoir cliqué avec le bouton droit de la souris sur le clip concerné et avoir choisi la commande "liaison".
Voilà donc, chacun de ces trois clips doit avoir un nom de liaison pour pourvoir être placé sur la scène avec la méthode attachMovie().
III-E. Préparation des bonus
Les bonus sont eux aussi des clips, ce qui permet d'utiliser la méthode hitTest() pour tester la collision de la tête du serpent avec ces derniers quand il seront placés sur la scène.
De la même façon que pour la gestion du serpent, il faut créer un clip vide dans la bibliothèque, par type de bonus et y placer une image parmi ces deux :

Avec un peu d'humour, on peut dire que notre serpent était herbivore.
L'ajout de ces clips dans la scène sera dynamiquement fait avec la méthode attachMovie().
De la même façon que pour la gestion du serpent, il faut créer un clip vide dans la bibliothèque, par type de bonus et y placer une image parmi ces deux :

Avec un peu d'humour, on peut dire que notre serpent était herbivore.
L'ajout de ces clips dans la scène sera dynamiquement fait avec la méthode attachMovie().
Après avoir préparé les différents éléments graphiques constituant le jeu, passons maintenant à l'écriture du code permettant la manipulation de tous ces éléments.
IV. Implémentation
Généralement, un code ActionScript peut être placé dans trois endroits différents :
Pour mieux organiser le code, on peut utiliser un nouveau calque CODE.
- dans un fichier externe ;
- sur une image des scénarios ;
- sur un bouton, un clip, etc.
Pour mieux organiser le code, on peut utiliser un nouveau calque CODE.
IV-A. Déplacement de la tête du serpent
Au début, il faut placer le clip correspondant à la tête du serpent au milieu de la scène.
Ensuite, il faut donner un nom à cette occurrence. On va utiliser l'identifiant tete_snake.
Pour déplacer la tête, on doit utiliser les touches directionnelles du clavier. La gestion des appuis clavier est définie dans la fonction mouvement_snake().
Le serpent va se déplacer suivant les huit directions. Cependant sa tête et son corps ne doivent pas garder le même sens et le même angle durant son mouvement suivant ces différentes directions. Ils doivent s'orienter suivant la sens de déplacement du serpent comme le montre la figure suivante :

La variable sens est utilisée pour déterminer le sens du mouvement du serpent. Elle peut prendre huit valeurs suivant le sens de mouvement. Ces valeurs correspondent en fait aux numéros des images clés dans le clip tête_snake sur lesquelles on va faire une rotation de la tête du serpent pour quelle corresponde à l'une des images dans la figure précédente.
Le scénario du clip tête_snake doit donc contenir huit images clés comme le montre la figure suivante

Pour naviguer entre ces différentes états, on peut avoir recours à la méthode gotoAndStop(num_image_clé).
Finalement, la fonction mouvement_snake() devra contenir le code suivant :
Rappelons que le code du jeu sera placé dans des images scénarios sur le calque CODE. Ce code sera donc exécuté à chaque passage de la tête de lecture du flash player par l'image contenant le code.
Vous devez donc écrire la fonction mouvement_snake() sur la première image du scénario (toutes les définitions des méthodes doivent être faites sur cette image), quant à l'appel de cette fonction, il doit se faire dans la deuxième image du scénario.
L'exécution des instructions doit être permanente tant que le jeu n'est pas fini. On peut donc utiliser le gestionnaire d'événement onEnterFrame :
Ensuite, il faut donner un nom à cette occurrence. On va utiliser l'identifiant tete_snake.
Pour déplacer la tête, on doit utiliser les touches directionnelles du clavier. La gestion des appuis clavier est définie dans la fonction mouvement_snake().
Le serpent va se déplacer suivant les huit directions. Cependant sa tête et son corps ne doivent pas garder le même sens et le même angle durant son mouvement suivant ces différentes directions. Ils doivent s'orienter suivant la sens de déplacement du serpent comme le montre la figure suivante :

La variable sens est utilisée pour déterminer le sens du mouvement du serpent. Elle peut prendre huit valeurs suivant le sens de mouvement. Ces valeurs correspondent en fait aux numéros des images clés dans le clip tête_snake sur lesquelles on va faire une rotation de la tête du serpent pour quelle corresponde à l'une des images dans la figure précédente.
Le scénario du clip tête_snake doit donc contenir huit images clés comme le montre la figure suivante

Pour naviguer entre ces différentes états, on peut avoir recours à la méthode gotoAndStop(num_image_clé).
Sélectionnez
tete_snake.
gotoAndStop
(20
);
Sélectionnez
if
(Key
.
isDown
(key.
RIGHT
) and
Key
.
isDown
(key.
UP
))
{
sens =
20
;
tete_snake.
gotoAndStop
(20
);
}
else
if
( Key
.
isDown
(key.
RIGHT
) and
Key
.
isDown
(key.
DOWN
) )
{
sens =
30
;
tete_snake.
gotoAndStop
(30
);
}
else
if
( Key
.
isDown
(key.
RIGHT
) and
!
( Key
.
isDown
(key.
UP
) ) and
!
( Key
.
isDown
(key.
DOWN
) ) )
{
sens =
1
;
tete_snake.
gotoAndStop
(1
);
}
else
if
( Key
.
isDown
(key.
LEFT
)and
(Key
.
isDown
(key.
UP
)) )
{
sens =
25
;
tete_snake.
gotoAndStop
(25
);
}
else
if
( Key
.
isDown
(key.
LEFT
) and
(Key
.
isDown
(key.
DOWN
)) )
{
sens =
35
;
tete_snake.
gotoAndStop
(35
);
}
else
if
( Key
.
isDown
(key.
LEFT
) and
!
(Key
.
isDown
(key.
DOWN
)) and
!
(Key
.
isDown
(key.
UP
)) )
{
sens =
10
;
tete_snake.
gotoAndStop
(10
);
}
else
if
( Key
.
isDown
(key.
DOWN
) and
!
(Key
.
isDown
(key.
LEFT
)) and
!
(Key
.
isDown
(key.
RIGHT
)) )
{
sens =
5
;
tete_snake.
gotoAndStop
(5
);
}
else
if
( Key
.
isDown
(key.
UP
) and
!
(Key
.
isDown
(key.
LEFT
)) and
!
(Key
.
isDown
(key.
RIGHT
)) )
{
sens =
15
;
tete_snake.
gotoAndStop
(15
);
}
if
(sens =
=
1
) tete_snake.
_x
+
=
10
;
else
if
(sens =
=
5
) tete_snake.
_y
+
=
10
;
else
if
(sens =
=
10
) tete_snake.
_x
-
=
10
;
else
if
(sens =
=
15
) tete_snake.
_y
-
=
10
;
else
if
(sens =
=
20
) {
tete_snake.
_y
-
=
5
;
tete_snake.
_x
+
=
5
;
}
else
if
(sens =
=
25
) {
tete_snake.
_y
-
=
5
;
tete_snake.
_x
-
=
5
;
}
else
if
(sens =
=
30
) {
tete_snake.
_y
+
=
5
;
tete_snake.
_x
+
=
5
;
}
else
if
(sens =
=
35
) {
tete_snake.
_y
+
=
5
;
tete_snake.
_x
-
=
5
;
}
}
Vous devez donc écrire la fonction mouvement_snake() sur la première image du scénario (toutes les définitions des méthodes doivent être faites sur cette image), quant à l'appel de cette fonction, il doit se faire dans la deuxième image du scénario.
L'exécution des instructions doit être permanente tant que le jeu n'est pas fini. On peut donc utiliser le gestionnaire d'événement onEnterFrame :
Sélectionnez
stop
();
onEnterFrame
=
function
()
{
mouvement_snake
();
collision_bonus
();
dessiner_snake
();
}
;
IV-B. Affichage des bonus sur la scène
Comme expliqué au début du chapitre, il y a deux objets qui présentent le bonus que le serpent doit atteindre pour augmenter sa taille.
La position de chacun de ces deux objets étant aléatoire et changeable, elle ne doit pas dépasser les limites de la surface du jeu qui est de 500 pixels en largeur et 320 pixels en hauteur.
De plus, la surface du jeu est définie au point supérieur gauche de coordonnées (40,20).
Deux fonctions ( affhcier_bonus_1 et afficher_bonus_2 ) doivent être créés pour regrouper les instructions de gestion de l'emplacement des bonus sur la scène :
L'appel de ces deux fonctions doit être fait de façon régulière et après un certain temps de latence.
On peut donc utiliser la méthode setInterval() qui permet d'appeler une fonction ou une méthode d'un objet à des intervalles périodiques pendant la lecture d'un fichier SWF.
L'ensemble du code présenté dans cette partie doit être placé dans la première image du scénario.
À ce niveau, la tête du serpent se déplace bien sur la scène mais la collision avec les objets bonus n'est pas détectée.
La position de chacun de ces deux objets étant aléatoire et changeable, elle ne doit pas dépasser les limites de la surface du jeu qui est de 500 pixels en largeur et 320 pixels en hauteur.
De plus, la surface du jeu est définie au point supérieur gauche de coordonnées (40,20).
Deux fonctions ( affhcier_bonus_1 et afficher_bonus_2 ) doivent être créés pour regrouper les instructions de gestion de l'emplacement des bonus sur la scène :
Sélectionnez
function
aléatoire
(min
:
Number
,
max
:
Number
):
Number
{
return
(max
-
min
)*
Math
.
random
()+
min
;
}
//
utiliser
pour
ne
pas
afficher
un
bonus
sur
le
corps
du
serpent.
function
existePosition
(tab:
Array
,
position
:
flash.
geom.
Point,
taille_bonus:
Number
)
{
l=
taille_bonus/
2
;
for
(var
i=
0
;
i<
tab.
length
;
i+
+
)
if
(
(tab[
i]
.
posX >=
position
.
x -
l) and
(tab[
i]
.
posX <=
position
.
x+
l) and
(tab[
i]
.
posY >=
position
.
y -
l) and
(tab[
i]
.
posY <=
position
.
y+
l)
)
return
true
;
return
false
;
}
function
afficher_bonus_1
()
{
//
pour
afficher
le
bonus
sur
la
surface
de
déplacement
du
serpent
//
les
limites
de
la
surface
en
x
:
59
--->
552
en
y
:
56
--->
340
Xbonus1 =
aléatoire
(59
,
552
);
Ybonus1 =
aléatoire
(56
,
340
);
var
posBonus:
flash.
geom.
Point =
new
flash.
geom.
Point
(Xbonus1,
Ybonus1);
//
pour
ne
pas
afficher
un
bonus
sur
le
corsp
du
serpent.
if
( !
(existePosition
(array_position_corp,
posBonus ,
20
)))
{
//
je
vais
laisser
le
méme
niveau
(-1)
(car
le
0
est
occupé
par
les
élement
corps
)pour
que
le
nouveau
bonus
remplace
l'ancien
attachMovie
("
bonus_1
"
,
"
bonus_1
"
,
100
);
bonus_1.
_x
=
Xbonus1;
bonus_1.
_y
=
Ybonus1;
}
else
afficher_bonus_1
();
}
function
afficher_bonus_2
()
{
//
pour
afficher
le
bonus
sur
la
surface
de
déplacement
du
serpent
//
les
limites
de
la
surface
en
x
:
59
--->
552
en
y
:
56
--->
340
Xbonus2 =
aléatoire
(59
,
552
);
Ybonus2 =
aléatoire
(56
,
340
);
var
posBonus:
flash.
geom.
Point =
new
flash.
geom.
Point
(Xbonus2,
Ybonus2);
//
pour
ne
pas
afficher
un
bonus
sur
le
corsp
du
serpent.
if
( !
(existePosition
(array_position_corp,
posBonus ,
30
)))
{
//
je
vais
laisser
le
méme
niveau
(-1)
(car
le
0
est
occupé
par
les
élement
corps
)pour
que
le
nouveau
bonus
remplace
l'ancien
attachMovie
("
bonus_2
"
,
"
bonus_2
"
,
200
);
bonus_2.
_x
=
Xbonus2;
bonus_2.
_y
=
Ybonus2;
}
else
afficher_bonus_2
();
}
On peut donc utiliser la méthode setInterval() qui permet d'appeler une fonction ou une méthode d'un objet à des intervalles périodiques pendant la lecture d'un fichier SWF.
Sélectionnez
//
appel
à
la
fonction
//
afficher_bonus_1
à
chaque
3
secondes.
monBonus1 =
setInterval
( afficher_bonus_1 ,
3000
) ;
//
appel
à
la
fonction
//
afficher_bonus_2
à
chaque
5
secondes.
monBonus2 =
setInterval
( afficher_bonus_2 ,
5000
) ;
À ce niveau, la tête du serpent se déplace bien sur la scène mais la collision avec les objets bonus n'est pas détectée.
IV-C. Détection des bonus
Rappelons que tous les objets graphiques constituant le jeu sont des clips. On peut donc profiter des services de la méthode hitTest() pour tester les collisions.
Si la tête entrelace un objet bonus, alors sa taille augmente. On utilise alors une variable taille_snake pour déterminer la taille actuelle du snake.
Après un contact avec la tête du serpent, le bonus doit disparaître de la scène, ce qui nous ammène à penser à utiliser la fonction removeMovieClip().
Les instructions de traitement sont regroupées dans la fonction collision_bonus() :
L'appel de cette méthode doit se faire dans l'image 2 du scénario après la fonction de gestion de déplacement du serpent mouvement_snake() puisque la détection du contact avec les bonus se fait d'une façon itérative après chaque mouvement du serpent.
Si la tête entrelace un objet bonus, alors sa taille augmente. On utilise alors une variable taille_snake pour déterminer la taille actuelle du snake.
Après un contact avec la tête du serpent, le bonus doit disparaître de la scène, ce qui nous ammène à penser à utiliser la fonction removeMovieClip().
Les instructions de traitement sont regroupées dans la fonction collision_bonus() :
Sélectionnez
function
collision_bonus
()
{
if
(tete_snake .
hitTest
(bonus_1))
{
taille_snake +
=
1
;
//
nouveau
morceau
du
corp;
bonus_1.
removeMovieClip
();
taille_snake +
=
1
;
//
place
réservée
à
la
queue
du
snake
score +
=
1
;
}
if
(tete_snake .
hitTest
(bonus_2))
{
taille_snake +
=
2
;
//
nouveau
morceau
du
corp;
bonus_2.
removeMovieClip
();
taille_snake +
=
1
;
//
place
réservée
à
la
queue
du
snake
score +
=
2
;
}
}
IV-D. Dessin du serpent▲
Cette partie est la plus importante de l'article et au cours de celle-ci je vais expliquer l'idée que j'ai suivie pour gérer l'augmentation de la taille du serpent à chaque contact avec un objet bonus.
Durant son mouvement, le serpent passe d'un point à un autre. La vitesse de déplacement est de 10 pixels et la fréquence de l'animation est de huit images par seconde.
L'idée consiste en fait à enregistrer les coordonnées de ces points parcourus par la tête du serpent. Le nombre de ces points doit être égal à la taille du serpent.
La structure de données utilisée pour le stockage de ces points est le tableau array_position_corp.
Chaque point contenu dans ce tableau va correspondre par la suite à la position d'insertion d'un élément du corps sur la scène.

Quant au dernier élément du tableau, il définirait la positon de la queue.
Puisque le déplacement du serpent suit huit directions, il faut donc adapter ces deux objets constituants le corps et la queue du serpent, au sens de déplacement de la tête à son passage par un point trajectoire. Ce sens de mouvement est important, il faut donc enregistrer les informations sur la direction de la tête à son passage par un tel point.
Bref, on est amené à enregistrer à chaque mouvement de la tête trois propriétés pour chaque point trajectoire :

Si on suit une approche orienté objet pour garder ces informations, il faut utiliser un type d'objets avec trois propriétés correspondant respectivement à l'abscisse, l'ordonnée et le sens de mouvement des points de la trajectoire.
En ActionScript 2.0, on crée alors une classe personnelle de nom Position_Direction qui admet trois attributs et une méthode constructeur pour initialiser ces attributs :
L'enregistrement de ces postions (les points de la trajectoire) dans le vecteur array_position_corp doit se faire dès le changement de la position du serpent géré par les appuis sur les touches du clavier.
Il faut donc modifier la fonction mouvement_snake() pour remplir le vecteur array_position_corp :
Les éléments enregistrés dans le vecteur array_position_corp seront utilisés pour déterminer la position d'addition d'un nouvel élément au corps du serpent (un nouveau nœud), ce qui va entraîner l'augmentation de sa taille. Ce nombre d'éléments doit être égal alors à la valeur de la variable taille_snake qui s'incrémente au cas où la tête du serpent atteint un objet bonus.
La taille de ce vecteur est dans certain cas trés supérieure à taille_snake. Il faut donc éliminer les éléments superflus avec la fonction splice().
Après ces traitements, on dispose de toutes les données pour ajouter un élément corps au serpent et augmenter sa taille effective sur la surface du jeu.

Pour ce faire, il faut créer une occurrence du clip nœud et la positionner sur la scène suivant les propriétés d'un élément du vecteur array_position_corp.
Ce traitement est définit par la fonction dessiner_snake :
Le dernier élément du vecteur est de valeur taille_snake-1 puisqu'on commence par la valeur 0. Cet élément contient les informations pour ajouter la queue au reste du corps du serpent.

À la fin, il ne reste plus qu'à appeler cette fonction pour exécuter ses instructions durant le déplacement du serpent. On peut donc penser à faire appel dans l'image 2 du scénario qui doit contenir finalement les appels suivants :

Durant son mouvement, le serpent passe d'un point à un autre. La vitesse de déplacement est de 10 pixels et la fréquence de l'animation est de huit images par seconde.
L'idée consiste en fait à enregistrer les coordonnées de ces points parcourus par la tête du serpent. Le nombre de ces points doit être égal à la taille du serpent.
La structure de données utilisée pour le stockage de ces points est le tableau array_position_corp.
Chaque point contenu dans ce tableau va correspondre par la suite à la position d'insertion d'un élément du corps sur la scène.

Quant au dernier élément du tableau, il définirait la positon de la queue.
Puisque le déplacement du serpent suit huit directions, il faut donc adapter ces deux objets constituants le corps et la queue du serpent, au sens de déplacement de la tête à son passage par un point trajectoire. Ce sens de mouvement est important, il faut donc enregistrer les informations sur la direction de la tête à son passage par un tel point.
Bref, on est amené à enregistrer à chaque mouvement de la tête trois propriétés pour chaque point trajectoire :

Si on suit une approche orienté objet pour garder ces informations, il faut utiliser un type d'objets avec trois propriétés correspondant respectivement à l'abscisse, l'ordonnée et le sens de mouvement des points de la trajectoire.
En ActionScript 2.0, on crée alors une classe personnelle de nom Position_Direction qui admet trois attributs et une méthode constructeur pour initialiser ces attributs :
Sélectionnez
class
Position_Direction
{
//
Classe
pour
présenter
les
points
parcouru
par
le
snake
//
Chaque
point/position
admet
aussi
une
direction.
var
sens :
Number
;
var
posX :
Number
;
var
posY :
Number
;
function
Position_Direction
(directTemp :
Number
,
posXTemp :
Number
,
posYTemp:
Number
)
{
this
.
sens =
directTemp;
this
.
posX =
posXTemp;
this
.
posY =
posYTemp;
}
}
Il faut donc modifier la fonction mouvement_snake() pour remplir le vecteur array_position_corp :
Sélectionnez
function
mouvement_snake
()
{
//
gestion
des
événements
clavier
[
&
#8230;
]
//
Déplacement
de
la
tète
du
snake
[
&
#8230;
]
nouvelle_position =
new
Position_Direction
(sens,
tete_snake.
_x
,
tete_snake.
_y
) ;
[
&
#8230;
]
array_position_corp.
unshift
( nouvelle_position );
[
&
#8230;
]
//
il
faut
garder
seulement
un
nombre
d'éléments
dans
le
vecteur
égale
à
la
taille
du
serpent.
array_position_corp.
splice
(taille_snake+
1
);
}
La taille de ce vecteur est dans certain cas trés supérieure à taille_snake. Il faut donc éliminer les éléments superflus avec la fonction splice().
Sélectionnez
array_position_corp.
splice
(taille_snake+
1
);

Pour ce faire, il faut créer une occurrence du clip nœud et la positionner sur la scène suivant les propriétés d'un élément du vecteur array_position_corp.
Ce traitement est définit par la fonction dessiner_snake :
Sélectionnez
function
dessiner_snake
()
{
for
(i=
0
;
i<
taille_snake-
1
;
i+
+
)
{
attachMovie
("
corps_snake
"
,
"
corps_snake_
"
+
i,
i);
this
[
"
corps_snake_
"
+
i]
.
_x
=
array_position_corp[
i]
.
posX;
this
[
"
corps_snake_
"
+
i]
.
_y
=
array_position_corp[
i]
.
posY;
this
[
"
corps_snake_
"
+
i]
.
gotoAndStop
(array_position_corp[
i]
.
sens);
}
//
ajouter
la
queue
du
serpent
attachMovie
("
queue_snake
"
,
"
queue_snake
"
,
300
);
this
[
"
queue_snake
"
]
.
_x
=
array_position_corp[
i]
.
posX;
this
[
"
queue_snake
"
]
.
_y
=
array_position_corp[
i]
.
posY;
this
[
"
queue_snake
"
]
.
gotoAndStop
(array_position_corp[
i]
.
sens);
}

À la fin, il ne reste plus qu'à appeler cette fonction pour exécuter ses instructions durant le déplacement du serpent. On peut donc penser à faire appel dans l'image 2 du scénario qui doit contenir finalement les appels suivants :

IV-E. Fin du jeu
Comme indiqué dans la partie principe du jeu, le jeu se termine si :

La fonction collision_mur permet de tester le contact entre la tête du serpent et les murs sur les bornes :
la fonction collision_corps() permet de tester s'il y a une collision entre la tête du serpent et le reste du corps :
Si le jeu se termine il faut initialiser les variables utiliser et enlever le serpent de la scène ainsi que les bonus affichés :
- le serpent atteint la limite de la surface repérée par les clips mur_bas, mur_haut, mur_gauche, mur_droit ;
- la tête du serpent entrelace le reste de son corps.
Sélectionnez
if
(collision_mur
())
gotoAndPlay
(5
);
if
( !
(collision_coprs
(nouvelle_position,
array_position_corp) ))
//
s'il
n'y
a
pas
collision
avec
son
corps
alors
ajouter
un
nouvel
élément.
array_position_corp.
unshift
( nouvelle_position );
else
{
//
s'il
y
a
collision
avec
son
corps,
alors
fin
du
jeux
gotoAndPlay
(5
);
delete
onEnterFrame
;
}

La fonction collision_mur permet de tester le contact entre la tête du serpent et les murs sur les bornes :
Sélectionnez
function
collision_mur
()
{
if
( tete_snake.
hitTest
(mur_haut) or
tete_snake.
hitTest
(mur_bas) or
tete_snake.
hitTest
(mur_gauche) or
tete_snake.
hitTest
(mur_droit))
return
true
;
else
return
false
;
}
Sélectionnez
function
collision_corps
(nouvelle_position :
Position_Direction,
array_position_corp:
Array
)
{
//
vérifier
si
la
nouvelle
position
de
la
tête
est
déjà
parcourue
for
(i=
0
;
i<
array_position_corp.
length
and
taille_snake >
0
;
i+
+
)
{
if
(nouvelle_position.
posX =
=
array_position_corp[
i]
.
posX and
nouvelle_position.
posY =
=
array_position_corp[
i]
.
posY )
//
if(
testeCollision(nouvelle_position,array_position_corp[i])
)
return
true
;
}
return
false
;
}
Sélectionnez
tete_snake.
x =
304
.
9
;
tete_snake.
_y
=
160
.
4
;
sens =
0
;
//
reste
fixe
au
début
for
(i=
0
;
i<
array_position_corp.
length
;
i+
+
)
_root
[
"
corps_snake_
"
+
i]
.
removeMovieClip
();
queue_snake.
removeMovieClip
();
clearInterval
(monBonus1);
clearInterval
(monBonus2);
bonus_1.
removeMovieClip
();
bonus_2.
removeMovieClip
();
array_position_corp.
splice
(0
);
IV-G. Ajouter un son de fond pour le jeu
On peut améliorer le jeu en ajoutant une musique de fond qui se lance au démarrage du jeu ou bien un effet sonore qui accompagne les collisions avec les bonus et les murs d'extrémité.
Prenons l'exemple de doter le jeu d'une musique de fond.
Au début, on doit insérer le fichier son à la bibliothèque et lui attribuer ensuite un nom de liaison, par exemple son_fond.
Enfin, il faut écrire du code ActionScript pour lancer et contrôler la lecture de fichier son :
Prenons l'exemple de doter le jeu d'une musique de fond.
Au début, on doit insérer le fichier son à la bibliothèque et lui attribuer ensuite un nom de liaison, par exemple son_fond.
Enfin, il faut écrire du code ActionScript pour lancer et contrôler la lecture de fichier son :
Sélectionnez
son =
new
Sound
();
son.
attachSound
("
son_fond
"
);
son.
start
();
son_fond.
onSoundComplete
=
function
()
{
//
restart
du
sons
this
.
start
();
}
V. Sources du jeu
Le fichier .fla du jeu ainsi que le fichier .swf sont disponibles à cette adresse.
VI. Liens utiles
VII. Conclusion
Dans cet article, j'ai donné les étapes à suivre ainsi que le code ActionScrip2.0 à écrire pour réaliser un jeu de serpent en flash.
Le design du jeu peut être amélioré et d'autres fonctionnalités peuvent être ajoutées comme la gestion du niveau de jeu.
Le design du jeu peut être amélioré et d'autres fonctionnalités peuvent être ajoutées comme la gestion du niveau de jeu.
Aucun commentaire:
Enregistrer un commentaire