Vous avez toujours voulu créer un jeu de plateforme, mais vous n’êtes pas trop enthousiaste pour écrire tout le code? Citrus Engine n'élimine pas entièrement le code, mais il est beaucoup plus simple, grâce à de nombreuses fonctionnalités de jeu 2D intégrées. Ce didacticiel vous permettra de créer un jeu de plateforme simple..
Dans ce didacticiel, nous allons utiliser un moteur de jeu Flash très répandu, appelé Citrus, et une série de classes ActionScript pour créer un jeu de plateforme..
Ouvrez Flash et créez un document 420x280px. Définissez la cadence d'images sur 30fps.
Nous utiliserons ces superbes graphismes en pixels de Guillaume Moreau. Vous pouvez les télécharger sur opengameart.org.
Pour l’arrière-plan, changez la couleur de la scène en # 99D9EA ou utilisez l’outil Rectangle (R) pour dessiner un rectangle de cette couleur..
Une alerte apparaît lorsque le joueur termine le niveau ou meurt. il affichera un message de jeu et le score. Utilisez le Outil Rectangle pour le créer et définir son nom d'instance sur AlertView. marque le Exporter pour ActionScript boîte et lui donner le même nom de classe.
Il existe de nombreux autres objets dans le jeu (par exemple: un écran de titre, les différents symboles de chaque sprite, le terrain). Plutôt que d'expliquer comment les créer ici, je vous suggère de télécharger les fichiers source et de regarder quels objets se trouvent dans la bibliothèque de la FLA. Vous pouvez utiliser les mêmes symboles dans votre propre jeu ou en créer de nouveaux.!
Nous allons utiliser une police bitmap dans le jeu; étant donné que nous allons utiliser la police de manière dynamique, nous devrons l'intégrer à l'application. J'utilise les polices 04b11 et Arcade Classic.
Sélectionnez un champ de texte dynamique avec la police de votre choix et cliquez sur le bouton Intégrer… bouton dans le Panneau de propriétés.
Sélectionnez / ajoutez tous les caractères nécessaires et cliquez sur D'accord.
Nous utiliserons des effets sonores pour améliorer le ressenti du jeu. Les sons utilisés dans cet exemple ont été générés à l'aide d'as3sfxr et sont inclus dans les fichiers source..
Nous utiliserons un moteur d'interpolation différent de celui par défaut inclus dans Flash. Cela augmentera les performances tout en étant plus facile à utiliser.
Vous pouvez télécharger TweenNano depuis son site officiel.
Nous utiliserons le moteur Citrus pour faire fonctionner notre jeu..
Qu'est-ce que le moteur Citrus? En savoir plus sur son site web:
Citrus Engine est un moteur de jeu Flash évolutif de niveau professionnel conçu pour des jeux de qualité. Il est construit sur les pratiques modernes de programmation Flash, vous permettant de vous concentrer à rendre votre jeu génial! Il est livré avec un kit de démarrage "platformer", que vous pouvez utiliser pour créer facilement de superbes jeux 2D à défilement horizontal.
Accédez à la page de téléchargement et récupérez les fichiers nécessaires. Ouvrez les préférences de Flash, sélectionnez ActionScript dans la liste de gauche et cliquez sur Paramètres ActionScript 3.0… , puis ajoutez le chemin d'accès aux sources, comme indiqué dans l'image ci-dessus.
Nous allons rendre notre application interactive en utilisant une classe externe. Ajoutez son nom (Principale
) au Classe champ dans le Publier section de la Propriétés panneau pour associer la FLA à la classe de document Main.
Créez une nouvelle classe ActionScript 3.0 (Cmd + N) et enregistrez-la sous Main.as dans votre dossier de classe.
Créez votre structure de classe de base pour commencer à écrire votre code.
package public class Main fonction publique Main (): void // code constructeur
Main.as
le Principale
classe préparera le moteur Citrus pour gérer le premier niveau.
package import com.citrusengine.core.CitrusEngine; classe finale publique Main étend CitrusEngine fonction finale publique Main (): void super (); state = new Level ();
Cette classe étend la classe CitrusEngine et définit "l'état" du jeu sur Niveau, qui est le nom de la classe qui contiendra tout le comportement de notre jeu.
Niveau
La classe State est l’une des classes principales de Citrus Engine et vous devez l’étendre pour créer la logique de jeu de vos niveaux ou états. Dans cet exemple, le Niveau la classe s'étend Etat pour créer le premier niveau du jeu.
Créez une nouvelle classe ActionScript 3.0 (Cmd + N) et enregistrez-la sous Niveau dans votre dossier de classe.
Ce sont les classes que nous devons importer pour notre Niveau
classe pour travailler. le importation
directive met à la disposition de votre code des classes et des packages définis en externe.
import flash.display.MovieClip; import flash.display.Sprite; import flash.events.MouseEvent; importer com.citrusengine.core.CitrusEngine; importer com.citrusengine.core.State; import com.citrusengine.physics.Box2D; import com.citrusengine.objects.platformer. *; import com.citrusengine.objects. *; importer com.citrusengine.math.MathVector; import flash.events.Event; import flash.geom.Rectangle; importer flash.ui.Keyboard; import flash.events.KeyboardEvent; import flash.text.TextField; import flash.text.TextFormat; import com.greensock.TweenNano; importer com.greensock.easing.Expo; import flash.net.navigateToURL; import flash.net.URLRequest; import flash.filters.GlowFilter; import flash.filters.BitmapFilter;
Ce sont les variables que nous allons utiliser; lisez les commentaires dans le code pour en savoir plus. (Certains de leurs noms sont explicites, donc il n'y a pas de commentaire.)
var privé levelView: LevelView = new LevelView (); // sprite de la bibliothèque private var hero: Hero; coeurs var privé: vecteur.= nouveau vecteur. (); private var tf: TextFormat = new TextFormat ('ArcadeClassic', 17, 0xFFFFFF, null, null, null, null, null, 'right'); private var scoreTF: TextField = new TextField (); var privé gemSnd: GemSnd = new GemSnd (); // Snd = Variable privée du son goalSnd: GoalSnd = new GoalSnd (); private var hitSnd: HitSnd = new HitSnd (); private var jumpSnd: JumpSnd = new JumpSnd (); private var lostSnd: LoseSnd = new LoseSnd (); var privé baddySnd: BaddySnd = new BaddySnd ();
Le constructeur est une fonction qui s'exécute lorsqu'un objet est créé à partir d'une classe. Ce code est le premier à s'exécuter lorsque vous créez une instance d'un objet. Il se charge au démarrage du jeu si une partie de la classe du document.
Il appelle les fonctions nécessaires pour démarrer le jeu. Vérifiez ces fonctions dans les prochaines étapes.
fonction finale publique Level (): void // Code
Nous allons commencer par mettre le jeu en pause; cela empêchera le moteur d'ajouter les graphiques tant que l'image-objet Level View est sur scène.
fonction finale publique Level (): void super (); // code d'installation par défaut CitrusEngine.getInstance (). playing = false; // fait une pause dans le jeu
Cela ajoutera l'image-objet Level View à la scène, ainsi qu'un écouteur à la souris pour le supprimer..
redéfinit la fonction publique initialize (): void / * Vue de démarrage de niveau * / addChild (levelView); levelView.addEventListener (MouseEvent.MOUSE_UP, startLevel);
La fonction suivante s'exécute lorsque l'utilisateur clique sur la vue Niveau et gérera la logique de démarrage du jeu.
fonction finale privée startLevel (e: MouseEvent): void
Ce code détruit l'instance Level View.
levelView.removeEventListener (MouseEvent.MOUSE_UP, startLevel); removeChild (levelView); levelView = null;
Maintenant, nous désactivons le jeu et initialisons le niveau.
super.initialize (); CitrusEngine.getInstance (). Playing = true;
Le code suivant démarre le moteur Box2D qui gère la physique de Citrus Engine..
var box2D: Box2D = new Box2D ('Box2d'); ajouter (box2D); //box2D.visible = true; // commentez pour voir les graphiques de débogage de Box2D
Ces lignes créeront tout le niveau, lirez le code pour comprendre le système d’instanciation de Citrus Engine (ce qui est vraiment facile!).
(Tout vue
les propriétés sont les noms de classe des symboles de la bibliothèque FLA: Bg
, TerrainPart1
, WaterX3
, etc.)
var leftWall: Platform = new Platform ('LeftWall', largeur: 1, hauteur: 280, x: 0, y: 110); ajouter (leftWall); var rightWall: Platform = new Platform ('RightWall', largeur: 1, hauteur: 280, x: 726, y: 100); ajouter (rightWall); var bg: CitrusSprite = new CitrusSprite ('Bg', view: Bg, x: 0, y: 20); ajouter (bg); var terrain1: Plate-forme = nouvelle plate-forme ('Terrain1', largeur: 422, hauteur: 32, x: 211, y: 264, vue: TerrainPart1); ajouter (terrain1); var oneWay1: Platform = nouvelle Platform ('OneWay1', largeur: 92, hauteur: 32, x: 184, y: 232, oneWay: true, vue: OneWay1); ajouter (oneWay1); var gem: Coin = new Coin ('Gem', largeur: 11, hauteur: 10, x: 186, y: 136, vue: Gem); ajouter (gemme); var water: Sensor = nouveau capteur ('Water', largeur: 92, hauteur: 32, x: 468, y: 264, vue: Water X3); Ajoutez de l'eau); var terrain2: Plate-forme = nouvelle plate-forme ('Terrain2', largeur: 214, hauteur: 32, x: 621, y: 264, vue: TerrainPart2); ajouter (terrain2); var baddy: Baddy = new Baddy ('Baddy', x: 300, y: 200, leftBound: 250, rightBound: 350, vue: Ennemi); ajouter (baddy); var movingPlatform: MovingPlatform = new MovingPlatform ('MP', largeur: 32, hauteur: 8, x: 436, y: 232, startX: 436, startY: 232, endX: 500, endY: 232, vue: PlatformClip, vitesse : 0,9); ajouter (movingPlatform); var oneWay2: Platform = nouvelle Platform ('OneWay2', largeur: 127, hauteur: 32, x: 663, y: 232, oneWay: true, vue: OneWay2); ajouter (oneWay2); var oneWay3: Platform = nouvelle Platform ('OneWay3', largeur: 64, hauteur: 32, x: 695, y: 200, oneWay: true, vue: OneWay3); ajouter (oneWay3); var door: Capteur = nouveau capteur ('Porte', largeur: 20, hauteur: 28, x: 695, y: 202, vue: Porte); ajouter (porte); héros = nouveau héros ('Hero', x: 30, y: 234, largeur: 19, hauteur: 26, vue: HeroClip, jumpHauteur: 9, vitesse maximale: 2, blessVelocityX: 2); ajouter (héros);
Comme vous pouvez le constater, vous créez dans chaque cas une instance du type d’objet souhaité et vous utilisez les paramètres pour spécifier sa position, sa taille, son graphique ou son habillage (il s’agit de la vue paramètre) et d’autres éléments utiles. Ensuite, nous l’ajoutons à l’étape Citrus à l’aide du bouton ajouter()
méthode.
Arrêtons-nous ici pour faire un test rapide et pour nous assurer que notre code de jeu fonctionne:
N'oubliez pas que les jalons sont inclus dans les fichiers source. Si, pour une raison quelconque, votre fichier ne l'imite pas, jetez un coup d'œil à la source pour voir ce qui peut en être la cause. (Et gardez à l'esprit que certaines lignes doivent être commentées car certaines fonctions n'ont pas encore été créées.)
Citrus Engine utilise Signals pour gérer les interactions de type d'événement. Vous pouvez en apprendre plus sur les signaux sur ce tutoriel Activetuts +.
gem.onBeginContact.addOnce (fonction (e: *) gemSnd.play (); scoreTF.text = Chaîne (int (scoreTF.text) + 50);); door.onBeginContact.addOnce (levelComplete); hero.onTakeDamage.add (blesséHero); hero.onGiveDamage.addOnce (killBaddy); hero.onJump.add (function () jumpSnd.play ()); hero.onGiveDamage.addOnce (function () baddySnd.play ());
Notre Hero MovieClip sera lu par défaut sauf si nous l’empêchons. Ce code gère cela, et vous apprendrez également comment accéder au MovieClip qui sert d'art pour votre objet Citrus.
this.view.getArt (héros) .content.stop (); //State(Level).SpriteView.SpriteArt.MovieClip.stop gameListeners (); addIndicators ();
Ce code ajoute les écouteurs EnterFrame et Keyboard qui seront utilisés dans notre jeu. Vous pourrez en savoir plus sur les fonctions de gestionnaire correspondantes dans les étapes suivantes..
fonction finale privée gameListeners (action: String = 'add'): void if (action == 'add') stage.addEventListener (Event.ENTER_FRAME, gameLogic); stage.addEventListener (KeyboardEvent.KEY_DOWN, animateWalk); stage.addEventListener (KeyboardEvent.KEY_UP, stopWalk); else stage.removeEventListener (Event.ENTER_FRAME, gameLogic); stage.removeEventListener (KeyboardEvent.KEY_DOWN, animateWalk); stage.removeEventListener (KeyboardEvent.KEY_UP, stopWalk);
Les cœurs représenteront la santé de notre héros. Le code suivant ajoute trois cœurs à la scène et les stocke dans un vecteur pour les utiliser ultérieurement en dehors de cette fonction..
fonction finale privée addIndicators (): void / * Hearts * / for (var i: int = 0; i < 3; i++) var heart:Heart = new Heart(); heart.y = 5; heart.x = 5 + (i * heart.width); addChild(heart); hearts.push(heart);
Le Score TextField est créé par ce code. Nous utilisons des filtres pour ajouter le trait noir autour des lettres.
/ * Score * / scoreTF.x = 320; scoreTF.defaultTextFormat = tf; scoreTF.text = '0'; var filter: BitmapFilter = nouveau GlowFilter (0, 1, 2, 2); var filter2: BitmapFilter = new GlowFilter (0, 1, 1, 1); scoreTF.filters = [filtre, filtre2]; addChild (scoreTF);
Ici nous mettons en place la caméra, qui suivra notre héros si sa position dépasse le centre X de la scène.
fonction finale privée gameLogic (e: Event): void / * Handle Camera * / if (hero.x> = stage.stageWidth * 0.5) view.setupCamera (héros, nouveau MathVector (stage.stageWidth * 0.5, 234), nouveau rectangle (0, 0, 726, 228), null);
Ce code vérifie si notre héros est tombé à l'eau et, le cas échéant, il joue le son perdu et appelle une alerte..
/ * Vérifiez si le héros est tombé * / if (hero.y> stage.stageHeight) lostSnd.play (); alerte ('perdre');
Notre animation de marche de héros est lancée lorsque les touches fléchées gauche ou droite sont enfoncées.
fonction finale privée animateWalk (e: KeyboardEvent): void if (e.CodeCode == 37 || e.CodeCode == 39) this.view.getArt (héros) .content.play ();
Lorsque les touches sont relâchées, l'animation s'arrête.
fonction finale privée stopWalk (e: KeyboardEvent): void if (e.CodeCode == 37 || e.CodeCode == 39) this.view.getArt (héros) .content.gotoAndStop (1);
Arrêtons-nous ici pour faire un autre test et vérifier que notre code de jeu fonctionne:
N'oubliez pas que certaines lignes ont été commentées car toutes les fonctions n'ont pas encore été créées..
Rappelez-vous que les jalons sont inclus dans les fichiers source. Si, pour une raison quelconque, votre fichier ne l'imite pas, jetez un coup d'œil à la source pour voir ce qui pourrait le causer..
Le héros devrait subir des dégâts si le vaurien le touche. les lignes suivantes enlèvent un cœur et jouent le son blessé. Une alerte est déclenchée lorsque le héros est en mauvaise santé..
fonction finale privée hurtHero (): void removeChild (hearts [hearts.length-1]); hearts.splice (hearts.length-1, 1); hitSnd.play (); si (coeurs.longueur <= 0) loseSnd.play(); alert('lose');
Vous pouvez tuer un méchant en sautant dessus. Lorsque cela se produit, le score augmente.
fonction finale privée killBaddy (): void scoreTF.text = String (int (scoreTF.text) + 100);
Le niveau se termine lorsque le héros atteint la porte. Un son sera joué et une alerte sera appelée; vous pouvez voir le code d'alerte à l'étape suivante.
fonction finale privée levelComplete (e: *): void goalSnd.play (); alerte();
Cette fonction arrêtera le jeu et affichera son message, et ajoutera également un écouteur de souris pour réinitialiser le jeu lorsque vous cliquez dessus..
alerte de fonction finale privée (gameState: String = 'win'): void gameListeners ('rmv'); CitrusEngine.getInstance (). Playing = false; this.view.getArt (héros) .content.gotoAndStop (1); var alert: AlertView = new AlertView (); alert.x = stage.stageWidth * 0.5; alert.y = stage.stageHeight * 0,5; alert.scoreTF.text = scoreTF.text; alert.addEventListener (MouseEvent.MOUSE_UP, redémarrer); if (gameState == 'lost') alert.titleTF.text = 'Level Failed!'; addChild (alerte); TweenNano.from (alert, 0.6, scaleX: 0.2, scaleY: 0.2, facilité: Expo.easeOut);
Ce code rechargera le fichier SWF lorsque l'utilisateur cliquera sur le message "game over", restaurant toutes les valeurs initiales et revenant à l'écran initial.
redémarrage de la fonction finale privée (e: MouseEvent): void browseToURL (new URLRequest (stage.loaderInfo.url), '_level0');
Nous sommes maintenant prêts à effectuer un dernier test de notre jeu et à vérifier que tout fonctionne comme prévu.
Expérimentez avec ce puissant moteur de jeu et créez vos propres jeux!
J'espère que vous avez aimé ce tutoriel, merci d'avoir lu!