lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]




On Fri, Aug 2, 2019 at 9:52 AM Soni "They/Them" L. <fakedme@gmail.com> wrote:


On 2019-08-02 11:46 a.m., Coda Highland wrote:
>
>
> On Fri, Aug 2, 2019 at 9:41 AM Coda Highland <chighland@gmail.com
> <mailto:chighland@gmail.com>> wrote:
>
>
>
>     On Fri, Aug 2, 2019 at 2:33 AM Egor Skriptunoff
>     <egor.skriptunoff@gmail.com <mailto:egor.skriptunoff@gmail.com>>
>     wrote:
>
>         On Fri, Aug 2, 2019 at 12:19 AM Soni "They/Them" L. wrote:
>
>             > On 2019-08-01 6:05 p.m., Egor Skriptunoff wrote:
>             >> Could you provide an example to show benefits of traits?
>             >> What kinds of tasks traits solve better than conventional
>             >> 'objects-and-methods' approach?
>             >>
>             >
>             > I recommend reading
>             https://en.wikipedia.org/wiki/Entity_component_system
>
>             (Well, besides reading that, I recommend actually checking
>             out Rust and
>             using it for a while. You'll see what I mean.)
>
>
>         Could you just show a simple example from real-life
>         programming where using traits is better than not using them?
>         Such example should be understandable by any Lua programmer
>         (without Rust knowledge).
>         If you can't provide such example then why Lua users might
>         want to use Cratera?
>
>
>     If your own example on SO satisfies you, then let me rewrite it
>     using standard Lua syntax (not Cratera traits because I'm not
>     familiar enough):
>
>     all_entities = {]
>
>     function HealthRegen(self, entity, dt)
>       self.current_hp = math.min(
>         self.max_hp,
>         self.current_hp + self.max_hp * dt / (5*60)
>       )
>     end
>
>     traits = {
>       Health = function(hp) return { max_hp = hp, current_hp = hp,
>     update = HealthRegen },
>       Velocity = function(max) return { max_speed = max, speed_x = 0,
>     speed_y = 0 }
>     }
>
>     function Instantiate(type)
>       local obj = {}
>       for trait, param in pairs(type) do
>         obj[trait] = traits[trait](param)
>       end
>       table.insert(all_entities, obj)
>       return obj
>     end
>
>     Player = { Health = 42, Velocity = 1.0 }
>     Monster = { Health = 100, Velocity = 2.5 }
>
>     player = Instantiate(Player)
>     monster = Instantiate(Monster)
>
>     function update(dt)
>       for _, entity in pairs(all_entities) do
>         if entity.update then entity:update(dt) end
>         for _, trait in pairs(entity) do
>           if trait.update then trait:update(entity, dt) end
>         end
>       end
>     end
>
>
> Forgot to mention...
>
> function HealthDamage(self, entity, amount)
>   self.current_hp = self.current_hp - amount
>   if self.current_hp <= 0 then
>     self.current_hp = 0
>     if entity.OnDeath then entity:OnDeath() end
>   end
> end
>
> monster.Health:damage(monster, 10)
>
> This isn't quite compatible with how Cratera's syntax does it, because
> at this point I would want to write monster:[Health]:damage(10) and I
> can't do that. But it should still get the point across.
>
> /s/ Adam
>
>

you don't need to write monster:[Health]:damage(10) because you can just
write monster[Health] inside damage. e.g.:

function Health.damage(entity, amount)
     local healthComponent = entity[Health]
     -- ...
end

entity = {[Health] = Health.new()}

entity:[Health].damage(amount)


I realized that while I was writing the message but the quick-and-dirty ECS scheme I had cobbled together there wasn't written with the Cratera style of doing things in mind and it was too late to amend it. Thanks for following up with a better description.

/s/ Adam