Sign in to follow this  

preload entity object layers on Tiled, load in game later

Recommended Posts



I find Tiled incredibly convenient for entity placement, in addition to tilemapping obviously. 

My game requirements are to load NPCs at different quests. I'm aware you can easily add new Entities via code like this: MySprite());

But I'd rather define all the objects directly in Tiled, then render them with an option. Renderable offers the ability to setOpacity, but it doesn't seem to affect the visibility of the sprite.

Moreover, I'd rather just have it not be there, but have its space saved on the map ready to load it.

How can I best accomplish this? Perhaps I can create a spawn point object class and assign it an NPC ID?

game.FriendlyNPC = game.NPCEntity.extend({
    init: function(x, y, settings) {
        this._super(game.NPCEntity, "init", [x, y, settings]);


Screen Shot 2018-05-18 at 12.03.14 AM.png



Ended up using Spawn Entity location to spawn the NPC there

		let spawnEntity ='spawnID', 1)[0];

		var obj = {
			poolID : 'FriendlyNPC',
			x : spawnEntity.pos.x,
			y : spawnEntity.pos.y,
			data : {
				width: 16,
				height : 16,
				framewidth : 16,
				frameheight : 16

		var newEntity = me.pool.pull(obj.poolID, obj.x, obj.y,;
		newEntity.z = 44;;


Share this post

Link to post
Share on other sites

What kind of events would trigger the entities to "actually load"? Would it be something that just happens nondeterministically, or when loading the map with certain state? If the latter, I would probably lean toward using a copy of the map with the various different states. I know this won't work for every situation, but it's definitely the easiest to implement.

For a longer-term solution, you might consider using the object layers supported by Tiled. IIRC, you can change the visibility (on/off, but melonJS just uses it to set the entity opacity to 0) and melonJS won't render invisible layers. But the entity would still be active and needs to be "disabled" or else it will continue to be updated and will be included in collision detection tests, etc.

One idea that just came to me is that each object layer can be implemented as a me.Container, if you pass options.flatten=false to me.levelDirector.loadLevel. In short, the most naïve approach is to grab the container reference by the layer's name in the options.onLoaded callback, then remove it from the scene and store it somewhere for later until you need it again. It might look something like this:

me.levelDirector.loadLevel('my_map', {
  flatten: false,
  onLoaded: () => {
    // Save an array of every layer named 'quest' to a global object
    game.quest_layers ='quest');

    // Remove all of the quest layers from the scene
    game.quest_layers.forEach((layer) => {, true); // The second arg preserves the layer

setTimeout(() => {
  // ... Some time passes and we can trigger the quest entities to appear
  // We'll just use a random layer index for illustration ...
  let x = Math.floor(Math.random() * game.quest_layers.length);

  // Remove the layer from the global array, and add it to the scene
  let layer = game.quest_layers.splice(x, 1);;
}, 5000);

This is super simplified. A more complex implementation might take layers by multiple names, and store them in a hash map, or even iterate the entire world container looking for invisible containers... There's a lot that can be done to customize it, but the takeaway is that it's desirable to remove children from the scene graph, and add them back in later. And this can be done with the optional keepalive argument when removing children.

That might be a good place to start, anyway. Hope it helps.

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.