lua-users home
lua-l archive

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




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)