09 May 2013

Been using Citrus Engine for my several projects, but I never used any level editors, even if it’s possible to use Flash Pro as level editor. So, I think I need to give a try for CE supported level editors: Gleed2D, Level Architect, Tiled Map Editor, and Flash Pro itself.

Level Architect is eliminated early since it’s obsolete and not supported by latest CE version. Flash Pro might be great, but not what I’m looking for. I prefer a tile-based editors.
Why? because it’s the most efficient way to make a various level with very minimal assets. Creating a whole different art scene for each level will be a pain on my ass. Not to mention if it will also increase a lot of your file size.

I also tried Gleed2D, although it’s not a tile-based editor, but unfortunately Gleed2D crashed without any clear reasons when I attempting to open this application.

In the end, I’m using Tiled Map Editor. And after for about a day tinkering with this tool, and definitely the level editor I’m looking for. 

citrus engine tiled map editor

So, how to set-up this tool with CE? As I told before, it’s the level editor supported by CE, so there is a built-in parser on CE to read Tiled Map Editor file format (.tmx) which work like a magic… Open-mouthed smile

First things first, before we’re going too far, I just wanna let you know that it’s a CE with Display List mode, not the Starling one. But it could be also used for Starling CE. You can check my latest blog post about that here.

=====================
If you want to read the other Citrus Engine tutorial part, here are all the links:
1. Game Structure
2. Adding Screen Transition
3. Head-Up Display
4. Working with Data
5. Creating Level using Tiled Map Editor
=====================

Getting Started
Alright, let’s create a CE project on your Flash Develop. No more explanation for this step.
So, let’s jump to the next step: Creating the tileset.
tiled map editor citrus engine

For this sample, I’m using this free and cute art from Kenney at OpenGameArt.com. I arranged it into a 64x64 px tileset without spacing. I include anything from the ground tiles, decorations, to sky background. Yep, I’ll use a tiles for background also. Going so retro with no fancy background, and you’ll also lose the parallax function, but it’ll reduce the game resource, a lot.

Working with Tiled Map Editor
Tileset image ready, next step is importing it to the Tiled Map Editor. Open the application, create a new project.
To import the tileset image, go to Map –> New Tileset
tiled map editor citrus engine

Browse to your saved tileset image file. And change the name to the exact same with your tileset image name. In this sample, both image and tileset are named as “Tileset.png”. It’s very important, as the name will be used to parse the map to CE.

When the tileset already imported, you can see your already-sliced tileset appear on the bottom right dock of the app.
tiled map editor citrus engine

Okay, fun time…. click the specified tile and start drawing your game…
tiled map editor citrus engine

All done? Not yet. You need to specify the Citrus Object placement. The platforms, hero, enemies, crates, coins, etc.
How to do that? No worry it’s a piece of cake. Create a new Object Layer:
tiled map editor citrus engine

Now draw the CE objects using this available tools…
tiled map editor citrus engine

tiled map editor citrus engine

See these transparent squares? Yep, it’s the Citrus Objects I’ve drawn.
You can enable the Snap to Grid option on the View toolbar. It will really help to draw a perfect square that will match to the tile size. Will be very usable to draw the platform objects.

Almost done. Now you need to specify each type of the Citrus objects. Right click on the object, select Object Properties. A window will be opened:
tiled9

Object’s name is optional, so you can leave it blank. The most important is its type. Fill it with a complete path of the citrus object. So if it’s a Platform, the type will be: citrus.object.platformer.box2d.Platform as shown on the image above.

Do the same for other platform objects. Wut? Yes, this is the bad things from this app. You can’t change a bunch of objects properties at once and at the same time. So, for non-platform objects like enemy, coin, crates, etc you’d better create one object first, modify the properties, and then duplicate it.
tiled8

For non-platform objects, not much difference. But you can also modify its property in this app. Also, you can specify the view property in here too.
tiled10

The above image shows the property of Hero object. You need to give him a name as we will use it to set up the camera later.
Can you see this properties: canDuck, maxVelocity, view, etc? Yep, that’s the CE Hero object properties. You can simply define them here.

Non-Platform Art Creation
For non-platform objects I use Flash Pro to create its view and animation. Give them their linkage name then compiled them to a SWC file.
For example, I can access the hero view via its linkage name: CharMC.
You can take a look on my  Flash Pro library:
tiled11

The view for moving platforms, crates, coins, & enemies also created via Flash Pro.

Coding Time…
Level creation is done. Open your FlashDevelop project and crate a new state:

