feat(scene): implement transition

Should work :D
This commit is contained in:
2025-09-30 01:02:46 +07:00
parent c4c8235f45
commit 24f09bf303
5 changed files with 127 additions and 15 deletions

View File

@ -1,18 +1,34 @@
package org.vibecoders.moongazer; package org.vibecoders.moongazer;
import org.slf4j.Logger;
import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
public class Assets { public class Assets {
private static final AssetManager assetManager = new AssetManager(); private static final AssetManager assetManager = new AssetManager();
private static final Logger log = org.slf4j.LoggerFactory.getLogger(Assets.class);
public static <T> T getAsset(String fileName, Class<T> type) { public static <T> T getAsset(String fileName, Class<T> type) {
return assetManager.get(fileName, type); return assetManager.get(fileName, type);
} }
public static void loadAll() { /**
// We load all assets here for simplicity :) * Loads assets required for the intro scene only.
*
* This is used to load the logo before the main assets are loaded.
*/
public static void loadIntroAndWait() {
assetManager.load("icons/logo.png", Texture.class); assetManager.load("icons/logo.png", Texture.class);
waitUntilLoaded();
}
public static void loadAll() {
log.info("Loading all assets....");
log.warn("stub");
}
public static void waitUntilLoaded() {
assetManager.finishLoading(); assetManager.finishLoading();
} }

View File

@ -1,5 +1,9 @@
package org.vibecoders.moongazer; package org.vibecoders.moongazer;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
/** /**
* Client configuration constants and default values * Client configuration constants and default values
* used throughout the Moongazer client application. * used throughout the Moongazer client application.
@ -12,4 +16,12 @@ public class Constants {
public static final int WINDOW_WIDTH = 1280; public static final int WINDOW_WIDTH = 1280;
public static final int WINDOW_HEIGHT = 720; public static final int WINDOW_HEIGHT = 720;
public static final String WINDOW_TITLE = "Moongazer"; 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();
}});
} }

View File

@ -11,28 +11,38 @@ import org.vibecoders.moongazer.scene.*;
public class Game extends ApplicationAdapter { public class Game extends ApplicationAdapter {
private static final Logger log = LoggerFactory.getLogger(Game.class); private static final Logger log = LoggerFactory.getLogger(Game.class);
public static State state = State.INTRO; public static State state = State.INTRO;
public static Transition transition = null;
SpriteBatch batch; SpriteBatch batch;
Texture logo; Texture logo;
Scene currentScene; Scene currentScene;
Scene introScene; Scene introScene;
public static Scene mainMenuScene;
@Override @Override
public void create() { public void create() {
log.info("Loading assets..."); log.info("Loading intro assets...");
Assets.loadAll(); Assets.loadIntroAndWait();
log.info("Assets loaded successfully."); log.info("Intro assets loaded successfully.");
batch = new SpriteBatch(); batch = new SpriteBatch();
currentScene = introScene = new Intro(); currentScene = introScene = new Intro();
mainMenuScene = new MainMenu();
} }
@Override @Override
public void render() { public void render() {
// Handle transition if any
if (transition != null) {
batch.begin();
transition.render(batch);
batch.end();
return;
}
switch (Game.state) { switch (Game.state) {
case INTRO: case INTRO:
currentScene = introScene; currentScene = introScene;
break; break;
case MAIN_MENU: case MAIN_MENU:
// Render main menu scene currentScene = mainMenuScene;
break; break;
case IN_GAME: case IN_GAME:
// Render in-game scene // Render in-game scene
@ -48,6 +58,7 @@ public class Game extends ApplicationAdapter {
@Override @Override
public void dispose() { public void dispose() {
introScene.dispose(); introScene.dispose();
mainMenuScene.dispose();
Assets.dispose(); Assets.dispose();
log.debug("Resources disposed"); log.debug("Resources disposed");
} }

View File

@ -1,36 +1,57 @@
package org.vibecoders.moongazer.scene; package org.vibecoders.moongazer.scene;
import static org.vibecoders.moongazer.Constants.WINDOW_HEIGHT; import static org.vibecoders.moongazer.Constants.*;
import static org.vibecoders.moongazer.Constants.WINDOW_WIDTH;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.vibecoders.moongazer.Assets; import org.vibecoders.moongazer.Assets;
import org.vibecoders.moongazer.Game;
import org.vibecoders.moongazer.State;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.ScreenUtils; import com.badlogic.gdx.utils.ScreenUtils;
/**
* Intro scene displaying the game logo and handling asset loading.
*/
public class Intro extends Scene { public class Intro extends Scene {
private Texture logo; private Texture logo;
private long startTime; private long startTime;
private long endTime = 0; private long endTime = 0;
private static final Logger log = LoggerFactory.getLogger(Intro.class); private static final Logger log = LoggerFactory.getLogger(Intro.class);
/**
* Initializes the intro scene, starts loading assets.
*/
public Intro() { public Intro() {
logo = Assets.getAsset("icons/logo.png", Texture.class); logo = Assets.getAsset("icons/logo.png", Texture.class);
startTime = System.currentTimeMillis() + 500; startTime = System.currentTimeMillis() + 500;
log.info("Starting to load all remaining assets...");
Assets.loadAll();
} }
/**
* Renders the intro scene.
* @param batch The SpriteBatch to draw with.
*/
@Override
public void render(SpriteBatch batch) { public void render(SpriteBatch batch) {
if (System.currentTimeMillis() > endTime + 2000 && endTime != 0) {
Assets.waitUntilLoaded();
if (Game.transition == null) {
Game.transition = new Transition(this, Game.mainMenuScene, State.MAIN_MENU, 1000);
}
batch.draw(TEXTURE_BLACK, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
return;
}
ScreenUtils.clear(Color.BLACK); ScreenUtils.clear(Color.BLACK);
log.debug("Rendering logo at position: ({}, {})", WINDOW_WIDTH / 2 - logo.getWidth() / 4, // log.debug("Rendering logo at position: ({}, {})", WINDOW_WIDTH / 2 - logo.getWidth() / 4, WINDOW_HEIGHT / 2 - logo.getHeight() / 4);
WINDOW_HEIGHT / 2 - logo.getHeight() / 4);
var currentOpacity = (float) (System.currentTimeMillis() - startTime) / 1000; var currentOpacity = (float) (System.currentTimeMillis() - startTime) / 1000;
if (currentOpacity > 1) { if (currentOpacity > 1) {
if (endTime == 0) { if (endTime == 0) {
endTime = System.currentTimeMillis() + 3000; endTime = System.currentTimeMillis() + 2000;
} }
currentOpacity = 1 - ((float) (System.currentTimeMillis() - endTime) / 1000); currentOpacity = 1 - ((float) (System.currentTimeMillis() - endTime) / 1000);
} }
@ -38,8 +59,4 @@ public class Intro extends Scene {
batch.draw(logo, WINDOW_WIDTH / 2 - logo.getWidth() / 4, WINDOW_HEIGHT / 2 - logo.getHeight() / 4, batch.draw(logo, WINDOW_WIDTH / 2 - logo.getWidth() / 4, WINDOW_HEIGHT / 2 - logo.getHeight() / 4,
logo.getWidth() / 2, logo.getHeight() / 2); logo.getWidth() / 2, logo.getHeight() / 2);
} }
public void dispose() {
log.debug("sybau");
}
} }

View File

@ -0,0 +1,56 @@
package org.vibecoders.moongazer.scene;
import org.slf4j.Logger;
import org.vibecoders.moongazer.Game;
import org.vibecoders.moongazer.State;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
/**
* Handles transitions between scenes with a linear transition effect.
*/
public class Transition extends Scene {
private Scene from;
private Scene to;
private State targetState;
private long startTime;
private long duration;
private static final Logger log = org.slf4j.LoggerFactory.getLogger(Transition.class);
/**
* Creates a new transition between two scenes.
* @param from The scene to transition from.
* @param to The scene to transition to.
* @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) {
this.from = from;
this.to = to;
this.targetState = targetState;
this.duration = duration;
startTime = System.currentTimeMillis();
}
/**
* Renders the transition effect.
* @param batch The SpriteBatch to draw with.
*/
@Override
public void render(SpriteBatch batch) {
var toOpacity = ((float) (System.currentTimeMillis() - startTime)) / duration;
if (toOpacity >= 0.99) {
log.debug("Transition complete to state: {}", targetState);
Game.state = targetState;
Game.transition = null;
return;
}
var fromOpacity = 1 - toOpacity;
log.debug("Transition opacities - from: {}, to: {}", fromOpacity, toOpacity);
batch.setColor(1, 1, 1, fromOpacity);
from.render(batch);
batch.setColor(1, 1, 1, toOpacity);
to.render(batch);
}
}