Un troisième jeu de graphe

Code de CGraphe en développement

Licence

Ce code est fourni sous une licence CC-By (cf. fin de page).
De plus, il est interdit de recompiler le jeu directement en supprimant simplement le lien «Plus de jeux», la mention «directement» restant à l'appréciation de l'auteur original du code source.

À propos du code

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

Classe principale C-Graphe

Fichiers de bases :

Ces fichiers définissent l'architecture de base : la boite qui affiche un apercu des niveaux, la boite de dialogue, les données des niveaux...

Code source : Cgraphe.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/C-graphe/Cgraphe.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.Sprite;//La classe de base, fort utile !
import flash.display.Shape;//Un sprite plus light, qui ne gère pas les evenements, mais consomme moins de mémoire.
import flash.events.Event;//Les évenements "de bases", classe dont dérive MouseEvent
import flash.events.MouseEvent;//Interaction utilisateur//souris
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.net.URLRequest;//Prépare une requete pour une page web.
import flash.net.sendToURL;//Execute une requete sans récuperer la réponse du serveur. Assez pratique, l'air de rien.

import flash.net.SharedObject;//Sauvegarde locale sur le PC de l'utilisateur : enregistrement du dernier niveau joué, et des niveaux débloqués.

[SWF(width = "640", height = "480", 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 Cgraphe extends Sprite
{

public var Partie:Game;//La partie en cours

public var SAVE_LOCAL:SharedObject;//L'enregistrement du niveau en cours, et des niveaux unlockés.
public var SESSION:Object;//Un raccourci vers SharedObject.datas

private var Images_Niveaux:Array=new Array();//Une "capture d'écran" des niveaux, qui est affichée dans la boite de preview

public var NumeroNiveauActuel:int=0;
public var NumeroNiveauUnlockes:int;

function Cgraphe():void
{
// Récuperer les données locales, si elles existent.
SAVE_LOCAL = SharedObject.getLocal("CGraphe");
SESSION = SAVE_LOCAL.data;
// SESSION.NumeroNiveauUnlockes=SESSION.NumeroNiveauActuel=11;

if(SESSION.NumeroNiveauActuel==null)
SESSION.NumeroNiveauActuel=SESSION.NumeroNiveauUnlockes=0;//Création de la sauvegarde.

NumeroNiveauUnlockes=SESSION.NumeroNiveauUnlockes;//Recharger les dernières valeurs
NumeroNiveauActuel=NumeroNiveauUnlockes;//Commencer au dernier niveau

Const._stage=this.stage;

stage.frameRate=20;

include "ChangementsNiveaux.as";//Pendant le niveau, teste si il est fini. Prépare le passage à un nouveau niveau, et l'affiche.
include "ChargementNiveaux.as";//La liste des niveaux, et les fonctions pour les charger en mémoire.
include "Message.as";//La boite de message. Montre un message via la méthode ShowMessage(message:String)
include "Persos.as";//Permet la création de levels persos.

//Enregistrer le nouveau joueur :
sendToURL(new URLRequest("http://neamar.fr/Res/CGraphe/Player.php"));//Permet de garder des statistiques sur le nombre de joueurs même quand le jeu est hébergé sur un autre site.

// SwapBackGround();//Afficher l'image de fond
LancerNouveauNiveau();

////////////////////////////////
//Les éléments inclassables
////////////////////////////////
function SourisIN(e:Event):void
{//Fonction Utilisée sur tous les sprites de type bouton : ajoute un filtre au Sprite afin de l'illuminer
AppliquerFiltre(e.currentTarget)
}
function SourisOUT(e:Event):void
{//Fonction Utilisée sur tous les sprites de type bouton : retire les filtres du Sprite
e.currentTarget.filters=new Array();
}

function BevelIN(e:Event):void
{//Fonction utilisée sur tous les sprites de type flèche : ajoute un filtre au Sprite afin de l'enfoncer
e.currentTarget.filters=new Array(Const.BEVEL_IN);
}
function BevelOUT(e:Event):void
{//Fonction Utilisée sur tous les sprites de type bouton : retire les filtres du Sprite
e.currentTarget.filters=new Array(Const.BEVEL_OUT);
}
function AppliquerFiltre(Element:Sprite,Couleur:uint=0x000000):void
{//Ajoute un filtre de rayonnement à l'objet spécifié
var FiltreHover:BitmapFilter = new GlowFilter(Couleur, 0.8,16,16,3,1,false,false);
var ListeFiltres:Array = new Array();
ListeFiltres.push(FiltreHover);
Element.filters=ListeFiltres;
}
function ResetAll(e:Event):void
{//No comment !
NumeroNiveauActuel=NumeroNiveauUnlockes=SESSION.NumeroNiveauActuel=SESSION.NumeroNiveauUnlockes=0;
UpdaterBoite();
}
}
}
}
Code source : ChangementsNiveaux.as
/////////////////////////////////////
//Fonctions utilisées en cours de niveau
/////////////////////////////////////

function FinNiveau():void
{//Fonction de callback appelée quand le niveau est terminé.
if(Partie.Gagnant.IsHuman)
TerminerNiveau(1);
else
TerminerNiveau(0);
}

/////////////////////////////////////
//Fonctions utilisées lors des changements de niveaux
/////////////////////////////////////
function TerminerNiveau(Valeur:int):void
{//Termine un niveau en affichant la boite de changement
//Débloque un nouveau niveau si le dernier est réussi

Boite.visible=true;

NumeroNiveauActuel+=Valeur;
if(NumeroNiveauActuel>NumeroNiveauUnlockes && NumeroNiveauActuel<=11 && Partie.Officiel)
{//Si il vient de réussir le niveau sur lequel il était bloqué
NumeroNiveauUnlockes+=Valeur;//Débloquer un nouveau niveau
SESSION.NumeroNiveauActuel=NumeroNiveauActuel;//Et enregistrer en local la progression
SESSION.NumeroNiveauUnlockes=NumeroNiveauUnlockes;
ChangeLevelInfo.htmlText="Nouveau Niveau débloqué !";
LancerNouveauNiveau();
}
else if(NumeroNiveauUnlockes==11 && NumeroNiveauActuel>=11 && NumeroNiveauActuel>NumeroNiveauUnlockes && Partie.Officiel)
{
ShowMessage("<u>Félicitations !</u> Vous avez fini les 12 niveaux proposés par le jeu.<br>Maintenant, pourquoi ne pas tenter votre chance sur les prédecesseurs de ce jeu, <a href=\"http://www.neamar.fr/Res/Agraphe/\" target=\"_blank\">AGraphe</a> et <a href=\"http://www.neamar.fr/Res/Bgraphe/\" target=\"_blank\">BGraphe</a> ? Sinon, vous pouvez aussi éteindre votre ordinateur et reprendre une activité normale...<br>À la revoyure pour DGraphe, le dernier de la série, Neamar.");
NumeroNiveauActuel=11;
if(contains(Partie.Terrain))
{//C'est la première fois que le jeu est fini :
removeChild(Partie.Terrain);
Boite.visible=false;
}
else
UpdaterBoite();
}
else //Sinon, afficher la boite avec la liste des niveaux.
UpdaterBoite("<b>PERDU !</b> Essaie encore !");
}


function StopLevel(e:Event=null):void
{//Arrête le niveau directement.
TerminerNiveau(0);
Message_Container.visible=false;
ChangeLevelInfo.htmlText="<b>Niveau abandonné !</b>";
}

function LancerNouveauNiveau(NumNiveau:int=-1):void
{//Lancer un niveau "quelconque"
if(NumNiveau==-1)
NumNiveau=NumeroNiveauActuel;

if(Partie!=null && contains(Partie.Terrain))
removeChild(Partie.Terrain);//Si Fond a déjà été utilisé, le nettoyer.
Partie=GetLevelData(NumNiveau);

InitialiserJeu();
}

function InitialiserJeu():void
{//Appelé depuis LancerNouveauNiveau ou depuis LancerNouveauNiveauPerso
Partie.CallBack=FinNiveau;
addChild(Partie.Terrain);
//Repasser la boite de message au premier plan
setChildIndex(Partie.Terrain,0);

Boite.visible=false;
ChangeLevelInfo.htmlText="<u>Liste des niveaux</u>";
}
Code source : ChargementNiveaux.as
/////////////////////////////////////
//Fonctions de création de niveau
/////////////////////////////////////

function GetLevelData(Numero:int,Mute:Boolean=false):Game
{
var Jeu:Game;
//Renvoie les données pour un niveau fixé.
var Message:String="";

//Prototype : new Game(FirstPlayer,Short_Type,Cut_Type,Datas,Passif=false)
if(Numero==0)
{
Jeu=new Game(Const.SHORT,Const.COMPUTER,Const.HUMAN,"50,240|320,100|320,380|590,240:0,1,0,0|0,2,0,480|2,3,640,0|1,3,640,480",Mute);
Message="<u>Règles de C-graphe : <font size=\"-2\"><i>(partie 1/2)</i></font></u><br>Bienvenue ! Votre nom est <b>Couhpeur</b>.<br />Votre mission est d'empêcher l'ordinateur de dessiner un chemin complet entre les deux points rouges. Pour cela, pendant votre tour, cliquer sur un trait afin de le supprimer. On se revoit tout de suite après...(l'ordinateur a déjà joué un coup, en blanc)";
}
if(Numero==1)
{
Jeu=new Game(Const.SHORT,Const.HUMAN,Const.COMPUTER,"50,50|320,240|590,430:0,1,0,240|0,1,320,0|1,2,320,480|1,2,640,240",Mute);
Message="<u>Règles de C-graphe : <font size=\"-2\"><i>(partie 2/2)</i></font></u><br>Pas mal ! Votre nom est dorénavant <b>Paintre</b>.<br />Votre mission est de dessiner un chemin complet entre les deux points rouges. Pour cela, pendant votre tour, cliquez sur un trait afin de le peindre. L'ordinateur essaiera de vous en empêcher...";
}
if(Numero==2)
{
Jeu=new Game(Const.SHORT,Const.HUMAN,Const.COMPUTER,"100,240|280,100|280,380|460,50|460,430|620,240:5,3,350,200|3,1,260,170|5,4,350,280|4,2,260,310|2,0,145,300|0,1,145,180|1,2,185,240|5,2,180,250|5,1,180,250",Mute);

Message="Pour cette partie, vous serez <b>Paintre</b>.<br />N'oubliez pas:<li>Vous pouvez peindre n'importe quel trait tant qu'il n'est pas coupé</li><li><b>Coupheur</b> fera tout pour vous empêcher de rejoindre les points rouges</li><li>Le terrain est traître, pensez à l'examiner !</li>Bonne chance, et peut être à plus tard.";
}
if(Numero==3)
{
Jeu=new Game(Const.SHORT,Const.HUMAN,Const.COMPUTER,"34,249|72,159|80,379|129,336|109,378|130,418|156,126|153,172|204,76|283,76|369,75|522,66|361,128|199,338|312,418|319,340|464,131|433,345|386,387|483,414|563,216:5,2,105,399|2,3,104,358|3,4,124,355|4,2,99,377|2,0,57,314|0,1,53,204|7,1,113,166|1,6,114,142|6,8,180,101|8,9,244,76|9,10,326,75|10,11,446,70|12,6,259,127|13,7,174,215|3,13,162,297|5,13,162,338|5,3,129,377|15,13,257,299|5,14,221,418|14,15,315,379|16,12,413,129|7,15,236,256|15,12,340,234|19,14,397,416|14,18,349,403|18,17,410,366|17,15,376,343|17,16,448,238|17,19,458,379|12,10,365,101|20,11,542,141|16,20,513,174|20,17,498,281|19,20,523,315",Mute,Const.AI_NOT_SMART);
}
if(Numero==4)
{
Jeu=new Game(Const.SHORT,Const.COMPUTER,Const.HUMAN,"11,13|156,11|7,112|6,188|119,121|252,15|127,224|262,103|314,212|209,330|411,150|17,327|386,11|391,296|455,340|554,293|511,367|471,413|600,398:0,2,9,63|0,1,84,12|1,2,82,62|5,1,204,13|2,3,7,150|4,2,63,117|4,1,138,66|7,5,257,59|7,4,191,112|4,6,123,173|6,3,67,206|8,7,288,158|8,6,221,218|10,7,337,127|8,10,363,181|8,9,262,271|9,6,168,277|11,6,72,276|11,9,113,329|12,7,324,57|12,10,399,81|13,10,401,223|13,8,353,254|13,9,300,313|14,13,423,318|17,14,463,377|14,16,483,354|14,15,505,317|18,15,631,309|16,18,556,383|17,18,531,472|18,15,577,346|18,17,536,406",Mute,Const.AI_SMART);
}
if(Numero==5)
{
Jeu=new Game(Const.SHORT,Const.HUMAN,Const.COMPUTER,"27,44|311,48|23,109|159,165|312,171|312,232|161,232|23,182|435,204|242,259|241,224|239,361|238,412|178,361|178,417|113,358|111,421|64,352|63,428|14,337|15,443|542,226:0,1,169,46|0,2,25,76|2,3,75,132|2,4,168,140|4,6,236,202|3,5,235,199|3,6,160,199|4,5,312,202|5,8,385,272|6,7,90,268|7,9,166,198|8,9,296,196|8,9,428,288|7,9,8,285|9,10,241,243|9,11,240,310|11,12,238,386|12,14,208,414|14,13,178,389|13,11,208,361|13,15,145,360|15,17,85,357|17,19,34,350|19,20,7,388|20,18,33,428|18,16,86,423|16,14,144,419|16,15,112,389|18,17,56,391|11,14,208,389|12,13,208,386|13,16,144,391|15,14,145,387|21,1,423,138|21,12,386,319|9,13,210,310|9,15,177,308|9,17,153,305|9,19,128,298|21,14,259,475|10,3,200,194|10,4,276,197",Mute);
}
if(Numero==6)
{
Jeu=new Game(Const.SHORT,Const.HUMAN,Const.COMPUTER,"50,230|141,230|211,230|305,230|420,230|485,180|485,280|90,155|90,305|185,155|185,305|305,155|305,90|305,305|305,370|550,230:0,1,96,230|1,7,116,192|1,8,115,261|8,10,140,293|10,2,201,260|1,2,172,181|1,2,176,227|7,9,136,153|9,11,253,106|10,13,251,294|13,14,310,320|14,4,365,285|11,12,312,116|12,4,366,158|11,4,367,184|13,4,366,261|11,3,315,184|3,4,369,227|4,5,453,208|4,6,453,244|6,15,522,243|5,15,522,207|5,6,486,225|10,7,-100,480|10,9,-75,0|9,3,250,189|0,8,70,262|14,12,850,224|9,11,247,145",Mute,Const.AI_SMART);
}
if(Numero==7)
{
Jeu=new Game(Const.SHORT,Const.COMPUTER,Const.HUMAN,"51,225|343,217|428,218|495,216|295,191|296,250|294,143|293,302|189,139|187,90|190,305|187,349|49,305|48,134|490,151|546,181|590,139|530,98|417,151:0,13,50,180|0,12,50,265|12,10,120,305|12,11,118,327|11,7,240,326|7,10,242,304|13,8,119,137|13,9,118,112|9,6,241,117|6,8,242,141|0,8,120,182|0,6,173,184|0,10,121,265|0,7,172,264|7,5,295,276|6,4,295,167|4,1,319,204|1,5,320,234|4,5,296,221|11,1,353,374|9,1,349,70|1,2,386,218|2,3,462,217|3,14,493,184|14,15,518,166|15,16,568,160|16,17,560,119|17,14,506,128|15,17,538,140|14,16,540,145|18,14,455,120|18,14,445,171|18,17,435,87|2,14,459,185|2,17,316,32|3,16,601,245|0,4,173,208|0,5,174,238",Mute,Const.AI_SMART);
}
if(Numero==8)
{
Jeu=new Game(Const.SHORT,Const.HUMAN,Const.COMPUTER,"5,250|60,200|60,300|110,250|110,150|180,50|180,200|180,300|250,200|300,200|300,250|350,200|400,250|450,200|465,50|500,150|520,250|565,150:0,1,31,217|0,2,31,265|2,3,49,234|3,2,84,264|1,3,83,216|1,4,85,156|4,5,148,85|5,6,184,114|6,7,186,233|7,3,147,263|3,6,148,210|6,4,150,150|4,3,112,181|5,8,208,114|6,8,210,179|7,8,209,233|9,8,264,110|8,9,273,242|11,5,354,84|9,10,308,209|10,11,334,227|11,9,333,194|3,10,180,415|12,10,352,253|12,13,426,236|10,13,401,350|12,14,427,163|13,15,471,178|16,13,489,221|16,15,502,191|14,16,524,128|17,14,513,107|17,16,542,192",Mute,Const.AI_NOT_SMART);
}
if(Numero==9)
{
Jeu=new Game(Const.SHORT,Const.HUMAN,Const.COMPUTER,"290,100|290,161|401,206|193,210|118,78|107,282|189,257|178,323|279,289|273,363|332,317|364,247:0,1,290,131|1,3,242,186|3,0,242,155|0,2,346,153|2,1,346,184|2,4,520,72|5,4,113,180|3,5,150,246|5,6,148,270|5,7,143,303|6,9,231,310|7,8,229,306|8,10,306,303|9,10,303,340|9,8,276,326|8,11,322,268|11,10,348,282|6,7,184,290|5,0,144,141|4,3,156,144|6,3,191,234",Mute,Const.AI_SMART);
}
if(Numero==10)
{
Jeu=new Game(Const.SHORT,Const.COMPUTER,Const.HUMAN,"29,96|164,31|111,147|239,86|262,195|613,353|391,100|514,59|344,205|48,422:0,1,66,70|0,3,134,91|0,2,70,121|2,3,175,116|4,2,186,171|3,4,250,140|5,4,282,321|6,1,389,66|3,6,360,176|8,6,493,163|8,7,477,218|5,8,366,284|7,5,437,291|7,6,386,71|1,7,552,21|9,4,155,308|9,5,331,387",Mute,Const.AI_NOT_SMART);
}
if(Numero==11)
{
Jeu=new Game(Const.SHORT,Const.HUMAN,Const.COMPUTER,"17,237|94,156|97,238|117,303|168,242|166,117|100,86|42,52|106,20|170,44|323,52|243,143|328,133|382,131|445,72|398,90|433,108|470,198|504,120|179,345|230,309|279,370|260,390|314,302|271,330|510,362|325,427|433,132|396,182|380,353|476,447|398,412|554,458:0,1,56,197|1,2,96,197|2,3,95,286|3,0,69,272|4,1,136,196|0,2,57,238|2,4,138,237|4,5,172,176|5,1,130,137|8,6,103,53|6,1,97,121|5,6,133,102|6,7,71,69|7,8,74,36|8,9,138,32|9,5,168,81|12,11,287,130|11,5,206,122|9,10,247,48|10,12,326,93|11,4,211,189|13,10,353,92|12,13,355,132|14,10,384,62|13,15,390,111|15,16,416,99|16,14,439,90|14,15,422,81|13,16,408,120|18,17,487,159|18,14,475,96|14,17,458,135|3,19,153,325|19,22,228,372|4,20,199,276|20,21,255,340|20,23,272,306|23,21,297,336|24,23,293,316|24,21,275,350|21,22,270,380|25,17,490,280|26,22,288,403|21,26,298,393|4,27,252,224|27,25,423,284|28,4,331,214|28,25,396,249|23,28,355,242|26,29,353,390|23,29,347,328|31,29,389,383|26,31,362,420|31,30,437,430|30,25,493,405|32,30,540,403|30,32,515,453",Mute);
}

//

Jeu.NumeroNiveau=Numero;

if(Message!="" && !Mute)
ShowMessage(Message);
return Jeu;
}

function ChargementNiveauDirect(e:Event):void
{//Triggeré quand clic sur une des miniatures dans Boite.
while(Boite.numChildren > 0)
Boite.removeChildAt(0);//libérer de la mémoire (même si on ne peut s'assurer du passage du garbage collector)

Boite.addChild(ChangeLevelInfo);

ChangeLevelInfo.htmlText="<u>Chargement en cours</u> (niv. <b>"+e.currentTarget.Layer.NumeroNiveau+"</b>)";
NumeroNiveauActuel=e.currentTarget.Layer.NumeroNiveau;
LancerNouveauNiveau(e.currentTarget.Layer.NumeroNiveau);
}
Code source : Message.as

//Déclaration des Sprites
var Boite:Sprite = new Sprite();
var BoiteG:Sprite=new Sprite();
var RetryLevelButtonInterne:Sprite;
var Annuler_Choix:Sprite;
var Neamar_Sprite:Sprite;

var Message_Container:Sprite=new Sprite();
var Message_TexteOK:Sprite=new Sprite();
var Mods:Sprite=new Sprite();

//Remplissage des Sprites

//La boite qui affiche les messages
Message_Container.graphics.beginFill(0x444444);
Message_Container.graphics.lineStyle(2,0x000000);
Message_Container.graphics.drawRoundRect(0, 0,440,140,15);
Message_Container.x=100;
Message_Container.y=160;
Message_Container.visible=false;
Message_Container.alpha=.6;

var Message_Texte:TextField = CreerTextField(Message_Container,10,10,420,100);

Message_TexteOK = LevelChangeButton(0);
Message_TexteOK.scaleX=Message_TexteOK.scaleY=.3;
Message_Container.addChild(Message_TexteOK);
Message_TexteOK.x=420;
Message_TexteOK.y=120;
Message_TexteOK.addEventListener(MouseEvent.CLICK,RemoveMessage);


BoiteG.graphics.beginFill(0xEEEEEE);
BoiteG.graphics.lineStyle(1,0x000000);
BoiteG.graphics.drawRoundRect(0, 0,240,180,10);
AppliquerFiltre(BoiteG);
Boite.addChild(BoiteG);

Boite.x=50;
Boite.y=50;
Boite.width=Const.FLASHWIDTH-100;
Boite.height=Const.FLASHHEIGHT-100;
// Boite.visible=false;

addChild(Boite);


Annuler_Choix=LevelChangeButton(180);
Annuler_Choix.scaleX=Annuler_Choix.scaleY=0.15;
Annuler_Choix.addEventListener(MouseEvent.CLICK,Annuler);

addChild(Message_Container);
AppliquerFiltre(Message_Container);


var ChangeLevelInfo:TextField = CreerTextField(Boite,30,0,Const.FLASHWIDTH-100,25,false,false,false);
ChangeLevelInfo.htmlText="<u>Liste des niveaux</u>";


RetryLevelButtonInterne=LevelChangeButton(90);
addChild(RetryLevelButtonInterne);
RetryLevelButtonInterne.x=640;
RetryLevelButtonInterne.y=450;
RetryLevelButtonInterne.scaleX=RetryLevelButtonInterne.scaleY=.2;
RetryLevelButtonInterne.addEventListener(MouseEvent.CLICK,StopLevel);


Neamar_Sprite = new Sprite();
Neamar_Sprite.graphics.lineStyle(2,0x000000);
Neamar_Sprite.graphics.lineTo(640,0);
Neamar_Sprite.graphics.lineTo(340,220);
Neamar_Sprite.graphics.moveTo(0,0);
Neamar_Sprite.graphics.lineTo(320,220);
Neamar_Sprite.graphics.moveTo(320,260);
Neamar_Sprite.graphics.lineTo(0,480);
Neamar_Sprite.graphics.lineTo(640,480);
Neamar_Sprite.graphics.lineTo(360,260);
Neamar_Sprite.graphics.drawCircle(320, 240,120);
Neamar_Sprite.width=640;
Neamar_Sprite.height=480;
Neamar_Sprite.scaleX=Neamar_Sprite.scaleY=0.07;
AppliquerFiltre(Neamar_Sprite);
Neamar_Sprite.addEventListener(MouseEvent.MOUSE_OVER,APropos);
Neamar_Sprite.addEventListener(MouseEvent.CLICK,AProposTexte);

// Mods.graphics.beginFill(0xCCCCCC);
// Mods.graphics.drawRect(0, 0, 100,30);
// Mods.graphics.endFill();
// AppliquerFiltre(Mods);

//Ajout dans Mods
var SpriteReset:Sprite=new Sprite();
var Mods_Reset:TextField = CreerTextField(SpriteReset,0,0,180,20,false,false,false);
Mods_Reset.htmlText="<li>RESET</li>";
SpriteReset.scaleX=SpriteReset.scaleY=0.4;
SpriteReset.y=16;
Mods.addChild(SpriteReset);
SpriteReset.addEventListener(MouseEvent.MOUSE_OVER,SourisIN);
SpriteReset.addEventListener(MouseEvent.MOUSE_OUT,SourisOUT);
SpriteReset.addEventListener(MouseEvent.CLICK,ResetAll);

var SpriteQualiteL:Sprite=new Sprite();
var Mods_QualiteL:TextField = CreerTextField(SpriteQualiteL,0,0,180,20,false,false,false);
Mods_QualiteL.htmlText="<li>Réduire la qualité</li>";
SpriteQualiteL.scaleX=SpriteQualiteL.scaleY=0.4;
SpriteQualiteL.y=0;
Mods.addChild(SpriteQualiteL);
SpriteQualiteL.addEventListener(MouseEvent.MOUSE_OVER,SourisIN);
SpriteQualiteL.addEventListener(MouseEvent.MOUSE_OUT,SourisOUT);
SpriteQualiteL.addEventListener(MouseEvent.CLICK,ToggleQuality);


//Lien vers http://www.mini-jeu-gratuit.fr/
var SpriteSponsor:Sprite=new Sprite();
SpriteSponsor.filters=new Array(new BevelFilter(7,90,0x7F0000,1,0x000000,1,10,4,10));

var Mods_Sponsor:TextField=CreerTextField(SpriteSponsor,0,0,50,35,false,true,false)
Mods_Sponsor.htmlText="<a href=\"http://www.mini-jeu-gratuit.fr/vip/neamar/\" target=\"_blank\">Plus de jeux</a>";
// SpriteSponsor.addEventListener(MouseEvent.MOUSE_MOVE,SourisIN);
// SpriteSponsor.addEventListener(MouseEvent.MOUSE_OUT,SourisOUT);


function CreerTextField(Parent:Sprite,x:int,y:int,width:int,height:int,multiline:Boolean=true, selectable:Boolean=false,border:Boolean=true):TextField
{//Instanciateur de TextField
var TextFieldTemporaire:TextField=new TextField();
Parent.addChild(TextFieldTemporaire);
TextFieldTemporaire.x=x;
TextFieldTemporaire.y=y;
TextFieldTemporaire.width=width;
TextFieldTemporaire.height=height;
TextFieldTemporaire.wordWrap=true;
TextFieldTemporaire.background =TextFieldTemporaire.border=border;
TextFieldTemporaire.multiline=multiline;
TextFieldTemporaire.selectable=selectable;
return TextFieldTemporaire;
}

function LevelChangeButton(Angle:int):Sprite
{//fonction qui génére un bouton de type "Suivant".
var LevelChangeButtonSprite:Sprite=new Sprite();

var LevelChangeButtonSpriteFond:Shape=new Shape();
LevelChangeButtonSpriteFond.graphics.beginFill(0x21435d);//0x7F7FB3
LevelChangeButtonSpriteFond.graphics.lineStyle(1,0x000000);
LevelChangeButtonSpriteFond.graphics.drawCircle(75,75,75)
LevelChangeButtonSpriteFond.graphics.endFill();
LevelChangeButtonSpriteFond.filters=new Array(Const.BEVEL_OUT);
LevelChangeButtonSprite.addChild(LevelChangeButtonSpriteFond);

var LevelChangeButtonSpriteTop:Shape=new Shape();
LevelChangeButtonSpriteTop.graphics.lineStyle(1,0x4c99d5);
LevelChangeButtonSpriteTop.graphics.beginFill(0xFFFFFF);
LevelChangeButtonSpriteTop.graphics.moveTo(50,33);
LevelChangeButtonSpriteTop.graphics.curveTo(75,50,133,75);
LevelChangeButtonSpriteTop.graphics.curveTo(75,100,50,117);
LevelChangeButtonSpriteTop.graphics.curveTo(95,75,50,33);
LevelChangeButtonSpriteTop.graphics.endFill();

LevelChangeButtonSpriteTop.graphics.beginFill(0xFFFFFF);
LevelChangeButtonSpriteTop.graphics.moveTo(20,75);
LevelChangeButtonSpriteTop.graphics.curveTo(30,45,65,75);
LevelChangeButtonSpriteTop.graphics.curveTo(30,105,20,75);
LevelChangeButtonSpriteTop.graphics.endFill();

LevelChangeButtonSprite.addChild(LevelChangeButtonSpriteTop);

LevelChangeButtonSprite.rotation=Angle;
LevelChangeButtonSprite.alpha=1;
// LevelChangeButtonSprite.addEventListener(MouseEvent.MOUSE_MOVE,SourisIN);
LevelChangeButtonSprite.addEventListener(MouseEvent.MOUSE_MOVE,BevelIN);
// LevelChangeButtonSprite.addEventListener(MouseEvent.MOUSE_OUT,SourisOUT);
LevelChangeButtonSprite.addEventListener(MouseEvent.MOUSE_OUT,BevelOUT);
return LevelChangeButtonSprite;
}

function ShowMessage(Texte:String):void
{//Affiche un message.
Message_Container.visible=true;
Message_Texte.htmlText=Texte;
}
function RemoveMessage(e:Event=null):void
{//Cache la boite de messages
Message_Container.visible=false;
}

function UpdaterBoite(Msg:String=""):void
{
setChildIndex(Boite,numChildren-1);
Boite.visible=true;
var i:int=0;
var ThumbShot:Game;

function Afficher(Image:Land,Empl:int):void
{
Boite.addChild(Image);
Image.scaleX=Image.scaleY=0.07;
Image.x=15 + Empl%4*Ecart;
Image.filters=new Array(Const.BEVEL_OUT);
Image.addEventListener(MouseEvent.MOUSE_OVER,BevelIN);
Image.addEventListener(MouseEvent.MOUSE_OVER,AfficherInfos);
Image.addEventListener(MouseEvent.MOUSE_OUT,BevelOUT);
Image.addEventListener(MouseEvent.CLICK,ChargementNiveauDirect);
Image.y=20 + Math.floor(Empl/4)*Ecart/1.3;
}

RemoveMessage();
//Générer un préview des niveaux
while(Boite.numChildren > 0)
Boite.removeChildAt(0);


var Ecart:Number=540/10;
if(Images_Niveaux.length<=NumeroNiveauUnlockes)
{
Images_Niveaux=new Array();
for(i=0;i<=NumeroNiveauUnlockes;i++)
{
ThumbShot=GetLevelData(i,true);//true indique qu'il ne faut pas afficher les messages;
Images_Niveaux.push(ThumbShot);
}
}
for(i=0;i<=NumeroNiveauUnlockes;i++)
{
ThumbShot=Images_Niveaux[i];
Afficher(ThumbShot.Terrain,i);
Boite.addChild(ThumbShot.Terrain);
if(i==NumeroNiveauActuel)
ThumbShot.Terrain.filters=new Array(Const.BEVEL_IN);
}

Boite.addChild(SpriteSponsor);
SpriteSponsor.x=15+2*Ecart;
SpriteSponsor.y=20+3*Ecart/1.3;

//Retour
Boite.addChild(Annuler_Choix);
Annuler_Choix.y=16;
Annuler_Choix.x=16;
Boite.addChild(ChangeLevelInfo);

//Informations
Boite.addChild(Neamar_Sprite);
Neamar_Sprite.x=17 + 3*Ecart;
Neamar_Sprite.y=20 + 3*Ecart/1.3;

Boite.addChild(Mods);
Mods.x=15;
Mods.y=20 + 3*Ecart/1.3;

Boite.addChild(BoiteG);
Boite.setChildIndex(BoiteG,0);
BoiteG.alpha=.55;

if(Msg!="")
ChangeLevelInfo.htmlText=Msg;

}

function AfficherInfos(e:Event):void
{
ChangeLevelInfo.htmlText="Charger le niveau <b>"+e.currentTarget.Layer.NumeroNiveau +"</b>";
if(e.currentTarget.Layer.NumeroNiveau==NumeroNiveauUnlockes)
ChangeLevelInfo.htmlText="Dernier niveau débloqué : <b>"+e.currentTarget.Layer.NumeroNiveau +"</b>";
else if(e.currentTarget.Layer.NumeroNiveau==NumeroNiveauActuel)
{
ChangeLevelInfo.htmlText="Dernier niveau tenté : <b>"+e.currentTarget.Layer.NumeroNiveau +"</b>";
AppliquerFiltre(e.currentTarget,0x7F7FB3)
}
}
function APropos(e:Event):void
{
ChangeLevelInfo.htmlText="Informations, explications, code source...";
}

function AProposTexte(e:Event):void
{
ShowMessage("<u>À propos...</u><br><li>Jeu réalisé par Neamar en AS3 libre.</li><li>Explications du jeu, dernières mises à jour, code source, aide à la compilation : <a href=\"http://neamar.fr/Res/CGraphe/\" target=\"_blank\">http://neamar.fr/Res/CGraphe (click to go)</a></li>");
}

function Annuler(e:Event):void
{
Boite.visible=false;
}

function ToggleQuality(e:Event):void
{
if(stage.quality == "HIGH")
{
stage.quality="LOW";
Mods_QualiteL.htmlText="<li>Augmenter la qualité</li>";
}
else
{
stage.quality="HIGH";
Mods_QualiteL.htmlText="<li>Réduire la qualité</li>";
}
}

Fichiers de mod

Permet de jouer à plusieurs sur un terrain personnalisé.

Code source : Persos.as
//Ajout dans Mods
var SpritePerso:Sprite=new Sprite();
var Mods_Perso:TextField = CreerTextField(SpritePerso,0,0,180,20,false,false,false);
Mods_Perso.htmlText="<li>Éditeur de niveaux persos</li>";
SpritePerso.scaleX=SpritePerso.scaleY=0.4;
SpritePerso.y=8;
Mods.addChild(SpritePerso);

SpritePerso.addEventListener(MouseEvent.MOUSE_OVER,SourisIN);
SpritePerso.addEventListener(MouseEvent.MOUSE_OUT,SourisOUT);
SpritePerso.addEventListener(MouseEvent.CLICK,ShowLoadLevel);



//Graphismes de la boite
var LoadLevel:Sprite=new Sprite();
LoadLevel.graphics.beginFill(0x444444);
LoadLevel.graphics.lineStyle(2,0x000000);
LoadLevel.graphics.drawRect(0, 0,440,140);
LoadLevel.x=100;
LoadLevel.y=160;
LoadLevel.visible=false;
LoadLevel.alpha=.95;

var LoadLevelTexte:TextField = CreerTextField(LoadLevel,20,65,360,20,false,true);
LoadLevelTexte.type="input";
LoadLevelTexte.restrict=":,|0-9";
LoadLevelTexte.text="50,223|167,115|212,175|163,251|197,333|313,220|308,130|435,165:0,1,109,169|1,6,238,123|6,7,372,148|1,2,190,145|2,3,188,213|3,4,180,292|0,3,107,237|0,4,124,278|3,5,238,236|2,7,324,170|5,7,374,193|5,2,263,198";

var LoadLevelCaption:TextField = CreerTextField(LoadLevel,10,10,400,55,true,true,false);

var Lancer_Level:Sprite=LevelChangeButton(0);
Lancer_Level.scaleX=Lancer_Level.scaleY=.3;
Lancer_Level.x=420;
Lancer_Level.y=100;
Lancer_Level.addEventListener(MouseEvent.CLICK,LancerNouveauNiveauPerso);
LoadLevel.addChild(Lancer_Level);

//Qui commence ?
var FirstPlayer:int=Const.CUT;
var Perso_FPC:TextField = CreerTextField(LoadLevel,0,85,200,20,false,false,false);//First Player Coupheur : FPC
Perso_FPC.htmlText="<li>Coupheur commence</li>";
Perso_FPC.addEventListener(MouseEvent.MOUSE_OVER,tfSourisIN);
Perso_FPC.addEventListener(MouseEvent.MOUSE_OUT,tfSourisOUT);
Perso_FPC.addEventListener(MouseEvent.CLICK,FPC);
Perso_FPC.addEventListener(MouseEvent.CLICK,tfSourisCLICK);

var Perso_FPP:TextField = CreerTextField(LoadLevel,200,85,200,20,false,false,false);
Perso_FPP.htmlText="<li>Paintre commence</li>";
Perso_FPP.addEventListener(MouseEvent.MOUSE_OVER,tfSourisIN);
Perso_FPP.addEventListener(MouseEvent.MOUSE_OUT,tfSourisOUT);
Perso_FPP.addEventListener(MouseEvent.CLICK,FPP);
Perso_FPP.addEventListener(MouseEvent.CLICK,tfSourisCLICK);

function FPC(e:MouseEvent):void
{
FirstPlayer=Const.CUT;
}
function FPP(e:MouseEvent):void
{
FirstPlayer=Const.SHORT;
}


//Qui seront les adversaires ?
var Short_type:int=Const.COMPUTER;
var Cut_type:int=Const.HUMAN;

var Perso_PH_CH:TextField = CreerTextField(LoadLevel,0,100,200,20,false,false,false);
Perso_PH_CH.htmlText="<li>Paintre et Coupheur humains</li>";
Perso_PH_CH.addEventListener(MouseEvent.MOUSE_OVER,tfSourisIN);
Perso_PH_CH.addEventListener(MouseEvent.MOUSE_OUT,tfSourisOUT);
Perso_PH_CH.addEventListener(MouseEvent.CLICK,PH_CH);
Perso_PH_CH.addEventListener(MouseEvent.CLICK,tfSourisCLICK);

var Perso_PH_CC:TextField = CreerTextField(LoadLevel,0,120,200,20,false,false,false);//Player Human Coupheur Computer : PHCC
Perso_PH_CC.htmlText="<li>Paintre humain, Coupheur AI</li>";
Perso_PH_CC.addEventListener(MouseEvent.MOUSE_OVER,tfSourisIN);
Perso_PH_CC.addEventListener(MouseEvent.MOUSE_OUT,tfSourisOUT);
Perso_PH_CC.addEventListener(MouseEvent.CLICK,PH_CC);
Perso_PH_CC.addEventListener(MouseEvent.CLICK,tfSourisCLICK);

var Perso_PC_CH:TextField = CreerTextField(LoadLevel,200,100,200,20,false,false,false);
Perso_PC_CH.htmlText="<li>Paintre AI, Coupheur humain</li>";
Perso_PC_CH.addEventListener(MouseEvent.MOUSE_OVER,tfSourisIN);
Perso_PC_CH.addEventListener(MouseEvent.MOUSE_OUT,tfSourisOUT);
Perso_PC_CH.addEventListener(MouseEvent.CLICK,PC_CH);
Perso_PC_CH.addEventListener(MouseEvent.CLICK,tfSourisCLICK);

var Perso_PC_CC:TextField = CreerTextField(LoadLevel,200,120,200,20,false,false,false);
Perso_PC_CC.htmlText="<li>Paintre et Coupheur AI</li>";
Perso_PC_CC.addEventListener(MouseEvent.MOUSE_OVER,tfSourisIN);
Perso_PC_CC.addEventListener(MouseEvent.MOUSE_OUT,tfSourisOUT);
Perso_PC_CC.addEventListener(MouseEvent.CLICK,PC_CC);
Perso_PC_CC.addEventListener(MouseEvent.CLICK,tfSourisCLICK);

function PH_CH(e:Event=null):void
{
Short_type=Const.HUMAN;
Cut_type=Const.HUMAN;
}
function PH_CC(e:Event=null):void
{
Short_type=Const.HUMAN;
Cut_type=Const.COMPUTER;
}
function PC_CH(e:Event=null):void
{
Short_type=Const.COMPUTER;
Cut_type=Const.HUMAN;
}
function PC_CC(e:Event=null):void
{
Short_type=Const.COMPUTER;
Cut_type=Const.COMPUTER;
}

AppliquerFiltre(LoadLevel);

LoadLevelCaption.htmlText="<u>Éditeur de niveau</u><br>Créez vos propres niveaux en utilisant <a href=\"http://www.neamar.fr/Res/Cgraphe/Editor\" target=\"_blank\">E-Ditor (cliquez ici)</a>, puis collez le résultat ici.";

addChild(LoadLevel);

function ShowLoadLevel(e:Event):void
{
LoadLevel.visible=true;
Boite.visible=false;
}

function tfSourisIN(e:MouseEvent):void
{
if(e.currentTarget.textColor!=0xFF0000)
e.currentTarget.textColor=0xFFFFFF;
}
function tfSourisOUT(e:MouseEvent):void
{
if(e.currentTarget.textColor!=0xFF0000)
e.currentTarget.textColor=0x000000;
}
function tfSourisCLICK(e:MouseEvent):void
{

if(e.currentTarget==Perso_FPC || e.currentTarget==Perso_FPP)
Perso_FPP.textColor=Perso_FPC.textColor=0x000000;
else
Perso_PC_CC.textColor=Perso_PH_CC.textColor=Perso_PC_CH.textColor=Perso_PH_CH.textColor=0x000000;
e.currentTarget.textColor=0xFF0000;
}

function LancerNouveauNiveauPerso(e:Event=null):void
{//Lance le chargement à partir d'un niveau perso.
if(Partie!=null && contains(Partie.Terrain))
removeChild(Partie.Terrain);//Si Fond a déjà été utilisé, le nettoyer.
LoadLevel.visible=false;
Boite.visible=false;
Partie=new Game(Const.SHORT,Short_type,Cut_type,LoadLevelTexte.text);
Partie.Officiel=false;
InitialiserJeu();
}


Classes

Un jeu est une instance de Game. Cette instance se décompose en un BackGround (le fond qui bouge), et un terrain (Land) qui contient les noeuds et les aretes.
Le Game contient aussi les références vers les deux joueurs, (Human ou AI, tous deux héritant de Player).

Affichage et jeux

Code source : Game.as
//Une partie : contient donc les joueurs, le terrain, le bruit en arrière plan...
package
{
import flash.display.Sprite;
import flash.events.Event;


public class Game extends Sprite //On doit le faire extends sprite pour pouvoir bénéficier des listeners.
{
public var Terrain:Land;
public var Termine:Boolean=false;
public var Gagnant:Player;
public var NumeroNiveau:int=-1;
public var CallBack:Function;
public var Officiel:Boolean=true;//True par défaut, mis à false si chargé depuis level perso.

private var Short:Player;
private var Cut:Player;
private var Joueur_Actuel:int=-1;
private var Tour:Array;



public function Game(FirstPlayer:int,Short_Type:int,Cut_Type:int,Datas:String,Passif:Boolean=false,AI_Is_Smart:Boolean=true)
{
//L'initialisation du jeu. Rien de bien compliqué...
this.Terrain=new Land(Datas,this);
this.Terrain.Texte="INITIALISATION..."
switch (Short_Type)
{
case Const.HUMAN: Short=new Human(this,Const.SHORT); break;
case Const.COMPUTER: Short=new AI(this,Const.SHORT,AI_Is_Smart); break;
case Const.INTERNET: Short=new OnlinePlayer(this,Const.SHORT); break;
}
switch (Cut_Type)
{
case Const.HUMAN: Cut=new Human(this,Const.CUT); break;
case Const.COMPUTER: Cut=new AI(this,Const.CUT,AI_Is_Smart); break;
case Const.INTERNET: Cut=new OnlinePlayer(this,Const.CUT); break;
}

this.Tour=new Array(Short,Cut);
if(FirstPlayer==Const.CUT)
this.Tour.reverse();

if(!Passif)
{
Short.Initialiser(Fin_Initialisation);
Cut.Initialiser(Fin_Initialisation);//Attendre que les deux joueurs soient prêts.
}
else
{
this.Terrain.StopBackGround();
this.Terrain.PremierPlan.filters=new Array();
}

}

public function Fin_Initialisation():void
{
if(Short.Pret && Cut.Pret)
{
this.Terrain.graphics.clear();
Lancer_tour();
}
}

private function Lancer_tour():void
{
this.removeEventListener(Event.ENTER_FRAME,TestFinTour);
Joueur_Actuel = (Joueur_Actuel+1)%2;
this.Tour[Joueur_Actuel].Jouer();
this.addEventListener(Event.ENTER_FRAME,TestFinTour);

if(this.Tour[Joueur_Actuel].Joueur==Const.SHORT)
this.Terrain.Texte="Tour actuel : <strong>Paintre</strong>";
else
this.Terrain.Texte="Tour actuel : <strong>Couhpeur</strong>";
}

private function TestFinTour(e:Event):void
{
if(this.Tour[Joueur_Actuel].Tour_Termine)
{
this.Tour[Joueur_Actuel].Fin_Tour();
if(TestVictoire())
{
this.CallBack.call(this);
if(this.Tour[Joueur_Actuel].Joueur==Const.SHORT)
this.Terrain.Texte="Fin de la partie, gagnant : <strong>Paintre</strong>";
else
this.Terrain.Texte="Fin de la partie, gagnant : <strong>Couhpeur</strong>";
this.removeEventListener(Event.ENTER_FRAME,TestFinTour);
}
else
Lancer_tour();
}
}

private function TestVictoire():Boolean
{
var Resultat:Boolean=false;
var CorrectPath:ArrayPlus=new ArrayPlus();
//Teste si le jeu est terminé.
//Le jeu est déterministe, c'est à dire qu'il y a forcément un gagnant(il ne peut pas y avoir d'égalité).

//Teste si Short a gagné : (I.e il existe un chemin entièrement coloré)
if(TesteShort())
{
this.Gagnant=Short;
return true;
}

//Teste si Cut a gagné : (I.e il n'existe aucun chemin entre le départ et l'arivée)
if(TesteCut())
{
this.Gagnant=Cut;
return true;
}

return false;

//Fin de la fonction....
}

private function TesteShort():Boolean
{//true si short a gagné
var CheminExiste:Boolean=false;
function Short_PathFinde(Node:Noeud,Path:ArrayPlus):void
{
//Si le noeud examiné est le noeud final, on a gagné :)
if(Node==Terrain.EndNode)
CheminExiste=true;

if(CheminExiste!=true)
{//Sinon, on regarde chaque arete du noeud et on teste récursivement.d
for each(var Arete:Arc in Node.Liens)
{
if(Arete.PlayedByShort && !Path.Contains(Arete))
{
var CopiePath:ArrayPlus=Path.Clone();
CopiePath.push(Arete);
if(Arete.Extremites[0]==Node)
Short_PathFinde(Arete.Extremites[1],CopiePath)
else
Short_PathFinde(Arete.Extremites[0],CopiePath)
}
}
}
}
Short_PathFinde(this.Terrain.StartNode,new ArrayPlus());
return CheminExiste;
}
private function TesteCut():Boolean
{//true si cut a gagné
var CheminExiste:Boolean=false;
function Cut_PathFinde(Node:Noeud,Path:DictionaryPlus,Node_Liste:DictionaryPlus):void
{
//Si le noeud examiné est le noeud final, on a pas encore gagné :) (il existe un chemin entre le départ et l'arrivée)
if(Node==Terrain.EndNode)
CheminExiste=true;
else if(CheminExiste==false)
{//Sinon, on regarde chaque arete du noeud et on teste récursivement.
for each(var Arete:Arc in Node.Liens)
{
var AutreExtremite:Noeud;
if(Arete.Extremites[0]==Node)
AutreExtremite=Arete.Extremites[1];
else
AutreExtremite=Arete.Extremites[0];
if(!Path.Contains(Arete) && !Node_Liste.Contains(AutreExtremite))
{
var CopiePath:DictionaryPlus=Path.Clone();
CopiePath[Arete]=true;
var CopieNode:DictionaryPlus=Node_Liste.Clone();
CopieNode[AutreExtremite]=true;
Cut_PathFinde(AutreExtremite,CopiePath,CopieNode);
}
}
}
}
var Node_Liste:DictionaryPlus=new DictionaryPlus();
Node_Liste[Terrain.StartNode]=true;
Cut_PathFinde(this.Terrain.StartNode,new DictionaryPlus(),Node_Liste);
return !CheminExiste;
}
}
}
Code source : BackGround.as
//Le nuage bleu derrière chaque niveau.
//Baisser la qualité permet d'arrêter la génération du bruit pour récupérer des ressources.
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.Sprite;
import flash.filters.BitmapFilter;
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.events.Event;//Les évenements "de bases", classe dont dérive MouseEvent

public class BackGround extends Sprite
{
public var Fond:BitmapData = new BitmapData(640,480, false);

private var PetitFond:BitmapData=new BitmapData(128,96,false);
private var Champ:BitmapData=new BitmapData(128,96,true,0x00000000);
private var Affichage:Bitmap;
private var Influence:Bitmap;
private var Nb:int=-1;
private var StartValue:int;

private var Layer:Land;
private var Size:int=30;

private static var FiltreDessin:DisplacementMapFilter=new DisplacementMapFilter(null,new Point(0,0),BitmapDataChannel.RED,BitmapDataChannel.RED,40,40,DisplacementMapFilterMode.CLAMP);
private static var FiltreMvt:DisplacementMapFilter=new DisplacementMapFilter(null,new Point(0,0),BitmapDataChannel.BLUE,BitmapDataChannel.BLUE,15,15,DisplacementMapFilterMode.CLAMP,0.25,1)

public function BackGround(Layer:Land)
{

this.Layer=Layer;
StartValue=Math.random()*100;

Champ.perlinNoise(128,96,4,StartValue+1,false,false,BitmapDataChannel.RED,false);

Affichage = new Bitmap(Fond);
this.addChild(Affichage);

Influence=new Bitmap(Champ);
Influence.scaleX=Influence.scaleY=5;
addChild(Influence);
Influence.alpha=.2

this.addEventListener(Event.ENTER_FRAME,Anim_Fond);
}

public function StopBackGround():void
{
this.removeEventListener(Event.ENTER_FRAME,Anim_Fond);
Anim_Fond();//L'appeler juste une fois, pour quand même avoir un fond.
}

public function Anim_Fond(e:Event=null):void
{
Nb++;
if(Nb % 3==0 && (Const._stage.quality=="HIGH" || Nb ==0))
{
//public function perlinNoise(baseX:Number, baseY:Number, numOctaves:uint, randomSeed:int, stitch:Boolean, fractalNoise:Boolean, channelOptions:uint = 7, grayScale:Boolean = false, offsets:Array = null):void

PetitFond.perlinNoise(128,96,2,StartValue,false,false,BitmapDataChannel.BLUE,false,new Array(new Point(Nb,0),new Point(Nb>> 1,0)));//>>1 = *.5

FiltreDessin.mapBitmap=Champ;
PetitFond.applyFilter(PetitFond,new Rectangle(0,0,128,96),new Point(0,0),FiltreDessin);

Fond.draw(PetitFond,new Matrix(5,0,0,5));

FiltreMvt.mapBitmap=Fond;
this.Layer.PremierPlan.filters=new Array(FiltreMvt);
}

}
}
}
Code source : Land.as
//Un niveau standard : contient des liens et des noeuds !
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
import flash.events.MouseEvent;//Interaction utilisateur//souris
import flash.filters.BitmapFilter;

