• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

SOLVED How can I display some objects above a surface and some objects below it?

M

Maker90

Guest
I'm wanting to make a fog-of-war that allows the terrain to be seen, but the players, items, bullets, and so on, not be seen unless within LOS of a player. How can I do this? I am not against using a different fog-of-war system though I'd like to avoid doing this as the system I'm using now seems easier than the other method I've seen. I am currently using surfaces as it appears to be the more easily implemented system, but apparently there's another way to do it, using tiles, which I'm not familiar with.

The code of the oFogOfWar object that I'm currently using:

Create Event
GML:
fog_of_war = surface_create(room_width, room_height);

surface_set_target(fog_of_war);
draw_clear_alpha(c_black, 1);

surface_reset_target();
Draw Event
GML:
if (room == rGame)
{
    if (!surface_exists(fog_of_war))
    {
        fog_of_war = surface_create(room_width, room_height);
   
        surface_set_target(fog_of_war);
        draw_clear_alpha(c_black, 1);

        surface_reset_target();
    }

    draw_surface(fog_of_war, 0, 0);
}

surface_set_target(fog_of_war);
draw_clear_alpha(c_black, 1);

surface_reset_target();

surface_set_target(fog_of_war);

with (oLight)
{
    gpu_set_blendmode(bm_subtract);
    draw_sprite_ext(sprLight, 0, x, y, 2, 2, 0, c_white, 0.7);
    gpu_set_blendmode(bm_normal);
}

surface_reset_target();
Clean Up
GML:
if (surface_exists(fog_of_war))
{
    surface_free(fog_of_war);
}
As you can see, it currently redraws behind the player so they can't see where they were previously, only where they are at that exact moment. Which is what I want, with one exception. I want the map that I make (namely, the walls) to be visible, but nothing else. I'm using objects to make my map (namely, multiple instances of an oWall object).
 
I haven't worked with surfaces too much, but to answer your title question:

The first thing I would try to do is put the object with the surface on a separate layer in the room, and then have one instance layer above the surface layer and then one instance layer below the surface layer.

If that doesn't work, the second thing I would try is using draw begin and draw end for the objects you want above or below the surface, and then put draw_self() into those events.
 
M

Maker90

Guest
I haven't worked with surfaces too much, but to answer your title question:

The first thing I would try to do is put the object with the surface on a separate layer in the room, and then have one instance layer above the surface layer and then one instance layer below the surface layer.

If that doesn't work, the second thing I would try is using draw begin and draw end for the objects you want above or below the surface, and then put draw_self() into those events.
I thought of that first bit, but the Room Layers GUI in GMS2 doesn't have an option for creating or manipulating surfaces (it has to be done using GML itself). I can make a new Background, Instance, Tile, or Path layer (and manipulate which draws above the others accordingly), but not a new Surface layer. So with that said, how does do that?

As for the second, I hadn't thought of that. I'll try that immediately. If I'm not mistaken, anything in the Draw Begin event would be below the surface layer, while anything in the Draw End event would be above the surface layer... It just occurred to me, that perhaps if I use surface_set_target() in the Draw End event of the objects I want above the fog of war, that may also work...
 
M

Maker90

Guest
In the Draw End event of the objects I want above the fog of war surface I put:
GML:
surface_set_target(oFogOfWar.fog_of_war);
draw_self();
surface_reset_target();
I put this in the Draw Begin event of the objects I want below the fog of war surface.
GML:
surface_set_target(application_surface);
draw_self();
surface_reset_target();
I realize that "surface_set_target()" and "surface_reset_target" were probably unnecessary (and basically identical to each other as resetting the target returns to drawing on the application surface), but I did that anyways "just in case".

The result was that all objects were drawn above the fog of war surface, with the exception of the room's background layer.
 
M

Maker90

Guest
I may have found a solution by setting the depth variable of the oFogOfWar object. While it works, it means that I need to ensure that oWall objects drawn above the objects that I want to display above the fog of war surface, which is not as aesthetically pleasing (to me) as I'd like (it draws the walls over guns and bullets, so if you shooting into a wall you don't see half the gun or the flash of the bullet).

I suppose a way to solve this would be to adjust each object's depth based upon whether it's within the LOS of the local machine's player so that, as far as they can see, gun, player, and bullet objects, etc., are drawn above the terrain (but when something is outside of their LOS, they're drawn below the terrain, which allows them to disappear behind the fog of war surface).

I'll mark this as Solved a little later today just in case someone else has some advice for me.

Thank you for your help, FlameRooster.
 
I thought of that first bit, but the Room Layers GUI in GMS2 doesn't have an option for creating or manipulating surfaces (it has to be done using GML itself). I can make a new Background, Instance, Tile, or Path layer (and manipulate which draws above the others accordingly), but not a new Surface layer. So with that said, how does do that?
Well, I meant that you could make 3 instance layers inside a room, and have the object drawing the surface be in the middle instance layer. You would put the other objects on the top or bottom instance layers. I would think this should work because this is what room layers are for unless surfaces work differently that I am unaware of.

If changing depth works, putting the object which draws the surface on an instance layer should work as well.
 
Last edited:
M

Maker90

Guest
Ah, I see. I misinterpreted what you were saying and then basically implemented it in a roundabout kind of way. :p
 
Top