ID:153714
 
I'm happy to say the DDT is back in action, making good progress on a project that's been on our ToDo list since we first got together.

As part of this, we need a good fog of war. I know people have done various approaches to this, and I'm curious what has worked best, or what libraries/demos would be good to look at...
I expirimented with a turf based image overlay system. It worked fairly well, but was rather laggy. I haven't worked on it since the client.images var became accessible though. A modern rewrite of it would be much faster, since I'd only need one image for each state I wanted to display.
Glad to see it back! :)

As for the fog..

When you move, have it loop through a decent sized block(). If the turf's overlays list doesn't contain the 'fog' obj or whichever you use, skip over it. If it does contain it, remove it from the overlays.

I'm guessing this would work.. (Although it wouldn't be ideal for multiplayer)
turf/New()
..();src.overlays+=new/obj/fog
obj/fog/icon='black.dmi'
mob/Move()
..()
var/obj/fog/FogCheck
for(var/turf/CheckTurf in block(locate(src.x-3,src.y-3,src.z),locate(src.x+3,src.y+3,src.z))
for(FogCheck in CheckTurf.overlays) del FogCheck


I can see a few ways of converting this to images, or possibly screen objects, but then you would have to keep an array of some sort, to store which turfs have been uncovered.

There is probably a much better way of doing this, but then again, I'm not very bright. ;)

~>Volte
My current approach to fog of war -- that I'm experimenting with on paper, anyway -- is what I call the "overlapping" system. Essentially, the game compiles a list of all of the different places where fog of war overlaps for all of the players. For example, the default fog is where absolutely no one can see through it. For each separate player, there is another fog type that displays to every other player except that player. Where two players' visual ranges overlap, another fog type is made, which displays to all other players except those for which it overlaps.

This is basically done ad-infinitum: it compiles a list of the different fog types necessary, then creates areas with the fog icon and adds the turfs to the appropriate fog type. In other words, it only uses one image for every different fog type. In an eight-player game where you could only reasonably expect up to three players to be overlapping views at any given time, this means that you could only reasonably expect around 12 different fog types and images, as opposed to world.maxx times world.maxy images.

This is illustrated in this diagram:


Notice that even though there are dozens of turfs within the radii of both players, a total of only 4 images and areas is required. The red player can't see the territory that is in teal, while the blue player can't see the territory that is soft pink. Both players can see each other and can see all of the violet territory. Neither player can see beyond their visual radii, and thus the areas that are dark grey are obscured to both.


This system largely assumes two factors, however. One, that all terrain is visible at the start of the game (since the system isn't designed to remember explored territory, but rather to graphically display what territory is currently visible); and two, that you don't require areas for any other purpose (since adding a turf to an area automatically removes it from any other area it belonged to -- I could use a similar system to Shadowdarke's lighting library, but I figure there's little point, since I'm not planning on releasing this as a library).

In the case of Terra Dominus, this would work wonders, since a modern world has no unexplored territory, and because I'm using different systems to determine territorial boundaries.

I do intend to prototype this system at some point.
In response to Spuzzum
Spuzzum wrote:
This is basically done ad-infinitum: it compiles a list of the different fog types necessary, then creates areas with the fog icon and adds the turfs to the appropriate fog type. In other words, it only uses one image for every different fog type. In an eight-player game where you could only reasonably expect up to three players to be overlapping views at any given time, this means that you could only reasonably expect around 12 different fog types and images, as opposed to world.maxx times world.maxy images.

Good idea. From your description, I'm assuming it's possible to set the icon for an area to an image that has only been sent to certain players, which I hadn't realized.

I'll play around with this also...sounds like it might be a lag-free approach that would do the trick.

There is one typical case of FOW (fog of war) this doesn't cover, which is when a turf can be partially fogged; that is, if you've seen the turf before but don't currently have it in view, then you see a grayed out version of what it looked like back then, which means you don't see units moving through it and such. However, this case, while probably doable by compiling together an image for each turf, is probably to be avoided in BYOND.
In response to Deadron
Deadron wrote:
Spuzzum wrote:
This is basically done ad-infinitum: it compiles a list of the different fog types necessary, then creates areas with the fog icon and adds the turfs to the appropriate fog type. In other words, it only uses one image for every different fog type. In an eight-player game where you could only reasonably expect up to three players to be overlapping views at any given time, this means that you could only reasonably expect around 12 different fog types and images, as opposed to world.maxx times world.maxy images.

Good idea. From your description, I'm assuming it's possible to set the icon for an area to an image that has only been sent to certain players, which I hadn't realized.

Nope, it isn't -- but areas have the unique quirk that one icon applies to every turf the areas encompass. If you apply an image to an area, then every turf that the area encompasses shares that image as well. (Mind you, I haven't tested this theory yet, so I might actually discover that this isn't the case. In such case, however, I'd have to label it as a bug, since it wouldn't be consistent behaviour. ;-))


By the loosest terms, yeah, but by specific terms, it acts as any other image -- not as an icon. The area still has its own icon; the image is added on top of the area's blank icon via the image() proc.

In other words, it works just like applying an image to a turf, but applies the same image on top of every tile the area surrounds. It's probably easier to think of areas as a single tile that gets automatically repeated across the territory it encompasses as far as icons are concerned.


I'll play around with this also...sounds like it might be a lag-free approach that would do the trick.

There is one typical case of FOW (fog of war) this doesn't cover, which is when a turf can be partially fogged; that is, if you've seen the turf before but don't currently have it in view, then you see a grayed out version of what it looked like back then, which means you don't see units moving through it and such. However, this case, while probably doable by compiling together an image for each turf, is probably to be avoided in BYOND.

Yep, my earlier point about the fact that it assumes that the whole map has been explored covered that. A more robust fog of war that requires exploration as well as limited visibility would have to rely on turf images. You could, however, still use the so-called overlapping system for visibility beneath the "unexplored" blackness images.

Actually, now that I think about it, you could expand the overlapping system to factor in explored territory as well as immediate visibility, but then it would grow exponentially in complexity and in the number of images required: player 2 can see this territory (therefore having no images displayed), player 3 has explored this territory but can't see this territory (therefore getting a dither overlay), player 1 can't see this territory and hasn't explored it (therefore getting a black overlay)...
In response to Spuzzum
Spuzzum wrote:
My current approach to fog of war -- that I'm experimenting with on paper, anyway -- is what I call the "overlapping" system. Essentially, the game compiles a list of all of the different places where fog of war overlaps for all of the players. For example, the default fog is where absolutely no one can see through it. For each separate player, there is another fog type that displays to every other player except that player. Where two players' visual ranges overlap, another fog type is made, which displays to all other players except those for which it overlaps.

I haven't gotten to trying fog yet (it can come late, since it's easier to debug a game when you can see the entire map!), but I just remembered that client objects might offer a good solution to this, without the small number of objects but with more simplicity.

You can start out with the client objects set to a higher layer than everything on the map. When a player can see a turf, lower the layer of the client object.

This probably also allows for the faded view -- composite an image of the turf and put that on the client.

I'll try this out and report back...

[edit]
Well, thinking about it this will only work for single-screen games...since I want to be flexible, I'll try the area approach first.
In response to Deadron
Deadron wrote:
Well, thinking about it this will only work for single-screen games...since I want to be flexible, I'll try the area approach first.

I ended up doing a mixture, which, amazingly, worked on the first try. This probably oughta become a library/article sometime.

The approach I settled on is:

The game maintains two areas: unexplored and explored. The unexplored area has a level of 10, and its icon obscures anything on the turf. The explored area has no icon, and doesn't obscure anything.

Once any player sees a turf, the turf moves from unexplored to explored. At this time a fog object is created and placed on the turf; it sends an image to all other players, and keeps a list of those who haven't seen the turf yet (in case the game is saved/loaded, or players log in and out).

Each time an additional player sees the turf, the fog image is removed from their client.images; if all players have seen the turf, the fog object is removed.

This definitely uses a bunch more objects than the pure area approach, but it doesn't use as many as world.maxx * world.maxy, or at least that is unlikely.

Given our map size, the number of fog objects shouldn't be an issue. If we start using very large maps, it might be worth it to explore the pure area approach. The disadvantages are that that is a bit more of a complicated concept, and may be harder to have persist between game sessions.