How do I make see-thru walls in a 3D/Top-Down 8 direction game?

1 favourites
From the Asset Store
Set of tiles to create a map for top-down games with island theme
  • I am working on a small 3D tank game project where I want the walls to have a lower opacity every time there's a tank (player) behind them.

    I tried several different ways using the position of the walls, trigonometry and bounding boxes, but nothing seems to work and I need help.

    Here's the problem!

    In the top-down view, I want the wall to get transparent when the player is behind (higher in the Y axis) the wall and within points A and B, which would be the width of a rectangle encapsulating the wall.

    However, I want the wall to be fully opaque when the player is in front (below in the Y axis) of the wall.

    So far, so good! The problem is that I want to avoid this problem, where if the player is in front of the wall but higher than its origin point in the Y axis, the wall will go transparent.

    The opposite should also be avoided when the wall goes remains opaque even though the player is behind it because they're below the wall's origin point.

    This would work very simply if all the walls were at right angles, but I want to be able to have a full range of rotation for them and make it work.

    Any ideas on how I could approach this problem and achieve the desired result? I tried many different things with varying levels of success, but never fully got there.

  • I apologize, the 4th image is incorrect, and it's just the 3rd image repeated. This is what it looks like.

    As you can see, the player is in front of the wall, but the wall is still going transparent. I want to be able to keep it opaque in this situation.

  • Will the Line of Sight behaviour work for this? You could add an object at the position of the 3D camera, and then check to see if a tank leaves that object's line of sight to set the opacity of the wall.

    Example: editor.construct.net

  • That might work, but I am doing something wrong. This is what I quickly laid down in the event sheet.

    Where cam_seethru is the object that is always in the same position as the camera, checking for LOS.

    The result of this is that all walls are transparent all the time, even if the tanks are in front of them.

    I just left the LOS behaviour with its default values.

  • It's hard to just guess from screenshots of code as to what is happening. I agree that LOS is probably your best bet for this.

    Since there are multiple players, maybe you'll also need a "for each players" there. Also there is no event that sets the walls to full opacity again.

    I'd do something like this, but I haven't fully tested this.

    This works only in a 2D space though. If you also need to check if the object is obscured by the wall depending on height... well you gotta unzip happy triangle math stuff there. Something along those lines off the top of my head.

    If "wall height" < ("distance to player"/"distance to wall")*"camera height" -> player is visible. Else set wall opacity.

  • Thanks for sharing this approach. I didn't even know how much it was possible to do with the LOS behaviour. I never experimented much with it.

    That being said, I tried your approach and it didn't work very well. The walls are almost always opaque, especially when the camera is further away.

    The only instance in which it works is when the tanks are closer to each other and the camera is also closer to them. Then the walls start reacting, but even then it's not 100% accordingly to what's desired.

    For example: While the wall is getting transparent in the image above if I go slightly lower and more behind it, it gets opaque again. I didn't implement the whole math in relation to the Z axis here, so maybe that could be related.

    And then if I move the other tank behind the wall, that one doesn't get transparent, but the one closer to the other player does.

    I understand that not having access to the game's files can make the whole process of figuring this out harder, so I am sharing here a link to the file so you can take a look.

    drive.google.com/file/d/10OmeVZRQaRrGxZwgVrwMbD7Kx-kNrNpS/view

    Cheers!

  • This was actually a bit trickier than I thought at first. The issue with a raycast is that once the raycast hits an object, it stops. So if there's two or more walls, it will only set the opacity of one of those. So I thought instead of raycasting, using a sprite as a raycast could do (as it goes through all objects) and you can simply change the opacity of all walls that overlap. But then you lose the ability to factor in the height of objects/camera. So I had to recursively cast a ray every time it hits a wall.

    wackytoaster.at/parachute/raycast3DwallObscuring.c3p

    This should work.

  • Alright! So, I tried your code in my project and it's not working, and I believe it might be related to the way I am handling the camera.

    In your project, the camera is static, whereas I have the camera move accordingly to the following:

    I don't know if all these lerps might be affecting it. What do you think? I might have to sacrifice the smooth-ish camera and use something a bit more static if this is causing trouble.

    Here's the link for the new version:

    drive.google.com/file/d/10OmeVZRQaRrGxZwgVrwMbD7Kx-kNrNpS/view

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • The link to the new version seems to still be the old version. Anyway, a moving camera should not cause issues I think and from a brief test it does work with the new code I posted (I just put a sine on the camera to move it). Maybe you need to adjust the threshhold variable a bit?

  • Yeah, I'll grab some time this week to play around with it and see if I can make it work. I'll get back here once I get it sorted out or if I am unable to.

    Thanks for all the help though!

  • A slightly different way you could do it is to sample points on the line between the camera and each tank. If any point overlaps a wall in 2d and the point z is between the top and bottom z of the wall, then that point is inside the wall and you can make it transparent.

    The events would basically look like this:

    var steps=0
    
    every tick
    -- tank: set opacity to 100
    
    for each tank
    -- set steps to ceil(sqrt((camera.x-tank.x)^2+(camera.y-tank.y)^2+(camera.z-tank.z)^2)/32)
    -- repeat steps times
    -- pick wall overlapping point: lerp(camera.x, tank.x, loopindex/steps), lerp(camera.y, tank.y, loopindex/steps)
    -- value lerp(camera.z, tank.z, loopindex/steps) is between wall.z and wall.z+wall.zheight
    -- -- wall: set opacity to 50

    I can never remember if z goes up or down so the code assumes z goes up. If z goes down you’d need to change the in between values condition to: wall.z-wall.zheight and wall.z.

    In the steps calculation it uses 32 to make it sample points every 32 pixels. You can make that smaller to make it more accurate although it would be a bit slower.

  • That's a smart way to do that r0j0.

  • Hey guys! I took some time today to try these approaches out and both of them didn't seem to work well, although for one it could be me doing something wrong.

    Wacky's approach seems to work well enough when there's only one player on the screen. The moment there are two or more, things start falling apart.

    When attempting Rojo's approach, absolutely nothing happened. However, I am very suspicious that it's because I laid the code down wrong. Here's a screenshot of how I did it.

    There's also a link down here for the test project in the screenshot which I created to test these things out. It has both approaches coded in.

    drive.google.com/file/d/1SxCQj8_tXlQdfzSwp5sw-2MHwK3xmrFr/view

  • Posting again just to address an issue I was previously having regarding the camera movement.

    "In your project, the camera is static, whereas I have the camera move accordingly to the following:"

    "I don't know if all these lerps might be affecting it..."

    It's actually all working fine. What was giving bad results was an invisible wall with the solid behaviour I had on the open side of the arena. After I removed this invisible wall, everything started working better.

    The issues of my previous post still persist, of course. Just wanted to get this here in case somebody ever stumbles across this thread in the future when having a similar issue.

  • For multiple players all you have to do is add picking the player. Interestingly it does not work when setting the function to copy picked, I wonder if it's because of the recursive nature.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)