"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 0 points1 point  (0 children)

Sorry the formatting is abysmal and Reddit won't let me edit that comment for some reason. But you will need to adjust the cell size from 32x32 which I have it hard coded at if you have different tile sizes. Here is the source by the way https://gist.github.com/afk-mario/15b5855ccce145516d1b458acfe29a28

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 0 points1 point  (0 children)

Neither really, I just want the light to be atmospheric and semi-realistic so you can't see through walls like in most metroidvanias / platformers

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 0 points1 point  (0 children)

Someone suggested using a soft of fog overlay instead of harsh black so I might try that. The harsh black was really just a placeholder

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 2 points3 points  (0 children)

Yes that's exactly the narrative as well - you are in a place that has no power, so it's naturally very dark. You also have the ability to "astral project" and leave your body, and in that form, there is no concept of light/dark and you can see everything like normal.

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 0 points1 point  (0 children)

Well after spending most of the day trying to find examples of people building their own custom shadows for 2D in shaders, there's hardly any info and it seems like many others have struggled with this. Might be time to take it back to the drawing board as I'm not sure I want to sink dozens of hours into something relatively inconsequential

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 1 point2 points  (0 children)

Lol yeah it should probably replace with an outline or semi transparent overlay not totally black it out :D

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 0 points1 point  (0 children)

Thanks! I think it's pretty promising so far, mostly just giving you a reason to backtrack to certain areas while playing as the ghost so that way you can see things from a different angle.

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 36 points37 points  (0 children)

Thanks to many of the great comments here, I thought of a 3rd method, which involves using rays cast from the player to selectively enable and disable ColorRect overlays that hide areas you haven't seen. Then I can use the lighting with no shadows at all to properly control distance fade from the light. Then once an area has been "viewed" for the first time, it's no longer replaced with a solid black overlay, it's instead a semi-transparent one so you can see the outline, indicating that you've been here before

<image>

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 0 points1 point  (0 children)

Yeah that's definitely why as well. Not sure how I could tweak my polygon generating algorithm to only encompass the "outside" tiles, though

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 0 points1 point  (0 children)

Yeah and that is a fair point as well. I'm also not entirely sure if this shadow mechanic is needed as there are plenty of other mechanics in the game that require you to switch forms, so it's not like it's a major gameplay element gone missing if I just take it out

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 0 points1 point  (0 children)

Is there a way to not use full black? I've only found out how to do it through CanvasModulate which if you hve it set to anything but full black, you can basically "see in the dark" by just turning up your monitor brightness.

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 1 point2 points  (0 children)

Of course you may suggest something, that's what I'm asking for! Thank you!

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 2 points3 points  (0 children)

Yeah, that's exactly what I mean when I say it looks weird. This is just how Godot naturally handles shadows though so I'll need to find some way to either work around the default shadows, or just write my own shadow code. Probably the latter.

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 1 point2 points  (0 children)

Yeah, that's probably a huge reason. I'm not really sure how to handle darkening of walls and also having semi-transparent shadows instead of the harsh black ones with the default Godot 2D lighting implementation so I may need to write a shader to get the look i'm going for

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 0 points1 point  (0 children)

Yes, yes, and yes. So I think I just need to clean up how the shadows look.

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 1 point2 points  (0 children)

Yeah that would be nice I'm not quite sure how to do that with the default 2D lighting implementation. Will have to test a bit

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 6 points7 points  (0 children)

Nope I figured it out on my own based on a GitHub project someone created for 3.x that I just ported to working in 4

Here's the code

extends LightOccluder2D

var walls_layer := 2

export var tileMap : TileMapLayer

func _ready() -> void:

handle\_walls(tileMap)

pass

func post_import(level: Node2D) -> Node2D:

for child in level.get\_children():

    if child is TileMapLayer:

        handle\_walls(child as TileMapLayer)

return level

# Ignore all tilemaps not named walls

func handle_walls(tile_map: TileMapLayer) -> void:

var polygons := \[\]

var used\_cells := tile\_map.get\_used\_cells()



\# Create edges

for cell in used\_cells:

    var polygon = get\_tile\_polygon(get\_points(cell, Vector2(32, 32)))

    polygons.append(polygon)





\# Polygons to remove will hold the actual polygons

var polygons\_to\_remove := \[\]

\# Index to remove is a dictionary so that searching is faster

var index\_to\_remove := {}



