diff --git a/engine/src/main/java/com/bartlomiejpluta/base/core/world/object/Sprite.java b/engine/src/main/java/com/bartlomiejpluta/base/core/world/object/Sprite.java index 4822c6ee..5dbdfcb8 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/core/world/object/Sprite.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/core/world/object/Sprite.java @@ -7,10 +7,7 @@ import com.bartlomiejpluta.base.core.gl.shader.constant.UniformName; import com.bartlomiejpluta.base.core.gl.shader.manager.ShaderManager; import com.bartlomiejpluta.base.core.ui.Window; import com.bartlomiejpluta.base.core.world.camera.Camera; -import lombok.EqualsAndHashCode; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.Setter; +import lombok.*; @RequiredArgsConstructor @EqualsAndHashCode(callSuper = true) @@ -21,6 +18,7 @@ public abstract class Sprite extends Model implements Renderable { @NonNull @Setter + @Getter protected Material material; @Override diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/image/asset/ImageAsset.java b/game/src/main/java/com/bartlomiejpluta/base/game/image/asset/ImageAsset.java new file mode 100644 index 00000000..70957030 --- /dev/null +++ b/game/src/main/java/com/bartlomiejpluta/base/game/image/asset/ImageAsset.java @@ -0,0 +1,10 @@ +package com.bartlomiejpluta.base.game.image.asset; + +import com.bartlomiejpluta.base.game.common.asset.Asset; +import lombok.NonNull; + +public class ImageAsset extends Asset { + public ImageAsset(@NonNull String uid, @NonNull String source) { + super(uid, source); + } +} diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/image/manager/DefaultImageManager.java b/game/src/main/java/com/bartlomiejpluta/base/game/image/manager/DefaultImageManager.java index 8b3cb2a9..fa2db09d 100644 --- a/game/src/main/java/com/bartlomiejpluta/base/game/image/manager/DefaultImageManager.java +++ b/game/src/main/java/com/bartlomiejpluta/base/game/image/manager/DefaultImageManager.java @@ -1,36 +1,57 @@ package com.bartlomiejpluta.base.game.image.manager; +import com.bartlomiejpluta.base.core.error.AppException; import com.bartlomiejpluta.base.core.gl.object.material.Material; import com.bartlomiejpluta.base.core.gl.object.texture.TextureManager; import com.bartlomiejpluta.base.core.util.math.MathUtil; import com.bartlomiejpluta.base.core.util.mesh.MeshManager; +import com.bartlomiejpluta.base.game.image.asset.ImageAsset; import com.bartlomiejpluta.base.game.image.model.Image; +import com.bartlomiejpluta.base.game.project.config.ProjectConfiguration; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.HashMap; +import java.util.Map; + @Slf4j @Component @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class DefaultImageManager implements ImageManager { private final MeshManager meshManager; private final TextureManager textureManager; + private final Map assets = new HashMap<>(); + private final ProjectConfiguration configuration; + @Override - public Image createImage(String imageFileName) { - var texture = textureManager.loadTexture(imageFileName); + public void registerAsset(ImageAsset asset) { + log.info("Registering [{}] image asset under UID: [{}]", asset.getSource(), asset.getUid()); + assets.put(asset.getUid(), asset); + } + + @Override + public Image loadImage(String uid) { + var asset = assets.get(uid); + + if (asset == null) { + throw new AppException("The image asset with UID: [%s] does not exist", uid); + } + + var source = configuration.projectFile("images", asset.getSource()); + var texture = textureManager.loadTexture(source); var width = texture.getWidth(); var height = texture.getHeight(); var gcd = MathUtil.gcdEuclidean(width, height); var initialWidth = width / gcd; var initialHeight = height / gcd; var mesh = meshManager.createQuad(initialWidth, initialHeight, 0, 0); + var material = Material.textured(texture); + log.info("Creating new image on asset with UID: [{}]", uid); - var image = new Image(mesh, Material.textured(texture), initialWidth, initialHeight); - image.setScale(gcd); - - return image; + return new Image(mesh, material, initialWidth, initialHeight, gcd); } @Override diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/image/manager/ImageManager.java b/game/src/main/java/com/bartlomiejpluta/base/game/image/manager/ImageManager.java index e6c4263e..ecd44869 100644 --- a/game/src/main/java/com/bartlomiejpluta/base/game/image/manager/ImageManager.java +++ b/game/src/main/java/com/bartlomiejpluta/base/game/image/manager/ImageManager.java @@ -1,8 +1,11 @@ package com.bartlomiejpluta.base.game.image.manager; import com.bartlomiejpluta.base.core.gc.Cleanable; +import com.bartlomiejpluta.base.game.image.asset.ImageAsset; import com.bartlomiejpluta.base.game.image.model.Image; public interface ImageManager extends Cleanable { - Image createImage(String imageFileName); + void registerAsset(ImageAsset asset); + + Image loadImage(String uid); } diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/image/model/Image.java b/game/src/main/java/com/bartlomiejpluta/base/game/image/model/Image.java index 11293cfa..50c11f32 100644 --- a/game/src/main/java/com/bartlomiejpluta/base/game/image/model/Image.java +++ b/game/src/main/java/com/bartlomiejpluta/base/game/image/model/Image.java @@ -9,10 +9,12 @@ import lombok.Getter; public class Image extends Sprite { private final int initialWidth; private final int initialHeight; + private final int gcd; - public Image(Mesh mesh, Material texture, int initialWidth, int initialHeight) { + public Image(Mesh mesh, Material texture, int initialWidth, int initialHeight, int gcd) { super(mesh, texture); this.initialWidth = initialWidth; this.initialHeight = initialHeight; + this.gcd = gcd; } } diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/map/layer/image/ImageLayer.java b/game/src/main/java/com/bartlomiejpluta/base/game/map/layer/image/ImageLayer.java index e1ed6aeb..b3e9e09f 100644 --- a/game/src/main/java/com/bartlomiejpluta/base/game/map/layer/image/ImageLayer.java +++ b/game/src/main/java/com/bartlomiejpluta/base/game/map/layer/image/ImageLayer.java @@ -1,12 +1,12 @@ package com.bartlomiejpluta.base.game.map.layer.image; -import com.bartlomiejpluta.base.core.gl.shader.constant.UniformName; import com.bartlomiejpluta.base.core.gl.shader.manager.ShaderManager; import com.bartlomiejpluta.base.core.ui.Window; import com.bartlomiejpluta.base.core.world.camera.Camera; import com.bartlomiejpluta.base.game.image.model.Image; import com.bartlomiejpluta.base.game.map.layer.base.Layer; import com.bartlomiejpluta.base.game.map.model.GameMap; +import lombok.NonNull; public class ImageLayer implements Layer { private final float mapWidth; @@ -15,35 +15,48 @@ public class ImageLayer implements Layer { private Image image; private float imageInitialWidth; private float imageInitialHeight; + + @NonNull private final ImageLayerMode mode; - public ImageLayer(GameMap map, Image image, ImageLayerMode mode) { + public ImageLayer(GameMap map, Image image, ImageLayerMode mode, float opacity, float x, float y) { this.mapWidth = map.getWidth(); this.mapHeight = map.getHeight(); this.mode = mode; + setImage(image); + setOpacity(opacity); + setPosition(x, y); } public void setImage(Image image) { this.image = image; this.imageInitialWidth = image.getInitialWidth(); this.imageInitialHeight = image.getInitialHeight(); + + switch (mode) { + case NORMAL -> image.setScale(image.getGcd() * imageInitialWidth, image.getGcd() * imageInitialHeight); + case FIT_MAP -> image.setScale(mapWidth / imageInitialWidth, mapHeight / imageInitialHeight); + } + } + + public void setOpacity(float opacity) { + this.image.getMaterial().setAlpha(opacity); + } + + public void setPosition(float x, float y) { + image.setPosition(x, y); } @Override public void render(Window window, Camera camera, ShaderManager shaderManager) { - if (image == null) { - return; + if (image != null) { + if (mode == ImageLayerMode.FIT_SCREEN) { + image.setScale(window.getWidth() / imageInitialWidth, window.getHeight() / imageInitialHeight); + } + + image.render(window, camera, shaderManager); } - - shaderManager.setUniform(UniformName.UNI_VIEW_MODEL_MATRIX, camera.computeViewModelMatrix(image.getModelMatrix())); - - switch (mode) { - case FIT_SCREEN -> image.setScale(window.getWidth() / imageInitialWidth, window.getHeight() / imageInitialHeight); - case FIT_MAP -> image.setScale(mapWidth / imageInitialWidth, mapHeight / imageInitialHeight); - } - - image.render(window, camera, shaderManager); } @Override diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/map/model/GameMap.java b/game/src/main/java/com/bartlomiejpluta/base/game/map/model/GameMap.java index 191ab436..c0cce7a2 100644 --- a/game/src/main/java/com/bartlomiejpluta/base/game/map/model/GameMap.java +++ b/game/src/main/java/com/bartlomiejpluta/base/game/map/model/GameMap.java @@ -97,8 +97,8 @@ public class GameMap implements Renderable, Updatable { return layers.size() - 1; } - public int createImageLayer(Image image, ImageLayerMode imageDisplayMode) { - layers.add(new ImageLayer(this, image, imageDisplayMode)); + public int createImageLayer(Image image, ImageLayerMode imageDisplayMode, float opacity, float x, float y) { + layers.add(new ImageLayer(this, image, imageDisplayMode, opacity, x, y)); return layers.size() - 1; } diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/map/serial/ProtobufMapDeserializer.java b/game/src/main/java/com/bartlomiejpluta/base/game/map/serial/ProtobufMapDeserializer.java index fa990e09..3b499b93 100644 --- a/game/src/main/java/com/bartlomiejpluta/base/game/map/serial/ProtobufMapDeserializer.java +++ b/game/src/main/java/com/bartlomiejpluta/base/game/map/serial/ProtobufMapDeserializer.java @@ -2,6 +2,8 @@ package com.bartlomiejpluta.base.game.map.serial; import com.bartlomiejpluta.base.core.error.AppException; import com.bartlomiejpluta.base.core.util.mesh.MeshManager; +import com.bartlomiejpluta.base.game.image.manager.ImageManager; +import com.bartlomiejpluta.base.game.map.layer.image.ImageLayerMode; import com.bartlomiejpluta.base.game.map.layer.object.PassageAbility; import com.bartlomiejpluta.base.game.map.model.GameMap; import com.bartlomiejpluta.base.game.tileset.manager.TileSetManager; @@ -19,6 +21,7 @@ import java.io.InputStream; public class ProtobufMapDeserializer extends MapDeserializer { private final MeshManager meshManager; private final TileSetManager tileSetManager; + private final ImageManager imageManager; @Override protected GameMap parse(InputStream input) throws Exception { @@ -90,6 +93,14 @@ public class ProtobufMapDeserializer extends MapDeserializer { } private void deserializeImageLayer(GameMap map, GameMapProto.Layer proto) { - // TODO(return new ImageLayer(...)) + var protoImageLayer = proto.getImageLayer(); + var image = imageManager.loadImage(proto.getImageLayer().getImageUID()); + var mode = switch (proto.getImageLayer().getMode()) { + case NORMAL -> ImageLayerMode.NORMAL; + case FIT_MAP -> ImageLayerMode.FIT_MAP; + case FIT_SCREEN -> ImageLayerMode.FIT_SCREEN; + }; + + map.createImageLayer(image, mode, protoImageLayer.getOpacity() / 100.0f, protoImageLayer.getX(), protoImageLayer.getY()); } } diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/project/loader/DefaultProjectLoader.java b/game/src/main/java/com/bartlomiejpluta/base/game/project/loader/DefaultProjectLoader.java index eea216c7..7d44f126 100644 --- a/game/src/main/java/com/bartlomiejpluta/base/game/project/loader/DefaultProjectLoader.java +++ b/game/src/main/java/com/bartlomiejpluta/base/game/project/loader/DefaultProjectLoader.java @@ -1,5 +1,6 @@ package com.bartlomiejpluta.base.game.project.loader; +import com.bartlomiejpluta.base.game.image.manager.ImageManager; import com.bartlomiejpluta.base.game.map.manager.MapManager; import com.bartlomiejpluta.base.game.project.config.ProjectConfiguration; import com.bartlomiejpluta.base.game.project.serial.ProjectDeserializer; @@ -11,10 +12,11 @@ import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class DefaultProjectLoader implements ProjectLoader { + private final ProjectConfiguration configuration; private final ProjectDeserializer projectDeserializer; private final TileSetManager tileSetManager; private final MapManager mapManager; - private final ProjectConfiguration configuration; + private final ImageManager imageManager; @Override public void loadProject() { @@ -22,5 +24,6 @@ public class DefaultProjectLoader implements ProjectLoader { var project = projectDeserializer.deserialize(resource); project.getTileSetAssets().forEach(tileSetManager::registerAsset); project.getMapAssets().forEach(mapManager::registerAsset); + project.getImageAssets().forEach(imageManager::registerAsset); } } diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/project/model/Project.java b/game/src/main/java/com/bartlomiejpluta/base/game/project/model/Project.java index 47cdcc8c..7f2dbc20 100644 --- a/game/src/main/java/com/bartlomiejpluta/base/game/project/model/Project.java +++ b/game/src/main/java/com/bartlomiejpluta/base/game/project/model/Project.java @@ -1,5 +1,6 @@ package com.bartlomiejpluta.base.game.project.model; +import com.bartlomiejpluta.base.game.image.asset.ImageAsset; import com.bartlomiejpluta.base.game.map.asset.GameMapAsset; import com.bartlomiejpluta.base.game.tileset.asset.TileSetAsset; import lombok.Getter; @@ -20,4 +21,7 @@ public class Project { @NonNull private final List mapAssets; + + @NonNull + private final List imageAssets; } diff --git a/game/src/main/java/com/bartlomiejpluta/base/game/project/serial/ProtobufProjectDeserializer.java b/game/src/main/java/com/bartlomiejpluta/base/game/project/serial/ProtobufProjectDeserializer.java index 6dd66748..42b0648d 100644 --- a/game/src/main/java/com/bartlomiejpluta/base/game/project/serial/ProtobufProjectDeserializer.java +++ b/game/src/main/java/com/bartlomiejpluta/base/game/project/serial/ProtobufProjectDeserializer.java @@ -1,5 +1,6 @@ package com.bartlomiejpluta.base.game.project.serial; +import com.bartlomiejpluta.base.game.image.asset.ImageAsset; import com.bartlomiejpluta.base.game.map.asset.GameMapAsset; import com.bartlomiejpluta.base.game.project.model.Project; import com.bartlomiejpluta.base.game.tileset.asset.TileSetAsset; @@ -19,7 +20,8 @@ public class ProtobufProjectDeserializer extends ProjectDeserializer { var name = proto.getName(); var tileSetAssets = proto.getTileSetsList().stream().map(this::parseTileSetAsset).collect(toList()); var mapAssets = proto.getMapsList().stream().map(this::parseGameMapAsset).collect(toList()); - return new Project(name, tileSetAssets, mapAssets); + var imageAssets = proto.getImagesList().stream().map(this::parseImageAsset).collect(toList()); + return new Project(name, tileSetAssets, mapAssets, imageAssets); } private TileSetAsset parseTileSetAsset(ProjectProto.TileSetAsset proto) { @@ -29,4 +31,8 @@ public class ProtobufProjectDeserializer extends ProjectDeserializer { private GameMapAsset parseGameMapAsset(ProjectProto.GameMapAsset proto) { return new GameMapAsset(proto.getUid(), proto.getSource()); } + + private ImageAsset parseImageAsset(ProjectProto.ImageAsset proto) { + return new ImageAsset(proto.getUid(), proto.getSource()); + } }