quinton-ashley / p5play

JavaScript game engine that uses q5.js/p5.js for graphics and Box2D for physics.
https://p5play.org
GNU Affero General Public License v3.0
667 stars 184 forks source link

Out of bounds _display check doesn't take rotation into account #249

Closed cKrijgsman closed 1 year ago

cKrijgsman commented 1 year ago

https://github.com/quinton-ashley/p5play/blob/0259613058c0837ade6f0de24f3f0c2b2d75f191/p5play.js#L2421

When drawing a Sprite that has rotation off-screen, it will not consider the rotation when checking if it should be rendered.

Example:

function setup(){
    createCanvas(100, 100)

    // These work as intended
    // Renders and should
    const a = new Sprite(120,50,60,15)
    a.fill = "green"
    // Doesnt render and shouldn't
    const b = new Sprite(50,-25, 60, 15)
    a.fill = "green"

    // These do not

    // This one will be rendered but doesn't have to
    const c = new Sprite(120,50,60,15)
    c.rotation = 90
    c.fill = "red"

    // This one is not rendered but would have been in view
    const d = new Sprite(50,-25, 60, 15)
    c.rotation = 90
    c.fill = "red"

}

function draw() {

}
quinton-ashley commented 1 year ago

good catch! I will fix this today

quinton-ashley commented 1 year ago

Sorry I said I could fix this in a day but this issue will take some more time to get right. I'm thinking the most efficient solution will be to utilize planck's world.queryAABB method, like I did in my getSpritesAt method.

quinton-ashley commented 1 year ago

For v3.9, I just implemented an unsophisticated algorithm for the _display function that errors on the side of drawing, even if the entire sprite is offscreen.

I realized that an optimal solution for this would have to account for the scale of the sprite's image, not just the size of the sprite's collider.

I'll revisit this issue later to improve p5play's efficiency, thanks for bringing the error to my attention! Closing the issue for now.

let largestSide = Math.max(this._w, this._h);

// if the sprite is off screen, then it doesn't get drawn
// this is an unsophisticated algorithm that
// errors on the side of drawing
if (
this.shape != 'chain' &&
this.p.camera.active &&
(x + largestSide < this.p.camera.bound.min.x ||
    x - largestSide > this.p.camera.bound.max.x ||
    y + largestSide < this.p.camera.bound.min.y ||
    y - largestSide > this.p.camera.bound.max.y)
) {
  this._visible = null;
  return;
}