From 736e5b95b6240af9196b66b053c2558d1dbdd26b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 4 Jul 2024 06:09:29 +0300 Subject: [PATCH] add radial triggers --- res/content/base/entities/drop.json | 3 +- res/content/base/scripts/components/drop.lua | 18 ++++- res/content/base/scripts/hud.lua | 1 - src/content/ContentLoader.cpp | 6 +- src/maths/aabb.hpp | 2 +- src/objects/Entities.cpp | 75 +++++++++++++------- src/objects/EntityDef.hpp | 3 +- src/physics/Hitbox.hpp | 25 +++++-- src/physics/PhysicsSolver.cpp | 28 ++++++-- 9 files changed, 117 insertions(+), 44 deletions(-) diff --git a/res/content/base/entities/drop.json b/res/content/base/entities/drop.json index 6f0e680a..e158ddcb 100644 --- a/res/content/base/entities/drop.json +++ b/res/content/base/entities/drop.json @@ -1,6 +1,7 @@ { "hitbox": [0.2, 0.125, 0.2], "triggers": [ - ["aabb", -0.2, -0.2, -0.2, 0.2, 0.2, 0.2] + ["aabb", -0.2, -0.2, -0.2, 0.2, 0.2, 0.2], + ["radius", 1.6] ] } diff --git a/res/content/base/scripts/components/drop.lua b/res/content/base/scripts/components/drop.lua index 3adc5760..a68fb463 100644 --- a/res/content/base/scripts/components/drop.lua +++ b/res/content/base/scripts/components/drop.lua @@ -4,6 +4,7 @@ local rig = entity.modeltree inair = true ready = false +target = -1 local dropitem = ARGS.item local scale = {1, 1, 1} @@ -60,11 +61,20 @@ function on_fall() end function on_trigger_enter(index, oid) - if ready and oid == 0 then + if ready and oid == 0 and index == 0 then entity:despawn() inventory.add(player.get_inventory(oid), dropitem.id, dropitem.count) audio.play_sound_2d("events/pickup", 0.5, 0.8+math.random()*0.4, "regular") end + if index == 1 and ready and oid == 0 then + target = oid + end +end + +function on_trigger_exit(index, oid) + if oid == target and index == 1 then + target = -1 + end end function on_update() @@ -79,4 +89,10 @@ function on_update() mat4.scale(matrix, scale, matrix) rig:set_matrix(0, matrix) end + if target ~= -1 then + local dir = vec3.sub({player.get_pos(target)}, tsf:get_pos()) + vec3.normalize(dir, dir) + vec3.mul(dir, 10.0, dir) + body:set_vel(dir) + end end diff --git a/res/content/base/scripts/hud.lua b/res/content/base/scripts/hud.lua index 4a3af9cb..553e9945 100644 --- a/res/content/base/scripts/hud.lua +++ b/res/content/base/scripts/hud.lua @@ -14,7 +14,6 @@ function on_hud_open() local pvel = {player.get_vel(pid)} local ppos = vec3.add({player.get_pos(pid)}, {0, 0.7, 0}) local throw_force = vec3.mul(player.get_dir(pid), DROP_FORCE) - local drop = entities.spawn("base:drop", ppos, {item={ id=itemid, count=1 diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 80fbd9a4..f363702a 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -320,10 +320,12 @@ void ContentLoader::loadEntity(EntityDef& def, const std::string& name, const fs if (auto triggerarr = triggersarr->list(i)) { auto triggerType = triggerarr->str(0); if (triggerType == "aabb") { - def.boxTriggers.push_back({ + def.boxTriggers.push_back({i, { {triggerarr->num(1), triggerarr->num(2), triggerarr->num(3)}, {triggerarr->num(4), triggerarr->num(5), triggerarr->num(6)} - }); + }}); + } else if (triggerType == "radius") { + def.radialTriggers.push_back({i, triggerarr->num(1)}); } else { logger.error() << name << ": trigger #" << i << " - unknown type " << util::quote(triggerType); diff --git a/src/maths/aabb.hpp b/src/maths/aabb.hpp index 7859ef65..38c829ce 100644 --- a/src/maths/aabb.hpp +++ b/src/maths/aabb.hpp @@ -8,7 +8,7 @@ struct AABB { glm::vec3 a {0.0f}; glm::vec3 b {1.0f, 1.0f, 1.0f}; - AABB() {} + AABB() = default; AABB(glm::vec3 size) : a(0.0f), b(size) { } diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index b1d1356a..058e3ec4 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -42,6 +42,17 @@ void Entity::setRig(rigging::RigConfig* rigConfig) { Entities::Entities(Level* level) : level(level) { } +template +static triggercallback create_trigger_callback(Entities* entities) { + return [=](auto entityid, auto index, auto otherid) { + if (auto entity = entities->get(entityid)) { + if (entity->isValid()) { + callback(*entity, index, otherid); + } + } + }; +} + entityid_t Entities::spawn( Assets* assets, EntityDef& def, @@ -59,28 +70,25 @@ entityid_t Entities::spawn( registry.emplace(entity, pos, size, glm::mat3(1.0f)); auto& body = registry.emplace( entity, true, Hitbox {pos, def.hitbox}, std::vector{}); - for (auto& box : def.boxTriggers) { - body.triggers.emplace_back(Trigger{ - true, - id, - box, - AABB{}, - {}, - {}, - [=](auto entityid, auto index, auto otherid) { - if (auto entity = get(entityid)) { - if (entity->isValid()) { - scripting::on_trigger_enter(*entity, index, otherid); - } - } - }, - [=](auto entityid, auto index, auto otherid) { - if (auto entity = get(entityid)) { - if (entity->isValid()) { - scripting::on_trigger_exit(*entity, index, otherid); - } - } - }}); + + body.triggers.resize(def.radialTriggers.size() + def.boxTriggers.size()); + for (auto& [i, box] : def.boxTriggers) { + TriggerParams params {}; + params.aabb = box; + body.triggers[i] = Trigger { + true, TriggerType::AABB, i, id, params, params, {}, {}, + create_trigger_callback(this), + create_trigger_callback(this) + }; + } + for (auto& [i, radius] : def.radialTriggers) { + TriggerParams params {}; + params.radial = glm::vec4(radius); + body.triggers[i] = Trigger { + true, TriggerType::RADIUS, i, id, params, params, {}, {}, + create_trigger_callback(this), + create_trigger_callback(this) + }; } auto& scripting = registry.emplace( entity, entity_funcs_set {}, nullptr); @@ -135,8 +143,21 @@ void Entities::preparePhysics() { } trigger.prevEntered = trigger.nextEntered; trigger.nextEntered.clear(); - trigger.calculated = trigger.aabb; - trigger.calculated.transform(transform.combined); + + switch (trigger.type) { + case TriggerType::AABB: + trigger.calculated.aabb = trigger.params.aabb; + trigger.calculated.aabb.transform(transform.combined); + break; + case TriggerType::RADIUS: + trigger.calculated.radial = glm::vec4( + rigidbody.hitbox.position.x, + rigidbody.hitbox.position.y, + rigidbody.hitbox.position.z, + trigger.params.radial.w* + trigger.params.radial.w); + break; + } triggers.push_back(&trigger); } } @@ -204,9 +225,11 @@ void Entities::renderDebug(LineBatch& batch, const Frustum& frustum) { batch.box(hitbox.position, hitbox.halfsize * 2.0f, glm::vec4(1.0f)); for (auto& trigger : rigidbody.triggers) { + if (trigger.type != TriggerType::AABB) + continue; batch.box( - trigger.calculated.center(), - trigger.calculated.size(), + trigger.calculated.aabb.center(), + trigger.calculated.aabb.size(), glm::vec4(1.0f, 1.0f, 0.0f, 1.0f)); } } diff --git a/src/objects/EntityDef.hpp b/src/objects/EntityDef.hpp index f4bf20d2..a1044387 100644 --- a/src/objects/EntityDef.hpp +++ b/src/objects/EntityDef.hpp @@ -18,7 +18,8 @@ struct EntityDef { std::string scriptName = name.substr(name.find(':')+1); glm::vec3 hitbox {0.5f}; - std::vector boxTriggers {}; + std::vector> boxTriggers {}; + std::vector> radialTriggers {}; std::string rigName = name.substr(name.find(":")+1); struct { diff --git a/src/physics/Hitbox.hpp b/src/physics/Hitbox.hpp index 5090d7dc..5c0f9933 100644 --- a/src/physics/Hitbox.hpp +++ b/src/physics/Hitbox.hpp @@ -8,15 +8,32 @@ #include #include +enum class TriggerType { + AABB, + RADIUS, +}; + +union TriggerParams { + AABB aabb; + glm::vec4 radial; // x,y,z calculated entity coords + w - radius + + constexpr TriggerParams() : aabb() { + } +}; + +using triggercallback = std::function; + struct Trigger { bool enabled = true; + TriggerType type; + size_t index; entityid_t entity; - AABB aabb; - AABB calculated; + TriggerParams params; + TriggerParams calculated; std::set prevEntered; std::set nextEntered; - std::function enterCallback; - std::function exitCallback; + triggercallback enterCallback; + triggercallback exitCallback; }; struct Hitbox { diff --git a/src/physics/PhysicsSolver.cpp b/src/physics/PhysicsSolver.cpp index 96f66ba2..3057d587 100644 --- a/src/physics/PhysicsSolver.cpp +++ b/src/physics/PhysicsSolver.cpp @@ -7,13 +7,15 @@ #include "../voxels/voxel.hpp" #include +#define GLM_ENABLE_EXPERIMENTAL +#include const float E = 0.03f; const float MAX_FIX = 0.1f; PhysicsSolver::PhysicsSolver(glm::vec3 gravity) : gravity(gravity) { } -#include "../util/timeutil.hpp" + void PhysicsSolver::step( Chunks* chunks, Hitbox* hitbox, @@ -85,15 +87,27 @@ void PhysicsSolver::step( aabb.a = hitbox->position - hitbox->halfsize; aabb.b = hitbox->position + hitbox->halfsize; for (size_t i = 0; i < triggers.size(); i++) { - auto& trigger = triggers[i]; - if (trigger->entity == entity) { + auto& trigger = *triggers[i]; + if (trigger.entity == entity) { continue; } - if (aabb.intersect(trigger->calculated)) { - if (trigger->prevEntered.find(entity) == trigger->prevEntered.end()) { - trigger->enterCallback(trigger->entity, i, entity); + + bool triggered = false; + switch (trigger.type) { + case TriggerType::AABB: + triggered = aabb.intersect(trigger.calculated.aabb); + break; + case TriggerType::RADIUS: + triggered = glm::distance2( + hitbox->position, glm::vec3(trigger.calculated.radial)) + < trigger.calculated.radial.w; + break; + } + if (triggered) { + if (trigger.prevEntered.find(entity) == trigger.prevEntered.end()) { + trigger.enterCallback(trigger.entity, trigger.index, entity); } - trigger->nextEntered.insert(entity); + trigger.nextEntered.insert(entity); } } }