import flash.filters.GlowFilter;
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.

public class Land extends Sprite
{
public var All_Noeuds:Array;
public var All_Liens:Array;
public var initialAll_Lienslength:int;
public var Layer:Game;

public var StartNode:Noeud;
public var EndNode:Noeud;

public var ArrierePlan:BackGround;
public var PremierPlan:Sprite=new Sprite();

private var Infos:TextField=new TextField();

private const FlashWidth:int = 640;
private const FlashHeight:int = 480;


public function Land(Datas:String,Layer:Game)
{
// var Niv_String:String="140,240|500,240:0,1,320,440|0,1,320,40|0,1,320,240";
// var Niv_String:String= "98,370|419,367|266,211|256,49:3,2,261,130|2,0,232,361|2,1,289,330|2,0,182,291|2,1,342,289";
// var Niv_String:String= "34,289|174,282|286,181|286,221|280,280|277,325|277,353|415,320|531,279|411,200|607,276:0,1,104,285|1,2,230,231|1,3,230,252|1,4,227,281|1,5,225,303|1,6,225,317|6,7,347,316|5,7,347,302|7,8,473,299|4,8,406,279|3,9,313,211|2,9,313,191|9,8,471,240|8,10,569,277"

this.ArrierePlan=new BackGround(this);
this.addChild(ArrierePlan);
this.setChildIndex(ArrierePlan,0);


this.Layer=Layer;
Infos.x=0;
Infos.y=FlashHeight-15;
Infos.autoSize = "left";
Infos.textColor=0xFFFFFF;
Infos.thickness=3;
Infos.selectable=false;

this.addChild(Infos);
this.addChild(PremierPlan);

var Niv_String:String=Datas;
var Composants:Array;
var Part:Array=Niv_String.split(":");
var strNoeuds_Array:Array=Part[0].split("|");
var strArc_Array:Array=Part[1].split("|");
var Noeuds:Array=new Array();
var Liens:Array=new Array();
for each(var Node:String in strNoeuds_Array)
{
Composants=Node.split(",");
Noeuds.push(Composants);
}
for each(var Arete:String in strArc_Array)
{
Composants=Arete.split(",");
Liens.push(Composants);
}

CreerNiveau(Noeuds,Liens,FlashWidth,FlashHeight);

this.setChildIndex(ArrierePlan,0);
}

public function set Texte(v:String):void
{
this.Infos.htmlText=v.toLocaleUpperCase();
}

public function StopBackGround():void
{
this.ArrierePlan.StopBackGround();
}
private function CreerNiveau(Noeuds:Array,Liens:Array,Largeur:int=0,Hauteur:int=0):void
{
var Node:Noeud;
var Arete:Arc;

All_Noeuds = new Array();
All_Liens = new Array();
for each(var Arr_Noeud:Array in Noeuds)
All_Noeuds.push(new Noeud(this,Arr_Noeud[0],Arr_Noeud[1]));

StartNode=All_Noeuds[0];
EndNode=All_Noeuds[All_Noeuds.length-1];
StartNode.filters=Const.Filtre_Noeuds_Extremes;
EndNode.filters=Const.Filtre_Noeuds_Extremes;

for each(var Arr_Lien:Array in Liens)
{
Arete=new Arc(this,All_Noeuds[Arr_Lien[0]],All_Noeuds[Arr_Lien[1]],new Point(Arr_Lien[2],Arr_Lien[3]));
All_Noeuds[Arr_Lien[0]].AjouterLien(Arete);
All_Noeuds[Arr_Lien[1]].AjouterLien(Arete);
All_Liens.push(Arete);
}
initialAll_Lienslength=All_Liens.length;

this.graphics.beginFill(0xFFFFFF);
this.graphics.drawRect(0,0, Largeur, Hauteur);
}
}
}
Code source : Noeud.as
//Un noeud quelconque.
//Dans C_Graphe les noeuds n'ont pas d'utilité particulière.
//Le code est donc très court...
package
{
import flash.display.Shape;
import flash.geom.Point;


public class Noeud extends Shape
{

public var Liens:Array=new Array();

private var Final_Glow:int;//La valeur de rayonnement désirée
private var Current_Glow:Number;//Le rayonnement actuel du noeud

private var Layer:Land;//Le conteneur


private static const RAYON:int=10;

public function Noeud(Layer:Land,x:Number,y:Number)
{//Instancie un nouveau noeud

this.Layer = Layer;

this.x=x; this.y=y;

this.graphics.beginFill(0xEEEEEE);
this.graphics.lineStyle(1,0x000000);
this.graphics.drawCircle(0, 0, 4);//Plus il y a de noeuds, plus le dessin est petit. Mais on impose une taille minimum !

Layer.PremierPlan.addChild(this);

}

public function AjouterLien(Lien:Arc):void
{
Liens.push(Lien);
}
public function RemoveLien(Lien:Arc):void
{
Liens.splice(Liens.indexOf(Lien),1);
if(Liens.length==0)
this.alpha=.3;
}
}
}
Code source : Arc.as
//Un lien (arete, arc...peut importe le nom !)
package
{
import flash.display.Sprite;
import flash.geom.Point;
import flash.events.Event;
import flash.events.MouseEvent;//Interaction utilisateur//souris
import flash.filters.BitmapFilter;
import flash.filters.GlowFilter;
import flash.geom.ColorTransform;

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.

public class Arc extends Sprite
{

private var Final_Glow:int=0;//La valeur de rayonnement désirée
private var Current_Glow:Number=0;//Le rayonnement actuel du noeud
private var PBS:Boolean=false;

public var Extremites:Array;//Extremites contient les noeuds parents
public var ID:int;

private var Layer:Land;

private static var Defaut_Color:ColorTransform= new ColorTransform();
private static var Short_Color:ColorTransform = new ColorTransform(1, 1, 1,1, 255,255,255);

private static const Filtres:Array=new Array(
new Array(),
new Array(new GlowFilter(0x00FF00, 0.8,16,16,.5)),
new Array(new GlowFilter(0x00FF00, 0.8,16,16,1)),
new Array(new GlowFilter(0x00FF00, 0.8,16,16,1.5)),
new Array(new GlowFilter(0x00FF00, 0.8,16,16,2)),
new Array(new GlowFilter(0x00FF00, 0.8,16,16,2.5)),
new Array(new GlowFilter(0x00FF00, 0.8,16,16,3)),
new Array(new GlowFilter(0x00FF00, 0.8,16,16,3.5)),
new Array(new GlowFilter(0x00FF00, 0.8,16,16,4)),
new Array(new GlowFilter(0x00FF00, 0.8,16,16,4.5)),
new Array(new GlowFilter(0x00FF00, 0.8,16,16,5)));//Evite d'avoir à recréer le filtre en permanence. En plus on utilise static ce qui allège la consommation de mémoire : les filtres ne sont crées qu'une fois au démarrage de l'application, pas à chaque instanciation de noeud.


//la representation graphique de l'arc :
private var Depart:Point;//Depart est l'emplacement du premier parent, avec un peu de trigonométrie...cf. plus bas
private var Arrivee:Point;//idem
private var Controle:Point;//Le point de controle pour la courbe de Bézier
private var Texte:TextField=new TextField();

public function Arc(Layer:Land,Point1:Noeud,Point2:Noeud,ControlePoint:Point)
{//Instancie un nouveau lien : prend en paramètre le conteneur et les extremités.
this.Layer = Layer;
Layer.PremierPlan.addChild(this);
Layer.PremierPlan.setChildIndex(this,0);

this.Extremites=new Array(Point1,Point2);
this.Controle=ControlePoint;

this.Refresh();

Texte.x = (Point1.x+Point2.x)/2;
Texte.y = (Point1.y+Point2.y)/2-10;
Texte.autoSize = "left";
Texte.mouseEnabled=false;
this.addChild(Texte);

}

public function set PlayedByShort(v:Boolean):void
{
this.PBS=v;

if(v)
{
this.transform.colorTransform=Short_Color;
this.AddFocus(2);
}
}
public function get PlayedByShort():Boolean
{
return this.PBS;
}

public function set Caption(v:String):void
{
if(Const.MODE==Const.DEBUG)
Texte.text=v;
}
public function Refresh():void
{//Redessine entièrement le lien. Cette méthode est utilisée lorsque l'un des noeuds se déplace||est déplacé
//Met aussi à jour la liste des collisions.
this.graphics.clear();

this.Depart=new Point(this.Extremites[0].x,this.Extremites[0].y);
this.Arrivee=new Point(this.Extremites[1].x,this.Extremites[1].y);

//Le trait principal
this.graphics.moveTo(Depart.x,Depart.y);
this.graphics.lineStyle(3,0x444444,.9);
this.graphics.curveTo(Controle.x,Controle.y,Arrivee.x,Arrivee.y);

//L'ombrage
this.graphics.lineStyle(23,0xFFFFFF,.001);
this.graphics.curveTo(Controle.x,Controle.y,Depart.x,Depart.y);
}

public function AddFocus(Level:int):void
{//Ajoute un flou à la forme.
this.Final_Glow=2*Level;//Il y a un facteur 2 entre ce qui est demandé et ce qui est dessiné.
this.addEventListener(Event.ENTER_FRAME,ChangeFiltre);
}

public function Sommet(OtherThan:Noeud):Noeud
{
if(OtherThan==this.Extremites[0])
return Extremites[1];
else
return Extremites[0];
}

private function ChangeFiltre(e:Event=null):void
{//gestion des filtres dans le temps

//Filtre HOVER
if(Current_Glow<Final_Glow)
Current_Glow=Math.min(Final_Glow,Current_Glow+.5);
else
Current_Glow=Math.max(Final_Glow,Current_Glow-1);

this.filters=Filtres[int(Current_Glow)];

//Enlever l'évenement afin de décharger la mémoire.
if(Current_Glow==Final_Glow)
this.removeEventListener(Event.ENTER_FRAME,ChangeFiltre);
}
}
}