package
{     
    import citrus.math.MathVector;     
    import citrus.objects.platformer.box2d.Coin;     
    import citrus.objects.platformer.box2d.Enemy;     
    import citrus.objects.platformer.box2d.Hero;     
    import citrus.objects.platformer.box2d.MovingPlatform;     
    import citrus.objects.platformer.box2d.Platform;
    import citrus.objects.platformer.box2d.Crate;
    import citrus.physics.box2d.Box2D;     
    import citrus.utils.objectmakers.ObjectMaker2D;     
    import flash.display.Bitmap;     
    import flash.geom.Rectangle;     
 
    public class GameState extends State     
    {     
        [Embed(source="../assets/tmx/platformer.tmx", mimeType="application/octet-stream")]     
        private var tileMap:Class;     
        
        [Embed(source="../assets/tmx/Tileset.png")]     
        private var tileView:Class;     
       
        public function GameState()     
        {     
            super();    
           
            var objects:Array = [Hero, Crate, Platform, MovingPlatform, Enemy, Coin];     
        }    
       
        override public function initialize():void     
        {     
            super.initialize();     
            
            var box2D:Box2D = new Box2D("box2D");     
            //box2D.visible = true;     
            add(box2D);     
            
            var bitmapView:Bitmap = new tileView();     
            bitmapView.name = "Tileset.png";     
           
            ObjectMaker2D.FromTiledMap(XML(new tileMap()), [bitmapView]);     
            
            var hero:Hero = getObjectByName("hero") as Hero;     
            
            view.camera.setUp(hero, new MathVector(300, 200), new Rectangle(0, 0, 1472, 576));     
        }     
    }     
}


A pretty minimal code for a game with not-so-basic-level… I don't know smile

16-20: Embed the .TMX and .PNG file.
TMX is a Tiled Map Editor save files. While the PNG is a Tileset image we’ve created before. Give each of them a reference class: tileMap for the map and tileView for its view / tileset image.

26: I don’t know the exact cause, but if you don’t include all used CE objects in this array, you’ll get an error…
I almost gave up using Tiled Map Editor with CE before because of this issue. But after seeing the example here, which mentioned that line, everything work like a charm.

37-38: We need to convert the tileView into a bitmap first. And give it a name.
Exact same name with the tileset image file and also tileset that imported to Tiled Map Editor: Tileset.png

40: Execute the parser function.
The first parameter, we need to convert the tileMap as an XML. And on the second parameter, insert the bitmap into an array.

42-44: That’s why we need to define a name for the hero before… Smile

For the SWC file, don’t forget to add it to your library. Right click –> Add to Library:
tiled12

And change its options (Right click –> Options),  to be like this, or it won’t work at all:
tiled13

Everything done… YAY… Open-mouthed smile

Run Time…
Compile it and see the result…

Issues
Not everything work smoothly like as expected. I found some issues with this method. Well, it must be because of my noobness… Smile with tongue out

1. So far, what I know to define a view for non-platform objects that created on Tiled Map Editor is only can be done via their linkage name on FLA, SWC, or (probably) SWF. And via string of the image path, for example: “../assets/hero/hero.png”

For an assets that embedded via code seems to be not work. I’ve tried it, and don’t know why, the ObjectMaker can’t locate the reference class for the view although it’s already declared on the state class.

Define the view on the code like this also not work.
Hero(getObjectbyName(“hero”)).view = HeroMC;

You’ll get "…must be child of the caller”  error…

But if you create the objects not in the Tiled Map Editor, it will be work normally. But you’ll need to set its position manually on the game level.

2. I have no idea to use multiple tilesets image. It supported on Tiled Map Editor. The CE parser itself also accept array of tilesets, which means I can use multiple image for a map. But when I insert more that one tileset images on the array, I got this error: "ObjectMaker didn't find an image name corresponding to the tileset imagesource name, add its name to your bitmap."
The solution? Simply using all-in-one tileset image.

3. I think there is something weird with the parser. The tile that positioned on the very right side and not in the first row sometimes not drawn. Although it’s shown on Tiled Map Editor, but when the game compiled it’s magically gone…
That’s why I arranged my tileset oddly like this:
tiled14

I keep the last tile on the first row but will leave 5 blank tiles. Not the efficient way to create a tileset, but unfortunately, seems that this is the only way to sort the problem.

4. The position and size unit used on Tiled Map Editor isn’t pixel and I can’t find a way to change it to another format. So it will be quite a mess when you want to match the object size with their view / image size. Also when you want to define a position, like when defining the end position of a moving platform.

5. As mentioned before, you cannot do a ctrl-click to select multiple objects and change their properties at once…

