diff --git a/pom.xml b/pom.xml index a815d6b..9e81c13 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,8 @@ 1.18.38 + 25 + 25 @@ -152,4 +154,4 @@ 6.1.1-1.5.10 - \ No newline at end of file + diff --git a/src/main/java/cz/jzitnik/events/PlayVideo.java b/src/main/java/cz/jzitnik/events/PlayVideo.java deleted file mode 100644 index dc2f5c1..0000000 --- a/src/main/java/cz/jzitnik/events/PlayVideo.java +++ /dev/null @@ -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; -} diff --git a/src/main/java/cz/jzitnik/events/handlers/PlayVideoHandler.java b/src/main/java/cz/jzitnik/events/handlers/PlayVideoHandler.java deleted file mode 100644 index da2c168..0000000 --- a/src/main/java/cz/jzitnik/events/handlers/PlayVideoHandler.java +++ /dev/null @@ -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 { - 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); - } -} diff --git a/src/main/java/cz/jzitnik/events/handlers/TerminalResizeEventHandler.java b/src/main/java/cz/jzitnik/events/handlers/TerminalResizeEventHandler.java index c876b3f..2f3e971 100644 --- a/src/main/java/cz/jzitnik/events/handlers/TerminalResizeEventHandler.java +++ b/src/main/java/cz/jzitnik/events/handlers/TerminalResizeEventHandler.java @@ -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 { + 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); + } +} diff --git a/src/main/java/cz/jzitnik/game/setup/GameSetup.java b/src/main/java/cz/jzitnik/game/setup/GameSetup.java index 9c75690..0b07fa7 100644 --- a/src/main/java/cz/jzitnik/game/setup/GameSetup.java +++ b/src/main/java/cz/jzitnik/game/setup/GameSetup.java @@ -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), diff --git a/src/main/java/cz/jzitnik/screens/scenes/IntroScene.java b/src/main/java/cz/jzitnik/game/setup/IntroScene.java similarity index 64% rename from src/main/java/cz/jzitnik/screens/scenes/IntroScene.java rename to src/main/java/cz/jzitnik/game/setup/IntroScene.java index ee1c3be..9cb07a7 100644 --- a/src/main/java/cz/jzitnik/screens/scenes/IntroScene.java +++ b/src/main/java/cz/jzitnik/game/setup/IntroScene.java @@ -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); } diff --git a/src/main/java/cz/jzitnik/screens/scenes/BasicImageScene.java b/src/main/java/cz/jzitnik/screens/scenes/BasicImageScene.java new file mode 100644 index 0000000..d8a5c0c --- /dev/null +++ b/src/main/java/cz/jzitnik/screens/scenes/BasicImageScene.java @@ -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) { + + } +} diff --git a/src/main/java/cz/jzitnik/screens/scenes/Scene.java b/src/main/java/cz/jzitnik/screens/scenes/Scene.java index 3245e3f..c11ec1d 100644 --- a/src/main/java/cz/jzitnik/screens/scenes/Scene.java +++ b/src/main/java/cz/jzitnik/screens/scenes/Scene.java @@ -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); diff --git a/src/main/resources/audio/menu.ogg b/src/main/resources/audio/menu.ogg new file mode 100644 index 0000000..50369b3 Binary files /dev/null and b/src/main/resources/audio/menu.ogg differ diff --git a/src/main/resources/menu.png b/src/main/resources/menu.png new file mode 100644 index 0000000..9b53242 Binary files /dev/null and b/src/main/resources/menu.png differ