Les joueurs

Code source : Player.as
//Un Player définit un joueur de la façon la plus générale possible.
//LEs spécificités sont ajoutés via les classes qui héritent de Player, telles que AI ou Human.

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;

import flash.geom.Point;


public class Player extends Sprite
{
public var Tour_Termine:Boolean=false;
public var Pret:Boolean=false;
public var Joueur:int;
public var IsHuman:Boolean;

protected var Jeu:Game;
protected var Terrain:Land;



public function Player()
{
}

//Les fonctions présentées ici sont destinées à être overridées dans certains cas, voir les sous classes.
public function Initialiser(TriggerWhenReady:Function):void
{//Par défaut, l'intialisation est instantanée.
this.Pret=true;
TriggerWhenReady.call(this);
}

public function Fin_Tour():void
{
}

public function JouerArete(Arete:Arc):Boolean
{
if(Arete.PlayedByShort)
return false; //L'arete a déjà été jouée.

if(Joueur==Const.CUT)
{//Supprimer l'arete :
//Le graphisme
Arete.graphics.clear();
this.Terrain.PremierPlan.removeChild(Arete);

//Les références :
Arete.Extremites[0].RemoveLien(Arete);
Arete.Extremites[1].RemoveLien(Arete);

//La copie originale :
this.Terrain.All_Liens.splice(this.Terrain.All_Liens.indexOf(Arete),1);
Arete=null;
}
else//Cas Joueur==SHORT)
Arete.PlayedByShort=true;
Tour_Termine=true;
return true;
}
}
}
Code source : AI.as
//Définit le comportement d'un ordinateur en instanciant un Joueur.
//Cette classe comporte plus de fonctions que Human, et peut être plus difficile d'accès.

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;


