Answers:
好了,所以您在这里使用两个矩形。其中较大的静态对象(地图)和较小的活动对象(相机)。您想要的是不要让较小矩形的边界移到较大矩形的内部边界之外。
// These values likely need to be scaled according to your world coordinates.
// The left boundary of the map (x)
int mapLeft = 0;
// The right boundary of the map (x + width)
int mapRight = 0 + map.getWidth();
// The bottom boundary of the map (y)
int mapBottom = 0;
// The top boundary of the map (y + height)
int mapTop = 0 + map.getHeight();
// The camera dimensions, halved
float cameraHalfWidth = cam.viewportWidth * .5f;
float cameraHalfHeight = cam.viewportHeight * .5f;
// Move camera after player as normal
float cameraLeft = cam.position.x - cameraHalfWidth;
float cameraRight = cam.position.x + cameraHalfWidth;
float cameraBottom = cam.position.y - cameraHalfHeight;
float cameraTop = cam.position.y + cameraHalfHeight;
// Horizontal axis
if(map.getWidth() < cam.viewportWidth)
{
cam.position.x = mapRight / 2;
}
else if(cameraLeft <= mapLeft)
{
cam.position.x = mapLeft + cameraHalfWidth;
}
else if(cameraRight >= mapRight)
{
cam.position.x = mapRight - cameraHalfWidth;
}
// Vertical axis
if(map.getHeight() < cam.viewportHeight)
{
cam.position.y = mapTop / 2;
}
else if(cameraBottom <= mapBottom)
{
cam.position.y = mapBottom + cameraHalfHeight;
}
else if(cameraTop >= mapTop)
{
cam.position.y = mapTop - cameraHalfHeight;
}
因此逻辑很简单。将小盒子放在大盒子里。一旦您了解了这个主意,就可以随意折叠该代码。如果愿意,您甚至可以在相机位置跟踪中将其移动到一系列嵌套的Min / Max语句中。
您可以像这样轻松地将相机位置固定在地图边界上:
camera.position.x = MathUtils.clamp(camera.position.x, camViewportHalfX, mapWidth - camViewportHalfX);
camera.position.y = MathUtils.clamp(camera.position.y, camViewportHalfY, mapHeight - camViewportHalfY);
camViewportHalfX
和camViewportHalfY
?
camViewportHalfX
等于camera.viewportWidth / 2
?
要移动Camera
的TiledMap
界限,OrthogonalTiledMapRenderer
被使用。
我还注意到它的行为异常:Camera
到达地图边界时,平铺的地图会像惯性一样将某些像素移得太远(取决于滑动的速度)。
作为解决方案,每次Camera
移动都Camera
被强制置于地图范围内。参见putInMapBounds()
方法。
为避免TiledMap
渲染出现毛刺,请使用Math.min(float, float)
。
使用此侦听器来处理您的Camera
:
/**
* @author Gram <gram7gram@gmail.com>
*/
public class CameraListener extends InputAdapter {
private final UIStage stage;
private final Camera camera;
private final Vector3 curr;
private final Vector3 last;
private final Vector3 delta;
private final int mapWidth;
private final int mapHeight;
public CameraListener(UIStage stage) {
this.stage = stage;
this.camera = stage.getViewport().getCamera();
curr = new Vector3();
last = new Vector3(-1, -1, -1);
delta = new Vector3();
TiledMapTileLayer layer = stage.getLevel().getMap().getFirstLayer();
mapWidth = layer.getWidth() * DDGame.TILE_HEIGHT;
mapHeight = layer.getHeight() * DDGame.TILE_HEIGHT;
}
@Override
public boolean touchDragged(int x, int y, int pointer) {
camera.unproject(curr.set(x, y, 0));
if (!(last.x == -1 && last.y == -1 && last.z == -1)) {
camera.unproject(delta.set(last.x, last.y, 0));
delta.sub(curr);
camera.translate(Math.min(delta.x, 5), Math.min(delta.y, 5), 0);
if (isInMapBounds()) {
stage.moveBy(Math.min(delta.x, 5), Math.min(delta.y, 5));
}
}
last.set(x, y, 0);
putInMapBounds();
return false;
}
private boolean isInMapBounds() {
return camera.position.x >= camera.viewportWidth / 2f
&& camera.position.x <= mapWidth - camera.viewportWidth / 2f
&& camera.position.y >= camera.viewportHeight / 2f
&& camera.position.y <= mapHeight - camera.viewportHeight / 2f;
}
private void putInMapBounds() {
if (camera.position.x < camera.viewportWidth / 2f)
camera.position.x = camera.viewportWidth / 2f;
else if (camera.position.x > mapWidth - camera.viewportWidth / 2f)
camera.position.x = mapWidth - camera.viewportWidth / 2f;
if (camera.position.y < camera.viewportHeight / 2f)
camera.position.y = camera.viewportHeight / 2f;
else if (camera.position.y > mapHeight - camera.viewportHeight / 2f)
camera.position.y = mapHeight - camera.viewportHeight / 2f;
stage.moveTo(
camera.position.x,
camera.position.y);
}
@Override
public boolean touchUp(int x, int y, int pointer, int button) {
last.set(-1, -1, -1);
Log.info("Camera at " + camera.position.x + ":" + camera.position.y);
return false;
}
}
如果您有足够的缩放系数,我发现它可以更好地工作:
public void fixBounds() {
float scaledViewportWidthHalfExtent = viewportWidth * zoom * 0.5f;
float scaledViewportHeightHalfExtent = viewportHeight * zoom * 0.5f;
// Horizontal
if (position.x < scaledViewportWidthHalfExtent)
position.x = scaledViewportWidthHalfExtent;
else if (position.x > xmax - scaledViewportWidthHalfExtent)
position.x = xmax - scaledViewportWidthHalfExtent;
// Vertical
if (position.y < scaledViewportHeightHalfExtent)
position.y = scaledViewportHeightHalfExtent;
else if (position.y > ymax - scaledViewportHeightHalfExtent)
position.y = ymax - scaledViewportHeightHalfExtent;
}
setPosition()
方法来固定边界,而是直接设置了凸轮的位置(例如cam.position.set()
)。这就像一个魅力!感谢您的解释!