This project is read-only.

Simulating "Fog of War" on WP7, WP8

Topics: Sprites and SpriteBatch, Windows Phone 7
Jul 23, 2014 at 3:42 AM
Hi,
I would like to know if you have any idea how I could simulate a "fog of war" effect on my game.
Basically I have a single map image (no tiles here, it's the world map and not the in-game map), where I would like to hide some parts not yet discovered.
If possible, I don't want to split the map in multiple parts, but that could be an alternative.

Browsing around, my understanding is that I should use "shaders" or "custom shaders", which I have no idea how to work with, but my guess is they're not implemented in cocos2-xna.

Is there any alternative? Using blending modes or overlaid images.

I target WP7, WP8, Android and IOS.

Regards
Jul 23, 2014 at 5:09 PM
This question is very vague and hard to answer.
  1. WP7 does not support custom shaders. If you target WP7 then you are limited
  2. Cocos2D-XNA supports effects like any other XNA project. You define your own HLSL effects and it runs them. Read an XNA book to learn more about using XNA and the rendering capabilities of that framework.
If all you are looking for is a way to hide a map region, then use an overlay texture, like a fog/cloud sprite. Draw that over the tile that is not known to the player. That's the easiest solution to all of this. Using a shader is over-kill.

If you don't want to use an overlay, then use the fade effects to fade out regions of the map.

You say that you have a single image map, ok. So you define a sprite called Map:

CCSprite map = new CCSprite("myMap");

Next you want to hide regions on that map where the user has not visited.

CCSprite fog = new CCSprite("fog"); // cooler thing to do here is use a fog animation

Now you place your stuff:

AddChild(map, 0);
foreach(var region in myMapModel) {
CCSprite fog = new CCSprite("fog"); // cooler thing to do here is use a fog animation
AddChild(fog, 1);
fog.Position = region.CenterInMap;
// If region is a large area, then make lots of fog instances
}

You want to use a sprite batch node to make the rendering faster. Coalesce your images into sprite sheets that make sense so that you can use a single sprite sheet per scene.
Jul 24, 2014 at 2:46 AM
Hi,
you're very helpful as always.
The effect I'm trying to create is very similar to this:

http://www.gaming-blog.co.uk/wp-content/uploads/2014/01/0.jpg
http://images.gameskinny.com/gameskinny/7998bb42ec4ea0c520ebf94ae87fb0bc.jpg

Yes I know I could do an overlay, but as I have about 10 regions in my map, that would mean creating 10 versions of the overlay fog (one where only the first city is visible, one where 2 cities are visible and so on). Also that would mean the user cannot discover the regions in a random order.

The map is not made of tiles, a "region" is not a square, and it overlaps with other regions.

My guess is I would need something like this:
http://forum.cocos2d-swift.org/t/dynamic-lighting-shader-with-cocos2d-v2-0-and-ccspritebatchnode/11004

But if it's not supported by WP7, I will just skip the fog, it's not vital to the game.

Thanks
Kind regards
Jul 24, 2014 at 4:34 PM
The dynamic lighting effect can be done with the XNA SpriteBatch (CCSpriteBatchNode in our world). You would have to take their GLSL shader program and convert it to HLSL, then run it through the FX processor in XNA, or MGFX for the MonoGame version of the effect. Then you just load the effect at runtime, and add it to the render pipe using the CCDrawManager.

On WP7 though you can't do this kind of effect processing. Those devices don't have the hardware for effect processing like this.

You can do it without the shader, and it's far more versatile. Here you use a CCSpriteBatchNode that utilizes several different types of overlays.

Each overlay is a different opacity and fill. You mark out a grid on your map, it can be any size really, say 10x10, but you can make it 100x100. The sprite batch node can handle a pretty good number of sprites to render, but no more than 65535. this is the visibility grid.

On the visibility grid you keep track of here the player is located. From the player's location, you draw out a circle that is immediately visible, so you set those sprite in that circle to be invisible. Then you have another radius where the visibility is 80%, so you set the opacity to 0.8, and then another radius for less, and so on... If you make the visibility overlay sprites small enough then you can get a very fine grained appearance of visibility on the map.

This technique is more versatile because it allows you to use any image as your "cloud" or fog. The shader doesn't really let you do that. It just variably sets the opacity and tint of the polygons around a specific point.