feat: New scenes
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -23,6 +23,8 @@
|
||||
<version>1.18.38</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<source>25</source>
|
||||
<target>25</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
@@ -152,4 +154,4 @@
|
||||
<version>6.1.1-1.5.10</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package cz.jzitnik.events;
|
||||
|
||||
import cz.jzitnik.utils.events.Event;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class PlayVideo implements Event {
|
||||
private String fileName;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package cz.jzitnik.events.handlers;
|
||||
|
||||
import com.googlecode.lanterna.TextColor;
|
||||
import com.googlecode.lanterna.screen.Screen;
|
||||
import com.googlecode.lanterna.screen.TerminalScreen;
|
||||
import cz.jzitnik.annotations.EventHandler;
|
||||
import cz.jzitnik.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.annotations.injectors.InjectState;
|
||||
import cz.jzitnik.events.PlayVideo;
|
||||
import cz.jzitnik.game.ResourceManager;
|
||||
import cz.jzitnik.states.TerminalState;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
import cz.jzitnik.utils.events.AbstractEventHandler;
|
||||
import org.bytedeco.javacv.FFmpegFrameGrabber;
|
||||
import org.bytedeco.javacv.Frame;
|
||||
import org.bytedeco.javacv.Java2DFrameConverter;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
@EventHandler(PlayVideo.class)
|
||||
public class PlayVideoHandler extends AbstractEventHandler<PlayVideo> {
|
||||
public PlayVideoHandler(DependencyManager dm) {
|
||||
super(dm);
|
||||
}
|
||||
|
||||
@InjectDependency
|
||||
private ResourceManager resourceManager;
|
||||
|
||||
@InjectState
|
||||
private TerminalState terminalState;
|
||||
|
||||
@Override
|
||||
public void handle(PlayVideo event) {
|
||||
}
|
||||
|
||||
|
||||
private static TextColor.RGB toColor(int rgb) {
|
||||
int r = (rgb >> 16) & 0xFF;
|
||||
int g = (rgb >> 8) & 0xFF;
|
||||
int b = rgb & 0xFF;
|
||||
return new TextColor.RGB(r, g, b);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import cz.jzitnik.annotations.EventHandler;
|
||||
import cz.jzitnik.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.annotations.injectors.InjectState;
|
||||
import cz.jzitnik.events.FullRoomDraw;
|
||||
import cz.jzitnik.events.PlayVideo;
|
||||
import cz.jzitnik.events.TerminalResizeEvent;
|
||||
import cz.jzitnik.game.GameState;
|
||||
import cz.jzitnik.states.ScreenBuffer;
|
||||
@@ -32,6 +31,8 @@ public class TerminalResizeEventHandler extends AbstractEventHandler<TerminalRes
|
||||
@InjectState
|
||||
private GameState gameState;
|
||||
|
||||
private boolean screenRerendering = false;
|
||||
|
||||
@Override
|
||||
public void handle(TerminalResizeEvent event) {
|
||||
TerminalSize size = event.getNewSize();
|
||||
@@ -47,7 +48,13 @@ public class TerminalResizeEventHandler extends AbstractEventHandler<TerminalRes
|
||||
screenBuffer.setRenderedBuffer(buffer);
|
||||
|
||||
if (gameState.getScreen() != null) {
|
||||
gameState.getScreen().fullRender();
|
||||
if (screenRerendering) {
|
||||
return;
|
||||
} else {
|
||||
screenRerendering = true;
|
||||
gameState.getScreen().fullRender();
|
||||
screenRerendering = false;
|
||||
}
|
||||
} else {
|
||||
eventManager.emitEvent(new FullRoomDraw(true));
|
||||
}
|
||||
|
||||
@@ -60,6 +60,19 @@ public class ResourceManager {
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage getResource(String path) {
|
||||
InputStream is = classLoader.getResourceAsStream(path);
|
||||
if (is == null) {
|
||||
throw new RuntimeException("Image not found in resources!");
|
||||
}
|
||||
|
||||
try {
|
||||
return ImageIO.read(is);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getResourceAsStream(String path) {
|
||||
return classLoader.getResourceAsStream(path);
|
||||
}
|
||||
|
||||
77
src/main/java/cz/jzitnik/game/setup/GameMenuScene.java
Normal file
77
src/main/java/cz/jzitnik/game/setup/GameMenuScene.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package cz.jzitnik.game.setup;
|
||||
|
||||
import com.googlecode.lanterna.input.KeyType;
|
||||
import cz.jzitnik.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.annotations.injectors.InjectState;
|
||||
import cz.jzitnik.events.FullRoomDraw;
|
||||
import cz.jzitnik.events.KeyboardPressEvent;
|
||||
import cz.jzitnik.events.MouseAction;
|
||||
import cz.jzitnik.game.GameState;
|
||||
import cz.jzitnik.screens.Screen;
|
||||
import cz.jzitnik.screens.scenes.BasicImageScene;
|
||||
import cz.jzitnik.screens.scenes.Scene;
|
||||
import cz.jzitnik.sound.SoundPlayer;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
import cz.jzitnik.utils.events.EventManager;
|
||||
|
||||
public class GameMenuScene extends Scene {
|
||||
private static class GameMenuScreen extends Screen {
|
||||
protected final SoundPlayer soundPlayer = new SoundPlayer();
|
||||
protected boolean play = true;
|
||||
|
||||
@Override
|
||||
public void fullRender() {
|
||||
// No render here just basic audio playback
|
||||
new Thread(() -> {
|
||||
while (play) {
|
||||
soundPlayer.playSound("audio/menu.ogg", 30, 100);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMouseAction(MouseAction event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleKeyboardAction(KeyboardPressEvent event) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ImageScene extends BasicImageScene {
|
||||
@InjectState
|
||||
private GameState gameState;
|
||||
|
||||
@InjectDependency
|
||||
private EventManager eventManager;
|
||||
|
||||
private final GameMenuScreen gameMenuScreen;
|
||||
|
||||
public ImageScene(String filePath, GameMenuScreen gameMenuScreen) {
|
||||
super(filePath);
|
||||
this.gameMenuScreen = gameMenuScreen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleKeyboardAction(KeyboardPressEvent event) {
|
||||
if (event.getKeyStroke().getKeyType() == KeyType.Enter) {
|
||||
gameMenuScreen.play = false;
|
||||
gameMenuScreen.soundPlayer.stopCurrentSound();
|
||||
gameState.setScreen(null);
|
||||
eventManager.emitEvent(new FullRoomDraw(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GameMenuScene(DependencyManager dependencyManager) {
|
||||
GameMenuScreen gameMenuScreen = new GameMenuScreen();
|
||||
ImageScene basicImageScene = new ImageScene("menu.png", gameMenuScreen);
|
||||
|
||||
super(new Screen[]{gameMenuScreen, basicImageScene}, new OnEndAction.Repeat());
|
||||
|
||||
dependencyManager.inject(this);
|
||||
dependencyManager.inject(basicImageScene);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import cz.jzitnik.game.items.GameItem;
|
||||
import cz.jzitnik.game.items.WoodenSword;
|
||||
import cz.jzitnik.game.objects.Chest;
|
||||
import cz.jzitnik.game.utils.RoomCords;
|
||||
import cz.jzitnik.screens.scenes.IntroScene;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
|
||||
@Dependency
|
||||
@@ -31,9 +30,13 @@ public class GameSetup {
|
||||
GameRoom mainRoom = new GameRoom(ResourceManager.Resource.ROOM1);
|
||||
GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2);
|
||||
GameRoom topRightRoom = new GameRoom(ResourceManager.Resource.ROOM3);
|
||||
GameRoom topRightTop = new GameRoom(ResourceManager.Resource.ROOM4);
|
||||
GameRoom topRightTopLeft = new GameRoom(ResourceManager.Resource.ROOM_FROZEN);
|
||||
|
||||
mainRoom.setRight(rightRoom);
|
||||
rightRoom.setUp(topRightRoom);
|
||||
topRightRoom.setUp(topRightTop);
|
||||
topRightTop.setLeft(topRightTopLeft);
|
||||
|
||||
Chest chest = new Chest(dependencyManager, resourceManager, new RoomCords(100, 45), new GameItem[]{
|
||||
new WoodenSword(resourceManager),
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package cz.jzitnik.screens.scenes;
|
||||
package cz.jzitnik.game.setup;
|
||||
|
||||
import cz.jzitnik.screens.Screen;
|
||||
import cz.jzitnik.screens.scenes.Scene;
|
||||
import cz.jzitnik.screens.scenes.VideoSceneWithAudio;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
|
||||
public class IntroScene extends Scene {
|
||||
@@ -9,7 +11,7 @@ public class IntroScene extends Scene {
|
||||
new Screen[]{
|
||||
new VideoSceneWithAudio("video.mp4", "audio.ogg")
|
||||
},
|
||||
OnEndAction.SWITCH_TO_GAME
|
||||
new OnEndAction.SwitchToScreen(new GameMenuScene(dependencyManager))
|
||||
);
|
||||
dependencyManager.inject(this);
|
||||
}
|
||||
105
src/main/java/cz/jzitnik/screens/scenes/BasicImageScene.java
Normal file
105
src/main/java/cz/jzitnik/screens/scenes/BasicImageScene.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package cz.jzitnik.screens.scenes;
|
||||
|
||||
import com.googlecode.lanterna.TextColor;
|
||||
import com.googlecode.lanterna.screen.TerminalScreen;
|
||||
import cz.jzitnik.annotations.injectors.InjectDependency;
|
||||
import cz.jzitnik.annotations.injectors.InjectState;
|
||||
import cz.jzitnik.events.KeyboardPressEvent;
|
||||
import cz.jzitnik.events.MouseAction;
|
||||
import cz.jzitnik.game.ResourceManager;
|
||||
import cz.jzitnik.screens.Screen;
|
||||
import cz.jzitnik.states.TerminalState;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
public class BasicImageScene extends Screen {
|
||||
@InjectDependency
|
||||
private ResourceManager resourceManager;
|
||||
|
||||
@InjectState
|
||||
private TerminalState terminalState;
|
||||
|
||||
private final String imagePath;
|
||||
|
||||
public BasicImageScene(String filePath) {
|
||||
imagePath = filePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fullRender() {
|
||||
BufferedImage image = resourceManager.getResource(imagePath);
|
||||
TerminalScreen screen = terminalState.getTerminalScreen();
|
||||
screen.clear();
|
||||
var tg = terminalState.getTextGraphics();
|
||||
|
||||
int termWidth = screen.getTerminalSize().getColumns();
|
||||
int termHeight = screen.getTerminalSize().getRows();
|
||||
|
||||
int imgWidth = image.getWidth();
|
||||
int imgHeight = image.getHeight();
|
||||
|
||||
// Terminal pixel space (because 1 cell = 2 vertical pixels)
|
||||
int termPixelWidth = termWidth;
|
||||
int termPixelHeight = termHeight * 2;
|
||||
|
||||
// Scale while preserving aspect ratio
|
||||
double scale = Math.min(
|
||||
(double) termPixelWidth / imgWidth,
|
||||
(double) termPixelHeight / imgHeight
|
||||
);
|
||||
|
||||
int scaledWidth = (int) (imgWidth * scale);
|
||||
int scaledHeight = (int) (imgHeight * scale);
|
||||
|
||||
// Centering offsets (in pixel space)
|
||||
int xOffset = (termPixelWidth - scaledWidth) / 2;
|
||||
int yOffset = (termPixelHeight - scaledHeight) / 2;
|
||||
|
||||
for (int y = 0; y < scaledHeight / 2; y++) {
|
||||
int imgYTop = (int) ((y * 2) / scale);
|
||||
int imgYBottom = (int) ((y * 2 + 1) / scale);
|
||||
|
||||
int termY = y + (yOffset / 2);
|
||||
if (termY < 0 || termY >= termHeight) continue;
|
||||
|
||||
for (int x = 0; x < scaledWidth; x++) {
|
||||
int termX = x + xOffset;
|
||||
if (termX < 0 || termX >= termWidth) continue;
|
||||
|
||||
int imgX = (int) (x / scale);
|
||||
|
||||
int topPixel = image.getRGB(imgX, imgYTop);
|
||||
int bottomPixel = image.getRGB(imgX, imgYBottom);
|
||||
|
||||
tg.setBackgroundColor(toColor(topPixel));
|
||||
tg.setForegroundColor(toColor(bottomPixel));
|
||||
tg.setCharacter(termX, termY, '▄');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
screen.refresh(com.googlecode.lanterna.screen.Screen.RefreshType.COMPLETE);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private TextColor.RGB toColor(int rgb) {
|
||||
int r = (rgb >> 16) & 0xFF;
|
||||
int g = (rgb >> 8) & 0xFF;
|
||||
int b = rgb & 0xFF;
|
||||
return new TextColor.RGB(r, g, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMouseAction(MouseAction event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleKeyboardAction(KeyboardPressEvent event) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import cz.jzitnik.game.GameState;
|
||||
import cz.jzitnik.screens.Screen;
|
||||
import cz.jzitnik.utils.DependencyManager;
|
||||
import cz.jzitnik.utils.events.EventManager;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
public abstract class Scene extends Screen {
|
||||
private final Screen[] parts;
|
||||
@@ -26,8 +28,16 @@ public abstract class Scene extends Screen {
|
||||
@InjectDependency
|
||||
private EventManager eventManager;
|
||||
|
||||
public enum OnEndAction {
|
||||
SWITCH_TO_GAME
|
||||
public static class OnEndAction {
|
||||
public static class SwitchToGame extends OnEndAction {}
|
||||
public static class Repeat extends OnEndAction {}
|
||||
public static class None extends OnEndAction {}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public static class SwitchToScreen extends OnEndAction {
|
||||
private final Screen screen;
|
||||
}
|
||||
}
|
||||
|
||||
public Scene(Screen[] parts, OnEndAction onEndAction) {
|
||||
@@ -41,6 +51,8 @@ public abstract class Scene extends Screen {
|
||||
if (!isRenderedAlready) {
|
||||
isRenderedAlready = true;
|
||||
render();
|
||||
} else if (currentPart != null && !onEndAction.getClass().equals(OnEndAction.Repeat.class)) {
|
||||
currentPart.fullRender();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,18 +64,28 @@ public abstract class Scene extends Screen {
|
||||
try {
|
||||
currentPart = parts[++currentIndex];
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
currentPart = null;
|
||||
if (!onEndAction.getClass().equals(OnEndAction.Repeat.class)) {
|
||||
currentPart = null;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (onEndAction) {
|
||||
case SWITCH_TO_GAME -> {
|
||||
gameState.setScreen(null);
|
||||
eventManager.emitEvent(new FullRoomDraw(true));
|
||||
}
|
||||
if (onEndAction.getClass().equals(OnEndAction.SwitchToGame.class)) {
|
||||
switchToGame();
|
||||
} else if (onEndAction.getClass().equals(OnEndAction.SwitchToScreen.class)) {
|
||||
OnEndAction.SwitchToScreen switchToScreen = (OnEndAction.SwitchToScreen) onEndAction;
|
||||
gameState.setScreen(switchToScreen.getScreen());
|
||||
eventManager.emitEvent(new FullRoomDraw(true));
|
||||
}
|
||||
}
|
||||
|
||||
protected void switchToGame() {
|
||||
gameState.setScreen(null);
|
||||
eventManager.emitEvent(new FullRoomDraw(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMouseAction(MouseAction event) {
|
||||
currentPart.handleMouseAction(event);
|
||||
|
||||
BIN
src/main/resources/audio/menu.ogg
Normal file
BIN
src/main/resources/audio/menu.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/menu.png
Normal file
BIN
src/main/resources/menu.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 MiB |
Reference in New Issue
Block a user