Code FireWorks

Retour à l'application SkyFire

Licence

Ce code est fourni sous une licence CC-By (cf. fin de page).

À propos du code

Le code est réparti en classes claires et nettes.
L'ensemble du fichier représente moins de 10ko !

Structure de l'application

Diagramme de SkyFire

Classe principale SkyFire

Dessine les feux, gère l'affichage global et l'artificier.

Code source : SkyFire.as
//Code original par Neamar. Réutilisation libre.
//neamar@neamar.fr
//Date : 2008

//Ligne de commande pour compiler :
//(après s'être placé dans le bon dossier, cf. http://neamar.fr/Res/Compiler_AS3/)
//
//bash mxmlc Sources/SkyFire/SkyFire.as -default-size 640 480 -compiler.strict

//Life begins when you can spend your spare time programming instead of watching television.

package
{

import flash.display.Stage;//...
import flash.display.StageDisplayState;//Pour le plein écran
import flash.display.StageScaleMode;//Pour le plein écran
import flash.display.Sprite;//La classe de base, fort utile !
import flash.events.Event;//Les évenements "de bases", classe dont dérive MouseEvent
import flash.events.MouseEvent;//Interaction utilisateur//souris
import flash.geom.Rectangle;//Un rectangle : x,y, width, height
import flash.geom.Point;//Un point tout ce qu'il y a de plus normal : défini par (x,y).
import flash.text.TextField;//Champ de texte. Classe assez vaste, utilisée uniquement pour l'affichage de texte ici. Peut être du texte au format HTML.

import flash.filters.BitmapFilter;//Classe globale pour les filtres
import flash.filters.GlowFilter;//Filtre d'irridescence (éclairage, le plus utilisé)
import flash.filters.BlurFilter//Flouter
import flash.filters.BevelFilter;//Effet de biseau, appliqué sur le "Plus de jeux".
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.GradientType;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.display.Shape;
import flash.geom.ColorTransform;

import flash.geom.Matrix;

import flash.system.System;

import Particules.*;


[SWF(frameRate = 25)];//Quelques paramètres pour la compilation. Ils sont cependant redéfinis dans la ligne de commande, mais laissés ici pour des raisons sentimentales (sic)

public class SkyFire extends Sprite
{
private static const MaxDistance:int=8;
public static const Origine:Point=new Point();
public static const Size:Point=new Point(800,600);
public static const Ecran:Rectangle = new Rectangle(0,0,Size.x,Size.y);
public static const TransformationMatrix:Matrix=new Matrix(1,0,0,1);//La matrice par défaut d'affichage : scaleX=scaleY = 1, pas de transformée

public var d_Fond:BitmapData=new BitmapData(Size.x,Size.y,false,0x000000);
public var Fond:Bitmap;
public var Operateur:Artificier;

public var Items:Array=new Array();

private var k:int=0;
private var Ligne:Shape=new Shape();
private var Fumee:BlurFilter=new BlurFilter(8,8);

function SkyFire():void
{
include "../Trace.as";
Fond=new Bitmap(d_Fond);

addChild(Fond);

function toggleFullScreen(e:MouseEvent):void
{
stage.displayState = StageDisplayState.FULL_SCREEN;
stage.scaleMode= StageScaleMode.SHOW_ALL;
// Fond.pixelSmoothing=true;//Lisser le bitmap.
}

stage.addEventListener(MouseEvent.CLICK,toggleFullScreen);

Operateur = new Artificier();
addEventListener(Event.ENTER_FRAME,Move);


function Move(e:Event):void
{
d_Fond.lock();//Economiser les ressources

//Flouter les anciens évenements
//function applyFilter(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, filter:BitmapFilter):void
d_Fond.applyFilter(d_Fond,Ecran,Origine,Fumee);

for each(var Item:Particule in Operateur.Feux)//ON "tronque" à Particule, même si c'est une classe qui dérive de Particule.
{
if(Item.y<=Size.y)
{
Ligne.graphics.clear();
Ligne.graphics.lineStyle(Item.Diametre,Item.Couleur,.4)
Ligne.graphics.moveTo(Item.x,Item.y);

Item.Iterate();


Ligne.graphics.lineTo(Item.x,Item.y);
Ligne.filters=Item.filters;

//function draw(source:IBitmapDrawable, matrix:Matrix = null, colorTransform:ColorTransform = null, blendMode:String = null, clipRect:Rectangle = null, smoothing:Boolean = false):void
d_Fond.draw(Ligne,TransformationMatrix,Item.colorTransform);
}
}

// Trace(System.totalMemory / 1000000 + "Mb");
d_Fond.unlock();

}
}
}
}

