Jump to content

Hide portions of tilemap (fog of war)


pinusc
 Share

Recommended Posts

Hi all.

I am writing a roguelike game using Phaser and in particular I am using the TileMap feature.

I need to restrict the user's field of view, so that the player can't see tiles that are not lit, and to do so, I have a working Line Of Sight algorithm that computes which tiles are not visible. 

The problem is that I don't know how to actually hide these tiles. Since they haven't got a "visible" attribute, I tried setting their "alpha" to 0, but I noticed a consistent performance issue that makes the game unplayable on mobile. 

How can I efficiently hide tiles?

Link to comment
Share on other sites

  • 1 year later...

This is probably the direction I would investigate: I would create a 2D array that correlates to the stage. In the elements of this array (with each one representing one tile) you can note whether that tile should be drawn or not. Then you have your actual tilemap object. I would create a "master" tilemap object that will always contain the tiles for the map. But then I would have another tilemap object that we will call the "visible" tilemap object that I fill only with the tiles that are visible. When you run the LoS algorithm, you can set bool values in your 2D array to determine what tiles will be drawn and then use that array to copy tile data from the master tilemap object to the visible tilemap object (or maybe you could do this directly with your algorithm and not even use the 2D array but that may be mixing a lot of logic into one place and could get messy). Then use your "visible" tilemap to actually set the tilemap to be drawn, thus only showing the tiles you want to. 

Note that I have not done this before and there may be some attribute I am missing that would make this much easier or more performant. You may also be able to use the method call shown in the Fill Tiles example to simply swap out the tiles you don't want to show with a black tile or whatever your background color is (even though this example seems to be messed-up for me for some reason, the method call itself should work). In this case you would still need some kind of object or 2D array to keep track of what the tile is supposed to be when it is visible. 

You may just need to play around and see which technique is more performant and/or easier to work with. 

Link to comment
Share on other sites

What I did on another game (Using Box2D) was to create a floating canvas to render the fog.

<canvas id="fog"></canvas>
<script>
		Game.fog = document.getElementById("fog");
		Game.fog.width = Game.canvasSize;
		Game.fog.height = Game.canvasSize;
		Game.fog.context = Game.fog.getContext("2d");
		Game.fog.context.fillStyle = 'black';
		Game.fog.context.fillRect(0, 0, Game.canvas.width, Game.canvas.height);
		Game.fog.context.globalCompositeOperation = 'destination-out';
    	touchCanvas = Game.fog;

		Game.fog.context.save();
		Game.fog.context.globalCompositeOperation = 'source-over';
		Game.fog.context.fillRect(0, 0, Game.canvas.width, Game.canvas.height);
	    Game.fog.context.restore();
		Game.fog.context.globalCompositeOperation = 'destination-out';

		Game.fog.context.save();
		
		var x = Game.player.x*Game.scale;
		var y = Game.player.y*Game.scale;
		var grad = Game.fog.context.createRadialGradient(x, y, 0, x, y, Game.scale*1.5);
		
		grad.addColorStop(0, "rgba(0, 0, 0, 1)");
		grad.addColorStop(.5, "rgba(0, 0, 0, .1)");
		grad.addColorStop(1, "rgba(0, 0, 0, 0)");
		
		Game.fog.context.beginPath();
		Game.fog.context.fillStyle = grad;
		Game.fog.context.arc(x, y, Game.scale, 0, 2 * Math.PI, !1);
		Game.fog.context.fill();
		Game.fog.context.restore();
</script>

You track the character position and then use the Path to clean the area. I could send the entire code if you like.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...