How to create a Flash platformer using Citrus Engine
More than a year ago I shows you how to create a little game prototype using Citrus Engine.
A year has passed, and now Citrus Engine is back with version 2.0 which promises to let us create complex games in a quick.
For all you specs maniacs, here it is a brief list of features:
* Blazing 50 FPS in the browser on current machines, and 250+ FPS on the desktop (or Adobe AIR).
* Integrated with Box2D physics, which allows for tumbling crates, pulleys, vehicles, and just about anything else you can imagine, without the limitations of a grid.
* Supports multiple rendering methods with very little code. Like blitting and sprite sheets? Citrus Engine’s got it. Prefer animating using the timeline? No problem.
* Hijack the Flash IDE and use it as a level editor, for easily laying out and iterating on level designs.
* Robust documentation includes and ASDoc API, tutorial videos, and a forum.
* Standards-based code API means developers and designers spend more time tweaking the fun stuff, and less time debugging.
* Level-based progressive downloading allows gamers to start playing the game quicker by only downloading what the next level needs.
* Pre-made commonly used objects, like a hero, coins, enemy, platforms, clouds, and more!
* Easily use embedded or dynamic graphics.
* Decoupled architecture allows for custom rendering methods, like blitting or 3D.
* Sound management
* Keyboard and input management
* Built-in particle system
* Intuitive Signals event framework
Ok, the boring part is over. Now take this little prototype I made in 20 minutes (yes, 20 minutes):
Look at what we have:
* The hero (on the bottom right)
* A pushable crate (on the bottom left)
* Some platforms around the stage
* A moving platform
* An enemy (on the upper right corner)
* A coin (on the upper right corner)
Move the hero with LEFT and RIGHT and jump with SPACE. Try to grab the coin. See what happens if you touch the enemy. The game mechanics are complex enough to represent a level of a good platformer. But it took me only a few lines to do it.
This is the main class:
1 2 3 4 5 6 7 8 9 10 | package { import com.citrusengine.core.CitrusEngine; [SWF(width="640",height="480",frameRate="30",backgroundColor="#000000")] public class helloCitrus extends CitrusEngine { public function helloCitrus() { super(); state=new GameState; } } } |
Here I am just creating a state instance bound to GameState class which handles the game itself:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | package { import com.citrusengine.core.State; import com.citrusengine.objects.platformer.Baddy; import com.citrusengine.objects.platformer.Coin; import com.citrusengine.objects.platformer.Crate; import com.citrusengine.objects.platformer.Hero; import com.citrusengine.objects.platformer.MovingPlatform; import com.citrusengine.objects.platformer.Platform; import com.citrusengine.physics.Box2D; public class GameState extends State { public function GameState() { super(); } override public function initialize():void { super.initialize(); var box2D:Box2D=new Box2D("Box2d"); add(box2D); box2D.visible=true; var hero:Hero=new Hero("Hero",{x:520,y:440,jumpHeight:10}); add(hero); var platform:Platform=new Platform("floor",{width:640,height:20,x:320,y:470}); add(platform); platform=new Platform("ceil",{width:640,height:20,x:320,y:10}); add(platform); platform=new Platform("leftWall",{width:20,height:480,x:10,y:240}); add(platform); platform=new Platform("rightWall",{width:20,height:480,x:630,y:240}); add(platform); platform=new Platform("leftRamp",{width:120,height:20,x:60,y:350}); add(platform); platform=new Platform("rughtRamp",{width:280,height:20,x:540,y:120}); add(platform); var crate:Crate=new Crate("crate",{x:320,y:440,width:30,height:30}); add(crate); var baddy:Baddy=new Baddy("baddy",{x:600,y:100,leftBound:400}); add(baddy); var coin:Coin=new Coin("coin",{x:600,y:50,width:20,height:20}); add(coin); var movingPlatform:MovingPlatform=new MovingPlatform("moving",{x:220,y:350,width:100,height:20,startX:220,startY:350,endX:300,endY:120}); add(movingPlatform); } } } |
That is. The entire game is here. Let’s examine the most interesting lines:
Lines 17-18: create a Box2D environment which will be used to handle physics
Line 19: draws something similar to Box2D debug draw
Lines 21-22: add the hero. Look how parameters are passed as an Object. In this case, x and y represent the position in pixels, while jumpHeight handles the jump. Yes, creating a jumping hero is that quick.
Lines 24-35: with the same concept, we are adding platforms and walls. width and height represent the width and height of the platform, in pixels. Think about the platform as a static Box2D object.
Lines 37-38: the crate is a Box2D dynamic object
Lines 40-41: this is the bad guy. The bad guy will start moving and patrolling the area, but it does not know when it’s about to fall down (not with these few lines at least), so leftBound puts an invisible bound marking a left limit to bad guy movement. This somehow scripted way of moving the bad guy gives the player the feeling the bad guy is patrolling the upper platform.
Lines 43-44: the coin is just an object the hero can collect
Lines 46-47: the moving platform will move from startX,startY to endX,endY and then back to startX,startY and so on.
That’s all, Citrus Engine takes care of the rest and you can have a prototype done in a few minutes.
The engine comes with a free version for learning purpose, then the commercial license starts from $249.
If you want to start playing with it, I suggest you to watch the first 10 minutes of this video to see which libraries you need to include in your Flash Builder project.
Next time, we will be adding graphics to the game.
They can be easily customized to meet the unique requirements of your project.















