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;
+}
+