gdx-studio
git clone https://git.pyrossh.dev/gdx-studio
An IDE for creating Games using libgdx and Java supported on all platforms Android, iOS, Desktop
src/scene2d/Camera.java
| a9b2a64 | 1 | package scene2d; |
| a9b2a64 | 2 | import com.badlogic.gdx.Gdx; |
| a9b2a64 | 3 | import com.badlogic.gdx.graphics.OrthographicCamera; |
| a9b2a64 | 4 | import com.badlogic.gdx.math.Interpolation; |
| a9b2a64 | 5 | import com.badlogic.gdx.math.Vector3; |
| a9b2a64 | 6 | import com.badlogic.gdx.scenes.scene2d.Actor; |
| a9b2a64 | 7 | import com.badlogic.gdx.utils.Array; |
| a9b2a64 | 8 | import com.badlogic.gdx.math.Rectangle; |
| a9b2a64 | 9 | |
| a9b2a64 | 10 | public class Camera extends OrthographicCamera {
|
| a9b2a64 | 11 | private static Camera instance; |
| a9b2a64 | 12 | private static float duration; |
| a9b2a64 | 13 | private static float time; |
| a9b2a64 | 14 | private static Interpolation interpolation; |
| a9b2a64 | 15 | private static boolean moveCompleted; |
| a9b2a64 | 16 | private static float lastPercent; |
| a9b2a64 | 17 | private static float percentDelta; |
| a9b2a64 | 18 | private static float panSpeedX, panSpeedY; |
| a9b2a64 | 19 | private static final Array<Actor> hudActors = new Array<Actor>(); |
| a9b2a64 | 20 | |
| a9b2a64 | 21 | |
| a9b2a64 | 22 | private static Actor followedActor = null; |
| a9b2a64 | 23 | private static float followSpeed = 1f; |
| a9b2a64 | 24 | /* |
| a9b2a64 | 25 | * This is to set the offsets of camera position when following the actor |
| a9b2a64 | 26 | * When the camera follows the actor its (x,y) position is set to actor's (x,y) position |
| a9b2a64 | 27 | * based on followSpeed. The offsets are used to position the camera in such a way that the actor |
| a9b2a64 | 28 | * doesn't need to be at the center of the camera always |
| a9b2a64 | 29 | */ |
| a9b2a64 | 30 | public static Rectangle followOffset = new Rectangle(10,70,10,60); |
| a9b2a64 | 31 | private static boolean followContinous = false; |
| a9b2a64 | 32 | |
| a9b2a64 | 33 | |
| a9b2a64 | 34 | public static boolean usePan = false; |
| a9b2a64 | 35 | public static boolean useDrag = false; |
| a9b2a64 | 36 | /* |
| a9b2a64 | 37 | * Sets the speed at which the camera pans. By default it moves 1px for a duration a 1f |
| a9b2a64 | 38 | * so its speed is 1px/f. So reduce the duration to increase its speed. |
| a9b2a64 | 39 | * ex: setPanSpeed(0.5) will change its speed to 2px/f |
| a9b2a64 | 40 | * Here: f can/maybe also indicate seconds |
| a9b2a64 | 41 | */ |
| a9b2a64 | 42 | public static float panSpeed = 5f; |
| a9b2a64 | 43 | public static Rectangle panSize; |
| a9b2a64 | 44 | |
| a9b2a64 | 45 | /* |
| a9b2a64 | 46 | * This sets the boundary of the camera till what position can it move or pan in the |
| a9b2a64 | 47 | * directions left, right, top, down. This is to prevent is from panning overboard the game area. |
| a9b2a64 | 48 | * Usually the bounds of the camera is like a rectangle. This must be calculated carefully |
| a9b2a64 | 49 | * as the camera's position is based on its center. |
| a9b2a64 | 50 | */ |
| a9b2a64 | 51 | public static Rectangle bounds = new Rectangle(0,0,999,999); |
| a9b2a64 | 52 | |
| a9b2a64 | 53 | |
| a9b2a64 | 54 | Camera(){
|
| a9b2a64 | 55 | setToOrtho(false, Scene.targetWidth, Scene.targetHeight); |
| a9b2a64 | 56 | position.set(Scene.targetWidth/2, Scene.targetHeight/2, 0); |
| a9b2a64 | 57 | instance = this; |
| a9b2a64 | 58 | panSize = new Rectangle(10, 10, Scene.targetWidth-10, Scene.targetHeight - 10); |
| a9b2a64 | 59 | } |
| a9b2a64 | 60 | |
| a9b2a64 | 61 | /* |
| a9b2a64 | 62 | * Moves the camera to x,y over a time duration |
| a9b2a64 | 63 | */ |
| a9b2a64 | 64 | public void moveTo(float x, float y, float duration) {
|
| a9b2a64 | 65 | moveBy(x-position.x, y-position.y, duration); |
| a9b2a64 | 66 | } |
| a9b2a64 | 67 | |
| a9b2a64 | 68 | /* |
| a9b2a64 | 69 | * Moves the camera by amountX, amountY over a time duration |
| a9b2a64 | 70 | */ |
| a9b2a64 | 71 | public static void moveBy (float amountX, float amountY, float duration) {
|
| a9b2a64 | 72 | moveBy(amountX, amountY, duration, null); |
| a9b2a64 | 73 | } |
| a9b2a64 | 74 | |
| a9b2a64 | 75 | /* |
| a9b2a64 | 76 | * Moves the camera by amountX, amountY over a time duration and interpolation interp |
| a9b2a64 | 77 | */ |
| a9b2a64 | 78 | public static void moveBy (float amountX, float amountY, float dur, Interpolation interp) {
|
| a9b2a64 | 79 | duration = dur; |
| a9b2a64 | 80 | interpolation = interp; |
| a9b2a64 | 81 | panSpeedX = amountX; |
| a9b2a64 | 82 | panSpeedY = amountY; |
| a9b2a64 | 83 | lastPercent = 0; |
| a9b2a64 | 84 | time = 0; |
| a9b2a64 | 85 | moveCompleted = false; |
| a9b2a64 | 86 | } |
| a9b2a64 | 87 | |
| a9b2a64 | 88 | private static Rectangle cullRect = new Rectangle(); |
| a9b2a64 | 89 | private void moveByAction(float delta){
|
| a9b2a64 | 90 | time += delta; |
| a9b2a64 | 91 | moveCompleted = time >= duration; |
| a9b2a64 | 92 | float percent; |
| a9b2a64 | 93 | if (moveCompleted) |
| a9b2a64 | 94 | percent = 1; |
| a9b2a64 | 95 | else {
|
| a9b2a64 | 96 | percent = time / duration; |
| a9b2a64 | 97 | if (interpolation != null) percent = interpolation.apply(percent); |
| a9b2a64 | 98 | } |
| a9b2a64 | 99 | percentDelta = percent - lastPercent; |
| a9b2a64 | 100 | if(Scene.cullingEnabled){
|
| a9b2a64 | 101 | cullRect.set(getXLeft(), getYBot(), Scene.targetWidth, Scene.targetHeight); |
| a9b2a64 | 102 | Scene.getCurrentScene().setCullingArea(cullRect); |
| a9b2a64 | 103 | } |
| a9b2a64 | 104 | translate(panSpeedX * percentDelta, panSpeedY * percentDelta, 0); |
| a9b2a64 | 105 | for(Actor actor: hudActors) |
| a9b2a64 | 106 | actor.setPosition(actor.getX()+panSpeedX * percentDelta, actor.getY()+panSpeedY * percentDelta); |
| a9b2a64 | 107 | lastPercent = percent; |
| a9b2a64 | 108 | if (moveCompleted) interpolation = null; |
| a9b2a64 | 109 | } |
| a9b2a64 | 110 | |
| a9b2a64 | 111 | public void resetCamera(){
|
| a9b2a64 | 112 | position.set(Scene.targetWidth/2, Scene.targetHeight/2, 0); |
| a9b2a64 | 113 | } |
| a9b2a64 | 114 | |
| a9b2a64 | 115 | /* |
| a9b2a64 | 116 | * This makes the camera follow the actor once and only once. Once the camera reaches its |
| a9b2a64 | 117 | * target, it stops following the actor. |
| a9b2a64 | 118 | */ |
| a9b2a64 | 119 | public static void followActor(Actor actor){
|
| a9b2a64 | 120 | followedActor = actor; |
| a9b2a64 | 121 | followContinous = false; |
| a9b2a64 | 122 | } |
| a9b2a64 | 123 | |
| a9b2a64 | 124 | /* |
| a9b2a64 | 125 | * This makes the camera follow the actor continuously, even after the camera reaches its |
| a9b2a64 | 126 | * target, it keeps following the if the actor changes its position. |
| a9b2a64 | 127 | */ |
| a9b2a64 | 128 | public static void followActorContinuously(Actor actor){
|
| a9b2a64 | 129 | followedActor = actor; |
| a9b2a64 | 130 | followContinous = true; |
| a9b2a64 | 131 | } |
| a9b2a64 | 132 | |
| a9b2a64 | 133 | |
| a9b2a64 | 134 | |
| a9b2a64 | 135 | /* |
| a9b2a64 | 136 | * Sets the speed at which the camera follows the actor. By default it moves 1px for a duration of 1f |
| a9b2a64 | 137 | * so its speed is 1px/f. So reduce the duration to increase its speed. |
| a9b2a64 | 138 | * ex: setPanSpeed(0.5) will change its speed to 2px/f |
| a9b2a64 | 139 | * Here: f can/maybe also indicate seconds |
| a9b2a64 | 140 | */ |
| a9b2a64 | 141 | public static void setFollowSpeed(float duration){
|
| a9b2a64 | 142 | followSpeed = duration; |
| a9b2a64 | 143 | } |
| a9b2a64 | 144 | |
| a9b2a64 | 145 | private void follow(){
|
| a9b2a64 | 146 | //if(camera.position.x == followedActor.getX()+followLeftOffset && |
| a9b2a64 | 147 | // camera.position.y == followedActor.getY()+followTopOffset) |
| a9b2a64 | 148 | //return; |
| a9b2a64 | 149 | //moveTo(followedActor.getX()+followLeftOffset, followedActor.getY()+followTopOffset, 100f); |
| a9b2a64 | 150 | if(position.x < followedActor.getX() - followOffset.x) moveBy(1f, 0, followSpeed); |
| a9b2a64 | 151 | else if(position.x > followedActor.getX() + followOffset.width) moveBy(-1f, 0, followSpeed); |
| a9b2a64 | 152 | else if(position.y < followedActor.getY() - followOffset.y) moveBy(0, 1f, followSpeed); |
| a9b2a64 | 153 | else if(position.y > followedActor.getY() - followOffset.height) moveBy(0, -1f, followSpeed); |
| a9b2a64 | 154 | else {
|
| a9b2a64 | 155 | if(!followContinous) |
| a9b2a64 | 156 | followedActor = null; |
| a9b2a64 | 157 | } |
| a9b2a64 | 158 | } |
| a9b2a64 | 159 | |
| a9b2a64 | 160 | @Override |
| a9b2a64 | 161 | public void update(){
|
| a9b2a64 | 162 | super.update(); |
| a9b2a64 | 163 | Scene.mouse.x = Gdx.input.getX(); |
| a9b2a64 | 164 | Scene.mouse.y = Gdx.graphics.getHeight() - Gdx.input.getY(); |
| a9b2a64 | 165 | if(!moveCompleted) |
| a9b2a64 | 166 | moveByAction(Scene.stateTime);//FIXME |
| a9b2a64 | 167 | if(usePan) |
| a9b2a64 | 168 | panCameraWithMouse(); |
| a9b2a64 | 169 | if(followedActor != null) |
| a9b2a64 | 170 | follow(); |
| a9b2a64 | 171 | } |
| a9b2a64 | 172 | |
| a9b2a64 | 173 | private void panCameraWithMouse(){
|
| a9b2a64 | 174 | if(Scene.mouse.x > panSize.width && getXLeft() < bounds.width) moveBy(1f, 0, panSpeed); |
| a9b2a64 | 175 | else if(Scene.mouse.x < panSize.x && getXLeft() > bounds.x) moveBy(-1f, 0, panSpeed); |
| a9b2a64 | 176 | else if(Scene.mouse.y < panSize.y && getYBot() > bounds.y) moveBy(0, -1f, panSpeed); |
| a9b2a64 | 177 | else if(Scene.mouse.y > panSize.height && getYBot() < bounds.height) moveBy(0, 1f, panSpeed); |
| a9b2a64 | 178 | } |
| a9b2a64 | 179 | |
| a9b2a64 | 180 | private final static Vector3 curr = new Vector3(); |
| a9b2a64 | 181 | private final static Vector3 last = new Vector3(-1, -1, -1); |
| a9b2a64 | 182 | private final static Vector3 deltaDrag = new Vector3(); |
| a9b2a64 | 183 | private static float deltaCamX = 0; |
| a9b2a64 | 184 | private static float deltaCamY = 0; |
| a9b2a64 | 185 | public static void dragCam(int x, int y){
|
| a9b2a64 | 186 | instance.unproject(curr.set(x, y, 0)); |
| a9b2a64 | 187 | if (!(last.x == -1 && last.y == -1 && last.z == -1)) {
|
| a9b2a64 | 188 | instance.unproject(deltaDrag.set(last.x, last.y, 0)); |
| a9b2a64 | 189 | deltaDrag.sub(curr); |
| a9b2a64 | 190 | deltaCamX = deltaDrag.x + instance.position.x; |
| a9b2a64 | 191 | deltaCamY = deltaDrag.y + instance.position.y; |
| a9b2a64 | 192 | if(deltaCamX > bounds.x && deltaCamX < bounds.x+bounds.width) |
| a9b2a64 | 193 | moveBy(deltaDrag.x, 0f, 0f); |
| a9b2a64 | 194 | if(deltaCamY > bounds.y && deltaCamY < bounds.y+bounds.height) |
| a9b2a64 | 195 | moveBy(0f, deltaDrag.y, 0f); |
| a9b2a64 | 196 | } |
| a9b2a64 | 197 | last.set(x, y, 0); |
| a9b2a64 | 198 | } |
| a9b2a64 | 199 | |
| a9b2a64 | 200 | public static void resetDrag(){
|
| a9b2a64 | 201 | last.set(-1, -1, -1); |
| a9b2a64 | 202 | } |
| a9b2a64 | 203 | |
| a9b2a64 | 204 | public static void reset(){
|
| a9b2a64 | 205 | usePan = false; |
| a9b2a64 | 206 | followActor(null); |
| a9b2a64 | 207 | clearAllHud(); |
| a9b2a64 | 208 | instance.position.set(Scene.targetWidth/2, Scene.targetHeight/2, 0); |
| a9b2a64 | 209 | } |
| a9b2a64 | 210 | |
| a9b2a64 | 211 | /* If you want to make any elements/actors to move along with the camera |
| a9b2a64 | 212 | * like HUD's add them using this method */ |
| a9b2a64 | 213 | public static void addHud(Actor actor){
|
| a9b2a64 | 214 | if(actor != null){
|
| a9b2a64 | 215 | Scene.getCurrentScene().addActor(actor); |
| a9b2a64 | 216 | hudActors.add(actor); |
| a9b2a64 | 217 | } |
| a9b2a64 | 218 | } |
| a9b2a64 | 219 | |
| a9b2a64 | 220 | /* If you want to make any elements/actors to move along with the camera |
| a9b2a64 | 221 | * like HUD's add them using this method */ |
| a9b2a64 | 222 | public static void addHud(String actorName){
|
| a9b2a64 | 223 | if(actorName != null && !actorName.isEmpty()){
|
| a9b2a64 | 224 | Actor actor = Scene.getCurrentScene().findActor(actorName); |
| a9b2a64 | 225 | Scene.getCurrentScene().addActor(actor); |
| a9b2a64 | 226 | hudActors.add(actor); |
| a9b2a64 | 227 | } |
| a9b2a64 | 228 | } |
| a9b2a64 | 229 | |
| a9b2a64 | 230 | |
| a9b2a64 | 231 | /* If you want to any elements/actors which was a Hud the use this */ |
| a9b2a64 | 232 | public static void removeHud(Actor actor){
|
| a9b2a64 | 233 | Scene.getCurrentScene().removeActor(actor); |
| a9b2a64 | 234 | hudActors.removeValue(actor, true); |
| a9b2a64 | 235 | } |
| a9b2a64 | 236 | |
| a9b2a64 | 237 | /* If you want to any elements/actors which was a Hud the use this */ |
| a9b2a64 | 238 | public static void removeHud(String actorName){
|
| a9b2a64 | 239 | if(actorName != null && !actorName.isEmpty()){
|
| a9b2a64 | 240 | Actor actor = Scene.getCurrentScene().findActor(actorName); |
| a9b2a64 | 241 | Scene.getCurrentScene().removeActor(actor); |
| a9b2a64 | 242 | hudActors.removeValue(actor, true); |
| a9b2a64 | 243 | } |
| a9b2a64 | 244 | } |
| a9b2a64 | 245 | |
| a9b2a64 | 246 | |
| a9b2a64 | 247 | |
| a9b2a64 | 248 | /* |
| a9b2a64 | 249 | * Clears all hud's registered with the camera |
| a9b2a64 | 250 | */ |
| a9b2a64 | 251 | public static void clearAllHud(){
|
| a9b2a64 | 252 | hudActors.clear(); |
| a9b2a64 | 253 | } |
| a9b2a64 | 254 | |
| a9b2a64 | 255 | /* |
| a9b2a64 | 256 | * Returns the x position of the camera |
| a9b2a64 | 257 | */ |
| a9b2a64 | 258 | public static float getX(){
|
| a9b2a64 | 259 | return instance.position.x; |
| a9b2a64 | 260 | } |
| a9b2a64 | 261 | |
| a9b2a64 | 262 | /* |
| a9b2a64 | 263 | * Returns the y position of the camera |
| a9b2a64 | 264 | */ |
| a9b2a64 | 265 | public static float getY(){
|
| a9b2a64 | 266 | return instance.position.y; |
| a9b2a64 | 267 | } |
| a9b2a64 | 268 | |
| a9b2a64 | 269 | public static float getXLeft(){
|
| a9b2a64 | 270 | return instance.position.x - Scene.targetWidth/2; |
| a9b2a64 | 271 | } |
| a9b2a64 | 272 | |
| a9b2a64 | 273 | public static float getYBot(){
|
| a9b2a64 | 274 | return instance.position.y - Scene.targetHeight/2; |
| a9b2a64 | 275 | } |
| a9b2a64 | 276 | |
| a9b2a64 | 277 | public static float getWidth(){
|
| a9b2a64 | 278 | return instance.viewportWidth; |
| a9b2a64 | 279 | } |
| a9b2a64 | 280 | |
| a9b2a64 | 281 | public static float getHeight(){
|
| a9b2a64 | 282 | return instance.viewportHeight; |
| a9b2a64 | 283 | } |
| a9b2a64 | 284 | } |