Implement day-night cycle | put some lights to the maps

This commit is contained in:
2023-11-07 19:27:04 +01:00
parent e9ee8f7541
commit 356f792523
14 changed files with 226 additions and 29 deletions

View File

@@ -1,6 +1,8 @@
package com.bartlomiejpluta.demo.entity;
import com.bartlomiejpluta.base.api.character.Character;
import com.bartlomiejpluta.base.api.light.Light;
import com.bartlomiejpluta.base.api.map.layer.object.ObjectLayer;
import com.bartlomiejpluta.demo.world.item.Item;
import com.bartlomiejpluta.demo.world.weapon.Ammunition;
import com.bartlomiejpluta.demo.world.weapon.RangedWeapon;
@@ -39,6 +41,9 @@ public abstract class Creature extends NamedCharacter {
@Getter
private NamedCharacter lastAttacker;
@Getter
protected Light light;
public Creature(@NonNull Character entity) {
super(entity);
}
@@ -88,6 +93,39 @@ public abstract class Creature extends NamedCharacter {
this.hp = Math.min(this.hp + hp, this.maxHp);
}
public void setLight(Light light) {
this.light = light;
if(getLayer() != null) {
var layer = getLayer().getMap().getLayer(0);
if(light != null) {
layer.addLight(light);
} else if (this.light != null){
layer.removeLight(this.light);
}
}
this.light = light;
}
@Override
public void onAdd(ObjectLayer layer) {
super.onAdd(layer);
if(light != null) {
layer.getMap().getLayer(0).addLight(light);
}
}
@Override
public void onRemove(ObjectLayer layer) {
super.onRemove(layer);
if(light != null) {
layer.getMap().getLayer(0).removeLight(light);
}
}
@Override
public void update(float dt) {
super.update(dt);
@@ -100,6 +138,10 @@ public abstract class Creature extends NamedCharacter {
alive = false;
die();
}
if(light != null) {
light.setPosition(getPosition());
}
}
protected void die() {

View File

@@ -34,6 +34,11 @@ public class Player extends Creature {
setAnimationSpeed(1f);
setBlocking(true);
var light = context.createLight();
light.setAttenuation(4f, 0, 0.001f);
light.setIntensity(1f, 1f, 1f);
setLight(light);
Arrays.fill(equipment, null);
}

View File

@@ -13,6 +13,7 @@ import com.bartlomiejpluta.demo.event.EnemyDiedEvent;
import com.bartlomiejpluta.demo.event.HitEvent;
import com.bartlomiejpluta.demo.runner.DemoRunner;
import com.bartlomiejpluta.demo.util.LimitedQueue;
import com.bartlomiejpluta.demo.world.time.WorldTime;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@@ -24,6 +25,7 @@ public class HUD extends BorderLayout {
private static final float LOG_VISIBILITY_DURATION = 8000f;
private static final float LOG_VISIBILITY_FADING_OUT = 1000f;
private final Player player;
private final WorldTime time;
private final Runtime runtime;
private final LimitedQueue<String> logger = new LimitedQueue<>(MAX_LOG_SIZE);
@@ -42,6 +44,7 @@ public class HUD extends BorderLayout {
super(context, gui, refs);
this.player = DemoRunner.instance().getPlayer();
this.runtime = Runtime.getRuntime();
this.time = DemoRunner.instance().getTime();
context.addEventListener(HitEvent.TYPE, this::logHitEvent);
context.addEventListener(EnemyDiedEvent.TYPE, this::logEnemyDiedEvent);
}
@@ -72,15 +75,13 @@ public class HUD extends BorderLayout {
} else {
logVisibilityDuration = 0;
}
}
@Override
public void draw(Screen screen, GUI gui) {
var coords = player.getCoordinates();
var pos = player.getPosition();
debugTxt.setText(String.format("Mem: %.2f / %.2f [MB]\nCoords: %d : %d\nPos: %.2f : %.2f\nEntities: %d\n", runtime.totalMemory() / 1024f / 1024f, runtime.maxMemory() / 1024f / 1024f, coords.x(), coords.y(), pos.x(), pos.y(), player.getLayer().getEntities().size()));
debugTxt.setText(String.format("Clock: %02d:%02d\nTime: %.2f\nMem: %.2f / %.2f [MB]\nCoords: %d : %d\nPos: %.2f : %.2f\nEntities: %d\n", time.getHour(), time.getMinute(), time.getProgress(), runtime.totalMemory() / 1024f / 1024f, runtime.maxMemory() / 1024f / 1024f, coords.x(), coords.y(), pos.x(), pos.y(), player.getLayer().getEntities().size()));
logLbl.setAlpha(Math.min(1f, logVisibilityDuration / LOG_VISIBILITY_FADING_OUT));

View File

@@ -7,6 +7,7 @@ import com.bartlomiejpluta.base.api.gui.WindowPosition;
import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.api.input.Input;
import com.bartlomiejpluta.base.api.input.Key;
import com.bartlomiejpluta.base.api.light.Light;
import com.bartlomiejpluta.base.api.map.handler.MapHandler;
import com.bartlomiejpluta.base.api.map.layer.object.MapPin;
import com.bartlomiejpluta.base.api.map.model.GameMap;
@@ -20,11 +21,14 @@ import com.bartlomiejpluta.demo.entity.*;
import com.bartlomiejpluta.demo.event.EnemyDiedEvent;
import com.bartlomiejpluta.demo.menu.GuiManager;
import com.bartlomiejpluta.demo.runner.DemoRunner;
import com.bartlomiejpluta.demo.world.light.Torch;
import com.bartlomiejpluta.demo.world.potion.Medicament;
import lombok.NonNull;
import java.util.concurrent.CompletableFuture;
import static java.lang.Math.*;
public abstract class BaseMapHandler implements MapHandler {
protected Screen screen;
protected Context context;
@@ -35,6 +39,8 @@ public abstract class BaseMapHandler implements MapHandler {
protected Player player;
protected CameraController cameraController;
protected boolean dayNightCycle = false;
@Override
public void onCreate(Context context, GameMap map) {
this.context = context;
@@ -73,6 +79,21 @@ public abstract class BaseMapHandler implements MapHandler {
@Override
public void update(Context context, GameMap map, float dt) {
cameraController.update();
if(!dayNightCycle) {
return;
}
var x = runner.getTime().getProgress();
map.setAmbientColor(
ambientColor(1.2f, -0.3f, 0, x),
ambientColor(1.4f, -0.6f, 0.05f, x),
ambientColor(1.7f, -1.1f, 0.2f, x)
);
}
private float ambientColor(float a, float b, float offset, float x) {
return ((float) max(sin(x * PI * a + b), 0) + offset) / (1 + offset);
}
public CompletableFuture<Object> dialog(NamedCharacter speaker, String message, WindowPosition position) {
@@ -124,6 +145,22 @@ public abstract class BaseMapHandler implements MapHandler {
return addEntity(icon, tile);
}
public Torch torch(MapPin tile) {
var torch = new Torch();
map.getLayer(tile.getLayer()).addLight(torch);
torch.setCoordinates(tile.toCoordinates());
return torch;
}
public Light light(MapPin tile) {
var light = context.createLight();
map.getLayer(tile.getLayer()).addLight(light);
light.setCoordinates(tile.toCoordinates());
light.setIntensity(1f, 1f, 1f);
light.setAttenuation(0.1f, 0, 0.001f);
return light;
}
public Warp warp(@NonNull MapPin tile, MapPin target) {
var warp = new Warp(target);
warp.setEntity(player);

View File

@@ -1,10 +1,12 @@
package com.bartlomiejpluta.demo.map;
import com.bartlomiejpluta.demo.map.BaseMapHandler;
import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.input.Input;
import com.bartlomiejpluta.base.api.map.model.GameMap;
import com.bartlomiejpluta.base.api.screen.Screen;
public class ForrestHandler extends BaseMapHandler {
@Override
public void onCreate(Context context, GameMap map) {
super.onCreate(context, map);
dayNightCycle = true;
}
}

View File

@@ -11,6 +11,7 @@ import static com.bartlomiejpluta.base.lib.animation.AnimationRunner.simple;
public class HeroHomeHandler extends BaseMapHandler {
@Override
public void onOpen(Context context, GameMap map) {
map.setAmbientColor(0.05f, 0.01f, 0.01f);
dialog(player, "Ahhh, another beautiful day for an adventure... Let's go!");
}

View File

@@ -1,5 +1,12 @@
package com.bartlomiejpluta.demo.map;
public class HeroHouse extends BaseMapHandler {
import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.map.model.GameMap;
public class HeroHouse extends BaseMapHandler {
@Override
public void onCreate(Context context, GameMap map) {
super.onCreate(context, map);
dayNightCycle = true;
}
}

View File

@@ -1,7 +1,6 @@
package com.bartlomiejpluta.demo.runner;
import A.maps;
import DB.ConfigDAO;
import DB.dao;
import com.bartlomiejpluta.base.api.context.Context;
import com.bartlomiejpluta.base.api.gui.GUI;
@@ -9,15 +8,17 @@ import com.bartlomiejpluta.base.api.runner.GameRunner;
import com.bartlomiejpluta.base.api.screen.Screen;
import com.bartlomiejpluta.demo.entity.Player;
import com.bartlomiejpluta.demo.menu.GuiManager;
import com.bartlomiejpluta.demo.world.time.WorldTime;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.lang.Integer.parseInt;
public class DemoRunner implements GameRunner {
private static final Logger log = LoggerFactory.getLogger(DemoRunner.class);
@Getter
private WorldTime time;
private static DemoRunner INSTANCE;
private Screen screen;
@@ -107,6 +108,7 @@ public class DemoRunner implements GameRunner {
this.context = context;
this.screen = context.getScreen();
this.time = new WorldTime(context);
configureScreen();
configureCamera();
@@ -118,4 +120,9 @@ public class DemoRunner implements GameRunner {
screen.show();
}
@Override
public void update(float dt) {
time.update(dt);
}
}

View File

@@ -0,0 +1,29 @@
package com.bartlomiejpluta.demo.world.light;
import com.bartlomiejpluta.base.api.context.ContextHolder;
import com.bartlomiejpluta.base.lib.light.LightDelegate;
import java.util.Random;
public class Torch extends LightDelegate {
private final Random random = new Random();
private float acc = 0;
public Torch() {
super(ContextHolder.INSTANCE.getContext().createLight());
setIntensity(100f, 50f, 0f);
setConstantAttenuation(1f);
}
@Override
public void update(float dt) {
super.update(dt);
if (acc > 0.1f) {
setQuadraticAttenuation(0.1f * (1f + ((float) random.nextGaussian()) * 0.1f));
acc = 0;
}
acc += dt;
}
}

View File

@@ -0,0 +1,39 @@
package com.bartlomiejpluta.demo.world.time;
import DB.dao;
import com.bartlomiejpluta.base.api.context.Context;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
public class WorldTime {
@Getter
private float progress = 0;
private final float period; // seconds
private final Context context;
public WorldTime(@NonNull Context context) {
this.context = context;
this.period = Float.parseFloat(dao.config.find("full_day_duration").getValue());
}
public int getHour() {
return (int) (progress * 24);
}
public int getMinute() {
return (int) (progress * 24 * 60) % 60;
}
public void update(float dt) {
if (context.isPaused()) {
return;
}
progress += dt / period;
if (progress > 1) {
progress = 0;
}
}
}