Simple jeu de tir en as3

Soyez le premier à donner votre avis sur cette source.

Vue 16 057 fois - Téléchargée 1 468 fois

Description

Après avoir vu un message sur le forum j'ai eu envie de creer une esquisse de jeu trés simpliste dans laquelle vous pourrez decouvrir les bases de quelques concept necessaires au codage de jeux en flash.

Entre autre :
- Dessiner sur un DisplayObject des formes simples avec l'api de dessin de flash
- Utiliser un clip pour un hitTest
- Creer une animation qui prend tout le navigateur, sans zoom (scalemode NO_SCALE)
- Capturer les événements souris, enterFrame et redimensionnement du stage
- Pivoter un clip suivant la position de la souris
- Gérer la vitesse d'un clip en utilisant une pseudo gravité
- Créer un Timer pour invoquer une fonction a intervalle régulier
- Jouer un son de fond
- Jouer un son FX lors d'un événemment
- etc...

Bien sur le tout en actionScript3.

Un jeu digne de ce nom devrait avoir une architecture plus travaillée et une encapsulation plus efficace, mais ici j'ai voulu "simplifier" au maximum.

Bien entendu, l'ajout de fonctionnalités, la mise a jour du code, ou la correction de bug serait bien plus difficile dans un code comme celui ci que dans un vrai projet orienté objet.

En tout cas...
Bonne lecture ;)

Source / Exemple :


