From bcbac0fa90ee13d6439afa3ca3ef0d8c7bb0f348 Mon Sep 17 00:00:00 2001 From: Quillraven Date: Fri, 30 May 2025 00:18:12 +0200 Subject: [PATCH] add camera system and optimize y sorting for rendering --- assets/graphics/objects.atlas | 106 +++++++++--------- assets/graphics/objects.png | Bin 14697 -> 14467 bytes assets/maps/mainmap.tmx | 3 +- assets/maps/objects.tsx | 5 +- assets/maps/secondmap.tmx | 28 ----- assets/maps/tileset.tsx | 100 +++++++++++++++++ assets_raw/objects/oak_tree/oak_tree.png | Bin 1495 -> 5406 bytes .../io/github/com/quillraven/GdxGame.java | 4 +- .../github/com/quillraven/asset/MapAsset.java | 3 +- .../quillraven/component/CameraFollow.java | 6 + .../com/quillraven/component/Transform.java | 11 +- .../com/quillraven/screen/GameScreen.java | 5 +- .../com/quillraven/system/CameraSystem.java | 78 +++++++++++++ .../quillraven/tiled/TiledAshleySpawner.java | 16 ++- 14 files changed, 272 insertions(+), 93 deletions(-) delete mode 100644 assets/maps/secondmap.tmx create mode 100644 core/src/main/java/io/github/com/quillraven/component/CameraFollow.java create mode 100644 core/src/main/java/io/github/com/quillraven/system/CameraSystem.java diff --git a/assets/graphics/objects.atlas b/assets/graphics/objects.atlas index e37f140..c87c44d 100644 --- a/assets/graphics/objects.atlas +++ b/assets/graphics/objects.atlas @@ -6,357 +6,357 @@ filter: Nearest, Nearest repeat: none chest/chest rotate: false - xy: 2, 2 + xy: 482, 237 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 house/house rotate: false - xy: 2, 142 + xy: 2, 141 size: 80, 112 orig: 80, 112 offset: 0, 0 index: -1 oak_tree/oak_tree rotate: false - xy: 2, 58 - size: 64, 80 - orig: 64, 80 + xy: 2, 74 + size: 41, 63 + orig: 41, 63 offset: 0, 0 index: -1 player/idle_down rotate: false - xy: 86, 222 + xy: 86, 221 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 0 player/idle_down rotate: false - xy: 2, 22 + xy: 2, 38 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 1 player/idle_down rotate: false - xy: 86, 186 + xy: 47, 105 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 2 player/idle_down rotate: false - xy: 122, 222 + xy: 86, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 3 player/idle_down rotate: false - xy: 86, 150 + xy: 122, 221 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 4 player/idle_down rotate: false - xy: 122, 186 + xy: 2, 2 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 5 player/idle_left rotate: false - xy: 158, 222 + xy: 86, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 0 player/idle_left rotate: false - xy: 122, 150 + xy: 122, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 1 player/idle_left rotate: false - xy: 158, 186 + xy: 158, 221 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 2 player/idle_left rotate: false - xy: 194, 222 + xy: 122, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 3 player/idle_left rotate: false - xy: 158, 150 + xy: 158, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 4 player/idle_left rotate: false - xy: 194, 186 + xy: 194, 221 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 5 player/idle_right rotate: false - xy: 230, 222 + xy: 158, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 0 player/idle_right rotate: false - xy: 194, 150 + xy: 194, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 1 player/idle_right rotate: false - xy: 230, 186 + xy: 230, 221 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 2 player/idle_right rotate: false - xy: 266, 222 + xy: 194, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 3 player/idle_right rotate: false - xy: 230, 150 + xy: 230, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 4 player/idle_right rotate: false - xy: 266, 186 + xy: 266, 221 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 5 player/idle_up rotate: false - xy: 302, 222 + xy: 230, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 0 player/idle_up rotate: false - xy: 266, 150 + xy: 266, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 1 player/idle_up rotate: false - xy: 302, 186 + xy: 302, 221 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 2 player/idle_up rotate: false - xy: 338, 222 + xy: 266, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 3 player/idle_up rotate: false - xy: 302, 150 + xy: 302, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 4 player/idle_up rotate: false - xy: 338, 186 + xy: 338, 221 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 5 player/walk_down rotate: false - xy: 374, 222 + xy: 302, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 0 player/walk_down rotate: false - xy: 338, 150 + xy: 338, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 1 player/walk_down rotate: false - xy: 374, 186 + xy: 374, 221 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 2 player/walk_down rotate: false - xy: 410, 222 + xy: 338, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 3 player/walk_down rotate: false - xy: 374, 150 + xy: 374, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 4 player/walk_down rotate: false - xy: 410, 186 + xy: 410, 221 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 5 player/walk_left rotate: false - xy: 446, 222 + xy: 374, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 0 player/walk_left rotate: false - xy: 410, 150 + xy: 410, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 1 player/walk_left rotate: false - xy: 446, 186 + xy: 446, 221 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 2 player/walk_left rotate: false - xy: 446, 150 + xy: 410, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 3 player/walk_left rotate: false - xy: 38, 22 + xy: 446, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 4 player/walk_left rotate: false - xy: 70, 106 + xy: 446, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 5 player/walk_right rotate: false - xy: 70, 70 + xy: 47, 69 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 0 player/walk_right rotate: false - xy: 106, 114 + xy: 38, 33 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 1 player/walk_right rotate: false - xy: 106, 78 + xy: 74, 33 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 2 player/walk_right rotate: false - xy: 142, 114 + xy: 86, 113 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 3 player/walk_right rotate: false - xy: 142, 78 + xy: 122, 113 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 4 player/walk_right rotate: false - xy: 178, 114 + xy: 158, 113 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 5 player/walk_up rotate: false - xy: 178, 78 + xy: 194, 113 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 0 player/walk_up rotate: false - xy: 214, 114 + xy: 230, 113 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 1 player/walk_up rotate: false - xy: 214, 78 + xy: 266, 113 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 2 player/walk_up rotate: false - xy: 250, 114 + xy: 302, 113 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 3 player/walk_up rotate: false - xy: 250, 78 + xy: 338, 113 size: 32, 32 orig: 32, 32 offset: 0, 0 index: 4 player/walk_up rotate: false - xy: 286, 114 + xy: 374, 113 size: 32, 32 orig: 32, 32 offset: 0, 0 diff --git a/assets/graphics/objects.png b/assets/graphics/objects.png index e2462c4849528bc012dc40cbee8bba9297c5ef43..d945c67cdb6cab8890b40e978bbef799c5b68163 100644 GIT binary patch literal 14467 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 literal 14697 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 diff --git a/assets/maps/mainmap.tmx b/assets/maps/mainmap.tmx index 4eed490..1f14860 100644 --- a/assets/maps/mainmap.tmx +++ b/assets/maps/mainmap.tmx @@ -1,5 +1,5 @@ - + @@ -31,6 +31,7 @@ + diff --git a/assets/maps/objects.tsx b/assets/maps/objects.tsx index 4cbb157..715e5e1 100644 --- a/assets/maps/objects.tsx +++ b/assets/maps/objects.tsx @@ -4,7 +4,7 @@ - + @@ -20,6 +20,9 @@ + + + diff --git a/assets/maps/secondmap.tmx b/assets/maps/secondmap.tmx deleted file mode 100644 index fa070c2..0000000 --- a/assets/maps/secondmap.tmx +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - eJx9k1EOgDAMQnuC0fufVj9c0jyhH426RmiBdVXpq/NWf89b7DXe3XfjHwHvGL5e+hfD9RR4Jyfx545acLjf1INcqr8W3CdhzRkFbrc3+elb0oN7J4+pjfNl027z12XM4au8rvOcZw6bnnBWzpw0Tr47zxKu67m7xDwkz1MuqWnCp5bprqQMu5mYGZfl2X8AE4YQ2w== - - - - - eJxjYBgFo2AUjIKBAQAEgAAB - - - - - eJxjYBgFo2AUjIKBAQAEgAAB - - - - - eJxjYBgFo2AUjIKBAQAEgAAB - - - - - - diff --git a/assets/maps/tileset.tsx b/assets/maps/tileset.tsx index 0ae7864..c508304 100644 --- a/assets/maps/tileset.tsx +++ b/assets/maps/tileset.tsx @@ -1,6 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets_raw/objects/oak_tree/oak_tree.png b/assets_raw/objects/oak_tree/oak_tree.png index 5dbb903cf3178b51b6c40c3f2743d8882bf25a57..a88b0fccc26f591a1487ea26635eeada9e053921 100644 GIT binary patch literal 5406 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 { private final int z; private final Vector2 size; private final Vector2 scaling; - private final float rotationDeg; + private float rotationDeg; + private float sortOffsetY; public Transform( Vector2 position, int z, Vector2 size, Vector2 scaling, - float rotationDeg + float rotationDeg, + float sortOffsetY ) { this.position = position; this.z = z; this.size = size; this.scaling = scaling; this.rotationDeg = rotationDeg; + this.sortOffsetY = sortOffsetY; } @Override @@ -32,8 +35,8 @@ public class Transform implements Component, Comparable { if (this.z != other.z) { return Float.compare(this.z, other.z); } - if (this.position.y != other.position.y) { - return Float.compare(other.position.y, this.position.y); + if (this.position.y + this.sortOffsetY != other.position.y + other.sortOffsetY) { + return Float.compare(other.position.y + other.sortOffsetY, this.position.y + this.sortOffsetY); } return Float.compare(this.position.x, other.position.x); } diff --git a/core/src/main/java/io/github/com/quillraven/screen/GameScreen.java b/core/src/main/java/io/github/com/quillraven/screen/GameScreen.java index eebe7d5..d8b9f0d 100644 --- a/core/src/main/java/io/github/com/quillraven/screen/GameScreen.java +++ b/core/src/main/java/io/github/com/quillraven/screen/GameScreen.java @@ -16,6 +16,7 @@ import io.github.com.quillraven.component.Controller; import io.github.com.quillraven.input.GameControllerState; import io.github.com.quillraven.input.KeyboardController; import io.github.com.quillraven.system.AnimationSystem; +import io.github.com.quillraven.system.CameraSystem; import io.github.com.quillraven.system.FacingSystem; import io.github.com.quillraven.system.FsmSystem; import io.github.com.quillraven.system.PhysicDebugRenderSystem; @@ -48,6 +49,7 @@ public class GameScreen extends ScreenAdapter { this.engine.addSystem(new FacingSystem()); this.engine.addSystem(new FsmSystem()); this.engine.addSystem(new AnimationSystem(game.getAssetService())); + this.engine.addSystem(new CameraSystem(game.getCamera())); this.engine.addSystem(new RenderSystem(game.getBatch(), game.getViewport(), game.getCamera())); this.engine.addSystem(new PhysicDebugRenderSystem(this.physicWorld, game.getCamera())); } @@ -61,7 +63,8 @@ public class GameScreen extends ScreenAdapter { Consumer renderConsumer = this.engine.getSystem(RenderSystem.class)::setMap; Consumer ashleySpawnerConsumer = this.tiledAshleySpawner::loadMapObjects; - this.tiledService.setMapChangeConsumer(renderConsumer.andThen(ashleySpawnerConsumer)); + Consumer cameraConsumer = this.engine.getSystem(CameraSystem.class)::setMap; + this.tiledService.setMapChangeConsumer(renderConsumer.andThen(ashleySpawnerConsumer).andThen(cameraConsumer)); TiledMap startMap = this.tiledService.loadMap(MapAsset.MAIN); this.tiledService.setMap(startMap); diff --git a/core/src/main/java/io/github/com/quillraven/system/CameraSystem.java b/core/src/main/java/io/github/com/quillraven/system/CameraSystem.java new file mode 100644 index 0000000..e2e545a --- /dev/null +++ b/core/src/main/java/io/github/com/quillraven/system/CameraSystem.java @@ -0,0 +1,78 @@ +package io.github.com.quillraven.system; + +import com.badlogic.ashley.core.Entity; +import com.badlogic.ashley.core.Family; +import com.badlogic.ashley.systems.IteratingSystem; +import com.badlogic.gdx.graphics.Camera; +import com.badlogic.gdx.maps.tiled.TiledMap; +import com.badlogic.gdx.math.MathUtils; +import com.badlogic.gdx.math.Vector2; +import io.github.com.quillraven.GdxGame; +import io.github.com.quillraven.component.CameraFollow; +import io.github.com.quillraven.component.Transform; + +public class CameraSystem extends IteratingSystem { + private static final float CAM_OFFSET_Y = 1f; // make the camera look up 'X' additional tiles + + private final Camera camera; + private final float smoothingFactor; + private final Vector2 targetPosition; + private float mapW; + private float mapH; + + public CameraSystem(Camera camera) { + super(Family.all(CameraFollow.class, Transform.class).get()); + this.camera = camera; + this.smoothingFactor = 4f; // lower value = slower camera follow + this.targetPosition = new Vector2(); + } + + @Override + protected void processEntity(Entity entity, float deltaTime) { + Transform transform = Transform.MAPPER.get(entity); + calcTargetPosition(transform.getPosition()); + + // Apply smoothing using linear interpolation (LERP) + float progress = smoothingFactor * deltaTime; + float smoothedX = MathUtils.lerp(camera.position.x, this.targetPosition.x, progress); + float smoothedY = MathUtils.lerp(camera.position.y, this.targetPosition.y, progress); + camera.position.set(smoothedX, smoothedY, camera.position.z); + } + + private void calcTargetPosition(Vector2 entityPosition) { + // Keep the target position within map boundaries + float targetX = entityPosition.x; + float targetY = entityPosition.y + CAM_OFFSET_Y; + float camHalfW = camera.viewportWidth * 0.5f; + if (mapW > camHalfW) { + float min = Math.min(camHalfW, mapW - camHalfW); + float max = Math.max(camHalfW, mapW - camHalfW); + targetX = MathUtils.clamp(targetX, min, max); + } + float camHalfH = camera.viewportHeight * 0.5f; + if (mapH > camHalfH) { + float min = Math.min(camHalfH, mapH - camHalfH); + float max = Math.max(camHalfH, mapH - camHalfH); + targetY = MathUtils.clamp(targetY, min, max); + } + this.targetPosition.set(targetX, targetY); + } + + public void setMap(TiledMap tiledMap) { + int width = tiledMap.getProperties().get("width", 0, Integer.class); + int tileW = tiledMap.getProperties().get("tilewidth", 0, Integer.class); + int height = tiledMap.getProperties().get("height", 0, Integer.class); + int tileH = tiledMap.getProperties().get("tileheight", 0, Integer.class); + mapW = width * tileW * GdxGame.UNIT_SCALE; + mapH = height * tileH * GdxGame.UNIT_SCALE; + + Entity camEntity = getEntities().first(); + if (camEntity == null) { + return; + } + + Transform transform = Transform.MAPPER.get(camEntity); + calcTargetPosition(transform.getPosition()); + camera.position.set(this.targetPosition.x, this.targetPosition.y, camera.position.z); + } +} diff --git a/core/src/main/java/io/github/com/quillraven/tiled/TiledAshleySpawner.java b/core/src/main/java/io/github/com/quillraven/tiled/TiledAshleySpawner.java index 844f182..6ec47fe 100644 --- a/core/src/main/java/io/github/com/quillraven/tiled/TiledAshleySpawner.java +++ b/core/src/main/java/io/github/com/quillraven/tiled/TiledAshleySpawner.java @@ -26,6 +26,7 @@ import io.github.com.quillraven.GdxGame; import io.github.com.quillraven.asset.AtlasAsset; import io.github.com.quillraven.component.Animation2D; import io.github.com.quillraven.component.Animation2D.AnimationType; +import io.github.com.quillraven.component.CameraFollow; import io.github.com.quillraven.component.Controller; import io.github.com.quillraven.component.Facing; import io.github.com.quillraven.component.Facing.FacingDirection; @@ -88,6 +89,7 @@ public class TiledAshleySpawner { rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight(), 1f, 1f, + 0, entity); addEntityPhysic( rectMapObj, @@ -116,11 +118,14 @@ public class TiledAshleySpawner { TiledMapTile tile = tileMapObject.getTile(); TextureRegion textureRegion = tile.getTextureRegion(); String classType = tile.getProperties().get("type", "", String.class); + float sortOffsetY = tile.getProperties().get("sortOffsetY", 0, Integer.class); + sortOffsetY *= GdxGame.UNIT_SCALE; addEntityTransform( tileMapObject.getX(), tileMapObject.getY(), textureRegion.getRegionWidth(), textureRegion.getRegionHeight(), tileMapObject.getScaleX(), tileMapObject.getScaleY(), + sortOffsetY, entity); addEntityPhysic( tile.getObjects(), @@ -130,6 +135,7 @@ public class TiledAshleySpawner { addEntityAnimation(tile, entity); addEntityMove(tile, entity); addEntityController(tileMapObject, entity); + addEntityCameraFollow(tileMapObject, entity); entity.add(new Facing(FacingDirection.DOWN)); entity.add(new Fsm(entity)); entity.add(new Graphic(textureRegion, Color.WHITE.cpy())); @@ -137,6 +143,13 @@ public class TiledAshleySpawner { this.engine.addEntity(entity); } + private void addEntityCameraFollow(TiledMapTileMapObject tileMapObject, Entity entity) { + boolean cameraFollow = tileMapObject.getProperties().get("camFollow", false, Boolean.class); + if (!cameraFollow) return; + + entity.add(new CameraFollow()); + } + private void addEntityController(TiledMapTileMapObject tileMapObject, Entity entity) { boolean controller = tileMapObject.getProperties().get("controller", false, Boolean.class); if (!controller) return; @@ -212,6 +225,7 @@ public class TiledAshleySpawner { float x, float y, float w, float h, float scaleX, float scaleY, + float sortOffsetY, Entity entity ) { Vector2 position = new Vector2(x, y); @@ -221,7 +235,7 @@ public class TiledAshleySpawner { position.scl(GdxGame.UNIT_SCALE); size.scl(GdxGame.UNIT_SCALE); - entity.add(new Transform(position, 0, size, scaling, 0f)); + entity.add(new Transform(position, 0, size, scaling, 0f, sortOffsetY)); } }