From be235c67983d1376a50589cb47d116ced47b65cc Mon Sep 17 00:00:00 2001 From: Dmitrii Morozov Date: Sat, 4 Jan 2025 19:06:26 +0100 Subject: Star field and haze --- .../java/org/snoopdesigns/endless/EndlessGame.java | 81 ++---------------- .../snoopdesigns/endless/render/RenderContext.java | 27 ++++++ .../snoopdesigns/endless/render/Renderable.java | 5 ++ .../endless/screen/main/CameraDebug.java | 41 +++++++++ .../endless/screen/main/MainScreen.java | 96 ++++++++++++++++++++++ .../endless/screen/main/StarField.java | 83 +++++++++++++++++++ 6 files changed, 257 insertions(+), 76 deletions(-) create mode 100644 core/src/main/java/org/snoopdesigns/endless/render/RenderContext.java create mode 100644 core/src/main/java/org/snoopdesigns/endless/render/Renderable.java create mode 100644 core/src/main/java/org/snoopdesigns/endless/screen/main/CameraDebug.java create mode 100644 core/src/main/java/org/snoopdesigns/endless/screen/main/MainScreen.java create mode 100644 core/src/main/java/org/snoopdesigns/endless/screen/main/StarField.java (limited to 'core/src/main/java/org') diff --git a/core/src/main/java/org/snoopdesigns/endless/EndlessGame.java b/core/src/main/java/org/snoopdesigns/endless/EndlessGame.java index 1453a6e..8bfeb0b 100644 --- a/core/src/main/java/org/snoopdesigns/endless/EndlessGame.java +++ b/core/src/main/java/org/snoopdesigns/endless/EndlessGame.java @@ -1,92 +1,21 @@ package org.snoopdesigns.endless; -import com.badlogic.gdx.ApplicationAdapter; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Input; -import com.badlogic.gdx.graphics.OrthographicCamera; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.math.MathUtils; -import com.badlogic.gdx.utils.ScreenUtils; +import com.badlogic.gdx.Game; +import org.snoopdesigns.endless.screen.main.MainScreen; -public class EndlessGame extends ApplicationAdapter { - - private static final int WORLD_WIDTH = 100; - private static final int WORLD_HEIGHT = 100; - - private static final int DEFAULT_VIEWPORT_WIDTH = 30; - private static final int DEFAULT_VIEWPORT_HEIGHT = 30; - - private OrthographicCamera cam; - private SpriteBatch batch; - private Sprite imageSprite; - private Texture image; +public class EndlessGame extends Game { @Override public void create() { - batch = new SpriteBatch(); - image = new Texture("sc_map.png"); - imageSprite = new Sprite(image); - imageSprite.setPosition(0, 0); - imageSprite.setSize(WORLD_WIDTH, WORLD_HEIGHT); - - float graphicsWidth = Gdx.graphics.getWidth(); - float graphicsHeight = Gdx.graphics.getHeight(); - - cam = new OrthographicCamera( - DEFAULT_VIEWPORT_WIDTH, - DEFAULT_VIEWPORT_HEIGHT * (graphicsHeight / graphicsWidth)); - cam.position.set(cam.viewportWidth / 2f, cam.viewportHeight / 2f, 0); - cam.update(); + setScreen(new MainScreen()); } @Override public void render() { - handleInput(); - cam.update(); - batch.setProjectionMatrix(cam.combined); - - ScreenUtils.clear(0.15f, 0.15f, 0.2f, 1f); - - batch.begin(); - imageSprite.draw(batch); - batch.end(); + super.render(); } @Override public void dispose() { - imageSprite.getTexture().dispose(); - batch.dispose(); - image.dispose(); - } - - private void handleInput() { - if (Gdx.input.isKeyPressed(Input.Keys.A)) { - cam.zoom += 0.02; - } - if (Gdx.input.isKeyPressed(Input.Keys.Q)) { - cam.zoom -= 0.02; - } - if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) { - cam.translate(-3, 0, 0); - } - if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) { - cam.translate(3, 0, 0); - } - if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) { - cam.translate(0, -3, 0); - } - if (Gdx.input.isKeyPressed(Input.Keys.UP)) { - cam.translate(0, 3, 0); - } - - cam.zoom = MathUtils.clamp(cam.zoom, 0.1f, 100 / cam.viewportWidth); - - float effectiveViewportWidth = cam.viewportWidth * cam.zoom; - float effectiveViewportHeight = cam.viewportHeight * cam.zoom; - - cam.position.x = MathUtils.clamp(cam.position.x, effectiveViewportWidth / 2f, 100 - effectiveViewportWidth / 2f); - cam.position.y = MathUtils.clamp(cam.position.y, effectiveViewportHeight / 2f, 100 - effectiveViewportHeight / 2f); } } diff --git a/core/src/main/java/org/snoopdesigns/endless/render/RenderContext.java b/core/src/main/java/org/snoopdesigns/endless/render/RenderContext.java new file mode 100644 index 0000000..eced07d --- /dev/null +++ b/core/src/main/java/org/snoopdesigns/endless/render/RenderContext.java @@ -0,0 +1,27 @@ +package org.snoopdesigns.endless.render; + +import com.badlogic.gdx.graphics.Camera; +import com.badlogic.gdx.math.Matrix4; +import com.badlogic.gdx.math.Vector3; + +public class RenderContext { + + private final Camera camera; + + public RenderContext(final Camera camera) { + this.camera = camera; + } + + public Camera getCamera() { + return this.camera; + } + + public Matrix4 getProjectionMatrix() { + return camera.combined; + } + + public Vector3 getCameraPosition() { + return camera.position; + } + +} diff --git a/core/src/main/java/org/snoopdesigns/endless/render/Renderable.java b/core/src/main/java/org/snoopdesigns/endless/render/Renderable.java new file mode 100644 index 0000000..d9930cb --- /dev/null +++ b/core/src/main/java/org/snoopdesigns/endless/render/Renderable.java @@ -0,0 +1,5 @@ +package org.snoopdesigns.endless.render; + +public interface Renderable { + void render(float delta, RenderContext renderContext); +} diff --git a/core/src/main/java/org/snoopdesigns/endless/screen/main/CameraDebug.java b/core/src/main/java/org/snoopdesigns/endless/screen/main/CameraDebug.java new file mode 100644 index 0000000..123f5bc --- /dev/null +++ b/core/src/main/java/org/snoopdesigns/endless/screen/main/CameraDebug.java @@ -0,0 +1,41 @@ +package org.snoopdesigns.endless.screen.main; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; +import org.snoopdesigns.endless.render.RenderContext; +import org.snoopdesigns.endless.render.Renderable; + +public class CameraDebug implements Renderable { + + private BitmapFont font; + private SpriteBatch batch; + + public CameraDebug() { + batch = new SpriteBatch(); + + FreeTypeFontGenerator generator = new FreeTypeFontGenerator( + Gdx.files.internal("fonts/DroidSans.ttf")); + FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter(); + parameter.size = 32; + font = generator.generateFont(parameter); + generator.dispose(); + } + + @Override + public void render(float delta, RenderContext renderContext) { + batch.begin(); + font.draw(batch, formatDebugText(renderContext), 100f, 100f); + batch.end(); + } + + private static String formatDebugText(final RenderContext renderContext) { + return "cam: %f %f\nviewport: %f %f".formatted( + renderContext.getCameraPosition().x, + renderContext.getCameraPosition().y, + renderContext.getCamera().viewportWidth, + renderContext.getCamera().viewportHeight + ); + } +} diff --git a/core/src/main/java/org/snoopdesigns/endless/screen/main/MainScreen.java b/core/src/main/java/org/snoopdesigns/endless/screen/main/MainScreen.java new file mode 100644 index 0000000..5f162b7 --- /dev/null +++ b/core/src/main/java/org/snoopdesigns/endless/screen/main/MainScreen.java @@ -0,0 +1,96 @@ +package org.snoopdesigns.endless.screen.main; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; +import com.badlogic.gdx.InputAdapter; +import com.badlogic.gdx.Screen; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.utils.ScreenUtils; +import org.snoopdesigns.endless.render.RenderContext; +import org.snoopdesigns.endless.render.Renderable; + +public class MainScreen implements Screen { + + private Renderable starField; + private Renderable cameraDebug; + private OrthographicCamera camera; + private RenderContext renderContext; + + @Override + public void show() { + float screenWidth = Gdx.graphics.getWidth(); + float screenHeight = Gdx.graphics.getHeight(); + + camera = new OrthographicCamera( + screenWidth, + screenWidth * (screenHeight / screenWidth)); + + Gdx.input.setInputProcessor(new InputAdapter() { + @Override + public boolean scrolled(float amountX, float amountY) { + final var scale = 1.0f + (0.1f * amountY); + camera.viewportWidth *= scale; + camera.viewportHeight *= scale; + normalizeCamera(); + return true; + } + + private void normalizeCamera() { + //camera.zoom = MathUtils.clamp(camera.zoom, 0.1f, + //WORLD_WIDTH / camera.viewportWidth); + } + }); + + starField = new StarField(); + cameraDebug = new CameraDebug(); + + renderContext = new RenderContext(camera); + } + + @Override + public void render(float delta) { + handleInput(); + camera.update(); + + ScreenUtils.clear(Color.BLACK); + + starField.render(delta, renderContext); + cameraDebug.render(delta, renderContext); + } + + @Override + public void resize(int width, int height) { + } + + @Override + public void pause() { + } + + @Override + public void resume() { + } + + @Override + public void hide() { + } + + @Override + public void dispose() { + } + + private void handleInput() { + if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) { + camera.translate(-3, 0, 0); + } + if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) { + camera.translate(3, 0, 0); + } + if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) { + camera.translate(0, -3, 0); + } + if (Gdx.input.isKeyPressed(Input.Keys.UP)) { + camera.translate(0, 3, 0); + } + } +} diff --git a/core/src/main/java/org/snoopdesigns/endless/screen/main/StarField.java b/core/src/main/java/org/snoopdesigns/endless/screen/main/StarField.java new file mode 100644 index 0000000..e5c059b --- /dev/null +++ b/core/src/main/java/org/snoopdesigns/endless/screen/main/StarField.java @@ -0,0 +1,83 @@ +package org.snoopdesigns.endless.screen.main; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.GL30; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.math.Vector3; +import org.snoopdesigns.endless.render.RenderContext; +import org.snoopdesigns.endless.render.Renderable; + +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.List; + +public class StarField implements Renderable { + + private final float STAR_RADIUS = 1.0f; + private final float TILE_AMOUNT = 100; + private final float TILE_SIZE = 60; + private final float BRIGHTNESS_FACTOR = 0.6f; + private final int HAZE_AMOUNT = 16; + + private final ShapeRenderer shapeRenderer; + private final SpriteBatch batch; + private final SecureRandom random = new SecureRandom(); + private final List stars = new ArrayList<>(); + private final List hazes = new ArrayList<>(); + + public StarField() { + shapeRenderer = new ShapeRenderer(); + batch = new SpriteBatch(); + + final var displacement = (TILE_AMOUNT * TILE_SIZE) / -2.0f; + for (int i = 0; i < TILE_AMOUNT; i++) { + for (int j = 0; j < TILE_AMOUNT; j++) { + stars.add(new Vector3( + displacement + TILE_SIZE * i + random.nextFloat(TILE_SIZE), + displacement + TILE_SIZE * j + random.nextFloat(TILE_SIZE), + random.nextFloat(BRIGHTNESS_FACTOR))); + } + } + + for (int i = 0; i < HAZE_AMOUNT; i++) { + final var randomHazeVector = stars.get(random.nextInt(stars.size())); + final var hazeSprite = new Sprite(new Texture(Gdx.files.internal("haze.jpg"))); + hazeSprite.setSize(500, 500); + hazeSprite.setPosition(randomHazeVector.x, randomHazeVector.y); + hazeSprite.setRotation(random.nextFloat(360)); + hazes.add(hazeSprite); + } + } + + @Override + public void render(float delta, RenderContext renderContext) { + final var projectionMatrix = renderContext.getProjectionMatrix(); + final var cameraPosition = renderContext.getCameraPosition(); + + batch.setProjectionMatrix(projectionMatrix); + batch.begin(); + hazes.forEach(haze -> { + haze.draw(batch); + }); + batch.end(); + + Gdx.gl.glEnable(GL30.GL_BLEND); + Gdx.gl.glBlendFunc(GL30.GL_SRC_ALPHA, GL30.GL_ONE_MINUS_SRC_ALPHA); + + shapeRenderer.setProjectionMatrix(projectionMatrix); + shapeRenderer.begin(ShapeRenderer.ShapeType.Filled); + + stars.forEach(star -> { + shapeRenderer.setColor(1, 1, 1, star.z); + shapeRenderer.circle( + star.x + cameraPosition.x * star.z, + star.y + cameraPosition.y * star.z, STAR_RADIUS); + }); + + shapeRenderer.end(); + Gdx.gl.glDisable(GL30.GL_BLEND); + } +} -- cgit v1.2.3