I am currently working on a basic HTML, CSS, and JavaScript game as a freshman high school summer project. I am currently trying to implement separating axis theorem (I spent a lot of time learning the math on khan academy in their linear algebra course because I didn't know what vectors and dot product were). It is for my player’s shield. I have been having a lot of trouble with it generally. But right now, I am just focusing on trying to locate the top left of the shield hitbox. I also draw the hitbox results out so I can see what is going on. The result is that the located hitbox is really far away, and just doesn't seem to really correlate to the top left corner of the hitbox at all. The equations I have been trying to use are:
x′= xcos(θ)−ysin(θ)
y′ = xsin(θ)+ycos(θ).
The following code is my attempt to locate the top left vertex:
const vertOne = {
x: oneX + Math.cos(shieldAng + Math.PI/2) * oneRad,
y: oneY - Math.sin(shieldAng + Math.PI/2) * oneRad
};
// Other vertex of shield
const vertTwo = {
x: oneX + Math.cos(shieldAng - Math.PI/2) * oneRad,
y: oneY - Math.sin(shieldAng - Math.PI/2) * oneRad
};
const midpoint = {
x: oneX + Math.cos(shieldAng) * oneRad,
y: oneY - Math.sin(shieldAng) * oneRad
};
const center = {
x: oneX,
y: oneY - oneRad / 2
};
const rectOne = {
get x() {
let v1UnrotatedX = (((vertOne.x - center.x) * Math.cos(Math.PI / 2) - (vertOne.y - center.y) * Math.sin(Math.PI / 2)) + center.x);
let v1UnrotatedY = (((vertOne.x - center.x) * Math.sin(Math.PI / 2) + (vertOne.y - center.y) * Math.cos(Math.PI / 2)) + center.y);
let x = v1UnrotatedX + 2 * oneRad;
let y = v1UnrotatedY + oneRad;
return (((x - center.x) * Math.cos(shieldAng) - (y - center.y) * Math.sin(shieldAng)) + center.x);
},
get y() {
let v1UnrotatedX = (((vertOne.x - center.x) * Math.cos(Math.PI / 2) - (vertOne.y - center.y) * Math.sin(Math.PI / 2)) + center.x);
let v1UnrotatedY = (((vertOne.x - center.x) * Math.sin(Math.PI / 2) + (vertOne.y - center.y) * Math.cos(Math.PI / 2)) + center.y);
let x = v1UnrotatedX + 2 * oneRad;
let y = v1UnrotatedY + oneRad;
ctx.strokeStyle = 'blue';
ctx.strokeRect(v1UnrotatedX - 10, v1UnrotatedY - 10, 20, 20);
return (((x - center.x) * Math.sin(shieldAng) + (y - center.y) * Math.cos(shieldAng)) + center.y);
},
width: 2 * oneRad,
height: oneRad
};
If you are interested in the rest of the code, I linked to it on GitHub below. The file for the code mentioned above is called collision.js. Thanks for reading, and any help is greatly appreciated!
Resources I Have Been Using:
How to calculate corner positions/marks of a rotated/tilted rectangle?
https://math.stackexchange.com/questions/270194/how-to-find-the-vertices-angle-after-rotation
https://www.youtube.com/watch?v=7Ik2vowGcU0&t=609s&pp=ygUXc2VwYXJhdGluZyBheGlzIHRoZW9yZW0%3D
https://www.youtube.com/watch?v=Nm1Cgmbg5SQ&t=620s&pp=ygUXc2VwYXJhdGluZyBheGlzIHRoZW9yZW0%3D
https://www.youtube.com/watch?v=Ap5eBYKlGDo&t=84s&pp=ygUXc2VwYXJhdGluZyBheGlzIHRoZW9yZW0%3D
http://programmerart.weebly.com/separating-axis-theorem.html
https://dyn4j.org/2010/01/sat/
https://www.khanacademy.org/math/linear-algebra/vectors-and-spaces (up to the video "Defining the angle between vectors" in lesson 5)
My GitHub Page (all the code is here):
https://github.com/Josh60169/Shape-Fight/tree/main/Shape%20Fight
oneX
andoneY
are the center of the shield (at first was thinking they were unit vectors on the x and y axis respectively),oneRad
is the shield radius (I was thinking it was something about radians). Now, you definedcenter.y
like thisoneY - oneRad / 2
, does that mean the center of rotation is different from the center of the shield? - Also, you are defining the points already rotated, then inrectOne
you seem to undo the rotation (but not byshieldAng
) and rotate... Why don't you define the points without rotation and rotate only once? \$\endgroup\$oneRad
is not even a radius, it is theheight
, and you have a hard-coded aspect ratio of 2 to 1:width: 2 * oneRad
,height: oneRad
. I was thinking you had a square (since squares are rectangles and can be defined by their center and a radius - and, by the way, the radius is to the corner, see also "Apothem"). \$\endgroup\$