All posts by Ateoz

Traer une « particule »-arité dans le rendu physique

flag

Si Box2D est sans aucun doute le moteur physique 2D le plus utilisé pour ActionScript 3, je me suis intéresser de plus prés au moteur Traer. À l’origine, il a été écrit en Java par  Jeffrey Traer Bernstein. Le très bon article de Arnaud Icard explique les fonctionnalités de ce moteur. Il s’agit de jouer avec les particules, en leur donnant une force, une attraction, imbriquer entre elles elles donne une animation sur lequel nous pouvons intérargir à l’aide de la souris ou/et du clavier. Personnellement j’ai utilisé la classe « makeSpring », pour réaliser mon test. Une pléiade d’exemples  avec leurs codes sources en bonus ;) sont présentés sur le site Github.

A très bientôt et have fun on Flash! :)

les mots en image

androp

Dernièrement je suis allé jeter un coup d’oeil sur FWA visualiser les sélections de sites full Flash. Parmis tous, un a retirer mon attention. Son nom, Androp. ce site amuserait beaucoup un écrivain, car il propose un concept originale : « celle de jouer avec les mots«  . Immergé dans un décor en synchro avec la musique, son côté fun ( et oui on parle de gameplay là ) ajoute la grosse cerise sur le gateau :)

le but du jeu est très simple, envoi un message à un de tes amis. Une fois ton message écrit….et bien je te laisse découvrir la suite et surtout enjoy cette expérience de jeu ;)

 

Un trace pour flash Develop

Sachez que si vous travaillez sous flash develop, il existe deux solutions pour afficher les traces de votre application flash :

-> la première consiste à installer la version flash player avec le mode debugger. Si votre version actuelle flash player ne contient pas le mode debugger, désinstallée-là avant d’installer la nouvelle version.

-> la deuxième est qu’il faut importer la classe FlashConnect. Pour cela vous écrivez à l’endroit où sont écrits vos imports de classes :  » import org.flashdevelop.utils.FlashConnect;  »

Puis à l’endroit où vous souhaitez effectuer votre trace, vous écrivez le bout de code suivant :  » FlashConnect.trace(  » éléments à tracer  » );  » ensuite vous compilez et appuyer sur le bouton play pour afficher votre swf. Puis regardez en bas à droite dans le « output » vous verrez marquez juste en dessous du  » Done(0) » votre trace. L’image parle d’elle même :)

 

mini jeu pour la pause café

Le Puzzle fait partie de ces jeux dont on profite durant une pause café au travail, histoire de se divertir et parfois même ce détendre à condition de ne pas avoir 500 pièces à remettre dans l’ordre lol :) .

Ceci dit pour mon jeu de puzzle j’ai intégré 3 niveau de difficulté. Ce jeu est développé en AS3 avec l’utilisation du Frameworks Lowra de Francis Bourre concernant le chargement de l’image Bitmap (qui servira au Puzzle) et du swf  du bouton permettant de choisir le niveau du jeu.

En effet, lors du développement du jeu de puzzle, j’avais rencontré un petit problème. Je souhaitais que les éléments chargés soit mis dans un tableau dans un ordre précis. Or quand je lancer les chargement par le biais d’une boucle, c’est celui qui terminé de chargé en premier qui était  ajouté en premier dans le tableau.

Pour remédier à ce problème, j’ai utilisé la classe « QueueLoader » du Frameworks Lowra qui permet de charger dans un ordre précis. En gros, tant que le 1er chargement n’est pas fini et bien les autres chargements reste en attente. Trés pratique cette classe :) .

Ce jeu de Puzzle est directement inspiré des minis jeux de  Gary Rosenzweig.  Son site FlashGameUniversity propose des tutoriels vidéo pour la réalisation des mini jeux en Flash.

A très bientôt :)

voici le code source

