diff --git a/CMakeLists.txt b/CMakeLists.txt index 7faddc1..8b94016 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.7) - option(VERSION_STRING "Project version string" "0.0.0") project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) diff --git a/src/ai/ai.hpp b/src/ai/ai.hpp index 1428736..7057132 100644 --- a/src/ai/ai.hpp +++ b/src/ai/ai.hpp @@ -23,6 +23,7 @@ /// Artificial intelligence (AI) namespace ai {} -#include "behavior-tree.hpp" +#include "bt/bt.hpp" +#include "steering/steering.hpp" #endif // ANTKEEPER_AI_HPP diff --git a/src/game/state/brood.hpp b/src/ai/bt/bt.hpp similarity index 68% rename from src/game/state/brood.hpp rename to src/ai/bt/bt.hpp index 1658aae..6a4dd01 100644 --- a/src/game/state/brood.hpp +++ b/src/ai/bt/bt.hpp @@ -17,23 +17,20 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_GAME_STATE_BROOD_HPP -#define ANTKEEPER_GAME_STATE_BROOD_HPP +#ifndef ANTKEEPER_AI_BT_HPP +#define ANTKEEPER_AI_BT_HPP -#include "game/context.hpp" +#include +#include -namespace game { -namespace state { +namespace ai { -/// Brood game state functions. -namespace brood { +/// Behavior tree (BT) +namespace bt {} -void enter(game::context* ctx); -void exit(game::context* ctx); +} // namespace ai -} // namespace brood +#include "ai/bt/node.hpp" +#include "ai/bt/status.hpp" -} // namespace state -} // namespace game - -#endif // ANTKEEPER_GAME_STATE_BROOD_HPP +#endif // ANTKEEPER_AI_BT_HPP diff --git a/src/ai/behavior-tree.hpp b/src/ai/bt/node.hpp similarity index 90% rename from src/ai/behavior-tree.hpp rename to src/ai/bt/node.hpp index be00e37..9697057 100644 --- a/src/ai/behavior-tree.hpp +++ b/src/ai/bt/node.hpp @@ -17,25 +17,14 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_AI_BEHAVIOR_TREE_HPP -#define ANTKEEPER_AI_BEHAVIOR_TREE_HPP +#ifndef ANTKEEPER_AI_BT_NODE_HPP +#define ANTKEEPER_AI_BT_NODE_HPP -#include -#include +#include "ai/bt/status.hpp" namespace ai { - -/// Behavior tree (BT) namespace bt { -/// Behavior tree node return status enumerations. -enum class status -{ - failure, ///< Indicates a node's execution failed. - success, ///< Indicates a node's execution succeed. - running ///< Indicates a node's execution has not finished. -}; - /** * Abstract base class for behavior tree nodes. * @@ -48,17 +37,18 @@ struct node typedef T context_type; /** - * Executes a node's functionality and returns its status. + * Executes a node's function and returns its status. * * @param context Context data on which the node will operate. */ virtual status execute(context_type& context) const = 0; }; -/// A node with no children. +/// Behavior tree node with no children. template using leaf_node = node; + /// A node with exactly one child. template struct decorator_node: node @@ -193,4 +183,4 @@ status selector::execute(context_type& context) const } // namespace bt } // namespace ai -#endif // ANTKEEPER_AI_BEHAVIOR_TREE_HPP +#endif // ANTKEEPER_AI_BT_NODE_HPP diff --git a/src/game/state/forage.hpp b/src/ai/bt/status.hpp similarity index 64% rename from src/game/state/forage.hpp rename to src/ai/bt/status.hpp index b6068e5..e8417af 100644 --- a/src/game/state/forage.hpp +++ b/src/ai/bt/status.hpp @@ -17,23 +17,26 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_GAME_STATE_FORAGE_HPP -#define ANTKEEPER_GAME_STATE_FORAGE_HPP - -#include "game/context.hpp" - -namespace game { -namespace state { - -/// Forage game state functions. -namespace forage { - -void enter(game::context* ctx); -void exit(game::context* ctx); - -} // namespace forage - -} // namespace state -} // namespace game - -#endif // ANTKEEPER_GAME_STATE_FORAGE_HPP +#ifndef ANTKEEPER_AI_BT_STATUS_HPP +#define ANTKEEPER_AI_BT_STATUS_HPP + +namespace ai { +namespace bt { + +/// Behavior tree node return status enumerations. +enum class status +{ + /// Indicates a node's execution has failed. + failure, + + /// Indicates a node's execution has succeeded. + success, + + /// Indicates a node's execution has not finished. + running +}; + +} // namespace bt +} // namespace ai + +#endif // ANTKEEPER_AI_BT_STATUS_HPP diff --git a/src/ai/steering/behavior/wander.cpp b/src/ai/steering/behavior/wander.cpp index f412a46..6eb8592 100644 --- a/src/ai/steering/behavior/wander.cpp +++ b/src/ai/steering/behavior/wander.cpp @@ -46,18 +46,14 @@ float3 wander_2d(const agent& agent, float noise, float distance, float radius, return seek(agent, center + offset); } -/* -float3 wander_3d(const agent& agent, float distance, float radius, float delta, float& theta, float& phi) +float3 wander_3d(const agent& agent, float noise, float distance, float radius, float& theta, float& phi) { // Shift wander angles - theta += random(-delta, delta); - phi += random(-delta, delta); + theta += math::random(-noise, noise); + phi += math::random(-noise, noise); // Calculate center of wander sphere - float3 center = agent.position; - const float speed_squared = math::dot(agent.velocity, agent.velocity); - if (speed_squared) - center += (agent.velocity / std::sqrt(speed_squared)) * distance; + const float3 center = agent.position + agent.forward * distance; // Convert spherical coordinates to Cartesian point on wander sphere const float r_cos_theta = radius * std::cos(theta); @@ -71,7 +67,6 @@ float3 wander_3d(const agent& agent, float distance, float radius, float delta, // Seek toward point on wander sphere return seek(agent, center + offset); } -*/ } // namespace behavior } // namespace steering diff --git a/src/ai/steering/behavior/wander.hpp b/src/ai/steering/behavior/wander.hpp index ea0f840..8b2b939 100644 --- a/src/ai/steering/behavior/wander.hpp +++ b/src/ai/steering/behavior/wander.hpp @@ -47,13 +47,12 @@ float3 wander_2d(const agent& agent, float noise, float distance, float radius, * @param distance Distance to the wander sphere. * @param radius Radius of the wander sphere. * @param delta Maximum angle offset. - * @param theta Polar wander angle, in radians. - * @param phi Azimuthal wander angle, in radians. - * @param[in,out] Wander angle, in radians. + * @param[in,out] theta Polar wander angle, in radians. + * @param[in,out] phi Azimuthal wander angle, in radians. * * @return Wander force. */ -//float3 wander_3d(const agent& agent, float distance, float radius, float delta, float& theta, float& phi); +float3 wander_3d(const agent& agent, float noise, float distance, float radius, float& theta, float& phi); } // namespace behavior } // namespace steering diff --git a/src/ai/steering/steering.hpp b/src/ai/steering/steering.hpp index 71694a2..07b0c7c 100644 --- a/src/ai/steering/steering.hpp +++ b/src/ai/steering/steering.hpp @@ -29,6 +29,11 @@ namespace ai { */ namespace steering {} +#include "ai/steering/agent.hpp" +#include "ai/steering/behavior/flee.hpp" +#include "ai/steering/behavior/seek.hpp" +#include "ai/steering/behavior/wander.hpp" + } // namespace ai #endif // ANTKEEPER_AI_STEERING_HPP diff --git a/src/entity/components/steering.hpp b/src/entity/components/steering.hpp index d8eb520..1fe34dd 100644 --- a/src/entity/components/steering.hpp +++ b/src/entity/components/steering.hpp @@ -30,17 +30,23 @@ struct steering /// Steering agent. ai::steering::agent agent; + // Wander behavior float wander_weight; float wander_noise; float wander_distance; float wander_radius; float wander_angle; + float wander_angle2; + // Seek behavior float seek_weight; float3 seek_target; + // Flee behavior float flee_weight; - float weight_sum; + + /// Sum of steering behavior weights + float sum_weights; }; } // namespace component diff --git a/src/entity/ebt.hpp b/src/entity/ebt.hpp index eeb1da0..7b79008 100644 --- a/src/entity/ebt.hpp +++ b/src/entity/ebt.hpp @@ -20,7 +20,7 @@ #ifndef ANTKEEPER_ENTITY_EBT_HPP #define ANTKEEPER_ENTITY_EBT_HPP -#include "ai/behavior-tree.hpp" +#include "ai/bt/bt.hpp" #include "entity/id.hpp" #include "entity/registry.hpp" diff --git a/src/entity/systems/steering.cpp b/src/entity/systems/steering.cpp index 939d031..94b0c07 100644 --- a/src/entity/systems/steering.cpp +++ b/src/entity/systems/steering.cpp @@ -47,7 +47,8 @@ void steering::update(double t, double dt) float3 force = {0, 0, 0}; if (steering.wander_weight) { - force += ai::steering::behavior::wander_2d(agent, steering.wander_noise * dt, steering.wander_distance, steering.wander_radius, steering.wander_angle) * steering.wander_weight; + //force += ai::steering::behavior::wander_2d(agent, steering.wander_noise * dt, steering.wander_distance, steering.wander_radius, steering.wander_angle) * steering.wander_weight; + force += ai::steering::behavior::wander_3d(agent, steering.wander_noise * dt, steering.wander_distance, steering.wander_radius, steering.wander_angle, steering.wander_angle2) * steering.wander_weight; } if (steering.seek_weight) { @@ -55,7 +56,8 @@ void steering::update(double t, double dt) } // Normalize force - force /= steering.weight_sum; + if (steering.sum_weights) + force /= steering.sum_weights; // Accelerate agent.acceleration = force / agent.mass; diff --git a/src/game/state/boot.cpp b/src/game/state/boot.cpp index ff4d268..5254e58 100644 --- a/src/game/state/boot.cpp +++ b/src/game/state/boot.cpp @@ -493,7 +493,7 @@ void boot::setup_rendering() ctx.sky_pass = new render::sky_pass(ctx.rasterizer, ctx.hdr_framebuffer, ctx.resource_manager); ctx.sky_pass->set_enabled(false); - ctx.sky_pass->set_magnification(10.0f); + ctx.sky_pass->set_magnification(3.0f); ctx.app->get_event_dispatcher()->subscribe(ctx.sky_pass); ctx.ground_pass = new render::ground_pass(ctx.rasterizer, ctx.hdr_framebuffer, ctx.resource_manager); diff --git a/src/game/state/brood.cpp b/src/game/state/brood.cpp deleted file mode 100644 index d774a1f..0000000 --- a/src/game/state/brood.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (C) 2021 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 "game/state/brood.hpp" -#include "entity/archetype.hpp" -#include "entity/commands.hpp" -#include "entity/components/observer.hpp" -#include "entity/components/camera.hpp" -#include "entity/components/terrain.hpp" -#include "entity/components/transform.hpp" -#include "entity/components/chamber.hpp" -#include "entity/components/constraints/spring-to.hpp" -#include "entity/components/constraints/three-dof.hpp" -#include "entity/components/constraint-stack.hpp" -#include "animation/screen-transition.hpp" -#include "animation/ease.hpp" -#include "resources/resource-manager.hpp" -#include "render/passes/sky-pass.hpp" -#include "application.hpp" -#include - -namespace game { -namespace state { -namespace brood { - -static void setup_nest(game::context* ctx); -static void setup_ants(game::context* ctx); -static void setup_camera(game::context* ctx); -static void setup_controls(game::context* ctx); - -void enter(game::context* ctx) -{ - setup_nest(ctx); - setup_ants(ctx); - setup_camera(ctx); - setup_controls(ctx); - - ctx->underground_ambient_light->set_intensity(1.0f); - - // Create larva - { - entity::archetype* larva_archetype = ctx->resource_manager->load("ant-larva.ent"); - auto larva_eid = larva_archetype->create(*ctx->entity_registry); - entity::command::warp_to(*ctx->entity_registry, larva_eid, {0.0f, 0.0f, 0.0f}); - entity::command::assign_render_layers(*ctx->entity_registry, larva_eid, 0b1); - } - - // Create cocoon - { - entity::archetype* cocoon_archetype = ctx->resource_manager->load("ant-cocoon.ent"); - auto cocoon_eid = cocoon_archetype->create(*ctx->entity_registry); - entity::command::warp_to(*ctx->entity_registry, cocoon_eid, {-50, 0.1935f, 0}); - entity::command::assign_render_layers(*ctx->entity_registry, cocoon_eid, 0b1); - } - - // Reset tweening - ctx->underground_scene->update_tweens(); - - // Start fade in - ctx->fade_transition->transition(1.0f, true, ease::in_quad); -} - -void exit(game::context* ctx) -{} - -void setup_nest(game::context* ctx) -{ - // Create nest central shaft entity - if (!ctx->entities.count("shaft")) - { - entity::id shaft_eid = ctx->entity_registry->create(); - ctx->entities["shaft"] = shaft_eid; - - entity::component::transform transform; - transform.local = math::transform::identity; - transform.world = transform.local; - transform.warp = true; - - ctx->entity_registry->assign(shaft_eid, transform); - } - - // Create nest lobby chamber entity - if (!ctx->entities.count("lobby")) - { - entity::id lobby_eid = ctx->entity_registry->create(); - ctx->entities["lobby"] = lobby_eid; - - entity::component::chamber chamber; - chamber.shaft_eid = ctx->entities["shaft"]; - chamber.distance = 10.0f; - chamber.previous_chamber_eid = entt::null; - chamber.next_chamber_eid = entt::null; - } -} - -void setup_ants(game::context* ctx) -{ - // Create queen ant entity - if (!ctx->entities.count("queen")) - { - entity::id queen_eid = ctx->entity_registry->create(); - ctx->entities["queen"] = queen_eid; - } -} - -void setup_camera(game::context* ctx) -{ - // Switch to underground camera - ctx->surface_camera->set_active(false); - ctx->underground_camera->set_active(true); - - // Create underground camera entity - if (!ctx->entities.count("underground_cam")) - { - // Create camera target entity - entity::id target_eid = ctx->entity_registry->create(); - ctx->entities["underground_cam_target"] = target_eid; - { - // Transform - entity::component::transform target_transform; - target_transform.local = math::transform::identity; - target_transform.world = target_transform.local; - target_transform.warp = true; - ctx->entity_registry->assign(target_eid, target_transform); - } - - // Create camera entity - entity::id camera_eid = ctx->entity_registry->create(); - ctx->entities["underground_cam"] = camera_eid; - - // Create camera transform component - entity::component::transform transform; - transform.local = math::transform::identity; - transform.world = transform.local; - transform.warp = true; - ctx->entity_registry->assign(camera_eid, transform); - - // Create camera camera component - entity::component::camera camera; - camera.object = ctx->underground_camera; - ctx->entity_registry->assign(camera_eid, camera); - - // Create camera 3DOF constraint entity - entity::id three_dof_constraint_eid = ctx->entity_registry->create(); - ctx->entities["underground_cam_3dof"] = three_dof_constraint_eid; - { - // Create 3DOF to constraint - entity::component::constraint::three_dof three_dof; - three_dof.yaw = 0.0f; - three_dof.pitch = 0.0f; - three_dof.roll = 0.0f; - ctx->entity_registry->assign(three_dof_constraint_eid, three_dof); - - // Create constraint stack node component - entity::component::constraint_stack_node node; - node.active = true; - node.weight = 1.0f; - node.next = entt::null; - ctx->entity_registry->assign(three_dof_constraint_eid, node); - } - - // Create camera spring to constraint entity - entity::id spring_constraint_eid = ctx->entity_registry->create(); - { - // Create spring to constraint - entity::component::constraint::spring_to spring; - spring.target = target_eid; - spring.translation = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 1.0f, math::two_pi}; - spring.translation.w = hz_to_rads(8.0f); - - spring.spring_translation = true; - spring.spring_rotation = false; - ctx->entity_registry->assign(spring_constraint_eid, spring); - - // Create constraint stack node component - entity::component::constraint_stack_node node; - node.active = true; - node.weight = 1.0f; - node.next = three_dof_constraint_eid; - ctx->entity_registry->assign(spring_constraint_eid, node); - } - - // Create camera constraint stack component - entity::component::constraint_stack constraint_stack; - constraint_stack.head = spring_constraint_eid; - ctx->entity_registry->assign(camera_eid, constraint_stack); - } - - ctx->underground_camera->set_exposure(0.0f); -} - -void setup_controls(game::context* ctx) -{ - // Get underground camera entity - entity::id camera_eid = ctx->entities["underground_cam"]; - entity::id target_eid = ctx->entities["underground_cam_target"]; - entity::id three_dof_eid = ctx->entities["underground_cam_3dof"]; - - const float dolly_speed = 20.0f; - const float truck_speed = dolly_speed; - const float pedestal_speed = 30.0f; - const float pan_speed = math::radians(8.0f); - const float tilt_speed = pan_speed; - - const input::control* move_slow = ctx->controls["move_slow"]; - const input::control* move_fast = ctx->controls["move_fast"]; - const input::control* mouse_rotate = ctx->controls["mouse_rotate"]; - - ctx->controls["dolly_forward"]->set_active_callback - ( - [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.5f; - if (move_fast->is_active()) - value *= 2.0f; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); - - const float3 movement = {0.0f, 0.0f, -truck_speed * value * (1.0f / 60.0f)}; - entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); - } - ); - - // Dolly backward - ctx->controls["dolly_backward"]->set_active_callback - ( - [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.5f; - if (move_fast->is_active()) - value *= 2.0f; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); - - const float3 movement = {0.0f, 0.0f, truck_speed * value * (1.0f / 60.0f)}; - entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); - } - ); - - // Truck right - ctx->controls["truck_right"]->set_active_callback - ( - [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.5f; - if (move_fast->is_active()) - value *= 2.0f; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); - - const float3 movement = {truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f}; - entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); - } - ); - - // Truck left - ctx->controls["truck_left"]->set_active_callback - ( - [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.5f; - if (move_fast->is_active()) - value *= 2.0f; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); - - const float3 movement = {-truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f}; - entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); - } - ); - - // Pedestal up - ctx->controls["pedestal_up"]->set_active_callback - ( - [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.5f; - if (move_fast->is_active()) - value *= 2.0f; - - const float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f}; - entity::command::translate(*ctx->entity_registry, target_eid, movement); - } - ); - - // Pedestal down - ctx->controls["pedestal_down"]->set_active_callback - ( - [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.5f; - if (move_fast->is_active()) - value *= 2.0f; - - const float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f}; - entity::command::translate(*ctx->entity_registry, target_eid, movement); - } - ); - - // Mouse rotate - ctx->controls["mouse_rotate"]->set_activated_callback - ( - [&ctx]() - { - ctx->app->set_relative_mouse_mode(true); - } - ); - ctx->controls["mouse_rotate"]->set_deactivated_callback - ( - [&ctx]() - { - ctx->app->set_relative_mouse_mode(false); - } - ); - - // Pan left - ctx->controls["pan_left_mouse"]->set_active_callback - ( - [ctx, three_dof_eid, pan_speed, mouse_rotate](float value) - { - if (!mouse_rotate->is_active()) - return; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.yaw += pan_speed * value * (1.0f / 60.0f); - } - ); - - // Pan right - ctx->controls["pan_right_mouse"]->set_active_callback - ( - [ctx, three_dof_eid, pan_speed, mouse_rotate](float value) - { - if (!mouse_rotate->is_active()) - return; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.yaw -= pan_speed * value * (1.0f / 60.0f); - } - ); - - // Tilt up - ctx->controls["tilt_up_mouse"]->set_active_callback - ( - [ctx, three_dof_eid, tilt_speed, mouse_rotate](float value) - { - if (!mouse_rotate->is_active()) - return; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.pitch -= tilt_speed * value * (1.0f / 60.0f); - three_dof.pitch = std::max(math::radians(-90.0f), three_dof.pitch); - } - ); - - // Tilt down - ctx->controls["tilt_down_mouse"]->set_active_callback - ( - [ctx, three_dof_eid, tilt_speed, mouse_rotate](float value) - { - if (!mouse_rotate->is_active()) - return; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.pitch += tilt_speed * value * (1.0f / 60.0f); - three_dof.pitch = std::min(math::radians(90.0f), three_dof.pitch); - } - ); -} - -} // namespace brood -} // namespace state -} // namespace game diff --git a/src/game/state/forage.cpp b/src/game/state/forage.cpp deleted file mode 100644 index e95510b..0000000 --- a/src/game/state/forage.cpp +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright (C) 2021 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 "game/state/forage.hpp" -#include "entity/archetype.hpp" -#include "entity/commands.hpp" -#include "entity/components/observer.hpp" -#include "entity/components/terrain.hpp" -#include "entity/components/transform.hpp" -#include "entity/components/celestial-body.hpp" -#include "entity/components/tool.hpp" -#include "entity/systems/astronomy.hpp" -#include "animation/screen-transition.hpp" -#include "animation/ease.hpp" -#include "resources/resource-manager.hpp" -#include "entity/components/camera.hpp" -#include "entity/components/constraints/spring-to.hpp" -#include "entity/components/constraints/three-dof.hpp" -#include "entity/components/constraint-stack.hpp" -#include "application.hpp" -#include "game/tools.hpp" - -namespace game { -namespace state { -namespace forage { - -static void setup_camera(game::context* ctx); -static void setup_tools(game::context* ctx); -static void setup_controls(game::context* ctx); - -void enter(game::context* ctx) -{ - setup_camera(ctx); - setup_tools(ctx); - setup_controls(ctx); - - // Find planet EID by name - entity::id planet_eid = ctx->entities["planet"]; - - // Create biome terrain component - entity::component::terrain biome_terrain; - biome_terrain.max_lod = 18; - biome_terrain.patch_material = ctx->resource_manager->load("desert-terrain.mtl"); - biome_terrain.elevation = [](double, double) -> double - { - return 0.0; - }; - - // Replace planet terrain component with biome terrain component - ctx->entity_registry->replace(planet_eid, biome_terrain); - - // Create observer - entity::id observer_eid = ctx->entity_registry->create(); - { - entity::component::observer observer; - observer.reference_body_eid = planet_eid; - observer.elevation = 0.0; - observer.latitude = 0.0; - observer.longitude = 0.0; - observer.camera = ctx->surface_camera; - ctx->entity_registry->assign(observer_eid, observer); - - // Set reference location of astronomy system - //ctx->astronomy_system->set_reference_body(planet_eid); - ctx->astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude}); - } - - // Create larva - { - entity::archetype* larva_archetype = ctx->resource_manager->load("ant-larva.ent"); - auto larva_eid = larva_archetype->create(*ctx->entity_registry); - entity::command::warp_to(*ctx->entity_registry, larva_eid, {50, 0.1935f, 0}); - entity::command::assign_render_layers(*ctx->entity_registry, larva_eid, 0b10); - } - - // Create cocoon - { - entity::archetype* cocoon_archetype = ctx->resource_manager->load("ant-cocoon.ent"); - auto cocoon_eid = cocoon_archetype->create(*ctx->entity_registry); - entity::command::warp_to(*ctx->entity_registry, cocoon_eid, {-50, 0.1935f, 0}); - entity::command::assign_render_layers(*ctx->entity_registry, cocoon_eid, 0b10); - } - - // Create moon - { - entity::archetype* moon_archetype = ctx->resource_manager->load("moon.ent"); - auto moon_eid = moon_archetype->create(*ctx->entity_registry); - entity::command::warp_to(*ctx->entity_registry, moon_eid, {50.0f, 50.0f, 50.0f}); - entity::command::assign_render_layers(*ctx->entity_registry, moon_eid, 0b10); - entity::command::set_scale(*ctx->entity_registry, moon_eid, float3{1.0f, 1.0f, 1.0f} * 10.0f); - } - - ctx->surface_scene->update_tweens(); - - // Start fade in - ctx->fade_transition->transition(1.0f, true, ease::in_quad); -} - -void exit(game::context* ctx) -{} - -void setup_camera(game::context* ctx) -{ - // Switch to surface camera - ctx->underground_camera->set_active(false); - ctx->surface_camera->set_active(true); - - // Create surface camera entity - if (!ctx->entities.count("surface_cam")) - { - // Create camera target entity - entity::id target_eid = ctx->entity_registry->create(); - ctx->entities["surface_cam_target"] = target_eid; - { - // Transform - entity::component::transform target_transform; - target_transform.local = math::transform::identity; - target_transform.world = target_transform.local; - target_transform.warp = true; - ctx->entity_registry->assign(target_eid, target_transform); - } - - // Create camera entity - entity::id camera_eid = ctx->entity_registry->create(); - ctx->entities["surface_cam"] = camera_eid; - - // Create camera transform component - entity::component::transform transform; - transform.local = math::transform::identity; - transform.world = transform.local; - transform.warp = true; - ctx->entity_registry->assign(camera_eid, transform); - - // Create camera camera component - entity::component::camera camera; - camera.object = ctx->surface_camera; - ctx->entity_registry->assign(camera_eid, camera); - - // Create camera 3DOF constraint entity - entity::id three_dof_constraint_eid = ctx->entity_registry->create(); - ctx->entities["surface_cam_3dof"] = three_dof_constraint_eid; - { - // Create 3DOF to constraint - entity::component::constraint::three_dof three_dof; - three_dof.yaw = 0.0f; - three_dof.pitch = 0.0f; - three_dof.roll = 0.0f; - ctx->entity_registry->assign(three_dof_constraint_eid, three_dof); - - // Create constraint stack node component - entity::component::constraint_stack_node node; - node.active = true; - node.weight = 1.0f; - node.next = entt::null; - ctx->entity_registry->assign(three_dof_constraint_eid, node); - } - - // Create camera spring to constraint entity - entity::id spring_constraint_eid = ctx->entity_registry->create(); - { - // Create spring to constraint - entity::component::constraint::spring_to spring; - spring.target = target_eid; - spring.translation = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 1.0f, math::two_pi}; - spring.translation.w = hz_to_rads(8.0f); - - spring.spring_translation = true; - spring.spring_rotation = false; - ctx->entity_registry->assign(spring_constraint_eid, spring); - - // Create constraint stack node component - entity::component::constraint_stack_node node; - node.active = true; - node.weight = 1.0f; - node.next = three_dof_constraint_eid; - ctx->entity_registry->assign(spring_constraint_eid, node); - } - - // Create camera constraint stack component - entity::component::constraint_stack constraint_stack; - constraint_stack.head = spring_constraint_eid; - ctx->entity_registry->assign(camera_eid, constraint_stack); - } - - ctx->surface_camera->set_exposure(-14.5f); -} - -void setup_tools(game::context* ctx) -{ - ctx->entities["camera_tool"] = build_camera_tool(*ctx); - ctx->entities["time_tool"] = build_time_tool(*ctx); - - // Set active tool - ctx->entities["active_tool"] = ctx->entities["time_tool"]; -} - -void setup_controls(game::context* ctx) -{ - // Get underground camera entity - entity::id camera_eid = ctx->entities["surface_cam"]; - entity::id target_eid = ctx->entities["surface_cam_target"]; - entity::id three_dof_eid = ctx->entities["surface_cam_3dof"]; - - const float dolly_speed = 20.0f; - const float truck_speed = dolly_speed; - const float pedestal_speed = 30.0f; - float mouse_tilt_sensitivity = 1.0f; - float mouse_pan_sensitivity = 1.0f; - bool mouse_invert_tilt = false; - bool mouse_invert_pan = false; - float gamepad_tilt_sensitivity = 1.0f; - float gamepad_pan_sensitivity = 1.0f; - bool gamepad_invert_tilt = false; - bool gamepad_invert_pan = false; - bool mouse_look_toggle = false; - ctx->mouse_look = false; - - if (ctx->config->contains("mouse_tilt_sensitivity")) - mouse_tilt_sensitivity = math::radians((*ctx->config)["mouse_tilt_sensitivity"].get()); - if (ctx->config->contains("mouse_pan_sensitivity")) - mouse_pan_sensitivity = math::radians((*ctx->config)["mouse_pan_sensitivity"].get()); - if (ctx->config->contains("mouse_invert_tilt")) - mouse_invert_tilt = math::radians((*ctx->config)["mouse_invert_tilt"].get()); - if (ctx->config->contains("mouse_invert_pan")) - mouse_invert_pan = math::radians((*ctx->config)["mouse_invert_pan"].get()); - if (ctx->config->contains("mouse_look_toggle")) - mouse_look_toggle = math::radians((*ctx->config)["mouse_look_toggle"].get()); - - if (ctx->config->contains("gamepad_tilt_sensitivity")) - gamepad_tilt_sensitivity = math::radians((*ctx->config)["gamepad_tilt_sensitivity"].get()); - if (ctx->config->contains("gamepad_pan_sensitivity")) - gamepad_pan_sensitivity = math::radians((*ctx->config)["gamepad_pan_sensitivity"].get()); - if (ctx->config->contains("gamepad_invert_tilt")) - gamepad_invert_tilt = math::radians((*ctx->config)["gamepad_invert_tilt"].get()); - if (ctx->config->contains("gamepad_invert_pan")) - gamepad_invert_pan = math::radians((*ctx->config)["gamepad_invert_pan"].get()); - - const input::control* move_slow = ctx->controls["move_slow"]; - const input::control* move_fast = ctx->controls["move_fast"]; - const input::control* mouse_look = ctx->controls["mouse_look"]; - - float mouse_tilt_factor = mouse_tilt_sensitivity * (mouse_invert_tilt ? -1.0f : 1.0f); - float mouse_pan_factor = mouse_pan_sensitivity * (mouse_invert_pan ? -1.0f : 1.0f); - float gamepad_tilt_factor = gamepad_tilt_sensitivity * (gamepad_invert_tilt ? -1.0f : 1.0f); - float gamepad_pan_factor = gamepad_pan_sensitivity * (gamepad_invert_pan ? -1.0f : 1.0f); - - ctx->controls["dolly_forward"]->set_active_callback - ( - [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.25f; - if (move_fast->is_active()) - value *= 4.0f; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); - - const float3 movement = {0.0f, 0.0f, -truck_speed * value * (1.0f / 60.0f)}; - entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); - } - ); - - // Dolly backward - ctx->controls["dolly_backward"]->set_active_callback - ( - [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.25f; - if (move_fast->is_active()) - value *= 4.0f; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); - - const float3 movement = {0.0f, 0.0f, truck_speed * value * (1.0f / 60.0f)}; - entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); - } - ); - - // Truck right - ctx->controls["truck_right"]->set_active_callback - ( - [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.25f; - if (move_fast->is_active()) - value *= 4.0f; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); - - const float3 movement = {truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f}; - entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); - } - ); - - // Truck left - ctx->controls["truck_left"]->set_active_callback - ( - [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.25f; - if (move_fast->is_active()) - value *= 4.0f; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); - - const float3 movement = {-truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f}; - entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); - } - ); - - // Pedestal up - ctx->controls["pedestal_up"]->set_active_callback - ( - [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.25f; - if (move_fast->is_active()) - value *= 4.0f; - - const float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f}; - entity::command::translate(*ctx->entity_registry, target_eid, movement); - } - ); - - // Pedestal down - ctx->controls["pedestal_down"]->set_active_callback - ( - [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value) - { - if (move_slow->is_active()) - value *= 0.25f; - if (move_fast->is_active()) - value *= 4.0f; - - const float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f}; - entity::command::translate(*ctx->entity_registry, target_eid, movement); - } - ); - - // Mouse rotate - ctx->controls["mouse_look"]->set_activated_callback - ( - [ctx, mouse_look_toggle]() - { - if (mouse_look_toggle) - ctx->mouse_look = !ctx->mouse_look; - else - ctx->mouse_look = true; - - ctx->app->set_relative_mouse_mode(ctx->mouse_look); - } - ); - ctx->controls["mouse_look"]->set_deactivated_callback - ( - [ctx, mouse_look_toggle]() - { - if (!mouse_look_toggle) - { - ctx->mouse_look = false; - ctx->app->set_relative_mouse_mode(false); - } - } - ); - - // Pan left - ctx->controls["pan_left_gamepad"]->set_active_callback - ( - [ctx, three_dof_eid, gamepad_pan_factor](float value) - { - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.yaw += gamepad_pan_factor * value * (1.0f / 60.0f); - } - ); - ctx->controls["pan_left_mouse"]->set_active_callback - ( - [ctx, three_dof_eid, mouse_pan_factor](float value) - { - if (!ctx->mouse_look) - return; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.yaw += mouse_pan_factor * value * (1.0f / 60.0f); - } - ); - - // Pan right - ctx->controls["pan_right_gamepad"]->set_active_callback - ( - [ctx, three_dof_eid, gamepad_pan_factor](float value) - { - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.yaw -= gamepad_pan_factor * value * (1.0f / 60.0f); - } - ); - ctx->controls["pan_right_mouse"]->set_active_callback - ( - [ctx, three_dof_eid, mouse_pan_factor](float value) - { - if (!ctx->mouse_look) - return; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.yaw -= mouse_pan_factor * value * (1.0f / 60.0f); - } - ); - - // Tilt up - ctx->controls["tilt_up_gamepad"]->set_active_callback - ( - [ctx, three_dof_eid, gamepad_tilt_factor](float value) - { - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.pitch -= gamepad_tilt_factor * value * (1.0f / 60.0f); - three_dof.pitch = std::max(math::radians(-90.0f), three_dof.pitch); - } - ); - ctx->controls["tilt_up_mouse"]->set_active_callback - ( - [ctx, three_dof_eid, mouse_tilt_factor](float value) - { - if (!ctx->mouse_look) - return; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.pitch -= mouse_tilt_factor * value * (1.0f / 60.0f); - three_dof.pitch = std::max(math::radians(-90.0f), three_dof.pitch); - } - ); - - // Tilt down - ctx->controls["tilt_down_gamepad"]->set_active_callback - ( - [ctx, three_dof_eid, gamepad_tilt_factor](float value) - { - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.pitch += gamepad_tilt_factor * value * (1.0f / 60.0f); - three_dof.pitch = std::min(math::radians(90.0f), three_dof.pitch); - } - ); - ctx->controls["tilt_down_mouse"]->set_active_callback - ( - [ctx, three_dof_eid, mouse_tilt_factor](float value) - { - if (!ctx->mouse_look) - return; - - auto& three_dof = ctx->entity_registry->get(three_dof_eid); - three_dof.pitch += mouse_tilt_factor * value * (1.0f / 60.0f); - three_dof.pitch = std::min(math::radians(90.0f), three_dof.pitch); - } - ); - - // Use tool - ctx->controls["use_tool"]->set_activated_callback - ( - [&ctx]() - { - if (ctx->entities.count("active_tool")) - { - entity::id tool_eid = ctx->entities["active_tool"]; - const auto& tool = ctx->entity_registry->get(tool_eid); - if (tool.activated) - tool.activated(); - } - } - ); - ctx->controls["use_tool"]->set_deactivated_callback - ( - [&ctx]() - { - if (ctx->entities.count("active_tool")) - { - entity::id tool_eid = ctx->entities["active_tool"]; - const auto& tool = ctx->entity_registry->get(tool_eid); - if (tool.deactivated) - tool.deactivated(); - } - } - ); - ctx->controls["use_tool"]->set_active_callback - ( - [&ctx](float value) - { - if (ctx->entities.count("active_tool")) - { - entity::id tool_eid = ctx->entities["active_tool"]; - const auto& tool = ctx->entity_registry->get(tool_eid); - if (tool.active) - tool.active(); - } - } - ); - - /* - auto [mouse_x, mouse_y] = ctx->app->get_mouse()->get_current_position(); - ctx->logger->log("tool used (" + std::to_string(mouse_x) + ", " + std::to_string(mouse_y) + ")"); - - entity::id planet_eid = ctx->entities["planet"]; - entity::component::celestial_body& body = ctx->entity_registry->get(planet_eid); - body.axial_tilt += math::radians(30.0f) * 1.0f / 60.0f; - */ -} - -} // namespace forage -} // namespace state -} // namespace game diff --git a/src/game/state/main-menu.cpp b/src/game/state/main-menu.cpp index 39d68bc..62e67d9 100644 --- a/src/game/state/main-menu.cpp +++ b/src/game/state/main-menu.cpp @@ -20,7 +20,6 @@ #include "game/state/main-menu.hpp" #include "game/state/options-menu.hpp" #include "game/state/extras-menu.hpp" -#include "game/state/forage.hpp" #include "game/state/nuptial-flight.hpp" #include "game/menu.hpp" #include "render/passes/clear-pass.hpp" diff --git a/src/game/state/nuptial-flight.cpp b/src/game/state/nuptial-flight.cpp index 544b44b..d12f782 100644 --- a/src/game/state/nuptial-flight.cpp +++ b/src/game/state/nuptial-flight.cpp @@ -113,7 +113,7 @@ nuptial_flight::nuptial_flight(game::context& ctx): game::world::set_time_scale(ctx, 60.0); // Create boids - for (int i = 0; i < 20; ++i) + for (int i = 0; i < 50; ++i) { entity::id boid_eid = ctx.entity_registry->create(); @@ -134,10 +134,10 @@ nuptial_flight::nuptial_flight(game::context& ctx): // Create steering component entity::component::steering steering; steering.agent.mass = 1.0f; - steering.agent.position = {0, 0, 0}; + steering.agent.position = {0, 100, 0}; steering.agent.velocity = {0, 0, 0}; steering.agent.acceleration = {0, 0, 0}; - steering.agent.max_force = 2.5f; + steering.agent.max_force = 4.0f; steering.agent.max_speed = 5.0f; steering.agent.max_speed_squared = steering.agent.max_speed * steering.agent.max_speed; steering.agent.orientation = math::quaternion::identity; @@ -146,18 +146,19 @@ nuptial_flight::nuptial_flight(game::context& ctx): steering.wander_weight = 1.0f; steering.wander_noise = math::radians(2000.0f); steering.wander_distance = 10.0f; - steering.wander_radius = 5.0f; + steering.wander_radius = 8.0f; steering.wander_angle = 0.0f; + steering.wander_angle2 = 0.0f; steering.seek_weight = 0.2f; - steering.seek_target = {0, 0, 0}; + steering.seek_target = {0, 100, 0}; steering.flee_weight = 0.0f; - steering.weight_sum = steering.wander_weight + steering.seek_weight + steering.flee_weight; + steering.sum_weights = steering.wander_weight + steering.seek_weight + steering.flee_weight; ctx.entity_registry->assign(boid_eid, steering); } } // Load biome - game::load::biome(ctx, "lab.bio"); + game::load::biome(ctx, "desert-scrub.bio"); // Setup and enable sky and ground passes ctx.sky_pass->set_enabled(true);