{"id":264,"date":"2011-05-15T22:00:00","date_gmt":"2011-05-15T21:00:00","guid":{"rendered":"http:\/\/www.aymericlamboley.fr\/blog\/?p=264"},"modified":"2014-11-01T15:08:50","modified_gmt":"2014-11-01T14:08:50","slug":"create-objects-and-art-in-the-citrus-engine","status":"publish","type":"post","link":"http:\/\/www.aymericlamboley.fr\/blog\/create-objects-and-art-in-the-citrus-engine\/","title":{"rendered":"Create objects and Art in the Citrus Engine"},"content":{"rendered":"<p>Update : if you want a version with a SWC for targeting iOS, please refers to this <a href=\"http:\/\/www.aymericlamboley.fr\/blog\/finally-using-swc-in-the-citrus-engine\/\" target=\"_blank\"><strong>post<\/strong><\/a>.<\/p>\n<p>Hey ! I started to make my school game project this week. I advance quickly, it should be fine for the end of june !<\/p>\n<p>For this third tutorial on the Citrus Engine, I explain better how you can use the Flash IDE as Level Editor, and I show two classes that I&#8217;ve created for my game. <a target=\"_blank\" href=\"http:\/\/www.aymericlamboley.fr\/blog\/wp-content\/uploads\/2011\/05\/bin\/index.html\"><strong>Here is what you will have<\/strong><\/a>.<\/p>\n<p><!--more--><\/p>\n<p>Same as the last tutorial, create a fla and your MovieClips with params. This is my level :<br \/>\n<img decoding=\"async\" src=\"http:\/\/www.aymericlamboley.fr\/blog\/wp-content\/uploads\/2011\/05\/level.png\" alt=\"This is my level\" \/><br \/>\nAdding platforms is always a difficult task, because of the rectangle&#8217;s angle. Try to don&#8217;t have corner ! A box2D platform with a rounded edge would be nice !<\/p>\n<p>You can see the box2D objects on the game by opening the console with the TAB key, and write : <em>set Box2D visible true<\/em><\/p>\n<p>You should make several layers to handle the depth of field ! You can use a guide with your photoshop level to see it and set your layers. When you export your SWF, the photoshop layer will not be added. Your swf stay light \ud83d\ude09 <img decoding=\"async\" src=\"http:\/\/www.aymericlamboley.fr\/blog\/wp-content\/uploads\/2011\/05\/scenario.png\" alt=\"This is my layers\" \/><\/p>\n<p>All my decorations are on several layers. Background, Bg Elements and Grass are big PNG 1409 * 637. I put them on the top left corner. If the length of the level is higher than 4000, you can use negative coordinates. So your level max length will be approximately 7500 px !<\/p>\n<p>We have already seen how you can add a view and params in your MovieClip :<\/p>\n<pre lang=\"actionscript3\">var className = \"objects.Roseau\";\r\nvar params = {\r\n\tview: \"objects\/Roseau.swf\"\r\n}\r\n\r\nvar className = \"objects.MusicalSensor\"\r\nvar params = {\r\n\tsong: \"Si\"\r\n}<\/pre>\n<p>I created 4 MusicalSensor&#8217;s MovieClip, because I have 4 songs, I create one MovieClip by song. This is two new objects that I&#8217;ve created for my game. I will show their classes later.<\/p>\n<p>Here is my Class Document :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">package {\r\n\r\n\timport com.citrusengine.core.CitrusEngine;\r\n\t\r\n\timport flash.display.Loader;\r\n\timport flash.display.MovieClip;\r\n\timport flash.events.Event;\r\n\timport flash.net.URLRequest;\r\n\timport flash.text.TextField;\r\n\r\n\t\/**\r\n\t * @author Aymeric\r\n\t *\/\r\n\tpublic class Main extends CitrusEngine {\r\n\t\t\r\n\t\tpublic var loading:TextField;\r\n\r\n\t\tpublic function Main() {\r\n\r\n\t\t\tsuper();\r\n\t\t\t\r\n\t\t\tsound.addSound(\"Si\", \"sounds\/si.mp3\");\r\n\t\t\tsound.addSound(\"Do\", \"sounds\/do.mp3\");\r\n\t\t\tsound.addSound(\"Re\", \"sounds\/re.mp3\");\r\n\t\t\tsound.addSound(\"Mi\", \"sounds\/mi.mp3\");\r\n\t\t\t\r\n\t\t\tvar loader:Loader = new Loader();\r\n\t\t\tloader.load(new URLRequest(\"levels\/LevelA1.swf\"));\r\n\t\t\tloader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleSWFLoadComplete);\r\n\t\t}\r\n\t\t\r\n\t\tprivate function handleSWFLoadComplete(evt:Event):void {\r\n\t\t\t\r\n\t\t\tvar levelObjectsMC:MovieClip = evt.target.loader.content;\r\n\t\t\tstate = new GameState(levelObjectsMC, loading);\r\n\t\t\t\r\n\t\t\tevt.target.removeEventListener(Event.COMPLETE, handleSWFLoadComplete);\r\n\t\t\tevt.target.loader.unloadAndStop();\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>The loading TextField come from the stage (not the level stage). I add 4 sounds that I use later.<\/p>\n<p>The game state :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">package {\r\n\t\r\n\timport Box2DAS.Dynamics.ContactEvent;\r\n\r\n\timport com.citrusengine.core.CitrusEngine;\r\n\timport com.citrusengine.core.CitrusObject;\r\n\timport com.citrusengine.core.State;\r\n\timport com.citrusengine.math.MathVector;\r\n\timport com.citrusengine.objects.CitrusSprite;\r\n\timport com.citrusengine.objects.platformer.Hero;\r\n\timport com.citrusengine.objects.platformer.Platform;\r\n\timport com.citrusengine.objects.platformer.Sensor;\r\n\timport com.citrusengine.physics.Box2D;\r\n\timport com.citrusengine.utils.ObjectMaker;\r\n\t\r\n\timport objects.MusicalSensor;\r\n\timport objects.Roseau;\r\n\r\n\timport flash.display.MovieClip;\r\n\timport flash.geom.Rectangle;\r\n\timport flash.text.TextField;\r\n\r\n\t\/**\r\n\t * @author Aymeric\r\n\t *\/\r\n\tpublic class GameState extends State {\r\n\t\t\r\n\t\tprivate var _ce:CitrusEngine;\r\n\t\tprivate var _levelObjectsMC:MovieClip;\r\n\t\tprivate var _loading:TextField;\r\n\r\n\t\tpublic function GameState(levelObjectsMC:MovieClip, loading:TextField) {\r\n\r\n\t\t\tsuper();\r\n\t\t\t\r\n\t\t\t_ce = CitrusEngine.getInstance();\r\n\t\t\t\r\n\t\t\t_levelObjectsMC = levelObjectsMC;\r\n\t\t\t_loading = loading;\r\n\t\t\t\r\n\t\t\tvar objects:Array = [Platform, Hero, CitrusSprite, Sensor, MusicalSensor, Roseau];\r\n\t\t}\r\n\r\n\t\toverride public function initialize():void {\r\n\r\n\t\t\tsuper.initialize();\r\n\r\n\t\t\tvar box2D:Box2D = new Box2D(\"Box2D\");\r\n\t\t\tadd(box2D);\r\n\r\n\t\t\tview.loadManager.onLoadComplete.addOnce(handleLoadComplete);\r\n\r\n\t\t\tObjectMaker.FromMovieClip(_levelObjectsMC);\r\n\t\t\t\r\n\t\t\tvar hero:Hero = Hero(getObjectByName(\"Hero\"));\r\n\t\t\t\r\n\t\t\tview.setupCamera(hero, new MathVector(320, 240), new Rectangle(0, 0, 1409, 637), new MathVector(.25, .05));\r\n\t\t\t\r\n\t\t\tvar roseaux:Vector.<CitrusObject> = getObjectsByType(Roseau);\r\n\t\t\tfor each (var roseau:Roseau in roseaux) {\r\n\t\t\t\troseau.onBeginContact.add(_roseauTouche);\r\n\t\t\t\troseau.onEndContact.add(_roseauFin);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tvar musicalSensors:Vector.<CitrusObject> = getObjectsByType(MusicalSensor);\r\n\t\t\tfor each (var musicalSensor:MusicalSensor in musicalSensors) {\r\n\t\t\t\tmusicalSensor.onBeginContact.add(_playSound);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\toverride public function update(timeDelta:Number):void {\r\n\t\t\t\r\n\t\t\tsuper.update(timeDelta);\r\n\t\t\t\r\n\t\t\tvar loaded:int = Math.round(view.loadManager.bytesLoaded \/ view.loadManager.bytesTotal * 100)\r\n\t\t\tif (loaded < 100)\r\n\t\t\t\t_loading.text = loaded.toString();\r\n\t\t\telse\r\n\t\t\t\t_loading.text = \"\";\r\n\t\t}\r\n\r\n\t\tprivate function handleLoadComplete():void {\r\n\t\t\t\/\/remove loader\r\n\t\t}\r\n\t\t\r\n\t\tprivate function _roseauTouche(cEvt:ContactEvent):void {\r\n\t\t\t\r\n\t\t\tif (cEvt.other.GetBody().GetUserData() is Hero) {\r\n\t\t\t\tcEvt.fixture.GetBody().GetUserData().anim = \"white\";\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tprivate function _roseauFin(cEvt:ContactEvent):void {\r\n\t\t\t\r\n\t\t\tif (cEvt.other.GetBody().GetUserData() is Hero) {\r\n\t\t\t\tcEvt.fixture.GetBody().GetUserData().anim = \"black\";\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tprivate function _playSound(cEvt:ContactEvent):void {\r\n\r\n\t\t\tif (cEvt.other.GetBody().GetUserData() is Hero) {\r\n\t\t\t\t_ce.sound.playSound(cEvt.fixture.GetBody().GetUserData().song, 1, 0);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n}<\/pre>\n<p>Roseaux are reeds (it's French \ud83d\ude42 ), when my hero touches them the light change into white, otherwise it's black. My roseau is a swf with three labels : idle (black), white (black to white) and black (white to black). To change my label into the Citrus Engine, we may use <em>myRoseau.gotoAndPlay(\"white\");<\/em> but it doesn't work ! Indeed, Citrus objects are always updated in an enter frame so it \"stays\" on the same frame ! To do that, we use the animation property of Citrus' objects :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">package objects {\r\n\r\n\timport com.citrusengine.objects.platformer.Sensor;\r\n\r\n\t\/**\r\n\t * @author Aymeric\r\n\t *\/\r\n\tpublic class Roseau extends Sensor {\r\n\t\t\r\n\t\tprivate var _anim:String = \"idle\";\r\n\r\n\t\tpublic function Roseau(name:String, params:Object = null) {\r\n\t\t\tsuper(name, params);\r\n\t\t}\r\n\r\n\t\toverride public function update(timeDelta:Number):void {\r\n\r\n\t\t\tsuper.update(timeDelta);\r\n\r\n\t\t\tupdateAnimation();\r\n\t\t}\r\n\r\n\t\tprivate function updateAnimation():void {\r\n\t\t\t\r\n\t\t\t_animation = _anim;\r\n\t\t}\r\n\r\n\t\tpublic function get anim():String {\r\n\t\t\treturn _anim;\r\n\t\t}\r\n\t\tpublic function set anim(value:String):void {\r\n\t\t\t_anim = value;\r\n\t\t}\r\n\t\t\r\n\t}\r\n}<\/pre>\n<p>My roseau extends Sensor because of the contact with the hero ! And I use it easily :<\/p>\n<pre lang=\"actionscript3\">private function _roseauTouche(cEvt:ContactEvent):void {\r\n\t\t\t\r\n\tif (cEvt.other.GetBody().GetUserData() is Hero) {\r\n\t\tcEvt.fixture.GetBody().GetUserData().anim = \"white\";\r\n\t}\r\n}\r\n\r\nprivate function _roseauFin(cEvt:ContactEvent):void {\r\n\t\r\n\tif (cEvt.other.GetBody().GetUserData() is Hero) {\r\n\t\tcEvt.fixture.GetBody().GetUserData().anim = \"black\";\r\n\t}\r\n}<\/pre>\n<p>Now the musical sensor, it is really a simple sensor, I just added a param song to play :<\/p>\n<pre lang=\"actionscript3\" line=\"1\">package objects {\r\n\r\n\timport com.citrusengine.objects.platformer.Sensor;\r\n\r\n\t\/**\r\n\t * @author Aymeric\r\n\t *\/\r\n\tpublic class MusicalSensor extends Sensor {\r\n\t\t\r\n\t\tpublic var song:String;\r\n\r\n\t\tpublic function MusicalSensor(name:String, params:Object = null) {\r\n\t\t\tsuper(name, params);\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>And I use it like that :<\/p>\n<pre lang=\"actionscript3\">private function _playSound(cEvt:ContactEvent):void {\r\n\r\n\tif (cEvt.other.GetBody().GetUserData() is Hero) {\r\n\t\t_ce.sound.playSound(cEvt.fixture.GetBody().GetUserData().song, 1, 0);\r\n\t}\r\n}<\/pre>\n<p>Instead of cutting my flowers into MovieClip, I just put my musical sensor in front of them. It's a bit lazy, but it is faster to do \ud83d\ude42<\/p>\n<p>You can download my <a target=\"_blank\" href=\"http:\/\/www.aymericlamboley.fr\/blog\/wp-content\/uploads\/2011\/05\/CitrusArt.zip\"><strong>zip<\/strong><\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update : if you want a version with a SWC for targeting iOS, please refers to this post. Hey ! I started to make my school game project this week. I advance quickly, it should be fine for the end of june ! For this third tutorial on the Citrus Engine, I explain better how &hellip; <a href=\"http:\/\/www.aymericlamboley.fr\/blog\/create-objects-and-art-in-the-citrus-engine\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Create objects and Art in the Citrus Engine<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[4,51,33,11],"tags":[20,15,52],"_links":{"self":[{"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/posts\/264"}],"collection":[{"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/comments?post=264"}],"version-history":[{"count":24,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/posts\/264\/revisions"}],"predecessor-version":[{"id":1301,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/posts\/264\/revisions\/1301"}],"wp:attachment":[{"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/media?parent=264"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/categories?post=264"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.aymericlamboley.fr\/blog\/wp-json\/wp\/v2\/tags?post=264"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}