Classes secondaires :

Artificier

L'artificier est la classe qui gère la cadence des tirs, et les feux qui sont tirés.

Code source : Artificier.as
//Un artificer virtuel qui gère tous les feux
package
{
import flash.display.Shape;
import flash.geom.Point;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event;

import Particules.*;

public class Artificier extends Shape
{
public var Feux:Array=new Array();
public var GarbageCollectorTimer:Timer= new Timer(15000);


public function Artificier()
{
addEventListener(Event.ENTER_FRAME,AjoutFeux);

GarbageCollectorTimer.start();
GarbageCollectorTimer.addEventListener(TimerEvent.TIMER, GarbageCollector);
}

public function AjoutFeux(e:Event):void
{
AjoutFontaine();
AjoutRampant();
AjoutBoomer();
AjoutBiBoomer();
AjoutPchitter();
AjoutBoomerPchitter();
}

public function GarbageCollector(e:TimerEvent=null):void
{
function Cleaner(Element:*, Index:int, Arr:Array):*
{//Nettoie les artifices inutilisés
return (Element.y<SkyFire.Size.y)
}
Feux = Feux.filter(Cleaner);
}



private function Prob(P:Number):Boolean
{
return (Math.random()<P)
}

private function AjoutFontaine():void
{//Les feux de type fontaine qui ne s'atténuent pas dans le temps, et retombent forcément. Couleur blanche
if(Prob(.15))
{
var Ma_Particule:Particule=new Particule();
var Angle:Number=Math.random()*Math.PI;

Ma_Particule.Pos=new Point(SkyFire.Size.x*Math.random(),SkyFire.Size.y);
Ma_Particule.applyForce
(
new Vecteur
(
(100*Math.random())*Math.cos(Angle),
-(50 + 60*Math.random())*Math.sin(Angle)
)
);

Ma_Particule.glow=10*Math.random()+4;

Feux.push(Ma_Particule);
}
}

private function AjoutRampant():void
{//Les feux "normaux" qui montent et s'éteignent à leur apogée. Couleur aléatoire.
if(Prob(.04))
{
var Ma_Particule:SpeedFader=new SpeedFader(Math.random()*0xFFFFFF);
var Angle:Number=Math.random()*Math.PI;

Ma_Particule.Pos=new Point(SkyFire.Size.x*Math.random(),SkyFire.Size.y);
Ma_Particule.applyForce
(
new Vecteur
(
(100*Math.random()+2)*Math.cos(Angle),
-(100*Math.random() + 50 )*Math.sin(Angle)
)
);

Ma_Particule.glow=20*Math.random()+4;

Feux.push(Ma_Particule);
}
}

private function AjoutBoomer():void
{//Les feux qui explosent en une gerbe de fontaines. Rouge à l'origine, couleur aléatoire après
if(Prob(.015))
{
var Ma_Particule:Boomer=new Boomer(this,0xFF0000);
var Angle:Number=Math.PI/4 + Math.random()*Math.PI/2;

Ma_Particule.Pos=new Point(SkyFire.Size.x*Math.random(),SkyFire.Size.y);
Ma_Particule.applyForce
(
new Vecteur
(
(100*Math.random())*Math.cos(Angle),
-(50 + 100*Math.random())*Math.sin(Angle)
)
);

Ma_Particule.glow=6*Math.random()+20;

Feux.push(Ma_Particule);
}
}

private function AjoutBiBoomer():void
{//Des feux qui explosent en feux qui explosent : des bi-boomers en quelque sorte !
if(Prob(.0025))
{
var Ma_Particule:BiBoomer=new BiBoomer(this,0xFF0000);
var Angle:Number=Math.PI/4 + Math.random()*Math.PI/2;

Ma_Particule.Pos=new Point(SkyFire.Size.x*Math.random(),SkyFire.Size.y);
Ma_Particule.applyForce
(
new Vecteur
(
(100*Math.random())*Math.cos(Angle),
-(50 + 100*Math.random())*Math.sin(Angle)
)
);

Ma_Particule.glow=6*Math.random()+20;

Feux.push(Ma_Particule);
}
}

private function AjoutPchitter():void
{//Les feux "normaux" un peu améliorés : ils ont des étincelles à leurs bouts. Couleur aléatoire.
if(Prob(.1))
{
var Ma_Particule:Pchitter=new Pchitter(this,Math.random()*0xFFFFFF);
var Angle:Number=Math.random()*Math.PI;

Ma_Particule.Pos=new Point(SkyFire.Size.x*Math.random(),SkyFire.Size.y);
Ma_Particule.applyForce
(
new Vecteur
(
(100*Math.random())*Math.cos(Angle),
-(100*Math.random() + 50 )*Math.sin(Angle)
)
);

Ma_Particule.glow=20*Math.random()+4;

Feux.push(Ma_Particule);
}
}

private function AjoutBoomerPchitter():void
{//Les feux qui explosent, relachant plein de petites étincelles.
if(Prob(.03))
{
var Ma_Particule:BoomerPchitter=new BoomerPchitter(this,Math.random()*0xFFFFFF);
var Angle:Number=Math.random()*Math.PI;

Ma_Particule.Pos=new Point(SkyFire.Size.x*Math.random(),SkyFire.Size.y);
Ma_Particule.applyForce
(
new Vecteur
(
(100*Math.random())*Math.cos(Angle),
-(100*Math.random() + 50 )*Math.sin(Angle)
)
);

Ma_Particule.glow=20*Math.random()+4;

Feux.push(Ma_Particule);
}
}
}
}

