Refactor world-related objects | move them to :game module
This commit is contained in:
@@ -21,34 +21,32 @@ public class Mesh implements Renderable, Disposable {
|
||||
private final int elementsCount;
|
||||
|
||||
public Mesh(float[] vertices, float[] texCoords, int[] elements) {
|
||||
try(var stack = MemoryStack.stackPush()) {
|
||||
elementsCount = elements.length;
|
||||
var verticesBuffer = stack.mallocFloat(vertices.length);
|
||||
var texCoordsBuffer = stack.mallocFloat(texCoords.length);
|
||||
var elementsBuffer = stack.mallocInt(elementsCount);
|
||||
verticesBuffer.put(vertices).flip();
|
||||
texCoordsBuffer.put(texCoords).flip();
|
||||
elementsBuffer.put(elements).flip();
|
||||
elementsCount = elements.length;
|
||||
|
||||
var vboId = 0;
|
||||
try(var stack = MemoryStack.stackPush()) {
|
||||
vaoId = glGenVertexArrays();
|
||||
glBindVertexArray(vaoId);
|
||||
|
||||
int vboId = glGenBuffers();
|
||||
vboIds.add(vboId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboId);
|
||||
glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
|
||||
|
||||
// Vertices VBO
|
||||
vboId = glGenBuffers();
|
||||
vboIds.add(vboId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboId);
|
||||
glBufferData(GL_ARRAY_BUFFER, texCoordsBuffer, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, stack.mallocFloat(vertices.length).put(vertices).flip(), GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
|
||||
|
||||
// Texture Coordinates VBO
|
||||
vboId = glGenBuffers();
|
||||
vboIds.add(vboId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboId);
|
||||
glBufferData(GL_ARRAY_BUFFER, stack.mallocFloat(texCoords.length).put(texCoords).flip(), GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
|
||||
|
||||
// Elements VBO
|
||||
vboId = glGenBuffers();
|
||||
vboIds.add(vboId);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementsBuffer, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, stack.mallocInt(elementsCount).put(elements).flip(), GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
@@ -58,17 +56,23 @@ public class Mesh implements Renderable, Disposable {
|
||||
@Override
|
||||
public void render(Window window, Camera camera, ShaderManager shaderManager) {
|
||||
glBindVertexArray(vaoId);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, elementsCount, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.image;
|
||||
|
||||
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 lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
public class DefaultImageManager implements ImageManager {
|
||||
private final MeshManager meshManager;
|
||||
private final TextureManager textureManager;
|
||||
|
||||
@Override
|
||||
public Image createImage(String imageFileName) {
|
||||
var texture = textureManager.loadTexture(imageFileName);
|
||||
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 image = new Image(mesh, Material.textured(texture), initialWidth, initialHeight);
|
||||
image.setScale(gcd);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
log.info("There is nothing to clean up here");
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.image;
|
||||
|
||||
import com.bartlomiejpluta.base.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.core.world.object.RenderableObject;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class Image extends RenderableObject {
|
||||
private final int initialWidth;
|
||||
private final int initialHeight;
|
||||
|
||||
Image(Mesh mesh, Material texture, int initialWidth, int initialHeight) {
|
||||
super(mesh, texture);
|
||||
this.initialWidth = initialWidth;
|
||||
this.initialHeight = initialHeight;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.image;
|
||||
|
||||
import com.bartlomiejpluta.base.core.gc.Cleanable;
|
||||
|
||||
public interface ImageManager extends Cleanable {
|
||||
Image createImage(String imageFileName);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.animation;
|
||||
|
||||
import com.bartlomiejpluta.base.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.core.gl.object.mesh.Mesh;
|
||||
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.core.world.object.RenderableObject;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public abstract class AnimationableObject extends RenderableObject {
|
||||
|
||||
public AnimationableObject(Mesh mesh, Material material) {
|
||||
super(mesh, material);
|
||||
}
|
||||
|
||||
// Returns time in ms between frames
|
||||
public abstract int getAnimationSpeed();
|
||||
|
||||
public abstract boolean shouldAnimate();
|
||||
|
||||
public abstract Vector2f[] getSpriteAnimationFramesPositions();
|
||||
|
||||
@Override
|
||||
public void render(Window window, Camera camera, ShaderManager shaderManager) {
|
||||
animate();
|
||||
super.render(window, camera, shaderManager);
|
||||
}
|
||||
|
||||
private void animate() {
|
||||
if (shouldAnimate()) {
|
||||
var positions = getSpriteAnimationFramesPositions();
|
||||
var delay = getAnimationSpeed();
|
||||
var currentPosition = (int) (System.currentTimeMillis() % (positions.length * delay)) / delay;
|
||||
var current = positions[currentPosition];
|
||||
material.setSpritePosition(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@ package com.bartlomiejpluta.base.core.world.camera;
|
||||
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.object.PositionableObject;
|
||||
import com.bartlomiejpluta.base.core.world.object.Model;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
public class Camera extends PositionableObject {
|
||||
public class Camera extends Model {
|
||||
private final Matrix4f projectionMatrix = new Matrix4f();
|
||||
private final Matrix4f viewMatrix = new Matrix4f();
|
||||
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.map;
|
||||
|
||||
import com.bartlomiejpluta.base.core.gl.render.Renderable;
|
||||
import com.bartlomiejpluta.base.core.gl.shader.manager.ShaderManager;
|
||||
import com.bartlomiejpluta.base.core.image.Image;
|
||||
import com.bartlomiejpluta.base.core.logic.Updatable;
|
||||
import com.bartlomiejpluta.base.core.ui.Window;
|
||||
import com.bartlomiejpluta.base.core.world.camera.Camera;
|
||||
import com.bartlomiejpluta.base.core.world.movement.MovableObject;
|
||||
import com.bartlomiejpluta.base.core.world.movement.Movement;
|
||||
import com.bartlomiejpluta.base.core.world.tileset.model.Tile;
|
||||
import com.bartlomiejpluta.base.core.world.tileset.model.TileSet;
|
||||
import lombok.Getter;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class GameMap implements Renderable, Updatable {
|
||||
private final TileSet tileSet;
|
||||
private final List<Layer> layers = new ArrayList<>();
|
||||
|
||||
private final float scale;
|
||||
|
||||
@Getter
|
||||
private final int rows;
|
||||
|
||||
@Getter
|
||||
private final int columns;
|
||||
|
||||
@Getter
|
||||
private final Vector2f stepSize;
|
||||
|
||||
public GameMap(TileSet tileSet, int rows, int columns, float scale) {
|
||||
this.tileSet = tileSet;
|
||||
this.scale = scale;
|
||||
this.rows = rows;
|
||||
this.columns = columns;
|
||||
this.stepSize = new Vector2f(this.scale * this.tileSet.getTileWidth(), this.scale * this.tileSet.getTileHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Window window, Camera camera, ShaderManager shaderManager) {
|
||||
for (var layer : layers) {
|
||||
layer.render(window, camera, shaderManager);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
for (var layer : layers) {
|
||||
layer.update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2f getSize() {
|
||||
return new Vector2f(columns * stepSize.x, rows * stepSize.y);
|
||||
}
|
||||
|
||||
public GameMap createObjectLayer() {
|
||||
var passageMap = new PassageAbility[rows][columns];
|
||||
for (int i = 0; i < rows; ++i) {
|
||||
Arrays.fill(passageMap[i], 0, columns, PassageAbility.ALLOW);
|
||||
}
|
||||
|
||||
layers.add(new ObjectLayer(new ArrayList<>(), passageMap));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public GameMap createTileLayer() {
|
||||
layers.add(new TileLayer(new Tile[rows][columns], stepSize, scale));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public GameMap createImageLayer(Image image, ImageLayer.Mode imageDisplayMode) {
|
||||
layers.add(new ImageLayer(this, image, imageDisplayMode));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public GameMap addObject(int layerIndex, MovableObject object) {
|
||||
((ObjectLayer) layers.get(layerIndex)).addObject(object);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public GameMap removeObject(int layerIndex, MovableObject object) {
|
||||
((ObjectLayer) layers.get(layerIndex)).removeObject(object);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public GameMap setPassageAbility(int layerIndex, int row, int column, PassageAbility passageAbility) {
|
||||
((ObjectLayer) layers.get(layerIndex)).setPassageAbility(row, column, passageAbility);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GameMap setTile(int layerIndex, int row, int column, Tile tile) {
|
||||
((TileLayer) layers.get(layerIndex)).setTile(row, column, tile);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public GameMap setImage(int layerIndex, Image image) {
|
||||
((ImageLayer) layers.get(layerIndex)).setImage(image);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isMovementPossible(int layerIndex, Movement movement) {
|
||||
var target = movement.getTargetCoordinate();
|
||||
|
||||
// Is trying to go beyond the map
|
||||
if (target.x < 0 || target.y < 0 || target.x >= columns || target.y >= rows) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var source = movement.getSourceCoordinate();
|
||||
var direction = movement.getDirection();
|
||||
|
||||
return ((ObjectLayer) layers.get(layerIndex)).isMovementPossible(source, target, direction);
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.map;
|
||||
|
||||
import com.bartlomiejpluta.base.core.gl.shader.constant.UniformName;
|
||||
import com.bartlomiejpluta.base.core.gl.shader.manager.ShaderManager;
|
||||
import com.bartlomiejpluta.base.core.image.Image;
|
||||
import com.bartlomiejpluta.base.core.ui.Window;
|
||||
import com.bartlomiejpluta.base.core.world.camera.Camera;
|
||||
|
||||
public class ImageLayer implements Layer {
|
||||
|
||||
public enum Mode {
|
||||
NORMAL,
|
||||
FIT_SCREEN,
|
||||
FIT_MAP
|
||||
}
|
||||
|
||||
private final float mapWidth;
|
||||
private final float mapHeight;
|
||||
|
||||
private Image image;
|
||||
private float imageInitialWidth;
|
||||
private float imageInitialHeight;
|
||||
private final Mode mode;
|
||||
|
||||
public ImageLayer(GameMap map, Image image, Mode mode) {
|
||||
var stepSize = map.getStepSize();
|
||||
this.mapWidth = map.getColumns() * stepSize.x;
|
||||
this.mapHeight = map.getRows() * stepSize.y;
|
||||
this.mode = mode;
|
||||
setImage(image);
|
||||
}
|
||||
|
||||
public void setImage(Image image) {
|
||||
this.image = image;
|
||||
this.imageInitialWidth = image.getInitialWidth();
|
||||
this.imageInitialHeight = image.getInitialHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Window window, Camera camera, ShaderManager shaderManager) {
|
||||
if (image == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
public void update(float dt) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.map;
|
||||
|
||||
import com.bartlomiejpluta.base.core.gl.render.Renderable;
|
||||
import com.bartlomiejpluta.base.core.logic.Updatable;
|
||||
|
||||
public interface Layer extends Renderable, Updatable {
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.map;
|
||||
|
||||
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.core.world.movement.Direction;
|
||||
import com.bartlomiejpluta.base.core.world.movement.MovableObject;
|
||||
import org.joml.Vector2i;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ObjectLayer implements Layer {
|
||||
private final List<MovableObject> objects;
|
||||
|
||||
private final PassageAbility[][] passageMap;
|
||||
|
||||
public ObjectLayer(List<MovableObject> objects, PassageAbility[][] passageMap) {
|
||||
this.objects = objects;
|
||||
this.passageMap = passageMap;
|
||||
}
|
||||
|
||||
public void addObject(MovableObject object) {
|
||||
objects.add(object);
|
||||
}
|
||||
|
||||
public void removeObject(MovableObject object) {
|
||||
objects.remove(object);
|
||||
}
|
||||
|
||||
public void setPassageAbility(int row, int column, PassageAbility passageAbility) {
|
||||
passageMap[row][column] = passageAbility;
|
||||
}
|
||||
|
||||
public boolean isMovementPossible(Vector2i source, Vector2i target, Direction direction) {
|
||||
var isTargetReachable = switch (passageMap[target.y][target.x]) {
|
||||
case UP_ONLY -> direction != Direction.DOWN;
|
||||
case DOWN_ONLY -> direction != Direction.UP;
|
||||
case LEFT_ONLY -> direction != Direction.RIGHT;
|
||||
case RIGHT_ONLY -> direction != Direction.LEFT;
|
||||
case BLOCK -> false;
|
||||
case ALLOW -> true;
|
||||
};
|
||||
|
||||
var canMoveFromCurrentTile = switch (passageMap[source.y][source.x]) {
|
||||
case UP_ONLY -> direction == Direction.UP;
|
||||
case DOWN_ONLY -> direction == Direction.DOWN;
|
||||
case LEFT_ONLY -> direction == Direction.LEFT;
|
||||
case RIGHT_ONLY -> direction == Direction.RIGHT;
|
||||
default -> true;
|
||||
};
|
||||
|
||||
return isTargetReachable && canMoveFromCurrentTile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Window window, Camera camera, ShaderManager shaderManager) {
|
||||
for (var object : objects) {
|
||||
object.render(window, camera, shaderManager);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
for (var object : objects) {
|
||||
object.update(dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.map;
|
||||
|
||||
public enum PassageAbility {
|
||||
BLOCK,
|
||||
ALLOW,
|
||||
UP_ONLY,
|
||||
DOWN_ONLY,
|
||||
LEFT_ONLY,
|
||||
RIGHT_ONLY
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.map;
|
||||
|
||||
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.core.world.tileset.model.Tile;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
public class TileLayer implements Layer {
|
||||
private final Tile[][] layer;
|
||||
private final Vector2f stepSize;
|
||||
private final float scale;
|
||||
|
||||
public TileLayer(Tile[][] layer, Vector2f stepSize, float scale) {
|
||||
this.layer = layer;
|
||||
this.stepSize = stepSize;
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
public void setTile(int row, int column, Tile tile) {
|
||||
layer[row][column] = tile;
|
||||
recalculateTileGeometry(tile, row, column);
|
||||
}
|
||||
|
||||
private void recalculateTileGeometry(Tile tile, int row, int column) {
|
||||
tile.setScale(scale);
|
||||
tile.setPosition(column * stepSize.x, row * stepSize.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Window window, Camera camera, ShaderManager shaderManager) {
|
||||
for (var row : layer) {
|
||||
for (var tile : row) {
|
||||
if (tile != null) {
|
||||
tile.render(window, camera, shaderManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.movement;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector2i;
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public enum Direction {
|
||||
UP(new Vector2i(0, -1)),
|
||||
DOWN(new Vector2i(0, 1)),
|
||||
LEFT(new Vector2i(-1, 0)),
|
||||
RIGHT(new Vector2i(1, 0));
|
||||
|
||||
private final Vector2i vector;
|
||||
|
||||
public Vector2i asIntVector() {
|
||||
return new Vector2i(vector);
|
||||
}
|
||||
|
||||
public Vector2f asFloatVector() {
|
||||
return new Vector2f(vector);
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.movement;
|
||||
|
||||
import com.bartlomiejpluta.base.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.core.logic.Updatable;
|
||||
import com.bartlomiejpluta.base.core.world.animation.AnimationableObject;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector2i;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public abstract class MovableObject extends AnimationableObject implements Updatable {
|
||||
private final Vector2f coordinateStepSize;
|
||||
|
||||
private int moveTime = 0;
|
||||
private Vector2f movementVector;
|
||||
|
||||
@Getter
|
||||
private final Vector2i coordinates = new Vector2i(0, 0);
|
||||
|
||||
protected int framesToCrossOneTile = 1;
|
||||
|
||||
public boolean isMoving() {
|
||||
return movementVector != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
if(movementVector != null) {
|
||||
if(moveTime > 0) {
|
||||
--moveTime;
|
||||
movePosition(movementVector);
|
||||
} else {
|
||||
adjustCoordinates();
|
||||
setDefaultAnimationFrame();
|
||||
movementVector = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void setDefaultAnimationFrame();
|
||||
|
||||
private void adjustCoordinates() {
|
||||
var position = new Vector2f(getPosition());
|
||||
setCoordinates(new Vector2i((int) (position.x / coordinateStepSize.x), (int) (position.y / coordinateStepSize.y)));
|
||||
}
|
||||
|
||||
public Movement prepareMovement(Direction direction) {
|
||||
return new Movement(this, direction);
|
||||
}
|
||||
|
||||
protected boolean move(Direction direction) {
|
||||
if (this.movementVector != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var speed = new Vector2f(coordinateStepSize).div(framesToCrossOneTile);
|
||||
movementVector = direction.asFloatVector().mul(speed);
|
||||
moveTime = framesToCrossOneTile;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public MovableObject setCoordinates(int x, int y) {
|
||||
coordinates.x = x;
|
||||
coordinates.y = y;
|
||||
setPosition((x + 0.5f) * coordinateStepSize.x, (y + 0.5f) * coordinateStepSize.y);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MovableObject setCoordinates(Vector2i coordinates) {
|
||||
return setCoordinates(coordinates.x, coordinates.y);
|
||||
}
|
||||
|
||||
public MovableObject(Mesh mesh, Material material, Vector2f coordinateStepSize) {
|
||||
super(mesh, material);
|
||||
this.coordinateStepSize = coordinateStepSize;
|
||||
setCoordinates(0, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.movement;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.joml.Vector2i;
|
||||
|
||||
@Data
|
||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
public class Movement {
|
||||
private final MovableObject object;
|
||||
private final Direction direction;
|
||||
private boolean performed = false;
|
||||
|
||||
public boolean perform() {
|
||||
performed = object.move(direction);
|
||||
return performed;
|
||||
}
|
||||
|
||||
public Vector2i getSourceCoordinate() {
|
||||
return new Vector2i(object.getCoordinates());
|
||||
}
|
||||
|
||||
public Vector2i getTargetCoordinate() {
|
||||
return direction.asIntVector().add(object.getCoordinates());
|
||||
}
|
||||
|
||||
public Movement getAnother() {
|
||||
return object.prepareMovement(direction);
|
||||
}
|
||||
}
|
||||
//@Data
|
||||
//public class Movement {
|
||||
// private final MovableObject object;
|
||||
// private final Direction direction;
|
||||
// private final Vector2i source;
|
||||
// private final Vector2i target;
|
||||
//
|
||||
// Movement(MovableObject object, Direction direction) {
|
||||
// this.object = object;
|
||||
// this.direction = direction;
|
||||
// this.source = new Vector2i(object.getCoordinates());
|
||||
// this.target = direction.asIntVector().add(source);
|
||||
// }
|
||||
//
|
||||
// public boolean perform() {
|
||||
// return object.move(direction);
|
||||
// }
|
||||
//}
|
||||
@@ -9,7 +9,7 @@ import org.joml.Vector2f;
|
||||
import static java.lang.Math.toRadians;
|
||||
|
||||
@EqualsAndHashCode
|
||||
public abstract class PositionableObject {
|
||||
public abstract class Model {
|
||||
private final Matrix4f modelMatrix = new Matrix4f();
|
||||
|
||||
@Getter
|
||||
@@ -27,42 +27,42 @@ public abstract class PositionableObject {
|
||||
@Setter
|
||||
protected float scaleY = 1.0f;
|
||||
|
||||
public PositionableObject setPosition(float x, float y) {
|
||||
public Model setPosition(float x, float y) {
|
||||
position.x = x;
|
||||
position.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PositionableObject setPosition(Vector2f position) {
|
||||
public Model setPosition(Vector2f position) {
|
||||
this.position.x = position.x;
|
||||
this.position.y = position.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PositionableObject movePosition(float x, float y) {
|
||||
public Model movePosition(float x, float y) {
|
||||
position.x += x;
|
||||
position.y += y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PositionableObject movePosition(Vector2f position) {
|
||||
public Model movePosition(Vector2f position) {
|
||||
this.position.x += position.x;
|
||||
this.position.y += position.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PositionableObject moveRotation(float rotation) {
|
||||
public Model moveRotation(float rotation) {
|
||||
this.rotation += rotation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PositionableObject setScale(float scale) {
|
||||
public Model setScale(float scale) {
|
||||
this.scaleX = scale;
|
||||
this.scaleY = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PositionableObject setScale(float scaleX, float scaleY) {
|
||||
public Model setScale(float scaleX, float scaleY) {
|
||||
this.scaleX = scaleX;
|
||||
this.scaleY = scaleY;
|
||||
return this;
|
||||
@@ -14,7 +14,8 @@ import lombok.Setter;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public abstract class RenderableObject extends PositionableObject implements Renderable {
|
||||
public abstract class Sprite extends Model implements Renderable {
|
||||
|
||||
@NonNull
|
||||
protected final Mesh mesh;
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.tileset.manager;
|
||||
|
||||
import com.bartlomiejpluta.base.core.gl.object.texture.TextureManager;
|
||||
import com.bartlomiejpluta.base.core.util.mesh.MeshManager;
|
||||
import com.bartlomiejpluta.base.core.world.tileset.model.TileSet;
|
||||
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 DefaultTileSetManager implements TileSetManager {
|
||||
private final TextureManager textureManager;
|
||||
private final MeshManager meshManager;
|
||||
private final Map<String, TileSet> tileSets = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public TileSet createTileSet(String tileSetFileName, int rows, int columns) {
|
||||
var tileset = tileSets.get(tileSetFileName);
|
||||
|
||||
if(tileset == null) {
|
||||
log.info("Loading [{}] tileset to cache", tileSetFileName);
|
||||
var texture = textureManager.loadTexture(tileSetFileName);
|
||||
var tileWidth = texture.getWidth() / columns;
|
||||
var tileHeight = texture.getHeight() / rows;
|
||||
var mesh = meshManager.createQuad(tileWidth, tileHeight, 0, 0);
|
||||
tileset = new TileSet(mesh, texture, rows, columns, tileWidth, tileHeight);
|
||||
}
|
||||
|
||||
return tileset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
log.info("There is nothing to clean up here");
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.tileset.manager;
|
||||
|
||||
import com.bartlomiejpluta.base.core.gc.Cleanable;
|
||||
import com.bartlomiejpluta.base.core.world.tileset.model.TileSet;
|
||||
|
||||
public interface TileSetManager extends Cleanable {
|
||||
TileSet createTileSet(String tileSetFileName, int rows, int columns);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.tileset.model;
|
||||
|
||||
import com.bartlomiejpluta.base.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.core.world.object.RenderableObject;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class Tile extends RenderableObject {
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
Tile(Mesh mesh, Material material, int width, int height) {
|
||||
super(mesh, material);
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.bartlomiejpluta.base.core.world.tileset.model;
|
||||
|
||||
import com.bartlomiejpluta.base.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.core.gl.object.mesh.Mesh;
|
||||
import com.bartlomiejpluta.base.core.gl.object.texture.Texture;
|
||||
import lombok.Getter;
|
||||
|
||||
public class TileSet {
|
||||
private final Texture texture;
|
||||
private final int rows;
|
||||
private final int columns;
|
||||
private final float columnStep;
|
||||
private final float rowStep;
|
||||
private final Mesh mesh;
|
||||
|
||||
@Getter
|
||||
private final int tileWidth;
|
||||
|
||||
@Getter
|
||||
private final int tileHeight;
|
||||
|
||||
public TileSet(Mesh mesh, Texture texture, int rows, int columns, int tileWidth, int tileHeight) {
|
||||
this.texture = texture;
|
||||
this.rows = rows;
|
||||
this.columns = columns;
|
||||
this.columnStep = 1/(float) columns;
|
||||
this.rowStep = 1/(float) rows;
|
||||
this.tileWidth = tileWidth;
|
||||
this.tileHeight = tileHeight;
|
||||
this.mesh = mesh;
|
||||
}
|
||||
|
||||
public Tile getTile(int row, int column) {
|
||||
var material = Material.textured(texture);
|
||||
material.setSpritePosition(column * columnStep, row * rowStep);
|
||||
return new Tile(mesh, material, tileWidth, tileHeight);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user