package {
	import caurina.transitions.Tweener;
	import com.bourre.load.GraphicLoader;
	import com.bourre.load.QueueLoader;
	import com.bourre.load.QueueLoaderEvent;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.MovieClip;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.net.URLRequest;
	import flash.text.TextField;

	/**
	 * @author Elvis Leroux
	 */
	public class Puzzle extends Sprite
	{

		protected var _sBitmapOne       : String = "http://www.ateoz.com/projet/Puzzle/Image/landscape.jpg";//mettez ici le chemin pour acceder à votre image
		protected var _sButtonPlay      : String = "http://www.ateoz.com/projet/Puzzle/Image/BoutonPlay.swf";//mettez ici le chemin pour acceder à votre bouton

		protected var _aTabStringBitmap : Array = [_sBitmapOne, _sButtonPlay];
		protected var _tabImageLoaded   : Array = new Array();
		protected var _aTabPieceBmp     : Array;
		protected var _aTabMovePiece    : Array;
		protected var _qLoader          : QueueLoader = new QueueLoader();
		protected var _blankPoint       : Point;
		protected var _spContainer      : Sprite;
		protected var _mcScene          : MovieClip;
		protected var _puzzleObject     : Object;
		protected var _bButtonClick     : Boolean = false;
		protected  var _bslideEffect    : Boolean = false;
		protected var _bTweening        : Boolean = false;
		protected var _mixAleatoire     : Number = 500;
		protected var _nChoiceLevel     : Number = -1;
		protected var _nBitmapLoaded    : Number = 0;
		protected var nbrePieceAtX      : Number;
		protected var nbrePieceAtY      : Number;
		protected var _nBmpWidth        : Number ;
		protected var _nBmpHeight       : Number ;
		protected var _nX               : Number;
		protected var _nY               : Number;

		public function Puzzle()
		{
			//initialise l'image bitmap du puzzle et le swf Bouton permettant de choisir le niveau
			initBitmapPuzzle();
		}

		protected function initBitmapPuzzle():void
		{
			for( var i : Number = 0; i < _aTabStringBitmap.length; i++ )
			{
				var Loader : GraphicLoader = new GraphicLoader();
				_qLoader.add(Loader, "loader"+i, new URLRequest(_aTabStringBitmap[i]));
			}
			_qLoader.addEventListener(QueueLoaderEvent.onItemLoadInitEVENT, endingLoad);

			_qLoader.load();
		}

		protected function endingLoad ( e : QueueLoaderEvent ):void
		{
			_nBitmapLoaded ++;
			if( _nBitmapLoaded == 1 )
			{
				//ici on recupere l'image du puzzle
				var bmp : Bitmap = Bitmap((e.getLoader() as GraphicLoader).getView().getChildAt(0));
				_tabImageLoaded.push(bmp);
			}

			if( _nBitmapLoaded == 2 )
			{
				//ici on recupere le swf bouton
				var dob : DisplayObject = (e.getLoader() as GraphicLoader).getView();
				_tabImageLoaded.push(dob);
				_bButtonClick = true;
				//initialise le bouton
				initButton();
			}
		}

		protected function initButton():void
		{
			//recuperer la longueur de la bitmap pour le puzzle afin de placer le bouton en x
			var longWidthPuzzle : DisplayObject = _tabImageLoaded[0];

			_mcScene = _tabImageLoaded[1] as MovieClip;
			_mcScene.x = (longWidthPuzzle.width / 2) - (_mcScene.width / 2);
			_mcScene.y = 0;
			addChild(_mcScene);

			var bouton : SimpleButton = (_mcScene.getChildByName("MainScene") as DisplayObjectContainer).getChildByName("Button") as SimpleButton;
			bouton.addEventListener(MouseEvent.CLICK, onClickBouton);
		}

		protected function onClickBouton( e : MouseEvent ):void
		{
			if( _nChoiceLevel == 2)
			{
				_nChoiceLevel = -1;
			}
			if( _bButtonClick == true )
			{
				_nChoiceLevel++;
				if(_spContainer != null )
				{
					removeChild(_spContainer);
				}
				var sp : Sprite = new Sprite();
				createPuzzle( _nChoiceLevel, sp );

				//on melange les pieces du puzzle
				mixPieceBmp();
			}
		}

		protected function createPuzzle( n : Number, sp : Sprite ):void
		{
			//un array pour stocker le nombre de pieces en longueur et en hauteur
			var _aTabContentPiece : Array = new Array();

			//un textefield qui ecrira dans la barre du bouton le niveau de difficulté
			var tTexteLevel : TextField = ((_mcScene.getChildByName("MainScene") as DisplayObjectContainer).getChildByName("Barre")
				                               as DisplayObjectContainer).getChildByName("level") as TextField;

			switch(n)
			{

				case 0:
				nbrePieceAtX = 4;
				nbrePieceAtY = 3;
				_aTabContentPiece.push( nbrePieceAtX, nbrePieceAtY );
				tTexteLevel.text = "EASY";
				break;

				case 1:
				nbrePieceAtX = 7;
				nbrePieceAtY = 5;
				_aTabContentPiece.push( nbrePieceAtX, nbrePieceAtY );
				tTexteLevel.text = "NORMAL";
				break;

				case 2:
				nbrePieceAtX = 10;
				nbrePieceAtY = 7;
				_aTabContentPiece.push( nbrePieceAtX, nbrePieceAtY );
				tTexteLevel.text = "HARD";
				break;

				default:
			}

			// CREATION DU PUZZLE
			var bmp : Bitmap = _tabImageLoaded[0];
			_aTabPieceBmp = new Array();
			_spContainer = sp;

			//determine la longueur et hauteur de la pieceBitmap
			_nBmpWidth = Math.floor(bmp.width / _aTabContentPiece[0]);
			_nBmpHeight = Math.floor(bmp.height / _aTabContentPiece[1]);

			//coordonnes de X et Y permettant de definir a quel coordonnées de la bitmap principale
			//une partie de son image sera copié dans la pieceBmp
			_nX  = bmp.width / _aTabContentPiece[0];
			_nY  = bmp.height / _aTabContentPiece[1];

			//creation d'un point qui compare avec le rectangle
			//si celui est égale il ne faudra pas ajouter la piece
			_blankPoint = new Point(_aTabContentPiece[0]-1, _aTabContentPiece[1]-1);

			for( var v : Number = 0; v < _aTabContentPiece[1]; v ++)
			{
				for ( var h : Number = 0; h < _aTabContentPiece[0]; h++ )
				{
					if(_blankPoint.equals(new Point(h, v)))
					{
						return;
					}

					var pieceBmp : Bitmap = new Bitmap( new BitmapData(_nBmpWidth, _nBmpHeight));
					pieceBmp.bitmapData.copyPixels(bmp.bitmapData, new Rectangle(h*_nX, v*_nY, _nBmpWidth, _nBmpHeight ), new Point(0, 0));
					var container : Sprite = new Sprite();
					container.x = h * (pieceBmp.width)+50;
					container.y = v * (pieceBmp.height)+100;
					container.addEventListener(MouseEvent.CLICK, onAnim);
					container.addChild(pieceBmp);
					_spContainer.addChild(container);
					addChild(_spContainer);

					_puzzleObject = new Object();
					_puzzleObject.currentLoc = new Point(h, v);
					_puzzleObject.piece = container;
					_aTabPieceBmp.push(_puzzleObject);
				}
			}
		}

		protected function mixPieceBmp( ):void
		{
			//on brasse un nombre de fois les pieces du puzzle pour avoir un meilleur melange
			for( var i : Number = 0; i < _mixAleatoire; i++ )
			{
				shufflePiecePuzzle();
			}
		}

		protected function shufflePiecePuzzle():void
		{
			//ici on determine si les pieces sont deplacables ou non
			//si la piece est deplacable l'ajouter dans un tableau sinon ne rien faire
			_aTabMovePiece = new Array();
			for ( var i : Number = 0; i < _aTabPieceBmp.length; i++ )
			{
				if(possibleMove(_aTabPieceBmp[i]) != "NOT POSSIBLE")
				{
					_aTabMovePiece.push(_aTabPieceBmp[i]);
				}
			}
			var pieceMove : Number = Math.floor(Math.random() * _aTabMovePiece.length);
			moveThePiecePuzzle(_aTabMovePiece[pieceMove], false);
		}

		protected function possibleMove( obj : Object ):String
		{
			if( (obj.currentLoc.x == _blankPoint.x) && (obj.currentLoc.y == _blankPoint.y + 1))
			{
				return "UP";
			}

			if( obj.currentLoc.x == _blankPoint.x && (obj.currentLoc.y == _blankPoint.y - 1))
			{
				return "DOWN";
			}

			if( obj.currentLoc.x == _blankPoint.x+1 && (obj.currentLoc.y == _blankPoint.y) )
			{
				return "LEFT";
			}

			if( obj.currentLoc.x == _blankPoint.x-1 && (obj.currentLoc.y == _blankPoint.y) )
			{
				return "RIGHT";
			}
			return "NOT POSSIBLE";
		}

		protected function moveThePiecePuzzle( Obj: Object, slideEffect : Boolean):void
		{
			switch(possibleMove(Obj))
			{
				case "UP":
				movePieceToDirection(Obj, 0, -1, slideEffect);
				break;

				case "DOWN":
				movePieceToDirection(Obj, 0, 1, slideEffect);
				break;

				case "RIGHT":
				movePieceToDirection(Obj, 1, 0, slideEffect);
				break;

				case "LEFT":
				movePieceToDirection(Obj, -1, 0, slideEffect);
				break;
			}
		}

		protected function movePieceToDirection( obj : Object, atX : Number, atY : Number, b : Boolean):void
		{
			obj.currentLoc.x += atX;
			obj.currentLoc.y += atY;
			_blankPoint.x -=atX;
			_blankPoint.y -=atY;

			if( b == false)
			{
				obj.piece.x = obj.currentLoc.x *(_nBmpWidth)+50;
				obj.piece.y = obj.currentLoc.y *(_nBmpHeight)+100;
			}

			if( b == true )
			{
				//un effet tween sur la piece quand celle-ci est cliquer par le joueur
				slideEffect(obj);
			}
		}

		protected function onAnim ( e : MouseEvent ):void
		{
			if(_bTweening){return;}
			for( var i : Number =0; i < _aTabPieceBmp.length; i++ )
			{
				if(_aTabPieceBmp[i].piece == e.currentTarget)
				{
					moveThePiecePuzzle(_aTabPieceBmp[i], true);
				}
			}
		}

		protected function slideEffect(object : Object):void
		{
			var slidePiece : Object = object;

			Tweener.addTween(slidePiece.piece, {x: slidePiece.currentLoc.x * (_nBmpWidth)+50,
			                 y:slidePiece.currentLoc.y * (_nBmpHeight)+100, time:0.250, transition : "linearinexpo",
			                  onStart: function():Boolean{_bTweening = true; return true;}, onComplete : function():Boolean{ _bTweening = false;return false;}});
		}

       }

}

mesure l’influence de ton jeu

mochi

Il est toujours gratifiant de voir à quel point votre jeu remporte un succés que ce soit par le gameplay, le style visuel etc… Mochimedia met à disposition des développeur flash une Api nommé  » mochi analytics API  » qui établi un rapport complet sur les statistiques de ton jeu. le temps en moyenne passer sur ton jeu, l’endroit où il a été joué, etc…tu as également un comparatif de ton jeu avec ceux des autres développeurs. Cela fonctionne aussi pour des videos, des animations des banners ads. Biensur, mochi propose d’autres api come  le « coin api » pour la monétisation de ton jeu.

Voila! la messe est dite! welcome in « Wall Street Gaming » lol. A tres bientôt.