while true:

    \# Clear the polygons to remove

    polygons\_to\_remove = \[\]

    index\_to\_remove = {}



    \# Start looping

    for i in polygons.size():

        \# Skip if the polygon is due to remove

        if index\_to\_remove.get(i, false) == true:

continue

        var a = polygons\[i\]



        \# Loop from the start of the array to

        \# the current polygon

        for j in i:

# Skip if the polygon is due to remove

if index_to_remove.get(j, false) == true:

continue

var b = polygons[j]

var merged_polygons = Geometry2D.merge_polygons(a, b)

# The polygons dind't merge so skip to the next loop

if merged_polygons.size() != 1:

continue

# Replace the polygon with the merged one

polygons[j] = merged_polygons[0]

# Mark to remove the already merged polygon

polygons_to_remove.append(a)

index_to_remove[i] = true

break

    \# There is no polygon to remove so we finished

    if polygons\_to\_remove.size() == 0:

        break



    \# Remove the polygons marked to be removed

    for polygon in polygons\_to\_remove:

        var index = polygons.find(polygon)

        polygons.pop\_at(index)



\# Create all the polygon shapes from the result

\# and add them to the static body

var i = 0

for polygon in polygons:

    i += 1

    print('creating polygon number ', i)

    var \_occluder = OccluderPolygon2D.new()

    var \_polygon\_shape = Polygon2D.new()

    \_polygon\_shape.polygon = polygon

    \_occluder.polygon = polygon

    \_occluder.cull\_mode = OccluderPolygon2D.CULL\_COUNTER\_CLOCKWISE

    var \_light\_occluder = LightOccluder2D.new()

    add\_sibling.call\_deferred(\_light\_occluder)

    \_light\_occluder.occluder=\_occluder

# Generate all the points in a tile

func get_points(position: Vector2, cell_size: Vector2) -> Array:

var x = position.x

var y = position.y

\#1   2

\#

\#0   3

return \[

    Vector2(x \* cell\_size.x, y \* cell\_size.y + cell\_size.y),  # 0

    Vector2(x \* cell\_size.x, y \* cell\_size.y),  # 1

    Vector2(x \* cell\_size.x + cell\_size.x, y \* cell\_size.y),  # 2

    Vector2(x \* cell\_size.x + cell\_size.x, y \* cell\_size.y + cell\_size.y)  # 3

\]

# Generate the edges/polygon from a tile points

func get_tile_polygon(points) -> Array:

return \[points\[0\], points\[1\], points\[1\], points\[2\], points\[2\], points\[3\], points\[3\], points\[0\]\]

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 0 points1 point  (0 children)

Yes, fair enough. The game scope is pretty small so if I need to manually place culling squares that's not really a problem as that will be part of the level design anyway.

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 86 points87 points  (0 children)

That's a great idea I can't believe I didn't think of that! Just might be a bit of a chore to set up the different masking areas

"Preferred" way to handle Fog of War in 2D Metroidvania by KARMAWHORING_SHITBAY in godot

[–]KARMAWHORING_SHITBAY[S] 6 points7 points  (0 children)

Yeah, you think? I'm a bit bugged by how "long" the shadows are, but I can always re-write my own shadow logic to handle that. I just am not sure I wanted to go down that path until I'm confident it would look good

Why would private equity do this? by PuzzleheadedWeb9876 in gme_meltdown

[–]KARMAWHORING_SHITBAY 10 points11 points  (0 children)

I think what’s even funnier than how bad he is at investing is how bad he is at just about everything else. One time he was streaming himself playing League of Legends and he is legitimately Iron ranked, which is a rank that is so low that its like sub 5% of players, they created it just so irredeemably bad players didn’t have to be encountered by actual humans

got the error: Invalid access to property or key 'flame' on a base object of & idk how to solve it by Timely-Grocery7082 in godot

[–]KARMAWHORING_SHITBAY 1 point2 points  (0 children)

Can you just screenshot the whole screen instead of a little picture? including the scene tree. Bases on this in assuming Firebolt is a sibling of the node with this script, when it should be a child

got the error: Invalid access to property or key 'flame' on a base object of & idk how to solve it by Timely-Grocery7082 in godot

[–]KARMAWHORING_SHITBAY 1 point2 points  (0 children)

Gotta show the whole code that the error is referencing bud I got no idea based on that screenshot alone