Vecteur

Un vecteur mathématique. De façon interne, il s'agit juste d'un type Point renommé en Vecteur pour une meilleure lisibilité du code général.

Code source : Vecteur.as
//Un vecteur, qui est en fait un déguisement de Point, mais cela clarifie le code.
package
{
import flash.geom.Point;

public class Vecteur extends Point
{
public function Vecteur(x:Number=0,y:Number=0)
{
super(x,y);
}

public function Plus(P:Vecteur):void
{
this.x += P.x;
this.y += P.y;
}
public function ScalarMul(k:Number):void
{
this.x=k*this.x;
this.y=k*this.y;
}
}
}

Particules

L'ensemble des feux existants sont des classes qui héritent de Particule.

Code source : Particule.as
//Une particule de base
package Particules
{
import flash.display.Shape;
import flash.geom.Point;
import flash.filters.BitmapFilter;
import flash.filters.GlowFilter;

import flash.geom.ColorTransform;


public class Particule
{
public var Gravite:Vecteur=new Vecteur(0,4);

public var Couleur:int;
public var Rayon:Number;
public var Diametre:int;

protected var Masse:Number;

protected var Vitesse:Vecteur=new Vecteur();
protected var Forces:Array=new Array();

protected var Rayonnement_Strength:int;

public var filters:Array=new Array();
public var x:int=0;
public var y:int=0;
public var colorTransform:ColorTransform=new ColorTransform();


public function Particule(Couleur:int=0xFFFFFF,Rayon:int=1,Densite:int=1)
{//Instancie un nouveau lien : prend en paramètre le conteneur et les extremités.

this.Rayon = Rayon;
this.Diametre = 2*Rayon;//On le calcule une fois pour toutes, et on le stocke dans un entier pour optimiser les calculs.
this.Masse=Math.PI*Rayon*Rayon*Densite;
this.Couleur=Couleur;

// this.graphics.beginFill(Couleur);
// this.graphics.drawCircle(0,0,Rayon);
}

public function Iterate():void
{//Met à jour la position de la particule.

//Ajouter un peu de gravité :
this.applyForce(Gravite);

//Calcul de la somme des forces
var Resultante:Vecteur=new Vecteur();
for each(var Force:Vecteur in Forces)
{
Resultante.Plus(Force);
}

//application du PFD : Somme des forces = masse * Acceleration
Resultante.ScalarMul(1/this.Masse);
var Acceleration:Vecteur = Resultante;

//Puis mise à jour de la vitesse
Vitesse.Plus(Acceleration);

//Et enfin, de la position.
this.x +=Vitesse.x;
this.y +=Vitesse.y;

//Vidage de la liste des forces
Forces=new Array();
}

public function applyForce(F:Vecteur):void
{//Ajoute une force en liste
Forces.push(F);
}

public function set glow(v:Number):void
{
this.Rayonnement_Strength=v;
updateFilters();
}
public function get glow():Number
{
return this.Rayonnement_Strength;
}

public function set Pos(P:Point):void
{
this.x=P.x;
this.y=P.y;
}
public function get Pos():Point
{
return new Point(this.x,this.y);
}

// public override function set filters(F:Array):void
// {
// this.inner_filters=F;
// }
// public override function get filters():Array
// {
// return this.inner_filters;
// }
//
// public override function set x(v:int):void
// {
// this.inner_x=v;
// }
// public override function get x():int
// {
// return this.inner_x;
// }
//
// public override function set y(v:int):void
// {
// this.inner_y=v;
// }
// public override function get y():int
// {
// return this.inner_y;
// }

private function updateFilters():void
{
//GlowFilter(color:uint = 0xFF0000, alpha:Number = 1.0, blurX:Number = 6.0, blurY:Number = 6.0, strength:Number = 2, quality:int = 1, inner:Boolean = false, knockout:Boolean = false)
var Rayon_Filtre:GlowFilter = new GlowFilter(this.Couleur,.8,8,8,this.Rayonnement_Strength);

var Filtres:Array=new Array(Rayon_Filtre);
this.filters=Filtres;
}
}
}

