diff --git a/src/kekrooms/cpp/kekrooms.cpp b/src/kekrooms/cpp/kekrooms.cpp index ffbaf4d..88ebfa8 100644 --- a/src/kekrooms/cpp/kekrooms.cpp +++ b/src/kekrooms/cpp/kekrooms.cpp @@ -1,6 +1,12 @@ +#include +#include +#include #include #include +#include #include +#include +#include #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btBoxShape.h" @@ -22,8 +28,103 @@ using namespace kek; +#define CHUNK_SIZE 64 +#define CHUNK_RADIUS 2 +#define WALLS_PER_CHUNK 20 +#define WALL_HEIGHT 9 + static ButtonElement *buttonPlay; +static SpotLight *flashlight; + +struct Chunk { + int x, z; + GameObject *floor; + GameObject *ceiling; + std::vector walls; +}; + +std::map loadedChunks; +Mesh *floorMesh; +TextElement *debugText; +std::shared_ptr red; +std::shared_ptr gray; + +void gameLoop(GLFWwindow *window, void *) { + Player *player = Engine::getPlayer(); + Camera *camera = Engine::getActiveCamera(); + glm::vec3 playerPos = player->getPosition(); + Scene *scene = Engine::getActiveScene(); + + SpotLight *fl = (SpotLight *) flashlight; + glm::vec3 playerRight = glm::cross(camera->direction, glm::vec3(0, 1, 0)); + fl->moveTo(playerPos + glm::normalize(playerRight) * 0.3f); + fl->lookAt(camera->direction); + + int chunkX = (int) playerPos.x / CHUNK_SIZE; + int chunkZ = (int) playerPos.z / CHUNK_SIZE; + debugText->setText("CX: " + std::to_string(chunkX) + ", CZ: " + std::to_string(chunkZ)); + + for(auto it = loadedChunks.cbegin(); it != loadedChunks.cend();) { + const Chunk *ch = &it->second; + if(std::abs(ch->x - chunkX) > CHUNK_RADIUS || abs(ch->z - chunkZ) > CHUNK_RADIUS) { + scene->removeObject(ch->floor); + + for(auto w : ch->walls) { + scene->removeObject(w); + } + + it = loadedChunks.erase(it); + continue; + } + + it = std::next(it); + } + + std::shared_ptr wallpaper = Texture::load("image/wallpaper.png"); + + for(int x = chunkX - CHUNK_RADIUS; x <= chunkX + CHUNK_RADIUS; x++) { + for(int z = chunkZ - CHUNK_RADIUS; z <= chunkZ + CHUNK_RADIUS; z++) { + long int chunkID = ((long int) x & 0xFFFF) << 16 | ((long int) z & 0xFFFF); + auto chunk = loadedChunks.find(chunkID); + if(chunk == loadedChunks.end()) { + GameObject *floor = new GameObject(); + floor->addMesh(genCubeMesh(CHUNK_SIZE, 2, CHUNK_SIZE, gray, gray, gray)); + floor->addPhysics(new btBoxShape(btVector3(CHUNK_SIZE / 2, 1, CHUNK_SIZE / 2)), 0, btCollisionObject::CF_STATIC_OBJECT); + floor->moveTo(glm::vec3(x * CHUNK_SIZE, 0, z * CHUNK_SIZE)); + scene->addObject(floor); + + GameObject *ceiling = new GameObject(); + ceiling->addMesh(genCubeMesh(CHUNK_SIZE, 2, CHUNK_SIZE, gray, gray, gray)); + ceiling->addPhysics(new btBoxShape(btVector3(CHUNK_SIZE / 2, 1, CHUNK_SIZE / 2)), 0, btCollisionObject::CF_STATIC_OBJECT); + ceiling->moveTo(glm::vec3(x * CHUNK_SIZE, WALL_HEIGHT, z * CHUNK_SIZE)); + scene->addObject(ceiling); + + std::vector walls; + std::srand(chunkID); + for(unsigned int i = 0; i < WALLS_PER_CHUNK; i++) { + double wallLength = (double) std::rand() / RAND_MAX * 20 + 10; + bool rotated = std::rand() < RAND_MAX / 2; + GameObject *wall = new GameObject(); + wall->addMesh(genCubeMesh(wallLength, WALL_HEIGHT, 1, wallpaper, wallpaper, wallpaper)); + wall->addPhysics(new btBoxShape(btVector3(wallLength / 2, WALL_HEIGHT / 2, 0.5)), 0, btCollisionObject::CF_STATIC_OBJECT); + wall->moveTo(glm::vec3(x * CHUNK_SIZE + ((double) rand() / RAND_MAX * CHUNK_SIZE), WALL_HEIGHT / 2, z * CHUNK_SIZE + ((double) rand() / RAND_MAX * CHUNK_SIZE))); + + if(rotated) { + wall->rotate(glm::radians(90.0f), glm::vec3(0, 1, 0)); + } + + scene->addObject(wall); + walls.push_back(wall); + } + + Chunk newChunk{x, z, floor, ceiling, walls}; + loadedChunks.emplace(chunkID, newChunk); + } + } + } +} + void startGame(void *) { buttonPlay->visible = false; @@ -31,23 +132,19 @@ void startGame(void *) { std::shared_ptr wallpaper = Texture::load("image/wallpaper.png"); std::shared_ptr white = Texture::generateColor(glm::vec3(1)); + red = Texture::generateColor(glm::vec3(1, 0, 0)); + gray = Texture::generateColor(glm::vec3(0.2, 0.2, 0.2)); - SpotLight *flashlight = new SpotLight(glm::vec3(1), glm::vec3(0), 2, 5, 5, 0.5, 0.7); - flashlight->moveTo(Engine::getPlayer()->getPosition()); + flashlight = new SpotLight(glm::vec3(1), glm::vec3(0), 2, 3, 5, 0.5, 0.6); + flashlight->moveTo(Engine::getPlayer()->getPosition() + glm::vec3(0, KEK_PLAYER_EYE_OFFSET, 0)); - Input::addPeriodicCallback(PeriodicCallback([](GLFWwindow *window, void *light) { - SpotLight *fl = (SpotLight *) light; - glm::vec3 playerRight = glm::cross(Engine::getActiveCamera()->direction, glm::vec3(0, 1, 0)); - fl->moveTo(Engine::getPlayer()->getPosition() + glm::normalize(playerRight) * 0.3f); - fl->lookAt(Engine::getActiveCamera()->direction); - }, - flashlight)); + Input::addPeriodicCallback(PeriodicCallback(gameLoop, nullptr)); std::shared_ptr cubeTexture = Texture::generateColor(glm::vec3(1, 0, 0)); - GameObject *floor = new GameObject(); - floor->addPhysics(new btBoxShape(btVector3(50, 0.5, 50)), 0, btCollisionObject::CF_STATIC_OBJECT); - floor->addMesh(genCubeMesh(100, 1, 100, cubeTexture, cubeTexture, white)); - scene->addObject(floor); + GameObject *floorObject = new GameObject(); + floorObject->addPhysics(new btBoxShape(btVector3(CHUNK_SIZE / 2, 0.5, CHUNK_SIZE / 2)), 0, btCollisionObject::CF_STATIC_OBJECT); + floorObject->addMesh(genCubeMesh(CHUNK_SIZE, 1, CHUNK_SIZE, cubeTexture, cubeTexture, white)); + scene->addObject(floorObject); for(unsigned int i = 0; i < 10; i++) { GameObject *cube = new GameObject(); @@ -58,7 +155,11 @@ void startGame(void *) { } scene->lights->add(flashlight); - scene->lights->add(new DirectionalLight(glm::vec3(0.001), glm::vec3(-0.1, -1, 0.1))); + scene->lights->add(new DirectionalLight(glm::vec3(0.005), glm::vec3(-0.1, -1, 0.1))); + + debugText = new TextElement(uiPx(10), uiPx(100)); + debugText->setText("Hello!"); + UI::addElement(debugText); Engine::setActiveScene(scene);