Optimize autotile layers
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
package com.bartlomiejpluta.base.engine.world.autotile.manager;
|
||||
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture;
|
||||
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.autotile.asset.AutoTileSetAsset;
|
||||
import com.bartlomiejpluta.base.engine.world.autotile.model.AutoTileSet;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -19,14 +19,12 @@ import java.util.Map;
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
public class DefaultAutoTileSetManager implements AutoTileManager {
|
||||
private final TextureManager textureManager;
|
||||
private final MeshManager meshManager;
|
||||
private final Map<String, AutoTileSet> autoTiles = new HashMap<>();
|
||||
private final Map<String, AutoTileSet> tileSets = new HashMap<>();
|
||||
private final Map<String, AutoTileSetAsset> assets = new HashMap<>();
|
||||
private final ProjectConfiguration configuration;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
// TODO: this.mesh = meshManager.createQuad(1, 1, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,9 +40,9 @@ public class DefaultAutoTileSetManager implements AutoTileManager {
|
||||
|
||||
@Override
|
||||
public AutoTileSet loadObject(String uid) {
|
||||
var autoTile = autoTiles.get(uid);
|
||||
var tileSet = tileSets.get(uid);
|
||||
|
||||
if (autoTile == null) {
|
||||
if (tileSet == null) {
|
||||
var asset = assets.get(uid);
|
||||
|
||||
if (asset == null) {
|
||||
@@ -53,11 +51,12 @@ public class DefaultAutoTileSetManager implements AutoTileManager {
|
||||
|
||||
var source = configuration.projectFile("autotiles", asset.getSource());
|
||||
var texture = textureManager.loadTexture(source, asset.getRows() * asset.getLayout().getRows() * 2, asset.getColumns() * asset.getLayout().getColumns() * 2);
|
||||
autoTile = new AutoTileSet(texture, asset.getRows(), asset.getColumns(), asset.getLayout());
|
||||
tileSet = new AutoTileSet(texture, asset.getLayout());
|
||||
|
||||
log.info("Loading auto tile set from assets to cache under the key: [{}]", uid);
|
||||
autoTiles.put(uid, autoTile);
|
||||
tileSets.put(uid, tileSet);
|
||||
}
|
||||
|
||||
return autoTile;
|
||||
return tileSet;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
package com.bartlomiejpluta.base.engine.world.autotile.model;
|
||||
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
|
||||
import com.bartlomiejpluta.base.engine.world.object.Sprite;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector2fc;
|
||||
import org.joml.Vector2ic;
|
||||
|
||||
@Getter
|
||||
public class AutoSubTile extends Sprite {
|
||||
private final Vector2fc tileSpriteSize;
|
||||
private final Vector2f tileScale = new Vector2f(1, 1);
|
||||
|
||||
public AutoSubTile(AutoTileSet autoTileSet) {
|
||||
super(Material.textured(autoTileSet.getTexture()));
|
||||
|
||||
tileSpriteSize = getMaterial().getTexture().getSpriteSize();
|
||||
|
||||
super.setScale(tileSpriteSize.x() * tileScale.x, tileSpriteSize.y() * tileScale.y);
|
||||
}
|
||||
|
||||
public void recalculate(@NonNull Vector2ic spritePosition) {
|
||||
setFrame(spritePosition.x(), spritePosition.y());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScale(float scale) {
|
||||
this.tileScale.x = scale;
|
||||
this.tileScale.y = scale;
|
||||
super.setScale(tileSpriteSize.x() * scale, tileSpriteSize.y() * scale);
|
||||
}
|
||||
|
||||
public void setScale(float scaleX, float scaleY) {
|
||||
this.tileScale.x = scaleX;
|
||||
this.tileScale.y = scaleY;
|
||||
super.setScale(tileSpriteSize.x() * scaleX, tileSpriteSize.y() * scaleY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getScaleX() {
|
||||
return tileScale.x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScaleX(float scaleX) {
|
||||
this.tileScale.x = scaleX;
|
||||
super.setScaleX(tileSpriteSize.x() * scaleX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getScaleY() {
|
||||
return tileScale.y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScaleY(float scaleY) {
|
||||
this.tileScale.y = scaleY;
|
||||
super.setScaleY(tileSpriteSize.x() * scaleY);
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package com.bartlomiejpluta.base.engine.world.autotile.model;
|
||||
|
||||
import com.bartlomiejpluta.base.api.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.internal.render.Renderable;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
public class AutoTile implements Renderable {
|
||||
private final AutoTileSet autoTileSet;
|
||||
private final AutoSubTile topLeftSubTile;
|
||||
private final AutoSubTile topRightSubTile;
|
||||
private final AutoSubTile bottomLeftSubTile;
|
||||
private final AutoSubTile bottomRightSubTile;
|
||||
|
||||
@Getter
|
||||
private int setId;
|
||||
|
||||
public AutoTile(@NonNull AutoTileSet autoTileSet, int setId) {
|
||||
this.topLeftSubTile = new AutoSubTile(autoTileSet);
|
||||
this.topRightSubTile = new AutoSubTile(autoTileSet);
|
||||
this.bottomLeftSubTile = new AutoSubTile(autoTileSet);
|
||||
this.bottomRightSubTile = new AutoSubTile(autoTileSet);
|
||||
this.autoTileSet = autoTileSet;
|
||||
this.setId = setId;
|
||||
}
|
||||
|
||||
public void setCoordinates(int column, int row) {
|
||||
var x = column * autoTileSet.getTileSize().x() * 2;
|
||||
var y = row * autoTileSet.getTileSize().y() * 2;
|
||||
|
||||
topLeftSubTile.setPosition(x, y);
|
||||
topRightSubTile.setPosition(x + autoTileSet.getTileSize().x(), y);
|
||||
bottomLeftSubTile.setPosition(x, y + autoTileSet.getTileSize().y());
|
||||
bottomRightSubTile.setPosition(x + autoTileSet.getTileSize().x(), y + autoTileSet.getTileSize().y());
|
||||
}
|
||||
|
||||
public void regularTile(Integer setId, int topLeft, int topRight, int bottomLeft, int bottomRight) {
|
||||
if (setId == null) {
|
||||
setId = this.setId;
|
||||
}
|
||||
|
||||
topLeftSubTile.recalculate(autoTileSet.getTopLeftSubTiles()[setId][topLeft]);
|
||||
topRightSubTile.recalculate(autoTileSet.getTopRightSubTiles()[setId][topRight]);
|
||||
bottomLeftSubTile.recalculate(autoTileSet.getBottomLeftSubTiles()[setId][bottomLeft]);
|
||||
bottomRightSubTile.recalculate(autoTileSet.getBottomRightSubTiles()[setId][bottomRight]);
|
||||
}
|
||||
|
||||
public void islandTile(Integer setId) {
|
||||
if (setId == null) {
|
||||
setId = this.setId;
|
||||
}
|
||||
|
||||
topLeftSubTile.recalculate(autoTileSet.getIslandSubTiles()[setId][0]);
|
||||
topRightSubTile.recalculate(autoTileSet.getIslandSubTiles()[setId][1]);
|
||||
bottomLeftSubTile.recalculate(autoTileSet.getIslandSubTiles()[setId][2]);
|
||||
bottomRightSubTile.recalculate(autoTileSet.getIslandSubTiles()[setId][3]);
|
||||
}
|
||||
|
||||
public void shiftTileSet() {
|
||||
this.setId = (setId + 1) % autoTileSet.getSetsCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Screen screen, Camera camera, ShaderManager shaderManager) {
|
||||
topLeftSubTile.render(screen, camera, shaderManager);
|
||||
topRightSubTile.render(screen, camera, shaderManager);
|
||||
bottomLeftSubTile.render(screen, camera, shaderManager);
|
||||
bottomRightSubTile.render(screen, camera, shaderManager);
|
||||
}
|
||||
}
|
||||
@@ -4,201 +4,22 @@ import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import org.joml.Vector2fc;
|
||||
import org.joml.Vector2i;
|
||||
import org.joml.Vector2ic;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
// Algorithm source: https://love2d.org/forums/viewtopic.php?t=7826
|
||||
@Getter
|
||||
public class AutoTileSet {
|
||||
private static final Vector2ic ISLAND_TILE_2x3 = new Vector2i(0, 0);
|
||||
private static final Vector2ic CROSS_TILE_2x3 = new Vector2i(1, 0);
|
||||
private static final Vector2ic TOP_LEFT_TILE_2x3 = new Vector2i(0, 1);
|
||||
private static final Vector2ic TOP_RIGHT_TILE_2x3 = new Vector2i(1, 1);
|
||||
private static final Vector2ic BOTTOM_LEFT_TILE_2x3 = new Vector2i(0, 2);
|
||||
private static final Vector2ic BOTTOM_RIGHT_TILE_2x3 = new Vector2i(1, 2);
|
||||
|
||||
private static final Vector2ic TOP_LEFT_TILE_2x2 = new Vector2i(0, 0);
|
||||
private static final Vector2ic TOP_RIGHT_TILE_2x2 = new Vector2i(1, 0);
|
||||
private static final Vector2ic BOTTOM_LEFT_TILE_2x2 = new Vector2i(0, 1);
|
||||
private static final Vector2ic BOTTOM_RIGHT_TILE_2x2 = new Vector2i(1, 1);
|
||||
|
||||
private final int textureSubTilesRows;
|
||||
private final int textureSubTilesColumns;
|
||||
|
||||
|
||||
@Getter
|
||||
private Vector2ic[][] islandSubTiles;
|
||||
|
||||
@Getter
|
||||
private Vector2ic[][] topLeftSubTiles;
|
||||
|
||||
@Getter
|
||||
private Vector2ic[][] topRightSubTiles;
|
||||
|
||||
@Getter
|
||||
private Vector2ic[][] bottomLeftSubTiles;
|
||||
|
||||
@Getter
|
||||
private Vector2ic[][] bottomRightSubTiles;
|
||||
|
||||
@Getter
|
||||
private final Texture texture;
|
||||
|
||||
@Getter
|
||||
private final Vector2fc tileSize;
|
||||
|
||||
@Getter
|
||||
private final AutoTileLayout layout;
|
||||
private final int rows;
|
||||
private final int columns;
|
||||
|
||||
@Getter
|
||||
private final int setsColumns;
|
||||
private final int setsRows;
|
||||
private final int setsCount;
|
||||
|
||||
public AutoTileSet(@NonNull Texture texture, int rows, int columns, @NonNull AutoTileLayout layout) {
|
||||
|
||||
public AutoTileSet(@NonNull Texture texture, @NonNull AutoTileLayout layout) {
|
||||
this.texture = texture;
|
||||
this.rows = rows;
|
||||
this.columns = columns;
|
||||
this.tileSize = texture.getSpriteSize();
|
||||
this.layout = layout;
|
||||
this.setsCount = rows * columns;
|
||||
this.textureSubTilesRows = layout.getRows() * 2;
|
||||
this.textureSubTilesColumns = layout.getColumns() * 2;
|
||||
|
||||
switch (layout) {
|
||||
case LAYOUT_2X2 -> init2x2();
|
||||
case LAYOUT_2X3 -> init2x3();
|
||||
}
|
||||
}
|
||||
|
||||
private void init2x3() {
|
||||
var islandSubTiles = new LinkedList<Vector2ic[]>();
|
||||
var topLeftSubTiles = new LinkedList<Vector2ic[]>();
|
||||
var topRightSubTiles = new LinkedList<Vector2ic[]>();
|
||||
var bottomLeftSubTiles = new LinkedList<Vector2ic[]>();
|
||||
var bottomRightSubTiles = new LinkedList<Vector2ic[]>();
|
||||
|
||||
for (int setId = 0; setId < setsCount; ++setId) {
|
||||
var crossSubTiles = cutSubTiles(setId, CROSS_TILE_2x3);
|
||||
var topLeftTileSubTiles = cutSubTiles(setId, TOP_LEFT_TILE_2x3);
|
||||
var topRightTileSubTiles = cutSubTiles(setId, TOP_RIGHT_TILE_2x3);
|
||||
var bottomLeftTileSubTiles = cutSubTiles(setId, BOTTOM_LEFT_TILE_2x3);
|
||||
var bottomRightTileSubTiles = cutSubTiles(setId, BOTTOM_RIGHT_TILE_2x3);
|
||||
|
||||
/*
|
||||
* Indexes:
|
||||
* 0 - No connected tiles
|
||||
* 1 - Left tile is connected
|
||||
* 2 - Right tile is connected
|
||||
* 3 - Left and Right tiles are connected
|
||||
* 4 - Left, Right, and Center tiles are connected.
|
||||
*/
|
||||
var tl3 = crossSubTiles[0];
|
||||
var tr3 = crossSubTiles[1];
|
||||
var bl3 = crossSubTiles[2];
|
||||
var br3 = crossSubTiles[3];
|
||||
|
||||
var tl0 = topLeftTileSubTiles[0];
|
||||
var tr2 = topLeftTileSubTiles[1];
|
||||
var bl1 = topLeftTileSubTiles[2];
|
||||
var br4 = topLeftTileSubTiles[3];
|
||||
|
||||
var tl1 = topRightTileSubTiles[0];
|
||||
var tr0 = topRightTileSubTiles[1];
|
||||
var bl4 = topRightTileSubTiles[2];
|
||||
var br2 = topRightTileSubTiles[3];
|
||||
|
||||
var tl2 = bottomLeftTileSubTiles[0];
|
||||
var tr4 = bottomLeftTileSubTiles[1];
|
||||
var bl0 = bottomLeftTileSubTiles[2];
|
||||
var br1 = bottomLeftTileSubTiles[3];
|
||||
|
||||
var tl4 = bottomRightTileSubTiles[0];
|
||||
var tr1 = bottomRightTileSubTiles[1];
|
||||
var bl2 = bottomRightTileSubTiles[2];
|
||||
var br0 = bottomRightTileSubTiles[3];
|
||||
|
||||
islandSubTiles.add(cutSubTiles(setId, ISLAND_TILE_2x3));
|
||||
topLeftSubTiles.add(new Vector2ic[]{tl0, tl1, tl2, tl3, tl4});
|
||||
topRightSubTiles.add(new Vector2ic[]{tr0, tr1, tr2, tr3, tr4});
|
||||
bottomLeftSubTiles.add(new Vector2ic[]{bl0, bl1, bl2, bl3, bl4});
|
||||
bottomRightSubTiles.add(new Vector2ic[]{br0, br1, br2, br3, br4});
|
||||
}
|
||||
|
||||
this.islandSubTiles = islandSubTiles.toArray(new Vector2ic[islandSubTiles.size()][]);
|
||||
this.topLeftSubTiles = topLeftSubTiles.toArray(new Vector2ic[topLeftSubTiles.size()][]);
|
||||
this.topRightSubTiles = topRightSubTiles.toArray(new Vector2ic[topRightSubTiles.size()][]);
|
||||
this.bottomLeftSubTiles = bottomLeftSubTiles.toArray(new Vector2ic[bottomLeftSubTiles.size()][]);
|
||||
this.bottomRightSubTiles = bottomRightSubTiles.toArray(new Vector2ic[bottomRightSubTiles.size()][]);
|
||||
}
|
||||
|
||||
private void init2x2() {
|
||||
var topLeftSubTiles = new LinkedList<Vector2ic[]>();
|
||||
var topRightSubTiles = new LinkedList<Vector2ic[]>();
|
||||
var bottomLeftSubTiles = new LinkedList<Vector2ic[]>();
|
||||
var bottomRightSubTiles = new LinkedList<Vector2ic[]>();
|
||||
|
||||
for (int setId = 0; setId < setsCount; ++setId) {
|
||||
var topLeftTileSubTiles = cutSubTiles(setId, TOP_LEFT_TILE_2x2);
|
||||
var topRightTileSubTiles = cutSubTiles(setId, TOP_RIGHT_TILE_2x2);
|
||||
var bottomLeftTileSubTiles = cutSubTiles(setId, BOTTOM_LEFT_TILE_2x2);
|
||||
var bottomRightTileSubTiles = cutSubTiles(setId, BOTTOM_RIGHT_TILE_2x2);
|
||||
|
||||
/*
|
||||
* Indexes:
|
||||
* 0 - No connected tiles
|
||||
* 1 - Left tile is connected
|
||||
* 2 - Right tile is connected
|
||||
* 3 - Left, Right, and Center tiles are connected.
|
||||
*/
|
||||
|
||||
var tl0 = topLeftTileSubTiles[0];
|
||||
var tr2 = topLeftTileSubTiles[1];
|
||||
var bl1 = topLeftTileSubTiles[2];
|
||||
var br3 = topLeftTileSubTiles[3];
|
||||
|
||||
var tl1 = topRightTileSubTiles[0];
|
||||
var tr0 = topRightTileSubTiles[1];
|
||||
var bl3 = topRightTileSubTiles[2];
|
||||
var br2 = topRightTileSubTiles[3];
|
||||
|
||||
var tl2 = bottomLeftTileSubTiles[0];
|
||||
var tr3 = bottomLeftTileSubTiles[1];
|
||||
var bl0 = bottomLeftTileSubTiles[2];
|
||||
var br1 = bottomLeftTileSubTiles[3];
|
||||
|
||||
var tl3 = bottomRightTileSubTiles[0];
|
||||
var tr1 = bottomRightTileSubTiles[1];
|
||||
var bl2 = bottomRightTileSubTiles[2];
|
||||
var br0 = bottomRightTileSubTiles[3];
|
||||
|
||||
topLeftSubTiles.add(new Vector2ic[]{tl0, tl1, tl2, tl3});
|
||||
topRightSubTiles.add(new Vector2ic[]{tr0, tr1, tr2, tr3});
|
||||
bottomLeftSubTiles.add(new Vector2ic[]{bl0, bl1, bl2, bl3});
|
||||
bottomRightSubTiles.add(new Vector2ic[]{br0, br1, br2, br3});
|
||||
}
|
||||
|
||||
this.topLeftSubTiles = topLeftSubTiles.toArray(new Vector2ic[topLeftSubTiles.size()][]);
|
||||
this.topRightSubTiles = topRightSubTiles.toArray(new Vector2ic[topRightSubTiles.size()][]);
|
||||
this.bottomLeftSubTiles = bottomLeftSubTiles.toArray(new Vector2ic[bottomLeftSubTiles.size()][]);
|
||||
this.bottomRightSubTiles = bottomRightSubTiles.toArray(new Vector2ic[bottomRightSubTiles.size()][]);
|
||||
}
|
||||
|
||||
private Vector2ic[] cutSubTiles(int setId, Vector2ic tile) {
|
||||
var topLeft = getTile(setId, tile.y() * 2, tile.x() * 2);
|
||||
var topRight = getTile(setId, tile.y() * 2, tile.x() * 2 + 1);
|
||||
var bottomLeft = getTile(setId, tile.y() * 2 + 1, tile.x() * 2);
|
||||
var bottomRight = getTile(setId, tile.y() * 2 + 1, tile.x() * 2 + 1);
|
||||
|
||||
return new Vector2ic[]{topLeft, topRight, bottomLeft, bottomRight};
|
||||
}
|
||||
|
||||
private Vector2ic getTile(int setId, int row, int column) {
|
||||
return new Vector2i(((setId / columns) * textureSubTilesRows) + row, ((setId % columns) * textureSubTilesColumns) + column);
|
||||
}
|
||||
|
||||
public AutoTile createTile(int setId) {
|
||||
return new AutoTile(this, setId);
|
||||
this.setsColumns = texture.getColumns() / layout.getColumns() / 2;
|
||||
this.setsRows = texture.getRows() / layout.getRows() / 2;
|
||||
this.setsCount = setsRows * setsColumns;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.bartlomiejpluta.base.engine.world.map.layer.autotile;
|
||||
|
||||
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture;
|
||||
import com.bartlomiejpluta.base.engine.world.autotile.model.AutoTileSet;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
/*
|
||||
* 0 1 2 3
|
||||
*
|
||||
* +-------------------+---------+---------+
|
||||
* | . | . |
|
||||
* 0 | TL0 . TR2 | TL1 . TR0 |
|
||||
* | . | . |
|
||||
* + . . . . + . . . . + . . . . + . . . . +
|
||||
* | . | . |
|
||||
* 1 | BL1 . BR3 | BL3 . BR2 |
|
||||
* | . | . |
|
||||
* +---------+---------+---------+---------+
|
||||
* | . | . |
|
||||
* 2 | TL2 . TR3 | TL3 . TR1 |
|
||||
* | . | . |
|
||||
* + . . . . + . . . . + . . . . + . . . . +
|
||||
* | . | . |
|
||||
* 3 | BL0 . BR1 | BL2 . BR0 |
|
||||
* | . | . |
|
||||
* +---------+---------+---------+---------+
|
||||
*
|
||||
* Legend:
|
||||
* TL - top left
|
||||
* TR - top right
|
||||
* BL - bottom left
|
||||
* BR - bottom right
|
||||
* 0 - Not connected
|
||||
* 1 - Left tile connected
|
||||
* 2 - Right tile connected
|
||||
* 3 - Left and right tiles connected
|
||||
* 4 - Left, right and center tiles connected
|
||||
*/
|
||||
public class AutoTileLayer2x2 extends BaseAutoTileLayer {
|
||||
private static final int ROWS = 2;
|
||||
private static final int COLUMNS = 2;
|
||||
private static final int SUB_ROWS = ROWS * 2;
|
||||
private static final int SUB_COLUMNS = COLUMNS * 2;
|
||||
|
||||
// 0 1 2 3
|
||||
private static final int[][] TOP_LEFT = {{0, 0}, {2, 0}, {0, 2}, {2, 2}};
|
||||
private static final int[][] TOP_RIGHT = {{3, 0}, {3, 2}, {1, 0}, {1, 2}};
|
||||
private static final int[][] BOTTOM_LEFT = {{0, 3}, {0, 1}, {2, 3}, {2, 1}};
|
||||
private static final int[][] BOTTOM_RIGHT = {{3, 3}, {1, 3}, {3, 1}, {1, 3}};
|
||||
|
||||
private final int tileSetColumns;
|
||||
|
||||
|
||||
public AutoTileLayer2x2(@NonNull GameMap map, @NonNull AutoTileSet tileSet, int rows, int columns, boolean connect, boolean animated, double animationDuration) {
|
||||
super(map, tileSet, rows, columns, connect, animated, animationDuration);
|
||||
|
||||
this.tileSetColumns = tileSet.getSetsColumns();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void recalculateTile(int row, int column) {
|
||||
if (layer[row][column] == EMPTY_TILE) {
|
||||
return;
|
||||
}
|
||||
|
||||
var topLeft = 0;
|
||||
var topRight = 0;
|
||||
var bottomLeft = 0;
|
||||
var bottomRight = 0;
|
||||
|
||||
var tile = layer[row][column];
|
||||
|
||||
// Top
|
||||
if (row > 0 && (layer[row - 1][column] != EMPTY_TILE && (connect || layer[row - 1][column] == tile))) {
|
||||
topLeft += 2;
|
||||
topRight += 1;
|
||||
}
|
||||
|
||||
// Bottom
|
||||
if (row < map.getRows() - 1 && (layer[row + 1][column] != EMPTY_TILE && (connect || layer[row + 1][column] == tile))) {
|
||||
bottomLeft += 1;
|
||||
bottomRight += 2;
|
||||
}
|
||||
|
||||
// Left
|
||||
if (column > 0 && (layer[row][column - 1] != EMPTY_TILE && (connect || layer[row][column - 1] == tile))) {
|
||||
topLeft += 1;
|
||||
bottomLeft += 2;
|
||||
}
|
||||
|
||||
// Right
|
||||
if (column < map.getColumns() - 1 && (layer[row][column + 1] != EMPTY_TILE && (connect || layer[row][column + 1] == tile))) {
|
||||
topRight += 2;
|
||||
bottomRight += 1;
|
||||
}
|
||||
|
||||
setSubTiles(
|
||||
tile % tileSetColumns * SUB_COLUMNS,
|
||||
tile / tileSetColumns * SUB_ROWS,
|
||||
row,
|
||||
column,
|
||||
TOP_LEFT[topLeft],
|
||||
TOP_RIGHT[topRight],
|
||||
BOTTOM_LEFT[bottomLeft],
|
||||
BOTTOM_RIGHT[bottomRight]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.bartlomiejpluta.base.engine.world.map.layer.autotile;
|
||||
|
||||
import com.bartlomiejpluta.base.api.map.layer.autotile.AutoTileLayer;
|
||||
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture;
|
||||
import com.bartlomiejpluta.base.engine.world.autotile.model.AutoTileSet;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
/*
|
||||
* 0 1 2 3
|
||||
*
|
||||
* +-------------------+---------+---------+
|
||||
* | | . |
|
||||
* 0 | | TL3 . TR3 |
|
||||
* | | . |
|
||||
* | ISLAND + . . . . + . . . . +
|
||||
* | | . |
|
||||
* 1 | | BL3 . BR3 |
|
||||
* | | . |
|
||||
* +-------------------+---------+---------+
|
||||
* | . | . |
|
||||
* 2 | TL0 . TR2 | TL1 . TR0 |
|
||||
* | . | . |
|
||||
* + . . . . + . . . . + . . . . + . . . . +
|
||||
* | . | . |
|
||||
* 3 | BL1 . BR4 | BL4 . BR2 |
|
||||
* | . | . |
|
||||
* +---------+---------+---------+---------+
|
||||
* | . | . |
|
||||
* 4 | TL2 . TR4 | TL4 . TR1 |
|
||||
* | . | . |
|
||||
* + . . . . + . . . . + . . . . + . . . . +
|
||||
* | . | . |
|
||||
* 5 | BL0 . BR1 | BL2 . BR0 |
|
||||
* | . | . |
|
||||
* +---------+---------+---------+---------+
|
||||
*
|
||||
* Legend:
|
||||
* TL - top left
|
||||
* TR - top right
|
||||
* BL - bottom left
|
||||
* BR - bottom right
|
||||
* 0 - Not connected
|
||||
* 1 - Left tile connected
|
||||
* 2 - Right tile connected
|
||||
* 3 - Left and right tiles connected
|
||||
* 4 - Left, right and center tiles connected
|
||||
*/
|
||||
public class AutoTileLayer3x2 extends BaseAutoTileLayer implements AutoTileLayer {
|
||||
private static final int ROWS = 3;
|
||||
private static final int COLUMNS = 2;
|
||||
private static final int SUB_ROWS = ROWS * 2;
|
||||
private static final int SUB_COLUMNS = COLUMNS * 2;
|
||||
|
||||
// 0 1 2 3 4
|
||||
private static final int[][] TOP_LEFT = {{0, 2}, {2, 2}, {0, 4}, {2, 0}, {2, 4}};
|
||||
private static final int[][] TOP_RIGHT = {{3, 2}, {3, 4}, {1, 2}, {3, 0}, {1, 4}};
|
||||
private static final int[][] BOTTOM_LEFT = {{0, 5}, {0, 3}, {2, 5}, {2, 1}, {2, 3}};
|
||||
private static final int[][] BOTTOM_RIGHT = {{3, 5}, {1, 5}, {3, 3}, {3, 1}, {1, 3}};
|
||||
|
||||
private final int tileSetColumns;
|
||||
|
||||
public AutoTileLayer3x2(@NonNull GameMap map, @NonNull AutoTileSet tileSet, int rows, int columns, boolean connect, boolean animated, double animationDuration) {
|
||||
super(map, tileSet, rows, columns, connect, animated, animationDuration);
|
||||
|
||||
this.tileSetColumns = tileSet.getSetsColumns();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void recalculateTile(int row, int column) {
|
||||
if (layer[row][column] == EMPTY_TILE) {
|
||||
return;
|
||||
}
|
||||
|
||||
byte topLeft = 0;
|
||||
byte topRight = 0;
|
||||
byte bottomLeft = 0;
|
||||
byte bottomRight = 0;
|
||||
|
||||
var tile = layer[row][column];
|
||||
|
||||
// Top
|
||||
if (row > 0 && (layer[row - 1][column] != EMPTY_TILE && (connect || layer[row - 1][column] == tile))) {
|
||||
topLeft += 2;
|
||||
topRight += 1;
|
||||
}
|
||||
|
||||
// Bottom
|
||||
if (row < map.getRows() - 1 && (layer[row + 1][column] != EMPTY_TILE && (connect || layer[row + 1][column] == tile))) {
|
||||
bottomLeft += 1;
|
||||
bottomRight += 2;
|
||||
}
|
||||
|
||||
// Left
|
||||
if (column > 0 && (layer[row][column - 1] != EMPTY_TILE && (connect || layer[row][column - 1] == tile))) {
|
||||
topLeft += 1;
|
||||
bottomLeft += 2;
|
||||
}
|
||||
|
||||
// Right
|
||||
if (column < map.getColumns() - 1 && (layer[row][column + 1] != EMPTY_TILE && (connect || layer[row][column + 1] == tile))) {
|
||||
topRight += 2;
|
||||
bottomRight += 1;
|
||||
}
|
||||
|
||||
// Top left
|
||||
if (row > 0 && column > 0 && (layer[row - 1][column - 1] != EMPTY_TILE && (connect || layer[row - 1][column - 1] == tile)) && topLeft == 3) {
|
||||
topLeft = 4;
|
||||
}
|
||||
|
||||
// Top right
|
||||
if (row > 0 && column < map.getColumns() - 1 && (layer[row - 1][column + 1] != EMPTY_TILE && (connect || layer[row - 1][column + 1] == tile)) && topRight == 3) {
|
||||
topRight = 4;
|
||||
}
|
||||
|
||||
// Bottom left
|
||||
if (row < map.getRows() - 1 && column > 0 && (layer[row + 1][column - 1] != EMPTY_TILE && (connect || layer[row + 1][column - 1] == tile)) && bottomLeft == 3) {
|
||||
bottomLeft = 4;
|
||||
}
|
||||
|
||||
// Bottom right
|
||||
if (row < map.getRows() - 1 && column < map.getColumns() - 1 && (layer[row + 1][column + 1] != EMPTY_TILE && (connect || layer[row + 1][column + 1] == tile)) && bottomRight == 3) {
|
||||
bottomRight = 4;
|
||||
}
|
||||
|
||||
setSubTiles(
|
||||
tile % tileSetColumns * SUB_COLUMNS,
|
||||
tile / tileSetColumns * SUB_ROWS,
|
||||
row,
|
||||
column,
|
||||
TOP_LEFT[topLeft],
|
||||
TOP_RIGHT[topRight],
|
||||
BOTTOM_LEFT[bottomLeft],
|
||||
BOTTOM_RIGHT[bottomRight]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.bartlomiejpluta.base.engine.world.map.layer.autotile;
|
||||
|
||||
import com.bartlomiejpluta.base.api.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture;
|
||||
import com.bartlomiejpluta.base.engine.world.autotile.model.AutoTileSet;
|
||||
import com.bartlomiejpluta.base.engine.world.map.layer.base.BaseLayer;
|
||||
import com.bartlomiejpluta.base.engine.world.map.layer.tile.ChunkManager;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.NonNull;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
import static java.util.Arrays.fill;
|
||||
import static java.util.Arrays.stream;
|
||||
|
||||
// Algorithm source: https://love2d.org/forums/viewtopic.php?t=7826
|
||||
public abstract class BaseAutoTileLayer extends BaseLayer {
|
||||
protected static final int EMPTY_TILE = -1;
|
||||
|
||||
protected final int[][] layer;
|
||||
protected final ChunkManager chunkManager;
|
||||
protected final boolean connect;
|
||||
protected final boolean animated;
|
||||
protected final double animationDuration;
|
||||
private final int setsCount;
|
||||
|
||||
private float accumulator = 0f;
|
||||
private boolean dirty = true;
|
||||
|
||||
public BaseAutoTileLayer(@NonNull GameMap map, @NonNull AutoTileSet tileSet, int rows, int columns, boolean connect, boolean animated, double animationDuration) {
|
||||
super(map);
|
||||
this.layer = new int[rows][columns];
|
||||
this.connect = connect;
|
||||
this.animated = animated;
|
||||
this.animationDuration = animationDuration;
|
||||
this.setsCount = tileSet.getSetsCount();
|
||||
|
||||
this.chunkManager = new ChunkManager(
|
||||
tileSet.getTexture(),
|
||||
rows * 4,
|
||||
columns * 4,
|
||||
new Vector2f(tileSet.getTexture().getSpriteSize()).div(2)
|
||||
);
|
||||
|
||||
stream(layer).forEach(tiles -> fill(tiles, EMPTY_TILE));
|
||||
}
|
||||
|
||||
public void setTile(int row, int column, int setId) {
|
||||
layer[row][column] = setId;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public void clearTile(int row, int column) {
|
||||
layer[row][column] = EMPTY_TILE;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public void recalculate() {
|
||||
for (int row = 0; row < map.getRows(); ++row) {
|
||||
for (int column = 0; column < map.getColumns(); ++column) {
|
||||
recalculateTile(row, column);
|
||||
}
|
||||
}
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
protected abstract void recalculateTile(int row, int column);
|
||||
|
||||
protected void setSubTiles(int tileSetColumnOffset, int tileSetRowOffset, int row, int column, int[] topLeft, int[] topRight, int[] bottomLeft, int[] bottomRight) {
|
||||
var y = row * 4;
|
||||
var x = column * 4;
|
||||
|
||||
chunkManager.upsertTile(y, x, topLeft[0] + tileSetColumnOffset, topLeft[1] + tileSetRowOffset);
|
||||
chunkManager.upsertTile(y, x + 2, topRight[0] + tileSetColumnOffset, topRight[1] + tileSetRowOffset);
|
||||
chunkManager.upsertTile(y + 2, x, bottomLeft[0] + tileSetColumnOffset, bottomLeft[1] + tileSetRowOffset);
|
||||
chunkManager.upsertTile(y + 2, x + 2, bottomRight[0] + tileSetColumnOffset, bottomRight[1] + tileSetRowOffset);
|
||||
}
|
||||
|
||||
private void nextAnimationFrame() {
|
||||
for (int row = 0; row < map.getRows(); ++row) {
|
||||
for (int column = 0; column < map.getColumns(); ++column) {
|
||||
var tile = layer[row][column];
|
||||
if (tile != EMPTY_TILE) {
|
||||
layer[row][column] = (tile + 1) % setsCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
super.update(dt);
|
||||
|
||||
if (animated) {
|
||||
accumulator += dt;
|
||||
|
||||
if (accumulator > animationDuration) {
|
||||
nextAnimationFrame();
|
||||
accumulator = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Screen screen, Camera camera, ShaderManager shaderManager) {
|
||||
if (dirty) {
|
||||
recalculate();
|
||||
}
|
||||
|
||||
chunkManager.render(screen, camera, shaderManager);
|
||||
// super.render(screen, camera, shaderManager);
|
||||
}
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
package com.bartlomiejpluta.base.engine.world.map.layer.autotile;
|
||||
|
||||
import com.bartlomiejpluta.base.api.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.map.layer.autotile.AutoTileLayer;
|
||||
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.engine.world.autotile.model.AutoTile;
|
||||
import com.bartlomiejpluta.base.engine.world.autotile.model.AutoTileSet;
|
||||
import com.bartlomiejpluta.base.engine.world.map.layer.base.BaseLayer;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
// Algorithm source: https://love2d.org/forums/viewtopic.php?t=7826
|
||||
public class DefaultAutoTileLayer extends BaseLayer implements AutoTileLayer {
|
||||
private final AutoTileSet autoTileSet;
|
||||
private final AutoTile[][] layer;
|
||||
private final boolean animated;
|
||||
private final double animationDuration;
|
||||
private final boolean connect;
|
||||
private double accumulator;
|
||||
|
||||
public DefaultAutoTileLayer(@NonNull GameMap map, @NonNull AutoTileSet autoTileSet, int rows, int columns, boolean animated, double animationDuration, boolean connect) {
|
||||
super(map);
|
||||
this.autoTileSet = autoTileSet;
|
||||
this.animated = animated;
|
||||
this.animationDuration = animationDuration;
|
||||
this.connect = connect;
|
||||
layer = new AutoTile[rows][columns];
|
||||
Arrays.stream(layer).forEach(tiles -> Arrays.fill(tiles, null));
|
||||
}
|
||||
|
||||
public void setTile(int row, int column, int setId) {
|
||||
var tile = autoTileSet.createTile(setId);
|
||||
tile.setCoordinates(column, row);
|
||||
layer[row][column] = tile;
|
||||
}
|
||||
|
||||
public void clearTile(int row, int column) {
|
||||
layer[row][column] = null;
|
||||
}
|
||||
|
||||
public void recalculate(Integer setId) {
|
||||
for (int row = 0; row < map.getRows(); ++row) {
|
||||
for (int column = 0; column < map.getColumns(); ++column) {
|
||||
recalculateTile(setId, row, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void recalculateTile(Integer setId, int row, int column) {
|
||||
switch(autoTileSet.getLayout()) {
|
||||
case LAYOUT_2X2 -> recalculateTile2x2(setId, row, column);
|
||||
case LAYOUT_2X3 -> recalculateTile2x3(setId, row, column);
|
||||
}
|
||||
}
|
||||
|
||||
private void recalculateTile2x2(Integer setId, int row, int column) {
|
||||
if (layer[row][column] == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var topLeft = 0;
|
||||
var topRight = 0;
|
||||
var bottomLeft = 0;
|
||||
var bottomRight = 0;
|
||||
|
||||
var tile = layer[row][column];
|
||||
var centerSetId = tile.getSetId();
|
||||
|
||||
if (animated) {
|
||||
tile.shiftTileSet();
|
||||
}
|
||||
|
||||
// Top
|
||||
if (row > 0 && (layer[row - 1][column] != null && (connect || layer[row - 1][column].getSetId() == centerSetId))) {
|
||||
topLeft += 2;
|
||||
topRight += 1;
|
||||
}
|
||||
|
||||
// Bottom
|
||||
if (row < map.getRows() - 1 && (layer[row + 1][column] != null && (connect || layer[row + 1][column].getSetId() == centerSetId))) {
|
||||
bottomLeft += 1;
|
||||
bottomRight += 2;
|
||||
}
|
||||
|
||||
// Left
|
||||
if (column > 0 && (layer[row][column - 1] != null && (connect || layer[row][column - 1].getSetId() == centerSetId))) {
|
||||
topLeft += 1;
|
||||
bottomLeft += 2;
|
||||
}
|
||||
|
||||
// Right
|
||||
if (column < map.getColumns() - 1 && (layer[row][column + 1] != null && (connect || layer[row][column + 1].getSetId() == centerSetId))) {
|
||||
topRight += 2;
|
||||
bottomRight += 1;
|
||||
}
|
||||
|
||||
tile.regularTile(setId, topLeft, topRight, bottomLeft, bottomRight);
|
||||
}
|
||||
|
||||
private void recalculateTile2x3(Integer setId, int row, int column) {
|
||||
if (layer[row][column] == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var topLeft = 0;
|
||||
var topRight = 0;
|
||||
var bottomLeft = 0;
|
||||
var bottomRight = 0;
|
||||
|
||||
var tile = layer[row][column];
|
||||
var centerSetId = tile.getSetId();
|
||||
|
||||
if (animated) {
|
||||
tile.shiftTileSet();
|
||||
}
|
||||
|
||||
// Top
|
||||
if (row > 0 && (layer[row - 1][column] != null && (connect || layer[row - 1][column].getSetId() == centerSetId))) {
|
||||
topLeft += 2;
|
||||
topRight += 1;
|
||||
}
|
||||
|
||||
// Bottom
|
||||
if (row < map.getRows() - 1 && (layer[row + 1][column] != null && (connect || layer[row + 1][column].getSetId() == centerSetId))) {
|
||||
bottomLeft += 1;
|
||||
bottomRight += 2;
|
||||
}
|
||||
|
||||
// Left
|
||||
if (column > 0 && (layer[row][column - 1] != null && (connect || layer[row][column - 1].getSetId() == centerSetId))) {
|
||||
topLeft += 1;
|
||||
bottomLeft += 2;
|
||||
}
|
||||
|
||||
// Right
|
||||
if (column < map.getColumns() - 1 && (layer[row][column + 1] != null && (connect || layer[row][column + 1].getSetId() == centerSetId))) {
|
||||
topRight += 2;
|
||||
bottomRight += 1;
|
||||
}
|
||||
|
||||
// Top left
|
||||
if (row > 0 && column > 0 && (layer[row - 1][column - 1] != null && (connect || layer[row - 1][column - 1].getSetId() == centerSetId)) && topLeft == 3) {
|
||||
topLeft = 4;
|
||||
}
|
||||
|
||||
// Top right
|
||||
if (row > 0 && column < map.getColumns() - 1 && (layer[row - 1][column + 1] != null && (connect || layer[row - 1][column + 1].getSetId() == centerSetId)) && topRight == 3) {
|
||||
topRight = 4;
|
||||
}
|
||||
|
||||
// Bottom left
|
||||
if (row < map.getRows() - 1 && column > 0 && (layer[row + 1][column - 1] != null && (connect || layer[row + 1][column - 1].getSetId() == centerSetId)) && bottomLeft == 3) {
|
||||
bottomLeft = 4;
|
||||
}
|
||||
|
||||
// Bottom right
|
||||
if (row < map.getRows() - 1 && column < map.getColumns() - 1 && (layer[row + 1][column + 1] != null && (connect || layer[row + 1][column + 1].getSetId() == centerSetId)) && bottomRight == 3) {
|
||||
bottomRight = 4;
|
||||
}
|
||||
|
||||
if (topLeft == 0 && topRight == 0 && bottomLeft == 0 && bottomRight == 0) {
|
||||
tile.islandTile(setId);
|
||||
return;
|
||||
}
|
||||
|
||||
tile.regularTile(setId, topLeft, topRight, bottomLeft, bottomRight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
super.update(dt);
|
||||
|
||||
if (animated) {
|
||||
accumulator += dt;
|
||||
|
||||
if (accumulator > animationDuration) {
|
||||
accumulator = 0;
|
||||
recalculate(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Screen screen, Camera camera, ShaderManager shaderManager) {
|
||||
for (var row : layer) {
|
||||
for (var tile : row) {
|
||||
if (tile != null) {
|
||||
tile.render(screen, camera, shaderManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.render(screen, camera, shaderManager);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture;
|
||||
import com.bartlomiejpluta.base.internal.gc.Disposable;
|
||||
import com.bartlomiejpluta.base.internal.render.Renderable;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.NonNull;
|
||||
import org.joml.Vector2fc;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -25,12 +27,20 @@ public class ChunkManager implements Renderable, Disposable {
|
||||
this(tileSet, rows, columns, DEFAULT_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
public ChunkManager(Texture tileSet, int rows, int columns, Vector2fc tileSize) {
|
||||
this(tileSet, rows, columns, tileSize, DEFAULT_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
public ChunkManager(Texture tileSet, int rows, int columns, int chunkSize) {
|
||||
this(tileSet, rows, columns, tileSet.getSpriteSize(), chunkSize);
|
||||
}
|
||||
|
||||
public ChunkManager(@NonNull Texture tileSet, int rows, int columns, @NonNull Vector2fc tileSize, int chunkSize) {
|
||||
this.tileSet = tileSet;
|
||||
this.mapRows = rows;
|
||||
this.mapColumns = columns;
|
||||
this.tileWidth = tileSet.getSpriteSize().x();
|
||||
this.tileHeight = tileSet.getSpriteSize().y();
|
||||
this.tileWidth = tileSize.x();
|
||||
this.tileHeight = tileSize.y();
|
||||
this.chunkSize = chunkSize;
|
||||
}
|
||||
|
||||
@@ -63,6 +73,21 @@ public class ChunkManager implements Renderable, Disposable {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public void setTile(int row, int column, int tileX, int tileY) {
|
||||
if (row < 0 || row >= mapRows || column < 0 || column >= mapColumns) {
|
||||
throw new IllegalArgumentException("Tile coordinates out of bounds");
|
||||
}
|
||||
|
||||
clearTile(row, column);
|
||||
|
||||
var chunk = getOrCreateChunk(row, column);
|
||||
var chunkKey = getChunkKey(row, column);
|
||||
var localTileKey = getLocalTileKey(row, column);
|
||||
|
||||
var quadId = chunk.addTile(column % chunkSize * (int) this.tileHeight, row % chunkSize * (int) this.tileWidth, tileX, tileY);
|
||||
|
||||
chunkTileIds.get(chunkKey).put(localTileKey, quadId);
|
||||
}
|
||||
|
||||
public void setTile(int row, int column, int tileId) {
|
||||
if (row < 0 || row >= mapRows || column < 0 || column >= mapColumns) {
|
||||
@@ -80,6 +105,33 @@ public class ChunkManager implements Renderable, Disposable {
|
||||
chunkTileIds.get(chunkKey).put(localTileKey, quadId);
|
||||
}
|
||||
|
||||
public void updateTile(int row, int column, int tileId) {
|
||||
var chunk = getOrCreateChunk(row, column);
|
||||
var chunkKey = getChunkKey(row, column);
|
||||
var localTileKey = getLocalTileKey(row, column);
|
||||
var quadId = chunkTileIds.get(chunkKey).get(localTileKey);
|
||||
chunk.updateTile(quadId, tileId);
|
||||
}
|
||||
|
||||
public void upsertTile(int row, int column, int tileX, int tileY) {
|
||||
if (row < 0 || row >= mapRows || column < 0 || column >= mapColumns) {
|
||||
throw new IllegalArgumentException("Tile coordinates out of bounds");
|
||||
}
|
||||
|
||||
var chunk = getOrCreateChunk(row, column);
|
||||
var chunkKey = getChunkKey(row, column);
|
||||
var localTileKey = getLocalTileKey(row, column);
|
||||
var tileMap = chunkTileIds.get(chunkKey);
|
||||
var quadId = tileMap.get(localTileKey);
|
||||
|
||||
if (quadId == null) {
|
||||
quadId = chunk.addTile(column % chunkSize * (int) this.tileHeight, row % chunkSize * (int) this.tileWidth, tileX, tileY);
|
||||
chunkTileIds.get(chunkKey).put(localTileKey, quadId);
|
||||
} else {
|
||||
chunk.updateTile(quadId, tileX, tileY);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearTile(int row, int column) {
|
||||
if (row < 0 || row >= mapRows || column < 0 || column >= mapColumns) {
|
||||
return;
|
||||
|
||||
@@ -35,10 +35,22 @@ public class TileChunk extends Model implements Placeable, Renderable, Disposabl
|
||||
this.originY = originY;
|
||||
}
|
||||
|
||||
public int addTile(int x, int y, int tileX, int tileY) {
|
||||
return mesh.addQuad(template, x, y, tileSet.getTextureCoordinates(tileX, tileY));
|
||||
}
|
||||
|
||||
public int addTile(int x, int y, int tileId) {
|
||||
return mesh.addQuad(template, x, y, tileSet.getTextureCoordinates(tileId));
|
||||
}
|
||||
|
||||
public void updateTile(int quadId, int tileX, int tileY) {
|
||||
mesh.setQuadTextureCoordinates(quadId, tileSet.getTextureCoordinates(tileX, tileY));
|
||||
}
|
||||
|
||||
public void updateTile(int quadId, int tileId) {
|
||||
mesh.setQuadTextureCoordinates(quadId, tileSet.getTextureCoordinates(tileId));
|
||||
}
|
||||
|
||||
public void removeTile(int quadId) {
|
||||
mesh.removeQuad(quadId);
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@ import com.bartlomiejpluta.base.api.map.layer.object.PassageAbility;
|
||||
import com.bartlomiejpluta.base.api.map.layer.tile.TileLayer;
|
||||
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.UniformName;
|
||||
import com.bartlomiejpluta.base.engine.util.mesh.MeshManager;
|
||||
import com.bartlomiejpluta.base.engine.world.autotile.model.AutoTileSet;
|
||||
import com.bartlomiejpluta.base.engine.world.map.layer.autotile.DefaultAutoTileLayer;
|
||||
import com.bartlomiejpluta.base.engine.world.map.layer.autotile.AutoTileLayer2x2;
|
||||
import com.bartlomiejpluta.base.engine.world.map.layer.autotile.AutoTileLayer3x2;
|
||||
import com.bartlomiejpluta.base.engine.world.map.layer.color.DefaultColorLayer;
|
||||
import com.bartlomiejpluta.base.engine.world.map.layer.image.DefaultImageLayer;
|
||||
import com.bartlomiejpluta.base.engine.world.map.layer.object.DefaultObjectLayer;
|
||||
@@ -139,8 +141,15 @@ public class DefaultGameMap implements Renderable, Updatable, GameMap {
|
||||
return layer;
|
||||
}
|
||||
|
||||
public DefaultAutoTileLayer createAutoTileLayer(@NonNull AutoTileSet autoTileSet, boolean animated, double animationDuration, boolean connect) {
|
||||
var layer = new DefaultAutoTileLayer(this, autoTileSet, rows, columns, animated, animationDuration, connect);
|
||||
public AutoTileLayer3x2 createAutoTileLayer3x2(@NonNull AutoTileSet tileSet, boolean animated, double animationDuration, boolean connect) {
|
||||
var layer = new AutoTileLayer3x2(this, tileSet, rows, columns, connect, animated, animationDuration);
|
||||
layers.add(layer);
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
public AutoTileLayer2x2 createAutoTileLayer2x2(@NonNull AutoTileSet tileSet, boolean animated, double animationDuration, boolean connect) {
|
||||
var layer = new AutoTileLayer2x2(this, tileSet, rows, columns, connect, animated, animationDuration);
|
||||
layers.add(layer);
|
||||
|
||||
return layer;
|
||||
|
||||
@@ -73,21 +73,19 @@ public class ProtobufMapDeserializer extends MapDeserializer {
|
||||
var animationDuration = proto.getAutoTileLayer().getAnimationDuration();
|
||||
var connect = proto.getAutoTileLayer().getConnect();
|
||||
|
||||
var layer = map.createAutoTileLayer(autoTileSet, animated, animationDuration, connect);
|
||||
var layer = switch(autoTileSet.getLayout()) {
|
||||
case LAYOUT_2X3 -> map.createAutoTileLayer3x2(autoTileSet, animated, animationDuration, connect);
|
||||
case LAYOUT_2X2 -> map.createAutoTileLayer2x2(autoTileSet, animated, animationDuration, connect);
|
||||
};
|
||||
|
||||
var columns = map.getColumns();
|
||||
var tiles = proto.getAutoTileLayer().getTilesList();
|
||||
|
||||
for (var i = 0; i < tiles.size(); ++i) {
|
||||
var tile = tiles.get(i);
|
||||
|
||||
if (tile == 0) {
|
||||
layer.clearTile(i / columns, i % columns);
|
||||
} else {
|
||||
layer.setTile(i / columns, i % columns, tile - 1);
|
||||
}
|
||||
layer.setTile(i / columns, i % columns, tile - 1);
|
||||
}
|
||||
|
||||
layer.recalculate(null);
|
||||
}
|
||||
|
||||
private void deserializeObjectLayer(DefaultGameMap map, GameMapProto.Layer proto) {
|
||||
|
||||
Reference in New Issue
Block a user