I originally posted this on Stack Overflow via the p5 tag, but figured this might be a better place for it.
I’m working on getting 2D zooming and panning working in a p5 project, a la this example code. I’m working in instance mode in node, so my version of this translate/scale works like the block below. I wasn’t using this method before, and was instead just panning the canvas without translating it, but I’m adding it now so that I can (eventually) get zoom working as well. zoom = 1
, for now.
p.push();
p.translate(p.width/2, p.height/2);
p.scale(zoom);
p.translate(pan.x/zoom, pan.y/zoom);
// ... some code ...
p.pop();
I have a tile-based map that’s larger than the canvas, which I was drawing starting at untranslated (0,0), with canvas dimensions of (700, 500) and the map as (1300, 1300). So when I translate the first time, I’m turning (0,0) into (350, 250). If I set the panning at the start at (-350, -250) to compensate, and at least position the “camera” over the map, the values I have to use to constrain the user’s ability to pan are really weird.
// in setup()
p.B_CENTER = p5.Vector.mult(dim.view, 0.5);
p.B_PANNING = p5.Vector.mult(p.B_CENTER, -1);
p.B_MAXDIFF = p5.Vector.sub(dim.map, dim.view).add(p.B_CENTER).mult(0.5);
// in mouseDragged()
p.B_PANNING.add(p.createVector(p.mouseX - p.pmouseX, p.mouseY - p.pmouseY));
p.B_PANNING.x = p.round(p.constrain(p.B_PANNING.x, -p.B_MAXDIFF.x, -p.B_CENTER.x/2));
p.B_PANNING.y = p.round(p.constrain(p.B_PANNING.y, -p.B_MAXDIFF.y, -p.B_CENTER.y/2));
My problem is, even though all the tiles and points I have are positioning themselves correctly, the resulting relative position has no apparent relationship to the canvas dimensions. Before I added this translation code, I could check if the relative position was inside the bounds of the canvas easily, because a point panned to the top-left of the canvas would show a relative position of (0,0). My max and min constrained panning values are super weird because I’m translating to not the center of the map but the center of the canvas:
// effective max panning values
minX = -440 // furthest right, -maxdiff.x
maxX = -175 // furthest left, -center.x
minY = -580 // furthest bottom, -maxdiff.y
maxY = -125 // furthest top, -center.y
// checking for visibility
function __isVisible(pos, bounds) {
if (pos.x < 0 || pos.y < 0) {
return false;
}
if (pos.x >= bounds.x || pos.y >= bounds.y) {
return false;
}
return true;
}
And in the below image, you can see what this does to the relative position (sorry for the terrible debug colors). Each point on the map shows its id, then its fixed position relative to the size of the map, followed by its relative position with panning applied. But most of the relative positions don’t reflect where they actually are relative to the canvas. For example, point #7’s relative x value is way too far to the right to really be at 378px when the width of the canvas is 700px.
So, my question(s):
- What do I need to do to be able to check if these points are visible on the canvas? It’s important for muting sounds attached to points that go offscreen. Right now the panning makes the relative positions of these points make absolutely zero sense with that algorithm.
- Did I misunderstand how this translate/scale/translate thing is supposed to work?
- Is there an easier way to work with a 2D camera than this? Is there a way to control the camera’s actual position when I need to translate it to the center of the screen? Or should I just give up and use p5’s camera object?
Sorry if this is confusing, I’ve been racking my brain to solve it and haven’t been able to come up with anything.