diff --git a/core/src/main/java/wtf/beatrice/retrorender/GameScreen.java b/core/src/main/java/wtf/beatrice/retrorender/GameScreen.java index 0157f58..35c9e3d 100644 --- a/core/src/main/java/wtf/beatrice/retrorender/GameScreen.java +++ b/core/src/main/java/wtf/beatrice/retrorender/GameScreen.java @@ -14,10 +14,7 @@ import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute; import com.badlogic.gdx.graphics.g3d.environment.DirectionalShadowLight; import com.badlogic.gdx.graphics.g3d.utils.DepthShaderProvider; import com.badlogic.gdx.graphics.glutils.FrameBuffer; -import wtf.beatrice.retrorender.engine.DebugHud; -import wtf.beatrice.retrorender.engine.FpsCameraController; -import wtf.beatrice.retrorender.engine.PauseMenu; -import wtf.beatrice.retrorender.engine.World3D; +import wtf.beatrice.retrorender.engine.*; public class GameScreen implements Screen { @@ -32,9 +29,11 @@ public class GameScreen implements Screen { private DebugHud hud; private boolean showHud = false; - private boolean paused = false; - private PauseMenu pauseMenu; + // menus + private GameSettings settings; + private GameUi gameUi; + private UiMode uiMode = UiMode.GAMEPLAY; // Shadow Mapping private ModelBatch shadowBatch; @@ -53,14 +52,10 @@ public class GameScreen implements Screen { } private void initCamera() { - camera = new PerspectiveCamera( - 67f, - RETRO_WIDTH, - RETRO_HEIGHT - ); - - // near/far + initial direction handled in controller constructor - cameraController = new FpsCameraController(camera); + camera = new PerspectiveCamera(67f, RETRO_WIDTH, RETRO_HEIGHT); + settings = new GameSettings(); + settings.fov = camera.fieldOfView; + cameraController = new FpsCameraController(camera, settings); } private void initEnvironment() { @@ -75,12 +70,12 @@ public class GameScreen implements Screen { // shadow-casting directional light shadowLight = new DirectionalShadowLight( 1024, 1024, // shadow map resolution - 60f, 60f, // viewport size - 1f, 50f // near/far for the light camera + 60f, 60f, // viewport size + 1f, 50f // near/far for the light camera ); shadowLight.set( - 1.0f, 0.85f, 0.9f, // casting light color - -0.7f, -1.0f, -0.3f // direction + 1.0f, 0.85f, 0.9f, // light color + -0.7f, -1.0f, -0.3f // direction ); environment.add(shadowLight); @@ -95,12 +90,10 @@ public class GameScreen implements Screen { private void initMenus() { hud = new DebugHud(); - pauseMenu = new PauseMenu(); + gameUi = new GameUi(settings); } - // --- screen methods private void initRetroBuffer() { - // RGB + depth frameBuffer = new FrameBuffer( com.badlogic.gdx.graphics.Pixmap.Format.RGBA8888, RETRO_WIDTH, @@ -111,10 +104,9 @@ public class GameScreen implements Screen { Texture fbTex = frameBuffer.getColorBufferTexture(); frameRegion = new TextureRegion(fbTex); fbTex.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest); - // FBO textures are Y-flipped in libGDX, so flip once here frameRegion.flip(false, true); - screenBatch = new com.badlogic.gdx.graphics.g2d.SpriteBatch(); + screenBatch = new SpriteBatch(); } @Override @@ -134,24 +126,25 @@ public class GameScreen implements Screen { // ESC: toggle pause and mouse capture if (Gdx.input.isKeyJustPressed(Input.Keys.ESCAPE)) { - paused = !paused; - if (paused) { - cameraController.releaseMouse(); - } else { + UiMode newMode = gameUi.onEsc(uiMode); + boolean goingToGameplay = (newMode == UiMode.GAMEPLAY); + uiMode = newMode; + + if (uiMode == UiMode.GAMEPLAY) { cameraController.captureMouse(); + } else { + cameraController.releaseMouse(); } } - if (!paused) { + boolean gameplay = (uiMode == UiMode.GAMEPLAY); + + if (gameplay) { cameraController.update(delta, world); world.update(delta); } - if (Gdx.input.isKeyJustPressed(Input.Keys.TAB)) { - showHud = !showHud; - } - - // --- shadow pass: render depth from light's point of view + // --- shadow pass --- shadowLight.begin(new com.badlogic.gdx.math.Vector3(0f, 0f, 0f), camera.direction); shadowBatch.begin(shadowLight.getCamera()); @@ -160,7 +153,7 @@ public class GameScreen implements Screen { shadowLight.end(); - // --- render scene into low res framebuffer + // --- render scene into low res framebuffer --- frameBuffer.begin(); Gdx.gl.glViewport(0, 0, RETRO_WIDTH, RETRO_HEIGHT); Gdx.gl.glClearColor(0.5f, 0.6f, 1.0f, 1f); @@ -168,85 +161,89 @@ public class GameScreen implements Screen { camera.update(); modelBatch.begin(camera); - world.render(modelBatch, environment); // DefaultShader uses shadowLight + env.shadowMap + world.render(modelBatch, environment); modelBatch.end(); - // --- HUD - if (showHud) + // HUD + if (Gdx.input.isKeyJustPressed(Input.Keys.TAB)) { + showHud = !showHud; + } + if (showHud) { hud.render( RETRO_WIDTH, RETRO_HEIGHT, camera, cameraController.getYaw(), - cameraController.getPitch()); + cameraController.getPitch() + ); + } - // pause menu - if (paused && pauseMenu != null) { - pauseMenu.render(RETRO_WIDTH, RETRO_HEIGHT); + // pause UI + if (uiMode != UiMode.GAMEPLAY) { + gameUi.render(RETRO_WIDTH, RETRO_HEIGHT, uiMode); } frameBuffer.end(); // -- scale framebuffer to screen, preserve aspect ratio -- - int windowW = Gdx.graphics.getWidth(); // logical size + int windowW = Gdx.graphics.getWidth(); int windowH = Gdx.graphics.getHeight(); + int backW = Gdx.graphics.getBackBufferWidth(); + int backH = Gdx.graphics.getBackBufferHeight(); - int backW = Gdx.graphics.getBackBufferWidth(); // actual GL framebuffer - int backH = Gdx.graphics.getBackBufferHeight(); + RetroViewportHelper.RetroViewport vp = + RetroViewportHelper.computeViewport(windowW, windowH, RETRO_WIDTH, RETRO_HEIGHT); - // compute how much we can scale the FBO into the window - float scale = Math.min( - windowW / (float) RETRO_WIDTH, - windowH / (float) RETRO_HEIGHT - ); - - int drawW = Math.round(RETRO_WIDTH * scale); - int drawH = Math.round(RETRO_HEIGHT * scale); - - // center the image - int offsetX = (windowW - drawW) / 2; - int offsetY = (windowH - drawH) / 2; - - // --- handle mouse click on pause button (window -> retro coords) --- - if (paused && pauseMenu != null && Gdx.input.justTouched()) { + // click → UI + if (uiMode != UiMode.GAMEPLAY && Gdx.input.justTouched()) { int mouseX = Gdx.input.getX(); - int mouseY = Gdx.graphics.getHeight() - Gdx.input.getY(); // to bottom-left origin + int mouseY = Gdx.input.getY(); - // is the click inside the scaled game area? - if (mouseX >= offsetX && mouseX <= offsetX + drawW && - mouseY >= offsetY && mouseY <= offsetY + drawH) { + RetroViewportHelper.RetroClick rc = + RetroViewportHelper.toRetroCoords( + vp, + RETRO_WIDTH, RETRO_HEIGHT, + mouseX, mouseY, + windowH + ); - float relX = (mouseX - offsetX) / (float) drawW; - float relY = (mouseY - offsetY) / (float) drawH; + if (rc.inside) { + GameUi.UiResult result = gameUi.handleClick(rc.x, rc.y, uiMode); - float retroX = relX * RETRO_WIDTH; - float retroY = relY * RETRO_HEIGHT; - - PauseMenu.MenuAction action = pauseMenu.getActionAt(retroX, retroY); - switch (action) { + switch (result) { case RESUME: - paused = false; - cameraController.onShow(); + uiMode = UiMode.GAMEPLAY; + cameraController.captureMouse(); break; + + case OPEN_SETTINGS: + uiMode = UiMode.SETTINGS; + // mouse already released when we entered PAUSE, so nothing to do + break; + + case CLOSE_SETTINGS: + uiMode = UiMode.PAUSE; + // stay in pause, mouse remains free + break; + case QUIT: Gdx.app.exit(); break; + + case NONE: default: break; - } + } } } // viewport in backbuffer coordinates + // final draw using vp.offsetX / vp.offsetY / vp.drawW / vp.drawH Gdx.gl.glViewport(0, 0, backW, backH); - Gdx.gl.glClearColor(0f, 0f, 0f, 1f); - Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); - - // projection in window (logical) coordinates screenBatch.getProjectionMatrix().setToOrtho2D(0, 0, windowW, windowH); screenBatch.begin(); - screenBatch.draw(frameRegion, offsetX, offsetY, drawW, drawH); + screenBatch.draw(frameRegion, vp.offsetX, vp.offsetY, vp.drawW, vp.drawH); screenBatch.end(); } @@ -273,10 +270,9 @@ public class GameScreen implements Screen { world.dispose(); modelBatch.dispose(); hud.dispose(); - shadowBatch.dispose(); shadowLight.dispose(); - if (pauseMenu != null) pauseMenu.dispose(); + if (gameUi != null) gameUi.dispose(); if (frameBuffer != null) frameBuffer.dispose(); if (screenBatch != null) screenBatch.dispose(); } diff --git a/core/src/main/java/wtf/beatrice/retrorender/engine/FpsCameraController.java b/core/src/main/java/wtf/beatrice/retrorender/engine/FpsCameraController.java index 9d9a88d..d44b354 100644 --- a/core/src/main/java/wtf/beatrice/retrorender/engine/FpsCameraController.java +++ b/core/src/main/java/wtf/beatrice/retrorender/engine/FpsCameraController.java @@ -10,10 +10,9 @@ import com.badlogic.gdx.math.Vector3; public class FpsCameraController { private final PerspectiveCamera camera; + private final GameSettings settings; // movement + look - private float moveSpeed = 5f; // units / second - private float mouseSensitivity = 0.15f; private float yaw = 0f; private float pitch = 0f; @@ -45,10 +44,10 @@ public class FpsCameraController { private Cursor invisibleCursor; - public FpsCameraController(PerspectiveCamera camera) { + public FpsCameraController(PerspectiveCamera camera, GameSettings settings) { this.camera = camera; + this.settings = settings; - // default camera setup camera.position.set(0f, eyeHeight, 6f); camera.near = 0.1f; camera.far = 100f; @@ -128,8 +127,8 @@ public class FpsCameraController { // recenter for next frame Gdx.input.setCursorPosition(centerX, centerY); - float deltaX = -dx * mouseSensitivity; - float deltaY = -dy * mouseSensitivity; + float deltaX = -dx * settings.mouseSensitivity; + float deltaY = -dy * settings.mouseSensitivity; yaw += deltaX; pitch += deltaY; @@ -149,7 +148,9 @@ public class FpsCameraController { // right vector (perpendicular) tmpRight.set(tmpForward.z, 0f, -tmpForward.x).nor(); - float moveAmount = moveSpeed * delta; + camera.fieldOfView = settings.fov; + + float moveAmount = settings.moveSpeed * delta; float moveX = 0f; float moveZ = 0f; @@ -260,7 +261,4 @@ public class FpsCameraController { public float getYaw() { return yaw; } public float getPitch() { return pitch; } - - public void setMoveSpeed(float moveSpeed) { this.moveSpeed = moveSpeed; } - public void setMouseSensitivity(float mouseSensitivity) { this.mouseSensitivity = mouseSensitivity; } } diff --git a/core/src/main/java/wtf/beatrice/retrorender/engine/GameSettings.java b/core/src/main/java/wtf/beatrice/retrorender/engine/GameSettings.java new file mode 100644 index 0000000..7010ef1 --- /dev/null +++ b/core/src/main/java/wtf/beatrice/retrorender/engine/GameSettings.java @@ -0,0 +1,11 @@ +package wtf.beatrice.retrorender.engine; + +public class GameSettings { + + public float fov = 67f; // degrees + public float mouseSensitivity = 0.15f; + public float moveSpeed = 5f; + + public float minFov = 40f; + public float maxFov = 100f; +} diff --git a/core/src/main/java/wtf/beatrice/retrorender/engine/GameUi.java b/core/src/main/java/wtf/beatrice/retrorender/engine/GameUi.java new file mode 100644 index 0000000..53fe3c4 --- /dev/null +++ b/core/src/main/java/wtf/beatrice/retrorender/engine/GameUi.java @@ -0,0 +1,87 @@ +package wtf.beatrice.retrorender.engine; + +public class GameUi { + + public enum UiResult { + NONE, + RESUME, + OPEN_SETTINGS, + CLOSE_SETTINGS, + QUIT + } + + private final PauseMenu pauseMenu; + private final SettingsMenu settingsMenu; + private final GameSettings settings; + + public GameUi(GameSettings settings) { + this.settings = settings; + this.pauseMenu = new PauseMenu(); + this.settingsMenu = new SettingsMenu(); + + // sync initial settings + this.settingsMenu.setFov(settings.fov); + } + + public UiMode onEsc(UiMode current) { + switch (current) { + case GAMEPLAY: + return UiMode.PAUSE; + case PAUSE: + case SETTINGS: + return UiMode.GAMEPLAY; + default: + return UiMode.GAMEPLAY; + } + } + + public void render(int retroW, int retroH, UiMode mode) { + switch (mode) { + case PAUSE: + pauseMenu.render(retroW, retroH); + break; + case SETTINGS: + settingsMenu.render(retroW, retroH); + break; + case GAMEPLAY: + default: + break; + } + } + + public UiResult handleClick(float retroX, float retroY, UiMode mode) { + if (mode == UiMode.SETTINGS) { + boolean close = settingsMenu.handleClick(retroX, retroY); + // always sync FOV to settings + settings.fov = settingsMenu.getFov(); + + if (close) { + // Settings “Close” button clicked -> go back to PAUSE + return UiResult.CLOSE_SETTINGS; + } + return UiResult.NONE; + } + + if (mode == UiMode.PAUSE) { + PauseMenu.MenuAction action = pauseMenu.getActionAt(retroX, retroY); + return switch (action) + { + case RESUME -> UiResult.RESUME; + case QUIT -> UiResult.QUIT; + case SETTINGS -> UiResult.OPEN_SETTINGS; + default -> UiResult.NONE; + }; + } + + return UiResult.NONE; + } + + public void dispose() { + pauseMenu.dispose(); + settingsMenu.dispose(); + } + + public SettingsMenu getSettingsMenu() { + return settingsMenu; + } +} diff --git a/core/src/main/java/wtf/beatrice/retrorender/engine/PauseMenu.java b/core/src/main/java/wtf/beatrice/retrorender/engine/PauseMenu.java index 66b37d8..d94d4f8 100644 --- a/core/src/main/java/wtf/beatrice/retrorender/engine/PauseMenu.java +++ b/core/src/main/java/wtf/beatrice/retrorender/engine/PauseMenu.java @@ -22,6 +22,7 @@ public class PauseMenu { public enum MenuAction { NONE, RESUME, + SETTINGS, QUIT } @@ -62,9 +63,10 @@ public class PauseMenu { font = generator.generateFont(param); generator.dispose(); - // create buttons - buttons.add(new Button(" Resume ", MenuAction.RESUME)); - buttons.add(new Button(" Quit ", MenuAction.QUIT)); + // create buttons (ordered left → right) + buttons.add(new Button(" Resume ", MenuAction.RESUME)); + buttons.add(new Button(" Settings ", MenuAction.SETTINGS)); + buttons.add(new Button(" Quit ", MenuAction.QUIT)); // 1x1 pixel texture (white, we tint it) Pixmap pm = new Pixmap(1, 1, Pixmap.Format.RGBA8888); @@ -79,14 +81,14 @@ public class PauseMenu { batch.begin(); // --- black bar at bottom --- - float barH = 40f; // in retro pixels + float barH = 80f; // in retro pixels float barY = 0f; batch.setColor(0f, 0f, 0f, 0.9f); batch.draw(pixel, 0f, barY, width, barH); // --- buttons --- - float spacing = 8f; // horizontal space between buttons + float spacing = 10f; // horizontal space between buttons // measure each button label GlyphLayout layout = new GlyphLayout(); @@ -96,7 +98,7 @@ public class PauseMenu { for (Button b : buttons) { layout.setText(font, b.label); float bw = layout.width + 16f; // padding - float bh = layout.height + 8f; + float bh = layout.height + 12f; b.w = bw; b.h = bh; totalWidth += bw; diff --git a/core/src/main/java/wtf/beatrice/retrorender/engine/RetroViewportHelper.java b/core/src/main/java/wtf/beatrice/retrorender/engine/RetroViewportHelper.java new file mode 100644 index 0000000..bdf051c --- /dev/null +++ b/core/src/main/java/wtf/beatrice/retrorender/engine/RetroViewportHelper.java @@ -0,0 +1,60 @@ +package wtf.beatrice.retrorender.engine; + +public class RetroViewportHelper { + + public static class RetroViewport { + public int offsetX, offsetY; + public int drawW, drawH; + public float scale; + } + + public static class RetroClick { + public boolean inside; + public float x, y; // retro coords + } + + public static RetroViewport computeViewport( + int windowW, int windowH, + int retroW, int retroH) { + + RetroViewport vp = new RetroViewport(); + + float scale = Math.min( + windowW / (float) retroW, + windowH / (float) retroH + ); + + vp.scale = scale; + vp.drawW = Math.round(retroW * scale); + vp.drawH = Math.round(retroH * scale); + vp.offsetX = (windowW - vp.drawW) / 2; + vp.offsetY = (windowH - vp.drawH) / 2; + + return vp; + } + + public static RetroClick toRetroCoords( + RetroViewport vp, + int retroW, int retroH, + int mouseX, int mouseYWindow, + int windowHeight) { + + RetroClick rc = new RetroClick(); + // libGDX gives mouse from top-left; you already invert Y like this: + int yBottomOrigin = windowHeight - mouseYWindow; + + if (mouseX < vp.offsetX || mouseX > vp.offsetX + vp.drawW || + yBottomOrigin < vp.offsetY || yBottomOrigin > vp.offsetY + vp.drawH) { + rc.inside = false; + return rc; + } + + float relX = (mouseX - vp.offsetX) / (float) vp.drawW; + float relY = (yBottomOrigin - vp.offsetY) / (float) vp.drawH; + + rc.inside = true; + rc.x = relX * retroW; + rc.y = relY * retroH; + return rc; + } +} diff --git a/core/src/main/java/wtf/beatrice/retrorender/engine/SettingsMenu.java b/core/src/main/java/wtf/beatrice/retrorender/engine/SettingsMenu.java new file mode 100644 index 0000000..8f21db4 --- /dev/null +++ b/core/src/main/java/wtf/beatrice/retrorender/engine/SettingsMenu.java @@ -0,0 +1,219 @@ +package wtf.beatrice.retrorender.engine; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; +import com.badlogic.gdx.math.MathUtils; + +public class SettingsMenu { + + private final SpriteBatch batch; + private final BitmapFont font; + private final Texture pixel; + + // FOV value stored here, GameScreen syncs it to the camera + private float fov; + private final float minFov = 40f; + private final float maxFov = 100f; + private final float fovStep = 2f; + + // button / hit areas + private float fovDecX, fovDecY, fovDecW, fovDecH; + private float fovIncX, fovIncY, fovIncW, fovIncH; + private float closeX, closeY, closeW, closeH; + + public SettingsMenu() { + batch = new SpriteBatch(); + + FreeTypeFontGenerator generator = + new FreeTypeFontGenerator(Gdx.files.internal("fonts/red-hat-mono.ttf")); + FreeTypeFontGenerator.FreeTypeFontParameter param = + new FreeTypeFontGenerator.FreeTypeFontParameter(); + + param.size = 12; + param.color = Color.WHITE; + param.mono = true; + param.hinting = FreeTypeFontGenerator.Hinting.None; + param.borderWidth = 0.2f; + param.borderColor = Color.WHITE; + param.shadowOffsetX = 0; + param.shadowOffsetY = 0; + param.minFilter = Texture.TextureFilter.Nearest; + param.magFilter = Texture.TextureFilter.Nearest; + + font = generator.generateFont(param); + generator.dispose(); + + // 1x1 pixel + Pixmap pm = new Pixmap(1, 1, Pixmap.Format.RGBA8888); + pm.setColor(1f, 1f, 1f, 1f); + pm.fill(); + pixel = new Texture(pm); + pm.dispose(); + + // default FOV + fov = 67f; + } + + public void setFov(float fov) { + this.fov = MathUtils.clamp(fov, minFov, maxFov); + } + + public float getFov() { + return fov; + } + + /** + * @param width RETRO_WIDTH + * @param height RETRO_HEIGHT + */ + public void render(int width, int height) { + batch.getProjectionMatrix().setToOrtho2D(0, 0, width, height); + batch.begin(); + + GlyphLayout layout = new GlyphLayout(); + + // --- central panel --- + float panelW = 200f; + float panelH = 220f; + float panelX = (width - panelW) / 2f; + float panelY = (height - panelH) / 2f; + + // background + batch.setColor(0f, 0f, 0f, 0.9f); + batch.draw(pixel, panelX, panelY, panelW, panelH); + + // border + batch.setColor(1f, 1f, 1f, 1f); + float border = 1f; + + // --- title --- + String title = "Settings"; + layout.setText(font, title); + float titleX = panelX + (panelW - layout.width) / 2f; + float titleY = panelY + panelH - 10f; + font.draw(batch, layout, titleX, titleY); + + // small separator line under title + batch.draw(pixel, panelX + 8f, titleY - 14f, panelW - 16f, 1f); + + // --- FOV row --- + float rowY = panelY + panelH - 50f; + float rowH = 18f; + + // label + String fovLabel = "FOV"; + layout.setText(font, fovLabel); + float labelX = panelX + 12f; + float labelY = rowY + rowH - 4f; + font.draw(batch, layout, labelX, labelY); + + // buttons + value area + fovDecW = 20f; + fovDecH = rowH; + fovDecX = panelX + 80f; + fovDecY = rowY; + + fovIncW = 20f; + fovIncH = rowH; + fovIncX = panelX + panelW - 32f; + fovIncY = rowY; + + // draw dec button "<" + drawButtonWithLabel("<", fovDecX, fovDecY, fovDecW, fovDecH); + + // draw inc button ">" + drawButtonWithLabel(">", fovIncX, fovIncY, fovIncW, fovIncH); + + // numeric value centered between dec/inc + String fovText = String.format("%3.0f°", fov); + layout.setText(font, fovText); + + float valueCenter = (fovDecX + fovDecW + fovIncX) / 2f; + float valueX = valueCenter - layout.width / 2f; + float valueY = rowY + rowH - 4f; + font.draw(batch, layout, valueX, valueY); + + // --- Close button at bottom --- + String closeLabel = " Close "; + layout.setText(font, closeLabel); + closeW = layout.width + 16f; + closeH = layout.height + 8f; + closeX = panelX + (panelW - closeW) / 2f; + closeY = panelY + 16f; + + // button bg + border + batch.setColor(0.1f, 0.1f, 0.1f, 1f); + batch.draw(pixel, closeX, closeY, closeW, closeH); + batch.setColor(1f, 1f, 1f, 1f); + // border + batch.draw(pixel, closeX, closeY + closeH - border, closeW, border); + batch.draw(pixel, closeX, closeY, closeW, border); + batch.draw(pixel, closeX, closeY, border, closeH); + batch.draw(pixel, closeX + closeW - border, closeY, border, closeH); + + float closeTextX = closeX + (closeW - layout.width) / 2f; + float closeTextY = closeY + closeH - (closeH - layout.height) / 2f - 2f; + font.draw(batch, closeLabel, closeTextX, closeTextY); + + batch.end(); + } + + private void drawButtonWithLabel(String text, float x, float y, float w, float h) { + // background + batch.setColor(0.1f, 0.1f, 0.1f, 1f); + batch.draw(pixel, x, y, w, h); + // border + batch.setColor(1f, 1f, 1f, 1f); + float border = 1f; + batch.draw(pixel, x, y + h - border, w, border); + batch.draw(pixel, x, y, w, border); + batch.draw(pixel, x, y, border, h); + batch.draw(pixel, x + w - border, y, border, h); + + GlyphLayout layout = new GlyphLayout(font, text); + float tx = x + (w - layout.width) / 2f; + float ty = y + h - (h - layout.height) / 2f - 2f; + font.draw(batch, layout, tx, ty); + } + + /** + * Handle a click in RETRO coords. + * + * @return true if the menu wants to close (Close button clicked) + */ + public boolean handleClick(float x, float y) { + // FOV - + if (x >= fovDecX && x <= fovDecX + fovDecW && + y >= fovDecY && y <= fovDecY + fovDecH) { + fov = MathUtils.clamp(fov - fovStep, minFov, maxFov); + return false; + } + + // FOV + + if (x >= fovIncX && x <= fovIncX + fovIncW && + y >= fovIncY && y <= fovIncY + fovIncH) { + fov = MathUtils.clamp(fov + fovStep, minFov, maxFov); + return false; + } + + // Close + if (x >= closeX && x <= closeX + closeW && + y >= closeY && y <= closeY + closeH) { + return true; + } + + return false; + } + + public void dispose() { + batch.dispose(); + font.dispose(); + pixel.dispose(); + } +} diff --git a/core/src/main/java/wtf/beatrice/retrorender/engine/UiMode.java b/core/src/main/java/wtf/beatrice/retrorender/engine/UiMode.java new file mode 100644 index 0000000..96d73de --- /dev/null +++ b/core/src/main/java/wtf/beatrice/retrorender/engine/UiMode.java @@ -0,0 +1,7 @@ +package wtf.beatrice.retrorender.engine; + +public enum UiMode { + GAMEPLAY, + PAUSE, // only bottom bar + SETTINGS // pause bar + center settings +}