day-night loop, dynamic skybox, clock on debug panel
This commit is contained in:
@@ -110,6 +110,8 @@ void AssetsLoader::addDefaults(AssetsLoader& loader) {
|
||||
loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/main"), "main");
|
||||
loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/lines"), "lines");
|
||||
loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/ui"), "ui");
|
||||
loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/background"), "background");
|
||||
loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/skybox_gen"), "skybox_gen");
|
||||
|
||||
loader.add(ASSET_ATLAS, resdir/path(TEXTURES_FOLDER"/blocks"), "blocks");
|
||||
loader.add(ASSET_TEXTURE, resdir/path(TEXTURES_FOLDER"/menubg.png"), "menubg");
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#define PLAYER_FLAG_NOCLIP 0x2
|
||||
|
||||
#define WORLD_SECTION_MAIN 1
|
||||
#define WORLD_SECTION_DAYNIGHT 2
|
||||
|
||||
using glm::ivec2;
|
||||
using glm::vec3;
|
||||
@@ -235,11 +236,15 @@ void WorldFiles::writeWorldInfo(const WorldInfo& info) {
|
||||
BinaryWriter out;
|
||||
out.putCStr(WORLD_FORMAT_MAGIC);
|
||||
out.put(WORLD_FORMAT_VERSION);
|
||||
|
||||
out.put(WORLD_SECTION_MAIN);
|
||||
|
||||
out.putInt64(info.seed);
|
||||
out.put(info.name);
|
||||
|
||||
out.put(WORLD_SECTION_DAYNIGHT);
|
||||
out.putFloat32(info.daytime);
|
||||
out.putFloat32(info.daytimeSpeed);
|
||||
|
||||
files::write_bytes(getWorldFile(), (const char*)out.data(), out.size());
|
||||
}
|
||||
|
||||
@@ -260,6 +265,10 @@ bool WorldFiles::readWorldInfo(WorldInfo& info) {
|
||||
info.seed = inp.getInt64();
|
||||
info.name = inp.getString();
|
||||
break;
|
||||
case WORLD_SECTION_DAYNIGHT:
|
||||
info.daytime = inp.getFloat32();
|
||||
info.daytimeSpeed = inp.getFloat32();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -36,6 +36,8 @@ struct WorldInfo {
|
||||
std::string name;
|
||||
std::filesystem::path directory;
|
||||
uint64_t seed;
|
||||
float daytime;
|
||||
float daytimeSpeed;
|
||||
};
|
||||
|
||||
class WorldFiles {
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "Skybox.h"
|
||||
#include <GL/glew.h>
|
||||
#include <iostream>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "../../graphics/Shader.h"
|
||||
#include "../../graphics/Mesh.h"
|
||||
#include "../../window/Window.h"
|
||||
|
||||
using glm::vec3;
|
||||
|
||||
Skybox::Skybox(uint size, Shader* shader) : size(size), shader(shader) {
|
||||
glGenTextures(1, &cubemap);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
for (uint face = 0; face < 6; face++) {
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
}
|
||||
glGenFramebuffers(1, &fbo);
|
||||
|
||||
float vertices[] {
|
||||
-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
|
||||
-1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f
|
||||
};
|
||||
vattr attrs[] {2, 0};
|
||||
mesh = new Mesh(vertices, 6, attrs);
|
||||
}
|
||||
|
||||
Skybox::~Skybox() {
|
||||
glDeleteTextures(1, &cubemap);
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
void Skybox::draw(Shader* shader) {
|
||||
shader->uniform1i("u_cubemap", 1);
|
||||
bind();
|
||||
mesh->draw();
|
||||
unbind();
|
||||
}
|
||||
|
||||
void Skybox::refresh(float t, float mie, uint quality) {
|
||||
ready = true;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
|
||||
shader->use();
|
||||
Window::viewport(0,0, size,size);
|
||||
const vec3 xaxs[] = {
|
||||
{0.0f, 0.0f, -1.0f},
|
||||
{0.0f, 0.0f, 1.0f},
|
||||
{-1.0f, 0.0f, 0.0f},
|
||||
|
||||
{-1.0f, 0.0f, 0.0f},
|
||||
{-1.0f, 0.0f, 0.0f},
|
||||
{1.0f, 0.0f, 0.0f},
|
||||
};
|
||||
const vec3 yaxs[] = {
|
||||
{0.0f, 1.0f, 0.0f},
|
||||
{0.0f, 1.0f, 0.0f},
|
||||
{0.0f, 0.0f, -1.0f},
|
||||
|
||||
{0.0f, 0.0f, 1.0f},
|
||||
{0.0f, 1.0f, 0.0f},
|
||||
{0.0f, 1.0f, 0.0f},
|
||||
};
|
||||
|
||||
const vec3 zaxs[] = {
|
||||
{1.0f, 0.0f, 0.0f},
|
||||
{-1.0f, 0.0f, 0.0f},
|
||||
{0.0f, -1.0f, 0.0f},
|
||||
|
||||
{0.0f, 1.0f, 0.0f},
|
||||
{0.0f, 0.0f, -1.0f},
|
||||
{0.0f, 0.0f, 1.0f},
|
||||
};
|
||||
t *= M_PI*2.0f;
|
||||
|
||||
shader->uniform1i("u_quality", quality);
|
||||
shader->uniform1f("u_mie", mie);
|
||||
shader->uniform3f("u_lightDir", glm::normalize(vec3(sin(t), -cos(t), 0.7f)));
|
||||
for (uint face = 0; face < 6; face++) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
shader->uniform3f("u_xaxis", xaxs[face]);
|
||||
shader->uniform3f("u_yaxis", yaxs[face]);
|
||||
shader->uniform3f("u_zaxis", zaxs[face]);
|
||||
mesh->draw(GL_TRIANGLES);
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
Window::viewport(0, 0, Window::width, Window::height);
|
||||
}
|
||||
|
||||
void Skybox::bind() const {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
void Skybox::unbind() const {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef FRONTEND_GRAPHICS_SKYBOX_H_
|
||||
#define FRONTEND_GRAPHICS_SKYBOX_H_
|
||||
|
||||
#include "../../typedefs.h"
|
||||
|
||||
class Mesh;
|
||||
class Shader;
|
||||
|
||||
class Skybox {
|
||||
uint fbo;
|
||||
uint cubemap;
|
||||
uint size;
|
||||
Mesh* mesh;
|
||||
Shader* shader;
|
||||
bool ready = false;
|
||||
public:
|
||||
Skybox(uint size, Shader* shader);
|
||||
~Skybox();
|
||||
|
||||
void draw(Shader* shader);
|
||||
|
||||
void refresh(float t, float mie, uint quality);
|
||||
void bind() const;
|
||||
void unbind() const;
|
||||
bool isReady() const {
|
||||
return ready;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // FRONTEND_GRAPHICS_SKYBOX_H_
|
||||
+13
-3
@@ -11,6 +11,7 @@
|
||||
#include "../typedefs.h"
|
||||
#include "../content/Content.h"
|
||||
#include "../util/stringutil.h"
|
||||
#include "../util/timeutil.h"
|
||||
#include "../assets/Assets.h"
|
||||
#include "../graphics/Shader.h"
|
||||
#include "../graphics/Batch2D.h"
|
||||
@@ -128,13 +129,22 @@ HudRenderer::HudRenderer(Engine* engine,
|
||||
sub->add(box);
|
||||
panel->add(sub);
|
||||
}
|
||||
panel->add(shared_ptr<Label>(create_label([this](){
|
||||
int hour, minute, second;
|
||||
timeutil::from_value(this->level->world->daytime, hour, minute, second);
|
||||
|
||||
std::wstring timeString =
|
||||
util::lfill(std::to_wstring(hour), 2, L'0') + L":" +
|
||||
util::lfill(std::to_wstring(minute), 2, L'0');
|
||||
return L"time: "+timeString;
|
||||
})));
|
||||
{
|
||||
TrackBar* bar = new TrackBar(0.0f, 1.0f, 1.0f, 0.02f, 2);
|
||||
TrackBar* bar = new TrackBar(0.0f, 1.0f, 1.0f, 0.005f, 8);
|
||||
bar->supplier([=]() {
|
||||
return renderer->skyLightMutliplier;
|
||||
return level->world->daytime;
|
||||
});
|
||||
bar->consumer([=](double val) {
|
||||
renderer->skyLightMutliplier = val;
|
||||
level->world->daytime = val;
|
||||
});
|
||||
panel->add(bar);
|
||||
}
|
||||
|
||||
@@ -136,6 +136,9 @@ void LevelScreen::update(float delta) {
|
||||
level->chunks->saveAndClear();
|
||||
backlight = settings.graphics.backlight;
|
||||
}
|
||||
if (!hud->isPause()) {
|
||||
level->world->updateTimers(delta);
|
||||
}
|
||||
level->updatePlayer(delta, !inputLocked, hud->isPause(), !inputLocked);
|
||||
level->update();
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "../settings.h"
|
||||
#include "../engine.h"
|
||||
#include "ContentGfxCache.h"
|
||||
#include "graphics/Skybox.h"
|
||||
|
||||
using glm::vec3;
|
||||
using std::string;
|
||||
@@ -35,15 +36,19 @@ using std::shared_ptr;
|
||||
|
||||
WorldRenderer::WorldRenderer(Engine* engine, Level* level, const ContentGfxCache* cache)
|
||||
: engine(engine), level(level) {
|
||||
EngineSettings& settings = engine->getSettings();
|
||||
|
||||
lineBatch = new LineBatch(4096);
|
||||
renderer = new ChunksRenderer(level, cache, engine->getSettings());
|
||||
renderer = new ChunksRenderer(level, cache, settings);
|
||||
frustumCulling = new Frustum();
|
||||
level->events->listen(EVT_CHUNK_HIDDEN, [this](lvl_event_type type, Chunk* chunk) {
|
||||
renderer->unload(chunk);
|
||||
});
|
||||
skybox = new Skybox(64, engine->getAssets()->getShader("skybox_gen"));
|
||||
}
|
||||
|
||||
WorldRenderer::~WorldRenderer() {
|
||||
delete skybox;
|
||||
delete lineBatch;
|
||||
delete renderer;
|
||||
delete frustumCulling;
|
||||
@@ -100,6 +105,10 @@ void WorldRenderer::drawChunks(Chunks* chunks,
|
||||
|
||||
|
||||
void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion){
|
||||
EngineSettings& settings = engine->getSettings();
|
||||
skybox->refresh(level->world->daytime,
|
||||
fmax(1.0f, 18.0f/settings.chunks.loadDistance), 4);
|
||||
|
||||
const Content* content = level->content;
|
||||
const ContentIndices* contentIds = content->indices;
|
||||
Assets* assets = engine->getAssets();
|
||||
@@ -110,32 +119,32 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
|
||||
const Viewport& viewport = pctx.getViewport();
|
||||
int displayWidth = viewport.getWidth();
|
||||
int displayHeight = viewport.getHeight();
|
||||
Window::clearDepth();
|
||||
Window::viewport(0, 0, displayWidth, displayHeight);
|
||||
|
||||
Shader* backShader = assets->getShader("background");
|
||||
backShader->use();
|
||||
backShader->uniformMatrix("u_view", camera->getView(false));
|
||||
backShader->uniform1f("u_zoom", camera->zoom);
|
||||
backShader->uniform1f("u_ar", (float)Window::width/(float)Window::height);
|
||||
skybox->draw(backShader);
|
||||
|
||||
{
|
||||
GfxContext ctx = pctx.sub();
|
||||
ctx.depthTest(true);
|
||||
ctx.cullFace(true);
|
||||
|
||||
EngineSettings& settings = engine->getSettings();
|
||||
|
||||
vec3 skyColor(0.7f, 0.81f, 1.0f);
|
||||
skyColor *= skyLightMutliplier;
|
||||
|
||||
Window::setBgColor(skyColor);
|
||||
Window::clear();
|
||||
Window::viewport(0, 0, displayWidth, displayHeight);
|
||||
|
||||
float fogFactor = 18.0f / (float)settings.chunks.loadDistance;
|
||||
|
||||
shader->use();
|
||||
skybox->bind();
|
||||
shader->uniformMatrix("u_proj", camera->getProjection());
|
||||
shader->uniformMatrix("u_view", camera->getView());
|
||||
shader->uniform1f("u_gamma", 1.0f);
|
||||
shader->uniform3f("u_skyLightColor", vec3(1.1f) * skyLightMutliplier);
|
||||
shader->uniform3f("u_fogColor", skyColor);
|
||||
shader->uniform1f("u_fogFactor", fogFactor);
|
||||
shader->uniform1f("u_fogCurve", settings.graphics.fogCurve);
|
||||
shader->uniform3f("u_cameraPos", camera->position);
|
||||
shader->uniform1i("u_cubemap", 1);
|
||||
|
||||
Block* cblock = contentIds->getBlockDef(level->player->choosenBlock);
|
||||
assert(cblock != nullptr);
|
||||
@@ -168,6 +177,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
|
||||
}
|
||||
lineBatch->render();
|
||||
}
|
||||
skybox->unbind();
|
||||
}
|
||||
|
||||
if (level->player->debug) {
|
||||
@@ -175,7 +185,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
|
||||
ctx.depthTest(true);
|
||||
|
||||
linesShader->use();
|
||||
if (engine->getSettings().debug.showChunkBorders){
|
||||
if (settings.debug.showChunkBorders){
|
||||
linesShader->uniformMatrix("u_projview", camera->getProjView());
|
||||
vec3 coord = level->player->camera->position;
|
||||
if (coord.x < 0) coord.x--;
|
||||
|
||||
@@ -22,6 +22,7 @@ class Frustum;
|
||||
class Engine;
|
||||
class Chunks;
|
||||
class ContentGfxCache;
|
||||
class Skybox;
|
||||
|
||||
class WorldRenderer {
|
||||
Engine* engine;
|
||||
@@ -29,11 +30,10 @@ class WorldRenderer {
|
||||
Frustum* frustumCulling;
|
||||
LineBatch* lineBatch;
|
||||
ChunksRenderer* renderer;
|
||||
Skybox* skybox;
|
||||
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion);
|
||||
void drawChunks(Chunks* chunks, Camera* camera, Shader* shader, bool occlusion);
|
||||
public:
|
||||
float skyLightMutliplier = 1.0f; // will be replaced with day-night cycle
|
||||
|
||||
WorldRenderer(Engine* engine, Level* level, const ContentGfxCache* cache);
|
||||
~WorldRenderer();
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "timeutil.h"
|
||||
|
||||
float timeutil::time_value(float hour, float minute, float second) {
|
||||
return (hour + (minute + second / 60.0f) / 60.0f) / 24.0f;
|
||||
}
|
||||
|
||||
void timeutil::from_value(float value, int& hour, int& minute, int& second) {
|
||||
value *= 24;
|
||||
hour = value;
|
||||
value *= 60;
|
||||
minute = int(value) % 60;
|
||||
value *= 60;
|
||||
second = int(value) % 60;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef UTIL_TIMEUTIL_H_
|
||||
#define UTIL_TIMEUTIL_H_
|
||||
|
||||
namespace timeutil {
|
||||
float time_value(float hour, float minute, float second);
|
||||
void from_value(float value, int& hour, int& minute, int& second);
|
||||
}
|
||||
|
||||
#endif // UTIL_TIMEUTIL_H_
|
||||
@@ -42,11 +42,16 @@ mat4 Camera::getProjection(){
|
||||
return glm::ortho(0.0f, fov*aspect, 0.0f, fov);
|
||||
}
|
||||
|
||||
mat4 Camera::getView(){
|
||||
if (perspective)
|
||||
mat4 Camera::getView(bool pos){
|
||||
vec3 position = this->position;
|
||||
if (!pos) {
|
||||
position = vec3(0.0f);
|
||||
}
|
||||
if (perspective) {
|
||||
return glm::lookAt(position, position+front, up);
|
||||
else
|
||||
} else {
|
||||
return glm::translate(glm::mat4(1.0f), position);
|
||||
}
|
||||
}
|
||||
|
||||
mat4 Camera::getProjView(){
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ public:
|
||||
void rotate(float x, float y, float z);
|
||||
|
||||
mat4 getProjection();
|
||||
mat4 getView();
|
||||
mat4 getView(bool position=true);
|
||||
mat4 getProjView();
|
||||
};
|
||||
|
||||
|
||||
@@ -127,6 +127,10 @@ int Window::initialize(DisplaySettings& settings){
|
||||
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, GLFW_DONT_CARE);
|
||||
}
|
||||
glfwSwapInterval(settings.swapInterval);
|
||||
const GLubyte* vendor = glGetString(GL_VENDOR);
|
||||
const GLubyte* renderer = glGetString(GL_RENDERER);
|
||||
std::cout << "GL Vendor: " << (char*)vendor << std::endl;
|
||||
std::cout << "GL Renderer: " << (char*)renderer << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -134,6 +138,10 @@ void Window::clear() {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void Window::clearDepth() {
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void Window::setBgColor(glm::vec3 color) {
|
||||
glClearColor(color.r, color.g, color.b, 1.0f);
|
||||
}
|
||||
@@ -252,6 +260,7 @@ DisplaySettings* Window::getSettings() {
|
||||
|
||||
ImageData* Window::takeScreenshot() {
|
||||
ubyte* data = new ubyte[width * height * 3];
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||||
return new ImageData(ImageFormat::rgb888, width, height, data);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ public:
|
||||
static void resetScissor();
|
||||
|
||||
static void clear();
|
||||
static void clearDepth();
|
||||
static void setBgColor(glm::vec3 color);
|
||||
static double time();
|
||||
static DisplaySettings* getSettings();
|
||||
|
||||
+9
-2
@@ -29,6 +29,11 @@ World::~World(){
|
||||
delete wfile;
|
||||
}
|
||||
|
||||
void World::updateTimers(float delta) {
|
||||
daytime += delta * daytimeSpeed;
|
||||
daytime = fmod(daytime, 1.0f);
|
||||
}
|
||||
|
||||
void World::write(Level* level) {
|
||||
const Content* content = level->content;
|
||||
|
||||
@@ -41,15 +46,17 @@ void World::write(Level* level) {
|
||||
wfile->put(chunk.get());
|
||||
}
|
||||
|
||||
wfile->write(WorldInfo {name, wfile->directory, seed}, content);
|
||||
wfile->write(WorldInfo {name, wfile->directory, seed, daytime, daytimeSpeed}, content);
|
||||
wfile->writePlayer(level->player);
|
||||
}
|
||||
|
||||
Level* World::load(EngineSettings& settings, const Content* content) {
|
||||
WorldInfo info {name, wfile->directory, seed};
|
||||
WorldInfo info {name, wfile->directory, seed, daytime, daytimeSpeed};
|
||||
wfile->readWorldInfo(info);
|
||||
seed = info.seed;
|
||||
name = info.name;
|
||||
daytime = info.daytime;
|
||||
daytimeSpeed = info.daytimeSpeed;
|
||||
|
||||
vec3 playerPosition = vec3(0, 100, 0);
|
||||
Camera* camera = new Camera(playerPosition, glm::radians(90.0f));
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <filesystem>
|
||||
#include "../typedefs.h"
|
||||
#include "../settings.h"
|
||||
#include "../util/timeutil.h"
|
||||
|
||||
class Content;
|
||||
class WorldFiles;
|
||||
@@ -18,12 +19,20 @@ public:
|
||||
WorldFiles* wfile;
|
||||
uint64_t seed;
|
||||
|
||||
/* Day/night loop timer in range 0..1
|
||||
0.0 - is midnight
|
||||
0.5 - is noon
|
||||
*/
|
||||
float daytime = timeutil::time_value(10, 00, 00);
|
||||
float daytimeSpeed = 1.0f/60.0f/24.0f;
|
||||
|
||||
World(std::string name,
|
||||
std::filesystem::path directory,
|
||||
uint64_t seed,
|
||||
EngineSettings& settings);
|
||||
~World();
|
||||
|
||||
void updateTimers(float delta);
|
||||
void write(Level* level);
|
||||
Level* load(EngineSettings& settings, const Content* content);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user