谁能给我一个关于Lua中基于组件的实体系统的示例代码?

时间:2017-03-07 20:58:03

标签: class object lua entity components

经过长时间的搜索,我决定来这里,因为无法在互联网上找到纯粹用Lua编写的基于组件的实体系统。

让我说我有实体 - > “玩家”,它包含健康和Walkspeed。 这两个Health和walkpeed是否会考虑组件本身,以后可以在其他对象中使用,例如Monster。我的理解是组件只是具有方法和属性的常规表,以后可以添加到不同的实体。如果需要,可以将两个组件添加到一个组件中,例如将Health Component和Stamina组件合并为一个组件吗? 我真正想要的是示例代码,因为我不明白这个系统将如何完全工作,如何首先创建组件,如何将它们添加到实体等... 它们如何存储在全局_G表中或作为模块块? 我完全理解OOP和继承如何在lua中工作,但基于组件的实体系统只是没有任何代码示例,只有图片和图表。

感谢:)

1 个答案:

答案 0 :(得分:0)

这两篇文章:12详细描述了ECS(实体 - 组件 - 系统)。
阅读完之后,在Lua中很容易实现ECS。

"实体"是一个表:keys是属于该实体的组件类型名称,值为true

A"组件"只是一个包含一些数据的表,对于某些类型的组件,该表可能是空的。

您将需要:

  • 全局表" All_Components":键是组件类型名称,值是子表,其中键是实体ID,值是组件,
  • 全球表" All_Entities" (键是实体ID,值是实体),
  • 您的update()函数将由逻辑排序的"系统"组成。 (" system"是一个代码块,用于对具有某些特定组件类型组合的组件的所有实体执行某些操作)。

向实体添加新组件只是创建组件表并修改All_Components和All_Entities中的一些字段。

  

让我说我有实体 - > "播放"它包含健康和Walkspeed。这两个Health和walkpeed是否会考虑组件本身,以后可以在其他对象中使用,例如Monster?

组件只是其实体的私有原始数据 您应该为另一个实体创建另一个组件实例。

All_Entities = { 
   [100] = { Health = true, Velocity = true, .... },  -- Player
   [101] = { Health = true, Velocity = true, .... },  -- Monster
   ....
}

All_Components = {
   Health = {
      [100] = { max_hp = 42, current_hp = 31 },  -- Player's health
      [101] = { max_hp = 20, current_hp = 20 },  -- Monster's health
      ....
   }, 
   Velocity = {
      [100] = { max_speed = 1.0, speed_x = 0,    speed_y = 0 },  -- Player
      [101] = { max_speed = 2.5, speed_x = -2.5, speed_y = 0 },  -- Monster
      ....
   },
   ....
}

function update(dt)
   ....
   -- "Health system" will act on all entities having "Health" component
   for entity_id, component in pairs(All_Components.Health) do
      -- 5 minutes for full regeneration
      component.current_hp = math.min(
         component.max_hp,
         component.current_hp + component.max_hp * dt / (5*60)
      )
   end
   ....
   -- "Health_Bar system" will traverse over all the entities
   -- having both Health and Health_Bar components simultaneously
   for entity_id, comp_Health_Bar in pairs(All_Components.Health_Bar) do
      local comp_Health = All_Components.Health[entity_id]
      if comp_Health then
         -- entity "entity_id" has two components:
         --    comp_Health and comp_Health_Bar
         -- Now we have all the info needed to draw its health bar
         ....
      end
   end
   ....
end

请注意,这里根本没有OOP,ECS与OOP无关。

当然,您可以在此处添加OOP,例如,将相同类型的所有组件视为某个类的实例。但你真的需要它吗? ECS的想法:"组件"只是原始数据,所有代码都在内部"系统",这种方法比OOP更灵活。

  

如果需要,可以将两个组件添加到一起或合并为例如Health Component和Stamina组件吗?

一些"系统"将需要这些组件具有不同的类型,因此最好将它们分开。