Toutes les particules

Chaque feu d'artifice dans sa diversité.

Code source : DistanceFader.as
//Une particule qui se dissout quand elle atteint une durée de vie maxi.
//Ne pas confondre avec SpeedFader, qui se dissout en dessous d'une certaine vitesse selon Y.
package Particules
{
import flash.display.Shape;
import flash.geom.Point;

import flash.geom.ColorTransform;


public class DistanceFader extends Particule
{
public var MaxDistance:int=7;

private var NbIteration:int=0;

public function DistanceFader(Couleur:int=0xFFFFFF,Rayon:int=1,Densite:int=1)
{//les feux qui disparaissent progressivement
super(Couleur,Rayon,Densite);
}

public override function Iterate():void
{//Atténuer la couleur
NbIteration++;
var CoeffAttenuation:Number=1-(NbIteration/MaxDistance);
if(NbIteration<MaxDistance)
{
this.colorTransform=new ColorTransform(CoeffAttenuation,CoeffAttenuation,CoeffAttenuation);
this.glow = this.glow * .9
}
else if(NbIteration==MaxDistance)
{
this.colorTransform=new ColorTransform(0,0,0,0,0,0,0,0);
this.Gravite=new Vecteur(0,60);
}

super.Iterate();
}
}
}
Code source : SpeedFader.as
//Une particule qui se dissout en dessous d'une certaine vitesse selon Y.
//Ne pas confondre avec DistanceFader, qui se dissout quand elle atteint une durée de vie maxi.
package Particules
{
import flash.display.Shape;
import flash.geom.Point;

import flash.geom.ColorTransform;


public class SpeedFader extends Particule
{
public var MaxYSpeed:int=30;

public function SpeedFader(Couleur:int=0xFFFFFF,Rayon:int=1,Densite:int=1)
{//les feux qui disparaissent progressivement
super(Couleur,Rayon,Densite);
}

public override function Iterate():void
{//Atténuer la couleur
var CoeffAttenuation:Number=(MaxYSpeed - this.Vitesse.y)/MaxYSpeed;
if(this.Vitesse.y>0)
this.colorTransform=new ColorTransform(CoeffAttenuation,CoeffAttenuation,CoeffAttenuation);
else
this.colorTransform=new ColorTransform();

super.Iterate();
}
}
}
Code source : Pchitter.as
//Une particule qui explose en plusieurs particules
package Particules
{
import flash.display.Shape;
import flash.geom.Point;
import flash.geom.ColorTransform;


public class Pchitter extends SpeedFader
{

private static const MeanNbChildren:int=2;

private var Operateur:Artificier;

public function Pchitter(Operateur:Artificier,Couleur:int=0xFFFFFF,Rayon:int=1,Densite:int=1)
{//Les feux qui pétillent, extension de Fader, lui même extension de Particule
this.Operateur=Operateur;
super(Couleur,Rayon,Densite);
}

public override function Iterate():void
{

super.Iterate();

if(this.y<400 && this.Vitesse.y<0)
{//Pchitt

var NbChildren:int=2*Math.random();
var Couleur:int=this.Couleur;
for(var i:int=0;i<NbChildren;i++)
{
var Enfant:DistanceFader = new DistanceFader(Couleur);
var Angle:Number=Math.random()*2*Math.PI;
var Amplitude:int=30*Math.random();

Enfant.Pos=new Point(this.x + 20*Math.random() - 10,this.y + 20*Math.random() - 10);
Enfant.applyForce
(
new Vecteur
(
this.Vitesse.x + Amplitude*Math.cos(Angle),
this.Vitesse.y + Amplitude*Math.sin(Angle)
)
);
Enfant.Gravite=new Vecteur();
Enfant.glow=1;

Operateur.Feux.push(Enfant);
}
// this.Pos=new Point(0,2000);
// this.transform.colorTransform=new ColorTransform(0,0,0,0,0,0,0,0);
}

}
}
}
Code source : Boomer.as
//Une particule qui explose en plusieurs particules
package Particules
{
import flash.display.Shape;
import flash.geom.Point;
import flash.geom.ColorTransform;


public class Boomer extends Particule
{
private static const MeanNbChildren:int=30;
private var Explosion:int=30;


private var NbIteration:int=0;
private var Operateur:Artificier;

public function Boomer(Operateur:Artificier,Couleur:int=0xFFFFFF,Rayon:int=1,Densite:int=1)
{//Les feux qui explosent
this.Operateur=Operateur;
this.Explosion += -2 + 4*Math.random();
super(Couleur,Rayon,Densite);
}

public override function Iterate():void
{//Y a-t-il explosion ?
NbIteration++;

super.Iterate();

if(NbIteration==Explosion && this.y<500)
{//Boooom !

var NbChildren:int=MeanNbChildren - 5 + 10*Math.random();
var Couleur:int=0xFFFFFF*Math.random();
for(var i:int=0;i<NbChildren;i++)
{
var Enfant:Particule = new Particule(Couleur);
var Angle:Number=i* 2*Math.PI / NbChildren;
var Amplitude:int=20*Math.random()+70;

Enfant.Pos=new Point(this.x,this.y);
Enfant.applyForce
(
new Vecteur
(
Amplitude*Math.cos(Angle),
Amplitude*Math.sin(Angle)
)
);

Enfant.glow=8;

Operateur.Feux.push(Enfant);
}
this.Pos=new Point(0,2000);
this.colorTransform=new ColorTransform(0,0,0,0,0,0,0,0);
}

}
}
}
Code source : BiBoomer.as
//Une particule qui explose en plusieurs particules
package Particules
{
import flash.display.Shape;
import flash.geom.Point;
import flash.geom.ColorTransform;


public class BiBoomer extends Particule
{
private static const Explosion:int=20;
private static const MeanNbChildren:int=30;

private var NbIteration:int=0;
private var Operateur:Artificier;

public function BiBoomer(Operateur:Artificier,Couleur:int=0xFFFFFF,Rayon:int=1,Densite:int=1)
{//Les feux qui explosent
this.Operateur=Operateur;
super(Couleur,Rayon,Densite);
}

public override function Iterate():void
{//Y a-t-il explosion ?
NbIteration++;

super.Iterate();

if(NbIteration>=Explosion && this.y<500 && Math.random()<.2)
{//Boooom !

var NbChildren:int=MeanNbChildren - 5 + 10*Math.random();
var Couleur:int=0xFF0000;//0xFFFFFF*Math.random();
for(var i:int=0;i<NbChildren;i++)
{
var Enfant:Boomer = new Boomer(this.Operateur,Couleur);
var Angle:Number=i*2*Math.PI / NbChildren;
var Amplitude:int=20*Math.random()+70;

Enfant.Pos=new Point(this.x,this.y);
Enfant.applyForce
(
new Vecteur
(
Amplitude*Math.cos(Angle),
Amplitude*Math.sin(Angle)
)
);

Enfant.glow=8;

Operateur.Feux.push(Enfant);
}
this.Pos=new Point(0,2000);
this.colorTransform=new ColorTransform(0,0,0,0,0,0,0,0);
}

}
}
}
Code source : BoomerPchitter.as
//Une particule qui explose en plusieurs particules
package Particules
{
import flash.display.Shape;
import flash.geom.Point;
import flash.geom.ColorTransform;


public class BoomerPchitter extends Particule
{
private static const MeanNbChildren:int=120;

private var Explosion:int=30;

private var NbIteration:int=0;
private var Operateur:Artificier;

public function BoomerPchitter(Operateur:Artificier,Couleur:int=0xFFFFFF,Rayon:int=1,Densite:int=1)
{//Les feux qui explosent
this.Operateur=Operateur;
this.Explosion=this.Explosion - 7 + 14*Math.random();
super(Couleur,Rayon,Densite);
}

public override function Iterate():void
{//Y a-t-il explosion ?
NbIteration++;

super.Iterate();

if(NbIteration==Explosion && this.y<500)
{//Boooom !
Operateur.GarbageCollector();//On va rajouter beaucoup de particules, alors on nettoie d'abord.
var NbChildren:int=MeanNbChildren;
var Couleur:int=this.Couleur;
for(var i:int=0;i<NbChildren;i++)
{
var Enfant:DistanceFader = new DistanceFader(Couleur);
var Angle:Number=Math.random()*2*Math.PI;
var Amplitude:int=50*Math.random();

Enfant.Pos=new Point(this.x,this.y);
Enfant.applyForce
(
new Vecteur
(
this.Vitesse.x + Amplitude*Math.cos(Angle),
this.Vitesse.y + Amplitude*Math.sin(Angle)
)
);
Enfant.Gravite=new Vecteur();
Enfant.glow=1;
Enfant.MaxDistance=12 + 14*Math.random();

Operateur.Feux.push(Enfant);
}
this.Pos=new Point(0,2000);
this.colorTransform=new ColorTransform(0,0,0,0,0,0,0,0);
}

}
}
}
Auteur
Neamar
Date
Aout 2008
But
Finir le jeu
Voir aussi
Compiler l'AS3
Retour
Retour à SkyFire
Menu
Index des ressources

Chargement du sommaire...