feat: New scenes
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -23,6 +23,8 @@
|
|||||||
<version>1.18.38</version>
|
<version>1.18.38</version>
|
||||||
</path>
|
</path>
|
||||||
</annotationProcessorPaths>
|
</annotationProcessorPaths>
|
||||||
|
<source>25</source>
|
||||||
|
<target>25</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
|||||||
@@ -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.InjectDependency;
|
||||||
import cz.jzitnik.annotations.injectors.InjectState;
|
import cz.jzitnik.annotations.injectors.InjectState;
|
||||||
import cz.jzitnik.events.FullRoomDraw;
|
import cz.jzitnik.events.FullRoomDraw;
|
||||||
import cz.jzitnik.events.PlayVideo;
|
|
||||||
import cz.jzitnik.events.TerminalResizeEvent;
|
import cz.jzitnik.events.TerminalResizeEvent;
|
||||||
import cz.jzitnik.game.GameState;
|
import cz.jzitnik.game.GameState;
|
||||||
import cz.jzitnik.states.ScreenBuffer;
|
import cz.jzitnik.states.ScreenBuffer;
|
||||||
@@ -32,6 +31,8 @@ public class TerminalResizeEventHandler extends AbstractEventHandler<TerminalRes
|
|||||||
@InjectState
|
@InjectState
|
||||||
private GameState gameState;
|
private GameState gameState;
|
||||||
|
|
||||||
|
private boolean screenRerendering = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(TerminalResizeEvent event) {
|
public void handle(TerminalResizeEvent event) {
|
||||||
TerminalSize size = event.getNewSize();
|
TerminalSize size = event.getNewSize();
|
||||||
@@ -47,7 +48,13 @@ public class TerminalResizeEventHandler extends AbstractEventHandler<TerminalRes
|
|||||||
screenBuffer.setRenderedBuffer(buffer);
|
screenBuffer.setRenderedBuffer(buffer);
|
||||||
|
|
||||||
if (gameState.getScreen() != null) {
|
if (gameState.getScreen() != null) {
|
||||||
|
if (screenRerendering) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
screenRerendering = true;
|
||||||
gameState.getScreen().fullRender();
|
gameState.getScreen().fullRender();
|
||||||
|
screenRerendering = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
eventManager.emitEvent(new FullRoomDraw(true));
|
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) {
|
public InputStream getResourceAsStream(String path) {
|
||||||
return classLoader.getResourceAsStream(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.items.WoodenSword;
|
||||||
import cz.jzitnik.game.objects.Chest;
|
import cz.jzitnik.game.objects.Chest;
|
||||||
import cz.jzitnik.game.utils.RoomCords;
|
import cz.jzitnik.game.utils.RoomCords;
|
||||||
import cz.jzitnik.screens.scenes.IntroScene;
|
|
||||||
import cz.jzitnik.utils.DependencyManager;
|
import cz.jzitnik.utils.DependencyManager;
|
||||||
|
|
||||||
@Dependency
|
@Dependency
|
||||||
@@ -31,9 +30,13 @@ public class GameSetup {
|
|||||||
GameRoom mainRoom = new GameRoom(ResourceManager.Resource.ROOM1);
|
GameRoom mainRoom = new GameRoom(ResourceManager.Resource.ROOM1);
|
||||||
GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2);
|
GameRoom rightRoom = new GameRoom(ResourceManager.Resource.ROOM2);
|
||||||
GameRoom topRightRoom = new GameRoom(ResourceManager.Resource.ROOM3);
|
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);
|
mainRoom.setRight(rightRoom);
|
||||||
rightRoom.setUp(topRightRoom);
|
rightRoom.setUp(topRightRoom);
|
||||||
|
topRightRoom.setUp(topRightTop);
|
||||||
|
topRightTop.setLeft(topRightTopLeft);
|
||||||
|
|
||||||
Chest chest = new Chest(dependencyManager, resourceManager, new RoomCords(100, 45), new GameItem[]{
|
Chest chest = new Chest(dependencyManager, resourceManager, new RoomCords(100, 45), new GameItem[]{
|
||||||
new WoodenSword(resourceManager),
|
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.Screen;
|
||||||
|
import cz.jzitnik.screens.scenes.Scene;
|
||||||
|
import cz.jzitnik.screens.scenes.VideoSceneWithAudio;
|
||||||
import cz.jzitnik.utils.DependencyManager;
|
import cz.jzitnik.utils.DependencyManager;
|
||||||
|
|
||||||
public class IntroScene extends Scene {
|
public class IntroScene extends Scene {
|
||||||
@@ -9,7 +11,7 @@ public class IntroScene extends Scene {
|
|||||||
new Screen[]{
|
new Screen[]{
|
||||||
new VideoSceneWithAudio("video.mp4", "audio.ogg")
|
new VideoSceneWithAudio("video.mp4", "audio.ogg")
|
||||||
},
|
},
|
||||||
OnEndAction.SWITCH_TO_GAME
|
new OnEndAction.SwitchToScreen(new GameMenuScene(dependencyManager))
|
||||||
);
|
);
|
||||||
dependencyManager.inject(this);
|
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.screens.Screen;
|
||||||
import cz.jzitnik.utils.DependencyManager;
|
import cz.jzitnik.utils.DependencyManager;
|
||||||
import cz.jzitnik.utils.events.EventManager;
|
import cz.jzitnik.utils.events.EventManager;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
public abstract class Scene extends Screen {
|
public abstract class Scene extends Screen {
|
||||||
private final Screen[] parts;
|
private final Screen[] parts;
|
||||||
@@ -26,8 +28,16 @@ public abstract class Scene extends Screen {
|
|||||||
@InjectDependency
|
@InjectDependency
|
||||||
private EventManager eventManager;
|
private EventManager eventManager;
|
||||||
|
|
||||||
public enum OnEndAction {
|
public static class OnEndAction {
|
||||||
SWITCH_TO_GAME
|
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) {
|
public Scene(Screen[] parts, OnEndAction onEndAction) {
|
||||||
@@ -41,6 +51,8 @@ public abstract class Scene extends Screen {
|
|||||||
if (!isRenderedAlready) {
|
if (!isRenderedAlready) {
|
||||||
isRenderedAlready = true;
|
isRenderedAlready = true;
|
||||||
render();
|
render();
|
||||||
|
} else if (currentPart != null && !onEndAction.getClass().equals(OnEndAction.Repeat.class)) {
|
||||||
|
currentPart.fullRender();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,16 +64,26 @@ public abstract class Scene extends Screen {
|
|||||||
try {
|
try {
|
||||||
currentPart = parts[++currentIndex];
|
currentPart = parts[++currentIndex];
|
||||||
} catch (ArrayIndexOutOfBoundsException e) {
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
if (!onEndAction.getClass().equals(OnEndAction.Repeat.class)) {
|
||||||
currentPart = null;
|
currentPart = null;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (onEndAction) {
|
if (onEndAction.getClass().equals(OnEndAction.SwitchToGame.class)) {
|
||||||
case SWITCH_TO_GAME -> {
|
switchToGame();
|
||||||
gameState.setScreen(null);
|
} else if (onEndAction.getClass().equals(OnEndAction.SwitchToScreen.class)) {
|
||||||
|
OnEndAction.SwitchToScreen switchToScreen = (OnEndAction.SwitchToScreen) onEndAction;
|
||||||
|
gameState.setScreen(switchToScreen.getScreen());
|
||||||
eventManager.emitEvent(new FullRoomDraw(true));
|
eventManager.emitEvent(new FullRoomDraw(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void switchToGame() {
|
||||||
|
gameState.setScreen(null);
|
||||||
|
eventManager.emitEvent(new FullRoomDraw(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
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