[Library] tiny-ecs - Fast Simple Entity Component System

Showcase your libraries, tools and other projects that help your fellow love users.
bakpakin
Party member
Posts: 114
Joined: Sun Mar 15, 2015 9:29 am
Location: Boston

[Library] tiny-ecs - Fast Simple Entity Component System

tiny-ecs: Make Games Faster

CODE
API
COPY/PASTE SOURCE

What is this?

tiny-ecs is a Lua module for implementing entity component systems (ECS) in a fast and flexible way. For those unfamiliar with ECS, I recommend reading the wikipedia page on it. It's the hip, cool, and not-so-new trend in how to structure a game. This should make your games easier to extend, reason about, and scale.

Why?

One of LOVE's greatest strengths and also greatest weaknesses is a lack of defined structure for games. You're just given library calls, a few callbacks to build off of, and told to get going. Without some structure, it's hard to make a medium sized game, let alone a large or marketable product. tiny-ecs is a framework / library that facilitates proven and intelligent ways to structure games.

How?

So I was making a game, and I did what probably every developer and hobbyist has done at some point, and I started making a library rather than a game. I made another Entity Component System for Lua (not just LOVE), because all the other's that I found online were either unsatisfactory or not good enough do dissuade me from making my own. I've seen a couple (Fez) around here, but they seem to be mostly ports of things like Artemis, which is a poor fit for Lua IMHO. I spent a few days making a complete library with documentation, and tiny-ecs was born. I've since put some effort into updating it and adding new features.

Demos

I personally have used tiny-ecs in two Ludum Dares successfully. I evolved the syntax and capabilities of tiny-ecs as I realized how I liked to use it and I realized how other people used it. Keep in mind that the demo code is not always a pure example of entity component systems; they are practical examples that show ONE WAY how to use tiny-ecs to make a game. I am sure there is impractical code aplenty in the demos, but don't worry - tiny-ecs.lua itself has much cleaner code.

Also keep in mind that the demos may be using an older version of tiny-ecs that is slightly different than the current one. When there is a disagreement between the API and a demo, the API wins.

DEMO1 - COMMANDO KIBBLES
DEMO2 - WEREGOAT

