Code: Select all
character()
:mixin(animation)
:mixin(box)
:mixin(sound)
Code: Select all
character()
:mixin(animation)
:mixin(box)
:mixin(sound)
Thanks! I do have a good understanding of entities now! I'll check out that site after I finish writing thisInny wrote:As an example of the idea that you add components to entities, here's some code I've been fiddling with lately:
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 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
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.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
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:
And thats it in a nutshell. Instead of complex declarations, I create tables that are copied into the final entity table.Code: Select all
local things = ColoredDraw(Entity()) :rectangle(200, 100, 64, 64) :color(255, 0, 0)
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.
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.markgo wrote:Seems like a mixin system to me.
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.markgo wrote:Right now I haven't found a nice solution to handle duplicate functions (getters) which return values.
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()
Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot] and 5 guests