import flash.geom.Point;


public class AI extends Player
{
public static const NO_CLEANING:Boolean=false;
public var Smart:Boolean;//Si cette valeur vaut AI_NOT_SMART, l'ordinateur sera moins intelligent et plus facile à vaincre.

private var AreteSelectionnee:Arc;
private var Chrono:Timer;

public function AI(Jeu:Game,Joueur:int,AI_Is_Smart:Boolean)
{
this.IsHuman=false;
this.Jeu = Jeu;
this.Terrain = Jeu.Terrain;
this.Joueur=Joueur;
this.Smart=AI_Is_Smart;

this.Chrono= new Timer(750);
Chrono.addEventListener(TimerEvent.TIMER, ActNow);

}

public function Jouer():void
{//Sélectionne l'arête la plus utile, et lance la coloration dessus. ATtention, elle n'est pas encor ejouée : il y a un petit temps pour permettre à l'utilisateur de voir le coup.
function GetMax():Array
{
var BestEdge:Arc;
var BestEdgesCoeff:Number=-1;
var CurrCoeff:Number;
for(var Arete:* in Aretes_Ponderees)
{
CurrCoeff=Aretes_Ponderees[Arete];
if(BestEdgesCoeff<=CurrCoeff && !Arete.PlayedByShort)
{
BestEdge=Arete;
BestEdgesCoeff=CurrCoeff;
}
Arete.Caption=(Math.round(CurrCoeff*100)/100).toString();
}
return new Array(BestEdge,BestEdgesCoeff);
}

Tour_Termine=false;
var Aretes_Ponderees:DictionaryPlus=this.getPonderedEdges();
var PlusLourd:Array=GetMax();
if(PlusLourd[1]==0)
{//Si le plus lourd vaut 0, alors toutes les aretes valent 0 et ont été interdites : relancer le calcul, même si la partie est plus que probablement perdue.
Aretes_Ponderees=this.getPonderedEdges(NO_CLEANING);//Refaire le calcul en autorisant toutes les aretes
PlusLourd=GetMax();
}

this.AreteSelectionnee=PlusLourd[0];
this.AreteSelectionnee.AddFocus(4);
Chrono.start();
}

//Fonctions privées

private function ActNow(e:TimerEvent):void
{
JouerArete(this.AreteSelectionnee);
Chrono.stop();
}
private function getPonderedEdges(Nettoyer:Boolean=true):DictionaryPlus
{//Cette fonction renvoie la liste des arêtes triées par ordre d'importance...selon un pseudo-pathfinding.
var All_Possible_Path:Array=new Array();
var ForbiddenEdge:DictionaryPlus=new DictionaryPlus();
var Edge:Arc;
var Node:Noeud;

if(Nettoyer && Smart)
{//Enlève du jeu les arêtes inutiles, à condition que l'on ne force pas l'utilisation de tout les noeuds (Nettoyer=true) et que l'ordinateur doit être intelligent.
//Commencer par lister les aretes inutiles :
for each(Node in this.Terrain.All_Noeuds)
{
//CAS 1 : ---------------O------------------- : deux liens seuls sur le même sommet, aucun des deux n'est joué.
if(Node.Liens.length==2 && !Node.Liens[0].PlayedByShort && !Node.Liens[1].PlayedByShort && Node!=Terrain.StartNode && Node!=Terrain.EndNode && Node.Liens[0].Sommet(Node)!=Node.Liens[1].Sommet(Node))
{
ForbiddenEdge[Node.Liens[0]]=true;
ForbiddenEdge[Node.Liens[1]]=true;
if(Const.MODE==Const.DEBUG)
Node.Liens[0].alpha=Node.Liens[1].alpha=.7;
}
}

for each(Edge in this.Terrain.All_Liens)
{
//CAS 2 : Un chemin PlayedByShort existe entre les deux extrémités de l'arête.
var CheminExiste:Boolean=false;
Short_PathFinde(Edge.Extremites[0],Edge.Extremites[1],Edge,new DictionaryPlus())
if(CheminExiste)
{
ForbiddenEdge[Edge]=true;
if(Const.MODE==Const.DEBUG)
Edge.alpha=.5;
}
}
function Short_PathFinde(Node:Noeud,Arrivee:Noeud,Excluding:Arc,Path:DictionaryPlus):void
{
//Si le noeud examiné est le noeud final, on a gagné :)
if(Node==Arrivee)
CheminExiste=true;
if(CheminExiste!=true)
{//Sinon, on regarde chaque arete du noeud et on teste récursivement.
for each(var Arete:Arc in Node.Liens)
{
if(Arete.PlayedByShort && Excluding!=Arete && !Path.Contains(Arete))
{
var CopiePath:DictionaryPlus=Path.Clone();
CopiePath[Arete]=true;
Short_PathFinde(Arete.Sommet(Node),Arrivee,Excluding,CopiePath)
}
}
}
}
}
function PathFind(Node:Noeud,Path:DictionaryPlus,Node_Liste:DictionaryPlus):void
{
//Si le noeud examiné est le noeud final, on a un nouveau chemin : l'enregistrer en mémoire.
if(Node==Terrain.EndNode)
All_Possible_Path.push(Path);
else
{
// Puis on regarde chaque arete du noeud et on teste récursivement.
for each(var Arete:Arc in Node.Liens)
{
var AutreExtremite:Noeud=Arete.Sommet(Node);//Récupére le noeud à l'autre bout du lien.

if(!Path.Contains(Arete) && !Node_Liste.Contains(AutreExtremite) && !ForbiddenEdge.Contains(Arete))
{
var CopiePath:DictionaryPlus=Path.Clone();
CopiePath[Arete]=true;
var CopieNode:DictionaryPlus=Node_Liste.Clone();
CopieNode[AutreExtremite]=true;
PathFind(AutreExtremite,CopiePath,CopieNode)
}
}
}
}
var Node_Liste:DictionaryPlus=new DictionaryPlus();
Node_Liste[Terrain.StartNode]=true;
PathFind(Terrain.StartNode,new DictionaryPlus(),Node_Liste);

//A ce point, le tableau All_Possible_Path est plein et contient l'ensemble des chemins que l'on peut emprunter pour se rendre du départ à l'arrivée.

function SizeOf(Item:DictionaryPlus):Number
{//Renvoie le nombre minimal d'arêtes à allumer pour terminer le chemin :
var Jouees:int=0;
var Total:int=0;
for(var Arete:* in Item)
{
if(Arete.PlayedByShort)
Jouees++;
Total++;
}
var DeltaS:int=Total-Jouees;
if(DeltaS>1)
return DeltaS;
else
return 0.001;
}

//On initialise la réponse :
var Poids:DictionaryPlus=new DictionaryPlus();
var Taille:int=this.Terrain.initialAll_Lienslength;
for each(Edge in Terrain.All_Liens)
Poids[Edge]=0;

//On va maintenant compter combien de fois chaque arete est présente :
for each(var Path:DictionaryPlus in All_Possible_Path)
{
if(this.Smart)
Taille=Math.pow(SizeOf(Path),2);//Selon l'intelligence, on n'utilise pas la même loi de calcul.
else
Taille=SizeOf(Path);
for(var Arete:* in Path)
{
if(!Arete.PlayedByShort)
Poids[Arete] +=1/Taille;
}
}
return Poids;
}
}
}
Code source : Human.as
//Cette classe permet à un humain de jouer.
//Elle s'occupe de placer les listneers ou il faut quand il faut, de les enlever...
//Elle n'est pas très complexe, par rapport à AI.
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;