Feedback is appreciated.
Last edited by bakpakin on Sun Jun 05, 2016 1:43 am, edited 8 times in total.
((_((_CRAYOLA_((_((_> GitHub <_((_((_CRAYOLA_((_(()

Snuux
Prole
Posts: 49
Joined: Sun Dec 15, 2013 10:43 am
Location: Russia, Moskow
Contact:

Re: tiny-ecs - Another Entity Component System

Nice! I'm like entity-based game structure. Good luck with this lib.
My library for easy saving Slib! Try this! Now you can encrypt your save!
- Drop of light LD#30
- OUTRANGE LD#31
(Sorry for my english. I learn it myself, and I don't have enough experience)

SiENcE
Party member
Posts: 782
Joined: Thu Jul 24, 2008 2:25 pm
Location: Berlin/Germany
Contact:

Re: tiny-ecs - Another Entity Component System

Nice. I have to take a look into it. I also wanted to make my own component system, but i' currently doing a game ;-).

bakpakin
Party member
Posts: 114
Joined: Sun Mar 15, 2015 9:29 am
Location: Boston

Re: tiny-ecs - Another Entity Component System

I just finished my game for Ludum Dare 32 using tiny-ecs, bump.lua, Simple Tiled Implentation, and several other libraries. Tiny-ecs worked very well, and allowed me to use a class system (30log) on top of the entity Component System. I know that's not really how Entity Component Systems are supposed to work, but it worked well for me. Infact, I just used classes like typical oo, added my instances to the world, and tiny-ecs processed them accordingly. The syntax for creating reusable systems, however, I think is rather ugly, and I may look into that. I want to tiny-ecs to be as flexible as possible, but without assuming or forcing a class system. The game is not exactly fun, but the mechanics are clean and fast. Big shoutout to bump.lua, which is really awesome, and to Simple Tiled Implementation.

Here's the game, and the source can be found at https://github.com/bakpakin/CommandoKibbles.
Attachments
Commando Kibbles.love
(758.11 KiB) Downloaded 273 times
((_((_CRAYOLA_((_((_> GitHub <_((_((_CRAYOLA_((_(()

SiENcE
Party member
Posts: 782
Joined: Thu Jul 24, 2008 2:25 pm
Location: Berlin/Germany
Contact:

Re: tiny-ecs - Another Entity Component System

Nice and good that you used your own library in a field test . I also used my gametemplate and found some bugs and possible enhancements.

bakpakin
Party member
Posts: 114
Joined: Sun Mar 15, 2015 9:29 am
Location: Boston

Re: tiny-ecs - Another Entity Component System

Just put tiny-ecs on https://luarocks.org/. Also, I have been updating the library even more, making it faster, cleaner, and improving the syntax. The syntax should be pretty stable now, but I want to add more different types of systems (and examples, of course).
((_((_CRAYOLA_((_((_> GitHub <_((_((_CRAYOLA_((_(()

bakpakin
Party member
Posts: 114
Joined: Sun Mar 15, 2015 9:29 am
Location: Boston

Re: tiny-ecs - Another Entity Component System

I just put my example game, Command Kibbles, in the github repository. I've also updated to include the post-compo version of tiny-ecs. The system code is now cleaner, and was very easy to port from the old syntax. Now, almost the entire game is based of 30log classes, and I could easily use middleclass or any other framework if I wanted to.

Tiny-ecs is also now quite performant, and iterates through entities as fast as any other framework, or faster. Adding and Removing Systems and Entities is as fast as I can get up it without injecting ids into Entities, which I don't want to do as Entities should just be arbitrary tables. I haven't done any profiling, but the demo performs quite well, even when I add lots of Entities. Safe to say, all operations with Entities are constant time.
((_((_CRAYOLA_((_((_> GitHub <_((_((_CRAYOLA_((_(()

WetDesertRock
Citizen
Posts: 67
Joined: Fri Mar 07, 2014 8:16 pm

Re: [Library] tiny-ecs - Fast Simple Entity Component System

Sorry for the gravedig, but as I'm interested in using ecs and learning more about it, I have a few questions.

How does a separation between update and draw get handled? Just different systems with different indices?

I noticed in the example you used a combination of systems and entity methods to do the logic. Slightly confused why someone may do this, is it just sloppy programming, or are the entity methods used because they are specific to that one entity and nothing else?

When filters are used, does it cache the results? For example, if I had a fadeout system that required "fadeout" and "opacity", would just adding those fields to an entity cause it to start using the fadeout system?

shakesoda
Citizen
Posts: 78
Joined: Thu Sep 25, 2014 11:57 am
Location: Seattle, WA
Contact:

Re: [Library] tiny-ecs - Fast Simple Entity Component System

WetDesertRock wrote:When filters are used, does it cache the results? For example, if I had a fadeout system that required "fadeout" and "opacity", would just adding those fields to an entity cause it to start using the fadeout system?
Filters aren't updated until you cycle an entity in the world (i.e. world:removeEntity(foo); world:addEntity(foo)) - although I'd very much like a world:modifyEntity as well which indicates an entity getting new components without being removed (I've got some systems which make/remove caches on add/remove - and cycling the entity means losing their data)
excessive ❤ moé (LÖVE3D, CPML, ...). holo on IRC.

bakpakin
Party member
Posts: 114
Joined: Sun Mar 15, 2015 9:29 am
Location: Boston

Re: [Library] tiny-ecs - Fast Simple Entity Component System

Filters do cache results for preformance reasons; systems that iterate through entities only iterate through a sequence when they update. Unless you add or remove a lot of entities every update cycle, there is very little overhead. In fact, a vanilla 'tiny.system' doesn't even iterate through it's entities by default, it just calls its 'update' function.

As for my example, it is a little bit of sloppy programming (considering that game was made in 48 for a game jam), but also an acknowledgement that sometimes entity methods are just easier than systems. This hybrid approach is actually what is used in many major game engines, like Unity. If I had more time and needed to scale the project more, I would moved more logic to systems and out of the the entities. tiny-ecs is completely compatible with most major Lua class systems including middleclass and 30log, to name two, so entity methods don't interfere with other more traditional system based logic. This one of the benefits of a dynamic language, as I see it.

shakesoda is correct in saying that caches aren't updated every frame for already existing entities. Right now, you just re-add entities to the world to update them if you add or remove components that would make them valid or invalid for certain systems. shakesoda's suggestion is valid, however.

Example on how to change an entities components:

Code: Select all

myEntity.newComponent = {1, 3, 5, 7, 42}
myEntity.oldComponent = nil

-- re-add myEntity to the World to refresh caches for that entity.
world:add(myEntity)

Separating drawing and update logic is another thing I added after the fact. In LOVE, you don't actually have to separate them (you could just put all of your update logic in love.draw), but it's often useful to make SURE that your update code gets called before your draw code. tiny.update takes an optional parameter after deltaTime called 'filter' that only selects certain systems. you can make two different filters for updateSystems and drawSystems and update only the correct systems in love.update and love.draw.

Code: Select all

-- Create drawing systems
myDrawSystem = tiny.system({isDrawingSystem = true})
myDrawSystem2 = tiny.system({isDrawingSystem = true})

-- Create update systems
myUpdateSystem = tiny.system()
myUpdateSystem2 = tiny.system()

-- Make system filters
drawSystemFilter = tiny.requireAll("isDrawingSystem")
updateSystemFilter = tiny.rejectAll("isDrawingSystem")

-- Initialize world
world = tiny.world(myDrawSystem, myDrawSystem2, myUpdateSystem, myUpdateSystem2)

function love.update(dt)
world:update(dt, updateSystemFilter)
end

function love.draw()
world:update(love.timer.getDelta(), drawSystemFilter)
end


In the above example, Update Systems will be called love.update, and Drawing Systems in love.draw.

For more info and examples, check the api here, and a newer example here. In the newer example in particular, check love.update and love.draw in main.lua for an example on how to separate update and draw systems. I do apologize, however, for the messy code.

Hope that helps and is not too confusing.

As its seems a few people are using tiny-ecs, I'm glad this thread is coming out of the grave.
Last edited by bakpakin on Sat Jun 18, 2016 9:28 pm, edited 1 time in total.
((_((_CRAYOLA_((_((_> GitHub <_((_((_CRAYOLA_((_(()

Who is online

Users browsing this forum: No registered users and 9 guests