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 e2462c4..d945c67 100644 Binary files a/assets/graphics/objects.png and b/assets/graphics/objects.png differ 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 5dbb903..a88b0fc 100644 Binary files a/assets_raw/objects/oak_tree/oak_tree.png and b/assets_raw/objects/oak_tree/oak_tree.png differ diff --git a/core/src/main/java/io/github/com/quillraven/GdxGame.java b/core/src/main/java/io/github/com/quillraven/GdxGame.java index 1592dad..2dc6f09 100644 --- a/core/src/main/java/io/github/com/quillraven/GdxGame.java +++ b/core/src/main/java/io/github/com/quillraven/GdxGame.java @@ -20,8 +20,8 @@ import io.github.com.quillraven.screen.LoadingScreen; import java.util.HashMap; public class GdxGame extends Game { - public static final float WORLD_HEIGHT = 11f; - public static final float WORLD_WIDTH = 6f; + public static final float WORLD_HEIGHT = 9f; + public static final float WORLD_WIDTH = 16f; public static final float UNIT_SCALE = 1f / 16f; private Batch batch; diff --git a/core/src/main/java/io/github/com/quillraven/asset/MapAsset.java b/core/src/main/java/io/github/com/quillraven/asset/MapAsset.java index 0829bfa..0bc1514 100644 --- a/core/src/main/java/io/github/com/quillraven/asset/MapAsset.java +++ b/core/src/main/java/io/github/com/quillraven/asset/MapAsset.java @@ -1,8 +1,7 @@ package io.github.com.quillraven.asset; public enum MapAsset { - MAIN("mainmap.tmx"), - SECOND("secondmap.tmx"); + MAIN("mainmap.tmx"); private final String path; diff --git a/core/src/main/java/io/github/com/quillraven/component/CameraFollow.java b/core/src/main/java/io/github/com/quillraven/component/CameraFollow.java new file mode 100644 index 0000000..8c3b477 --- /dev/null +++ b/core/src/main/java/io/github/com/quillraven/component/CameraFollow.java @@ -0,0 +1,6 @@ +package io.github.com.quillraven.component; + +import com.badlogic.ashley.core.Component; + +public class CameraFollow implements Component { +} diff --git a/core/src/main/java/io/github/com/quillraven/component/Transform.java b/core/src/main/java/io/github/com/quillraven/component/Transform.java index cad9bd9..8c5f9ee 100644 --- a/core/src/main/java/io/github/com/quillraven/component/Transform.java +++ b/core/src/main/java/io/github/com/quillraven/component/Transform.java @@ -11,20 +11,23 @@ public class Transform implements Component, Comparable { 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)); } }