From 39e97166b83531f3b1da69514653c7dd9e8810ff Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Fri, 4 Nov 2022 22:37:00 +0000 Subject: feat: add force field component/system This will apply continuous or instantaneus force to any object within a certain range. --- raccoon.lua | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/raccoon.lua b/raccoon.lua index ed0eaa2..8db51ca 100644 --- a/raccoon.lua +++ b/raccoon.lua @@ -20,12 +20,27 @@ local util = { } } +function util.signum(n) + if n < 0 then + return -1 + elseif n > 0 then + return 1 + else + return 0 + end +end + function util.size(t) local count = 0 for _,_ in pairs(t) do count = count + 1 end return count end +function util.distance(p1,p2) + local vec = { p2.x - p1.x, p2.y - p1.y } + return math.sqrt(math.pow(vec[1], 2) + math.pow(vec[2], 2)), vec +end + --- Class factory. -- Creates a new class. A function -- ``` @@ -316,12 +331,46 @@ function Particles:spawn(pos, entities) end end +local ForceField = Component() +function ForceField:init(force,range,instant) + self.force = force or 1 + self.range = range or 1 + self.instant = instant + return self +end local Metadata = Component() function Metadata:init(name) self.name = name or "Unnamed" return self end + +local ForceFieldSystem = System(Pos,ForceField) +function ForceFieldSystem:exec(entity,enemies) + local pos = entity.get_component[Pos] + local ff = entity.get_component[ForceField] + for _,e in pairs(enemies) do + if e.has_component[Pos] and e.has_component[Movement] then + local pos1 = e.get_component[Pos] + local mov = e.get_component[Movement] + local dist,vec = util.distance(pos,pos1) + if dist < ff.range then + if e.has_component[Metadata] then + local meta = e.get_component[Metadata] + trace("Hit " .. meta.name .. " at position " .. pos1.x .. " " .. pos1.y) + else + trace("Hit entity at position " .. pos1.x .. " " .. pos1.y) + end + mov.cur.x = mov.cur.x + util.signum(vec[1]) * ff.force + mov.cur.y = mov.cur.y - ff.force + end + end + end + if ff.instant then + return true, {ff} + end +end + local InputSystem = System(Input) function InputSystem:exec(entity) local input = entity.get_component[Input] @@ -547,7 +596,7 @@ local player = Entity() local pos = entity.get_component[Pos]--:to_screen(lpos) table.insert( game.entities, - Entity():with_component(Pos(pos.x,pos.y)):with_component(CircleEffect(20))) + Entity():with_component(Pos(pos.x,pos.y)):with_component(ForceField(5,10,true)):with_component(CircleEffect(20))) end, nil)) @@ -585,6 +634,7 @@ function TIC() MovementSystem:run(game.entities) ActionSystem:run(game.entities, game) EffectSystem:run(game.entities) + ForceFieldSystem:run(game.entities, game.entities) PosAnimSystem:run(game.entities) ParticlesSystem:run(game.entities, game) LevelSystem:run(game.levels, game) -- cgit v1.2.3