Classe principale : 
package
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.media.Sound;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import flash.utils.Timer;

	public class Canon extends Sprite
	{
		
		private static const GRAVITE:Number = 0.5;
		private static const XFORCE:Number = 20;
		private static const YFORCE:Number = 25;
		private static const NBMOUETTE:Number = 2;
		private static const DIFFICULTE:Number = 15;
		
		
		
		/* clip du canon */
		private var canon:Sprite;

		/* conteneur ennemis + boulets */
		private var cont:Sprite;
		private var contEnnemis:Sprite;
		
		private var score:int = 0;
		private var scoreText:TextField;

		/* reference vers le son FX qui sera préchargé*/
		private var fxSound:Sound;
		private var tim:Timer;
		
		private var lastStageWidth:int;
		private var lastStageHeight:int;
		
		
		/* Point d'entrée */
		public function Canon()
		{
			/* Reglage du stage */
			/* pas de scaling */			
			stage.scaleMode = StageScaleMode.NO_SCALE;
			/* alignement en haut a gauche */
			stage.align = StageAlign.TOP_LEFT;
			/* sauvegarde des dimensions pour le ratio lors du redimmensionnement du stage */
			lastStageWidth = stage.stageWidth;
			lastStageHeight = stage.stageHeight;
			
			/* TextField de score */
			scoreText = new TextField();
			stage.addChild(scoreText);
			scoreText.text = "score : 0";
			
			/* Creation du canon */
			canon = createCanon();
			canon.x = stage.stageWidth /2;
			canon.y = stage.stageHeight - canon.height;
			addChild(canon);
			
			/* le conteneur va contenir les boulets et contEnnemis */
			cont = new Sprite();
			cont.x = stage.stageWidth/2 - cont.width/2;
			cont.y = stage.stageHeight - cont.height;
			
			/* contEnnimis contient les ennemis */
			contEnnemis = new Sprite();
			cont.addChild(contEnnemis);
			addChild(cont);
			
			/* ajout des ecouteurs */
			stage.addEventListener(Event.RESIZE, resizeStage);
			stage.addEventListener(MouseEvent.CLICK,mouseClick);
			stage.addEventListener(MouseEvent.MOUSE_MOVE,mouseMove);
			
			/* le timer va faire apparaitre les oiseaux */
			tim = new Timer(1000/NBMOUETTE);
			tim.addEventListener(TimerEvent.TIMER, timerBird);
			tim.start();
			
			/* Lancement du son */
			var sound:Sound = new Sound();
			sound.load(new URLRequest("sound/bg.mp3"));
			/* On preferera gerer la boucle de son avec un listener dans un jeu */
			sound.play(0,int.MAX_VALUE);
			
			/* son FX */
			fxSound = new Sound();
			fxSound.load(new URLRequest("sound/fx.mp3"));
			
		}
		
		/* lance un boulet */
		private function mouseClick(evt:MouseEvent):void{
			/* on recuperere l'angle en radian */
			var angle:Number = getRadianAngle(canon, this.mouseX,this.mouseY);
			/* on instancie le boulet avec ses vecteurs de translation */
			var boulet:GameSprite = new GameSprite(GameSprite.BOULET,Math.cos(angle)*XFORCE,-Math.sin(angle)*YFORCE);
			/*on place le boulet juste au bout du canon */
			boulet.x = canon.x+Math.cos(angle)*10-cont.x;
			boulet.y = canon.y-Math.sin(angle)*10-cont.y;
			cont.addChild(boulet);
			boulet.addEventListener(Event.ENTER_FRAME, bouletEnterFrame);
		}
		
		/* pivote le cannon */
		private function mouseMove(evt:MouseEvent):void{
			var angle:Number = getRadianAngle(canon, this.mouseX,this.mouseY);
			canon.rotation = -angle*180/Math.PI+90;
		}
		
		/* Deplace les boulets */
		private function bouletEnterFrame(e:Event):void{
			/* on verifie que la cible est bien un GameSprite */
			if( e.target is GameSprite){
				var boulet:GameSprite = e.target as GameSprite;
				/* mouvement */
				boulet.x += boulet.getAccelX();
				boulet.y += boulet.getAccelY();
				/* on met a jour la vitesse sur l'axe Y */
				boulet.setAccelY(boulet.getAccelY() + GRAVITE);
				/* si le boulet sort du stage on l'enleve */
				if(boulet.y > stage.stageHeight) {
					boulet.removeEventListener(Event.ENTER_FRAME,bouletEnterFrame);
					cont.removeChild(boulet);
				}
				else {
					/* sinon on verifie si il touche un ennemi */
					for(var i:int = 0; i < contEnnemis.numChildren; i++){
						var bird:DisplayObject = contEnnemis.getChildAt(i);
						/* si le boulet touche un ennemi, on detruit les deux */
						if((bird is GameSprite) && boulet.hitTestObject((bird as GameSprite).getHitBound())) {
							boulet.removeEventListener(Event.ENTER_FRAME,bouletEnterFrame);
							bird.removeEventListener(Event.ENTER_FRAME,birdEnterFrame);
							cont.removeChild(boulet);
							contEnnemis.removeChild(bird);
							scoreText.text = "score : "+(++score);
							fxSound.play();
						}
					}
				}
			}
		}
		
		/* Deplace les oiseaux */
		private function birdEnterFrame(e:Event):void{
				if(e.target is GameSprite){
					var bird:GameSprite = e.target as GameSprite;
					bird.x += bird.getAccelX();
					bird.y += bird.getAccelY();
					if(bird.y > stage.stageHeight -cont.y|| bird.y < -cont.y || bird.x > stage.stageWidth-cont.x || bird.x < -cont.x ) {
						bird.removeEventListener(Event.ENTER_FRAME,birdEnterFrame);
						contEnnemis.removeChild(bird);
					}
				}
		}
		
		/* Crée les oiseaux */
		private function timerBird(e:Event):void{
			var accelx:int = Math.random()*DIFFICULTE-DIFFICULTE/2;
			var accely:int = Math.random()*DIFFICULTE-DIFFICULTE/2;
			accelx = accelx == 0 ? 1 : accelx; 
			accely = accely == 0 ? 1 : accely; 
			var bird:GameSprite = new GameSprite(GameSprite.BIRD,accelx,accely);
			bird.x = (accelx < 0 ? (Math.random()+1)*stage.stageWidth/2 : (Math.random())*stage.stageWidth/2) - cont.x;
			bird.y = (accely < 0 ? stage.stageHeight-1 : 0) - cont.y;
			contEnnemis.addChild(bird);
			bird.addEventListener(Event.ENTER_FRAME,birdEnterFrame);
		}
		
		/* replace les elements lors du redimmensionnement du stage */
		private function resizeStage(evt:Event):void{
			var ratioX:Number = stage.stageWidth / lastStageWidth; 
			var ratioY:Number = stage.stageHeight / lastStageHeight; 
			for(var i:int  = 0; i< this.numChildren; i++){
				getChildAt(i).x *= ratioX;
				getChildAt(i).y *= ratioY;
			}
			lastStageWidth = stage.stageWidth;
			lastStageHeight = stage.stageHeight;
		}
		
		/* crée le canon */
		private function createCanon():Sprite{
			var spr:Sprite = new Sprite();
			spr.graphics.beginFill(0x000000,1);
			spr.graphics.drawRect(-10,-20,20,40);
			spr.graphics.endFill();
			return spr;
		}
		
		/* Retourne l'angle en radian entre le DisplayObject d1 et le point (x,y) 
			On ne considere que la partie superieur du cercle trigonometrique donc 
			l'angle retourné sera entre 0° et 180°

  • /
public static function getRadianAngle(d1:DisplayObject, x:int,y:int):Number{ if(d1 != null){ var ac:int = x - d1.x; var bc:int = d1.y - y; return Math.acos((ac)/Math.sqrt(Math.pow(ac,2)+Math.pow(bc,2))); } else return NaN; } } } Classe GameSprite : package { import flash.display.DisplayObject; import flash.display.Shape; import flash.display.Sprite; public class GameSprite extends Sprite { /* Ici par simplicité on utilise une enumeration plutot qu'une classe pour les ennemis et une autre pour les boulets */ public static const BIRD:int = 1; public static const BOULET:int = 2; /* le vecteur d'acceleration sur l'axe X */ private var accelx:Number; /* le vecteur d'acceleration sur l'axe Y */ private var accely:Number; /* Le clip qui va etre utilisé pour le hitTest */ private var hitBound:Shape; public function GameSprite(type:int,accelx:Number, accely:Number) { this.accelx = accelx; this.accely = accely; hitBound = new Shape(); if(type == BOULET){ /* on dessine un simple rond avec une couleur au hasard */ hitBound.graphics.beginFill(Math.random()*0xFFFFFF,1); hitBound.graphics.drawEllipse(-5,-5,10,10); hitBound.graphics.endFill(); } if(type == BIRD){ /* aile gauche */ graphics.beginFill(Math.random()*0xFFFFFF,1); graphics.moveTo(0,0); graphics.curveTo(15,-10,30,0); graphics.curveTo(15,-5,0,0); /* corps, qui sert aussi de clip pour le hitTest */ hitBound.graphics.beginFill(Math.random()*0xFFFFFF,1); hitBound.graphics.drawEllipse(25,-5,10,10); hitBound.graphics.endFill(); /* aile droite */ graphics.moveTo(30,0); graphics.curveTo(45,-10,60,0); graphics.curveTo(45,-5,30,0); graphics.endFill(); } addChild(hitBound); } public function getAccelX():Number{ return this.accelx; } public function getAccelY():Number{ return this.accely; } public function setAccelX(ax:Number):void{ this.accelx = ax; } public function setAccelY(ay:Number):void{ this.accely = ay; } public function getHitBound():DisplayObject{ return hitBound; } } }

