diff options
Diffstat (limited to 'core/src/ch/asynk/zproject/screens/GameCamera.java')
-rw-r--r-- | core/src/ch/asynk/zproject/screens/GameCamera.java | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/core/src/ch/asynk/zproject/screens/GameCamera.java b/core/src/ch/asynk/zproject/screens/GameCamera.java new file mode 100644 index 0000000..e735bb5 --- /dev/null +++ b/core/src/ch/asynk/zproject/screens/GameCamera.java @@ -0,0 +1,211 @@ +package ch.asynk.zproject.screens; + +import com.badlogic.gdx.graphics.glutils.HdpiUtils; +import com.badlogic.gdx.graphics.OrthographicCamera; + +import com.badlogic.gdx.math.Rectangle; +import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.math.MathUtils; +import com.badlogic.gdx.math.Matrix4; + +public class GameCamera extends OrthographicCamera +{ + private static final float ZEROF = 0.01f; + + private int padding; + private float boardWidth; + private float boardHeight; + private float boardAspectRatio; + private float zoomMax; + private float zoomMin; + private int screenWidth; + private int screenHeight; + private float widthFactor; + private float heightFactor; + private Rectangle viewport; + + private Rectangle hud; + private Matrix4 hudMatrix; + private Matrix4 hudInvProjMatrix; + private int hudLeft; + private int hudBottom; + private boolean hudInBoard; + + public GameCamera(int padding, float boardWidth, float boardHeight, float zoomMax, float zoomMin, boolean hudInBoard) + { + super(boardWidth, boardHeight); + this.boardWidth = boardWidth; + this.boardHeight = boardHeight; + this.padding = padding; + this.boardAspectRatio = (boardWidth / boardHeight); + this.zoomMax = zoomMax; + this.zoomMin = zoomMin; + this.viewport = new Rectangle(); + + this.hudInBoard = hudInBoard; + this.hud = new Rectangle(); + this.hudMatrix = new Matrix4(); + this.hudInvProjMatrix = new Matrix4(); + } + + public void updateViewport(int screenWidth, int screenHeight) + { + this.screenWidth = screenWidth; + this.screenHeight = screenHeight; + + float screenAvailableWidth = screenWidth - (2 * padding); + float screenAvailableHeight = screenHeight - (2 * padding); + float screenAspectRatio = (screenWidth / (float) screenHeight); + float diff = (boardAspectRatio - screenAspectRatio); + + if (diff <= -ZEROF) { + // screen wider than board : use max height, width grows up until max available on zooming + viewport.height = screenAvailableHeight; + viewport.width = java.lang.Math.min((screenAvailableHeight * boardAspectRatio / zoom), screenAvailableWidth); + viewport.x = padding + ((screenAvailableWidth - viewport.width) / 2f); + viewport.y = padding; + // camera aspect ratio must follow viewport aspect ration + viewportHeight = boardHeight; + viewportWidth = (viewportHeight * (viewport.width / viewport.height)); + // hud + hud.y = 0; + hud.x = (hud.y * viewportWidth / viewportHeight); + } else if (diff > ZEROF) { + // word is wider than screen : use max width, height grows up until max available on zooming + viewport.width = screenAvailableWidth; + viewport.height = java.lang.Math.min((screenAvailableWidth / boardAspectRatio / zoom), screenAvailableHeight); + viewport.y = padding + ((screenAvailableHeight - viewport.height) / 2f); + viewport.x = padding; + // camera aspect ratio must follow viewport aspect ration + viewportWidth = boardWidth; + viewportHeight = (viewportWidth * (viewport.height / viewport.width)); + // hud + hud.x = 0; + hud.y = (hud.x * viewportHeight / viewportWidth); + } + + if (hudInBoard) { + hud.x = 0; + hud.y = 0; + hud.width = screenWidth; + hud.height = screenHeight; + } else { + hud.width = (viewport.width - (2 * hud.x)); + hud.height = (viewport.height - (2 * hud.y)); + } + + // ratio viewport -> camera + widthFactor = (viewportWidth / viewport.width); + heightFactor = (viewportHeight / viewport.height); + + clampPosition(); + update(true); + + hudMatrix.setToOrtho2D(hud.x, hud.y, hud.width, hud.height); + hudInvProjMatrix.set(hudMatrix); + Matrix4.inv(hudInvProjMatrix.val); + } + + public void applyMapViewport() + { + HdpiUtils.glViewport((int)viewport.x, (int)viewport.y, (int)viewport.width, (int)viewport.height); + } + + public void applyHudViewport() + { + if (hudInBoard) + HdpiUtils.glViewport(0, 0, screenWidth, screenHeight); + else + applyMapViewport(); + } + + public void centerOnWorld() + { + position.set((boardWidth / 2f), (boardHeight / 2f), 0f); + } + + public void zoom(float dz) + { + zoom += dz; + clampZoom(); + updateViewport(screenWidth, screenHeight); // zoom impacts viewport + } + + public void clampZoom() + { + zoom = MathUtils.clamp(zoom, zoomMin, zoomMax); + } + + public void translate(float dx, float dy) + { + float deltaX = (dx * zoom * widthFactor); + float deltaY = (dy * zoom * heightFactor); + translate(deltaX, -deltaY, 0); + clampPosition(); + update(true); + } + + public void clampPosition() + { + float cameraWidth = (viewportWidth * zoom); + float cameraHeight = (viewportHeight * zoom); + + // on each axis, clamp on [ cameraDim/2 ; boardDim - cameraDim/2 ] + + if ((boardWidth - cameraWidth) > ZEROF) { + cameraWidth /= 2f; + position.x = MathUtils.clamp(position.x, cameraWidth, (boardWidth - cameraWidth)); + } else { + position.x = (boardWidth / 2f); + } + + if ((boardHeight - cameraHeight) > ZEROF) { + cameraHeight /= 2f; + position.y = MathUtils.clamp(position.y, cameraHeight, (boardHeight - cameraHeight)); + } else { + position.y = (boardHeight / 2f); + } + } + + public void unproject(int x, int y, Vector3 v) + { + unproject(v.set(x, y, 0), viewport.x, viewport.y, viewport.width, viewport.height); + } + + public void unprojectHud(float x, float y, Vector3 v) + { + Rectangle r = (hudInBoard ? hud : viewport); + x = x - r.x; + y = screenHeight - y - 1; + y = y - r.y; + v.x = (2 * x) / r.width - 1; + v.y = (2 * y) / r.height - 1; + v.z = 2 * v.z - 1; + v.prj(hudInvProjMatrix); + } + + public int getScreenWidth() + { + return screenWidth; + } + + public int getScreenHeight() + { + return screenHeight; + } + + public Matrix4 getHudMatrix() + { + return hudMatrix; + } + + public Rectangle getViewport() + { + return viewport; + } + + public Rectangle getHud() + { + return hud; + } +} |