Create animation scaffolding in :engine
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
package com.bartlomiejpluta.base.api.game.animation;
|
||||||
|
|
||||||
|
import com.bartlomiejpluta.base.api.game.entity.Direction;
|
||||||
|
import com.bartlomiejpluta.base.api.game.entity.Movement;
|
||||||
|
import com.bartlomiejpluta.base.api.game.map.layer.object.ObjectLayer;
|
||||||
|
import com.bartlomiejpluta.base.api.internal.logic.Updatable;
|
||||||
|
import com.bartlomiejpluta.base.api.internal.object.Placeable;
|
||||||
|
import com.bartlomiejpluta.base.api.internal.render.Renderable;
|
||||||
|
import org.joml.Vector2ic;
|
||||||
|
|
||||||
|
public interface Animation extends Placeable, Renderable, Updatable {
|
||||||
|
void setStepSize(float x, float y);
|
||||||
|
|
||||||
|
Vector2ic getCoordinates();
|
||||||
|
|
||||||
|
void setCoordinates(Vector2ic coordinates);
|
||||||
|
|
||||||
|
void setCoordinates(int x, int y);
|
||||||
|
|
||||||
|
Movement prepareMovement(Direction direction);
|
||||||
|
|
||||||
|
Movement getMovement();
|
||||||
|
|
||||||
|
void setSpeed(float speed);
|
||||||
|
|
||||||
|
void setAnimationSpeed(float speed);
|
||||||
|
|
||||||
|
boolean isMoving();
|
||||||
|
|
||||||
|
void onAdd(ObjectLayer layer);
|
||||||
|
|
||||||
|
void onRemove(ObjectLayer layer);
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import com.bartlomiejpluta.base.engine.gui.xml.inflater.Inflater;
|
|||||||
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
|
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
|
||||||
import com.bartlomiejpluta.base.engine.project.serial.ProjectDeserializer;
|
import com.bartlomiejpluta.base.engine.project.serial.ProjectDeserializer;
|
||||||
import com.bartlomiejpluta.base.engine.util.reflection.ClassLoader;
|
import com.bartlomiejpluta.base.engine.util.reflection.ClassLoader;
|
||||||
|
import com.bartlomiejpluta.base.engine.world.animation.manager.AnimationManager;
|
||||||
import com.bartlomiejpluta.base.engine.world.entity.manager.EntityManager;
|
import com.bartlomiejpluta.base.engine.world.entity.manager.EntityManager;
|
||||||
import com.bartlomiejpluta.base.engine.world.entity.manager.EntitySetManager;
|
import com.bartlomiejpluta.base.engine.world.entity.manager.EntitySetManager;
|
||||||
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
|
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
|
||||||
@@ -34,6 +35,7 @@ public class DefaultContextManager implements ContextManager {
|
|||||||
private final EntitySetManager entitySetManager;
|
private final EntitySetManager entitySetManager;
|
||||||
private final FontManager fontManager;
|
private final FontManager fontManager;
|
||||||
private final EntityManager entityManager;
|
private final EntityManager entityManager;
|
||||||
|
private final AnimationManager animationManager;
|
||||||
private final ClassLoader classLoader;
|
private final ClassLoader classLoader;
|
||||||
private final Inflater inflater;
|
private final Inflater inflater;
|
||||||
private final WidgetDefinitionManager widgetDefinitionManager;
|
private final WidgetDefinitionManager widgetDefinitionManager;
|
||||||
@@ -50,6 +52,7 @@ public class DefaultContextManager implements ContextManager {
|
|||||||
project.getMapAssets().forEach(mapManager::registerAsset);
|
project.getMapAssets().forEach(mapManager::registerAsset);
|
||||||
project.getImageAssets().forEach(imageManager::registerAsset);
|
project.getImageAssets().forEach(imageManager::registerAsset);
|
||||||
project.getEntitySetAssets().forEach(entitySetManager::registerAsset);
|
project.getEntitySetAssets().forEach(entitySetManager::registerAsset);
|
||||||
|
project.getAnimationAssets().forEach(animationManager::registerAsset);
|
||||||
project.getFontAssets().forEach(fontManager::registerAsset);
|
project.getFontAssets().forEach(fontManager::registerAsset);
|
||||||
project.getWidgetDefinitionAssets().forEach(widgetDefinitionManager::registerAsset);
|
project.getWidgetDefinitionAssets().forEach(widgetDefinitionManager::registerAsset);
|
||||||
|
|
||||||
|
|||||||
@@ -2,18 +2,19 @@ package com.bartlomiejpluta.base.engine.project.model;
|
|||||||
|
|
||||||
import com.bartlomiejpluta.base.engine.gui.asset.FontAsset;
|
import com.bartlomiejpluta.base.engine.gui.asset.FontAsset;
|
||||||
import com.bartlomiejpluta.base.engine.gui.asset.WidgetDefinitionAsset;
|
import com.bartlomiejpluta.base.engine.gui.asset.WidgetDefinitionAsset;
|
||||||
|
import com.bartlomiejpluta.base.engine.world.animation.asset.AnimationAsset;
|
||||||
import com.bartlomiejpluta.base.engine.world.entity.asset.EntitySetAsset;
|
import com.bartlomiejpluta.base.engine.world.entity.asset.EntitySetAsset;
|
||||||
import com.bartlomiejpluta.base.engine.world.image.asset.ImageAsset;
|
import com.bartlomiejpluta.base.engine.world.image.asset.ImageAsset;
|
||||||
import com.bartlomiejpluta.base.engine.world.map.asset.GameMapAsset;
|
import com.bartlomiejpluta.base.engine.world.map.asset.GameMapAsset;
|
||||||
import com.bartlomiejpluta.base.engine.world.tileset.asset.TileSetAsset;
|
import com.bartlomiejpluta.base.engine.world.tileset.asset.TileSetAsset;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@RequiredArgsConstructor
|
@Builder
|
||||||
public class Project {
|
public class Project {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -34,6 +35,9 @@ public class Project {
|
|||||||
@NonNull
|
@NonNull
|
||||||
private final List<EntitySetAsset> entitySetAssets;
|
private final List<EntitySetAsset> entitySetAssets;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private final List<AnimationAsset> animationAssets;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final List<FontAsset> fontAssets;
|
private final List<FontAsset> fontAssets;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.bartlomiejpluta.base.engine.project.serial;
|
|||||||
import com.bartlomiejpluta.base.engine.gui.asset.FontAsset;
|
import com.bartlomiejpluta.base.engine.gui.asset.FontAsset;
|
||||||
import com.bartlomiejpluta.base.engine.gui.asset.WidgetDefinitionAsset;
|
import com.bartlomiejpluta.base.engine.gui.asset.WidgetDefinitionAsset;
|
||||||
import com.bartlomiejpluta.base.engine.project.model.Project;
|
import com.bartlomiejpluta.base.engine.project.model.Project;
|
||||||
|
import com.bartlomiejpluta.base.engine.world.animation.asset.AnimationAsset;
|
||||||
import com.bartlomiejpluta.base.engine.world.entity.asset.EntitySetAsset;
|
import com.bartlomiejpluta.base.engine.world.entity.asset.EntitySetAsset;
|
||||||
import com.bartlomiejpluta.base.engine.world.image.asset.ImageAsset;
|
import com.bartlomiejpluta.base.engine.world.image.asset.ImageAsset;
|
||||||
import com.bartlomiejpluta.base.engine.world.map.asset.GameMapAsset;
|
import com.bartlomiejpluta.base.engine.world.map.asset.GameMapAsset;
|
||||||
@@ -20,16 +21,18 @@ public class ProtobufProjectDeserializer extends ProjectDeserializer {
|
|||||||
@Override
|
@Override
|
||||||
protected Project parse(InputStream input) throws Exception {
|
protected Project parse(InputStream input) throws Exception {
|
||||||
var proto = ProjectProto.Project.parseFrom(input);
|
var proto = ProjectProto.Project.parseFrom(input);
|
||||||
var name = proto.getName();
|
|
||||||
var runner = proto.getRunner();
|
|
||||||
var tileSetAssets = proto.getTileSetsList().stream().map(this::parseTileSetAsset).collect(toList());
|
|
||||||
var mapAssets = proto.getMapsList().stream().map(this::parseGameMapAsset).collect(toList());
|
|
||||||
var imageAssets = proto.getImagesList().stream().map(this::parseImageAsset).collect(toList());
|
|
||||||
var entitySetAssets = proto.getEntitySetsList().stream().map(this::parseEntitySetAsset).collect(toList());
|
|
||||||
var fontAssets = proto.getFontsList().stream().map(this::parseFontAsset).collect(toList());
|
|
||||||
var widgetAssets = proto.getWidgetsList().stream().map(this::parseWidgetAsset).collect(toList());
|
|
||||||
|
|
||||||
return new Project(name, runner, tileSetAssets, mapAssets, imageAssets, entitySetAssets, fontAssets, widgetAssets);
|
return Project.builder()
|
||||||
|
.name(proto.getName())
|
||||||
|
.runner(proto.getRunner())
|
||||||
|
.tileSetAssets(proto.getTileSetsList().stream().map(this::parseTileSetAsset).collect(toList()))
|
||||||
|
.mapAssets(proto.getMapsList().stream().map(this::parseGameMapAsset).collect(toList()))
|
||||||
|
.imageAssets(proto.getImagesList().stream().map(this::parseImageAsset).collect(toList()))
|
||||||
|
.entitySetAssets(proto.getEntitySetsList().stream().map(this::parseEntitySetAsset).collect(toList()))
|
||||||
|
.animationAssets(proto.getAnimationsList().stream().map(this::parseAnimationAsset).collect(toList()))
|
||||||
|
.fontAssets(proto.getFontsList().stream().map(this::parseFontAsset).collect(toList()))
|
||||||
|
.widgetDefinitionAssets(proto.getWidgetsList().stream().map(this::parseWidgetAsset).collect(toList()))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private TileSetAsset parseTileSetAsset(ProjectProto.TileSetAsset proto) {
|
private TileSetAsset parseTileSetAsset(ProjectProto.TileSetAsset proto) {
|
||||||
@@ -55,4 +58,8 @@ public class ProtobufProjectDeserializer extends ProjectDeserializer {
|
|||||||
private WidgetDefinitionAsset parseWidgetAsset(ProjectProto.WidgetAsset proto) {
|
private WidgetDefinitionAsset parseWidgetAsset(ProjectProto.WidgetAsset proto) {
|
||||||
return new WidgetDefinitionAsset(proto.getUid(), proto.getSource());
|
return new WidgetDefinitionAsset(proto.getUid(), proto.getSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AnimationAsset parseAnimationAsset(ProjectProto.AnimationAsset proto) {
|
||||||
|
return new AnimationAsset(proto.getUid(), proto.getSource(), proto.getRows(), proto.getColumns());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.bartlomiejpluta.base.engine.world.animation.asset;
|
||||||
|
|
||||||
|
import com.bartlomiejpluta.base.engine.common.asset.Asset;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class AnimationAsset extends Asset {
|
||||||
|
private final int rows;
|
||||||
|
private final int columns;
|
||||||
|
private final String framesSignature;
|
||||||
|
|
||||||
|
public AnimationAsset(@NonNull String uid, @NonNull String source, int rows, int columns) {
|
||||||
|
super(uid, source);
|
||||||
|
this.rows = rows;
|
||||||
|
this.columns = columns;
|
||||||
|
this.framesSignature = String.format("%dx%d", rows, columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String framesSignature() {
|
||||||
|
return framesSignature;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.bartlomiejpluta.base.engine.world.animation.manager;
|
||||||
|
|
||||||
|
import com.bartlomiejpluta.base.api.game.animation.Animation;
|
||||||
|
import com.bartlomiejpluta.base.engine.common.manager.AssetManager;
|
||||||
|
import com.bartlomiejpluta.base.engine.world.animation.asset.AnimationAsset;
|
||||||
|
|
||||||
|
public interface AnimationManager extends AssetManager<AnimationAsset, Animation> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.bartlomiejpluta.base.engine.world.animation.manager;
|
||||||
|
|
||||||
|
import com.bartlomiejpluta.base.api.game.animation.Animation;
|
||||||
|
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||||
|
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||||
|
import com.bartlomiejpluta.base.engine.core.gl.object.texture.TextureManager;
|
||||||
|
import com.bartlomiejpluta.base.engine.error.AppException;
|
||||||
|
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
|
||||||
|
import com.bartlomiejpluta.base.engine.util.mesh.MeshManager;
|
||||||
|
import com.bartlomiejpluta.base.engine.world.animation.asset.AnimationAsset;
|
||||||
|
import com.bartlomiejpluta.base.engine.world.animation.model.DefaultAnimation;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.joml.Vector2f;
|
||||||
|
import org.joml.Vector2fc;
|
||||||
|
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 DefaultAnimationManager implements AnimationManager {
|
||||||
|
private final MeshManager meshManager;
|
||||||
|
private final TextureManager textureManager;
|
||||||
|
private final Map<String, AnimationAsset> assets = new HashMap<>();
|
||||||
|
private final Map<String, Vector2fc[]> frames = new HashMap<>();
|
||||||
|
private final ProjectConfiguration configuration;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerAsset(AnimationAsset asset) {
|
||||||
|
log.info("Registering [{}] animation asset under UID: [{}]", asset.getSource(), asset.getUid());
|
||||||
|
assets.put(asset.getUid(), asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Animation loadObject(String uid) {
|
||||||
|
var asset = assets.get(uid);
|
||||||
|
|
||||||
|
if (asset == null) {
|
||||||
|
throw new AppException("The entity set asset with UID: [%s] does not exist", uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
var animationFrames = frames.computeIfAbsent(asset.framesSignature(),
|
||||||
|
signature -> createFrames(asset.getRows(), asset.getColumns())
|
||||||
|
);
|
||||||
|
|
||||||
|
var source = configuration.projectFile("animations", asset.getSource());
|
||||||
|
var texture = textureManager.loadTexture(source, asset.getRows(), asset.getColumns());
|
||||||
|
var material = Material.textured(texture);
|
||||||
|
var mesh = buildMesh(material, asset.getRows(), asset.getColumns());
|
||||||
|
|
||||||
|
return new DefaultAnimation(mesh, material, animationFrames);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2fc[] createFrames(int rows, int columns) {
|
||||||
|
var frames = new Vector2fc[rows * columns];
|
||||||
|
|
||||||
|
for (int row = 0; row < rows; ++row) {
|
||||||
|
for (int column = 0; column < columns; ++column) {
|
||||||
|
frames[row * columns + column] = new Vector2f(column, row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mesh buildMesh(Material material, int rows, int columns) {
|
||||||
|
var texture = material.getTexture();
|
||||||
|
var spriteWidth = texture.getWidth() / columns;
|
||||||
|
var spriteHeight = texture.getHeight() / rows;
|
||||||
|
return meshManager.createQuad(spriteWidth, spriteHeight, spriteWidth / 2f, spriteHeight * 0.9f);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.bartlomiejpluta.base.engine.world.animation;
|
package com.bartlomiejpluta.base.engine.world.animation.model;
|
||||||
|
|
||||||
import com.bartlomiejpluta.base.api.game.camera.Camera;
|
import com.bartlomiejpluta.base.api.game.camera.Camera;
|
||||||
import com.bartlomiejpluta.base.api.game.screen.Screen;
|
import com.bartlomiejpluta.base.api.game.screen.Screen;
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package com.bartlomiejpluta.base.engine.world.animation.model;
|
||||||
|
|
||||||
|
import com.bartlomiejpluta.base.api.game.animation.Animation;
|
||||||
|
import com.bartlomiejpluta.base.api.game.map.layer.object.ObjectLayer;
|
||||||
|
import com.bartlomiejpluta.base.api.util.math.MathUtil;
|
||||||
|
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||||
|
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||||
|
import com.bartlomiejpluta.base.engine.world.movement.MovableSprite;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.joml.Vector2fc;
|
||||||
|
|
||||||
|
public class DefaultAnimation extends MovableSprite implements Animation {
|
||||||
|
private final Vector2fc[] frames;
|
||||||
|
private int animationSpeed = 100;
|
||||||
|
|
||||||
|
public DefaultAnimation(Mesh mesh, Material material, @NonNull Vector2fc[] frames) {
|
||||||
|
super(mesh, material);
|
||||||
|
this.frames = frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpeed(float speed) {
|
||||||
|
framesToCrossOneTile = (int) (1 / MathUtil.clamp(speed, Float.MIN_VALUE, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAnimationSpeed(float speed) {
|
||||||
|
animationSpeed = (int) (1 / MathUtil.clamp(speed, Float.MIN_VALUE, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAdd(ObjectLayer layer) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRemove(ObjectLayer layer) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAnimationSpeed() {
|
||||||
|
return animationSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldAnimate() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector2fc[] getSpriteAnimationFramesPositions() {
|
||||||
|
return frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setDefaultAnimationFrame() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,17 @@ public class DefaultEntity extends MovableSprite implements Entity {
|
|||||||
@Getter
|
@Getter
|
||||||
private Direction faceDirection;
|
private Direction faceDirection;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private boolean blocking;
|
||||||
|
|
||||||
|
public DefaultEntity(Mesh mesh, Material material, Map<Direction, Integer> spriteDirectionRows, Map<Direction, Vector2fc> spriteDefaultRows) {
|
||||||
|
super(mesh, material);
|
||||||
|
this.spriteDirectionRows = spriteDirectionRows;
|
||||||
|
this.faceDirection = Direction.DOWN;
|
||||||
|
this.spriteDefaultRows = spriteDefaultRows;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAnimationSpeed() {
|
public int getAnimationSpeed() {
|
||||||
return animationSpeed;
|
return animationSpeed;
|
||||||
@@ -37,10 +48,6 @@ public class DefaultEntity extends MovableSprite implements Entity {
|
|||||||
return isMoving();
|
return isMoving();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private boolean blocking;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2fc[] getSpriteAnimationFramesPositions() {
|
public Vector2fc[] getSpriteAnimationFramesPositions() {
|
||||||
var row = spriteDirectionRows.get(faceDirection);
|
var row = spriteDirectionRows.get(faceDirection);
|
||||||
@@ -109,11 +116,4 @@ public class DefaultEntity extends MovableSprite implements Entity {
|
|||||||
public void onRemove(ObjectLayer layer) {
|
public void onRemove(ObjectLayer layer) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultEntity(Mesh mesh, Material material, Map<Direction, Integer> spriteDirectionRows, Map<Direction, Vector2fc> spriteDefaultRows) {
|
|
||||||
super(mesh, material);
|
|
||||||
this.spriteDirectionRows = spriteDirectionRows;
|
|
||||||
this.faceDirection = Direction.DOWN;
|
|
||||||
this.spriteDefaultRows = spriteDefaultRows;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import com.bartlomiejpluta.base.api.game.entity.Movement;
|
|||||||
import com.bartlomiejpluta.base.api.internal.logic.Updatable;
|
import com.bartlomiejpluta.base.api.internal.logic.Updatable;
|
||||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||||
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
|
||||||
import com.bartlomiejpluta.base.engine.world.animation.AnimatedSprite;
|
import com.bartlomiejpluta.base.engine.world.animation.model.AnimatedSprite;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.joml.Vector2f;
|
import org.joml.Vector2f;
|
||||||
|
|||||||
Reference in New Issue
Block a user