It looks like you're new here. If you want to get involved, click one of these buttons!
Hey, everyone!
I am currently working on a 3D FPS, and I'm making progress. The game includes houses, collisions, enemies, shooting, and even an intro. But there's a problem I want to fix before continuing: The player can shoot through walls. My code works like this: "If shoot button pressed then iterate over each guard and check if the player is aiming at one", but I don't know how to change it so the player cant shoot through a wall before hitting a guard. I've been trying to figure this problem out for a while now, but this is all I could think of:
Right now, my code uses math to find out if a guard is hit. Instead, I could take a screenshot of the screen but color code everything and then check the pixels in the middle of the screen to see if they match the right color code.
The problem is that I fear that that process might be too slow. I would really like some help from you guys! The code is located in the gist below. The shooting detection code is located at around line 262.
https://gist.github.com/Kolosso7/ebb9a85f0683b9ea8c9da5fb70d4bd0a
Thank-you so much in advance!
Comments
Holy crap, great job!
@EvanDavis Thanks!

I worked hard on it, and I'm proud of my progress.
'Hope everyone has a good day
Doing it with math and hitboxes is the "right" way, but doing a coloured render (enemy's colour coded per enemy (or even coloured to body part), everything else rendered say black) and then render to a image with setcontext is simpler.
When doing that you could use the clip(x,y,width,height) function to restrict the drawing to just the area the bullet is going, this may reduce the drawing overhead as the fragment shaders shouldn't have to process all the pixels in the screen...
@spacemonkey I think I'll try the method you described for now, but if it's too slow for the finished game, I might need to figure out how to do the math.
Thanks for helping!
you can always optimize it a bit by doing a simple bounding box on the hit test pass to only pick up enemies and walls broadly within the pass, so the render only has to render the meshes for those items even with the clipping...
@spacemonkey Umm. I don't mean to sound stupid, but I don't know what a bounding box is...
Do you mean I can optimize it by only drawing meshes that are in the middle of the screen?
I've not looked at your code, but what collision detection do you have currently? What stops the player being able to walk through walls, and could that be adapted to the firing routine?
Are the walls aligned with any of the axes (eg, vertically aligned with the "up" axis)? If so, the walls can effectively be treated as lines, and maths should be a quite straightforward, "do these 2 lines cross" algorithm.
@yojimbo2000 This is the code that handles the gravity and collisions of the player. It's located in
Player.draw
so it's running 60 times a second (s
is a local variable used in the code that equalsPlayer
which is a table that holds all the player data):When I wrote this code I was trying not to use any complicated math. Here's how it works, starting at the line that says
-- Collisions with houses
:The walls are vertical, but I wanted to allow the player to jump high and stand on top of the roofs of the houses at some point in the game (maybe at the end in a sandbox mode or something). But, now as I think about it, I find it kind of a lame idea. Maybe I should remove the roof collisions, never let the player be able to jump that high and use the technique you described.
Bounding boxes are a simplified math for do you hit something, but not specific enough. Let's say you have a monster mesh that has a shape to it, it's all blobby. You could accurately detect a hit on it by somehow methematically describing it's overall shape and testing it. BUT this is expensive and complex. So what you do with a bounding box is put a cube or sphere around the object (logically not visually) where the object is fully within the bounding box. Then you can do a quick first test of does my shot or whatever hit the bounding box (for which the math is simple), and only if the bounding box is hit, then you worry about the object in detail.
So in drawing this can be good for culling all the meshes out of range, I did something similar in some landscape and things I did in the past, effectively for each quad in my landscape I defined a sphere fully encompassing that quad, then I can quickly test whether the quad is in the visual space (in front of camera), if it is I draw the mesh, if it's not I don't, so the graphics processor only considers things that are likely to at least be partially in view. This meant I could have an immense landscape, but the draw speed is still good.
https://codea.io/talk/discussion/5786/heightfield-terrain-very-large-with-good-performance#latest
@spacemonkey Okay. So, you're saying I can have a line (not visually) pointing outwards from the camera (and following the camera's rotation), and if it touches one of these bounding boxes, the mesh of that bounding box gets drawn? Do you mean it should do this every frame? Wouldn't that be expensive? Or should it do this only when the shoot button is pressed? Also, how do I detect if a 3D line intersects a cube?
@Kolosso with the normal maths for these sorts of things, just like in your current shoot you use maths to see whether there is an enemy in front of you. But you use the bounding box to determine whether the mesh is worth trying to draw. The theory is that the maths to determine whether the bounding box is in frame is cheaper than the GPU work to throw all the meshes at the screen and see what appears. Also the maths on a bounding box of a simple cube or sphere is much better than a more accurate collision with the mesh if it's not a nice simple shape.
If you have lots of complex meshes, then it can make a big difference if the world is big as you can only see a small portion of it.
This article I based part of the terrain thing on kind of describes it
https://www.gamedev.net/resources/_/technical/graphics-programming-and-theory/quadtrees-r1303
In figure 1 you can see it's a big terrain, but the camera is in one corner facing away, so you can effectively trim out all the other bits from processing. Then because it's a "flat" area, it describes a way of structuring the terrain in a quad tree structure for the non moving elements. This means if my terrain is say 64x64 rectangles I'd have to test bounding boxes for 4096 squares which might not be fun. By making them a quadtree type structure I can first test my terrain on a 2x2 grid (4 checks), then discard the big squares outside, and only test in more detail for the 4 squares in each big square I want and on down recursively. I guess it's analogous to using an index in SQL or something, so I can get to the in camera items by maybe doing 100 checks instead of 4096.
So in my terrain example, I have 16,385 possible quads in the tree, but while running it'll only have to check 100-120 of them, and it'll only draw 30-40 of them. -> result = performance. There's some other weirdness I do there so that if it's far away I draw it at a lower complexity to also reduce the number of mesh renders...
To be honest, a lot of the math on this stuff is a bit beyond me, I just try to understand the concepts and then steal code off the web.
I now understand what quadTrees are, but I don't know how to check if the view frustum (the triangle in Figure 1) is intersecting with a cell (a house in my case). Do you know how to do this? Sorry if I'm becoming annoying. I don't mean to
@Kolosso As you are working in 3D you should use an octree. The principal is basically the same except they are split into eight nodes instead of four to cope with the extra dimension.
Check out these links for some reference material. (The code examples aren't lua)
http://www.flipcode.com/archives/Introduction_To_Octrees.shtml
http://www.gamasutra.com/view/feature/131625/octree_partitioning_techniques.php
https://github.com/Nition/UnityOctree/
Getting the frustrum in Codea is a little tricky to understand but doesn't require too much typing because it can extracted directly from Codea's transform matrices using the OpenGL plane extraction technique described in the links below.
http://www.lighthouse3d.com/tutorials/view-frustum-culling/clip-space-approach-extracting-the-planes/
http://www.lighthouse3d.com/tutorials/view-frustum-culling/clip-space-approach-implementation-details/
To be honest it was a bit of a pain to port so I'll save you the trouble
Note: It also implements the radar method from the same tutorial so it actually has two independent representations of the frustrum.
Edit: Whoops I missed off a couple of extra links.
Extracting frustrum planes
http://www.txutxi.com/?p=444
AABB intersect algorithm
http://www.txutxi.com/?p=584
http://old.cescg.org/CESCG-2002/DSykoraJJelinek/
Usage example