import flash.geom.Point;

public class Human extends Player
{

public function Human(Jeu:Game,Joueur:int)
{
this.IsHuman=true;
this.Jeu = Jeu;
this.Terrain = Jeu.Terrain;
this.Joueur=Joueur;
}

public function Jouer():void
{

Tour_Termine=false;
for each(var Arete:Arc in this.Terrain.All_Liens)
{
if(!Arete.PlayedByShort)
{
Arete.addEventListener(MouseEvent.CLICK,ChoixArete);
Arete.addEventListener(MouseEvent.MOUSE_OVER,SourisIN);
Arete.addEventListener(MouseEvent.MOUSE_OUT,SourisOUT);
}
}
var Actuel:Array=this.Terrain.getObjectsUnderPoint(new Point(this.Terrain.mouseX,this.Terrain.mouseY));
for each(var Forme:* in Actuel)
{
if(Forme is Arc)
{
Forme.AddFocus(5);
break;
}
}
}

public override function Fin_Tour():void
{
for each(var Arete:Arc in this.Terrain.All_Liens)
{
Arete.removeEventListener(MouseEvent.CLICK,ChoixArete);
Arete.removeEventListener(MouseEvent.MOUSE_OVER,SourisIN);
Arete.removeEventListener(MouseEvent.MOUSE_OUT,SourisOUT);
}
}

//Fonctions privées
private function SourisIN(e:Event):void
{
e.target.AddFocus(5);
}
private function SourisOUT(e:Event):void
{
e.target.AddFocus(0);
}
private function ChoixArete(e:Event):void
{
JouerArete(Arc(e.target))
}
}
}
Code source : OnlinePlayer.as
//À l'origine, devait définir un joueur "online" pour pouvoir jouer en réseau. L'idée a été abandonnée, peut être pour être reprise dans DGraphe.
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;

