问题
I am making an HTML5 and Javascript platform game. At this moment all blocks of the map are handled as squares. This method is "ugly" when the block is not an exact square/rectangle.
Check this image I made to get a better understand of my point:
Case one: The "bottom bumper" is touching the square that envolves the block so the movement is stopped.
Case two: If I use the same method as above, when the players jumps, the movement will be stopped before the "top bumper" even touches the block.
How should I approach case two? I know that I have to check if the "Top Bumper" is colliding OR inside the area between the curve and the other 2 edges.
How would that curve be? How can I generate a function for it based on the block coordinates (x,y) and dimensions (width, height).
Note: I would like to avoid checking for collisions in every point of that curve because that would be very expensive for the CPU.
回答1:
There are many possibilities, depending on how "perfect" you want your collisions to be and how portable and labor-intensive you want the technique to be. By no means is this comprehensive, these are just the ones I would personally evaluate. I've used the first two personally.
Use line segments to approximate your curve. Create "vertices" along the curve, and make line segments out of each pair of them. You already know how to test against axis-aligned squares, it's not a huge leap to move to testing to see if any of your characters points are "behind" a collider line segment (similar to checking if points are "behind" a plane). You can get surprisingly accurate and performant results with this (depending on how granularly you generate line segments), the hardest part is generating the collision map in the first place. I chose to hand-define the segments, which I consider a mistake. If i were to do it again, I'd probably try to find a way to generate the line segments, given some settings about how granular I want them.
Calculate the outline of the curve, and create colliders 1px by 1px for each pixel of the curve. This is your collision map. Use a circle or ellipsis for the collision mesh of your character, and check distance between the colliders and character. This simplifies the calculations quite a lot, and although we're talking about a lot of possible calculations (one check per pixel), a lot of optimization can be had by aggressively spatially partitioning your world (bin, bsp, whatever). Generation of this is relatively straightforward image edge detection, so you wind up with a near-drop-in solution. I used this in a Spy Hunter ripoff, and the artist greatly appreciated the ability to just make art and not worry heavily about collisions.
Pixel diffs. I've never actually done this, but I've seen talks of "pdiffing" where the character sprite and tile sprites are overlaid in-memory, and if there is any overlap between non-transparent areas of either, it indicates a collision. Depending on the size of your sprites, this may become prohibitively expensive. It also would probably only work in the context of a tile-based game.
来源:https://stackoverflow.com/questions/39541744/how-to-detect-collisions-with-a-curve