For context, I'm working on a top-down 2D game with controls similar to 2D Zelda games.

What I'm trying to achieve: An impassible "pit" with moving platforms traveling back and forth across it, which the player can walk onto to traverse the pit. If the platform is adjacent to a non-pit tile or another platform, the player should be able to walk from the current platform to that place.

The problem: At first I implemented the pit as a Tilemap with collision to make it impassible to the player, and the moving platform as an Area2D moving along a Path2D. However, the pit's collision shape would not allow the player to walk onto the platform, since the platform exists entirely "within" the pit. I wish I could subtract the platform's area from the pit's collision shape, but I'm not sure that's possible.

My current (bad) solution: Instead of relying on the pit Tilemap's collision shape, I turned off the its collision and wrapped the pit with invisible barriers that prevent the player from crossing into the pit (shown as red outlines below). I surrounded the platform with the same barriers too, so the player can't walk off the platform and into the pit.

Now, in order to allow the player to walk onto or off of the platform, I have to disable the barriers at the place where I want the player to be able to walk.

Now the player can walk onto the platform, but I have to specify exactly when to turn off and on the barrier collision, and exactly which portions of the barrier to disable.

Is there a better to implement this, possibly a way that requires less manual intervention?

  • codyjs

    One note, I don't think it's possible to change individual tiles' collision layer, it seems like they are tied to the collision layer of the entire Tilemap 😞. However, I could get around this with an identical tile with no collision shape at all.

    Yes, that is essentially what I am suggesting. Sorry I forgot that 3.X doesn't have all the tilemap features I've gotten used to in 4.x.

    You don't really need to detect which tiles are overlapped. You just need to detect when your platform is docked. Now that I'm thinking about it more, you needn't change any tiles at runtime at all. Create the identical tile with no collision shape and fill the entire path of the platform with it. Then add barriers to the top and bottom of the platform and to the floor where the platform docks. Then you turn off/on those barriers (or layers) to use as "gates" onto the platform. That way you don't need to fiddle with your tiles at all. Just be careful the player doesn't accidentally break into the space of "walkable" pit tiles!

I wish I could subtract the platform's area from the pit's collision shape, but I'm not sure that's possible.

Maybe it is? Maybe you could have a second tile identical to the pit tile but with different collision layers, and then swap between the two as the platform passes over them. Wouldn't even need to be do swaps for the entire path of the platform, just the rows of cells adjacent to the floors at each end. Let me know if I'm not making sense and I can doodle over your doodles.

Then the only barrier you'd need to be concerned with would be the one around the moving platform. That would still be necessary to ensure that the player doesn't step off onto the "walkable" pit tiles. If your platform only moves two directions and is sided on left and right by impassible pit tiles, then you'd only need a barrier at the top and bottom. Then you just turn those on and off based on position. Could try using the one-way collision setting to make it less finicky so that you're not concerned with blocking the player from boarding the platform.

You would want to make sure there's some minor overlap between your docked platform and your floor tiles so that your player doesn't accidentally get stuck between the two. It also might behave better if instead of turning off and on the entire barrier, you just turn off and on a collision layer.

    award Thanks for the response!

    Let me make sure I understand: I think you're suggesting that the pit collision around the stationary floors can be switched on and off by swapping the tiles as they enter the Platform's Area2D. (Correct me if I'm wrong here). This means the barriers can be turned off automatically when the platform "docks." That would certainly be more dynamic than my current implementation.

    One note, I don't think it's possible to change individual tiles' collision layer, it seems like they are tied to the collision layer of the entire Tilemap 😞. However, I could get around this with an identical tile with no collision shape at all.

    That just leaves the problem of how to detect when an individual tile overlaps with the platform, since I think body_entered/body_exited signals will be triggered once for the entire Tilemap rather than individual tiles. Off the top of my head, I think I'd have to constantly check which tiles are underneath the platform as it moves.

      codyjs

      One note, I don't think it's possible to change individual tiles' collision layer, it seems like they are tied to the collision layer of the entire Tilemap 😞. However, I could get around this with an identical tile with no collision shape at all.

      Yes, that is essentially what I am suggesting. Sorry I forgot that 3.X doesn't have all the tilemap features I've gotten used to in 4.x.

      You don't really need to detect which tiles are overlapped. You just need to detect when your platform is docked. Now that I'm thinking about it more, you needn't change any tiles at runtime at all. Create the identical tile with no collision shape and fill the entire path of the platform with it. Then add barriers to the top and bottom of the platform and to the floor where the platform docks. Then you turn off/on those barriers (or layers) to use as "gates" onto the platform. That way you don't need to fiddle with your tiles at all. Just be careful the player doesn't accidentally break into the space of "walkable" pit tiles!

        award Carving a "hollow" path through the pit is a great idea! I think that is the approach I'm going to take here.

        Also, TIL about 4.x's Tilemap improvements, I'm going to have to look into that.

        Thanks again for your input!