View Profile 3p0ch


Joined on 2/13/10

Exp Points:
722 / 900
Exp Rank:
Vote Power:
5.08 votes
Town Watch
Global Rank:
B/P Bonus:

Making layers do what you want in HaxeFlixel with Ogmo3

Posted by 3p0ch - April 6th, 2020

If you're like me and a newbie to HaxeFlixel working on the Game Jam, and if you're like me and have been looking for some fancy spritesheets to make level maps, then you might've run into this problem too. I found this really nice spritesheet at https://opengameart.org/content/exterior-32x32-town-tileset. But it's a little too nice to use the same sort of approaches that were covered in the HaxeFlixel tutorial, and the issues would become immediately obvious if you tried to work with something like this, so I'm going to break down how I approached it.

First things first, if you look at the spritesheet for a while then you might see that it makes sense to classify tiles into one of three categories. 1) Stuff like the ground, floors, etc that characters should be able to walk over unimpeded. 2) Stuff like tree trunks and building walls that characters shouldn't be able to walk on. 3) Stuff like the tops of trees that should be in the foreground -- characters should be able to walk through those tiles unimpeded, but the tiles should be rendered "above" the characters so it looks like the character is underneath the treetops. Also notice that you've dealt with the first two types of things in the tutorial -- there was a "floor" tile and a "wall" tile and you manually set it where you could walk over floor tiles but were blocked by wall tiels -- but this new slick spritesheet I'm working with is huge and I'm not gonna sit there manually typing out which tiles should be walls and which should be floors. Finally, notice that some tiles like treetops have transparent areas within the tile, and are intended to be placed "on top of" other tiles like grass or a road or whatever so you see the appropriate ground behind the treetop, and the tutorial sure didn't teach how to handle that sort of thing.

So here's what you do. In Ogmo3, go to the Layers screen and add some Tile layers until you have (at least) three layers - I'll call mine "floor", "walls", and "foreground" for each of the three categories I talked about above. Depending on your spritesheet, if you have something like tiles of grass and also tiles with flowers with transparent area around the flowers so the grass can show up behind the flower but they should both still be part of the "floor" layer (rendered behind the characters and not blocking their movement), then you might need to get fancy and do things like have a "floorFront" and "floorBack" layer, but I'm gonna just stick with the three types to illustrate the concept in this post. For the spritesheet I'm working with, all sorts of tiles (floor, walls, and foreground) are scattered around the single spritesheet, so for each of the layers I'm going to have its Tileset be that spritesheet (so they're all looking at the same spritesheet). Also, once you've made the layers, you can drag them up or down on the list of layers. You should make foreground be on the top of the list, then walls, then floor so that Ogmo will show things how you'll ultimately want them to look and make stuff easier to see. The Entities layer can be right next to the walls layer, doesn't matter whether it's just above or just below.

Now when you go to edit levels in Ogmo, you'll see that you can pick which layer you're editing on the far left. You should place a tile on every square of the floor layer, the wall layer should have tiles placed only where you want to block character movement -- characters will be blocked at a tile IF AND ONLY IF there is a tile (any tile) placed there in the walls layer (remember you can delete a tile by right-clicking), and the foreground should have tiles placed only if you want that stuff to be rendered in front of the characters. Now save your level and get to your PlayState.hx file.

Here are key parts of my PlayState() class (note that if the code doesn't all fit in your window there's a horizontal scroll bar at the bottom of the code section), and I'll walk you through it

  var player:Player;
  var map:FlxOgmo3Loader;
  var ground:FlxTilemap;
  var walls:FlxTilemap;
  var foreground:FlxTilemap;
  var dudes:FlxTypedGroup<Dude>;

  override public function create():Void {
    /* Get the level's Ogmo3 tilemap
       In Ogmo3 I made a layer called floor with stuff like grass that should just be background,
       a layer called walls with stuff that the player and enemies should collide with and not walk through,
       and a layer called foreground with stuff like treetops that should be rendered in front of the player
       and enemies but shouldn't block them from moving on that tile.
    map = new FlxOgmo3Loader("assets/data/haxeFlixelJam.ogmo", "assets/data/" + Main.currentLevel.x + "-" + Main.currentLevel.y + ".json");
    ground =     map.loadTilemap("assets/images/tileset_town_multi_v002.png", "floor");
    walls =      map.loadTilemap("assets/images/tileset_town_multi_v002.png", "walls");
    foreground = map.loadTilemap("assets/images/tileset_town_multi_v002.png", "foreground");

    // Add the layers to the scene in the correct order (draw ground, then walls on top of ground,
    // then foreground on top of everything else)

    // Add the characters to the level
    player = new Player(Main.playerSpawn.x, Main.playerSpawn.y);
    dudes = new FlxTypedGroup<Dude>();
    map.loadEntities(placeEntities, "entities");

    // Add the foreground last (so it's rendered on top of the player & enemies)


  override public function update(elapsed:Float):Void {

    // Make anything in the walls layer block movement
    FlxG.collide(player, walls);

You'll have a map:FlxOgmo3Loader variable to put the Ogmo3 loader into just like in the tutorial. Then we make three calls so the ground, walls, and foreground FlxTilemap variables are set by using map.loadTilemap(), where the second parameter is the name of the layer from Ogmo3 that we're reading in.

Next thing to notice is that it matters what order you list things when you use the add() function. HaxeFlixel will draw things in the order that it sees them, so you want the ground to be drawn first, then walls and characters drawn next so they end up being drawn on top of the ground, then foreground drawn last so it's on top of everything else. If you have more stuff to add like textboxes that should be in front of even the foreground, then of course add them later.

Last thing to notice is that all you've got to do to make walls block movement is to add lines to the update() function specifying what should be blocked by walls. In this case I'm showing it for the player, but you would also want to have similar lines making the walls block enemies and projectiles and anything else that should be blocked. Notice that you don't need to specify which tiles block movement and which ones don't, by default HaxeFlixel will make every non-empty tile in a layer block movement, which is why I stressed to only put tiles in the walls layer in Ogmo3 if you want those tiles to block movement.

And that's it, now you know how to work with a slick spritesheet like this in Ogmo3 and bring it into your HaxeFlixel game!