From 50f2832db147a3fb18e6b2d47c7e56a712ca4beb Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Mon, 21 Sep 2020 19:43:30 -0700 Subject: [PATCH] Add biome loader --- CMakeLists.txt | 1 - src/game/biome.hpp | 50 +++++++++++++++ src/game/bootloader.cpp | 12 +++- src/game/game-context.hpp | 5 ++ src/game/states/play-state.cpp | 43 ++++++++++--- src/resources/biome-loader.cpp | 107 +++++++++++++++++++++++++++++++++ 6 files changed, 207 insertions(+), 11 deletions(-) create mode 100644 src/game/biome.hpp create mode 100644 src/resources/biome-loader.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1405aa0..b80be9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,6 @@ find_package(SDL2 REQUIRED COMPONENTS SDL2::SDL2-static SDL2::SDL2main CONFIG) find_package(OpenAL REQUIRED CONFIG) find_library(physfs REQUIRED NAMES physfs-static PATHS "${CMAKE_PREFIX_PATH}/lib") - # Determine dependencies set(STATIC_LIBS dr_wav diff --git a/src/game/biome.hpp b/src/game/biome.hpp new file mode 100644 index 0000000..d3d0f52 --- /dev/null +++ b/src/game/biome.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_BIOME_HPP +#define ANTKEEPER_BIOME_HPP + +#include +#include "utility/fundamental-types.hpp" +class material; + +struct biome +{ + std::string name; + + // Terrain + material* terrain_material; + + // Weather + float3 ambient_color; + float ambient_intensity; + float sun_azimuth; + float sun_elevation; + float3 sun_color; + float sun_intensity; + float sun_angular_radius; + float3 horizon_color; + float3 zenith_color; + float wind_speed; + float wind_direction; + + // Traits +}; + +#endif // ANTKEEPER_BIOME_HPP diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index 8a42ad3..ee91263 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -170,6 +170,7 @@ void parse_options(game_context* ctx, int argc, char** argv) { cxxopts::Options options("Antkeeper", "Ant colony simulation game"); options.add_options() + ("b,biome", "Selects the biome to load", cxxopts::value()) ("c,continue", "Continues from the last save") ("d,data", "Sets the data package path", cxxopts::value()) ("f,fullscreen", "Starts in fullscreen mode") @@ -180,6 +181,10 @@ void parse_options(game_context* ctx, int argc, char** argv) ("w,windowed", "Starts in windowed mode"); auto result = options.parse(argc, argv); + // --biome + if (result.count("biome")) + ctx->option_biome = result["biome"].as(); + // --continue if (result.count("continue")) ctx->option_continue = true; @@ -339,6 +344,8 @@ void setup_resources(game_context* ctx) ctx->resource_manager->include("/behaviors/"); ctx->resource_manager->include("/controls/"); ctx->resource_manager->include("/localization/"); + ctx->resource_manager->include("/biomes/"); + ctx->resource_manager->include("/traits/"); ctx->resource_manager->include("/"); } @@ -619,12 +626,11 @@ void setup_scenes(game_context* ctx) // Setup lights ctx->sun_indirect = new ambient_light(); - ctx->sun_indirect->set_intensity(0.5f); + ctx->sun_indirect->set_intensity(0.0f); ctx->sun_indirect->update_tweens(); ctx->sun_direct = new directional_light(); - ctx->sun_direct->look_at({-1.0f, 5.0f, 1.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}); - ctx->sun_direct->set_intensity(1.0f); + ctx->sun_direct->set_intensity(0.0f); ctx->sun_direct->update_tweens(); ctx->subterrain_light = new point_light(); diff --git a/src/game/game-context.hpp b/src/game/game-context.hpp index b793b0e..fc8ec2d 100644 --- a/src/game/game-context.hpp +++ b/src/game/game-context.hpp @@ -86,6 +86,7 @@ class cli; class outline_pass; class tracking_system; class painting_system; +struct biome; template class animation; template class material_property; template class tween; @@ -100,6 +101,7 @@ struct game_context std::ofstream log_filestream; // Command-line options + std::optional option_biome; std::optional option_continue; std::optional option_data; std::optional option_fullscreen; @@ -240,6 +242,9 @@ struct game_context tracking_system* tracking_system; painting_system* painting_system; + // Game + biome* biome; + // Debug cli* cli; diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp index 74d89c6..6ed3e40 100644 --- a/src/game/states/play-state.cpp +++ b/src/game/states/play-state.cpp @@ -44,11 +44,14 @@ #include "scene/model-instance.hpp" #include "scene/scene.hpp" #include "scene/camera.hpp" +#include "scene/ambient-light.hpp" +#include "scene/directional-light.hpp" #include "scene/directional-light.hpp" #include "game/systems/control-system.hpp" #include "game/systems/camera-system.hpp" #include "game/systems/render-system.hpp" #include "game/systems/tool-system.hpp" +#include "game/biome.hpp" #include "utility/fundamental-types.hpp" #include "utility/gamma.hpp" @@ -56,16 +59,35 @@ void play_state_enter(game_context* ctx) { logger* logger = ctx->logger; logger->push_task("Entering play state"); + + // Load biome + if (ctx->option_biome.has_value()) + { + ctx->biome = ctx->resource_manager->load(ctx->option_biome.value() + ".bio"); + } + else + { + ctx->biome = ctx->resource_manager->load("grassland.bio"); + } + + // Apply biome parameters to scene + ctx->sun_indirect->set_color(ctx->biome->ambient_color); + ctx->sun_indirect->set_intensity(ctx->biome->ambient_intensity); + + math::quaternion sun_azimuth_rotation = math::angle_axis(ctx->biome->sun_azimuth, float3{0, 1, 0}); + math::quaternion sun_elevation_rotation = math::angle_axis(ctx->biome->sun_elevation, float3{-1, 0, 0}); + math::quaternion sun_rotation = math::normalize(sun_azimuth_rotation * sun_elevation_rotation); + + ctx->sun_direct->set_rotation(sun_rotation); + ctx->sun_direct->set_color(ctx->biome->sun_color); + ctx->sun_direct->set_intensity(ctx->biome->sun_intensity); - // Set up sky pass sky_pass* sky_pass = ctx->overworld_sky_pass; sky_pass->set_enabled(true); - sky_pass->set_sun_angular_radius(math::radians(3.0f)); - sky_pass->set_sun_color({2.0f, 2.0f, 2.0f}); - sky_pass->set_horizon_color({0.129, 0.451, 0.549}); - sky_pass->set_zenith_color({0.0, 0.286, 0.415}); - //sky_pass->set_horizon_color(float3{0.002f, 0.158f, 0.250f}); - //sky_pass->set_zenith_color(float3{0.002f, 0.158f, 0.250f}); + sky_pass->set_sun_angular_radius(ctx->biome->sun_angular_radius); + sky_pass->set_sun_color(ctx->biome->sun_color * ctx->biome->sun_intensity); + sky_pass->set_horizon_color(ctx->biome->horizon_color); + sky_pass->set_zenith_color(ctx->biome->zenith_color); ctx->tool_system->set_sun_direction(ctx->sun_direct->get_direction()); @@ -89,6 +111,7 @@ void play_state_enter(game_context* ctx) ecs::archetype* flashlight_light_cone_archetype = resource_manager->load("flashlight-light-cone.ent"); ecs::archetype* lens_light_cone_archetype = resource_manager->load("lens-light-cone.ent"); ecs::archetype* ant_head_archetype = resource_manager->load("ant-head.ent"); + ecs::archetype* dandelion_plant_archetype = resource_manager->load("dandelion-plant.ent"); // Create tools forceps_archetype->assign(ecs_registry, ctx->forceps_entity); @@ -280,6 +303,9 @@ void play_state_enter(game_context* ctx) //transform.transform.translation.y -= 1.0f; } + auto dandelion_plant = dandelion_plant_archetype->create(ecs_registry); + ec::place(ecs_registry, dandelion_plant, {55, -30}); + control_system* control_system = ctx->control_system; control_system->update(0.0, 0.0); control_system->set_nest(nest); @@ -288,6 +314,9 @@ void play_state_enter(game_context* ctx) ctx->fade_transition->transition(1.0f, true, ease::in_quad); logger->pop_task(EXIT_SUCCESS); + + std::string biome_name = (*ctx->strings)[ctx->biome->name]; + logger->log("Entered biome \"" + biome_name + "\""); } void play_state_exit(game_context* ctx) diff --git a/src/resources/biome-loader.cpp b/src/resources/biome-loader.cpp new file mode 100644 index 0000000..58168c7 --- /dev/null +++ b/src/resources/biome-loader.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#include "resource-loader.hpp" +#include "resource-manager.hpp" +#include "game/biome.hpp" +#include "math/angles.hpp" +#include +#include + +template +static bool load_value(T* value, const nlohmann::json& json, const std::string& name) +{ + if (auto element = json.find(name); element != json.end()) + { + *value = element.value().get(); + return true; + } + + return false; +} + +template +static bool load_array(T* value, std::size_t size, const nlohmann::json& json, const std::string& name) +{ + if (auto element = json.find(name); element != json.end()) + { + std::size_t i = 0; + for (auto it = element.value().cbegin(); (it != element.value().cend()) && (i < size); ++it) + { + *(value++) = it.value().get(); + ++i; + } + + return true; + } + + return false; +} + +template <> +biome* resource_loader::load(resource_manager* resource_manager, PHYSFS_File* file) +{ + // Read file into buffer + std::size_t size = static_cast(PHYSFS_fileLength(file)); + std::string buffer; + buffer.resize(size); + PHYSFS_readBytes(file, &buffer[0], size); + + // Parse json from file buffer + nlohmann::json json = nlohmann::json::parse(buffer); + + biome* biome = new ::biome(); + + load_value(&biome->name, json, "name"); + + if (auto terrain = json.find("terrain"); terrain != json.end()) + { + std::string material_filename; + if (load_value(&material_filename, terrain.value(), "material")) + { + biome->terrain_material = resource_manager->load<::material>(material_filename); + } + } + + if (auto weather = json.find("weather"); weather != json.end()) + { + load_array(&biome->ambient_color.x, 3, weather.value(), "ambient_color"); + load_value(&biome->ambient_intensity, weather.value(), "ambient_intensity"); + + + load_value(&biome->sun_azimuth, weather.value(), "sun_azimuth"); + biome->sun_azimuth = math::radians(biome->sun_azimuth); + load_value(&biome->sun_elevation, weather.value(), "sun_elevation"); + biome->sun_elevation = math::radians(biome->sun_elevation); + load_array(&biome->sun_color.x, 3, weather.value(), "sun_color"); + load_value(&biome->sun_intensity, weather.value(), "sun_intensity"); + load_value(&biome->sun_angular_radius, weather.value(), "sun_angular_radius"); + biome->sun_angular_radius = math::radians(biome->sun_angular_radius); + + load_array(&biome->horizon_color.x, 3, weather.value(), "horizon_color"); + load_array(&biome->zenith_color.x, 3, weather.value(), "zenith_color"); + + load_value(&biome->wind_speed, weather.value(), "wind_speed"); + load_value(&biome->wind_direction, weather.value(), "wind_direction"); + biome->wind_direction = math::radians(biome->wind_direction); + } + + return biome; +} +