text: Ever wanted to make a platformer, but not too keen on writing all the code from scratch? The Citrus Engine doesn't eliminate code entirely, but it makes it much simpler, with plenty of useful 2D game features built right in. In this tutorial, we'll use it to build a simple platform game.
  Step 1: Brief Overview
  In this tutorial we'll use a popular Flash Game Engine, called Citrus, and a series of ActionScript classes to create a platformer game.
  Step 2: Flash Document Settings
  Open Flash and create a 420x280px document. Set the Frame rate to 30fps.
  Step 3: Interface
  We'll use these great pixel graphics by Guillaume Moreau. You can download them from opengameart.org.
  Step 4: Background
  For the background, change the stage color to #99D9EA, or use the Rectangle Tool (R) to draw a rectangle of that color.
  Step 5: Alert
  An alert will be shown when the player completes the level or dies; it will display a game over message and the score. Use the Rectangle Tool to create it and set its instance name to AlertView. Mark the Export for ActionScript box and give it the same class name.
  There are many other objects in the game (for example: a title screen, the various symbols for each sprite, the terrain). Rather than explaining how to create them here, I suggest you download the source files and look at what objects are in the FLA's Library. You can either use the same symbols in your own game, or create new ones!
  Step 6: Embed Font
  We'll use a bitmap font in the game; since we are going to use the font dynamically we will need to embed it in the application. I'm using the fonts 04b11 and Arcade Classic.
  Select a dynamic text field with the font of your preference and click the Embed... button in the Properties Panel.
  Select/add all the necesary characters and click OK.
  Step 7: Sounds
  We'll use Sound Effects to enhance the feeling of the game. The sounds used in this example were generated using as3sfxr and are included in the source files.
  Step 8: TweenNano
  We'll use a different tween engine from the default included in Flash. This will increase performace as well as being easier to use.
  You can download TweenNano from its official website.
  Step 9: Citrus Engine
  We'll use the Citrus Engine to power our game.
  What is the Citrus Engine? Learn more from its website: sidescrolling games.
  Step 10: Set Up Citrus Engine
  Go to the download page and get the necessary files. Open Flash Preferences, select ActionScript from the list on the left and click on ActionScript 3.0 settings..., then add the path to the sources as shown in the image above.
  Step 11: Set Document Class
  We'll make our application interactive by using an external class. Add its name (
  Main) to the Class field in the Publish section of the Properties panel to associate the FLA with the Main document class.
  Step 12: Create a New ActionScript Class
  Create a new (Cmd + N) ActionScript 3.0 Class and save it as Main.as in your class folder.
  Step 13: Class Structure
  Create your basic class structure to begin writing your code.
  package { public class Main { public function Main():void { // constructor code } } }
  Step 14:
  Main.as
  The
  Main class will prepare the Citrus Engine to handle the first level.
  package { import com.citrusengine.core.CitrusEngine; public final class Main extends CitrusEngine { public final function Main():void { super(); state = new Level(); } } }
  This class extends the CitrusEngine class and sets the game's "state" to Level, which is the name of the class that will contain all our game's behaviour.
  Step 15:
  Level.as
  The State class is one of the core classes of Citrus Engine, and you should extend this class to create the game logic of your levels or states. In this example the Level class extends State to create the game's first level.
  Create a new (Cmd + N) ActionScript 3.0 Class and save it as Level.as in your class folder.
  Step 16: Required Classes
  These are the classes we'll need to import for our
  Level class to work. The
  import directive makes externally defined classes and packages available to your code.
  import flash.display.MovieClip; import flash.display.Sprite; import flash.events.MouseEvent; import com.citrusengine.core.CitrusEngine; import com.citrusengine.core.State; import com.citrusengine.physics.Box2D; import com.citrusengine.objects.platformer.*; import com.citrusengine.objects.*; import com.citrusengine.math.MathVector; import flash.events.Event; import flash.geom.Rectangle; import flash.ui.Keyboard; import flash.events.KeyboardEvent; import flash.text.TextField; import flash.text.TextFormat; import com.greensock.TweenNano; import com.greensock.easing.Expo; import flash.net.navigateToURL; import flash.net.URLRequest; import flash.filters.GlowFilter; import flash.filters.BitmapFilter;
  Step 17: Variables
  These are the variables we'll use; read the comments in the code to know more about them. (Some of their names are self-explanatory, so there's no comment.)
  private var levelView:LevelView = new LevelView(); //sprite from the Library private var hero:Hero; private var hearts:Vector.<Sprite> = new Vector.<Sprite>(); private var tf:TextFormat = new TextFormat('ArcadeClassic', 17, 0xFFFFFF, null, null, null, null, null, 'right'); private var scoreTF:TextField = new TextField(); private var gemSnd:GemSnd = new GemSnd(); //Snd = Sound private var goalSnd:GoalSnd = new GoalSnd(); private var hitSnd:HitSnd = new HitSnd(); private var jumpSnd:JumpSnd = new JumpSnd(); private var loseSnd:LoseSnd = new LoseSnd(); private var baddySnd:BaddySnd = new BaddySnd();
  Step 18: Constructor
  The constructor is a function that runs when an object is created from a class, this code is the first to execute when you make an instance of an object, loads once the game starts if part of the document class.
  It calls the necessary functions to start the game. Check those functions in the next steps.
  public final function Level():void { //Code }
  Step 19: Pause Game
  We'll start by pausing the game; this will prevent the engine from adding the graphics while the Level View sprite is on stage.
  public final function Level():void { super(); //default setup code CitrusEngine.getInstance().playing = false; //actually pause game }
  Step 20: Add Level View
  This will add the Level View sprite to the stage, as well as a mouse listener to remove it.
  override public function initialize():void { /* Level Start View */ addChild(levelView); levelView.addEventListener(MouseEvent.MOUSE_UP, startLevel); }
  Step 21: Start Level
  The next function runs when the Level View is clicked, and will handle the logic to start the game.
  private final function startLevel(e:MouseEvent):void {
  Step 22: Remove Level View
  This code destroys the Level View instance.
  levelView.removeEventListener(MouseEvent.MOUSE_UP, startLevel); removeChild(levelView); levelView = null;
  Step 23: Start GameState (Unpause)
  Now we unpause the game and initialize the level.
  super.initialize(); CitrusEngine.getInstance().playing = true;
  Step 24: Start Box2D
  The following code starts the Box2D engine that handles the physics of Citrus Engine.
  var box2D:Box2D = new Box2D('Box2d'); add(box2D); //box2D.visible = true; //uncomment to see the debug graphics of Box2D
  Step 25: Add Graphic Objects
  These lines will create the entire level, read through the code to understand the Citrus Engine instantiation system (which is really easy!).
  (All
  view properties are the class names of symbols from the FLA Library:
  Bg,
  TerrainPart1,
  WaterX3, etc.)
  var leftWall:Platform = new Platform('LeftWall', {width:1, height:280, x:0, y:110}); add(leftWall); var rightWall:Platform = new Platform('RightWall', {width:1, height:280, x:726, y:100}); add(rightWall); var bg:CitrusSprite = new CitrusSprite('Bg', {view:Bg, x:0, y:20}); add(bg); var terrain1:Platform = new Platform('Terrain1', {width:422, height:32, x: 211, y:264, view:TerrainPart1}); add(terrain1); var oneWay1:Platform = new Platform('OneWay1', {width:92, height:32, x:184, y:232, oneWay:true, view:OneWay1}); add(oneWay1); var gem:Coin = new Coin('Gem',{width:11, height:10, x:186, y:136, view:Gem}); add(gem); var water:Sensor = new Sensor('Water', {width:92, height:32, x: 468, y:264, view:WaterX3}); add(water); var terrain2:Platform = new Platform('Terrain2', {width:214, height:32, x:621, y:264, view:TerrainPart2}); add(terrain2); var baddy:Baddy = new Baddy('Baddy', {x:300, y:200, leftBound:250, rightBound:350, view:Enemy}); add(baddy); var movingPlatform:MovingPlatform = new MovingPlatform('MP',{width:32, height:8, x:436, y:232, startX:436, startY:232, endX:500, endY:232, view:PlatformClip, speed:0.9}); add(movingPlatform); var oneWay2:Platform = new Platform('OneWay2', {width:127, height:32, x:663, y:232, oneWay:true, view:OneWay2}); add(oneWay2); var oneWay3:Platform = new Platform('OneWay3', {width:64, height:32, x:695, y:200, oneWay:true, view:OneWay3}); add(oneWay3); var door:Sensor = new Sensor('Door', {width:20, height:28, x:695, y:202, view:Door}); add(door); hero = new Hero('Hero', {x:30, y:234, width:19, height:26, view:HeroClip, jumpHeight:9, maxVelocity:2, hurtVelocityX:2}); add(hero);
  As you can see, in each case you create an instance of the type of object you want and use the parameters to specify its position, size, graphic or skin (this is the view parameter) and other useful elements. Then we add it to the Citrus stage using the
  add() method.
  Let's stop here to make a quick test and make sure that our game code is working:
  Remember that the Milestones are included in the source files, so if for some reason your file doesn't mimic this one take a look at the source to see what can be causing that. (And keep in mind that some lines must be commented out as some functions haven't been created yet.)
  Step 26: Add Signals
  Citrus Engine uses Signals to handle event type interaction. You can learn more about signals on this Activetuts+ tutorial.
  gem.onBeginContact.addOnce(function(e:*){gemSnd.play();scoreTF.text = String(int(scoreTF.text) + 50);}); door.onBeginContact.addOnce(levelComplete); hero.onTakeDamage.add(hurtHero); hero.onGiveDamage.addOnce(killBaddy); hero.onJump.add(function(){jumpSnd.play()}); hero.onGiveDamage.addOnce(function(){baddySnd.play()});
  Step 27: Stop Hero Animation
  Our Hero MovieClip will play by default unless we prevent it. This code handles that, and you will also learn how to access the MovieClip that serves as the art for your Citrus Object.
  this.view.getArt(hero).content.stop(); //State(Level).SpriteView.SpriteArt.MovieClip.stop gameListeners(); addIndicators();
  Step 28: Game Listeners
  This code adds EnterFrame and Keyboard listeners that will be used in our game. You can read about the corresponding handler functions in the next steps.
  private final function 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); } }
  Step 29: Add Hearts
  Hearts will represent our Hero's health. The next code adds three hearts to the stage and stores them in a Vector to use them later outside this function.
  private final function 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); }
  Step 30: Add Score
  The Score TextField is created by this code. We use filters to add the black stroke around the letters.
  /* Score */ scoreTF.x = 320; scoreTF.defaultTextFormat = tf; scoreTF.text = '0'; var filter:BitmapFilter = new GlowFilter(0, 1, 2, 2); var filter2:BitmapFilter = new GlowFilter(0, 1, 1, 1); scoreTF.filters = [filter, filter2]; addChild(scoreTF); }
  Step 31: Handle Camera
  Here we set up the camera, which will follow our Hero if its position is past the center X of the stage.
  private final function gameLogic(e:Event):void { /* Handle Camera */ if(hero.x >= stage.stageWidth * 0.5) { view.setupCamera(hero, new MathVector(stage.stageWidth * 0.5, 234), new Rectangle(0, 0, 726, 228), null); }
  Step 32: Check for Fall
  This code checks if our hero has fallen into the water, and if so it plays the lose sound and calls an alert.
  /* Check if hero fell */ if(hero.y > stage.stageHeight) { loseSnd.play(); alert('lose'); } }
  Step 33: Animate Hero Walk
  Our hero walking animation is started when the left or right arrow keys are pressed.
  private final function animateWalk(e:KeyboardEvent):void { if(e.keyCode == 37 || e.keyCode == 39) { this.view.getArt(hero).content.play(); } }
  Step 34: Stop Walk Animation
  When the keys are released the animation stops.
  private final function stopWalk(e:KeyboardEvent):void { if(e.keyCode == 37 || e.keyCode == 39) { this.view.getArt(hero).content.gotoAndStop(1); } }
  Let's stop here to make another test and check that our game code is working:
  Keep in mind again that some lines have been commented out as not all functions have been created yet.
  Remember that the Milestones are included in the source files, so if for some reason your file doesn't mimic this one take a look at the source to see what could be causing that.
  Step 35: Hurt Hero
  The hero should take damage if the baddy touches him; the next lines remove one heart and play the hurt sound. An alert is called when the hero is out of health.
  private final function hurtHero():void { removeChild(hearts[hearts.length-1]); hearts.splice(hearts.length-1, 1); hitSnd.play(); if(hearts.length <= 0) { loseSnd.play(); alert('lose'); } }
  Step 36: Kill Baddy
  You can kill a baddy by jumping on it. When this happens the score increases.
  private final function killBaddy():void { scoreTF.text = String(int(scoreTF.text) + 100); }
  Step 37: Level Complete
  The level ends when the hero reaches the door. A sound will be played and an alert will be called; you can see the alert code in the next step.
  private final function levelComplete(e:*):void { goalSnd.play(); alert(); }
  Step 38: Alert
  This function will stop the game and show the game over message, and also adds a mouse listener to reset the game when clicked.
  private final function alert(gameState:String = 'win'):void { gameListeners('rmv'); CitrusEngine.getInstance().playing = false; this.view.getArt(hero).content.gotoAndStop(1); 39: Restart
  This code will reload the SWF when the game over message is clicked, restoring all initial values and returning to the initial screen.
  private final function restart(e:MouseEvent):void { navigateToURL(new URLRequest(stage.loaderInfo.url), '_level0'); }
  Step 40: Final Test
  We are now ready to do a final test to our game and check that everything works as expected.
  Conclusion
  Experiment with this powerful game engine and create your own games!
  I hope you liked this tutorial, thank you for reading!
  Envato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!Translate this post
  