diff --git a/src/minecraft.cpp b/src/minecraft.cpp index a11421d..2c7bb8f 100755 --- a/src/minecraft.cpp +++ b/src/minecraft.cpp @@ -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(floor(viewer.transform.translation.x / Chunk::CHUNK_SIZE.x)); - viewZ = static_cast(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(floor(gameObject.transform.translation.x / Chunk::CHUNK_SIZE.x)); - int gridZ = static_cast(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); - } - } -} - } \ No newline at end of file diff --git a/src/minecraft.hpp b/src/minecraft.hpp index 5639ac7..59871b2 100755 --- a/src/minecraft.hpp +++ b/src/minecraft.hpp @@ -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 loadedChunks; + xe::Engine engine; }; } \ No newline at end of file diff --git a/src/world.cpp b/src/world.cpp new file mode 100644 index 0000000..485615d --- /dev/null +++ b/src/world.cpp @@ -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(floor(viewer.transform.translation.x / Chunk::CHUNK_SIZE.x)); + int currentViewZ = static_cast(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(floor(viewer.transform.translation.x / Chunk::CHUNK_SIZE.x)); + viewZ = static_cast(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(floor(object.transform.translation.x / Chunk::CHUNK_SIZE.x)); + int gridZ = static_cast(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(floor(object.transform.translation.x / Chunk::CHUNK_SIZE.x)); + int gridZ = static_cast(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); +} + +} \ No newline at end of file diff --git a/src/world.hpp b/src/world.hpp new file mode 100644 index 0000000..12e0285 --- /dev/null +++ b/src/world.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include "xe_game_object.hpp" +#include "chunk_renderer.hpp" +#include "chunk.hpp" + +#include + +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 loadedChunks; + + ChunkRenderer chunkRenderer; + +}; + +} \ No newline at end of file