diff --git a/config.json b/config.json index d246eec7..3601e59f 100644 --- a/config.json +++ b/config.json @@ -2,8 +2,8 @@ "game": { "maze": { "directory": "maps", - "procedural": true, - "maze_file": "test/orb_drop.maze" + "procedural": false, + "maze_file": "test/itemRoom.maze" }, "disable_enemies": true }, @@ -21,10 +21,10 @@ "client": { "default_name": "Conan O'Brien", "lobby_discovery": true, - "fullscreen": true, + "fullscreen": false, "draw_bboxes": false, "fps_counter": true, "presentation": false, - "render": 75 + "render": 50 } } diff --git a/include/client/client.hpp b/include/client/client.hpp index b6c87ca1..4c3ee6e1 100644 --- a/include/client/client.hpp +++ b/include/client/client.hpp @@ -277,6 +277,7 @@ class Client { std::unique_ptr lava_cross_model; std::unique_ptr lava_vertical_model; std::unique_ptr lava_horizontal_model; + std::unique_ptr lightning_model; GLFWwindow *window; diff --git a/include/server/game/exit.hpp b/include/server/game/exit.hpp index a98fb9d4..52de0881 100644 --- a/include/server/game/exit.hpp +++ b/include/server/game/exit.hpp @@ -13,6 +13,9 @@ class Exit : public Object { void doCollision(Object* other, ServerGameState& state) override; virtual SharedObject toShared() override; + + void setIntensity(float val); private: + float intensity; PointLightProperties properties; }; \ No newline at end of file diff --git a/include/server/game/introcutscene.hpp b/include/server/game/introcutscene.hpp index 45211a3c..9db08ede 100644 --- a/include/server/game/introcutscene.hpp +++ b/include/server/game/introcutscene.hpp @@ -25,6 +25,17 @@ class IntroCutscene { LoadIntroCutsceneEvent toNetwork(); + inline static const int START_TICK = 1; + inline static const int STOP_MOVING_TICK = START_TICK + 250; + inline static const int GATE_RAISE_TICK = STOP_MOVING_TICK + 30; + inline static const int GATE_STOP_RAISE_TICK = GATE_RAISE_TICK + 200; + inline static const int LIGHTNING_1_TICK = GATE_STOP_RAISE_TICK + 80; + inline static const int LIGHTNING_2_TICK = LIGHTNING_1_TICK + 50; + inline static const int LIGHTNING_3_TICK = LIGHTNING_2_TICK + 40; + inline static const int START_PLAYER_THEME_TICK = LIGHTNING_3_TICK + 110; + inline static const int EXIT_CUTSCENE_TICK = START_PLAYER_THEME_TICK + 240; + + int ticks; // just making everything public bc lazy ServerGameState state; diff --git a/include/server/game/torchlight.hpp b/include/server/game/torchlight.hpp index 2740da37..e3db996c 100644 --- a/include/server/game/torchlight.hpp +++ b/include/server/game/torchlight.hpp @@ -34,13 +34,21 @@ class Torchlight : public Object { */ void doTick(ServerGameState& state, std::optional lightning_light_cut_pos, std::optional action_light_cut_pos); + /** + * @brief manually set torchlight intensity, for use in intro cutscene + */ + void overrideIntensity(float val); + /** * @brief get current intensity of torch from 0-1 */ float getIntensity() const; + + bool is_cut; private: PointLightProperties properties; + // current intensity from 0-1 that gets // sent to client float curr_intensity; diff --git a/include/server/game/weaponcollider.hpp b/include/server/game/weaponcollider.hpp index f4f16afe..bdad7b32 100644 --- a/include/server/game/weaponcollider.hpp +++ b/include/server/game/weaponcollider.hpp @@ -33,7 +33,7 @@ class WeaponCollider : public Object { bool timeOut(ServerGameState& state); virtual SharedObject toShared() override; -private: +protected: std::chrono::time_point preparing_time; std::chrono::time_point attacked_time; Player* usedPlayer; @@ -92,7 +92,7 @@ class Lightning : public WeaponCollider { virtual SharedObject toShared() override { auto so = WeaponCollider::toShared(); so.pointLightInfo = SharedPointLightInfo { - .intensity = 1.0f, + .intensity = (this->info.attacked) ? 1.0f : 0.3f, .ambient_color = this->properties.ambient_color, .diffuse_color = this->properties.diffuse_color, .specular_color = this->properties.specular_color, diff --git a/include/shared/game/event.hpp b/include/shared/game/event.hpp index 97c60d37..ba443681 100644 --- a/include/shared/game/event.hpp +++ b/include/shared/game/event.hpp @@ -288,8 +288,9 @@ struct UpdateLightSourcesEvent { struct UpdatedLightSource { EntityID eid; float intensity; + bool is_cut; DEF_SERIALIZE(Archive& ar, const unsigned int version) { - ar & eid & intensity; + ar & eid & intensity & is_cut; } }; std::array, MAX_POINT_LIGHTS> lightSources; diff --git a/include/shared/game/sharedobject.hpp b/include/shared/game/sharedobject.hpp index da74babf..838ac045 100644 --- a/include/shared/game/sharedobject.hpp +++ b/include/shared/game/sharedobject.hpp @@ -239,9 +239,11 @@ struct SharedPointLightInfo { float attenuation_linear; float attenuation_quadratic; + bool is_cut = false; + DEF_SERIALIZE(Archive& ar, const int version) { ar & intensity & ambient_color & diffuse_color & specular_color & - attenuation_linear & attenuation_quadratic; + attenuation_linear & attenuation_quadratic & is_cut; } }; diff --git a/maps/cutscene/intro.maze b/maps/cutscene/intro.maze index 2c26434c..49d9604b 100644 --- a/maps/cutscene/intro.maze +++ b/maps/cutscene/intro.maze @@ -1,6 +1,6 @@ -##########[#####[#####[#### +################[########## .........................!o ..........@..............!o .........................!o .........................!o -##########]#####]#####]#### \ No newline at end of file +################]########## \ No newline at end of file diff --git a/src/client/client.cpp b/src/client/client.cpp index cc3a58f6..96973c92 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -256,6 +256,9 @@ bool Client::init() { auto exit_model_path = env_models_dir / "exit.obj"; this->exit_model = std::make_unique(exit_model_path.string(), true); + auto lightning_model_path = env_models_dir / "Lightning1" / "Lightning1_translated.obj"; + this->lightning_model = std::make_unique(lightning_model_path.string(), true); + auto player_walk_path = graphics_assets_dir / "animations/walk.fbx"; auto player_jump_path = graphics_assets_dir / "animations/jump.fbx"; auto player_idle_path = graphics_assets_dir / "animations/idle.fbx"; @@ -687,6 +690,8 @@ void Client::processServerInput(bool allow_defer) { this->closest_light_sources[i] = this->gameState.objects[light_id]; // update intensity with incoming intensity this->closest_light_sources[i]->pointLightInfo->intensity = updated_light_source.lightSources[i]->intensity; + this->closest_light_sources[i]->pointLightInfo->is_cut = updated_light_source.lightSources[i]->is_cut; + this->gameState.objects.at(light_id)->pointLightInfo->is_cut = updated_light_source.lightSources[i]->is_cut; } } else if (event.type == EventType::LoadIntroCutscene) { const auto& data = boost::get(event.data); @@ -1228,19 +1233,21 @@ void Client::geometryPass() { case ObjectType::WeaponCollider: { if (sharedObject->weaponInfo->lightning) { if (!sharedObject->weaponInfo->attacked) { - glm::vec3 preview_dims = sharedObject->physics.dimensions; - preview_dims.y = 0.01f; - this->item_model->setDimensions(preview_dims); + this->exit_model->setDimensions(glm::vec3(3.0f, 0.01f, 3.0f)); glm::vec3 preview_pos = sharedObject->physics.getCenterPosition(); preview_pos.y = 0.0f; - this->item_model->translateAbsolute(preview_pos); - this->item_model->draw(this->deferred_geometry_shader.get(), + this->exit_model->translateAbsolute(preview_pos); + this->exit_model->draw(this->deferred_geometry_shader.get(), this->cam->getPos(), true); } else { - this->item_model->setDimensions(sharedObject->physics.dimensions); - this->item_model->translateAbsolute(sharedObject->physics.getCenterPosition()); - this->item_model->draw(this->deferred_geometry_shader.get(), + this->lightning_model->setDimensions(glm::vec3(1.314906, 2.238910 * 2.0f, 0.019732) * 10.0f); + this->lightning_model->translateAbsolute(sharedObject->physics.corner); + glm::vec3 facing_curr_player = rotate90DegreesAroundYAxis(glm::normalize( + sharedObject->physics.getCenterPosition() - cam->getPos() + )); + this->lightning_model->rotateAbsolute(facing_curr_player); + this->lightning_model->draw(this->deferred_geometry_shader.get(), this->cam->getPos(), true); } @@ -1336,6 +1343,10 @@ void Client::lightingPass() { for (int i = 0; i < closest_lights->size(); i++) { boost::optional& curr_source = closest_lights->at(i); if (!curr_source.has_value()) { + // put the light in africa so it isn't shown + // important for intro cutscene since other lights wont replace entries that are removed! + glm::vec3 FAR_AWAY(10000, 10000, 10000); + lighting_shader->setVec3("pointLights[" + std::to_string(i) + "].position", FAR_AWAY); continue; } @@ -1427,14 +1438,25 @@ void Client::lightingPass() { Model* torch_frame_model = animManager->updateFrameAnimation(glfwGetTime()); glm::vec3 dims = torch_frame_model->getDimensions(); this->deferred_light_box_shader->use(); - this->deferred_light_box_shader->setVec3("lightColor", properties.diffuse_color); + + glm::vec3 flame_color; + + if (sharedObject->pointLightInfo->is_cut) { + glm::vec3 black(0.1f, 0.1f, 0.1f); + flame_color = black; + } else { + flame_color = properties.diffuse_color; + } + + this->deferred_light_box_shader->setVec3("lightColor", flame_color); + // this->torchlight_model->setDimensions(2.0f * sharedObject->physics.dimensions); // this->torchlight_model->translateAbsolute(sharedObject->physics.getCenterPosition()); // this->torchlight_model->draw(this->deferred_light_box_shader.get(), this->cam->getPos(), true); torch_frame_model->setDimensions(2.0f * sharedObject->physics.dimensions); torch_frame_model->translateAbsolute(sharedObject->physics.getCenterPosition()); // torch_frame_model->draw(this->deferred_light_box_shader.get(), this->cam->getPos(), true); - torch_frame_model->draw(this->deferred_light_box_shader.get(), this->cam->getPos(), true, properties.diffuse_color); + torch_frame_model->draw(this->deferred_light_box_shader.get(), this->cam->getPos(), true, flame_color); } } diff --git a/src/server/game/exit.cpp b/src/server/game/exit.cpp index 3ca8bfa5..1fdb1d8e 100644 --- a/src/server/game/exit.cpp +++ b/src/server/game/exit.cpp @@ -9,6 +9,11 @@ Exit::Exit(bool open, glm::vec3 corner, glm::vec3 dimensions, const PointLightPr properties(properties) { this->shared.open = open; + this->intensity = 1.0f; +} + +void Exit::setIntensity(float val) { + this->intensity = val; } void Exit::doCollision(Object* other, ServerGameState& state) { @@ -36,12 +41,12 @@ SharedObject Exit::toShared() { auto so = Object::toShared(); so.exit = this->shared; so.pointLightInfo = SharedPointLightInfo { - .intensity = 1.0f, + .intensity = this->intensity, .ambient_color = this->properties.ambient_color, .diffuse_color = this->properties.diffuse_color, .specular_color = this->properties.specular_color, .attenuation_linear = this->properties.attenuation_linear, - .attenuation_quadratic = this->properties.attenuation_quadratic, + .attenuation_quadratic = this->properties.attenuation_quadratic }; return so; } \ No newline at end of file diff --git a/src/server/game/introcutscene.cpp b/src/server/game/introcutscene.cpp index 11fb814f..791679fb 100644 --- a/src/server/game/introcutscene.cpp +++ b/src/server/game/introcutscene.cpp @@ -4,6 +4,7 @@ #include "server/game/weaponcollider.hpp" #include "shared/audio/constants.hpp" #include "shared/utilities/rng.hpp" +#include "server/game/exit.hpp" #include @@ -18,6 +19,7 @@ GameConfig getCutsceneConfig() { IntroCutscene::IntroCutscene(): state(GamePhase::INTRO_CUTSCENE, getCutsceneConfig()) { + this->ticks = 0; // state has loaded in the maze file we use for this cutscene, // hard code direction to face right based on the intro cutscene maze orientation @@ -62,17 +64,23 @@ IntroCutscene::IntroCutscene(): this->state.objects.createObject(dm); this->dm_eid = dm->globalID; + auto exits = this->state.objects.getExits(); + for (int i = 0; i < exits.size(); i++) { + auto exit = exits.get(i); + if (exit == nullptr) continue; + + exit->setIntensity(0.0f); + } + // load this->lights before sending down so the torch tick stuff works right } bool IntroCutscene::update() { this->state.updateMovement(); - this->state.doTorchlightTicks(); this->state.updateItems(); this->state.deleteEntities(); this->state.updateAttacks(); - static int ticks = 0; ticks++; Player* player = this->state.objects.getPlayer(0); @@ -80,15 +88,6 @@ bool IntroCutscene::update() { Player* player_right = this->state.objects.getPlayer(2); DungeonMaster* dm = this->state.objects.getDM(); - const int START_TICK = 1; - const int STOP_MOVING_TICK = START_TICK + 250; - const int GATE_RAISE_TICK = STOP_MOVING_TICK + 30; - const int GATE_STOP_RAISE_TICK = GATE_RAISE_TICK + 200; - const int LIGHTNING_1_TICK = GATE_STOP_RAISE_TICK + 80; - const int LIGHTNING_2_TICK = LIGHTNING_1_TICK + 50; - const int LIGHTNING_3_TICK = LIGHTNING_2_TICK + 40; - const int START_PLAYER_THEME_TICK = LIGHTNING_3_TICK + 110; - const int EXIT_CUTSCENE_TICK = START_PLAYER_THEME_TICK + 240; if (ticks == START_TICK) { this->state.soundTable().addNewSoundSource(SoundSource( @@ -119,6 +118,18 @@ bool IntroCutscene::update() { } if (ticks >= GATE_RAISE_TICK && ticks <= GATE_STOP_RAISE_TICK) { + const int RAISE_TICK_DUR = GATE_STOP_RAISE_TICK - GATE_RAISE_TICK; + float intensity = static_cast(ticks - GATE_RAISE_TICK) / RAISE_TICK_DUR; + + // make exits slowly brighter as it opens + auto exits = this->state.objects.getExits(); + for (int i = 0; i < exits.size(); i++) { + auto exit = exits.get(i); + if (exit == nullptr) continue; + + exit->setIntensity(intensity); + } + bool played_sound = false; auto walls = this->state.objects.getSolidSurfaces(); @@ -153,6 +164,25 @@ bool IntroCutscene::update() { .attenuation_quadratic = 0.0075f }; + const int TORCH_DECAY_NUM_TICKS = 100; + static int decay_tick = 0; + + if (ticks < LIGHTNING_1_TICK - TORCH_DECAY_NUM_TICKS) { + this->state.doTorchlightTicks(); + } else if (ticks < LIGHTNING_1_TICK) { + auto torches = this->state.objects.getTorchlights(); + for (int i = 0; i < torches.size(); i++) { + auto torch = torches.get(i); + if (torch == nullptr) continue; + + float intensity = 0.3f * (static_cast(TORCH_DECAY_NUM_TICKS - decay_tick) / TORCH_DECAY_NUM_TICKS) + 0.1f; + + torch->overrideIntensity(intensity); + } + decay_tick++; + } + + if (ticks == LIGHTNING_1_TICK) { this->state.soundTable().addNewSoundSource(SoundSource( ServerSFX::ZeusStartTheme, @@ -162,6 +192,7 @@ bool IntroCutscene::update() { FAR_ATTEN )); this->state.objects.createObject(new Lightning(lightning_pos1, player->physics.shared.facing, light_properties)); + } if (ticks == LIGHTNING_2_TICK) { @@ -170,7 +201,7 @@ bool IntroCutscene::update() { } if (ticks == LIGHTNING_3_TICK) { - glm::vec3 lightning_pos3 = player->physics.shared.getCenterPosition() + directionToFacing(Direction::RIGHT) * Grid::grid_cell_width * 1.5f; + glm::vec3 lightning_pos3 = player->physics.shared.getCenterPosition() + directionToFacing(Direction::RIGHT) * Grid::grid_cell_width * 2.0f; this->state.objects.createObject(new Lightning(lightning_pos3, player->physics.shared.facing, light_properties)); } @@ -185,6 +216,27 @@ bool IntroCutscene::update() { } if (ticks == EXIT_CUTSCENE_TICK) { + player->animState = AnimState::SprintAnim; + player->physics.velocity = glm::normalize(player->physics.shared.facing) * 0.20f; + } + + if (ticks == EXIT_CUTSCENE_TICK + 20) { + player_left->animState = AnimState::SprintAnim; + player_left->physics.velocity = glm::normalize(player->physics.shared.facing) * 0.20f; + player_right->animState = AnimState::SprintAnim; + player_right->physics.velocity = glm::normalize(player->physics.shared.facing) * 0.20f; + } + + if (ticks == EXIT_CUTSCENE_TICK + 100) { + this->state.soundTable().addNewSoundSource(SoundSource( + ServerSFX::Teleport, + player->physics.shared.getCenterPosition(), + FULL_VOLUME, + FAR_DIST, + FAR_ATTEN + )); + } + if (ticks == EXIT_CUTSCENE_TICK + 105) { return true; } @@ -203,12 +255,20 @@ LoadIntroCutsceneEvent IntroCutscene::toNetwork() { } } + std::array, MAX_POINT_LIGHTS> empty; + std::swap(this->lights, empty); + std::size_t lights_idx = 0; for (int i = 0; i < this->state.objects.getObjects().size(); i++) { auto object = this->state.objects.getObject(i); if (object == nullptr) continue; - if (lights_idx < MAX_POINT_LIGHTS && object->type == ObjectType::Torchlight) { + if (lights_idx < MAX_POINT_LIGHTS && + (object->type == ObjectType::Torchlight || + object->type == ObjectType::Exit || + object->type == ObjectType::WeaponCollider // lightning + )) { + this->lights[lights_idx] = object->toShared(); lights_idx++; } diff --git a/src/server/game/lava.cpp b/src/server/game/lava.cpp index 1de63545..d1086758 100644 --- a/src/server/game/lava.cpp +++ b/src/server/game/lava.cpp @@ -38,7 +38,7 @@ SharedObject Lava::toShared() { .diffuse_color = this->light_properties.diffuse_color, .specular_color = this->light_properties.specular_color, .attenuation_linear = this->light_properties.attenuation_linear, - .attenuation_quadratic = this->light_properties.attenuation_quadratic, + .attenuation_quadratic = this->light_properties.attenuation_quadratic }; return so; } diff --git a/src/server/game/orb.cpp b/src/server/game/orb.cpp index 3454c062..76834160 100644 --- a/src/server/game/orb.cpp +++ b/src/server/game/orb.cpp @@ -104,7 +104,7 @@ SharedObject Orb::toShared() { .diffuse_color = this->properties.diffuse_color, .specular_color = this->properties.specular_color, .attenuation_linear = this->properties.attenuation_linear, - .attenuation_quadratic = this->properties.attenuation_quadratic, + .attenuation_quadratic = this->properties.attenuation_quadratic }; return so; } \ No newline at end of file diff --git a/src/server/game/torchlight.cpp b/src/server/game/torchlight.cpp index 0e0e1e7b..61ad6e7e 100644 --- a/src/server/game/torchlight.cpp +++ b/src/server/game/torchlight.cpp @@ -16,7 +16,7 @@ SharedObject Torchlight::toShared() { .diffuse_color = this->properties.diffuse_color, .specular_color = this->properties.specular_color, .attenuation_linear = this->properties.attenuation_linear, - .attenuation_quadratic = this->properties.attenuation_quadratic, + .attenuation_quadratic = this->properties.attenuation_quadratic }; return so; } @@ -114,6 +114,8 @@ Torchlight::Torchlight( } void Torchlight::init() { + this->is_cut = false; + this->inc_intensity = true; // if not flickering, set intensity to a static // value @@ -151,10 +153,13 @@ void Torchlight::doTick(ServerGameState& state, std::optional lightni // if within threshold, black out (slightly expand the light cut action range) if (glm::distance(pos, this->physics.shared.getCenterPosition()) <= (1.5 * LIGHT_CUT_RANGE)) { this->curr_intensity = 0.0f; + this->is_cut = true; return; } } + this->is_cut = false; + // either increment or decrement intensity if (inc_intensity) { this->curr_step += this->flickering_speed; @@ -187,3 +192,8 @@ void Torchlight::doTick(ServerGameState& state, std::optional lightni float Torchlight::getIntensity() const { return this->curr_intensity; } + + +void Torchlight::overrideIntensity(float val) { + this->curr_intensity = val; +} \ No newline at end of file diff --git a/src/server/server.cpp b/src/server/server.cpp index b0ae27fd..8e95661d 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -174,13 +174,15 @@ void Server::sendLightSourceUpdates(EntityID playerID) { if (torchlight != nullptr) { event_data.lightSources[curr_light_num] = UpdateLightSourcesEvent::UpdatedLightSource { .eid = light_id, - .intensity = torchlight->getIntensity() + .intensity = torchlight->getIntensity(), + .is_cut = torchlight->is_cut }; } } else { event_data.lightSources[curr_light_num] = UpdateLightSourcesEvent::UpdatedLightSource { .eid = light_id, - .intensity = 1.0f + .intensity = 1.0f, + .is_cut = false }; } curr_light_num++;