Conclusion :


Pour compiler les sources avec FlexSDK3 :
mxmcl Canon.as

Pour ceux sous flash cs3, créez un nouveau FLA, mettez les fichiers décompressé de l'archive dans le même dossier. Ensuite cliquez sur un espace vide sur la scène, ouvrez le panneau propriété du document (CTRL+F3), et renseignez Canon dans la case "Classe du document".
Vous pouvez lancer le jeu.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Improve
Messages postés
176
Date d'inscription
mardi 27 novembre 2007
Statut
Membre
Dernière intervention
28 novembre 2009
-
Intéressant ton script, j'ai télécharger.
Moi j'adore les scripts de jeux. mxmlc en plus.
Avec des classes c'est sensas. Bravo.

Je suis prêt pour l'étude de ton script.
cs_mouahaha
Messages postés
210
Date d'inscription
mercredi 4 août 2004
Statut
Membre
Dernière intervention
6 avril 2009
1 -
Ok merci !
Ça fonctionne en effet, je vais pouvoir regarder ça de plus près...
Merci encore !
DigitalLumberjack
Messages postés
16
Date d'inscription
mardi 17 juin 2008
Statut
Membre
Dernière intervention
23 juin 2008
-
Alors pour faire rapide, je n'utilise pas flash pour créer mes swf mais un framework qui s'appelle Flex qui est gratuit et disponible pour linux.
Pour créer un swf sous ce framework il suffit de créer des fichiers actionscript et de les compiler avec le compilateur qui s'appelle mxmcl.

Pour ceux sous flash cs3, il faut cliquer sur un espace vide sur la scène, ensuite ouvrez le panneau propriété du document (CTRL+F3), et dans renseignez Canon dans la case "Classe du document".

Les fichiers ActionScript doivent être dans le même répertoire que votre fla.
cs_mouahaha
Messages postés
210
Date d'inscription
mercredi 4 août 2004
Statut
Membre
Dernière intervention
6 avril 2009
1 -
Ok bon je me décide enfin à passer pour un boulet (c'était inévitable de toute façon ^^), il se trouve que je ne comprend pas comment faire fonctionner ces sources en AS3, avec les classes séparées etc...
Est-ce qu'il faut les copier dans un des dossiers du logiciel, ou recompiler le fichier, ou je ne sais quoi ? Tu parles de recompiler, mais il n'y a pas de fichier .fla...
Peut-être que je suis complètement à côté de la plaque, mais ça ne coûte rien de demander...

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.