import flash.geom.Point;



public class OnlinePlayer extends Player
{
public function OnlinePlayer(Jeu:Game,Joueur:int)
{
this.IsHuman=true;
this.Jeu = Jeu;
this.Terrain = Jeu.Terrain;
this.Joueur=Joueur;
}

public override function Initialiser(TriggerWhenReady:Function):void
{//Recherche un joueur en ligne
Jeu.Terrain.Texte="Recherche d'un partenaire..."
TriggerWhenReady.call(this);
}

public function Jouer():void
{
Tour_Termine=false;
}

//Fonctions privées
}
}

Utilitaires

Code source : Const.as
//Les constantes utilisées tout au long de l'exécution.
//Les variables sont mises static afin d epouvoir y accéder à partir de n'importe quelle classe de CGraphe.
package
{
import flash.filters.BevelFilter;
import flash.filters.GlowFilter;
import flash.display.Stage;

public class Const
{
public static var _stage:Stage; //Pouvoir bénéficier du stage partout.

public static const VERSION:String="Final";//La version
public static const DEBUG:String="debug";
public static const RELEASE:String="release"
public static const MODE:String=RELEASE;//Le mode debug affiche des informations utiles concernant l'intelligence artificielle.

public static const SHORT:int=0;
public static const CUT:int=1;
public static const AI_NOT_SMART:Boolean=false;
public static const AI_SMART:Boolean=true;

public static const HUMAN:int=0;
public static const COMPUTER:int=1;
public static const INTERNET:int=2;

public static const FLASHWIDTH:int = 640;
public static const FLASHHEIGHT:int = 480;

public static const BEVEL_IN:BevelFilter=new BevelFilter(8,45,0x000000);
public static const BEVEL_OUT:BevelFilter=new BevelFilter();

public static const Filtre_Noeuds_Extremes:Array=new Array(new GlowFilter(0xFF0000, 0.8,16,16,4),new GlowFilter(0xFF0000, 0.8,8,8,4,1,true))

public function Const()
{
}
}
}
Code source : Trace.as
//Trace permet d'afficher à l'écran des informations utiles.
//Classe statique, qui doit être initialisée via sa méthode initialiser()
package
{
import flash.display.Sprite;
import flash.display.Stage;
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.events.Event;
import flash.events.MouseEvent;


public class Trace extends Sprite
{
private static var _stage:Stage;
private static var Container:Sprite = new Sprite();//Le conteneur principal
Container.addEventListener(MouseEvent.MOUSE_DOWN, StartDrag);
Container.scaleX=1;
Container.scaleY=1;
Container.alpha=1;

private static var Texte:TextField=new TextField();
Texte.x = 5;
Texte.y = 5;
Texte.autoSize = "left";
Container.addChild(Texte);

private static var Reduire:Sprite = new Sprite();
Reduire.graphics.beginFill(0xFFFFFF,1);
Reduire.graphics.drawRect(0,0,10,10);
Reduire.addEventListener(MouseEvent.MOUSE_UP, Delete);
Container.addChild(Reduire);

private static var LastTrace:String="";

public function Trace()
{//Constructeur non utilisé.
}

public static function initialiser(vstage:Stage):void
{
_stage=vstage;
_stage.addChild(Container);
}
public static function append(txt:String,ForceRepeat:Boolean=false):void
{//La fonction principale, qui trace le texte passé en paramètre.
if(LastTrace!=txt || ForceRepeat)
{
Texte.text = txt + "\r" + Texte.text;//\r indique un retour à la ligne.

if(_stage)//Seulement si initialisé.
_stage.setChildIndex(Container,_stage.numChildren-1);
LastTrace=txt;
}
}

public static function clear():void
{//Efface le contenu du Trace.
Texte.text="";
LastTrace="";
}

//Les fonctions pour déplacer
public static function set draggable(v:Boolean):void
{
if(v)
Container.addEventListener(MouseEvent.MOUSE_DOWN, StartDrag);
else
Container.removeEventListener(MouseEvent.MOUSE_DOWN, StartDrag);
}
private static function StartDrag(e:Event):void
{
Container.startDrag();
Container.addEventListener(MouseEvent.MOUSE_UP, StopDrag);
Container.removeEventListener(MouseEvent.MOUSE_DOWN, StartDrag);
Texte.selectable=false;
}
private static function StopDrag(e:Event):void
{
Container.stopDrag();
Container.removeEventListener(MouseEvent.MOUSE_UP, StopDrag);
Container.addEventListener(MouseEvent.MOUSE_DOWN, StartDrag);
Texte.selectable=true;
}

//Et pour supprimer la boite :
private static function Delete(e:Event):void
{
Container.visible=false;
Reduire.removeEventListener(MouseEvent.MOUSE_UP, Delete);
Container.removeEventListener(MouseEvent.MOUSE_DOWN, StartDrag);
Container.removeEventListener(MouseEvent.MOUSE_UP, StopDrag);
Container=null;
Texte=null;
}
}
}
Code source : ArrayPlus.as
//Ajoute quelques fonctions à la classe Array de base.
//On doit la mettre dynamique pour pouvoir stocker des données dedans.

