feat(gameplay): Added day-night cycle

This commit is contained in:
Jakub Žitník 2025-03-26 11:31:25 +01:00
parent ca98fe7fae
commit 8b09d71a44
Signed by: jzitnik
GPG Key ID: C577A802A6AF4EF3
6 changed files with 65 additions and 16 deletions

View File

@ -45,6 +45,8 @@ public class Game extends AutoTransientSupport {
private transient EntitySpawnProvider entitySpawnProvider = new EntitySpawnProvider();
@AutoTransient
private transient GameStates gameStates = new GameStates(this);
@Setter
private int daytime = 0; // 0-600
public Game() {
Generation.generateWorld(this);

View File

@ -26,6 +26,7 @@ public class DefaultPlaceHandler implements CustomPlaceHandler {
public boolean mine(Game game, int x, int y) {
var blocks = game.getWorld()[y][x];
log.info("Block was mined at coordinates x:{},y:{}", x, y);
blocks.removeAll(blocks.stream().filter(i -> !i.getBlockId().equals("air") && !i.isMob()).toList());
return true;

View File

@ -6,8 +6,11 @@ import java.util.List;
import java.util.Set;
import cz.jzitnik.game.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
@Slf4j
public class PlaceHandler {
private final HashMap<String, CustomPlaceHandler> placeHandlerList = new HashMap<>();
private final CustomPlaceHandler defaultPlaceHandler = new DefaultPlaceHandler();
@ -26,7 +29,10 @@ public class PlaceHandler {
return defaultPlaceHandler;
}
return placeHandlerList.get(itemId);
var placeHandler = placeHandlerList.get(itemId);
log.debug("Using {} to mine/place a block", placeHandler.getClass().getSimpleName());
return placeHandler;
}
public PlaceHandler() {

View File

@ -0,0 +1,19 @@
package cz.jzitnik.game.logic.services.daytime;
import cz.jzitnik.game.Game;
import cz.jzitnik.game.annotations.CustomLogic;
import cz.jzitnik.game.logic.CustomLogicInterface;
@CustomLogic
public class DayTimeLogic implements CustomLogicInterface {
@Override
public void nextIteration(Game game) {
int time = game.getDaytime();
if (time >= 600) {
game.setDaytime(0);
} else {
game.setDaytime(time + 1);
}
}
}

View File

@ -3,19 +3,29 @@ package cz.jzitnik.game.sprites;
import cz.jzitnik.tui.Sprite;
public class Air extends Sprite {
private String resource;
public Air() {
StringBuilder sprite = new StringBuilder();
for (int i = 0; i < 25; i++) {
sprite.append("\033[48;2;121;166;255m ".repeat(50));
sprite.append("\n");
}
resource = sprite.toString();
}
public String getSprite() {
return resource;
throw new RuntimeException("Imposible state");
}
public String getSprite(int daytime) {
StringBuilder sprite = new StringBuilder();
// Normalize daytime to a range of 0 to 1, where 300 is the darkest
double normalized = Math.abs((daytime - 300) / 300.0);
// Interpolate blue color intensity (darker at midday, brighter at
// sunrise/sunset)
int blue = (int) (255 * normalized);
int red = (int) (121 * normalized);
int green = (int) (166 * normalized);
String colorCode = String.format("\033[48;2;%d;%d;%dm ", red, green, blue);
for (int i = 0; i < 25; i++) {
sprite.append(colorCode.repeat(50)).append("\n");
}
return sprite.toString();
}
public String getSprite(Enum e) {

View File

@ -2,6 +2,7 @@ package cz.jzitnik.tui;
import cz.jzitnik.game.entities.Block;
import cz.jzitnik.game.Game;
import cz.jzitnik.game.sprites.Air;
import cz.jzitnik.game.sprites.SimpleSprite;
import cz.jzitnik.game.sprites.Steve;
import cz.jzitnik.game.blocks.Chest;
@ -45,6 +46,19 @@ public class ScreenRenderer {
return null;
}
public String getTexture(Block block, SpriteList spriteList, Game game) {
if (Air.class.isAssignableFrom(spriteList.getSprite(block.getSprite()).getClass())) {
var air = (Air) spriteList.getSprite(block.getSprite());
return air.getSprite(game.getDaytime());
}
if (block.getSpriteState().isEmpty()) {
return spriteList.getSprite(block.getSprite()).getSprite();
}
return spriteList.getSprite(block.getSprite()).getSprite(block.getSpriteState().get());
}
public synchronized void render(Game game) {
log.debug("Rendering frame");
var world = game.getWorld();
@ -103,10 +117,7 @@ public class ScreenRenderer {
for (int x = startX; x < endX; x++) {
List<Block> blocks = world[y][x];
List<String> sprites = new ArrayList<>(blocks.stream()
.map(block -> block.getSpriteState().isEmpty()
? spriteList.getSprite(block.getSprite()).getSprite()
: spriteList.getSprite(block.getSprite())
.getSprite(block.getSpriteState().get()))
.map(block -> getTexture(block, spriteList, game))
.toList());
if (selectedBlock.isPresent() && selectedBlock.get().get(0) == x