(16 votes, average: 4.81 out of 5)










This post has 20 comments
cascus
hello emanuel what the limitation of free version?
Keegan
@casius
There is none as far as functionality. You just can’t make any money off the free one. And you don’t get any priority support.
Stem
Amazing ! It looks very nice. I’m gonna test it today.
But one question, how can they know that you use Citrus for your game ?
I mean, if i make a game with citrus, a commercial game, i publish it, can they see “inside” the code if i used citrus ?
It’s just a question, i don’t plan to do it :)
Hilary Bridel
Hi Emanuele,
Does the framework perform ok on a mobile device?
Mike
Hi Emanuele,
I have read your topic “Flash physics draw game with a car using QuickB2″
http://www.emanueleferonato.com/2011/05/05/flash-physics-draw-game-with-a-car-using-quickb2/
I encountered the error when I compile your example:
Can not find the definition of cmodule.Box2D
Can you help me?
Baghbagho
Hi,
Also it need a Restart button! Because you should reload the page, if the block goes near the wall! :D
Monkios
@ Stem : Like with any other piece of code, you can use it as long as you don’t get caught. If they decompile your code and prove you’ve been using theirs for commercial purposes, they can ask for some money for all the time you’ve been using it and ask the law enforcement to stop you from using it.
@ Emmanuel : Why is the crate so wobbly when the hero jumps on it ?
Emanuele Feronato
I think it’s due to its mass. Actually it seems a very light crate.
Mike
@ Emmanuel :
Look my comment, plz.
Emanuele Feronato
@ Mike: probably you aren’t including all files or you’re using a Flash IDE older than 5
Greg
Any idea why I get the following errors after installing (fresh for the first time) Adobe Flash Builder 4.5 and CitrusEngine2 and copying your code verbatim:
ArgumentError: Error #2109: Frame label not found in scene .
at flash.display::MovieClip/gotoAndStop()
at com.citrusengine.view::SpriteView/updateArt()[D:\Flash\CitrusEngine\Source\com\citrusengine\view\SpriteView.as:129]
at com.citrusengine.view::SpriteView/createArt()[D:\Flash\CitrusEngine\Source\com\citrusengine\view\SpriteView.as:90]
at com.citrusengine.view::CitrusView/addArt()[D:\Flash\CitrusEngine\Source\com\citrusengine\view\CitrusView.as:114]
at com.citrusengine.core::State/add()[D:\Flash\CitrusEngine\Source\com\citrusengine\core\State.as:108]
at GameState/initialize()[D:\Flash\Projects\src\GameState.as:18]
at com.citrusengine.core::CitrusEngine/handleEnterFrame()[D:\Flash\CitrusEngine\Source\com\citrusengine\core\CitrusEngine.as:159]
Eric Smith
@Greg,
This is the guy who make the Citrus Engine. The issue is a new undocumented inconsistency in the new version of Flash that now throws an error that used to silently fail. I’ll have a fix for it soon. In the mean time (hopefully by tomorrow), switching to < 4.5 will fix the problem.
Eric Smith
The bug that @Greg mentioned is fixed in the latest posted version (2.9).
Marc
What if i want to change the “create” with a sprite, or custom image character. ?
Emanuele Feronato
@Marc It will be covered in next tutorial
Greg
Hey Eric,
Right after I posted my original message here, I went to the engine forums and did a search and found a thread discussing the problem and your reply saying that the error was caused by the latest version of Flash.
I’ll be honest, I hadn’t gone back to check to see if you replied yet, so thank you for taking the time to reply here. I really appreciate it!
Side note: Emanuele, after I bought your book and found my way to this website, its quickly become a favorite that I check daily now to see all of your latest and greatest discoveries/musings in Flash. Great job and keep it up!
peter
is there something special i had to know to run this on the flash IDE?
regards, peter
Averagejoedev
Good news. Citrus Engine is now free for commercial purposes aswell!
Will you be making more citrus tutorials now Emanuele?
panda
Emanuele:
hi,I am grade to wirte to you.but, i met a master. i know the citrus engine in the web site, now i down the citrus engine soure, but i don’t know how to use it, can you help me? thank you.
Elee
Awesome tutorials!