Création d'un jeu de serpent (snake) en AS2

Mohamed Slim

Adobe Flash (anciennement Macromedia Flash) est un logiciel multimédia utilisé pour créer du contenu interactif pour les sites Internet, 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.
Commentez

- Titre : Création d'un jeu de serpent (snake) en AS2

- Auteur : Mohamed Slim

- Parution : 14 juillet 2010

- Mise à jour : 6 janvier 2020

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2010 Mohamed Slim . Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Présentation du jeu

- I-A. Principe du jeu

- I-B. Aperçu du Jeu

- I-B-1. Essayer le Jeu

- II. Notions à maîtriser avant de commencer

- II-A. Classe Array

- II-B. Classe MovieClip

- II-C. Classes personnalisées

- II-D. Classe key

- III. Création du jeu

- III-A. Création de la surface du jeu

- III-B. Ajout d'une image de fond

- III-C. L'objet serpent

- III-D. Préparation du corps du serpent

- III-E. Préparation des bonus

- IV. Implémentation

- IV-A. Déplacement de la tête du serpent

- IV-B. Affichage des bonus sur la scène

- IV-C. Détection des bonus

- IV-D. Dessin du serpent

- IV-E. Fin du jeu

- IV-F. Ajouter un son de fond pour le jeu

- V. Sources du jeu

- VI. Liens utiles

- VII. Conclusion

- VIII. Remerciements

I - Présentation du jeu

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 quatre 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 :

les huit directions de déplacement

I-B - Aperçu du Jeu

Voici un aperçu de la surface du jeu.

surface du jeu

I-B-1 - Essayer le Jeu

Vous pouvez essayer le jeu à cette adresse : ./fichiers/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.

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 :

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.

Parmi les méthodes de la classe Array qu'on va utiliser dans la suite de l'article, on cite la fonction push() :

push(value: Object) : Number

qui ajoute un ou plusieurs éléments à la fin d'un tableau et renvoie la nouvelle longueur du tableau.
Exemple :

var myPets_array:Array = new Array("cat", "dog");
var pushed:Number = myPets_array.push("bird", "fish");
trace(pushed); // Affiche 4.

Et la fonction splice() :

splice(startIndex: Number, [deleteCount: Number], [value: Object]) : Array

qui supprime des éléments dans un tableau.
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'informations à cette adresse : https://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

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 :

duplicateMovieClip(),
MovieClip.duplicateMovieClip(),
MovieClip.createEmptyMovieClip()
MovieClip.attachMovie().

On va utiliser pour notre jeu la méthode :

attachMovie(id: String, name: String, depth: Number, [initObject: Object]) : MovieClip

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.

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 :

1. Sélectionner le menu Fichier ;

2. Commande Nouveau ;

3. Fichier ActionScript ;

4. Valider avec OK.

Exemple de classe :

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 :

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 :

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 :

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;
}

Cela pourra se faire autrement si on compare les coordonnées de la tête du serpent avec les coordonnées x et y de chaque mur.
Par exemple on pourra écrire cette instruction :

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.

image de fond

III-C - L'objet serpent

Le serpent est composé de trois parties :

- la tête ;

- le corps ;

- la queue.

Pour avoir un contrôle complet sur ces trois parties, il faut penser à l'utilisation des clips.
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 ses coordonné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 (ça 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 :

contenant.attachMovie("nom du clip dans la bibliothèque","nom à donner à l'occurrence du clip", profondeur) ;

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 pouvoir ê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 ils 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().

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 :

- dans un fichier externe ;

- sur une image des scénarios ;

- sur un bouton, un clip, etc.

Pour simplifier les choses, j'ai choisi de placer le code sur des images clés du scénario.
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 qu'elle 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érents états, on peut avoir recours à la méthode gotoAndStop(num_image_clé).

tete_snake.gotoAndStop(20);

Finalement, la fonction mouvement_snake() devra contenir le code suivant :

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;}

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 :

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 ( afficher_bonus_1 et afficher_bonus_2 ) doivent être créées pour regrouper les instructions de gestion de l'emplacement des bonus sur la scène :

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 corps du serpent.
if( !(existePosition(array_position_corp,posBonus ,20)))
{
//je vais laisser le même niveau (-1) (car le 0 est occupé par les éléments 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 corps du serpent.
if( !(existePosition(array_position_corp,posBonus ,30)))
{
//je vais laisser le même niveau (-1) (car le 0 est occupé par les éléments 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();
}

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.

//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) ;

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.

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 amène à penser à utiliser la fonction removeMovieClip().
Les instructions de traitement sont regroupées dans la fonction collision_bonus() :

function collision_bonus()
{
if(tete_snake .hitTest(bonus_1))
{
taille_snake +=1; // nouveau morceau du corps;
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 corps;
bonus_2.removeMovieClip();
taille_snake +=1; // place réservée à la queue du snake
score +=2;
}
}

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.

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 position de la queue.
Puisque le déplacement du serpent suit huit directions, il faut donc adapter ces deux objets constituant 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ée 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 :

class Position_Direction
{
// Classe pour présenter les points parcourus 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;
}
}

L'enregistrement de ces positions (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 :

function mouvement_snake()
{
//gestion des événements clavier
[…]

// Déplacement de la tète du snake
[…]

nouvelle_position = new Position_Direction(sens, tete_snake._x , tete_snake._y ) ;

[…]
array_position_corp.unshift( nouvelle_position );

[…]
// il faut garder seulement un nombre d'éléments dans le vecteur égal à la taille du serpent.
array_position_corp.splice(taille_snake+1);
}

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 certains cas très supérieure à taille_snake. Il faut donc éliminer les éléments superflus avec la fonction splice().

array_position_corp.splice(taille_snake+1);

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éfini par la fonction dessiner_snake :

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);
}

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 :

IV-E - Fin du jeu

Comme indiqué dans la partie principe du jeu, le jeu se termine si :

- 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.

On peut penser donc à afficher un message indiquant la fin du jeu comme « Game Over » qui sera inséré à une image du scénario de numéro num_image (avec num_image >3) et un appel à la méthode gotoAndPlay(num_image) pour atteindre cette image et afficher le message. Dans cet exemple, num_image =5 :

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 jeu
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 :

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;
}

la fonction collision_corps() permet de tester s'il y a une collision entre la tête du serpent et le reste du corps :

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;
}

Si le jeu se termine, il faut initialiser les variables utilisées et enlever le serpent de la scène ainsi que les bonus affichés :

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-F - 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 :

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

- Guide ActionScript2.0

- Aide et support Flash

- Centre de développeurs Flash

- Ressources Flash

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.

VIII - Remerciements

Je tiens à remercier la rubrique Flash de Developpez.com et son responsable Bovino, en particulier beekeep pour ses remarques et suggestions sur cet article.
Je remercie aussi Jacques THERY pour la relecture orthographique de l'article.