add radial triggers
This commit is contained in:
parent
e6c3775286
commit
736e5b95b6
@ -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]
|
||||
]
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
}
|
||||
|
||||
@ -42,6 +42,17 @@ void Entity::setRig(rigging::RigConfig* rigConfig) {
|
||||
Entities::Entities(Level* level) : level(level) {
|
||||
}
|
||||
|
||||
template<void(*callback)(const Entity&, size_t, entityid_t)>
|
||||
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<Transform>(entity, pos, size, glm::mat3(1.0f));
|
||||
auto& body = registry.emplace<Rigidbody>(
|
||||
entity, true, Hitbox {pos, def.hitbox}, std::vector<Trigger>{});
|
||||
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<scripting::on_trigger_enter>(this),
|
||||
create_trigger_callback<scripting::on_trigger_exit>(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<scripting::on_trigger_enter>(this),
|
||||
create_trigger_callback<scripting::on_trigger_exit>(this)
|
||||
};
|
||||
}
|
||||
auto& scripting = registry.emplace<Scripting>(
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,8 @@ struct EntityDef {
|
||||
|
||||
std::string scriptName = name.substr(name.find(':')+1);
|
||||
glm::vec3 hitbox {0.5f};
|
||||
std::vector<AABB> boxTriggers {};
|
||||
std::vector<std::pair<size_t, AABB>> boxTriggers {};
|
||||
std::vector<std::pair<size_t, float>> radialTriggers {};
|
||||
std::string rigName = name.substr(name.find(":")+1);
|
||||
|
||||
struct {
|
||||
|
||||
@ -8,15 +8,32 @@
|
||||
#include <functional>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
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<void(entityid_t, size_t, entityid_t)>;
|
||||
|
||||
struct Trigger {
|
||||
bool enabled = true;
|
||||
TriggerType type;
|
||||
size_t index;
|
||||
entityid_t entity;
|
||||
AABB aabb;
|
||||
AABB calculated;
|
||||
TriggerParams params;
|
||||
TriggerParams calculated;
|
||||
std::set<entityid_t> prevEntered;
|
||||
std::set<entityid_t> nextEntered;
|
||||
std::function<void(entityid_t, size_t, entityid_t)> enterCallback;
|
||||
std::function<void(entityid_t, size_t, entityid_t)> exitCallback;
|
||||
triggercallback enterCallback;
|
||||
triggercallback exitCallback;
|
||||
};
|
||||
|
||||
struct Hitbox {
|
||||
|
||||
@ -7,13 +7,15 @@
|
||||
#include "../voxels/voxel.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtx/norm.hpp>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user