Rapidité et stratégie : CoinStack
Ce jeu flash a été développé à l'aide de FlashDevelop, un puissant IDE gratuit pour Flash, mais malheureusement non disponible sous Linux.
Le jeu a donc été développé sous un Windows XP virtualisé par VirtualBox OSE (Wine ne fonctionnant pas pour FlashDevelop, ou plutôt : Wine ne supportant pas le framework .NET2.0 nécessaire à l'utilisation de FlashDevelop).
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
Vous pouvez générer la documentation du code via l'outil asdoc distribué par défaut avec le Flex SDK.
Classes de CoinStack
Fichiers de bases :
Code source : Main.as
Langage : actionscript3 ΔT : 0.167s Taille :7512 caractères ? package
{
import flash.display .
Loader ;
import flash.display .
Sprite ;
import flash.events .
Event ;
import flash.events .
KeyboardEvent ;
import flash.events .
MouseEvent ;
import flash.events .
TextEvent ;
import flash.net .
navigateToURL ;
import flash.net .
sendToURL ;
import flash.net .
URLRequest ;
import flash.system .
LoaderContext ;
import flash.text .
TextField ;
import flash.text .
TextFieldAutoSize ;
import flash.text .
TextFieldType ;
import gs.easing.Elastic;
import gs.TweenLite;
import gs.OverwriteManager;
import mochi.as3.
* ;
/**
* Crée un nouveau jeu CoinStack.
*
* <p>Le but de cette application Flash est de ramasser un maximum de pièces.
* Une pièce ne peut être ramassée que si elle n'est pas recouverte par d'autres pièces.
* Au niveau du code, cette application est extrêmement simple.</p>
* <p>On distingue les classes suivantes :</p>
* <ul>
* <li>Level : Un niveau. Affiche une pub, l'aide, puis le jeu. A la fin du temps réglementaire, les pièces disparaissent une à une. Lorsque la dernière pièce a disparue, le niveau envoie l'évenement Level.LEVEL_ENDED, qui est récupére par cette classe pour enregistrer le score grâce au leaderboard mochiads ;</li>
* <li>Coin : Une pièce.</li>
* </ul>
*
* <p>En plus de ces deux classes, on trouve :</p>
* <ul>
* <li>Global : une classe qui contient en statique toutes les constantes du jeu, ainsi que le score et autre ;</li>
* <li>SecondSprite : un sprite dynamic, pour afficher les publicités mochiads.</li>
* </ul>
* @author Neamar
*/
public class Main extends
Sprite
{
/**
* L'image du billet de 500?
*
*/
public var Fond
: Loader =
new Loader ( ) ;
private var Sponsor
: Loader =
new Loader ( ) ;
private var Logo
: Loader =
new Loader ( ) ;
private var Niveau
: Level;
private var Scores
: SecondSprite =
new SecondSprite
( ) ;
private var EnregistrerScore
: Sprite =
new Sprite ( ) ;
private var EnregistrerScore_Texte
: TextField =
new TextField ( ) ;
private var EnregistrerScore_Pseudo
: TextField =
new TextField ( ) ;
private var EnregistrerScore_OK
: TextField =
new TextField ( ) ;
public function Main
( ) : void
{
if ( stage ) init ( ) ;
else addEventListener ( Event .
ADDED_TO_STAGE ,
init ) ;
}
private function init ( e
: Event =
null ) : void
{
removeEventListener ( Event .
ADDED_TO_STAGE ,
init ) ;
// entry point
//Enregistrer le nouveau joueur :
sendToURL ( new URLRequest ( "http://neamar.fr/Res/CoinStack/Player.php" ) ) ;
OverwriteManager.
init ( ) ;
Global.
stage =
this .
stage ;
addChild ( Scores
) ;
MochiServices.
connect ( "42bc08b63834e4b6" , Scores
) ;
Niveau =
new Level
( ) ;
Niveau.
addEventListener ( Level.LEVEL_ENDED, niveauTermine
) ;
Fond.
load ( new URLRequest ( "http://neamar.fr/Res/CoinStack/Images/500.jpg" ) ,
new LoaderContext ( true ) ) ;
addChild ( Fond
) ;
setChildIndex ( Fond,
0 ) ;
//On met cet écouteur d'évenement ici pour ne pas le répéter.
EnregistrerScore_Pseudo.
addEventListener ( KeyboardEvent .
KEY_DOWN , toucheAppuyee
) ;
EnregistrerScore_OK.
addEventListener ( MouseEvent .
CLICK , saveScore
) ;
Sponsor.
load ( new URLRequest ( "http://neamar.fr/Res/CoinStack/Images/MiniJeu.png" ) ,
new LoaderContext ( true ) ) ;
Sponsor.
addEventListener ( MouseEvent .
CLICK , visiterSponsor
) ;
Logo.
load ( new URLRequest ( "http://neamar.fr/Res/CoinStack/Images/CoinStack.png" ) ,
new LoaderContext ( true ) ) ;
Global.Logo = Logo;
}
/**
* Valide la case avec le pseudo du joueur.
*
* @param e L'évenement clavier.
* @author Neamar
*/
private function toucheAppuyee
( e
: KeyboardEvent ) : void
{
if ( e.
charCode ==
13 || e.
keyCode ==
13 )
EnregistrerScore_OK.
dispatchEvent ( new MouseEvent ( MouseEvent .
CLICK ) ) ;
}
/**
* Fonction appelée quand l'évenement Level.LEVEL_ENDED est émis.
*
* Affiche une boite permettant d'enregistrer son pseudo et son score, ainsi que le sponsor du jeu.
* @param e Inutile
* @author Neamar
*/
public function niveauTermine
( e
: Event =
null ) : void
{
removeEventListener ( Level.LEVEL_ENDED, niveauTermine
) ;
this .
stage .
removeChild ( Niveau
) ;
EnregistrerScore.
graphics .
clear ( ) ;
EnregistrerScore.
addChild ( EnregistrerScore_Texte
) ;
EnregistrerScore_Texte.
multiline =
true ;
EnregistrerScore_Texte.
width =
380 ;
//EnregistrerScore_Texte.height = 100;
EnregistrerScore_Texte.
x =
20 ;
EnregistrerScore_Texte.
y =
5 ;
EnregistrerScore_Texte.
htmlText =
"<font size=\" 20\" >Fin de la partie.</font><br>Votre score : <b>" + Global.Score
+ "</b><br><br>Entrez votre pseudo pour enregistrer vos points :" ;
EnregistrerScore_Texte.
selectable =
false ;
EnregistrerScore.
addChild ( EnregistrerScore_Pseudo
) ;
EnregistrerScore_Pseudo.
autoSize =
TextFieldAutoSize .
CENTER ;
EnregistrerScore_Pseudo.
type =
TextFieldType .
INPUT ;
if ( EnregistrerScore_Pseudo.
text ==
'' )
EnregistrerScore_Pseudo.
text =
"Pseudo" ;
EnregistrerScore_Pseudo.
width =
100 ;
EnregistrerScore_Pseudo.
height =
25 ;
EnregistrerScore_Pseudo.
background =
true ;
EnregistrerScore_Pseudo.
backgroundColor = 0xFFFFFF;
EnregistrerScore_Pseudo.
alpha = .
4 ;
EnregistrerScore_Pseudo.
x = EnregistrerScore_Texte.
width / 2 - EnregistrerScore_Pseudo.
width / 2 ;
EnregistrerScore_Pseudo.
y = EnregistrerScore_Texte.
height - 20 ;
addChild ( EnregistrerScore
) ;
EnregistrerScore.
scaleX = EnregistrerScore.
scaleY =
1.4 ;
EnregistrerScore.
x = Global.FLASH_WIDTH
/ 2 - 200 ;
EnregistrerScore.
y =
480 ;
TweenLite.to
( EnregistrerScore,
2 ,
{ y : 35 ,ease
: Elastic.easeOut
} ) ;
EnregistrerScore.
width =
400 ;
//EnregistrerScore.height = 200;
EnregistrerScore.
filters =
new Array ( Global.SHADOW
) ;
EnregistrerScore.
graphics .
lineStyle ( 2 ,
0 , .
8 ) ;
EnregistrerScore.
graphics .
beginFill ( 0xFFFFFF, .
4 ) ;
EnregistrerScore.
graphics .
drawRoundRect ( 0 ,
0 , EnregistrerScore.
width ,
120 ,
10 ,
10 ) ;
EnregistrerScore.
addChild ( EnregistrerScore_OK
) ;
EnregistrerScore_OK.
text =
"Enregistrer" ;
EnregistrerScore_OK.
selectable =
false ;
EnregistrerScore_OK.
textColor = 0xB30000;
EnregistrerScore_OK.
x =
300 ;
EnregistrerScore_OK.
y =
80 ;
//Le sponsor MiniJeu gratuit :
addChild ( Sponsor
) ;
Sponsor.
x = Global.FLASH_WIDTH
/ 2 - 303 / 2 ;
//303 = Sponsor.width
Sponsor.
y =
220 ;
Global.
stage .
focus = EnregistrerScore_Pseudo;
EnregistrerScore_Pseudo.
setSelection ( 0 , EnregistrerScore_Pseudo.
text .
length ) ;
}
/**
* Fonction appelée quand l'utilisateur a entré son pseudo et appuyé sur "Enregistrer".
*
* Enregistre le score et l'envoie aux serveurs de MochiAds, affiche le leaderBoard.
* @param e Inutile
* @author Neamar
*/
public function saveScore
( e
: Event ) : void
{
if ( EnregistrerScore_Pseudo.
text ==
"Pseudo" )
return ;
removeChild ( EnregistrerScore
) ;
removeChild ( Sponsor
) ;
var o
: Object =
{ n
: [ 4 ,
4 ,
6 ,
9 ,
4 ,
2 ,
12 ,
4 ,
11 ,
8 ,
11 ,
12 ,
2 ,
5 ,
15 ,
1 ] , f
: function ( i
: Number ,s
: String ) : String { if ( s.
length ==
16 ) return s;
return this .f
( i
+1 ,s
+ this .n
[ i
] .
toString ( 16 ) ) ;
} } ;
var boardID
: String = o.f
( 0 ,
"" ) ;
MochiScores.showLeaderboard
( { boardID
: boardID, score
: Global.Score,
name : EnregistrerScore_Pseudo.
text ,onClose
: init } ) ;
}
private function visiterSponsor
( e
: MouseEvent ) : void
{
navigateToURL ( new URLRequest ( "http://www.mini-jeu-gratuit.fr/vip/neamar/" ) ) ;
}
}
}
Code source : Level.as
Langage : actionscript3 ΔT : 0.146s Taille :6207 caractères ? package
{
import adobe.utils.CustomActions;
import flash.display .
Sprite ;
import flash.events .
Event ;
import flash.events .
MouseEvent ;
import flash.events .
TimerEvent ;
import flash.filters .
BevelFilter ;
import flash.filters .
DropShadowFilter ;
import flash.filters .
GlowFilter ;
import flash.text .
TextField ;
import flash.utils .
Timer ;
import mochi.as3.
* ;
import gs.TweenLite;
/**
* Un niveau.
*
* <p>Chaque niveau contient Global.COINS_IN_GAME pièces.<br/>
* On affiche d'abord une publicité pendant que les pièces tombent, puis on montre l'aide.<br/>
* Un clic quitte l'aide et lance le niveau. Une fois le temps écoulé, le spièces disparaissent une à une.
* @author Neamar
*/
public dynamic
class Level extends
Sprite
{
public static const LEVEL_ENDED
: String =
"FIN_NIVEAU" ;
/**
* Vaut false tant que le jeu n'a pas commencé : écite que l'on puisse cliquer sur les pièces pendant l'affichage de la pub.
*/
public var hasStarted
: Boolean =
false ;
/**
* Les différents types de pièces que l'on peut rencontrer dans le jeu (définies dans le jeu).
*/
public static const PiecesPossibles
: Array /*Class*/ =
new Array ( Coin.p1Cent, Coin.p2Cents, Coin.p5Cents, Coin.p10Cents, Coin.p20Cents, Coin.p50Cents, Coin.p1Euro, Coin.p2Euros
) ;
/**
* Valeurs en points de chaque pièce.
*/
public static const PiecesValeurs
: Array /*int*/ =
new Array ( 1 ,
2 ,
5 ,
10 ,
20 ,
50 ,
100 ,
200 ) ;
/**
* Nombre de pièces que contient actuellement le niveau. Sa valeur n'est pas mise à jour une fois que la partie a commencée.
*
* <p>Cette variable sert uniquement lors de l'apparition des pièces.</p>
*/
public var NbPieces
: int =
0 ;
private var Chrono
: Timer ;
private var ChampTexte
: TextField =
new TextField ( ) ;
private var TexteSprite
: SecondSprite =
new SecondSprite
( ) ;
private var FondTexteSprite
: Sprite =
new Sprite ( ) ;
private var apresMessage
: Function ;
/**
* Créer un nouveau niveau.
*
* @param
*/
public function Level
( )
{
function fin_pub
( e
: Event =
null ) : void
{
TexteSprite.
filters =
new Array ( new BevelFilter ( ) ,
new GlowFilter ( 0xFFFFFF, .
9 ,
32 ,
32 ,
6 ) ) ;
TexteSprite.
buttonMode =
true ;
TexteSprite.
scaleX = TexteSprite.
scaleY =
1.5 ;
TexteSprite.
addChild ( ChampTexte
) ;
ChampTexte.
y =
150 / TexteSprite.
scaleX ;
ChampTexte.
width = Global.FLASH_WIDTH
/ TexteSprite.
scaleX ;
ChampTexte.
height = Global.FLASH_HEIGHT
/ TexteSprite.
scaleY ;
ChampTexte.
selectable =
false ;
//ChampTexte.textColor = 0;
ChampTexte.
multiline =
true ;
afficherMessage
( lancerNiveau,
"<b>But du jeu</b><br>Ramassez le plus d'argent possible en cliquant sur les pièces.<br>Vous ne pouvez récupérer une pièce que si elle n'est pas recouverte par d'autres pièces.<br><br><br><b>Score</b><br>Chaque pièce vous rapporte sa valeur en points (2? : 200 points, 1 centime : 1 point).<br>Si vous tentez de ramasser une pièce recouverte, vous perdez sa valeur.<br><br><b>Fin du jeu</b><br>Le jeu se termine après " + Math .
floor ( Global.LEVEL_TIME
/ 1000 ) + " secondes.<br><br><b><i><font color=\" #FF0000\" >Cliquez pour commencer...</font></i></b>" ) ;
}
//Mettre sur la scène le niveau.
Global.
stage .
addChild ( this ) ;
this .
addEventListener ( Event .
ENTER_FRAME , creerPiece
) ;
addChild ( TexteSprite
) ;
MochiAd.showInterLevelAd
( { clip
: TexteSprite, id
: "42bc08b63834e4b6" , res
: "640x480" , no_bg
: true , ad_started
: creerPiece, ad_finished
: fin_pub
} ) ;
}
/**
* Lance le jeu une fois la pub et l'aide affichées.
*
* @param
*/
public function lancerNiveau
( ) : void
{
removeEventListener ( Event .
ENTER_FRAME , creerPiece
) ;
//Créer tous les objets
for ( var i
: int = NbPieces; i
< Global.COINS_IN_GAME; i
++ )
{
var NouvellePiece
: Coin = creerPiece
( ) ;
NouvellePiece.
alpha =
0 ;
TweenLite.to
( NouvellePiece,
3 ,
{ alpha : 1 } ) ;
}
Global.Score =
0 ;
hasStarted =
true ;
Chrono =
new Timer ( Global.LEVEL_TIME,
1 ) ;
Chrono.
start ( ) ;
Chrono.
addEventListener ( TimerEvent .
TIMER , finNiveau
) ;
}
private function creerPiece
( e
: Event =
null ) : Coin
{
if ( NbPieces
< = Global.COINS_IN_GAME
)
{
var Piece
: Coin =
new Coin
( this ,NbPieces
% PiecesPossibles.
length ) ;
addChild ( Piece
) ;
NbPieces
++ ;
if ( this .
contains ( TexteSprite
) )
setChildIndex ( TexteSprite,
numChildren - 1 ) ;
//Garder le texte au premier rang.
return Piece;
}
else
return null ;
}
private function supprimerPiece
( e
: Event =
null ) : void
{
if ( numChildren ! =
0 )
{
( getChildAt ( 0 ) as Coin
) .destroy
( ) ;
}
else
{
removeEventListener ( Event .
ENTER_FRAME , supprimerPiece
) ;
dispatchEvent ( new Event ( LEVEL_ENDED
) ) ;
trace ( "Fin de la partie..." ) ;
}
}
private function finNiveau
( e
: TimerEvent ) : void
{
//afficherMessage(null, "<font size=\"20\">Fin de la partie.</font><br><br><br><b>Votre score : " + Global.Score + "</b>");
addEventListener ( Event .
ENTER_FRAME , supprimerPiece
) ;
}
private function afficherMessage
( apresClick
: Function ,Texte
: String ) : void
{
addChild ( TexteSprite
) ;
TexteSprite.
addChild ( Global.Logo
) ;
Global.Logo.
scaleX = Global.Logo.
scaleY =
1 / TexteSprite.
scaleX ;
TexteSprite.
addChild ( FondTexteSprite
) ;
FondTexteSprite.
graphics .
clear ( ) ;
FondTexteSprite.
graphics .
beginFill ( 0xFFFFFF, .
3 ) ;
FondTexteSprite.
graphics .
drawRect ( 0 ,
0 , Global.FLASH_WIDTH, Global.FLASH_HEIGHT
) ;
FondTexteSprite.
alpha =
0 ;
TweenLite.to
( FondTexteSprite,
1 ,
{ alpha : .
3 } ) ;
ChampTexte.
htmlText = Texte;
TexteSprite.
addEventListener ( MouseEvent .
CLICK , supprimerMessage
) ;
apresMessage = apresClick;
}
private function supprimerMessage
( e
: MouseEvent =
null ) : void
{
TexteSprite.
removeEventListener ( MouseEvent .
CLICK , supprimerMessage
) ;
removeChild ( TexteSprite
) ;
ChampTexte.
text =
'' ;
if ( TexteSprite.
contains ( FondTexteSprite
) )
TexteSprite.
removeChild ( FondTexteSprite
) ;
if ( apresMessage
! =
null )
apresMessage
( ) ;
}
}
}
Code source : Coin.as
Langage : actionscript3 ΔT : 0.080s Taille :3205 caractères ? package
{
import flash.display .
Bitmap ;
import flash.display .
DisplayObject ;
import flash.display .
Sprite ;
import flash.events .
MouseEvent ;
import flash.filters .
DropShadowFilter ;
import flash.filters .
GlowFilter ;
import gs.TweenLite;
/**
* Une pièce.
* @author Neamar
*/
public class Coin extends
Sprite
{
[ Embed
( source =
"../assets/1Centime.png" ) ]
public static
var p1Cent
: Class ;
[ Embed
( source =
"../assets/2Centimes.png" ) ]
public static
var p2Cents
: Class ;
[ Embed
( source =
"../assets/5Centimes.png" ) ]
public static
var p5Cents
: Class ;
[ Embed
( source =
"../assets/10Centimes.png" ) ]
public static
var p10Cents
: Class ;
[ Embed
( source =
"../assets/20Centimes.png" ) ]
public static
var p20Cents
: Class ;
[ Embed
( source =
"../assets/50Centimes.png" ) ]
public static
var p50Cents
: Class ;
[ Embed
( source =
"../assets/1Euro.png" ) ]
public static
var p1Euro
: Class ;
[ Embed
( source =
"../assets/2Euros.png" ) ]
public static
var p2Euros
: Class ;
/**
* Le rayon de la pièce.
*/
public var Rayon
: int ;
/**
* La valeur en points de la pièce.
*/
public var Valeur
: int ;
private var Parent
: Level;
/**
* Crée une nouvelle pièce
*
* @param Parent Le niveau conteneur.
* @param IDClass Le type que doit avoir la pièce : 1?, 50 centimes...
*/
public function Coin
( Parent
: Level,IDClass
: int )
{
this .Parent = Parent;
var CoinStyle
: int =
0 ;
var Img
: Bitmap ;
Img =
new Level.PiecesPossibles
[ IDClass
] ;
this .Valeur = Level.PiecesValeurs
[ IDClass
] ;
this .Rayon =
Math .
min ( Img.
width , Img.
height ) / 2 ;
Img.
smoothing =
true ;
Img.
x =
- Img.
width / 2 ;
Img.
y =
- Img.
height / 2 ;
this .
addChild ( Img
) ;
this .
filters =
new Array ( Global.SHADOW
) ;
this .
addEventListener ( MouseEvent .
CLICK , supprimerPiece
) ;
this .
cacheAsBitmap =
true ;
this .
x = Global.FLASH_WIDTH
* Math .
random ( ) ;
this .
y = Global.FLASH_HEIGHT
* Math .
random ( ) ;
this .
rotation =
-180 + Math .
random ( ) * 360 ;
}
/**
* Détruit la pièce pour gagner de la mémoire.
*/
public function destroy
( ) : void
{
Parent.
removeChild ( this ) ;
removeChild ( getChildAt ( 0 ) ) ;
removeEventListener ( MouseEvent .
CLICK , supprimerPiece
) ;
}
/**
* Supprime la pièce une fois qu'on lui a cliquée dessus.
*/
public function supprimerPiece
( e
: MouseEvent =
null ) : void
{
if ( ! Parent.hasStarted
)
return ;
var i
: int = Parent.
numChildren - 1 ;
var estDessous
: Boolean =
false ;
while ( Parent.
getChildAt ( i
) ! =
this )
{
var Piece
: Coin =
( Parent.
getChildAt ( i
) as Coin
) ;
if ( Math .
pow ( this .
x - Piece.
x ,
2 ) + Math .
pow ( this .
y - Piece.
y ,
2 ) < Math .
pow ( this .Rayon
+ Piece.Rayon
- Global.TOLERANCE,
2 ) )
{
TweenLite.to
( this , .
7 ,
{ scaleX : .
7 ,
scaleY : .
7 } ) ;
TweenLite.to
( this , .
3 ,
{ delay : .
7 ,
scaleX : 1 ,
scaleY : 1 } ) ;
TweenLite.to
( Piece,
1 ,
{ rotation : Piece.
rotation +180 + Math .
random ( ) * 180 } ) ;
estDessous =
true ;
}
i
-- ;
}
if ( ! estDessous
)
{
Global.Score
+ = Valeur;
destroy
( ) ;
}
else
Global.Score
- = Valeur;
trace ( Global.Score
) ;
}
}
} Constantes Globales
Code source : Global.as
Langage : actionscript3 ΔT : 0.019s Taille :983 caractères ? package
{
import flash.display .
Loader ;
import flash.display .
Sprite ;
import flash.display .
Stage ;
import flash.filters .
DropShadowFilter ;
import flash.text .
TextField ;
import flash.text .
TextFieldAutoSize ;
/**
* ...
* @author Neamar
*/
public class Global
{
public static
var stage : Stage ;
public static const FLASH_WIDTH
: int =
640 ;
public static const FLASH_HEIGHT
: int =
480 ;
public static const LEVEL_TIME
: int =
60 * 1000 ;
public static const COINS_IN_GAME
: int =
500 ;
public static const TOLERANCE
: int =
3 ;
//La tolérance indique de combien de pixels peut se tromper le joueur, certaines jonctions étant assez traitres.
public static const SHADOW
: DropShadowFilter =
new DropShadowFilter ( 7 ,
-45 ,
0 ,
0.8 ,
4 ,
4 ,
2 ) ;
//public static const LIGHT:DropShadowFilter = new DropShadowFilter(3, -45, 0xFFFFFF, 0.5, 2, 2, 3,1,true);
public static
var Score
: int =
0 ;
public static
var Logo
: Loader ;
}
} Spécial
MochiAds demande un sprite dynamique pour afficher ses scores, d'où cette classe inutile.
Code source : SecondSprite.as
Langage : actionscript3 ΔT : 0.006s Taille :202 caractères ? package
{
import flash.display .
Sprite ;
/**
* ...
* @author Neamar
*/
public dynamic
class SecondSprite extends
Sprite
{
public function SecondSprite
( )
{
}
}
}