Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Exercice pratique : le PROXIMITY

Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Par Monsieur Spi, le 07 février 2013

Bonjour,

Voici un petit exercice rapide qui se place dans la catégorie grand débutant, il s'agit du Proximity

Tout d'abord le résultat :

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Les sources sont disponibles en fin d'exercice.

Etude préliminaire

Tout d'abord le PROXIMITY c'est quoi ? (et cette fois on ne dit pas merci Wikipedia)

Le jeu est composé d'une grille comprenant des pièces de deux types. Au départ du jeu le type des pièces est disposé aléatoirement dans la grille. Le joueur peut cliquer sur chaque pièces ce qui retourne à la fois la pièce sur laquelle il a cliqué mais également les 4 pièces adjacentes à la case (haut, bas, droite , gauche). La case haut gauche de la grille réagit cependant différemment puisqu'elle retourne également la case située en diagonale directement en bas à droite de la case, c'est la clé pour permettre la résolution du casse tête.

Le joueur doit faire en sorte que toutes les pièces soient identiques dans la grille.

Un petit casse tête très simple à mettre en place mais extrêmement difficile à résoudre.

Les pré-requis

Je vous recommande fortement d'avoir au moins lu les exercices suivants : DEMINEUR, PONG, SNAKE, TAQUIN
Les exercices sont courts mais de nombreuses astuces y sont proposées, je ne les expliquerai pas à chaque nouvel exercice.

Pour ce programme vous devez connaître :

Si vous souhaitez plus de précisions sur ces points, je vous encourage à parcourir le Wiki de Mediabox où vous trouverez de nombreux tutoriaux détaillés.

Le code

Voyons d'abord tout le code d'un coup.

var C:int = 10;
var T:int = 48;
var p:Piece;
var i:int;
var stock:Array;
 
var panneaux:Panneaux = new Panneaux();
panneaux.addEventListener(MouseEvent.MOUSE_DOWN, init);
panneaux.buttonMode = true;
addChild(panneaux);
 
function init(e:Event):void {
	while(numChildren>0) removeChildAt(0);
	stock = [];
	for (i = 0; i<C*C; i++){
		p = new Piece();
		p.x = int(i%C)*T;
		p.y = int(i/C)*T;
		if (Math.random()>.5) p.gotoAndStop(2);
		p.addEventListener(MouseEvent.CLICK, clic);
		p.buttonMode = true;
		addChild(p);
		stock.push(p);
	}
}
 
function clic(e:MouseEvent):void{
	p = Piece(e.target);
	i = stock.indexOf(p);
	p.play();
	if (p.y/T<C-1) 	stock[i+C].play();
	if (p.y/T>0) 	stock[i-C].play();
	if (p.x/T<C-1) 	stock[i+1].play();
	if (p.x/T>0) 	stock[i-1].play();
	if (i == 0) 	stock[i+C+1].play();
	i = p.currentFrame;
	for each(p in stock){if(p.currentFrame != i) return;}
	for each(p in stock){p.removeEventListener(MouseEvent.CLICK, clic);}
	addChild(panneaux);
	panneaux.gotoAndStop(3);
}

C'est pas énorme comme vous pouvez le constater et comme vous avez lu les pré-requis ça va être encore plus court à expliquer ;-)

Etude du programme

Comme d'habitude j'utilise la bibliothèque de Flash pour gérer les graphismes, ce qui me permet d'alléger le code et de ne conserver que ce qui est utile pour l'exercice, si vous n'utilisez pas Flash voici les modifications à faire dans le programme :

Panneaux :

  • un clip qui regroupe tous les panneaux d'interface
  • un panneau différent par frame

Pieces :

  • un clip qui regroupe tous les types de pièces
  • un type sur chaque frame

Allez c'est parti pour l'étude pas à pas :

var C:int = 10;
var T:int = 48;
var p:Piece;
var i:int;
var stock:Array;
 
var panneaux:Panneaux = new Panneaux();
panneaux.addEventListener(MouseEvent.MOUSE_DOWN, init);
panneaux.buttonMode = true;
addChild(panneaux);

Initialisation du programme, je commence par effacer tout ce qui traîne à l'affichage et vider le stock pour le cas où le joueur recommencerait une partie. Ensuite je parcours la grille et je place les pièces, chaque pièce est aléatoirement de type A ou B et possède un écouteur pour le clic (c'est pour une fois plus simple à écrire comme ça ;-) ). Et enfin on ajoute la pièce à l'affichage et au stock.

function clic(e:MouseEvent):void{
	p = Piece(e.target);
	i = stock.indexOf(p);
	p.play();
	if (p.y/T<C-1) 	stock[i+C].play();
	if (p.y/T>0) 	stock[i-C].play();
	if (p.x/T<C-1) 	stock[i+1].play();
	if (p.x/T>0) 	stock[i-1].play();
	if (i == 0) 	stock[i+C+1].play();
	i = p.currentFrame;
	for each(p in stock){if(p.currentFrame != i) return;}
	for each(p in stock){p.removeEventListener(MouseEvent.CLICK, clic);}
	addChild(panneaux);
	panneaux.gotoAndStop(3);
}

Quand on cliques sur une pièce, on récupère son index dans le stock (qui représente la grille), et on la change de type (passe en frame suivante). On récupère les pièces adjacentes et on change également leur type, enfin, si la pièce est la première du stock (donc celle qui se trouve en haut à gauche de la grille) on change également le type de la pièce qui se trouve en bas à droite de cette case.

On récupère le nouveau type de la pièce sur laquelle on a cliqué (la frame qu'elle affiche) et on vérifie si toutes les pièces qui se trouvent dans le stock sont de même type, si c'est le cas le joueur a gagné, on retire les écouteurs de toutes les pièces et on affiche le panneau de fin.

Et voilà c'est tout, de la rigolade ;-)

Conclusion

Parfois les jeux les plus simples à coder sont aussi les plus durs à terminer, et c'est le cas ici, ce jeu est presque impossible tant il est difficile (enfin pour moi), tout réside dans la permutation d'une seule et unique pièce, celle du coin en haut à gauche, qui permet de changer la donne. Personnellement je n'ai réussi à le finir qu'une seule fois sur de nombreux essais, à vous de jouer ;-)

Les sources

proximity_mb.fla version CS6
proximity_mb_cs5.fla version CS5