# Pan camera within bounds of large image

I have a camera that I pan around a large image which works fine, however when I reach the end of the image I can keep panning on and on, forver. I have looked everywhere for an answer on how to prevent this but the only one I found did not use panning and I could not get it to work.

My code atm is very simple:

map.setPosition(-map.getWidth()/2, -map.getHeight()/2);

public boolean pan(float x, float y, float deltaX, float deltaY) {
cam.translate(-deltaX * PAN_SPEED, deltaY * PAN_SPEED);
cam.update();
return true;
}


My Image is very large, 4096x4096, and my camera is 480x800. My problem is I have no idea how to get the distance I have panned, and even if I did I dont know how to stop a pan from moving past a certain point, just setting camera position won't work because then there will be a "bounce" back.

Basically I have a rectangle inside another rectangle, and the inner rectangle should not be allowed to move outside the larger. But as I said I don't really know where to start since I can't get the panning distance.

Ex of something I've tried:

@Override
public boolean touchDown(float x, float y, int pointer, int button) {
startX = x * PAN_SPEED;
return false;
}

@Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
if(-totalX > map.getX() + cam.viewportWidth/2){
cam.translate(-deltaX * PAN_SPEED, deltaY * PAN_SPEED);
cam.update();
}
return true;
}

@Override
public boolean panStop(float x, float y, int pointer, int button) {
endX = x* PAN_SPEED;
totalX += endX - startX;
System.out.println("pan: " + totalX + ", map: " + map.getX());
return true;
}


This is just a test, basically I can't move anymore after I hit the left border of the image, but totalX still keeps adding up so this will not work.

EDIT: Got it to work, code below:

@Override

public boolean pan(float x, float y, float deltaX, float deltaY) {
cam.translate(-deltaX, deltaY);
keepCameraInBounds();
cam.update();
return true;
}

private void keepCameraInBounds () {
OrthographicCamera c = this.cam;
Vector3 camPos = c.position;
float HW = c.viewportWidth / 2, HH = c.viewportHeight / 2;
camPos.x = MathUtils.clamp(camPos.x, map.getWidth()/2 - map.getWidth() + HW, map.getWidth() - map.getWidth()/2 - HW);
camPos.y = MathUtils.clamp(camPos.y, map.getHeight()/2 - map.getWidth() + HH, map.getHeight() - map.getHeight()/2 - HH);
}

• Can you get the position of the camera and use that in place of totalX? That would solve your accumulation problems. Apr 15 '15 at 19:49
• Hmm, never thot of that. Will try :) Apr 16 '15 at 6:09
• By "pan" do you mean using a DragListener? Apr 18 '15 at 2:09
• Not sure what DragListener is, pan is a method from abstract LibGdx class GestureListener. I will try ur answer when I get my computer back :) Apr 18 '15 at 18:47
• You can probably continue to use the pan method, I just don't have experience with it since I use DragListeners (I don't need advanced gesture support). My answer should still be able to solve your problem though :) Apr 18 '15 at 19:25

I will assume you are using a DragListener or something similar to achieve the "panning" effect. This is the method I have that keeps the camera within its bounds:

private void keepCameraInBounds () {
Camera c = this.getCamera();
Vector3 camPos = c.position;
float HW = c.viewportWidth / 2, HH = c.viewportHeight / 2;
camPos.x = MathUtils.clamp(camPos.x, HW, mapWidth - HW);
camPos.y = MathUtils.clamp(camPos.y, HH, mapHeight - HH);
}


Essentially what this does is clamp (keep between) the camera's position to legitimate points within the map. This means from half of its viewport off the left and bottom to the right and top edges of the map (or picture; the variables mapWidth and mapHeight control the size) minues half of its viewport. You need to use halves because a camera's viewport is centered about its position.

As long as you call this method directly after you change its position (due to the pan) it should not move outside of its boundaries. Also, make sure the camera.update() call is made after you check its bounds since you might be changing its position.

• I edited your solution a bit and bam, works like a charm :) Added the edited version to my answer May 1 '15 at 17:43
• @Max Glad I could help! Feel free to upvote as well ;) May 1 '15 at 20:23