=====The CitrusEngine main class and its children===== When you want to create a game using the Citrus Engine, your Main class will extend the CitrusEngine class. Note it's also possible to integrate in your website a game made with the Citrus Engine via a SWF file, or create subclass which will instantiate and remove the Citrus Engine game. ====What does the CitrusEngine class define?==== By extending the CitrusEngine class (which extends Flash MovieClip), you've already set up a lot of useful events: * **Event.ADDED_TO_STAGE** calling handleAddedToStage function. It will define stage properties:stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; * **Event.ENTER_FRAME** calling handleEnterFrame function. This is the main loop. * **Event.ACTIVATE** calling handleStageActivated function. When this function is called, it will automatically set your game in a playing mode. * **Event.DEACTIVATE** calling handleStageDeactivated function. When this function is called, it will automatically set your game in a pausing mode. All these functions are defined as //protected// so that you can easily override them to fit your needs. The CitrusEngine class also defines variables for severals classes: [[citrus:state|State]], [[citrus:levelmanager|LevelManager]], [[citrus:gamedata|AGameData]], [[citrus:sound|SoundManager]], [[citrus:console|Console]], and [[citrus:input|Input]]. It's really easy and quick to define a GameState extending [[citrus:state|State]] class: import citrus.core.CitrusEngine; public class Main extends CitrusEngine { public function Main() { } override protected function handleAddedToStage(e:Event):void { super.handleAddedToStage(e); state = new GameState(); } } As for any version, we need to make sure the engine is actually added to the flash display list before doing anything... this is usually not a problem, but in case you want to preload the game from an external swf this will save you a lot of errors, and it's also common practice to wait for a stage explicitly to avoid surprises. Note the CitrusEngine class is always accessible thanks to a singleton, meaning you can change your game state from everywhere, access input ect. Use it carefully! var ce:CitrusEngine = CitrusEngine.getInstance(); ce.state = new AnOtherGameState(); ====The Main loop==== The CitrusEngine main loop is based on an **Event.ENTER_FRAME** function. It switches states if necessary (destroys the previous and creates the new one), then calls update on the current state. In this update loop we calculate a [[http://en.wikipedia.org/wiki/Delta_timing|delta time]], which is given as a parameter to the [[citrus:state|State]]. The State will update all of its game objects. If the game is DEACTIVATE or if you set //playing// property to false, it will prevent the main loop from running. ====Add a menu==== You can quickly add a game menu in your Main class. Even if you're using Stage3D stuff (Starling or Away3D), it's recommended to use display list elements there because they will be added very quickly! Note that when you're using Stage3D, you need to update your graphics on the GPU, which takes some time. By default, the game state will be displayed at index 0. It can be easily changed thanks to the //_stateDisplayIndex// protected property from the //CitrusEngine// class. Don’t forget that the state is added once a new one is created. Finally, if you use Starling for your game, you must wait for it to be ready before using it (loading assets, or starting a state). For this, you can override the //handleStarlingReady// public method from StarlingCitrusEngine, which is called when the context3D is ready and the starling root is created. (It's not an event listener, just a practical function.) Example: override public function handleStarlingReady():void { assets = new AssetManager(starling.contentScaleFactor); assets.enqueue(File.applicationDirectory.resolvePath(formatString("assets/{0}x", starling.contentScaleFactor))); assets.loadQueue(function(ratio:Number):void { if (ratio == 1.0) { _starling.stage.addChild(new Hud()); state = new GameState(); } }); } ====StarlingCitrusEngine==== If you want to create a game using [[http://gamua.com/starling/|Starling]], your Main class will have to extend //StarlingCitrusEngine//, which extends //CitrusEngine//. It adds useful features for handling Starling, like start/stop, context3D management, and a lot more. Please refer to the [[citrus:multi_resolution|multi-resolution]] article, which explains how to set up StarlingCitrusEngine along with example code. ====Away3DCitrusEngine==== It's also possible to create 3D games with the Citrus Engine thanks to [[http://away3d.com|Away3D]]. Extend //Away3DCitrusEngine// which extends //CitrusEngine// in your Main class. Like //StarlingCitrusEngine//, //Away3DCitrusEngine// has a great helper function to set up Away3D: public function setUpAway3D(debugMode:Boolean = false, antiAliasing:uint = 4, scene3D:Scene3D = null, stage3DProxy:Stage3DProxy = null):void { _away3D = new View3D(scene3D); _away3D.antiAlias = antiAliasing; if (stage3DProxy) { _away3D.stage3DProxy = stage3DProxy; _away3D.shareContext = true; // we're probably using Starling for a 2D menu/interface, we must listen the enter frame on Stage3DProxy _away3D.stage3DProxy.addEventListener(Event.ENTER_FRAME, handleEnterFrame); removeEventListener(Event.ENTER_FRAME, handleEnterFrame); } addChildAt(_away3D, _stateDisplayIndex); if (debugMode) addChild(new AwayStats(_away3D)); } This is the basis code to create a game with Away3D and the Citrus Engine: import citrus.core.away3d.Away3DCitrusEngine; public class Main extends Away3DCitrusEngine { public function Main() { } override protected function handleAddedToStage(e:Event):void { super.handleAddedToStage(e); setUpAway3D(true); state = new Away3DGameState(); } } **Note** it's also possible to combine a 3D game using Away3D with a 2D interface made with Starling thanks to [[citrus:stage3d_interoperation|Stage3D Interoperation]].