package
{
public dynamic class ArrayPlus extends Array
{
public function ArrayPlus(FirstItem:*=null)
{
if(FirstItem!=null)
this.push(FirstItem);
}

public function Clone():ArrayPlus
{
var Bis:ArrayPlus=new ArrayPlus();
for each(var i:* in this)
Bis.push(i);

return Bis;
}

public function Contains(item:*):Boolean
{
return (this.indexOf(item)!=-1)
}

//Fonctions privées
}
}
Code source : DictionaryPlus.as
//Ajoute quelques fonctions à la classe Dictionary de base.
//On doit la mettre dynamique pour pouvoir stocker des données dedans.

package
{
import flash.utils.Dictionary
public dynamic class DictionaryPlus extends Dictionary
{
public function DictionaryPlus(weakKeys:Boolean=false)
{
super(weakKeys);
}

public function Clone():DictionaryPlus
{
var Bis:DictionaryPlus=new DictionaryPlus(this.weakKeys);
for(var i:* in this)
Bis[i]=this[i];

return Bis;
}

public function Contains(item:*):Boolean
{
return (this[item]!=undefined);
}
}
}
Auteur
Neamar
Date
Février 2009
But
Finir le jeu
Voir aussi
Compiler l'AS3
Retour
Retour à CGraphe
Menu
Index des ressources

Chargement du sommaire...