Un jeu de logique en Flash
Licence
Ce code est fourni sous une licence CC-By (cf. fin de page).
De plus, il est interdit de recompiler le jeu "tel quel" en supprimant le lien «Plus de jeux», la mention «tel quel» restant à l'appréciation de l'auteur original du code source (copie, plagiat...).
À propos du code
Le code est réparti en classes claires et nettes. L'ensemble du fichier représente moins de 10ko !
La position de chaque noeud est calculée à la volée, à l'aide d'une méthode récursive plutôt performante.
Classe principale A-Graphe
Fichiers de bases :
Code source : Agraphe.as
Langage : actionscript3 ΔT : 0.142s Taille :5636 caractères //Code original par Neamar. Réutilisation libre.
//neamar@neamar.fr
//Ligne de commande pour compiler :
//(après s'être placé dans le bon dossier, cf. http://neamar.fr/Res/Compiler_AS3/)
//
//bash mxmlc Sources/A-graphe/Agraphe.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.events .
* ;
//Chargons tous les évenements ce sera plus simple :)
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
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 ;
import flash.net .
URLRequest ;
//Prépare une requete.
import flash.net .
sendToURL ;
//Execute une requete sans récuperer la réponse
import flash.display .
Loader ;
//Chargement d'un fichier normal, et récupère le contenu
import flash.system .
LoaderContext ;
//Forcer le chargement du crossdomain.xml
import flash.net .
SharedObject ;
//Sauvegarde locale
[ SWF
( width =
"640" ,
height =
"480" ,
frameRate =
25 ) ] ;
//Quelques paramètres pour la compilation. Ils sont cependant redéfinis dans la ligne de commande.
public class Agraphe extends
Sprite
{
public var Fond
: Niveau;
//Fond est un Sprite Niveau, qui contient le niveau en cours.
public const VERSION
: String =
"RC1" ;
//La version
public var Img_Fond
: Loader =
new Loader ( ) ;
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
public var NumeroNiveauActuel
: int =
0 ;
public var NumeroNiveauUnlockes
: int ;
private var GrandPere
: Noeud;
//GrandPere est présent dans chaque niveau, c'est le noeud final à atteindre.
function Agraphe
( ) : void
{
// Les constantes primitives utilisées tout au long du Flash
const FlashWidth
: int =
640 ;
const FlashHeight
: int =
480 ;
// Récuperer les données locales
SAVE_LOCAL =
SharedObject .
getLocal ( "AGraphe" ) ;
SESSION = SAVE_LOCAL.
data ;
// SESSION.NumeroNiveauUnlockes=SESSION.NumeroNiveauActuel=11;
// SESSION.NumeroNiveauActuel=SESSION.NumeroNiveauUnlockes=null;
if ( SESSION.NumeroNiveauActuel==
null )
SESSION.NumeroNiveauActuel=SESSION.NumeroNiveauUnlockes=NumeroNiveauActuel;
//On ne met pas à 0 afin de permettre des tests : lors du débuggage, il suffit de changer une variable pour passer à un niveau.
NumeroNiveauUnlockes=SESSION.NumeroNiveauUnlockes;
//Recharger les dernières valeurs
NumeroNiveauActuel=NumeroNiveauUnlockes;
//Commencer au dernier niveau
// include "../Trace.as";
include
"ChangementsNiveaux.as" ;
//Pendant le niveau, test si il est fini. Prépare le passage à un nouveau niveau.
include
"ChargementNiveaux.as" ;
//La liste des niveaux, les différentes possibilités de le charger (via un String, un Array...)
include
"Message.as" ;
//La boite de message. Montre un message via la méthode ShowMessage(message:String)
include
"2Joueurs.as" ;
//Gestion du mod «2 Joueurs»
include
"Persos.as" ;
//Gestion du mod «Créateur de niveaux»
// include "Resolution.as";//Non inclus dans la version distribuée. Teste un niveau, renvoie le nombre minimal de noeuds à allumer.
SwapBackGround
( ) ;
//Afficher l'image de fond
//Enregistrer le nouveau joueur :
sendToURL ( new URLRequest ( "http://neamar.fr/Res/AGraphe/Player.php" ) ) ;
Fond = GetLevelData
( NumeroNiveauActuel
) ;
//Charger le niveau de numéro NumeroNiveauActuel
addChild ( Fond
) ;
Fond.
graphics .
clear ( ) ;
//enlever le fond blanc que les niveaux ont normalement.
Fond.FlouFinal=Fond.FLOU_FINAL;
//Repasser la boite de message au premier plan...c'est plus pratique pour la lire :-)
setChildIndex ( Fond,
1 ) ;
//Sinon, Fond est au 1er plan et bloque la lecture des informations.
addEventListener ( Event .
ENTER_FRAME ,TesterFinNiveau
) ;
////////////////////////////////
//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 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 SwapBackGround
( ) : void
{ //Télecharger l'image de fond, l'afficher.
//Le Img_FondContext sert à demander le télechargement du fichier crossdomain.xml
Img_Fond.
load ( new URLRequest ( "http://neamar.fr/Res/AGraphe/Images/Fond.png" ) ,
new LoaderContext ( true ) ) ;
if ( ! contains ( Img_Fond
) )
{ //Et la mettre au dernier plan
addChild ( Img_Fond
) ;
setChildIndex ( Img_Fond,
0 ) ;
}
}
function ResetAll
( e
: Event ) : void
{
NumeroNiveauActuel=NumeroNiveauUnlockes=SESSION.NumeroNiveauActuel=SESSION.NumeroNiveauUnlockes=
0 ;
UpdaterBoite
( ) ;
}
}
}
}
Code source : ChangementsNiveaux.as
Langage : actionscript3 ΔT : 0.084s Taille :3268 caractères /////////////////////////////////////
//Fonctions utilisées en cours de niveau
/////////////////////////////////////
function TesterFinNiveau
( e
: Event ) : void
{ //Teste si le niveau est terminé, ou si il est invalide.
//Fonctionne aussi quand le mode 2 joueurs est activé.
if ( Mode2Joueurs
)
Verifier_2Joueurs
( ) ;
else
{
if ( GrandPere.Ferme
)
TerminerNiveau
( 1 ) ;
//GAGNÉ !
else
{
if ( Fond.NbJetonsToleres
- Fond.NbJetonsUtilises
< 0 )
{ //PERDU
TerminerNiveau
( 0 ) ;
ChangeLevelInfo.
htmlText =
"<b>Trop de noeuds allumés !</b>" ;
}
}
}
}
/////////////////////////////////////
//Fonctions utilisées lors des changements de niveaux
/////////////////////////////////////
function TerminerNiveau
( Valeur
: int ) : void
{ //Termine un niveau en affichant la boite de changement
//Ajoute la valeur aux niveaux unlockés.
removeEventListener ( Event .
ENTER_FRAME ,TesterFinNiveau
) ;
Flouter
( Fond,
0 ,Fond.FLOU_FINAL
) ;
//Ajouter un flou
NumeroNiveauActuel
+ =Valeur;
if ( NumeroNiveauActuel
> NumeroNiveauUnlockes
&& Fond.Officiel==
true && NumeroNiveauActuel
< 12 )
{ //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é !" ;
}
//Puis afficher la boite avec la liste des niveaux.
UpdaterBoite
( ) ;
}
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 ( Fond
! =
null && contains ( Fond
) )
{ //Si Fond a déjà été utilisé, nettoyer l'ensemble
Fond.Nettoyer
( ) ;
removeChild ( Fond
) ;
}
//SwapBackGround();
Fond = GetLevelData
( NumNiveau
) ;
Fond.
graphics .
clear ( ) ;
//Supprimer le fond blanc
addChild ( Fond
) ;
//Repasser la boite de message au premier plan
setChildIndex ( Fond,
1 ) ;
Flouter
( Fond,Fond.FLOU_FINAL,
0 ) ;
//Déflouter
addEventListener ( Event .
ENTER_FRAME ,TesterFinNiveau
) ;
ChangeLevelInfo.
htmlText =
"<u>Liste des niveaux</u>" ;
}
////////////////////////////////////////
//Partie gérant les effets graphiques
////////////////////////////////////////
function Flouter
( Layer
: Niveau,Depart
: int ,Arrivee
: int ) : void
{
Layer.FlouFinal=Arrivee;
Layer.Flou=Depart;
Layer.
addEventListener ( Event .
ENTER_FRAME ,GererFlou
) ;
}
function GererFlou
( e
: Event ) : void
{ //Flouter le niveau en arrière plan
var Layer
: Object =e.
currentTarget ;
if ( Layer.Flou
! =Layer.FlouFinal
)
{
if ( Layer.Flou
< Layer.FlouFinal
)
Layer.Flou
+ =
2 ;
else
Layer.Flou
- =
2 ;
var FiltreFlou
: BitmapFilter =
new BlurFilter ( Layer.Flou,Layer.Flou
)
var ListeFiltres
: Array =
new Array ( ) ;
ListeFiltres.
push ( FiltreFlou
) ;
Layer.
filters =ListeFiltres;
if ( Layer.FlouFinal==
0 )
{
Boite.
alpha =
Math .
max ( 0 ,Layer.Flou
/ Layer.FLOU_FINAL
) ;
if ( Layer.Flou==
0 )
Boite.
visible =
false ;
}
else
{
Boite.
visible =
true ;
Boite.
alpha =
Math .
min ( 1 ,
2 * Layer.Flou
/ Layer.FlouFinal
) ;
}
}
else
{
Boite.
visible =
( Boite.alpha
> .
5 ) ;
Layer.
removeEventListener ( Event .
ENTER_FRAME ,GererFlou
) ;
}
}
Code source : ChargementNiveaux.as
Langage : actionscript3 ΔT : 0.179s Taille :7966 caractères /////////////////////////////////////
//Fonctions de création de niveau
/////////////////////////////////////
function GetLevelData
( Numero
: int ,Not_Mute
: Boolean =
true ) : Niveau
{
const NIVEAUX_JETONS
: Array =
new Array ( 3 ,
4 ,
5 ,
4 ,
5 ,
5 ,
3 ,
5 ,
6 ,
7 ,
5 ,
6 ) ;
var Hook
: Array =
new Array ( ) ;
//Vide la liste des Hook.
var Non_Extinctible
: Array =
new Array ( ) ;
//Vide la liste des Non_Extinctible.
var Niveau_datas
: Array ;
//Contient l'arborescence sous forme numérique
var Inutile
: Array =
null ;
//Evite de réecrire complètement un niveau lors de sa modification
var Message
: String =
"" ;
function T
( ...Liste
) : Array
{ //T comme Tableau
//Plus court à écrire que new Array() à chaque fois
return Liste;
}
if ( Numero==
0 )
{
Niveau_datas=
new Array ( null ,
null ,T
( 0 ,
1 ) ) ;
Message =
"<u>Règles d'A-graphe : <font size=\" -2\" ><i>(partie 1/3)</i></font></u><br><li><b>Règle n°1 : </b> Pour allumer un noeud (representé par un cercle), cliquer dessus.</li><li><b>Règle n°2 : </b> Pour terminer un niveau, allumer le noeud principal, centré en haut.</li><li><b>Règle n°3 : </b> Un noeud est allumable si et seulement si tous ses enfants (les noeuds qui descendent de lui) sont allumés.</li>" ;
}
else if ( Numero==
1 )
{
Niveau_datas=
new Array ( null ,
null ,
null ,T
( 0 ,
1 ,
2 ) ,
null ,
null ,T
( 4 ,
5 ) ,T
( 3 ,
6 ) ) ;
Message =
"<u>Règles d'A-graphe : <font size=\" -2\" ><i>(partie 2/3)</i></font></u><br><li><b>Règle n°4 : </b> Il est interdit d'allumer simultanément plus de noeuds que le nombre imparti pour chaque niveau (ce nombre est affiché en haut, à droite).</li><li><b>Règle n°5 : </b> Une fois un noeud allumé, on peut éteindre ses enfants sans que cela éteigne le parent.</li>" ;
}
else if ( Numero==
2 )
{
Niveau_datas=
new Array ( null ,
null ,T
( 0 ,
1 ) ,
null ,
null ,T
( 1 ,
3 ,
4 ) ,
null ,T
( 4 ,
6 ) ,
null ,T
( 8 ) ,T
( 9 ) ,T
( 2 ,
5 ,
7 ,
10 ) ) ;
Message =
"<u>Règles d'A-graphe : <font size=\" -2\" ><i>(partie 3/3)</i></font></u><br><li><b>Règle n°6 : </b> Un noeud allumé puis éteint ne peut pas être rallumé.</li><li><b>Règle n°7 : </b> Les noeuds marqués d'une croix ne peuvent pas être éteints.</li><br>Voilà, c'est tout pour les règles. Bonne chance !" ;
}
else if ( Numero==
3 )
Niveau_datas=
new Array ( null ,
null ,
null ,T
( 0 ) ,T
( 3 ,
2 ) ,T
( 1 ,
0 ) ,T
( 5 ,
0 ,
4 ) ) ;
else if ( Numero==
4 )
{
Niveau_datas=
new Array ( null ,
null ,
null ,T
( 0 ,
1 ,
2 ) ,
null ,
null ,T
( 4 ,
5 ) ,T
( 3 ,
6 ) ,
null ,
null ,T
( 8 ,
9 ) ,
null ,
null ,T
( 11 ,
12 ) ,
null ,
null ,T
( 14 ,
15 ) ,T
( 10 ,
13 ,
16 ) ,
null ,T
( 17 ,
18 ) ,T
( 7 ,
19 ) ) ;
}
else if ( Numero==
5 )
{
Niveau_datas=
new Array ( null ,
null ,
null ,T
( 0 ) ,T
( 0 ,
2 ) ,T
( 2 ) ,T
( 3 ,
4 ,
5 ) ,T
( 1 ) ,T
( 3 ,
4 ,
5 ) ,T
( 6 ,
7 ,
8 ) ) ;
Hook
[ 1 ] =
1 ;
Message =
"<li><b>Dernier niveau du tutorial.</b> Les choses vont rapidement se gâter ! Bonne chance pour la suite...</li><li>Un conseil avant de nous quitter : pensez à bien vérifier l'agencement des noeuds avant de commencer : certains sont un peu traîtres...</li>" ;
}
else if ( Numero==
6 )
{
Niveau_datas=
new Array ( null ,T
( 0 ) ,
null ,
null ,T
( 3 ) ,T
( 2 ,
3 ) ,T
( 4 ) ,T
( 5 ,
6 ) ,T
( 1 ,
7 ) ) ;
Hook
[ 3 ] =
-1 ;
}
else if ( Numero==
7 )
{
Niveau_datas=
new Array ( null ,T
( 0 ) ,T
( 0 ) ,T
( 0 ) ,T
( 1 ) ,T
( 1 ,
2 ) ,T
( 2 ,
3 ) ,T
( 3 ) ,T
( 4 ,
5 ) ,T
( 5 ,
6 ,
7 ) ,T
( 8 ) ,
null ,T
( 9 ,
11 ) ,T
( 10 ) ,T
( 12 ) ,T
( 13 ,
14 ) ,T
( 13 ,
15 ) ,T
( 14 ,
11 ,
7 ) ,T
( 16 ,
15 ,
17 ) ) ;
//Hook[15]=-1;
Non_Extinctible
[ 7 ] =
true ;
}
else if ( Numero==
8 )
{
Niveau_datas=
new Array ( null ,T
( 0 ) ,
null ,T
( 0 ,
2 ) ,T
( 1 ) ,T
( 4 ) ,T
( 1 ,
0 ) ,T
( 3 ,
2 ) ,T
( 5 ,
4 ) ,
null ,
null ,
null ,T
( 9 ,
10 ) ,T
( 10 ,
11 ) ,T
( 12 ) ,T
( 13 ) ,T
( 14 ) ,T
( 15 ) ,T
( 12 ) ,T
( 13 ) ,T
( 10 ) ,T
( 16 ,
18 ,
20 ,
19 ,
17 ) ,T
( 6 ,
7 ,
8 ) ,T
( 21 ,
22 ) ) ;
}
else if ( Numero==
9 )
Niveau_datas=
new Array ( null ,T
( 0 ) ,T
( 0 ) ,T
( 1 ) ,T
( 1 ,
0 ) ,T
( 2 ,
0 ) ,T
( 2 ) ,T
( 3 ) ,T
( 3 ,
1 ,
4 ) ,T
( 5 ,
6 ) ,T
( 6 ) ,T
( 7 ,
3 ,
8 ) ,T
( 9 ,
10 ) ,T
( 11 ,
8 ,
4 ,
5 ,
9 ,
12 ) ) ;
else if ( Numero==
10 )
Niveau_datas=
new Array ( null ,
null ,
null ,
null ,T
( 0 ,
1 ) ,T
( 2 ,
3 ) ,T
( 4 ) ,T
( 4 ) ,T
( 5 ) ,T
( 5 ) ,T
( 6 ) ,T
( 6 ,
7 ) ,T
( 7 ) ,T
( 8 ) ,T
( 9 ) ,T
( 10 ,
11 ,
12 ) ,T
( 13 ,
14 ) ,T
( 15 ) ,T
( 15 ,
16 ) ,T
( 16 ) ,
null ,
null ,
null ,
null ,
null ,T
( 22 ,
20 ,
23 ) ,T
( 23 ,
21 ,
24 ) ,T
( 25 ,
26 ) ,T
( 17 ,
18 ) ,T
( 18 ,
19 ) ,T
( 28 ,
29 ) ,T
( 30 ,
27 ) ) ;
else if ( Numero==
11 )
{
Niveau_datas=
new Array ( null ,T
( 0 ) ,T
( 0 ) ,T
( 0 ) ,T
( 1 ,
0 ) ,T
( 1 ,
0 ,
2 ) ,T
( 1 ,
2 ,
3 ) ,T
( 4 ,
5 ,
6 ) ,T
( 5 ,
0 ,
6 ) ,T
( 0 ,
6 ) ,
null ,
null ,T
( 10 ) ,T
( 11 ) ,T
( 13 ,
11 ) ,
null ,
null ,
null ,
null ,
null ,T
( 12 ) ,T
( 14 ) ,T
( 13 ,
20 ) ,T
( 15 ,
16 ,
17 ,
18 ) ,T
( 19 ,
12 ,
10 ) ,T
( 21 ,
20 ) ,T
( 22 ,
23 ,
24 ) ,T
( 25 ) ,T
( 25 ) ,T
( 26 ,
27 ) ,T
( 27 ) ,T
( 28 ) ,T
( 29 ) ,T
( 29 ,
30 ) ,T
( 0 ,
6 ,
31 ,
32 ,
33 ) ,T
( 7 ,
8 ,
34 ) ) ;
Message=
"<u>Dernier niveau</u><br>Je vous souhaiterais bien bonne chance, mais je crains que cela ne suffise pas ;-)" ;
}
if ( Message
! =
"" && Not_Mute
&& ! Mode2Joueurs
)
ShowMessage
( Message
) ;
if ( Mode2Joueurs
)
ShowMessage
( "<u>Niveau en mode 2 Joueurs</u><li>Les informations du niveau sont affichées en haut, à droite.</li><li>N'oubliez pas que vous pouvez éteindre des noeuds ! Votre tour ne se finit que quand vous en allumez un.</li>" ) ;
return LoadNiveau
( Niveau_datas,Numero.
toString ( ) ,NIVEAUX_JETONS
[ Numero
] ,Hook,Non_Extinctible
) ;
}
function String2Level
( Niv_String
: String ,Titre
: String =
"Mon niveau perso" ,NbJetons
: int =
5 ) : Niveau
{ //Crée un niveau à partir d'un string.
//Utilisé en mode 2 joueurs, mais aussi lors de la résolution automatique d'un niveau.
var Hook
: Array =
new Array ( ) ;
//Vide la liste des Hook.
var Non_Extinctible
: Array =
new Array ( ) ;
//Vide la liste des Non_Extinctible.
var Allumes
: Array =
new Array ( ) ;
var DejaAllumes
: Array =
new Array ( ) ;
var i
: int =
0 ;
var Niv_Array
: Array =Niv_String.
split ( "," ) ;
function ReplaceNullItem
( T
: Array ) : void
{
if ( T.length
> 1 )
{
for ( var j
: int =
0 ;j
< T.
length ;j
++ )
{ //On ne peut pas utiliser for each, car String est un type primitif : on agirait sur une copie de l'objet.
if ( T
[ j
] ==
"null" )
T
[ j
] =
null ;
}
}
}
for ( i=
0 ;i
< Niv_Array.
length ;i
++ )
{ //Trouver les Hook, les allumés et les non exctinctibles.
if ( Niv_Array
[ i
] ! =Niv_Array
[ i
] .
replace ( "X" ,
"" ) )
{ //ajouter NonExtinctible
Niv_Array
[ i
] =Niv_Array
[ i
] .
replace ( "X" ,
"" ) ;
Non_Extinctible
[ i
] =
true ;
}
if ( Niv_Array
[ i
] ! =Niv_Array
[ i
] .
replace ( "@" ,
"" ) )
{ //ajouter NonExtinctible
Niv_Array
[ i
] =Niv_Array
[ i
] .
replace ( "@" ,
"" ) ;
Allumes
[ i
] =
true ;
}
if ( Niv_Array
[ i
] ! =Niv_Array
[ i
] .
replace ( "-" ,
"" ) )
{ //ajouter un Hook
Niv_Array
[ i
] =Niv_Array
[ i
] .
replace ( "-" ,
"" ) ;
Hook
[ i
] =
-1 ;
}
if ( Niv_Array
[ i
] ! =Niv_Array
[ i
] .
replace ( "+" ,
"" ) )
{ //ajouter un Hook
Niv_Array
[ i
] =Niv_Array
[ i
] .
replace ( "+" ,
"" ) ;
Hook
[ i
] =
1 ;
}
if ( Niv_Array
[ i
] ! =Niv_Array
[ i
] .
replace ( "!" ,
"" ) )
{ //ajouter un Hook
Niv_Array
[ i
] =Niv_Array
[ i
] .
replace ( "!" ,
"" ) ;
DejaAllumes
[ i
] =
true ;
}
}
//Remplacer "null" par...le vrai null
ReplaceNullItem
( Niv_Array
) ;
for ( i=
0 ;i
< Niv_Array.
length ;i
++ )
{ //On ne peut pas utiliser for each, car String est un type primitif
if ( Niv_Array
[ i
] ! =
null && Niv_Array
[ i
] .
indexOf ( "/" ) ! =
-1 )
{
Niv_Array
[ i
] =Niv_Array
[ i
] .
split ( "/" ) ;
Niv_Array
[ i
] .
pop ( ) ;
//Supprimer le dernier item, qui est null
ReplaceNullItem
( Niv_Array
[ i
] ) ;
}
}
return LoadNiveau
( Niv_Array,Titre,NbJetons,Hook,Non_Extinctible,Allumes,DejaAllumes
) ;
}
function ChargementNiveauDirect
( e
: Event ) : void
{ //Triggeré quand clic sur une des miniatures dans Boite.
while ( Boite.
numChildren > 0 )
Boite.
removeChildAt ( 0 ) ;
Boite.
addChild ( ChangeLevelInfo
) ;
ChangeLevelInfo.
htmlText =
"<u>Chargement en cours</u> (niv. <b>" + e.
currentTarget .NumeroNiveau
+ "</b>)" ;
if ( e.
currentTarget .Officiel
)
{
NumeroNiveauActuel=e.
currentTarget .NumeroNiveau;
LancerNouveauNiveau
( e.
currentTarget .NumeroNiveau
) ;
}
else
LancerChargement
( ) ;
}
function LoadNiveau
( Level
: Array ,NumNiveau
: String ,NBJetons
: int ,Hook
: Array ,Non_Extinctible
: Array ,Allumes
: Array =
null ,DejaAllumes
: Array =
null ) : Niveau
{ //La fonction principale, qui charge le niveau dans un sprite
var Layer
: Niveau;
//Layer est le Sprite qui doit contenir le niveau
if ( Allumes==
null )
Allumes=
new Array ( ) ;
if ( DejaAllumes==
null )
DejaAllumes=
new Array ( ) ;
Layer=
new Niveau
( NumNiveau,Level,Hook,Non_Extinctible,Allumes,DejaAllumes,NBJetons,FlashHeight,FlashWidth,Mode2Joueurs
) ;
GrandPere=Layer.All_Noeuds
[ Level.
length -1 ] ;
//Puis régler les positions Y.
//Pour cela, il faut d'abord trouver le nombre d'imbrications.
//Facile ! Il suffit d'appeler GrandPere.Profondeur(), qui est récursive.
GrandPere.GererXY
( 1 ,GrandPere.Profondeur
( ) ,FlashWidth
-20 ,FlashWidth
/ 2 -10 ) ;
GrandPere.RecreerArbreLien
( ) ;
Layer.CreerArbreParents
( GrandPere
) ;
return Layer;
}
Code source : Message.as
Langage : actionscript3 ΔT : 0.169s Taille :7918 caractères
//Déclaration des Sprites
var Boite
: 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 ( ) ;
var LVL_En_Cours
: Niveau;
var LVL_Edit
: Niveau=
null ;
//Remplissage des Sprites
Message_Container.
graphics .
beginFill ( 0x444444
) ;
Message_Container.
graphics .
lineStyle ( 2 ,0x000000
) ;
Message_Container.
graphics .
drawRect ( 0 ,
0 ,
440 ,
140 ) ;
Message_Container.
x =
100 ;
Message_Container.
y =
160 ;
Message_Container.
visible =
false ;
Message_Container.
alpha =.
8 ;
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
) ;
Boite.
graphics .
beginFill ( 0xCCCCCC
) ;
Boite.
graphics .
lineStyle ( 1 ,0x000000
) ;
Boite.
graphics .
drawRect ( 0 ,
0 ,
240 ,
180 ) ;
Boite.
x =
50 ;
Boite.
y =
50 ;
Boite.
width =FlashWidth
-100 ;
Boite.
height =FlashHeight
-100 ;
Boite.
visible =
false ;
addChild ( Boite
) ;
AppliquerFiltre
( 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 ,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 .
beginFill ( 0xCCCCCC
) ;
Neamar_Sprite.
graphics .
drawRect ( 0 ,
0 ,
640 ,
480 ) ;
Neamar_Sprite.
graphics .
endFill ( ) ;
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
) ;
//Lien vers http://www.mini-jeu-gratuit.fr/
var SpriteSponsor
: Sprite =
new Sprite ( ) ;
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 ( ) ;
LevelChangeButtonSprite.
graphics .
beginFill ( 0x7F7FB3
) ;
LevelChangeButtonSprite.
graphics .
lineStyle ( 1 ,0x000000
) ;
LevelChangeButtonSprite.
graphics .
drawCircle ( 75 ,
75 ,
75 )
LevelChangeButtonSprite.
graphics .
endFill ( ) ;
LevelChangeButtonSprite.
graphics .
lineStyle ( 10 ,0xFF0000
) ;
LevelChangeButtonSprite.
graphics .
moveTo ( 33 ,
33 ) ;
LevelChangeButtonSprite.
graphics .
lineTo ( 116 ,
75 ) ;
LevelChangeButtonSprite.
graphics .
lineTo ( 33 ,
117 ) ;
LevelChangeButtonSprite.
rotation =Angle;
LevelChangeButtonSprite.
alpha =
1 ;
LevelChangeButtonSprite.
addEventListener ( MouseEvent .
MOUSE_MOVE ,SourisIN
) ;
LevelChangeButtonSprite.
addEventListener ( MouseEvent .
MOUSE_OUT ,SourisOUT
) ;
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
( ) : void
{
function Afficher
( Image
: Niveau,Empl
: int ) : void
{
Boite.
addChild ( Image
) ;
Image.
scaleX =Image.
scaleY =
0.07 ;
Image.
x =
15 + ( Empl
% 4 ) * Ecart;
Image.
addEventListener ( MouseEvent .
MOUSE_OVER ,SourisIN
) ;
Image.
addEventListener ( MouseEvent .
MOUSE_OVER ,AfficherInfos
) ;
Image.
addEventListener ( MouseEvent .
MOUSE_OUT ,SourisOUT
) ;
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 =Boite.
width / 10 ;
for ( var i
: int =
0 ;i
< =NumeroNiveauUnlockes;i
++ )
{
var ThumbShot
: Niveau=GetLevelData
( i,
false ) ;
//true indique qu'il ne faut pas afficher les messages;
Afficher
( ThumbShot,i
) ;
Boite.
addChild ( ThumbShot
) ;
if ( i==NumeroNiveauActuel
)
AppliquerFiltre
( ThumbShot,0x7F7FB3
)
}
if ( LVL_Edit
! =
null ) //LVL_Edit est mis à jour lors du chargement d'un niveau perso
Afficher
( LVL_Edit,
14 ) ;
else
{
Boite.
addChild ( SpriteSponsor
) ;
SpriteSponsor.
x =
15 +2 * Ecart;
SpriteSponsor.
y =
20 +3 * Ecart
/ 1.3 ;
SpriteSponsor.
filters =
new Array ( new BevelFilter ( 7 ,
90 ,0x7F7F00,
1 ,0x000000,
1 ,
10 ,
4 ,
10 ) ) ;
}
Boite.
addChild ( Annuler_Choix
) ;
Annuler_Choix.
y =
16 ;
Annuler_Choix.
x =
16 ;
Boite.
addChild ( ChangeLevelInfo
) ;
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 ;
}
function AfficherInfos
( e
: Event ) : void
{
ChangeLevelInfo.
htmlText =
"Charger le niveau <b>" + e.
currentTarget .NumeroNiveau
+ "</b>" ;
if ( e.
currentTarget .NumeroNiveau==NumeroNiveauUnlockes
)
ChangeLevelInfo.
htmlText =
"Dernier niveau débloqué : <b>" + e.
currentTarget .NumeroNiveau
+ "</b>" ;
if ( e.
currentTarget .NumeroNiveau==NumeroNiveauActuel
)
{
ChangeLevelInfo.
htmlText =
"Dernier niveau tenté : <b>" + e.
currentTarget .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/AGraphe/\" target=\" _blank\" >http://neamar.fr/Res/AGraphe (click to go)</a></li>" ) ;
}
function Annuler
( e
: Event ) : void
{
Flouter
( Fond,Fond.FLOU_FINAL,
0 ) ;
//Déflouter
GrandPere=Fond.All_Noeuds
[ Fond.All_Noeuds.
length -1 ] ;
//Remettre le bon GrandPere !
addEventListener ( Event .
ENTER_FRAME ,TesterFinNiveau
) ;
} Fichiers de mod
Code source : 2Joueurs.as
Langage : actionscript3 ΔT : 0.051s Taille :2065 caractères
//Les variables utiles :
var Mode2Joueurs
: Boolean =
false ;
var SVGNbJetons
: int =
-1 ;
var TourDuJoueur
: int =
1 ;
//Les sprites du Mods
var Sprite2Joueurs
: Sprite =
new Sprite ( ) ;
var Mods_2Joueurs
: TextField =CreerTextField
( Sprite2Joueurs,
0 ,
0 ,
180 ,
25 ,
true ,
false ,
false ) ;
Mods_2Joueurs.
htmlText =
"<li>Activer le mode \" 2 Joueurs\" </li>" ;
Sprite2Joueurs.
scaleX =Sprite2Joueurs.
scaleY =
0.4 ;
Mods.
addChild ( Sprite2Joueurs
) ;
Sprite2Joueurs.
addEventListener ( MouseEvent .
MOUSE_OVER ,SourisIN
) ;
Sprite2Joueurs.
addEventListener ( MouseEvent .
MOUSE_OUT ,SourisOUT
) ;
Sprite2Joueurs.
addEventListener ( MouseEvent .
CLICK ,SwapMode
) ;
function SwapMode
( e
: Event ) : void
{ //passe du mode 1 joueur au mode 2 joueurs et vice versa
Mode2Joueurs=
! Mode2Joueurs;
UpdaterBoite
( ) ;
if ( Mode2Joueurs
)
{
Mods_2Joueurs.
htmlText =
"<li>Désactiver le mode \" 2 Joueurs\" </li>" ;
ShowMessage
( "<u>Mode 2 Joueurs</u> : Le mode 2 Joueurs se joue sur les mêmes niveaux que le mode normal. En voici les règles :<li>Chacun votre tour, il faut allumer un noeud. Avant d'allumer un noeud, vous pouvez en éteindre autant que vous le souhaitez ;</li><li>Le perdant est celui qui ne peut plus allumer de noeuds.</li>Les règles sont simples, à vous de bloquer l'adversaire !<br>Que le meilleur gagne..." ) ;
}
else
Mods_2Joueurs.
htmlText =
"<li>Activer le mode \" 2 Joueurs\" </li>" ;
if ( contains ( Fond
) )
removeChild ( Fond
) ;
}
function Verifier_2Joueurs
( ) : void
{ //Changmeent de tours, et vérification pour savoir si la partie est terminée
var NbNoeudsPossible
: int ;
if ( SVGNbJetons
< Fond.NbJetonsUtilises
)
TourDuJoueur=
( TourDuJoueur
+1 ) % 2 ;
//Tester si gagné ou perdu :
NbNoeudsPossible=
0 ;
for each ( var Enfant
: Noeud
in Fond.All_Noeuds
)
{ //Vérifier que tous les enfants sont bien fermés
if ( Enfant.Peut_Etre_Allume
( ) )
NbNoeudsPossible
++ ;
}
if ( NbNoeudsPossible==
0 )
Fond.Informations.
htmlText =
"<b>Joueur " + ( TourDuJoueur
+1 ) + " a perdu !</b>" ;
else
Fond.Informations.
htmlText =
"Tour de Joueur <b>" + ( TourDuJoueur
+1 ) + "</b> (" + NbNoeudsPossible
+ " choix)" ;
//Mettre à jour la sauvegarde
SVGNbJetons=Fond.NbJetonsUtilises;
}
Code source : Persos.as
Langage : actionscript3 ΔT : 0.061s Taille :3501 caractères //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</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 ,
110 ,
360 ,
20 ,
false ,
true ) ;
LoadLevelTexte.
type =
"input" ;
LoadLevelTexte.
restrict =
"null,/@+-X0-9" ;
LoadLevelTexte.
text =
"null,null,0/1/,2/,null,null,4/5/,3/6/" ;
var LoadLevelNb_Jetons
: TextField = CreerTextField
( LoadLevel,
390 ,
110 ,
20 ,
20 ,
false ,
true ) ;
LoadLevelNb_Jetons.
type =
"input" ;
LoadLevelNb_Jetons.
restrict =
"0-9" ;
LoadLevelNb_Jetons.
text =
"4" ;
var LoadLevelCaption
: TextField = CreerTextField
( LoadLevel,
20 ,
10 ,
400 ,
100 ,
true ,
true ,
false ) ;
var Lancer_Level
: Sprite =LevelChangeButton
( 0 ) ;
Lancer_Level.
scaleX =Lancer_Level.
scaleY =.
3 ;
Lancer_Level.
x =
420 ;
Lancer_Level.
y =
90 ;
Lancer_Level.
addEventListener ( MouseEvent .
CLICK ,LancerChargement
) ;
LoadLevel.
addChild ( Lancer_Level
) ;
AppliquerFiltre
( LoadLevel
) ;
LoadLevelCaption.
htmlText =
"<i>(Utilisez la roulette de la souris pour faire défiler le texte)<br>(<a href=\" http://neamar.fr/Res/AGraphe#Createur\" target=\" _blank\" >http://neamar.fr/Res/AGraphe#Createur pour un tutorial plus clair</a>)<br><u>Éditeur de niveau</u><br>Un niveau est une simple chaine de caractères, les virgules délimitant des intervalles contenant un noeud chacun.<br>Un noeud sans enfant est noté null. Ainsi, pour réaliser un niveau avec un unique noeud, il faut simplement marquer <u>null</u> dans le champ de texte.<br>Pour les parents, il faut marquer le numéro d'intervalle des noeuds enfants, séparés par un / (slash). Ainsi, le premier niveau du jeu se code très simplement de la façon suivante : <u>null,null,0/1/</u> : deux enfants, et un parent qui réunit les deux.<br><b>Attention</b> : N'oubliez pas de mettre un slash à la fin de la liste !<br>Quelques astuces pour aller plus loin :<li>Vous pouvez marquer un noeud comme inextinctible en placant un X dans la liste : <u>nullX,null,0/1/X</u></li><li>Vous pouvez décaler l'affichage d'un noeud à l'aide de hook : + et -. Cela force l'affichage du noeud un cran plus haut (ou un cran moins haut). Par exemple, <u>null,null,0/1/+</u> affiche un niveau «en ligne».</li>" ;
addChild ( LoadLevel
) ;
function ShowLoadLevel
( e
: Event ) : void
{
LoadLevel.
visible =
true ;
Boite.
visible =
false ;
}
function LancerChargement
( e
: Event =
null ) : void
{
LoadLevel.
visible =
false ;
Boite.
visible =
false ;
Fond.
filters =
new Array ( ) ;
if ( contains ( Fond
) )
removeChild ( Fond
) ;
Fond=String2Level
( LoadLevelTexte.
text ,
"Niveau Perso" ,LoadLevelNb_Jetons.
text ) ;
Fond.Officiel=
false ;
addChild ( Fond
) ;
Fond.
graphics .
clear ( ) ;
//Repasser la boite de message au premier plan...c'est plus pratique pour la lire :-)
setChildIndex ( Fond,
1 ) ;
addEventListener ( Event .
ENTER_FRAME ,TesterFinNiveau
) ;
//Mettre à jour la preview
LVL_Edit=String2Level
( LoadLevelTexte.
text ,
"Édition Actuelle" ,LoadLevelNb_Jetons.
text ) ;
LVL_Edit.Officiel=
false ;
// Trace("Nb :"+SolveLevel(Fond));
}
Classes
Code source : Niveau.as
Langage : actionscript3 ΔT : 0.121s Taille :5069 caractères //Un niveau standard : contient des liens et des noeuds !
package
{
import flash.display .
Sprite ;
import flash.geom .
Point ;
import flash.display .
Shape ;
import flash.events .
* ;
import flash.text .
TextField ;
public class Niveau extends
Sprite
{
public var All_Noeuds
: Array ;
//Contient l'arborescence sous forme de noeuds graphiques
public var NbJetonsUtilises
: int ;
public var NbJetonsToleres
: int ;
public var NumeroNiveau
: String ;
public var Mode2Joueurs
: Boolean ;
public var Informations
: TextField =
new TextField ( ) ;
public var Flou
: int =
0 ;
//Le niveau de flou du Fond actuel
public const FLOU_FINAL
: int =
32 ;
//Le niveau maximal de Flou, une constante.
public var FlouFinal
: int =FLOU_FINAL;
//Le niveau final de flou demandé pour Fond.
public var Officiel
: Boolean =
true ;
private var JetonsUtilises
: Array ;
private var Layer
: Sprite ;
private var GrandPere
: Noeud;
private var Niveau_Chiffre
: Array ;
public function Niveau
( NumeroNiveau
: String ,Niveau
: Array ,Hook
: Array ,Non_Extinctible
: Array ,Allumes
: Array , DejaAllumes
: Array , NbJetonsToleres
: int , Hauteur
: int ,Largeur
: int ,Mode2Joueurs
: Boolean )
{
this .All_Noeuds =
new Array ( ) ;
this .NbJetonsToleres=NbJetonsToleres;
this .JetonsUtilises=
new Array ( ) ;
this .NumeroNiveau=NumeroNiveau;
this .Mode2Joueurs=Mode2Joueurs;
this .Niveau_Chiffre=Niveau;
var Enfants
: Array ;
var i
: int ;
All_Noeuds=
new Array ( Niveau.
length ) ;
for ( i=
0 ;i
< Niveau.
length ;i
++ )
{
if ( Niveau
[ i
] ! =
null )
{
Enfants=
new Array ( ) ;
for each ( var Enfant
: int in Niveau
[ i
] )
{
Enfants.
push ( All_Noeuds
[ Enfant
] ) ;
}
All_Noeuds
[ i
] =AjoutNoeud
( Enfants
)
}
else
All_Noeuds
[ i
] =AjoutNoeud
( null ) ;
}
//Les options supplémentaires:
//Hook
//Inextinguible
i=
0 ;
for each ( var Child
: Noeud
in All_Noeuds
)
{
if ( Hook
[ i
] ==
null )
Hook
[ i
] =
0 ;
if ( Non_Extinctible
[ i
] ==
null )
Non_Extinctible
[ i
] =
false ;
Child.addHook
( Hook
[ i
] ) ;
Child.Is_Not_Eteignable
( Non_Extinctible
[ i
] ) ;
if ( Allumes
[ i
] ==
true )
Child.ChangeState
( true ,
false ) ;
if ( DejaAllumes
[ i
] ==
true )
Child.aEteFerme=
true ;
i
++ ;
}
//Nombre de jetons utilisables
for ( i=
0 ;i
< NbJetonsToleres;i
++ )
{
JetonsUtilises
[ i
] =
new Noeud
( new Array ( ) ,
this ) ;
if ( ! Mode2Joueurs
)
this .
addChild ( JetonsUtilises
[ i
] ) ;
JetonsUtilises
[ i
] .
x =Largeur
- ( i
+1 ) * 25 ;
JetonsUtilises
[ i
] .
y =
15 ;
JetonsUtilises
[ i
] .
scaleX =JetonsUtilises
[ i
] .
scaleY =.
5 ;
}
Informations.
x =
500 ;
Informations.
y =
0 ;
Informations.
width =
150 ;
Informations.
height =
20 ;
Informations.
background =
true ;
Informations.
border =
true ;
Informations.
selectable =
false ;
if ( Mode2Joueurs
)
addChild ( Informations
) ;
this .
graphics .
beginFill ( 0xFFFFFF
) ;
this .
graphics .
drawRect ( 0 ,
0 , Largeur, Hauteur
) ;
GrandPere=
this .All_Noeuds
[ All_Noeuds.
length -1 ] ;
UpdateNbJetons
( ) ;
//Si des noeuds sont allumés dès le départ, les compter
}
public function CreerArbreParents
( NoeudActuel
: Noeud
) : void
{
for each ( var Child
: Noeud
in NoeudActuel.Enfants
)
{ //Smells like recursivity again ;-)
Child.addParent
( NoeudActuel
) ;
CreerArbreParents
( Child
) ;
}
}
public function UpdateNbJetons
( ) : void
{
var Comparaison
: Boolean ;
var Nb
: int =
0 ;
for each ( var Child
: Noeud
in All_Noeuds
)
{
if ( Child.Ferme==
true )
Nb
++ ;
}
this .NbJetonsUtilises=Nb;
for ( var i
: int =
0 ;i
< this.NbJetonsToleres;i
++ )
{
Comparaison=
( i
< this.NbJetonsUtilises
) ;
JetonsUtilises
[ i
] .ChangeState
( Comparaison,
false ) ;
//Ne pas mettre à jour, sinon on a une réference infinie et stack overflow
if ( Comparaison
)
JetonsUtilises
[ i
] .
scaleX =JetonsUtilises
[ i
] .
scaleY =.
7 ;
else
JetonsUtilises
[ i
] .
scaleX =JetonsUtilises
[ i
] .
scaleY =.
5 ;
}
}
public function Niveau2String
( ) : String
{ //Renvoyer le niveau actuel sous la forme d'un string
var Level
: String =
"" ;
for ( var i
: int =
0 ;i
< Niveau_Chiffre.
length ;i
++ )
{
var Child
: Array =Niveau_Chiffre
[ i
] ;
if ( Child==
null )
Level
+ =
"null" ;
else
{
for each ( var BiChild
: int in Child
)
{
Level
+ =BiChild.
toString ( ) + "/" ;
}
}
if ( this .All_Noeuds
[ i
] .Ferme==
true )
Level
+ =
"@" ;
if ( this .All_Noeuds
[ i
] .Peut_Eteint==
false )
Level
+ =
"X" ;
if ( this .All_Noeuds
[ i
] .Hook_Y==
-1 )
Level
+ =
"-" ;
if ( this .All_Noeuds
[ i
] .Hook_Y==
1 )
Level
+ =
"+" ;
if ( this .All_Noeuds
[ i
] .aEteFerme==
true )
Level
+ =
"!" ;
Level
+ =
"," ;
}
Level=Level.
slice ( 0 ,Level.
length -1 ) ;
return Level;
}
public function Nettoyer
( ) : void
{
//Nettoyer le niveau
GrandPere.DeleteYourself
( ) ;
All_Noeuds=
new Array ( ) ;
//Il y a un bug qui empêche la suppression des liens, donc on les vire manuellement.
while ( this .
numChildren > 0 )
{
this .
removeChildAt ( 0 ) ;
}
}
private function AjoutNoeud
( Enfants
: Array =
null ) : Noeud
{ //Ajoute un noeud en mémoire, et retourne son occurence
if ( Enfants==
null )
Enfants=
new Array ( ) ;
var NouveauNoeud
: Noeud=
new Noeud
( Enfants,
this ) ;
this .
addChild ( NouveauNoeud
) ;
NouveauNoeud.
x =NouveauNoeud.
y =
-20
return NouveauNoeud
}
}
}
Code source : Noeud.as
Langage : actionscript3 ΔT : 0.204s Taille :8250 caractères //Un noeud quelconque
package
{
import flash.display .
Sprite ;
import flash.geom .
Point ;
import flash.events .
* ;
import flash.filters .
BitmapFilter ;
import flash.filters .
GlowFilter ;
public class Noeud extends
Sprite
{
public var Enfants
: Array ;
//La liste des enfants
public var Parents
: Array ;
//idem pour les parents
public var Ferme
: Boolean ;
//Si le noeud est allumé, Ferme vaut true
public var Hook_Y
: int ;
public var Peut_Eteint
: Boolean ;
//Les noeuds avec une croix à l'intérieur ont Peut_Eteint=false
public var aEteFerme
: Boolean ;
//Le noeud a déjà été allumé
private const RAYON
: int =
15 ;
private var Layer
: Niveau;
//Le sprite conteneur
private var Arc_Liste
: Array =
new Array ( ) ;
//La liste des liens vers les enfants
private var Final_Glow
: int ;
//Le rayonnement du noeud
private var Current_Glow
: Number ;
//La valeur de rayonnement désirée
private var NbPlacements
: int ;
//Le nombre de fois que le noeud a été placé
private const
PI : Number =
3.141 ;
//...
public function Noeud
( Enfants
: Array ,Layer
: Niveau
)
{ //Instancie un nouveau noeud
this .Enfants = Enfants;
this .Parents=
new Array ( ) ;
this .Ferme=
false ;
this .aEteFerme=
false ;
this .Layer=Layer;
this .Final_Glow=
this .Current_Glow=
0 ;
this .NbPlacements=
0 ;
//Le nombre de fois que le noeud a été déplacé dans l'arbre, cf. fonction GererXY.
this .Hook_Y=
0 ;
this .Peut_Eteint=
true ;
this .
graphics .
beginFill ( 0xEEEEEE
) ;
this .
graphics .
lineStyle ( 1 ,0x000000
) ;
this .
graphics .
drawCircle ( 0 ,
0 , RAYON
) ;
this .
addEventListener ( MouseEvent .
MOUSE_MOVE ,SourisIN
) ;
this .
addEventListener ( MouseEvent .
MOUSE_OUT ,SourisOUT
) ;
this .
addEventListener ( MouseEvent .
CLICK ,SourisClick
) ;
RecreerArbreLien
( ) ;
}
public function RecreerArbreLien
( ) : void
{ //Recrée l'ensemble des liens
//D'abord les supprimer proprement
RemoveLiens
( ) ;
var Lien
: Arc;
//Et refaire l'ensemble
for each ( var Child
: Noeud
in Enfants
)
{
Lien=
new Arc
( new Point ( this .
x ,
this .
y ) ,
new Point ( Child.
x ,Child.
y ) ) ;
Arc_Liste.
push ( Lien
) ;
Layer.
addChild ( Lien
) ;
Layer.
setChildIndex ( Lien,
0 ) ;
//Ne pas oublier d'informer l'enfant que l'on a refait l'arbre :
Child.RecreerArbreLien
( ) ;
}
}
public function Profondeur
( ) : int
{ //Renvoie la profondeur de l'objet, i.e le nombre maximal de sous enfants disponibles.
//Utilise la récursivité en faisant appel à ses enfants.
var Max
: uint =
0 ;
if ( this .Enfants.
length ==
0 )
return 1 ;
else
{
for each ( var Child
: Noeud
in Enfants
)
{
Max=
Math .
max ( Max,Child.Profondeur
( ) ) ;
}
return 1 + Max;
}
}
public function addParent
( Parent
: Noeud
) : void
{ //Ajoute un parent au noeud
this .Parents.
push ( Parent
) ;
}
public function AddFocus
( Level
: int ) : void
{ //Ajoute un flou à la forme.
for each ( var Enfant
: Noeud
in Enfants
)
{ //Demande aux enfants d'afficher un flou aussi, mais un peu plus faible
Enfant.AddFocus
( Math .
max ( 0 ,Level
-1 ) ) ;
}
//Puis lancer l'animation
this .Final_Glow=Level;
this .
addEventListener ( Event .
ENTER_FRAME ,ChangeFiltre
) ;
}
public function addHook
( Level
: int ) : void
{
this .Hook_Y=Level;
}
public function Is_Not_Eteignable
( Valeur
: Boolean ) : void
{
this .Peut_Eteint=
! Valeur;
if ( Valeur==
true )
{
this .
graphics .
moveTo ( - RAYON
* Math .
sin ( PI / 4 ) ,
- RAYON
* Math .
sin ( PI / 4 ) ) ;
this .
graphics .
lineTo ( RAYON
* Math .
sin ( PI / 4 ) ,RAYON
* Math .
sin ( PI / 4 ) ) ;
this .
graphics .
moveTo ( - RAYON
* Math .
sin ( PI / 4 ) ,RAYON
* Math .
sin ( PI / 4 ) ) ;
this .
graphics .
lineTo ( RAYON
* Math .
sin ( PI / 4 ) ,
- RAYON
* Math .
sin ( PI / 4 ) ) ;
}
}
public function GererXY
( NiveauActuel
: int ,NiveauMax
: int ,Largeur
: int ,Position
: int ) : void
{ //Cette fonction a pour but de gérer l'agencement des noeuds dans le graphe.
//Le noeud recoit des ordres : sa position y est determinée par son imbrication
//Sa position X est determinée par la variable Position.
//Largeur lui indique que tous ses enfants devront être dans un rectangle de Position-Largeur/2 à Position+Largeur/2.
var Child
: Noeud;
//Pour les boucles!
var FutureLargeur
: Number =Largeur
/ this .Enfants.
length ;
var i
: int =
0 ;
var YDemande
: int =
20 +400 * ( NiveauActuel
-1 ) / ( NiveauMax
-1 ) ;
//Le niveau Y des enfants
var DecalageYHook
: int =
400 / ( NiveauMax
-1 ) ;
//Une valeur de décalage de Y
var PositionInitialeXEnfants
: int =Position
- Largeur
/ 2 ;
this .NbPlacements
++ ;
//Nombre de fois que l'on place le noeud. Si on le place plusieurs fois, il faut le centrer de façon à ce qu'il soit bien, et pour cela on a besoin d ela moyenne, donc du nombre de déplacements à prendre en compte.
this .
x =
( Position
+ ( this .NbPlacements
-1 ) * this .
x ) / this .NbPlacements;
//Si il a déjà été placé auparavant, on le centre : un simple calcul de moyenne avec pondération.
this .
y =
Math .
max ( this .
y ,YDemande
) + this .Hook_Y
* DecalageYHook;
//Sile noeud a déjà été placé, ne conserver que le y le plus élevé. Ajouter le Hook si besoin.
for each ( Child
in this .Enfants
)
{ //Smells like recursivity again ;-)
i
++ ;
Child.GererXY
( NiveauActuel
+1 ,NiveauMax,FutureLargeur,PositionInitialeXEnfants
+ ( i
- .
5 ) * FutureLargeur
) ;
}
}
public function Peut_Etre_Allume
( ) : Boolean
{ //Ce noeud est il allumable ?
var unEnfantOuvert
: Boolean =
false ;
for each ( var Enfant
: Noeud
in Enfants
)
{ //Vérifier que tous les enfants sont bien fermés
if ( ! Enfant.Ferme
)
unEnfantOuvert=
true ;
}
return ( ! unEnfantOuvert
&& ! this .aEteFerme
&& ! this .Ferme
) ;
//Si le noeud a déjà été fermé, il ne peut pas être refermé.
}
public function Peut_Etre_Eteint
( ) : Boolean
{ //Ce noeud est-il éteignable ?
return ( this .Ferme
&& this .Peut_Eteint
) ;
}
public function ChangeState
( Etat
: Boolean ,TriggerUpdate
: Boolean =
true ) : void
{ //Passer d'un état à un autre.
this .Ferme=Etat;
if ( Etat
)
{
this .
addEventListener ( Event .
ENTER_FRAME ,ChangeFiltre
)
if ( ! this .Peut_Eteint
)
this .
addEventListener ( Event .
ENTER_FRAME ,Tourne
) ;
}
else
{
this .aEteFerme=
true ;
this .
filters =
new Array ( ) ;
}
//On peut demander à ne pas mettre à jour le niveau. Pratique dans le cas où on change juste les jetons indiquants le nombre de noeuds allumés :)
if ( TriggerUpdate
)
Layer.UpdateNbJetons
( ) ;
//Demander une MAJ du nombre de jetons
}
public function DeleteYourself
( ) : void
{ //Demande l'auto destruction du noeud et de ses enfants.
RemoveLiens
( ) ;
for each ( var Enfant
: Noeud
in Enfants
)
{ //Demander la destruction des enfants.
Enfant.DeleteYourself
( ) ;
}
//Puis supprimer du niveau le noeud
if ( Layer.
contains ( this ) )
Layer.
removeChild ( this ) ;
}
//Fonctions privées
private function SourisIN
( e
: MouseEvent ) : void
{ //Ajoute un filtre indiquant que la forme est hoverée
AddFocus
( Profondeur
( ) ) ;
}
private function SourisOUT
( e
: MouseEvent ) : void
{ //Ajoute le filtre indiquant que la forme n'est plus hoverée
AddFocus
( 0 ) ;
}
private function SourisClick
( e
: Event ) : void
{ //swapper l'état de ouvert à fermé ou vice versa.
if ( Peut_Etre_Eteint
( ) )
this .ChangeState
( false ) ;
//Eteindre le noeud
else if ( Peut_Etre_Allume
( ) )
this .ChangeState
( true ) ;
//L'allumer
}
private function Tourne
( e
: Event ) : void
{ //Fait tourner le noeud, modulo 360.
this .
rotation =
( this .
rotation +1 ) % 360 ;
}
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
+0.2 ) ;
else
Current_Glow=
Math .
max ( Final_Glow,Current_Glow
-0.1 ) ;
var ListeFiltres
: Array =
new Array ( new GlowFilter ( 0xFF0000,
0.8 ,
16 ,
16 ,Current_Glow,
1 ,
false ,
false ) ) ;
//Filtre FORME FERMEE
if ( Ferme
)
{
if ( Peut_Eteint
)
ListeFiltres.
push ( new GlowFilter ( 0x00FF00,
1 ,
16 ,
16 ,
2 * Profondeur
( ) ,
1 ,
false ,
false ) ) ;
else
ListeFiltres.
push ( new GlowFilter ( 0xFEA900,
1 ,
16 ,
16 ,
2 * Profondeur
( ) ,
1 ,
false ,
false ) ) ;
}
//Applications des filtres
for each ( var Lien
: Arc
in Arc_Liste
)
Lien.
filters =ListeFiltres;
this .
filters =ListeFiltres;
if ( Current_Glow==Final_Glow
)
this .
removeEventListener ( Event .
ENTER_FRAME ,ChangeFiltre
) ;
}
private function RemoveLiens
( ) : void
{ //Supprime les images des liens entres noeuds.
var Lien
: Arc;
for each ( Lien
in Arc_Liste
)
{
if ( Layer.
contains ( Lien
) )
Layer.
removeChild ( Lien
) ;
}
Arc_Liste=
new Array ( ) ;
}
}
}
Code source : Arc.as
Langage : actionscript3 ΔT : 0.025s Taille :1419 caractères //Un lien (arete, arc...peut importe le nom !)
//Rien de bien compliqué, si ce n'est la définition de la courbe de bézier lors de l'utilisation de curveTo.
package
{
import flash.display .
Shape ;
//Shape consomme moins de ressource que Sprite. En contrepartie, il ne peut pasz avoir d'enfants, et ne recoit pas d'évenements souris. Ca tombe bien, on en a pas besoin :)
import flash.geom .
Point ;
public class Arc extends
Shape
{
public var Parent
: Point ;
public var Enfant
: Point ;
public function Arc
( Parent
: Point ,Enfant
: Point )
{ //Instancie un nouveau lien : prend en paramètre le parent et l'enfant (en fait, leurs coordonnées)
this .Parent=Parent;
this .Enfant=Enfant;
this .Refresh
( ) ;
}
public function ChangeOrigine
( Parent
: Point ) : void
{ //Change l'origine du lien
this .Parent=Parent;
this .Refresh
( ) ;
}
private 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é
this .
graphics .
clear ( ) ;
this .
graphics .
moveTo ( this .Parent.
x ,
this .Parent.
y ) ;
this .
graphics .
lineStyle ( 2 ,0x444444
) ;
// this.graphics.lineTo(this.Enfant.x,this.Enfant.y);
this .
graphics .
curveTo ( this .Enfant.
x ,
this .Parent.
y + ( this .Enfant.y
- this .Parent.
y ) / 2 ,
this .Enfant.
x ,
this .Enfant.
y ) ;
//Rien de bien méchant : on commence à dessiner sur le parent, puis on définit un point de controle à mi-chemin, et on va jusqu'à Enfant.
}
}
} Bonus
En bonus, le fichier de résolution qui donne le nombre minimal de jetons à utiliser pour un niveau.
Attention, il n'est pas optimisé, et est particulièrement long à l'éxécution...nécessitera une fonction trace.
Code source : Resolution.as
Langage : actionscript3 ΔT : 0.051s Taille :2246 caractères function SolveLevel
( Level
: Niveau,MaxJetons
: int =
0 ,NbActions
: int =
0 ) : int
{ //Prend en paramètre un niveau, renvoie le nombre minimum de noeuds à allumer simultanément.
//Utilise la récursivité...
var Enfant
: Noeud;
//Variable utilisée dans les boucles
var Jetons_actuel
: int ;
//Le nombre de jetons consommés au maximum pendant la résolution
var BestValue
: int ;
//Le meilleur Jetons_actuel que l'on ait trouvé;
var HasMadeChange
: Boolean =
false ;
//Si il vaut false à la fin de l'étape 1, on arrete tout
var DernierParentTraite
: Noeud=
new Noeud
( new Array ( ) ,
null ) ;
//D'abord, présenter quelques fonctions utiles :
function Parents_Allumes
( Element
: Noeud,
index : int , Tableau
: Array ) : Boolean
{ //renvoie Vrai si l'élement a été fermé, ou est fermé.
return ( Element.Ferme
|| Element.aEteFerme
)
}
//Etape 0 : Si GrandPere est allumé, arrêter la recherche !
if ( Level.All_Noeuds
[ Level.All_Noeuds.
length -1 ] .Ferme==
true )
return 0 ;
//Etape 1 : Eteindre tous les noeuds qui n'ont plus besoin d'être allumés
for each ( Enfant
in Level.All_Noeuds
)
{
if ( Enfant.Ferme==
true && Enfant.Parents.
every ( Parents_Allumes
) )
{ //Every effectue un test sur tous les parents : si ils ont tous été allumés, on peut éteindre ce noeud.
Enfant.ChangeState
( false ) ;
//Eteindre l'item
}
}
//Etape 2 : Allumer tous les noeuds possibles, les passer à la fonction SolveLevel.
//Récuperer le plus petit résultat, et le renvoyer.
Jetons_actuel=
1000 ;
BestValue=
1000 ;
for each ( Enfant
in Level.All_Noeuds
)
{
if ( Enfant.Peut_Etre_Allume
( ) && DernierParentTraite
! = Enfant.Parents
[ 0 ] )
{ //L'allumer
Enfant.ChangeState
( true ) ;
Jetons_actuel=
Math .
max ( Level.NbJetonsUtilises,MaxJetons
) ;
Jetons_actuel=
Math .
max ( Jetons_actuel,SolveLevel
( String2Level
( Level.Niveau2String
( ) ,
"Résolution" ) ,Jetons_actuel,NbActions
+ 1 ) ) ;
//On est obligé de passer par un export en string, car sinon on agirait sur la copie originale...ce qui n'est pas idéal.
//SolveLevel va nous renvoyer le nombre de jetons requis. On ne le garde que si il est intéressant ;)
Enfant.ChangeState
( false ) ;
Enfant.aEteFerme=
false ;
HasMadeChange=
true ;
DernierParentTraite=Enfant.Parents
[ 0 ] ;
}
BestValue=
Math .
min ( Jetons_actuel,BestValue
) ;
}
if ( ! HasMadeChange
)
return 10000 ;
//Renvoyer une grosse valeur !
return BestValue;
}