// // level.cxx // danmaku // // Created by Sam Jaffe on 5/26/19. // Copyright © 2019 Sam Jaffe. All rights reserved. // #include "danmaku/level.hpp" #include #include "danmaku/actor.hpp" #include "danmaku/bullet.hpp" #include "danmaku/player.hpp" #include "danmaku/serial.hpp" #include "game/graphics/renderer.hpp" #include "game/math/common.hpp" #include "game/util/env.hpp" #include "resource_factory/prototype_factory.hpp" using namespace danmaku; struct wave_helper { using wave_t = std::vector>; wave_t get_wave(Json::Value const & json) { wave_t out; for (int i = 0; i < json.size(); ++i) { std::string file = mappings[json[i]["id"].asString()].asString(); std::string path = env::resource_file("scripts/entity/" + file); Json::Value actor = engine::read_file(path); actor["position"] = json[i]["position"]; out.emplace_back(to_actor(actor, manager)); } return out; } std::deque operator()() { std::deque out; for (int i = 0; i < waves.size(); ++i) { out.emplace_back(get_wave(waves[i])); } return out; } wave_helper(Json::Value const & json, graphics::manager const & mgr) : waves(json["waves"]), mappings(json["mappings"]), manager(mgr) {} Json::Value const & waves; Json::Value const & mappings; graphics::manager const & manager; }; level::level(Json::Value const & json, std::shared_ptr dispatch) : engine::scene(json["id"].asString(), dispatch), player_(), wave_timer_{json["timeBetweenWaves"].asFloat()}, waves_(wave_helper{json, graphics_manager()}()) {} level::level(std::string const & id, Json::Value const & json, std::shared_ptr dispatch) : engine::scene(id, dispatch), player_(), wave_timer_{json["timeBetweenWaves"].asFloat()}, waves_(wave_helper{json, graphics_manager()}()) {} level::~level() {} void level::add_bullet(bullet b) { bullets_.emplace_back(std::make_unique(std::move(b))); // TODO: Add to correct collision boxes... collidables[0].emplace_back(bullets_.back().get()); } template void level::perform_oob_culling_impl(std::vector> & data) { // TODO: Aquire screen size correctly...? math::dim2::rectangle bound{{{0.f, 0.f}}, {{3840.f, 2160.f}}}; auto is_oob = [&bound](std::unique_ptr & ptr) { return !math::intersects(ptr->render_info().points, bound); }; auto it = std::remove_if(data.begin(), data.end(), is_oob); auto remove_collider = [this](std::unique_ptr & ptr) { // TODO: colliders, use the collision enums. collidables[0].erase( std::remove(collidables[0].begin(), collidables[0].end(), ptr.get()), collidables[0].end()); }; std::for_each(it, data.end(), remove_collider); data.erase(it, data.end()); } void level::perform_oob_culling() { // perform_oob_culling_impl(actors_); perform_oob_culling_impl(bullets_); } void level::update(float delta) { perform_oob_culling(); update_waves(delta); update_object(delta); check_collisions(); } void level::update_object(float delta) { player_->update(delta); for (auto & a : actors_) { a->update(delta); } for (auto & b : bullets_) { b->update(delta); } } void level::check_collisions() { engine::scene::check_collisions(); // TODO: This is a bad hack until I can properly disassociate collision info for (auto & b : bullets_) { if (math::intersects(player_->render_info().points, b->render_info().points)) { player_->hit(*b); } } } void level::update_waves(float delta) { if (waves_.empty()) { return; } if ((wave_timer_.remainder -= delta) <= 0.f) { wave_timer_.remainder = wave_timer_.interval; for (auto & actor : waves_.front()) { actor->level(this); actors_.emplace_back(std::move(actor)); } waves_.pop_front(); } } void level::render(graphics::renderer & renderer) { renderer.draw(player_->render_info()); for (auto & a : actors_) { renderer.draw(a->render_info()); } for (auto & b : bullets_) { renderer.draw(b->render_info()); } }