move chunk loading into world class
This commit is contained in:
parent
6a001c4840
commit
4f83af1857
4 changed files with 156 additions and 74 deletions
|
@ -5,7 +5,7 @@ using namespace std::chrono;
|
|||
|
||||
namespace app {
|
||||
|
||||
Minecraft::Minecraft() : xeEngine{WIDTH, HEIGHT, "Minecraft Vulkan", "res/image/icon.png"} {};
|
||||
Minecraft::Minecraft() : engine{WIDTH, HEIGHT, "Minecraft Vulkan", "res/image/icon.png"} {};
|
||||
|
||||
Minecraft::~Minecraft() {}
|
||||
|
||||
|
@ -13,83 +13,35 @@ void Minecraft::run() {
|
|||
|
||||
Chunk::load();
|
||||
|
||||
auto viewerObject = xe::GameObject::createGameObject();
|
||||
viewerObject.transform.translation = {0.f, 40.f, 0.f};
|
||||
viewerObject.transform.rotation.y = glm::radians(45.f);
|
||||
auto viewer = xe::GameObject::createGameObject();
|
||||
viewer.transform.translation = {0.f, 40.f, 0.f};
|
||||
viewer.transform.rotation.y = glm::radians(45.f);
|
||||
|
||||
createGameObjects(viewerObject);
|
||||
|
||||
ChunkRenderer renderer{Chunk::getTextures()};
|
||||
World world {viewer, 10, 12345};
|
||||
|
||||
xe::Sound sound{"res/sound/when_the_world_ends.wav"};
|
||||
sound.setLooping(true);
|
||||
sound.play();
|
||||
|
||||
PlayerController cameraController{xeEngine.getInput(), viewerObject};
|
||||
PlayerController playerController{engine.getInput(), viewer};
|
||||
|
||||
while (xeEngine.poll()) {
|
||||
while (engine.poll()) {
|
||||
|
||||
float frameTime = xeEngine.getFrameTime();
|
||||
playerController.update(engine.getFrameTime());
|
||||
|
||||
cameraController.update(frameTime);
|
||||
xeEngine.getCamera().setViewYXZ(viewerObject.transform.translation, viewerObject.transform.rotation);
|
||||
world.reloadChunks();
|
||||
|
||||
if(xeEngine.beginFrame()) {
|
||||
renderer.render(loadedChunks, xeEngine.getCamera());
|
||||
xeEngine.endFrame();
|
||||
if(engine.beginFrame()) {
|
||||
world.render(engine.getCamera());
|
||||
engine.endFrame();
|
||||
}
|
||||
|
||||
reloadLoadedChunks(viewerObject);
|
||||
|
||||
}
|
||||
|
||||
xeEngine.close();
|
||||
engine.close();
|
||||
|
||||
Chunk::unload();
|
||||
|
||||
}
|
||||
|
||||
void Minecraft::createGameObjects(xe::GameObject& viewer) {
|
||||
int width = 2*RENDER_DISTANCE+1;
|
||||
loadedChunks.clear();
|
||||
for(int32_t x = 0; x < width; x++) {
|
||||
for(int32_t z = 0; z < width; z++) {
|
||||
auto gameObject = xe::GameObject::createGameObject();
|
||||
gameObject.transform.translation = glm::vec3(0.f);
|
||||
loadedChunks.push_back(std::move(gameObject));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Minecraft::reloadLoadedChunks(xe::GameObject& viewer) {
|
||||
viewX = static_cast<int>(floor(viewer.transform.translation.x / Chunk::CHUNK_SIZE.x));
|
||||
viewZ = static_cast<int>(floor(viewer.transform.translation.z / Chunk::CHUNK_SIZE.z));
|
||||
int width = 2*RENDER_DISTANCE+1;
|
||||
int minX = viewX - RENDER_DISTANCE;
|
||||
int minZ = viewZ - RENDER_DISTANCE;
|
||||
int maxX = viewX + RENDER_DISTANCE;
|
||||
int maxZ = viewZ + RENDER_DISTANCE;
|
||||
for(int32_t x = 0; x < width; x++) {
|
||||
for(int32_t z = 0; z < width; z++) {
|
||||
auto& gameObject = loadedChunks[x + z * width];
|
||||
int gridX = static_cast<int>(floor(gameObject.transform.translation.x / Chunk::CHUNK_SIZE.x));
|
||||
int gridZ = static_cast<int>(floor(gameObject.transform.translation.z / Chunk::CHUNK_SIZE.z));
|
||||
int newGridX = minX + x;
|
||||
int newGridZ = minZ + z;
|
||||
if(gridX < minX || gridZ < minZ || gridX > maxX || gridZ > maxZ)
|
||||
Chunk::deleteChunk(gridX, gridZ);
|
||||
Chunk* chunk = Chunk::getChunk(newGridX, newGridZ);
|
||||
if(chunk == nullptr) {
|
||||
chunk = Chunk::newChunk(newGridX, newGridZ, 12345);
|
||||
Chunk::generateAsync(chunk);
|
||||
}
|
||||
if(chunk->getMesh() == nullptr){
|
||||
Chunk::createMeshAsync(chunk);
|
||||
}
|
||||
gameObject.model = chunk->getMesh();
|
||||
gameObject.transform.translation = glm::vec3(newGridX * Chunk::CHUNK_SIZE.x, 0, newGridZ * Chunk::CHUNK_SIZE.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,8 +3,8 @@
|
|||
#include "xe_engine.hpp"
|
||||
|
||||
#include "player_controller.hpp"
|
||||
#include "chunk_renderer.hpp"
|
||||
#include "chunk.hpp"
|
||||
#include "world.hpp"
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||
|
@ -23,24 +23,13 @@ class Minecraft {
|
|||
Minecraft();
|
||||
~Minecraft();
|
||||
|
||||
Minecraft(const Minecraft &) = delete;
|
||||
Minecraft operator=(const Minecraft &) = delete;
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
|
||||
static constexpr int WIDTH = 800;
|
||||
static constexpr int HEIGHT = 600;
|
||||
static constexpr int RENDER_DISTANCE = 10;
|
||||
|
||||
void createGameObjects(xe::GameObject& viewer);
|
||||
void reloadLoadedChunks(xe::GameObject& viewer);
|
||||
|
||||
|
||||
int viewX, viewZ;
|
||||
|
||||
xe::Engine xeEngine;
|
||||
std::vector<xe::GameObject> loadedChunks;
|
||||
xe::Engine engine;
|
||||
};
|
||||
}
|
98
src/world.cpp
Normal file
98
src/world.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include "world.hpp"
|
||||
|
||||
namespace app {
|
||||
|
||||
World::World(xe::GameObject& viewer, int renderDistance, int worldSeed)
|
||||
: viewer{viewer},
|
||||
renderDistance{renderDistance},
|
||||
worldSeed{worldSeed},
|
||||
chunkRenderer{Chunk::getTextures()} {
|
||||
reloadChunks(renderDistance);
|
||||
}
|
||||
|
||||
World::~World() {}
|
||||
|
||||
void World::reloadChunks() {
|
||||
int currentViewX = static_cast<int>(floor(viewer.transform.translation.x / Chunk::CHUNK_SIZE.x));
|
||||
int currentViewZ = static_cast<int>(floor(viewer.transform.translation.z / Chunk::CHUNK_SIZE.z));
|
||||
if(currentViewX != viewX || currentViewZ != viewZ) {
|
||||
viewX = currentViewX;
|
||||
viewZ = currentViewZ;
|
||||
unloadOldChunks();
|
||||
loadNewChunks();
|
||||
}
|
||||
updateChunkMeshs();
|
||||
}
|
||||
|
||||
void World::reloadChunks(int newRenderDistance) {
|
||||
renderDistance = newRenderDistance;
|
||||
viewX = static_cast<int>(floor(viewer.transform.translation.x / Chunk::CHUNK_SIZE.x));
|
||||
viewZ = static_cast<int>(floor(viewer.transform.translation.z / Chunk::CHUNK_SIZE.z));
|
||||
resetChunks();
|
||||
loadNewChunks();
|
||||
updateChunkMeshs();
|
||||
}
|
||||
|
||||
void World::resetChunks() {
|
||||
unloadOldChunks();
|
||||
loadedChunks.clear();
|
||||
int width = 2*renderDistance+1;
|
||||
for(int i = 0; i < width*width; i++) {
|
||||
auto gameObject = xe::GameObject::createGameObject();
|
||||
loadedChunks.push_back(std::move(gameObject));
|
||||
}
|
||||
}
|
||||
|
||||
void World::unloadOldChunks() {
|
||||
int minX = viewX - renderDistance;
|
||||
int minZ = viewZ - renderDistance;
|
||||
int maxX = viewX + renderDistance;
|
||||
int maxZ = viewZ + renderDistance;
|
||||
for(auto &object : loadedChunks) {
|
||||
int gridX = static_cast<int>(floor(object.transform.translation.x / Chunk::CHUNK_SIZE.x));
|
||||
int gridZ = static_cast<int>(floor(object.transform.translation.z / Chunk::CHUNK_SIZE.z));
|
||||
if(gridX < minX || gridZ < minZ || gridX > maxX || gridZ > maxZ){
|
||||
Chunk::deleteChunk(gridX, gridZ);
|
||||
object.model = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void World::loadNewChunks() {
|
||||
int width = 2*renderDistance+1;
|
||||
int minX = viewX - renderDistance;
|
||||
int minZ = viewZ - renderDistance;
|
||||
int maxX = viewX + renderDistance;
|
||||
int maxZ = viewZ + renderDistance;
|
||||
int i = 0;
|
||||
for(auto &object : loadedChunks) {
|
||||
int gridX = minX + i % width;
|
||||
int gridZ = minZ + i / width;
|
||||
Chunk* chunk = Chunk::getChunk(gridX, gridZ);
|
||||
if(chunk == nullptr) {
|
||||
chunk = Chunk::newChunk(gridX, gridZ, worldSeed);
|
||||
Chunk::generateAsync(chunk);
|
||||
}
|
||||
object.transform.translation = glm::vec3(gridX * Chunk::CHUNK_SIZE.x, 0, gridZ * Chunk::CHUNK_SIZE.z);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void World::updateChunkMeshs() {
|
||||
for(auto &object : loadedChunks) {
|
||||
int gridX = static_cast<int>(floor(object.transform.translation.x / Chunk::CHUNK_SIZE.x));
|
||||
int gridZ = static_cast<int>(floor(object.transform.translation.z / Chunk::CHUNK_SIZE.z));
|
||||
Chunk* chunk = Chunk::getChunk(gridX, gridZ);
|
||||
if(chunk == nullptr) continue;
|
||||
if(chunk->getMesh() == nullptr)
|
||||
Chunk::createMeshAsync(chunk);
|
||||
object.model = chunk->getMesh();
|
||||
}
|
||||
}
|
||||
|
||||
void World::render(xe::Camera& camera) {
|
||||
camera.setViewYXZ(viewer.transform.translation, viewer.transform.rotation);
|
||||
chunkRenderer.render(loadedChunks, camera);
|
||||
}
|
||||
|
||||
}
|
43
src/world.hpp
Normal file
43
src/world.hpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include "xe_game_object.hpp"
|
||||
#include "chunk_renderer.hpp"
|
||||
#include "chunk.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace app {
|
||||
|
||||
class World {
|
||||
|
||||
public:
|
||||
|
||||
World(xe::GameObject& viewer, int renderDistance, int worldSeed);
|
||||
~World();
|
||||
|
||||
void reloadChunks();
|
||||
void reloadChunks(int newRenderDistance);
|
||||
|
||||
void render(xe::Camera& camera);
|
||||
|
||||
private:
|
||||
|
||||
void resetChunks();
|
||||
|
||||
void unloadOldChunks();
|
||||
void loadNewChunks();
|
||||
void updateChunkMeshs();
|
||||
|
||||
int viewX, viewZ;
|
||||
|
||||
int worldSeed;
|
||||
int renderDistance;
|
||||
|
||||
const xe::GameObject& viewer;
|
||||
std::vector<xe::GameObject> loadedChunks;
|
||||
|
||||
ChunkRenderer chunkRenderer;
|
||||
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in a new issue