diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/object/material/Material.java b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/object/material/Material.java index ba4a5f32..c53940d7 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/object/material/Material.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/object/material/Material.java @@ -2,11 +2,14 @@ package com.bartlomiejpluta.samplegame.core.gl.object.material; import com.bartlomiejpluta.samplegame.core.gl.object.texture.Texture; import lombok.Getter; +import org.joml.Vector2f; import org.joml.Vector4f; @Getter public class Material { private final Vector4f color = new Vector4f(); + private final Vector2f spriteSize = new Vector2f(1, 1); + private final Vector2f spritePosition = new Vector2f(0, 0); private final Texture texture; private Material(Texture texture, float r, float g, float b, float alpha) { @@ -21,6 +24,26 @@ public class Material { color.w = alpha; } + public void setSpriteSize(Vector2f spriteSize) { + this.spriteSize.x = spriteSize.x; + this.spriteSize.y = spriteSize.y; + } + + public void setSpriteSize(float w, float h) { + this.spriteSize.x = w; + this.spriteSize.y = h; + } + + public void setSpritePosition(Vector2f spritePosition) { + this.spritePosition.x = spritePosition.x; + this.spritePosition.y = spritePosition.y; + } + + public void setSpritePosition(float x, float y) { + this.spritePosition.x = x; + this.spritePosition.y = y; + } + public boolean hasTexture() { return texture != null; } diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/object/mesh/Mesh.java b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/object/mesh/Mesh.java index d551fdc9..ceb7e239 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/object/mesh/Mesh.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/object/mesh/Mesh.java @@ -22,10 +22,6 @@ public class Mesh implements Renderable { private final List vboIds = new ArrayList<>(2); private final int elementsCount; - @Getter - @Setter - private Material material; - public Mesh(float[] vertices, float[] texCoords, int[] elements) { try(var stack = MemoryStack.stackPush()) { elementsCount = elements.length; @@ -83,4 +79,22 @@ public class Mesh implements Renderable { glBindVertexArray(0); glDeleteVertexArrays(vaoId); } + + public static Mesh quad(float width, float height) { + var halfWidth = width/2; + var halfHeight = height/2; + + var vertices = new float[] { + -halfWidth, -halfHeight, + -halfWidth, halfHeight, + halfWidth, halfHeight, + halfWidth, -halfHeight + }; + + var texCoords = new float[] { 0, 0, 0, 1, 1, 1, 1, 0 }; + + var elements = new int[] { 0, 1, 2, 2, 3, 0 }; + + return new Mesh(vertices, texCoords, elements); + } } diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/render/DefaultRenderer.java b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/render/DefaultRenderer.java index 70691e92..b5f12261 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/render/DefaultRenderer.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/render/DefaultRenderer.java @@ -27,7 +27,9 @@ public class DefaultRenderer implements Renderer { .createUniform(UniformName.UNI_PROJECTION_MATRIX) .createUniform(UniformName.UNI_OBJECT_COLOR) .createUniform(UniformName.UNI_HAS_OBJECT_TEXTURE) - .createUniform(UniformName.UNI_TEXTURE_SAMPLER); + .createUniform(UniformName.UNI_TEXTURE_SAMPLER) + .createUniform(UniformName.UNI_SPRITE_SIZE) + .createUniform(UniformName.UNI_SPRITE_POSITION); } @Override diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/constant/UniformName.java b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/constant/UniformName.java index ed2d00ef..c8b82de1 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/constant/UniformName.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/constant/UniformName.java @@ -7,4 +7,6 @@ public interface UniformName { String UNI_OBJECT_COLOR = "objectColor"; String UNI_HAS_OBJECT_TEXTURE = "hasTexture"; String UNI_TEXTURE_SAMPLER = "sampler"; + String UNI_SPRITE_SIZE = "spriteSize"; + String UNI_SPRITE_POSITION = "spritePosition"; } diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/manager/DefaultShaderManager.java b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/manager/DefaultShaderManager.java index 9e914644..aa99d608 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/manager/DefaultShaderManager.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/manager/DefaultShaderManager.java @@ -5,10 +5,7 @@ import com.bartlomiejpluta.samplegame.core.gl.shader.program.ShaderProgram; import com.bartlomiejpluta.samplegame.core.gl.shader.uniform.Uniform; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.joml.Matrix3f; -import org.joml.Matrix4f; -import org.joml.Vector3f; -import org.joml.Vector4f; +import org.joml.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -95,6 +92,12 @@ public class DefaultShaderManager implements ShaderManager { return this; } + @Override + public ShaderManager setUniform(String uniformName, Vector2f value) { + current.setUniform(uniformName, value); + return this; + } + @Override public ShaderManager setUniform(String uniformName, Vector3f value) { current.setUniform(uniformName, value); diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/manager/ShaderManager.java b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/manager/ShaderManager.java index a483f2ab..b5226d0d 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/manager/ShaderManager.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/manager/ShaderManager.java @@ -1,10 +1,7 @@ package com.bartlomiejpluta.samplegame.core.gl.shader.manager; import com.bartlomiejpluta.samplegame.core.gl.shader.uniform.Uniform; -import org.joml.Matrix3f; -import org.joml.Matrix4f; -import org.joml.Vector3f; -import org.joml.Vector4f; +import org.joml.*; public interface ShaderManager { ShaderManager createShader(String programName, String vertexShaderFilename, String fragmentShaderFilename); @@ -29,6 +26,8 @@ public interface ShaderManager { ShaderManager setUniform(String uniformName, float value); + ShaderManager setUniform(String uniformName, Vector2f value); + ShaderManager setUniform(String uniformName, Vector3f value); ShaderManager setUniform(String uniformName, Vector4f value); diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/program/ShaderProgram.java b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/program/ShaderProgram.java index d44a9623..db983f1f 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/program/ShaderProgram.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/core/gl/shader/program/ShaderProgram.java @@ -3,10 +3,7 @@ package com.bartlomiejpluta.samplegame.core.gl.shader.program; import com.bartlomiejpluta.samplegame.core.error.AppException; import com.bartlomiejpluta.samplegame.core.gl.shader.uniform.Uniform; import lombok.extern.slf4j.Slf4j; -import org.joml.Matrix3f; -import org.joml.Matrix4f; -import org.joml.Vector3f; -import org.joml.Vector4f; +import org.joml.*; import org.lwjgl.system.MemoryStack; import java.util.HashMap; @@ -111,6 +108,10 @@ public class ShaderProgram { glUniform1f(uniforms.get(uniformName), value); } + public void setUniform(String uniformName, Vector2f value) { + glUniform2f(uniforms.get(uniformName), value.x, value.y); + } + public void setUniform(String uniformName, Vector3f value) { glUniform3f(uniforms.get(uniformName), value.x, value.y, value.z); } diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/core/world/object/RenderableObject.java b/app/src/main/java/com/bartlomiejpluta/samplegame/core/world/object/RenderableObject.java index 5803f8ad..54299fe5 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/core/world/object/RenderableObject.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/core/world/object/RenderableObject.java @@ -5,19 +5,17 @@ import com.bartlomiejpluta.samplegame.core.gl.object.mesh.Mesh; import com.bartlomiejpluta.samplegame.core.gl.render.Renderable; import com.bartlomiejpluta.samplegame.core.gl.shader.manager.ShaderManager; import com.bartlomiejpluta.samplegame.core.ui.Window; +import lombok.Getter; import lombok.RequiredArgsConstructor; +import lombok.Setter; @RequiredArgsConstructor public abstract class RenderableObject extends Object implements Renderable { private final Mesh mesh; - public void setMaterial(Material material) { - mesh.setMaterial(material); - } - - public Material getMaterial() { - return mesh.getMaterial(); - } + @Getter + @Setter + private Material material; @Override public void render(Window window, ShaderManager shaderManager) { diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/core/world/scene/Scene.java b/app/src/main/java/com/bartlomiejpluta/samplegame/core/world/scene/Scene.java index 24d05b2c..d03f87cf 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/core/world/scene/Scene.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/core/world/scene/Scene.java @@ -29,7 +29,6 @@ public class Scene implements Renderable { renderArray(map.getLayer(2), window, shaderManager); renderArray(map.getLayer(3), window, shaderManager); - } private void renderArray(T[] objects, Window window, ShaderManager shaderManager) { @@ -45,6 +44,8 @@ public class Scene implements Renderable { shaderManager.setUniform(UniformName.UNI_OBJECT_COLOR, object.getMaterial().getColor()); shaderManager.setUniform(UniformName.UNI_HAS_OBJECT_TEXTURE, object.getMaterial().hasTexture()); shaderManager.setUniform(UniformName.UNI_TEXTURE_SAMPLER, 0); + shaderManager.setUniform(UniformName.UNI_SPRITE_SIZE, object.getMaterial().getSpriteSize()); + shaderManager.setUniform(UniformName.UNI_SPRITE_POSITION, object.getMaterial().getSpritePosition()); object.render(window, shaderManager); } diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/game/logic/DefaultGameLogic.java b/app/src/main/java/com/bartlomiejpluta/samplegame/game/logic/DefaultGameLogic.java index 6d32eb1d..00cf4d21 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/game/logic/DefaultGameLogic.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/game/logic/DefaultGameLogic.java @@ -16,7 +16,6 @@ import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class DefaultGameLogic implements GameLogic { - private static final float SCALE = 3.0f; private final Renderer renderer; private final TileSetManager tileSetManager; diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/game/sprite/BaseSprite.java b/app/src/main/java/com/bartlomiejpluta/samplegame/game/sprite/BaseSprite.java deleted file mode 100755 index 19df1196..00000000 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/game/sprite/BaseSprite.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.bartlomiejpluta.samplegame.game.sprite; - -import com.bartlomiejpluta.samplegame.core.gl.object.material.Material; -import com.bartlomiejpluta.samplegame.core.gl.object.mesh.Mesh; -import com.bartlomiejpluta.samplegame.core.gl.object.texture.Texture; -import com.bartlomiejpluta.samplegame.core.world.object.RenderableObject; -import lombok.Getter; - -@Getter -public class BaseSprite extends RenderableObject { - private static final int[] ELEMENTS = new int[]{ - 0, 1, 2, - 2, 3, 0 - }; - - private final int row; - private final int col; - private final int tileWidth; - private final int tileHeight; - - public BaseSprite(Texture texture, int row, int col, int tileWidth, int tileHeight) { - super(buildTileMesh(texture, row, col, tileWidth, tileHeight)); - this.row = row; - this.col = col; - this.tileWidth = tileWidth; - this.tileHeight = tileHeight; - setMaterial(Material.textured(texture)); - } - - private static Mesh buildTileMesh(Texture texture, int row, int col, int tileWidth, int tileHeight) { - var vertices = getVertices(tileWidth, tileHeight); - var texCoords = getTextureCoordinates(row, col, tileWidth, tileHeight, texture.getWidth(), texture.getHeight()); - return new Mesh(vertices, texCoords, ELEMENTS); - } - - private static float[] getVertices(int tileWidth, int tileHeight) { - var halfWidth = tileWidth / 2; - var halfHeight = tileHeight / 2; - return new float[]{ - -halfWidth, -halfHeight, - -halfWidth, halfHeight, - halfWidth, halfHeight, - halfWidth, -halfHeight - }; - } - - private static float[] getTextureCoordinates(int col, int row, int tileWidth, int tileHeight, int textureWidth, int textureHeight) { - return new float[]{ - (col * tileWidth) / (float) textureWidth, (row * tileHeight) / (float) textureHeight, - (col * tileWidth) / (float) textureWidth, ((row + 1) * tileHeight) / (float) textureHeight, - ((col + 1) * tileWidth) / (float) textureWidth, ((row + 1) * tileHeight) / (float) textureHeight, - ((col + 1) * tileWidth) / (float) textureWidth, (row * tileHeight) / (float) textureHeight - }; - } -} diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/map/GameMap.java b/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/map/GameMap.java index 9a22af50..1646bad9 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/map/GameMap.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/map/GameMap.java @@ -32,7 +32,7 @@ public class GameMap { private void recalculateTileGeometry(Tile tile, int i, int j) { tile.setScale(scale); - var size = tile.getSize(); + var size = tile.getWidth(); var offset = size * scale; tile.setPosition(i * offset, j * offset); } diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/manager/DefaultTileSetManager.java b/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/manager/DefaultTileSetManager.java index af4f1a46..b74ac3c8 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/manager/DefaultTileSetManager.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/manager/DefaultTileSetManager.java @@ -2,17 +2,28 @@ package com.bartlomiejpluta.samplegame.game.world.tileset.manager; import com.bartlomiejpluta.samplegame.core.gl.object.texture.TextureManager; import com.bartlomiejpluta.samplegame.game.world.tileset.model.TileSet; -import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component -@RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class DefaultTileSetManager implements TileSetManager { private final TextureManager textureManager; + private final int tileWidth; + private final int tileHeight; + + @Autowired + public DefaultTileSetManager( + TextureManager textureManager, + @Value("${app.map.tile.width}") int tileWidth, + @Value("${app.map.tile.width}") int tileHeight) { + this.textureManager = textureManager; + this.tileWidth = tileWidth; + this.tileHeight = tileHeight; + } @Override - public TileSet createTileSet(String tileSetFileName) { - return new TileSet(textureManager.loadTexture(tileSetFileName)); + public TileSet createTileSet(String tileSetFileName, int rows, int columns) { + return new TileSet(textureManager.loadTexture(tileSetFileName), rows, columns, tileWidth, tileHeight); } } diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/manager/TileSetManager.java b/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/manager/TileSetManager.java index 1450856b..919afea1 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/manager/TileSetManager.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/manager/TileSetManager.java @@ -3,5 +3,5 @@ package com.bartlomiejpluta.samplegame.game.world.tileset.manager; import com.bartlomiejpluta.samplegame.game.world.tileset.model.TileSet; public interface TileSetManager { - TileSet createTileSet(String tileSetFileName); + TileSet createTileSet(String tileSetFileName, int rows, int columns); } diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/model/Tile.java b/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/model/Tile.java index 69e3a818..5701bd99 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/model/Tile.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/model/Tile.java @@ -1,16 +1,19 @@ package com.bartlomiejpluta.samplegame.game.world.tileset.model; -import com.bartlomiejpluta.samplegame.core.gl.object.texture.Texture; - -import com.bartlomiejpluta.samplegame.game.sprite.BaseSprite; +import com.bartlomiejpluta.samplegame.core.gl.object.material.Material; +import com.bartlomiejpluta.samplegame.core.gl.object.mesh.Mesh; +import com.bartlomiejpluta.samplegame.core.world.object.RenderableObject; import lombok.Getter; @Getter -public class Tile extends BaseSprite { - private final int size; +public class Tile extends RenderableObject { + private final int width; + private final int height; - public Tile(Texture texture, int row, int col, int size) { - super(texture, row, col, size, size); - this.size = size; + Tile(Mesh mesh, Material material, int width, int height) { + super(mesh); + this.width = width; + this.height = height; + setMaterial(material); } } diff --git a/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/model/TileSet.java b/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/model/TileSet.java index f684ec92..0829def9 100755 --- a/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/model/TileSet.java +++ b/app/src/main/java/com/bartlomiejpluta/samplegame/game/world/tileset/model/TileSet.java @@ -1,25 +1,35 @@ package com.bartlomiejpluta.samplegame.game.world.tileset.model; +import com.bartlomiejpluta.samplegame.core.gl.object.material.Material; +import com.bartlomiejpluta.samplegame.core.gl.object.mesh.Mesh; import com.bartlomiejpluta.samplegame.core.gl.object.texture.Texture; +import com.bartlomiejpluta.samplegame.core.world.object.RenderableObject; public class TileSet { - private static final int TILE_SIZE = 16; - private final Texture texture; private final int rows; - private final int cols; + private final int columns; + private final float columnStep; + private final float rowStep; + private final int tileWidth; + private final int tileHeight; + private final Mesh mesh; - public TileSet(Texture texture) { + public TileSet(Texture texture, int rows, int columns, int tileWidth, int tileHeight) { this.texture = texture; - this.rows = texture.getHeight() / TILE_SIZE; - this.cols = texture.getWidth() / TILE_SIZE; + 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.quad(tileWidth, tileHeight); } public Tile getTile(int m, int n) { - return new Tile(texture, m, n, TILE_SIZE); - } - - public Tile getTile(int i) { - return new Tile(texture, i % cols, i / rows, TILE_SIZE); + var material = Material.textured(texture); + material.setSpriteSize(columnStep, rowStep); + material.setSpritePosition(n * columnStep, m * rowStep); + return new Tile(mesh, material, tileWidth, tileHeight); } } diff --git a/app/src/main/resources/application.yml b/app/src/main/resources/application.yml index 470c8817..09772ca8 100755 --- a/app/src/main/resources/application.yml +++ b/app/src/main/resources/application.yml @@ -5,4 +5,9 @@ app: height: 480 core: - targetUps: 50 # Updates per second \ No newline at end of file + targetUps: 50 # Updates per second + + map: + tile: + width: 50 + height: 50 \ No newline at end of file diff --git a/app/src/main/resources/shaders/default.fs b/app/src/main/resources/shaders/default.fs index 42a6f4c8..17588409 100755 --- a/app/src/main/resources/shaders/default.fs +++ b/app/src/main/resources/shaders/default.fs @@ -3,6 +3,8 @@ uniform vec4 objectColor; uniform int hasTexture; uniform sampler2D sampler; +uniform vec2 spriteSize; +uniform vec2 spritePosition; in vec2 fragmentTexCoord; @@ -12,7 +14,7 @@ void main() { if(hasTexture == 1) { - fragColor = objectColor * texture(sampler, fragmentTexCoord); + fragColor = objectColor * texture(sampler, fragmentTexCoord * spriteSize + spritePosition); } else {