summaryrefslogtreecommitdiff
path: root/honey
diff options
context:
space:
mode:
Diffstat (limited to 'honey')
-rw-r--r--honey/ecs-systems.lua93
-rw-r--r--honey/ecs.lua15
2 files changed, 103 insertions, 5 deletions
diff --git a/honey/ecs-systems.lua b/honey/ecs-systems.lua
index 5b9692b..ed51e5d 100644
--- a/honey/ecs-systems.lua
+++ b/honey/ecs-systems.lua
@@ -8,6 +8,28 @@ setmetatable(module, {__index=_G})
setfenv(1, module)
+-- helper function for retrieving script functions
+local function getFunction(script)
+ local f = require(script.script)
+ if script.func then
+ return f[script.func]
+ else
+ return f
+ end
+end
+
+
+--===== dispatch messages to handlers =====--
+
+dispatch = function(entities, msg, data)
+ local query = entities:queryComponent(msg)
+ for id, handler in pairs(query) do
+ local f = getFunction(handler)
+ f(entities, id, data)
+ end
+end
+
+
--===== transform cascading =====--
@@ -111,9 +133,6 @@ end
---===== update functions =====--
-
-
--===== script system =====--
script = function(params)
@@ -122,7 +141,7 @@ script = function(params)
update=function(self, dt)
local entities = self.db:queryComponent("script")
for id, script in pairs(entities) do
- local f = require(script.name)
+ local f = getFunction(script)
f(self.db, id, dt)
end
end
@@ -130,4 +149,70 @@ script = function(params)
end
+--===== physics =====--
+
+physics = function(params)
+ local interval = params.interval or 0.01
+ local groupSize = params.groupSize or 20
+ return {
+ db=params.db,
+ space=params.space,
+ world=params.world,
+ contactGroup=ode.JointGroupCreate(groupSize),
+ time=interval,
+ update=function(self, dt)
+ local query = self.db:queryComponent("physics")
+ -- TODO: create physics bodies
+
+ self.time = self.time + dt
+ -- only run the update every [interval] seconds
+ if self.time > interval then
+ self.time = self.time - interval
+
+ -- check for near collisions between geoms
+ ode.SpaceCollide(self.space, function(a, b)
+ -- check for actual collisions
+ local collisions = ode.Collide(a, b, 1)
+ if #collisions > 0 then
+ -- set up the joint params
+ local contact = ode.CreateContact{ surface={
+ mode = ode.ContactBounce + ode.ContactSoftCFM,
+ mu = ode.Infinity,
+ bounce = 0.90,
+ bounce_vel = 0.1,
+ soft_cfm = 0.001,
+ }}
+ ode.ContactSetGeom(contact, collisions[1])
+ -- create the joint
+ local joint = ode.JointCreateContact(
+ self.world,
+ self.contactgroup,
+ contact
+ )
+ -- attach the two bodies
+ local bodyA = ode.GeomGetData(a)
+ local bodyB = ode.GeomGetData(b)
+ ode.JointAttach(joint, bodyA, bodyB)
+ end
+ end)
+ -- update the world
+ ode.WorldQuickStep(self.world, interval)
+ -- remove all contact joints
+ ode.JointGroupEmpty(self.contactGroup)
+
+ -- update entity transforms
+ for id, physics in pairs(query) do
+ local x,y,z = ode.BodyGetPosition(physics._body)
+ local d,a,b,c = ode.BodyGetQuaternion(physics._body)
+ entity.transform
+ :identity()
+ :translate(Vec3{x,y,z})
+ :mul(Quaternion{a,b,c,d}:toMat4())
+ end
+ end
+ end,
+ }
+end
+
+
return module
diff --git a/honey/ecs.lua b/honey/ecs.lua
index 69feb12..39f1c77 100644
--- a/honey/ecs.lua
+++ b/honey/ecs.lua
@@ -69,9 +69,22 @@ function EntityDb.addComponent(self, id, name, value)
end
+-- add multiple components at once, for convenience
+function EntityDb.addComponents(self, id, components)
+ for name, value in pairs(components) do
+ self:addComponent(id, name, value)
+ end
+end
+
+
-- get all entities with a given component
function EntityDb.queryComponent(self, name)
- return self.components[name].data
+ local component = self.components[name]
+ if component then
+ return component.data
+ else
+ return {}
+ end
end