Entities tutorial?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
markgo
Party member
Posts: 190
Joined: Sat Jan 05, 2013 12:21 am
Location: USA

Re: Entities tutorial?

Post by markgo »

Seems like a mixin system to me. I use something similar to that. Instead of inheritance, I copy values from other tables to extend an object. For duplicate method names, I put similar funcs in a subtables and the method would call all of them.

Code: Select all

character()
 :mixin(animation)
 :mixin(box)
 :mixin(sound)
User avatar
Eamonn
Party member
Posts: 550
Joined: Sat May 04, 2013 1:29 pm
Location: Ireland

Re: Entities tutorial?

Post by Eamonn »

Inny wrote:As an example of the idea that you add components to entities, here's some code I've been fiddling with lately:

Code: Select all

local Colored = Component {
  _color = {0, 0, 0, 255}
}

function Colored:color(r, g, b, a)
  if r==nil and g==nil and b==nil and a==nil then
    return self._color[1], self._color[2], self._color[3], self._color[4]
  else
    local old = self._color
    self._color = { r or old[1], g or old[2], b or old[3], a or old[4] }
  end
  return self
end
In this piece of code, I establish a component, Colored, that carries this one function that lets me define or access the color for an entity.

Code: Select all

local ColoredDraw = Component {
}

function ColoredDraw:init()
  self:import(Colored):import(Rectangular)
  self:on('draw', self.drawColoredRect)
end

function ColoredDraw:drawColoredRect(offset)
  local ox, oy = offset and offset.x or 0, offset and offset.y or 0
  local x, y, w, h = self:rectangle()
  Graphics:setColor(self:color())
  love.graphics.rectangle("fill", x+ox, y+oy, w, h)
  return self
end
This next piece is a component that depends on Colored and Rectangular, that will make use of those two components to draw a colored rectangle on the screen.

The definition of the abstract "Component" is trivial enough that you don't need to see it, it's basically just a way to copy everything from one table to another, sans the key "init" which has the special meaning that it'll be called when an entity imports the component the first time, and a __call metamethod to make it easier to use. Also, the "on" function is that Observer thing I mentioned in my earlier post, which I've actually open sourced that code here.

What this gets me is that I can declare things like so:

Code: Select all

local things = ColoredDraw(Entity())
    :rectangle(200, 100, 64, 64)
    :color(255, 0, 0)
And thats it in a nutshell. Instead of complex declarations, I create tables that are copied into the final entity table.

I'm still learning this stuff myself, but I'm please with what I've been experimenting with. To get a better feel for how to do this stuff, I'd say you should cross the void and look at http://craftyjs.com/ to see how they explain Entity systems. It's very interesting stuff.
Thanks! I do have a good understanding of entities now! I'll check out that site after I finish writing this :D
"In those quiet moments, you come into my mind" - Liam Reilly
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Re: Entities tutorial?

Post by Inny »

markgo wrote:Seems like a mixin system to me.
It seems to be the easiest way to to think about it. The only sidebar is that the entity in question needs to know what mixins/components it already has, so that the components can depend on each other without mixing in the same components over and over and having the individual init functions called repeatedly. The idea for multiple functions with the same name automatically becoming a table that can call of those functions is a very interesting one.
User avatar
markgo
Party member
Posts: 190
Joined: Sat Jan 05, 2013 12:21 am
Location: USA

Re: Entities tutorial?

Post by markgo »

Well the subtable is like a table of observers and the method would pass the event and args to all the observers. Right now I haven't found a nice solution to handle duplicate functions (getters) which return values. I have to manually define the function for my object and the mixin would not override any existing key-value. It's that or redefine the function after mixin.
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Re: Entities tutorial?

Post by Inny »

markgo wrote:Right now I haven't found a nice solution to handle duplicate functions (getters) which return values.
Not to be flippant, but in my design I decided that all of the functions across components should have different names. As a for instance, my Rectangular component is based off of the Rectangle snippet I made public just over a week ago, and then I ran into a case where the name "values" was a terrible ambiguity, so I renamed it to "rectangle". This does lead to the case where the generic "draw" and "update" becomes "drawPlayer" and "updatePlayer". It does make pretty printing an entity into the debug log easier to read.
User avatar
markgo
Party member
Posts: 190
Joined: Sat Jan 05, 2013 12:21 am
Location: USA

Re: Entities tutorial?

Post by markgo »

Ah I see! Attaching the component name to functions is a nice idea. I'm probably gonna modify it to something like this:

Code: Select all

character()
	:mixin(animation)
	:mixin(box)
	:mixin(sound)
 
 -- To access a specific component, attach the component name as a prefix
 x,y,w,h = character:box_getSize()
-- or maybe something like this
 x,y,w,h = character['box']:getSize()
Cool! Thanks for the idea. Good discussion.
Post Reply

Who is online

Users browsing this forum: No registered users and 6 guests