0
\$\begingroup\$

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://stackoverflow.com/questions/62028169/how-to-detect-when-rotated-rectangles-are-colliding-each-other

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://gamedevelopment.tutsplus.com/collision-detection-using-the-separating-axis-theorem--gamedev-169t

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

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Assume that external links will not be clicked. Format your question so that the information needed to diagnose the issue — minimal code needed to reproduce it, and documentation of the problematic test cases and symptoms — are present in the body of your question, not in external links. \$\endgroup\$
    – DMGregory
    Aug 1 at 2:21
  • \$\begingroup\$ @DMGregory, should I delete any of the links and do my edits to the question properly account for your feedback? Also, is it bad if I ask you for help? \$\endgroup\$
    – Yash-902
    Aug 1 at 3:38
  • \$\begingroup\$ Most of the links aren't necessary. Assume that if people need to know what "Separating Axis Theorem" is, they can search for it (given that you have mentioned and tagged it), and anything needed to understand that. You have linked another question on this site, can you explain why that didn't work? \$\endgroup\$
    – Theraot
    Aug 1 at 8:23
  • 1
    \$\begingroup\$ This took some guesswork: oneX and oneY 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 defined center.y like this oneY - 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 in rectOne you seem to undo the rotation (but not by shieldAng) and rotate... Why don't you define the points without rotation and rotate only once? \$\endgroup\$
    – Theraot
    Aug 1 at 8:34
  • \$\begingroup\$ Oh, oneRad is not even a radius, it is the height, 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\$
    – Theraot
    Aug 1 at 8:45

1 Answer 1

1
\$\begingroup\$

After reading the code and guesswork, I've landed in that you have a rectangle defined by:

  • A center point given by oneX and oneY
  • A height given by oneRad
  • A hardcoded aspect ratio of 2 to 1

Like this:

Picture of the rectangle

Rectangle with dimensions 2 * oneRad by oneRad centered at (oneX, oneY)


And you want to compute the coordinates of the corners of the rectangle...

After rotating it by shieldAng, by a pivot placed at (oneX, oneY - oneRad / 2). Probably that is what you want. I'll solve this for an arbitrary pivot anyway, so if it isn't you can change it.

But first, the coordinates of the corners without rotation:

let size {x: 2 * oneRad, y: oneRad};
let half_size = {x: size.x * 0.5, size.y * 0.5};
let center = {x: oneX, y: oneY};

let corners = [
    {x: center.x - half_size.x, y: center.y - half_size.y},
    {x: center.x - half_size.x, y: center.y + half_size.y},
    {x: center.x + half_size.x, y: center.y + half_size.y},
    {x: center.x + half_size.x, y: center.y - half_size.y}
];

And let us define a function to rotate them based on the answer of How to calculate corner positions/marks of a rotated/tilted rectangle?:

function rotate(vector, pivot, angle) {
    let tmp = {x: vector.x - pivot.x, y: vector.y - pivot.y};
    return {
        x: tmp.x * cos(angle) - tmp.y * sin(angle) + pivot.x;
        y: tmp.x * sin(theta) + tmp.y * cos(theta) + pivot.y;
    };
}

And we can get the rotated corners like this:

let size {x: 2 * oneRad, y: oneRad};
let half_size = {x: size.x * 0.5, size.y * 0.5};
let center = {x: oneX, y: oneY};

let pivot = {x: oneX, y: oneY - oneRad / 2};
let angle = shieldAng;

let rotated_corners = [
    rotate({x: center.x - half_size.x, y: center.y - half_size.y}, pivot, angle),
    rotate({x: center.x - half_size.x, y: center.y + half_size.y}, pivot, angle),
    rotate({x: center.x + half_size.x, y: center.y + half_size.y}, pivot, angle),
    rotate({x: center.x + half_size.x, y: center.y - half_size.y}, pivot, angle)
];

Change the pivot if it is incorrect. Add an offset to the angle if you need (e.g. angle = shieldAngle + Math.PI / 2 or whatever).

\$\endgroup\$
1
  • \$\begingroup\$ Thank you very much. It is clear that I just did a really poor job at implementing what I saw on the other posts. Once again, thank you so much, and sorry for the inconvenience. \$\endgroup\$
    – Yash-902
    Aug 2 at 23:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .