Mini map fog of war
by Jared Barger · in RTS Starter Kit · 11/17/2004 (10:28 am) · 44 replies

Additions below for changing the ugly boxes into squares (Different post in this thread)
11/19 Fixed bug that would cause any visible enemy units to render a vision blob on the minimap (ie. if you could see an enemy you could also see the radius around that unit). Changes are bolded.
First off we need to whip out the mightiness that is paint brush and build the fog image. Just a 16x16 pure black jpg is all we need. Now open up the starter app and add a GuiBitmapCtrl to the MapDisplay group.
r-click MapDisplay in the object list
click new control
select GuiBitmapCtrl
stretch it to fill the MapDisplay except for the border around the map
It should be completely covering the map at this point. Now we want to place this "in the middle" of that group.
With your black image selected go to layout->send to back.
Now select the background image and layout->send to back again.
The MapDisplay group should look like...
MapDisplay - GuiControl
|
|-MapDisplayBackground - GuiBitmapCtrl
|-FogImage - GuiBitmapCtrl
|-MapHud - GuiMapHud
...and the black image you added should be completely covered by the map itself now. Alrighty, done with the boring part.
All the code changes needed are within the engine/game/rts/guiMapHudRender.cc file. So first off back that bad boy up.
Fist we need to setup a little structure to hold onto some data for our units. Below the includes add...
struct ClientUnit{
S32 team;
Point2I point;
};//ClientUnitNext we need to comment out the current calls that render the map. Change...
//render the map dglSetBitmapModulation(ColorF(1.0, 1.0, 1.0)); dglDrawBitmap(mRenderTexture, offset, GFlip_Y);to..
//render the map // dglSetBitmapModulation(ColorF(1.0, 1.0, 1.0)); // dglDrawBitmap(mRenderTexture, offset, GFlip_Y);
Now we need to setup some variables...
Point2I drawChunkPoint; // Will hold a point to render some map at RectI mapRect; // Will hold our source rect from the map image ClientUnit* unitList = 0; // List of important info about our units ClientUnit* unitIter; // To iterate through the list later int listSize = 0; // Count of the unit list int vision = 10; // Unit vision range on the map (in pixels?) [b]RTSConnection* myConn = 0; // Will hold our connection to the game S32 localTeam = 0; // WIll hold our team id [/b]
Now we need to figure out what team we're on
myConn = (RTSConnection*)mConnection->getServerConnection(); localTeam = myConn->getTeam(); // Now get our team id
Now we're gonna need to figure out how many units we have to deal with and allocate the unit list for that.
for(SimSetIterator itr(mConnection); *itr; ++itr){
if((*itr)->getType() & PlayerObjectType) listSize++;
}//for
unitIter = unitList = new ClientUnit[listSize];Ok, here's where most everything is happening. We're going to alter the unit rendering loop to render our map objects and to collect data from our units. We need to hold off on rendering the unit dots to the map until we're done so they don't get covered up by pieces of the map.
Comment out everything from "//render the units" to the beginning of the loop and add in a call to dglSetBitmapModulation so that it looks like this...
//render the units // glPointSize(2.0f); // glColor3f(0.0, 0.0, 1.0); // glBegin(GL_POINTS); // static char buff[18]; // dSprintf(buff, 18, "$Server::TeamInfo0"); dglSetBitmapModulation(ColorF(1.0, 1.0, 1.0));
#22
12/07/2004 (9:08 pm)
If you come up with a good 3d fog of war rendering solution, I'd be interested in hearing about it. :)
#23
Take the problem statement literally: how do we represent 3-D "fog of war"?
Well, we already have fog in Torque--what about simply tightening it up a lot closer, and changing the fog tint to black instead of white? It would take some work to adapt properly for what we want to see, but I think it might be a worthwhile direction to attempt.
The other aspect is being able to visually recognize unit's "in vision range" circles/spheres--so that areas that aren't directely within vision range are "darker" than the areas that are under observation. It might work out to darken the ambient lighting of your mission as a whole, and providing each unit with some form of light source, with limited range.
Just some idle thoughts, I haven't even thought about any implementation for this yet.
12/08/2004 (4:17 am)
Hmm...been brainstorming a bit about this the last couple of days, and it hit me--we're treating this as a procedural problem, when it's really a rendering/artistic problem.Take the problem statement literally: how do we represent 3-D "fog of war"?
Well, we already have fog in Torque--what about simply tightening it up a lot closer, and changing the fog tint to black instead of white? It would take some work to adapt properly for what we want to see, but I think it might be a worthwhile direction to attempt.
The other aspect is being able to visually recognize unit's "in vision range" circles/spheres--so that areas that aren't directely within vision range are "darker" than the areas that are under observation. It might work out to darken the ambient lighting of your mission as a whole, and providing each unit with some form of light source, with limited range.
Just some idle thoughts, I haven't even thought about any implementation for this yet.
#24
1) If we were to take the black fog approach could we have both fogs somehow? My game plans were to have weather in my game (one aspect of which would be regular fog). Using the black fog method I think would preclude that.
2) Making the farther ranged items darker was my other thought or along the light idea maybe using the Lighting Pack some how but I haven't really been exposed to that so I wasn't sure what was/is possible.
3) My final (but I'm sure not last thought) was to shorten the camera's visible length to match whatever unit it was near and somehow cull out anything beyond that distance leaving it as a black void. But that's as far as I've gone with that thinking so far.
12/08/2004 (3:49 pm)
I was thinking the same things along the lines of Josh and Stephen. These are the issues I came up against though:1) If we were to take the black fog approach could we have both fogs somehow? My game plans were to have weather in my game (one aspect of which would be regular fog). Using the black fog method I think would preclude that.
2) Making the farther ranged items darker was my other thought or along the light idea maybe using the Lighting Pack some how but I haven't really been exposed to that so I wasn't sure what was/is possible.
3) My final (but I'm sure not last thought) was to shorten the camera's visible length to match whatever unit it was near and somehow cull out anything beyond that distance leaving it as a black void. But that's as far as I've gone with that thinking so far.
#25
Do you really need "fog of war" in the game world? If so, are you okay with constraining your camera so that you can't change the height and pitch so much? If so, then you're set... adjust height and pitch clamping so that the camera can't view farther than you want your players to be able to see, and then use mini-map fog-of-war.
If you want both fog of war that hides terrain in your game world and a very, very flexible camera.. then realize that you are asking a lot. :) Again, the simplest solution is just to make the mission fog distance very short (and make that server authoritative, if it's not already, I don't know for sure off-hand). If you want something more fancy... have fun! ;) It's an interesting problem to tackle, and we'd be delighted to see an elegant solution arise. I don't know of any RTS game that lets you do this right now though. I suppose if nothing else you could do something like rendering some giant partially-transparent, dark-colored billboards at the edge of your desired viewable camera distance.
Now, if you just want "fog of war" that doesn't render anything special or hide terrain, but simply makes sure players can't see enemy units that aren't in visible range of your units, then that is very doable. That is exactly what the visibility manager was intended to do. Note that there are two parts to this: making sure that the enemy units / buildings don't get rendered, and actually making sure that clients don't receive any information about those units / buildings over the network. The framework to do all this stuff is in place, but the vis manager wasn't implemented according to the intended specification. Stephen has offered to help (thanks Stephen!) rectify that, and I don't expect it'll take very long to get it properly implemented.
12/10/2004 (3:51 am)
Yeah, maybe there are some innovative solutions available, but I really think the above points stand.Do you really need "fog of war" in the game world? If so, are you okay with constraining your camera so that you can't change the height and pitch so much? If so, then you're set... adjust height and pitch clamping so that the camera can't view farther than you want your players to be able to see, and then use mini-map fog-of-war.
If you want both fog of war that hides terrain in your game world and a very, very flexible camera.. then realize that you are asking a lot. :) Again, the simplest solution is just to make the mission fog distance very short (and make that server authoritative, if it's not already, I don't know for sure off-hand). If you want something more fancy... have fun! ;) It's an interesting problem to tackle, and we'd be delighted to see an elegant solution arise. I don't know of any RTS game that lets you do this right now though. I suppose if nothing else you could do something like rendering some giant partially-transparent, dark-colored billboards at the edge of your desired viewable camera distance.
Now, if you just want "fog of war" that doesn't render anything special or hide terrain, but simply makes sure players can't see enemy units that aren't in visible range of your units, then that is very doable. That is exactly what the visibility manager was intended to do. Note that there are two parts to this: making sure that the enemy units / buildings don't get rendered, and actually making sure that clients don't receive any information about those units / buildings over the network. The framework to do all this stuff is in place, but the vis manager wasn't implemented according to the intended specification. Stephen has offered to help (thanks Stephen!) rectify that, and I don't expect it'll take very long to get it properly implemented.
#26
12/10/2004 (10:00 am)
The problem with visualizing fog of war is that it has to effect everything, and it's neither a vertex or material level effect, so it's likely to involve lots of weird and tricky changes. That said I'd love to see somebody pull it off. :) You might be able to generate a FoW texture and multipass it using texgen... I don't know how existing RTS games do it, although since they do everything in custom engines usually it seems likely to be a bit easier.
#27
Has anyone gotten the LOTR RTS yet? Not sure if it's real 3-D, or simulated 3-D, or?
12/10/2004 (10:08 am)
@Ben: I need to do myself some more "current" research on RTS's in general--my last major one was WC3, and I'm sure with the new LOTR one, and Total War out there, some neat new things have been done.Has anyone gotten the LOTR RTS yet? Not sure if it's real 3-D, or simulated 3-D, or?
#28
12/11/2004 (8:07 pm)
I hope to get the LOTR RTS for xmas, and I'll surely be "researching" it a lot. :) (Though, the reviews are really disappointing.) But yeah, it will be interesting to see if they do anything like this. I haven't really checked out Ground Control 2 much yet either. I'm betting that the LOTR game doesn't have fog of war where it blocks out the terrain, since that's pretty silly and unrealistic anyway... it probably just doesn't let you fly your camera around to anywhere except places you have units. For GC2, I believe they simply constrained the camera view, but I hope to found out for sure @ xmas too. ;)
#29
The main concern is that irl, you don't get all that freedom to "look at your terrain from all angles", and therefore there should be some feedback to the player as to what specific terrain areas are actually in view, as opposed to what can be seen from a totally unrestrained camera. Requiring the players to instinctively be able to calculate vision radii based on their unit's positions and therefore their total "in view" areas might not be the best way to do it.
In other words, your above statement is correct in that (smart) commanders get maps of terrain, but they do not get omniscient view of terrain and the abilty to real-time explore it!
12/11/2004 (8:16 pm)
@Josh: my goal isn't necessarily to block out terrain, but it might be appropriate to provide visual feedback to the players about what areas of terrain are actually "currently scouted" by their units, and what isn't. I'm not sure yet, will need some gameplay feedback. Maybe some form of dynamic constraint on the camera position/orientation is more appropriate.The main concern is that irl, you don't get all that freedom to "look at your terrain from all angles", and therefore there should be some feedback to the player as to what specific terrain areas are actually in view, as opposed to what can be seen from a totally unrestrained camera. Requiring the players to instinctively be able to calculate vision radii based on their unit's positions and therefore their total "in view" areas might not be the best way to do it.
In other words, your above statement is correct in that (smart) commanders get maps of terrain, but they do not get omniscient view of terrain and the abilty to real-time explore it!
#30
edit: Well, the FoW stuff is more impressive in later levels. Have to look at it more to see exactly how it works, but they're basically shadowing areas that aren't explored yet.
12/13/2004 (2:15 pm)
I just got to play the first part of the first level in the LOTR RTS. :) Pretty cool looking.edit: Well, the FoW stuff is more impressive in later levels. Have to look at it more to see exactly how it works, but they're basically shadowing areas that aren't explored yet.
#31
As Steph said, its feedback to the players of whats been explored, and unless your literally playing "God" (like Black and White)
you _arent_ omnipitent.
With fog of war, you never know where your enemies are, or resources, and it gives you incentive to explore.
Should I go North? How about South? Is there Gold in them thar hills? You wont know unless you go look!
If I recall, the original Warcraft had fog of war.
The way it has been traditionally done is the entire map is fogged out,
areas that you can immediently see are clear & visible,
areas you have been before are shaded (half visible, all you see is terrain and buildings, no others' people)
03/09/2005 (5:31 pm)
Fog of war isnt "neccessary" at all.. its simply another game feature that works with some games and not others.As Steph said, its feedback to the players of whats been explored, and unless your literally playing "God" (like Black and White)
you _arent_ omnipitent.
With fog of war, you never know where your enemies are, or resources, and it gives you incentive to explore.
Should I go North? How about South? Is there Gold in them thar hills? You wont know unless you go look!
If I recall, the original Warcraft had fog of war.
The way it has been traditionally done is the entire map is fogged out,
areas that you can immediently see are clear & visible,
areas you have been before are shaded (half visible, all you see is terrain and buildings, no others' people)
#32
04/26/2006 (1:47 pm)
Sorry to bring up an old post but somone may be intersested in knowing this, In a book I read that fog of war can be easily faked with lighting. They obviously used this in C&C Generals as you can see the terrain is a darker colour not really "fog". But in empire earth and empires dotmw (same engine I think) it looks as if they have used a 2D animation for the shroud.
#33
This way you get the battle maps that Stephen likes but can still have strategies that need to hide units (ie artillery shelling from out of opponent view range).
11/12/2008 (7:59 pm)
Bumping back to this topic with some new thoughts. Instead of showing fog or "blackness" has anyone tried to just not show units that aren't in view? The dots in the mini-map and/or the models in the main window. You can then possibly add some fog effect to the camera (it already has some, but bring it in closer) for a nice effect. For my own project I would stick with just not showing the dots on the mini-map.This way you get the battle maps that Stephen likes but can still have strategies that need to hide units (ie artillery shelling from out of opponent view range).
#34
Can anyone explain to me what i need to replace this over? (Sorry, Still a little new to this part ;P)
01/02/2009 (12:53 am)
if(projectPoint(unit->getPosition(), &screenPos))
{
/*
S32 team = unit->getTeam(); The original block of code that's removed now
buff[17] = '0' + team;
const char* pref = Con::getVariable(buff);
ColorF teamColor;
dSscanf(pref, "%f %f %f", &teamColor.red, &teamColor.green, &teamColor.blue);
glColor3f(teamColor.red, teamColor.green, teamColor.blue);
glVertex2f(offset.x + screenPos.x, offset.y + screenPos.y);
*/
if(localTeam == unit->getTeam()){ // Only give us map vision for our team
// Get the XY of the upper left corner that the
// unit can see
drawChunkPoint.set(offset.x + screenPos.x - vision, offset.y + screenPos.y - vision);
// Get the rect of the map to render. Since it's flipped
// on the Y axis before rendering we need to "come in"
// from the opposite side
mapRect.set(screenPos.x - vision, mTextureSize - screenPos.y - vision, vision * 2, vision * 2);
// Drop the rect from the map at point drawChunk with
// the clipping rectangle mapRect and then flip it
dglDrawBitmapSR(mRenderTexture, drawChunkPoint, mapRect, GFlip_Y);
// Save the info we'll need to render the blip later
}//if
unitIter->point.set(offset.x + screenPos.x, offset.y + screenPos.y);
unitIter->team = unit->getTeam();
unitIter++;
}Can anyone explain to me what i need to replace this over? (Sorry, Still a little new to this part ;P)
#35
This HOW-TO seems to be for a version of TGE prior to 1.5.2 (or at least it slightly differs from what I see)
Here are the steps I've done:
a) backup guiMapHudRender.cc
b) after the include statements, add the first block of code
c) now comment out the render map functions (~line 28 of original)
d) then add in the code for the new variables on the next line and follow that with the code for finding what team you are on ... and the for loop to count the units.
e) go down a few lines and comment out the render units code and add the dglSetBitmapModulation call.
f) then go down a few lines until you see the if statement (line ~38 original) and make the changes as described.
g) At this point - I'm confused - it says to add the consolidated code for rendering the units -- but doesnt say WHERE to add it ... within the for loop ? after the loop ??
Here is what I have so far ... which is almost there;
Is this correct ? I'm using TGE_1.5.2 and RTS kit for 1.5.2 as well.
01/17/2010 (10:14 pm)
NOTE: This HOW-TO seems to be for a version of TGE prior to 1.5.2 (or at least it slightly differs from what I see)
Here are the steps I've done:
a) backup guiMapHudRender.cc
b) after the include statements, add the first block of code
c) now comment out the render map functions (~line 28 of original)
d) then add in the code for the new variables on the next line and follow that with the code for finding what team you are on ... and the for loop to count the units.
e) go down a few lines and comment out the render units code and add the dglSetBitmapModulation call.
f) then go down a few lines until you see the if statement (line ~38 original) and make the changes as described.
g) At this point - I'm confused - it says to add the consolidated code for rendering the units -- but doesnt say WHERE to add it ... within the for loop ? after the loop ??
Here is what I have so far ... which is almost there;
if (projectPoint(unit->getPosition(), &screenPos))
{
/*
S32 team = unit->getTeam();
buff[17] = '0' + team;
const char* pref = Con::getVariable(buff);
ColorF teamColor;
dSscanf(pref, "%f %f %f", &teamColor.red, &teamColor.green, &teamColor.blue);
glColor3f(teamColor.red, teamColor.green, teamColor.blue);
glVertex2f(offset.x + screenPos.x, offset.y + screenPos.y);
*/
// Only give us map vision for our team
if(localTeam == unit->getTeam())
{
// Get the XY of the upper left corner that the unit can see
drawChunkPoint.set(offset.x + screenPos.x - vision, offset.y + screenPos.y - vision);
// Get the rect of the map to render. Since it's flipped
// on the Y axis before rendering we need to "come in"
// from the opposite side
mapRect.set(screenPos.x - vision, mTextureSize - screenPos.y - vision, vision * 2, vision * 2);
// Drop the rect from the map at point drawChunk with
// the clipping rectangle mapRect and then flip it
dglDrawBitmapSR(mRenderTexture, drawChunkPoint, mapRect, GFlip_Y);
// Save the info we'll need to render the blip later
}//if
unitIter->point.set(offset.x + screenPos.x, offset.y + screenPos.y);
unitIter->team = unit->getTeam();
unitIter++;
glPointSize(2.0f);
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_POINTS);
static char buff[18];
dSprintf(buff, 18, "$Server::TeamInfo0");
unitIter = unitList; // Reset the iterator
for(int i = 0; i < listSize; i++)
{
buff[17] = char(48) + unitIter->team; // forum font doesn't seem to like single quotes...char(48) == '0'
const char* pref = Con::getVariable(buff);
ColorF teamColor;
dSscanf(pref, "%f %f %f", &teamColor.red, &teamColor.green, &teamColor.blue);
glColor3f(teamColor.red, teamColor.green, teamColor.blue);
glVertex2f(unitIter->point.x, unitIter->point.y);
unitIter++;
} // for
glEnd();
}
}
}
}
// glEnd();
delete []unitList; // Cleanup!Is this correct ? I'm using TGE_1.5.2 and RTS kit for 1.5.2 as well.
#36
01/17/2010 (10:20 pm)
My guess is it needs to be after the original for loop ... right after the glEnd(); code ... next line, since it resets the iterator.
#37
15>..\engine\game\RTS\guiMapHudRender.cc(39) : error C2039: 'getServerConnection' : is not a member of 'GameConnection'
15> ../engine\game/gameConnection.h(41) : see declaration of 'GameConnection'
01/17/2010 (10:31 pm)
moved it after the glEnd() like I thought ... and getting compile errors;15>..\engine\game\RTS\guiMapHudRender.cc(39) : error C2039: 'getServerConnection' : is not a member of 'GameConnection'
15> ../engine\game/gameConnection.h(41) : see declaration of 'GameConnection'
#38
After some digging around, I tried this instead;
Will see if that works, at least it compiles w/o complaint now.
01/17/2010 (10:40 pm)
I'll assume this was due to TGE 1.5.2 changes ... considering this post started in 2004.After some digging around, I tried this instead;
// myConn = (RTSConnection*)mConnection->getServerConnection(); // localTeam = myConn->getTeam(); // Now get our team id myConn = (RTSConnection*)mConnection->getConnectionToServer(); // getConnectionToServer()->getId() localTeam = myConn->getId(); // Now get our team id
Will see if that works, at least it compiles w/o complaint now.
#39
01/17/2010 (10:55 pm)
It runs, and I see blue dots ... but the fog isn't cleared by my units.
#40
This is what it should be;
Now it works, but I want to change it from RECTS to CIRCLES
01/17/2010 (10:59 pm)
Aha! Its my own error now.This is what it should be;
myConn = (RTSConnection*)mConnection->getConnectionToServer(); localTeam = myConn->getTeam(); // Now get our team
Now it works, but I want to change it from RECTS to CIRCLES
Torque Owner Josh Williams
Default Studio Name
If you want both a very flexible camera (more flexible than most RTSs, as it exists now) and the ability to hide undiscovered terrain, then yes, you will have to do some custom work.. unless you are satisfied just making the view / fog distance in the mission very short. However, if you don't really care about hiding the terrain itself (most commanders in any kind of war would normally know the kind of terrain they'll be encountering, just not necessarily the enemy positions)... that is a pretty easy problem to solve.
The visibility manager is intended to do some of what's described in the last sentence, but you might want a different / more precise implementation for your game. Check out the resources forum for a nice little addition to the visibility manager for now, and I imagine that we'll be seeing more updates to it in the future.