Although there are few spotted issues, using this tool definitely better solution than built the level via hard-code, like what I’ve been done to my several CE games. LOL

Source Code:
download

Just Some Self-Ads…
I sell some game assets on my game asset store, if you’re looking a cheap tileset for your Citrus Engine game… Smile with tongue out
Samples:
platformer tile set for sale
platformer tile set for sale

Or simply take a look to the complete list of the items:

24 comments:

  1. How do you play this game? What should I write in the Citrus Console?

    ReplyDelete
    Replies
    1. No need to write anything into Citrus Console...
      Maybe you need to click the stage to activate the controls...

      Delete
  2. Source code not compiled:(
    [Fault] exception, information=ReferenceError: Error #1065: Variable Crate is not defined.

    ReplyDelete
    Replies
    1. Fixed the exception error... But adding a new glitch... XD

      Delete
    2. Uff, my problem is solved declare new Array with push class from the swc.

      var myObjects:Array = [HeartMC];

      Delete
    3. Could you tell us what the issue was?, I'm getting "variable Platform is now defined".

      Delete
    4. You need to declare all objects used in the game into an array on the constructor, like this:

      var objects:Array = [Hero, Crate, Platform, MovingPlatform, Enemy, Coin];

      Delete
  3. Why this simple game has cca 600 MB in RAM?! Measured value in Scout.

    ReplyDelete
    Replies
    1. Whoa, thanks for pointing out the leaks... I also can see it on the Task Manager...
      Not sure what is the cause, but I'll check it when I have some times... :D

      Delete
    2. Alright, problem fixed...
      The cause is bcoz I create a 100 x 100 tiles map on TiledMapEditor, while the game actually just used 23 x 9 tiles... lol

      Delete
  4. Hi, great stuff! just the kind of thing I guess we all are looking for. Got one question though.
    Using the swc for your game objects still allows them to be starling objects? I mean, are they rendered by Stage3D?
    About performance, wouldn't be better to have those in a spritesheet too?

    Thanks

    ReplyDelete
    Replies
    1. Not sure about that, but I heard there is a Flash MovieClip converter to Starling, right?
      And yes, spritesheet performance is better than movieclip.

      Delete
  5. Same anonymous as before... got an awnser from Aymeric Lamboley in his blog:

    " For a multiplatform development you will use SpriteSheets. You will create the same SpriteSheets with different sizes. SWC is equivalent to assets embedded. So you shouldn’t do that with many assets.

    Blitting uses the display list. Now with Stage3D, you should go on the Starling way instead of blitting."

    Not sure if I should post the URL, anyway, As for what I've understood this SWC trick wouldn't be GPU accelerated.

    Thanks for the fast awnser, no idea about that MovieClip to starling converter.

    ReplyDelete
    Replies
    1. Yep, this tutorial isn't intended for Citrus+Starling/Stage3d things, as I already mentioned on 6th paragraph... :)

      MovieClip converter: https://github.com/zenrobin/FlashMovieClipConverter
      Sounds cool. But Dragon Bones is way cooler for Citrus + Starling... :D

      Delete
  6. Yeah, you made that clear on 6th paragrah, my bad. I'll heck that Starling example you mention there. Great technique anyways, I think I'm gonna love Tiled.

    Thanks

    ReplyDelete
  7. Hi, do you have any tutorials on how to make as3 level editor for flash game?
    If not, is there any hope that you will make it, I cant find anything online, I mean level editor for players?
    This is one simple game with level editor, you can make level, save it, get code and play it.
    Can you help or suggest something?
    Thanks

    ReplyDelete
    Replies
    1. I'm sorry I also haven't had such knowledge yet...

      Delete
  8. http://www.agame.com/game/dino-blitz.html

    I forgot to add link to previous comment.

    ReplyDelete
  9. [Fault] exception, information=ReferenceError: Error #1069: Property setTo not found on flash.geom.Rectangle and there is no default value.

    What's wrong with this?

    ReplyDelete
    Replies
    1. Not sure, but try to target latest Flash Player...

      Delete
    2. This is correct. I suppose the OP never checked back, but this solved the problem for me.

      Delete
  10. " I arranged it into a 64x64 px tileset without spacing."
    This is pretty much where the tutorial stops for me. How do I do the above ?

    ReplyDelete
    Replies
    1. I used CorelDraw to do that. But you can also use this tool: http://renderhjs.net/shoebox/
      Drag & drop your PNG tiles to its 'Sprite Sheet' function. And make sure set the Tex Padding & Tex Extrude to 0.

      Delete
  11. another tile mapping editor www.tile2map.com . Compatible with .tmx and json

    ReplyDelete