TGB 1.7.5 creating a fog of war effect
by Keith Mc Dowell JR · in Torque Game Builder · 07/11/2010 (11:26 pm) · 6 replies
Wondering, if anyone has come across or has explored a fog of war effect? The game being developed for a prototype, is an RTS game, which having a fog of war effect as a nice feature to add to game play. In hints or resources along these lines, would be much appreciated.
#2
I haven’t implemented the fog of war just yet, only been thinking ahead and trying to visual how this might work with TGB. I should mention that I’m using TGB Pro, just in case need to make some modifications to the source code.
The special graphic overlay , you mention in your reply is this something you came up with or found and could you elaborate on the special graphic overlay just a little bit.
I’m guessing the calculation to remove small parts of the fog would be based on the total unit movement in one direction as the unit moves towards the fog area. Depending on the unit size, say 3 units wide would be a calculating point?
Thanks again
07/12/2010 (5:00 pm)
Thanks for the reply Charles,I haven’t implemented the fog of war just yet, only been thinking ahead and trying to visual how this might work with TGB. I should mention that I’m using TGB Pro, just in case need to make some modifications to the source code.
The special graphic overlay , you mention in your reply is this something you came up with or found and could you elaborate on the special graphic overlay just a little bit.
I’m guessing the calculation to remove small parts of the fog would be based on the total unit movement in one direction as the unit moves towards the fog area. Depending on the unit size, say 3 units wide would be a calculating point?
Thanks again
#3
I can't remember if you can fade individual tiles (like a setBlendColor), but you could use an image map that has the alpha channel fading with a gradient, and then have it broken out into frames inside TGB for use with the tilelayer.
Setting the blend color on the actual t2dSceneObjects related to visibility would probably also add to the overall fog of war effect too, either darkening them to solid black or fading them out etc
07/13/2010 (1:14 am)
you can probably use a tilelayer as some sort of coarse representation of fog and gradually fade out or just hide individual tiles as needed, that's what I'd start with at least.I can't remember if you can fade individual tiles (like a setBlendColor), but you could use an image map that has the alpha channel fading with a gradient, and then have it broken out into frames inside TGB for use with the tilelayer.
Setting the blend color on the actual t2dSceneObjects related to visibility would probably also add to the overall fog of war effect too, either darkening them to solid black or fading them out etc
#4
I came up with it off the top of my head as a basic implementation. I didn't bother researching the specifics because it seemed you were still in the conception phase. If you have some code you can post that you need specific feedback on or are just stuck I'll be glad to download it and take a shot it. I'm pretty new to TGB but programming is programming and it's what I'm good at. :-D Look forward to your reply or your posted solution, whichever comes first. :)
To elaborate cover the world with a transparent png that mucks everything up. Then add to each item that can clear the fog of war a clear fog algorithm that basically does a search based on their line of sight and moves the transparency to completely transparent. Since you're applying it to the whole map every draw it should always be current. Once again, probably not the most efficient method just th eone that popped into my brain. :)
Charles
07/13/2010 (6:20 am)
Keith,I came up with it off the top of my head as a basic implementation. I didn't bother researching the specifics because it seemed you were still in the conception phase. If you have some code you can post that you need specific feedback on or are just stuck I'll be glad to download it and take a shot it. I'm pretty new to TGB but programming is programming and it's what I'm good at. :-D Look forward to your reply or your posted solution, whichever comes first. :)
To elaborate cover the world with a transparent png that mucks everything up. Then add to each item that can clear the fog of war a clear fog algorithm that basically does a search based on their line of sight and moves the transparency to completely transparent. Since you're applying it to the whole map every draw it should always be current. Once again, probably not the most efficient method just th eone that popped into my brain. :)
Charles
#5
The transparent png should work, but since we can't do any render to texture stuff with stock TGB it probably wouldn't, since it seems like that would involve writing to the png changing the alpha at different coordinates.
Using a tileLayer would allow portions of it to be removed by hiding or swapping tiles from a gradient imageMap, so it would have the same effect. You'd want to place one mounted to the camera, covering the same area as the camera. The size of the tiles really depends on performance, it seems like something which would need to be updated either every frame, or only when the camera has moved....but that wouldn't factor in moving sceneObjects that are gradually seeing further outward each frame as they move.
If you had a giant tileLayer covering the entire play area you wouldn't really have the same potential hit of updating every frame, it would be more about individual objects erasing from the tileLayer using clearTile and pickTile. But I don't think it would be as flexible as having a small tileLayer mounted to the camera.
You'd need a method to create bubbles/areas of visibility, maybe with a radius property (or using their size?), probably just placing actual hidden scene objects, and then a method to scan through those objects to see if they are within the camera's view area. You might want objects in the game to have their own visibility bubbles/areas so mounting a bubble to any other object should work just fine.
After doing that you could clear the appropriate tiles at their positions (clearTile or setStaticTile), using a combination of pickTile and pickRadius/pickRect....possibly even screen space to world space thrown in there depending on how you're unveiling stuff.
If you were using setStaticTile you could ramp a tile through frames of a gradient imageMap, offering gradual changes in transparency or stylized dithering instead of transparency.
Another option would be to create simple fuzzy/noise particle FX around the edges of clear tiles, to soften out or generally camouflage the coarseness of the tileLayer, depending on the tile size... it would be similar to how some games treat the hard edges of dynamic shadow maps.
07/13/2010 (10:42 am)
I will eventually be needing some sort of fog of war thing too so I was thinking some more about it and it seems pretty straightforward to implement using existing TGB functions.The transparent png should work, but since we can't do any render to texture stuff with stock TGB it probably wouldn't, since it seems like that would involve writing to the png changing the alpha at different coordinates.
Using a tileLayer would allow portions of it to be removed by hiding or swapping tiles from a gradient imageMap, so it would have the same effect. You'd want to place one mounted to the camera, covering the same area as the camera. The size of the tiles really depends on performance, it seems like something which would need to be updated either every frame, or only when the camera has moved....but that wouldn't factor in moving sceneObjects that are gradually seeing further outward each frame as they move.
If you had a giant tileLayer covering the entire play area you wouldn't really have the same potential hit of updating every frame, it would be more about individual objects erasing from the tileLayer using clearTile and pickTile. But I don't think it would be as flexible as having a small tileLayer mounted to the camera.
You'd need a method to create bubbles/areas of visibility, maybe with a radius property (or using their size?), probably just placing actual hidden scene objects, and then a method to scan through those objects to see if they are within the camera's view area. You might want objects in the game to have their own visibility bubbles/areas so mounting a bubble to any other object should work just fine.
After doing that you could clear the appropriate tiles at their positions (clearTile or setStaticTile), using a combination of pickTile and pickRadius/pickRect....possibly even screen space to world space thrown in there depending on how you're unveiling stuff.
If you were using setStaticTile you could ramp a tile through frames of a gradient imageMap, offering gradual changes in transparency or stylized dithering instead of transparency.
Another option would be to create simple fuzzy/noise particle FX around the edges of clear tiles, to soften out or generally camouflage the coarseness of the tileLayer, depending on the tile size... it would be similar to how some games treat the hard edges of dynamic shadow maps.
#6
Here is the complete project.
Basically, I created a tile map that covers the scene, added a polygon with the asteroids behavior as the player.
Classed the tile map as fogOfWarClass and added the following code:
There's lots of room for improvement but it's a start.
07/16/2010 (2:27 am)
So I read your guys posts and got to thinking that I could use some of the code from my Fill Clone concept to create a fog of war effect. It's far from optimized but it's working pretty well.Here is the complete project.
Basically, I created a tile map that covers the scene, added a polygon with the asteroids behavior as the player.
Classed the tile map as fogOfWarClass and added the following code:
function fogOfWarClass::onLevelLoaded(%this, %scenegraph)
{
//%scenegraph.setDebugOn(0);
echo("Fog of war tile layer loaded.");
$SG = %scenegraph;
$fogOfWar = %this;
//set all tiles solid black
%this.init();
}
function fogOfWarClass::init(%this)
{
//fill all the tiles black to start
for(%x = 0; %x < %this.getTileCountX(); %x++)
{
for(%y = 0; %y < %this.getTileCountY(); %y++)
{
%this.setStaticTile(%x, %y, solidTileImageMap, 0);
%this.setTileCustomData(%x, %y, 0);
}
}
}
function fogOfWarClass::showFogOfWar(%this)
{
//set some limits to loop through
%maxX = %this.getTileCountX();
%maxY = %this.getTileCountY();
//loop through the tile layer, looking for owned tiles
for( %x = 0; %x < %maxX; %x++ )
{
for( %y = 0; %y < %maxY; %y++ )
{
//get the owner of the current tile (0 = nobody, 1 = ours)
%owner = %this.owner( %x, %y );
// If the tile isn't owned, make it black and bail
if( %owner == 0 )
{
%this.setStaticTile( %x, %y, solidTileImageMap, 0 );
continue;
}
%bits = 0;
// If it's owned choose the correct cell according to it's
// neighbors. This results in a number between 0 and 16
// that corresponds to a cell index in the linked image
// and draws the right one.
%bits |= (%owner != %this.owner(%x, %y - 1)) << 0;
%bits |= (%owner != %this.owner(%x + 1, %y)) << 1;
%bits |= (%owner != %this.owner(%x, %y + 1)) << 2;
%bits |= (%owner != %this.owner(%x - 1, %y)) << 3;
//Thanks Will!
%this.setStaticTile( %x, %y, FogOfWarBordersImageMap, %bits );
}
}
}
function fogOfWarClass::owner( %this, %posX, %posY )
{
//get the owner of a tile
return getWord( %this.getTileCustomData( %posX, %posY ), 0 );
}It performed rather poorly when called from the onUpdate of the asteroids behavior so I put in some code to prevent it from being called every update and I get above 100 fps.There's lots of room for improvement but it's a start.
Torque Owner Charles Thompson