perf: Significantly improved rendering performance

This commit is contained in:
2025-09-23 12:18:35 +02:00
parent 5d57d8e069
commit 13db7972eb
5 changed files with 18 additions and 14 deletions

View File

@ -116,11 +116,11 @@ public class Game {
world[cords[1]][cords[0]].remove(player.getPlayerBlock2()); world[cords[1]][cords[0]].remove(player.getPlayerBlock2());
world[cords[1] - 1][cords[0] + 1].add(player.getPlayerBlock1()); world[cords[1] - 1][cords[0] + 1].add(player.getPlayerBlock1());
world[cords[1] - 1][cords[0]].remove(player.getPlayerBlock1()); world[cords[1] - 1][cords[0]].remove(player.getPlayerBlock1());
screenRenderer.render(this); new Thread(() -> screenRenderer.render(this)).start();
stats.setBlocksTraveled(stats.getBlocksTraveled() + 1); stats.setBlocksTraveled(stats.getBlocksTraveled() + 1);
entitySpawnProvider.update(this, terminal); new Thread(() -> entitySpawnProvider.update(this, terminal)).start();
playMovePlayerSound(cords[0] + 1, cords[1]); playMovePlayerSound(cords[0] + 1, cords[1]);
@ -147,11 +147,11 @@ public class Game {
world[cords[1]][cords[0]].remove(player.getPlayerBlock2()); world[cords[1]][cords[0]].remove(player.getPlayerBlock2());
world[cords[1] - 1][cords[0] - 1].add(player.getPlayerBlock1()); world[cords[1] - 1][cords[0] - 1].add(player.getPlayerBlock1());
world[cords[1] - 1][cords[0]].remove(player.getPlayerBlock1()); world[cords[1] - 1][cords[0]].remove(player.getPlayerBlock1());
screenRenderer.render(this); new Thread(() -> screenRenderer.render(this)).start();
stats.setBlocksTraveled(stats.getBlocksTraveled() + 1); stats.setBlocksTraveled(stats.getBlocksTraveled() + 1);
entitySpawnProvider.update(this, terminal); new Thread(() -> entitySpawnProvider.update(this, terminal)).start();
playMovePlayerSound(cords[0] - 1, cords[1]); playMovePlayerSound(cords[0] - 1, cords[1]);

View File

@ -12,6 +12,6 @@ public class SimpleSprite extends Sprite {
} }
public String getSprite(Enum key) { public String getSprite(Enum key) {
throw new RuntimeException("Imposible state"); throw new RuntimeException("Impossible state");
} }
} }

View File

