diff --git a/app/src/main/java/org/vibecoders/moongazer/Constants.java b/app/src/main/java/org/vibecoders/moongazer/Constants.java index 4040289..4fc6b71 100644 --- a/app/src/main/java/org/vibecoders/moongazer/Constants.java +++ b/app/src/main/java/org/vibecoders/moongazer/Constants.java @@ -16,12 +16,4 @@ public class Constants { public static final int WINDOW_WIDTH = 1280; public static final int WINDOW_HEIGHT = 720; public static final String WINDOW_TITLE = "Moongazer"; - public static final Texture TEXTURE_WHITE = new Texture(new Pixmap(1, 1, Pixmap.Format.RGBA8888) {{ - setColor(Color.WHITE); - fill(); - }}); - public static final Texture TEXTURE_BLACK = new Texture(new Pixmap(1, 1, Pixmap.Format.RGBA8888) {{ - setColor(Color.BLACK); - fill(); - }}); } diff --git a/app/src/main/java/org/vibecoders/moongazer/Game.java b/app/src/main/java/org/vibecoders/moongazer/Game.java index 6218785..c7ab57e 100644 --- a/app/src/main/java/org/vibecoders/moongazer/Game.java +++ b/app/src/main/java/org/vibecoders/moongazer/Game.java @@ -1,8 +1,13 @@ package org.vibecoders.moongazer; import com.badlogic.gdx.ApplicationAdapter; -import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.badlogic.gdx.utils.viewport.ScreenViewport; + +import java.util.ArrayList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,13 +16,17 @@ import org.vibecoders.moongazer.scenes.*; public class Game extends ApplicationAdapter { private static final Logger log = LoggerFactory.getLogger(Game.class); - public static State state = State.INTRO; - public static Transition transition = null; + public State state = State.INTRO; + public Transition transition = null; SpriteBatch batch; - Texture logo; + // UI stage + public Stage stage; + public Table root; + // Scenes Scene currentScene; Scene introScene; - public static Scene mainMenuScene; + public Scene mainMenuScene; + public ArrayList gameScenes; @Override public void create() { @@ -25,7 +34,16 @@ public class Game extends ApplicationAdapter { Assets.loadIntroAndWait(); log.info("Intro assets loaded successfully."); batch = new SpriteBatch(); - currentScene = introScene = new Intro(); + // Stage for UI elements + stage = new Stage(new ScreenViewport(), batch); + Gdx.input.setInputProcessor(stage); + root = new Table(); + root.setFillParent(true); + stage.addActor(root); + // Scene initialization + gameScenes = new ArrayList<>(); + currentScene = introScene = new Intro(this); + gameScenes.add(introScene); // By the end of the intro, the main menu scene will be created and assigned to Game.mainMenuScene } @@ -36,9 +54,12 @@ public class Game extends ApplicationAdapter { batch.begin(); transition.render(batch); batch.end(); + // Handle stage drawing for UI elements + stage.act(Gdx.graphics.getDeltaTime()); + stage.draw(); return; } - switch (Game.state) { + switch (this.state) { case INTRO: currentScene = introScene; break; @@ -51,9 +72,26 @@ public class Game extends ApplicationAdapter { default: log.warn("Unknown state: {}", state); } + + for (var scene : gameScenes) { + // log.trace("Checking scene visibility: {}", scene.getClass().getSimpleName()); + if (scene != currentScene && scene.root.isVisible()) { + log.trace("Hiding scene: {}", scene.getClass().getSimpleName()); + scene.root.setVisible(false); + } + } + + if (!currentScene.root.isVisible()) { + log.trace("Showing current scene: {}", currentScene.getClass().getSimpleName()); + currentScene.root.setVisible(true); + } + batch.begin(); currentScene.render(batch); batch.end(); + // Handle stage drawing for UI elements + stage.act(Gdx.graphics.getDeltaTime()); + stage.draw(); } @Override @@ -61,6 +99,8 @@ public class Game extends ApplicationAdapter { introScene.dispose(); mainMenuScene.dispose(); Assets.dispose(); + batch.dispose(); + stage.dispose(); log.debug("Resources disposed"); } } diff --git a/app/src/main/java/org/vibecoders/moongazer/Main.java b/app/src/main/java/org/vibecoders/moongazer/Main.java index 9013301..a49e8e3 100644 --- a/app/src/main/java/org/vibecoders/moongazer/Main.java +++ b/app/src/main/java/org/vibecoders/moongazer/Main.java @@ -2,6 +2,8 @@ package org.vibecoders.moongazer; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration.GLEmulation; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.vibecoders.moongazer.Constants.*; @@ -20,6 +22,7 @@ public class Main { */ public static void main(String[] args) { Lwjgl3ApplicationConfiguration cfg = new Lwjgl3ApplicationConfiguration(); + cfg.setOpenGLEmulation(GLEmulation.GL32, 3, 2); cfg.setTitle(WINDOW_TITLE); cfg.setWindowedMode(WINDOW_WIDTH, WINDOW_HEIGHT); cfg.useVsync(true); diff --git a/app/src/main/java/org/vibecoders/moongazer/managers/Assets.java b/app/src/main/java/org/vibecoders/moongazer/managers/Assets.java index 49194de..794ca52 100644 --- a/app/src/main/java/org/vibecoders/moongazer/managers/Assets.java +++ b/app/src/main/java/org/vibecoders/moongazer/managers/Assets.java @@ -5,6 +5,8 @@ import org.slf4j.Logger; import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.assets.loaders.FileHandleResolver; import com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver; +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.freetype.FreeTypeFontGeneratorLoader; @@ -19,9 +21,21 @@ public class Assets { private static final ArrayList loadedFonts = new ArrayList<>(); private static boolean startLoadAll = false; private static boolean loadedAll = false; + private static Texture textureWhite; + private static Texture textureBlack; public static T getAsset(String fileName, Class type) { - return assetManager.get(fileName, type); + try { + if (!assetManager.isLoaded(fileName, type)) { + log.warn("Asset not loaded: {}", fileName); + assetManager.load(fileName, type); + assetManager.finishLoadingAsset(fileName); + } + return assetManager.get(fileName, type); + } catch (Exception e) { + log.error("Failed to load asset: {}", fileName, e); + throw new RuntimeException("Asset loading failed: " + fileName, e); + } } /** @@ -85,8 +99,7 @@ public class Assets { public static void waitUntilLoaded() { assetManager.finishLoading(); - if (startLoadAll) { - log.info("All assets loaded."); + if (startLoadAll) {; loadedAll = true; } } @@ -95,7 +108,37 @@ public class Assets { return assetManager; } + public static Texture getWhiteTexture() { + if (textureWhite == null) { + Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888); + pixmap.setColor(Color.WHITE); + pixmap.fill(); + textureWhite = new Texture(pixmap); + pixmap.dispose(); // Important: dispose pixmap after creating texture + } + return textureWhite; + } + + public static Texture getBlackTexture() { + if (textureBlack == null) { + Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888); + pixmap.setColor(Color.BLACK); + pixmap.fill(); + textureBlack = new Texture(pixmap); + pixmap.dispose(); + } + return textureBlack; + } + public static void dispose() { assetManager.dispose(); + if (textureWhite != null) { + textureWhite.dispose(); + textureWhite = null; + } + if (textureBlack != null) { + textureBlack.dispose(); + textureBlack = null; + } } } diff --git a/app/src/main/java/org/vibecoders/moongazer/scenes/Intro.java b/app/src/main/java/org/vibecoders/moongazer/scenes/Intro.java index 1d8c31b..a0ca145 100644 --- a/app/src/main/java/org/vibecoders/moongazer/scenes/Intro.java +++ b/app/src/main/java/org/vibecoders/moongazer/scenes/Intro.java @@ -16,17 +16,21 @@ import com.badlogic.gdx.utils.ScreenUtils; */ public class Intro extends Scene { private Texture logo; + private Game game; private long startTime; private long endTime = 0; /** * Initializes the intro scene, starts loading assets. */ - public Intro() { + public Intro(Game game) { + this.game = game; logo = Assets.getAsset("icons/logo.png", Texture.class); startTime = System.currentTimeMillis() + 500; log.info("Starting to load all remaining assets..."); Assets.loadAll(); + game.mainMenuScene = new MainMenu(game); + game.gameScenes.add(game.mainMenuScene); } /** @@ -36,12 +40,12 @@ public class Intro extends Scene { @Override public void render(SpriteBatch batch) { if (System.currentTimeMillis() > endTime + 2000 && endTime != 0) { - if (Game.transition == null) { + if (game.transition == null) { Assets.waitUntilLoaded(); - Game.mainMenuScene = new MainMenu(); - Game.transition = new Transition(this, Game.mainMenuScene, State.MAIN_MENU, 1000); + log.info("All assets loaded successfully."); + game.transition = new Transition(game, this, game.mainMenuScene, State.MAIN_MENU, 1000); } - batch.draw(TEXTURE_BLACK, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); + batch.draw(Assets.getBlackTexture(), 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); return; } ScreenUtils.clear(Color.BLACK); diff --git a/app/src/main/java/org/vibecoders/moongazer/scenes/MainMenu.java b/app/src/main/java/org/vibecoders/moongazer/scenes/MainMenu.java index 7630f40..4c867c8 100644 --- a/app/src/main/java/org/vibecoders/moongazer/scenes/MainMenu.java +++ b/app/src/main/java/org/vibecoders/moongazer/scenes/MainMenu.java @@ -3,6 +3,7 @@ package org.vibecoders.moongazer.scenes; import static org.vibecoders.moongazer.Constants.*; import org.vibecoders.moongazer.managers.Assets; +import org.vibecoders.moongazer.Game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; diff --git a/app/src/main/java/org/vibecoders/moongazer/scenes/Scene.java b/app/src/main/java/org/vibecoders/moongazer/scenes/Scene.java index e7c8f95..9d793e8 100644 --- a/app/src/main/java/org/vibecoders/moongazer/scenes/Scene.java +++ b/app/src/main/java/org/vibecoders/moongazer/scenes/Scene.java @@ -1,13 +1,20 @@ package org.vibecoders.moongazer.scenes; import org.slf4j.Logger; +import org.vibecoders.moongazer.Game; import org.vibecoders.moongazer.managers.Assets; import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.scenes.scene2d.ui.Table; public abstract class Scene { protected final Logger log = org.slf4j.LoggerFactory.getLogger(getClass()); + public Table root; + public Scene(Game game) { + this(); + } public Scene() { + root = new Table(); if (!Assets.isLoadedAll() && Assets.isStartLoadAll()) { Assets.waitUntilLoaded(); } diff --git a/app/src/main/java/org/vibecoders/moongazer/scenes/Transition.java b/app/src/main/java/org/vibecoders/moongazer/scenes/Transition.java index 3309fb2..ab8d63d 100644 --- a/app/src/main/java/org/vibecoders/moongazer/scenes/Transition.java +++ b/app/src/main/java/org/vibecoders/moongazer/scenes/Transition.java @@ -9,6 +9,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch; * Handles transitions between scenes with a linear transition effect. */ public class Transition extends Scene { + private Game game; private Scene from; private Scene to; private State targetState; @@ -22,7 +23,10 @@ public class Transition extends Scene { * @param targetState The target state of the game after the transition. * @param duration The duration of the transition in milliseconds. */ - public Transition(Scene from, Scene to, State targetState, long duration) { + public Transition(Game game, Scene from, Scene to, State targetState, long duration) { + // Transition does not need to render UI elements + this.root = null; + this.game = game; this.from = from; this.to = to; this.targetState = targetState; @@ -39,15 +43,17 @@ public class Transition extends Scene { var toOpacity = ((float) (System.currentTimeMillis() - startTime)) / duration; if (toOpacity >= 0.99) { log.trace("Transition complete to state: {}", targetState); - Game.state = targetState; - Game.transition = null; + game.state = targetState; + game.transition = null; return; } var fromOpacity = 1 - toOpacity; log.trace("Transition opacities - from: {}, to: {}", fromOpacity, toOpacity); batch.setColor(1, 1, 1, fromOpacity); + from.root.setVisible(true); from.render(batch); batch.setColor(1, 1, 1, toOpacity); + to.root.setVisible(true); to.render(batch); } }