I'm creating a game with JavaScript and HTML Canvas. It's a multiplayer 2D game with tanks that try to hit each other. The tanks can move as well as rotate. How can you figure out collision detection with rotating rectangular objects? I know, I could make them square and use circular detection, but it looks very messy when a tank runs into a wall. Thanks for all who try to help :)
相关问题
- Views base64 encoded blob in HTML with PHP
- Is there a limit to how many levels you can nest i
- How to toggle on Order in ReactJS
- void before promise syntax
- Keeping track of variable instances
Move hit point to local space
First an alternative
There are many ways you can do it. The simplest way. When you calculate the cross product between a point and a line it will be negative if the point is right of the line and positive if left. If you then do each of the four sides in turn and they are all the same sign the point must be inside.
To get the cross product of a line and a point
A Quicker way.
But that is a lot of math for each object and each bullet.
The best way is to transform the bullet into the tanks local coordinate system then its just a simple matter of testing the bounds, left, right, top, bottom.
To do that you need to invert the tanks transformation matrix. Unfortunately the easy way to do that is currently still behind browser flags/prefixes so you need to create and manipulate the transformations in javascript. (Should not be too long till ctx.getTransform() is implemented across the board and fill a very needed performance hole in the canvas 2d API)
If ctx.getTransform is available
So you have a tank at x,y and rotated r and you draw it with
The transform hold everything we need to do the calcs, all we need to do is invert it and then multiply the bullet with the inverted matrix
The bullet is at bx,by so create a DOMPoint
Then for each tank transform the bullet with DOMMatrix.transformPoint
Now just do the test in the tanks local coord space
The Javascript way
Well until the becomes the norm you have to do it the long way. Using the same x,y,r for tank, bx,by for bullet.
Test to make sure it works
Too many negatives, xdx,xdy etc etc for me to be able to see if I got it correct (Turned out I put the wrong sign in the determinant) so here is a quick demo to show it in action and working.
Use the mouse to move over the tank body and it will show that it is hit in red. You could extend it easily to also hit the tank moving parts. You just need the inverse transform of the turret to get the bullet in local space to do the test.
UPDATE
Add code to stop tank's visually popping in and out as the crossed canvas edge. This is done by subtracting an
OFFSET
from each tank when displayed. This offset must be factored in when doing the hit test by addingOFFSET
to the test coordinates.