@ -8,9 +8,11 @@ import cz.jzitnik.tui.MouseHandler;
import cz.jzitnik.tui.ScreenRenderer; import cz.jzitnik.tui.ScreenRenderer;
import org.jline.terminal.MouseEvent; import org.jline.terminal.MouseEvent;
import org.jline.terminal.Terminal; import org.jline.terminal.Terminal;
import java.io.IOException; import java.io.IOException;
import java.nio.BufferUnderflowException; import java.nio.BufferUnderflowException;
import java.util.Optional; import java.util.Optional;
import cz.jzitnik.game.annotations.ThreadRegistry; import cz.jzitnik.game.annotations.ThreadRegistry;
/** /**
@ -58,24 +60,22 @@ public class InputHandlerThread extends Thread {
case INVENTORY -> InventoryClickHandler.click(mouseEvent, terminal, screenRenderer, case INVENTORY -> InventoryClickHandler.click(mouseEvent, terminal, screenRenderer,
game, Optional.empty(), Optional.empty()); game, Optional.empty(), Optional.empty());
case CRAFTING_TABLE -> case CRAFTING_TABLE ->
game.getGameStates().craftingTable.click(mouseEvent, terminal, screenRenderer); game.getGameStates().craftingTable.click(mouseEvent, terminal, screenRenderer);
case CHEST -> ((Chest) game.getWorld()[game.getGameStates().clickY][game case CHEST -> ((Chest) game.getWorld()[game.getGameStates().clickY][game
.getGameStates().clickX].stream().filter(i -> i.getBlockId().equals("chest")) .getGameStates().clickX].stream().filter(i -> i.getBlockId().equals("chest"))
.toList().getFirst().getData()).click(game, mouseEvent, terminal, .toList().getFirst().getData()).click(game, mouseEvent, terminal,
screenRenderer); screenRenderer);
case FURNACE -> ((Furnace) game.getWorld()[game.getGameStates().clickY][game case FURNACE -> ((Furnace) game.getWorld()[game.getGameStates().clickY][game
.getGameStates().clickX].stream().filter(i -> i.getBlockId().equals("furnace")) .getGameStates().clickX].stream().filter(i -> i.getBlockId().equals("furnace"))
.toList().getFirst().getData()).click(game, mouseEvent, terminal, .toList().getFirst().getData()).click(game, mouseEvent, terminal,
screenRenderer); screenRenderer);
case ESC -> game.getGameStates().dependencies.escape.mouse(mouseEvent, terminal, case ESC -> game.getGameStates().dependencies.escape.mouse(mouseEvent, terminal,
screenRenderer); screenRenderer);
case SAVE_EXIT -> {
}
case OPTIONS -> game.getGameStates().dependencies.options.handleMouse(mouseEvent, case OPTIONS -> game.getGameStates().dependencies.options.handleMouse(mouseEvent,
terminal, screenRenderer); terminal, screenRenderer);
case DEATH_SCREEN -> game.getGameStates().dependencies.deathScreen case DEATH_SCREEN -> game.getGameStates().dependencies.deathScreen
.handleMouse(mouseEvent, terminal, screenRenderer, game); .handleMouse(mouseEvent, terminal, screenRenderer, game);
case SAVED -> { case SAVE_EXIT, SAVED -> {
} }
} }
} }
@ -86,11 +86,9 @@ public class InputHandlerThread extends Thread {
case '1', '2', '3', '4', '5', '6', '7', '8', '9' -> game.changeSlot(key - 49, screenRenderer); case '1', '2', '3', '4', '5', '6', '7', '8', '9' -> game.changeSlot(key - 49, screenRenderer);
case 'a' -> { case 'a' -> {
game.movePlayerLeft(screenRenderer, terminal); game.movePlayerLeft(screenRenderer, terminal);
screenRenderer.render(game);
} }
case 'd' -> { case 'd' -> {
game.movePlayerRight(screenRenderer, terminal); game.movePlayerRight(screenRenderer, terminal);
screenRenderer.render(game);
} }
case ' ' -> { case ' ' -> {
game.movePlayerUp(screenRenderer); game.movePlayerUp(screenRenderer);

View File

@ -189,6 +189,6 @@ public class MouseHandler {
screenRenderer.setSelectedBlock(Optional.empty()); screenRenderer.setSelectedBlock(Optional.empty());
} }
screenRenderer.render(game); new Thread(() -> screenRenderer.render(game)).start();
} }
} }

View File

@ -27,6 +27,7 @@ import java.util.Optional;
public class ScreenRenderer { public class ScreenRenderer {
private final SpriteList spriteList; private final SpriteList spriteList;
private final Terminal terminal; private final Terminal terminal;
private boolean rendering = false;
/** /**
* Constructs a {@code ScreenRenderer} with the given sprite list and terminal. * Constructs a {@code ScreenRenderer} with the given sprite list and terminal.
@ -98,6 +99,10 @@ public class ScreenRenderer {
* @param game Current game state to render. * @param game Current game state to render.
*/ */
public synchronized void render(Game game) { public synchronized void render(Game game) {
if (rendering) {
return;
}
rendering = true;
log.debug("Rendering frame"); log.debug("Rendering frame");
var world = game.getWorld(); var world = game.getWorld();
StringBuilder main = new StringBuilder(); StringBuilder main = new StringBuilder();
@ -216,6 +221,7 @@ public class ScreenRenderer {
log.debug("Frame rendered"); log.debug("Frame rendered");
System.out.println(main); System.out.println(main);
rendering = false;
} }
/** /**