Refactor Context and GameRunner
This commit is contained in:
@@ -1,24 +1,13 @@
|
||||
package com.bartlomiejpluta.base.engine.logic;
|
||||
|
||||
import com.bartlomiejpluta.base.api.game.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.game.runner.GameRunner;
|
||||
import com.bartlomiejpluta.base.api.game.screen.Screen;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.object.texture.TextureManager;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.render.Renderer;
|
||||
import com.bartlomiejpluta.base.engine.project.loader.ClassLoader;
|
||||
import com.bartlomiejpluta.base.engine.project.loader.ProjectLoader;
|
||||
import com.bartlomiejpluta.base.engine.project.model.Project;
|
||||
import com.bartlomiejpluta.base.engine.project.model.RenderableContext;
|
||||
import com.bartlomiejpluta.base.engine.util.mesh.MeshManager;
|
||||
import com.bartlomiejpluta.base.engine.util.profiling.fps.FPSMonitor;
|
||||
import com.bartlomiejpluta.base.engine.util.profiling.time.TimeProfilerService;
|
||||
import com.bartlomiejpluta.base.engine.world.camera.DefaultCamera;
|
||||
import com.bartlomiejpluta.base.engine.world.entity.manager.EntityManager;
|
||||
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
|
||||
import com.bartlomiejpluta.base.engine.world.map.manager.MapManager;
|
||||
import com.bartlomiejpluta.base.engine.world.tileset.manager.TileSetManager;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -28,36 +17,18 @@ import org.springframework.stereotype.Component;
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
public class DefaultGameLogic implements GameLogic {
|
||||
private final Renderer renderer;
|
||||
private final TileSetManager tileSetManager;
|
||||
private final MeshManager meshManager;
|
||||
private final TextureManager textureManager;
|
||||
private final EntityManager entityManager;
|
||||
private final ImageManager imageManager;
|
||||
private final TimeProfilerService profiler;
|
||||
private final FPSMonitor fpsMonitor;
|
||||
private final MapManager mapManager;
|
||||
private final ProjectLoader projectLoader;
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
private final RenderableContext context;
|
||||
|
||||
private final Camera camera = new DefaultCamera();
|
||||
|
||||
private Project project;
|
||||
private GameRunner runner;
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void init(Screen screen) {
|
||||
log.info("Initializing game logic");
|
||||
renderer.init();
|
||||
context.init(screen, camera);
|
||||
|
||||
project = projectLoader.loadProject();
|
||||
var runnerClass = classLoader.<GameRunner>loadClass(project.getRunner());
|
||||
runner = runnerClass.getConstructor().newInstance();
|
||||
Project project = projectLoader.loadProject();
|
||||
|
||||
runner.init(context);
|
||||
context.init(screen, camera, project);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,7 +39,6 @@ public class DefaultGameLogic implements GameLogic {
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
context.update(dt);
|
||||
fpsMonitor.update(dt);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,9 +9,11 @@ import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
|
||||
import com.bartlomiejpluta.base.engine.world.map.manager.MapManager;
|
||||
import com.bartlomiejpluta.base.engine.world.tileset.manager.TileSetManager;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
public class DefaultProjectLoader implements ProjectLoader {
|
||||
@@ -25,6 +27,7 @@ public class DefaultProjectLoader implements ProjectLoader {
|
||||
|
||||
@Override
|
||||
public Project loadProject() {
|
||||
log.info("Loading project resources");
|
||||
var resource = DefaultProjectLoader.class.getResourceAsStream(configuration.projectFile(configuration.getMainFile()));
|
||||
var project = projectDeserializer.deserialize(resource);
|
||||
project.getTileSetAssets().forEach(tileSetManager::registerAsset);
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.bartlomiejpluta.base.api.game.entity.Entity;
|
||||
import com.bartlomiejpluta.base.api.game.gui.base.GUI;
|
||||
import com.bartlomiejpluta.base.api.game.image.Image;
|
||||
import com.bartlomiejpluta.base.api.game.map.handler.MapHandler;
|
||||
import com.bartlomiejpluta.base.api.game.runner.GameRunner;
|
||||
import com.bartlomiejpluta.base.api.game.screen.Screen;
|
||||
import com.bartlomiejpluta.base.api.internal.gc.Cleanable;
|
||||
import com.bartlomiejpluta.base.api.internal.logic.Updatable;
|
||||
@@ -21,12 +22,14 @@ import com.bartlomiejpluta.base.engine.world.map.model.DefaultGameMap;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||
public class RenderableContext implements Context, Updatable, Renderable, Cleanable {
|
||||
@@ -38,17 +41,30 @@ public class RenderableContext implements Context, Updatable, Renderable, Cleana
|
||||
|
||||
@Getter
|
||||
private Screen screen;
|
||||
|
||||
@Getter
|
||||
private GameRunner gameRunner;
|
||||
|
||||
@Getter
|
||||
private Camera camera;
|
||||
|
||||
private Project project;
|
||||
private DefaultGameMap map;
|
||||
private MapHandler mapHandler;
|
||||
|
||||
private final List<GUI> guis = new LinkedList<>();
|
||||
|
||||
@Getter
|
||||
private Camera camera;
|
||||
|
||||
public void init(Screen screen, Camera camera) {
|
||||
@SneakyThrows
|
||||
public void init(Screen screen, Camera camera, Project project) {
|
||||
log.info("Initializing game context");
|
||||
this.screen = screen;
|
||||
this.camera = camera;
|
||||
this.project = project;
|
||||
|
||||
var runnerClass = classLoader.<GameRunner>loadClass(project.getRunner());
|
||||
gameRunner = runnerClass.getConstructor().newInstance();
|
||||
|
||||
gameRunner.init(this);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@@ -62,6 +78,7 @@ public class RenderableContext implements Context, Updatable, Renderable, Cleana
|
||||
|
||||
@Override
|
||||
public Entity createEntity(String entitySetUid) {
|
||||
log.info("Creating new entity with UID: [{}]", entitySetUid);
|
||||
return entityManager.createEntity(entitySetUid);
|
||||
}
|
||||
|
||||
@@ -72,6 +89,7 @@ public class RenderableContext implements Context, Updatable, Renderable, Cleana
|
||||
|
||||
@Override
|
||||
public GUI newGUI() {
|
||||
log.info("Creating new GUI");
|
||||
var gui = new NanoVGGUI(fontManager);
|
||||
guis.add(gui);
|
||||
gui.init(screen);
|
||||
@@ -79,6 +97,8 @@ public class RenderableContext implements Context, Updatable, Renderable, Cleana
|
||||
}
|
||||
|
||||
public void input(Screen screen) {
|
||||
gameRunner.input(screen);
|
||||
|
||||
if (mapHandler != null) {
|
||||
mapHandler.input(screen);
|
||||
}
|
||||
@@ -86,6 +106,8 @@ public class RenderableContext implements Context, Updatable, Renderable, Cleana
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
gameRunner.update(dt);
|
||||
|
||||
if (mapHandler != null) {
|
||||
mapHandler.update(this, map, dt);
|
||||
}
|
||||
@@ -112,6 +134,10 @@ public class RenderableContext implements Context, Updatable, Renderable, Cleana
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
log.info("Disposing game runner");
|
||||
gameRunner.dispose();
|
||||
|
||||
log.info("Disposing GUIs");
|
||||
guis.forEach(GUI::dispose);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.bartlomiejpluta.base.engine.util.profiling.fps;
|
||||
|
||||
import com.bartlomiejpluta.base.api.internal.gc.Cleanable;
|
||||
import com.bartlomiejpluta.base.api.internal.logic.Updatable;
|
||||
|
||||
public interface FPSMonitor extends Updatable, Cleanable {
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.bartlomiejpluta.base.engine.util.profiling.fps;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Comparator.comparingInt;
|
||||
import static java.util.function.Function.identity;
|
||||
import static java.util.stream.Collectors.counting;
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class LogFPSMonitor implements FPSMonitor {
|
||||
private static final int MOD = 30;
|
||||
private final List<Double> values = new LinkedList<>();
|
||||
private float fpsAccumulator = 0;
|
||||
private int pointer = 0;
|
||||
private double fps = 0;
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
fpsAccumulator += dt;
|
||||
|
||||
if (++pointer % MOD == 0) {
|
||||
fps = pointer / fpsAccumulator;
|
||||
fpsAccumulator = 0;
|
||||
pointer = 0;
|
||||
|
||||
values.add(fps);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
log.info("Min FPS: {}, max FPS: {}, avg FPS: {}",
|
||||
values.stream().min(Double::compareTo).orElse(-1.0),
|
||||
values.stream().max(Double::compareTo).orElse(-1.0),
|
||||
totalAverage()
|
||||
);
|
||||
|
||||
printHistogram();
|
||||
}
|
||||
|
||||
private double totalAverage() {
|
||||
return values.stream().reduce(0.0, Double::sum) / values.size();
|
||||
}
|
||||
|
||||
private void printHistogram() {
|
||||
values
|
||||
.stream()
|
||||
.mapToInt(Double::intValue)
|
||||
.boxed()
|
||||
.collect(groupingBy(identity(), counting()))
|
||||
.entrySet()
|
||||
.stream()
|
||||
.sorted(comparingInt(Map.Entry::getKey))
|
||||
.forEach(e -> log.info("{} FPS: {}% ({} occurrences)", e.getKey(), e.getValue() * 100.0f / values.size(), e.getValue()));
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.bartlomiejpluta.base.engine.util.profiling.time;
|
||||
|
||||
import com.bartlomiejpluta.base.api.internal.gc.Cleanable;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DefaultTimeProfilerService implements TimeProfilerService, Cleanable {
|
||||
private static final DecimalFormat DF = new DecimalFormat("0.00");
|
||||
private final Map<String, Double> averages = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void measure(String key, Runnable task) {
|
||||
var start = System.nanoTime();
|
||||
task.run();
|
||||
var time = System.nanoTime() - start;
|
||||
|
||||
if (!averages.containsKey(key)) {
|
||||
averages.put(key, time * 1.0);
|
||||
} else {
|
||||
averages.put(key, (averages.get(key) + time) / 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
averages.entrySet().stream()
|
||||
.sorted(Entry.<String, Double>comparingByValue().reversed())
|
||||
.forEachOrdered(entry -> log.info("[{}]: [{}ms] [{}us] [{}ns]",
|
||||
entry.getKey(),
|
||||
DF.format(entry.getValue() / 1_000_000),
|
||||
DF.format(entry.getValue() / 1_000),
|
||||
DF.format(entry.getValue())
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.bartlomiejpluta.base.engine.util.profiling.time;
|
||||
|
||||
public interface TimeProfilerService {
|
||||
void measure(String key, Runnable task);
|
||||
}
|
||||
Reference in New Issue
Block a user