Love2D | Entity Component System | Episode 1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello guys this is Ray's gamedev and welcome to the first episode in this tutorial series on how to create an entity component system in Lua used for love 2d or even Corona SDK or hell you can even take what you learn here and use it for any framework you know that you that you'd like umm so getting started today I'm going to be talking about what an actual entity class system is so let's start by talking about the traditional route that people take when creating entities and stuff like that so the traditional route is to have a base entity right and then you have you know in the entity you'll have common properties that you'll share between all of them for instance most entities need X and y position a width and a height for like checking if there's intersections or something a velocity health damage you know things like that um and then each entity will derive from it or extend from the base entity class so you can see this pirate you know it's extend it and then adds its own a Content that makes that part unique so like for instance AI pathfinding it has a weapon you know like a car Cutlass and then has armor or whatever you know that's that's that's code that's specific to the pirate but not necessarily because if you look over here on the ninja this by the way just imagine this says like katana I've forgot to change that but you'll you'll see that the u the same a I'd use the same deficit cloth or like they have an armor you know variable and stuff like that and there's there's there's a lot of code rewrite when you work in the system and you know the the solution to this is while you make another you make another base class that derives from entity that pirate ninja can derive from but doing that could be really messy and you have to really rewrite a lot of code to actually get that to work well and it's not very modular because let's say let me go to my next slide let's say you know from modding capabilities let's say want your modding community to be able to make new entities well with that structured system you have to have the source code you have to be able to compile it you have to understand it very very well and you can't really create your own unique entities like that I'm dynamic creation let's say you want to create an entity just off a string or a file you know data that you have in a file or maybe a little a table or something like that and then yeah modularity you know it's not it's very monolithic like it's not separated into a lot of different modules as you might think with a hierarchical approach it is to an extent because you can only go so far so what when entity component system tries to do is fix all this problem by making the empty not the entity doesn't have any specific variables all it has is a list or a dictionary or something of components and components are the actual separate objects that have the values so for instance this entity right here has a body component attached to the body has a position X and Y and a size and height it also has a sprite component as a sprite you know image quad and all that AI component and then entity or enemy oak let me go back enemy components um so you can kind of compose these entities by adding all the components that you want so if you want to create a ninja well the ninja is going to need a positions going or it's going to be the body right it's going to need a physics component it's going to need a image of a sprite and you can kind of take a entity and just add the features you want it'll just work and that's the really but that's the magic part of an entity component system um another aspect of it is a system now a system like all these components all they contain are variables they don't contain methods for updating or moving the entity or using them usually you can do that but it's it's a lot safer in a lot better if you actually create something called a system now there's a world and then a system a world contains entities and it create contains the system's and it tries to match the entity to the system to the system so it's kind of hard to explain it will be a lot clearer when we're in code but a system basically says I want an entity that has a body component and a sprite component that way I can rent it render this entity on so the world can be like okay so it wants a sprite and then once a body so let's look through this list of entities on oh I found one that matches that requirement so I'll pass into the systems rendering function whatever that may be that's just a brief rundown it's a little bit complicated if you want to do more research on it I definitely recommend you go to Wikipedia like any but there's tons of research this is like it's a very popular way of doing things um so let's get started today let's actually build this thing so we got a little project let me close down my slides right here so we don't have that running in the background so we just have a little love project right here right we can we can compile by saying 12:00 shift B hopefully and yeah I'll just bring up window very nice um so this series can be broken up in several parts the first part right now we're actually gonna be building this entity component system the second part we're going to be using it and showing you how you can use it in the third part I'm thinking about making it so you can or actually the second part we're going to be extending it so finding cool ways to create entities like for instance from a table and the third episode we're actually I'm going to I'm planning on making a game using the entry composer so you can see kind of how to use it how it's you know why it's actually really useful whew that was that was a lot of words let's actually get started so the first thing I'm going to do is I'm going to create an entity just create a file name identity make it a little file let's just return a table we're gonna have a new function and then we're going to create a empty table inside here I'm using Visual Studio code for this by the way uh it's what we becoming my de facto editor that and them um okay so let's let's remember back what entity has so as you can see just have a list of components and maybe a flag that says remember something so let's actually create that list of components we haven't actually defined what component is yet but we're just gonna create a table named components all right and then also I'm going to have a optional table called tags so you can add you know specific like let's say this entity has a enemy tag so that if a player collides and on with the enemy it can it can view that tag and see that oh yeah I need to damage or something I don't know it's a useful little feature in there and then we can have a remove this is used for the world later on so we're gonna create a couple functions for the entity add then we're going to component now the component is going to have a ID so let's make sure that we assert that the component has an ID it doesn't we'll just we'll leave it as an i-search so now we're going to say self dot components at component ID so you'll do component so that we just added it basically all that does is add a component to the entity then we're going to have an entity get gonna pass an ID oh let's just return that component so itself component ID alright so actually I'm going to real quick let's take a little break we're going to create a little file called utils this is going to create some common you know fun like functionality and stuff like that alright so in here is going to create one function right now there's going to be a table new all this going to do is going to create a table I found this code online I it's not mine I don't know where it's at it think should start ramp tutorial so let's make sure that we're just going to check the type of the original make sure that it is a table I'm never gonna make a local copy okay so if the original type is equal to a table and we're gonna say else if it's not equal to table then we're going to say set the copy equal to the original then we're gonna turn copy this is a recursive function so it's very fast it's very nice I really like recursive functions because they know they make your code a lot shorter and smaller so we're going to we're going to loop through this this table and just copy each value so let's make a original value in next bridge and nil and then do all right I don't know why this works honestly I'm not it I'm not Lua connoisseur like this but you know hey it works I'll take it on the reason why we need this function is that if you just say table is equal to this other table it doesn't actually copy it what it does is it copies the reference to the table so you're actually this used to this used to confuse me when I was learning Lua in and all that just used to confuse me when I was a little bit Java and stuff I yeah I couldn't for life of me figure out why my stuff wasn't working I'm just opening up my notes right now just so I can see what we're going to do next let me go back to the entity at the guy uh yeah okay okay yeah yeah so well actually I'm not going to do this real quick sorry I was just I'm just thinking out loud let's create a actual component now so let me open up my notes and let's go over here so the components can be super simple all we're going to do is return a table make your own function this is required so we're going to say ID we're going to assert that the ID is not nil I'm going to create a component right here and we're going to give it the a property called ID then all we're going to do is return the component again it's just super simple next let's create a system so I'm going to open up my system notes over here let's say system dot Lua ok again we're going to return super simple we're going to do this a couple times okay so now the system takes a table it takes a table sum of something called requires and requires are basically just IDs that each component has basically so it's like this this system requires a body component and a sprite component field render because you need to know where it's going to be rendering at and what to render yeah anyway so yeah so we're going to create our list a search at the type of requires is actually a table um then this we don't really need an ID actually yeah we don't really need an ID so I'm just gonna remove this just to make this easy okay let's see you let's create a local system table return system let's say requires is equal to requires just like that next we're going to create some functions that the system is going to have so it's gonna have a load function so as soon as the entity is created it's in it matches the required signature then it's going to be able then it's going to pass through the system load only once though updates will do the same thing but every tick every frame draw will do the same thing but again during the draw cycle I'm sure you guys understand if you don't understand how this works well at least you have some code that you can use on you I draw we might be using this later this is basically going to be drawn before this one draw so if you want some entities on top of the other one normally I would be having a render do all this the layering and stuff like that but for this for this series I mean this you can transform this into whatever you want last thing is a destroy function this is called when the entity is told to destroy itself actually I forgot to do that so let's go over to entity and let's add that function so the destroy function all it's going to do is going to say self dot Reba remove equal to true all right so we got a system what okay so this is where the this is where a lot of the magic happens this is something called a map we're going to have when we translate we're talking we're going to create a match function so what's going to happen is the world's going to pass this into it's going to loop through all the entities then looped all systems pass the entity through that system or the system's match if it matches then we'll do the code now there's a lot of more trainers let's just do match there's a lot of ways to make this more efficient this isn't the most efficient but I mean you can easily push a thousand entities on screen like you know it's not super efficient but you don't need it to be if you want to you won't do particles using entity component system you would do you would use a different system this is for entities like I don't know like you have a couple mobs or something I don't know you know it's up it's up to you all right so um what we're going to do is we're going to loop through the table of requires right we're going to say if entity yet um and I'm going to say self dot requires so we're going to try to grab that entity at index I if it's equal to nil that if it's equal to nail that means the entity does not have the required component so then we're going to return false else we're going to return true all right so I think that's just about it now we need to create the world this is where it's going to tie in tie everything together okay so up at the very top looks let's include the entity we're going to create risk and return the world or better idea we're going to create a module your name world I think it's a little bit better but we do it return world um alright so we're going to have a table of entities and table systems and I think that's yeah now it's creates a method so world register so it's going to this is where we're going to register system um and yeah let's just say system I was going to say maybe we need to do this with a hash map but I'm going to avoid that could say self dot our table insert self systems again if I were doing this in a actual game I would make a local local insert variable you know things like that there's a lot of ways you can do make this better I think it's actually all we need for that let's make it so we can update then draw um one thing I need to add to the entity we need to make sure that so we're going to say loaded we're gonna have a tag call it loaded um if it's not loaded Dennis are going to pass through all the systems and load it essentially so all right things are going pretty good let's create a function to create an entity so we're going to create a have it function that creates an entity and that just makes a little bit simpler iron ourselves let me let me think yeah let's just put this local entity is equal to MC dot new then we're going to turn that entity and we're gonna say table insert self and T's and T all right now that's looking pretty good so in the update we want to loop through all the entities now and update them and/or loop filled entities and pass them into the systems that they match up with so that they can be updated so we're going to say a for I now we want to iterate through it backwards through the loop backwards or the table backwards because we're going to be popping elements like any entity is if they get destroyed so entities one we're going to go till one and we're going to iterate backwards alright so we're going to create a local reference to the entity just like so we say if the entity wants to remove itself else we're going to do the actual update a first thing let's go back to the entity and see if we have the destroy function we do okay so we're good we're good so if it needs to remove itself we want to with building up system surprise system and I pairs again if I was going like this more uh well if I was gonna make this faster I would not use a knife edge loop I would just use a standard just standard loop okay so if system match entity then so if we match the system with the entity then we're going to say system destroy entity just like that um yeah it's as simple as that and then we're going to say table that remove a self the table that we want to remove from its entities and then I like that all right so let's lift copy so we don't have to write this a couple more times v n2 T dot loaded equal to false then we're going to pass it through all the loaded load functions just like that and I'm going to say entity that loaded let's go to true next we're going to do the exact same thing but for updating oh actually we can do this so much more efficiently I don't know why I'm doing this like that I wrote my notes when I was really tired so okay so if MC dot loaded is equal to be false then I'm going to say load the FT like that I'm just going to say entity that loaded equal to true and roots can always set that every frame and then system update pass in Delta time then the entity let's make sure we're yeah we're getting adults time alright cool so that yeah that's that's it for updating let's do the same thing for uh for drawing so we don't actually have iterate backwards this time we don't really want to iterate backwards because then we'll draw the entity in reverse order if we had a render this won't really matter but whatever okay paste that in there say if it matches we're going to call is the draw function remove the DT and I think we're good so let's do some tests this might be a long video we'll see let's see what we're we at read close to I cannot tell I'll talk to you on okay good okay so let's require the world say local world legal to require I don't why my syntax highlighting isn't okay it just worked it out look our world alright say uh world okay crashing delft time world draw like that let's make sure this build we have built in a long time alright so Thursday we have an issue so so used to them I am doing some crazy van keys all right so we have eagles equal or we don't have equals equals there that might okay so we look like we're good we look like we're good alright so let's create an entity let's just see if this works second spell that'd be very nice world create alright we create an entity let's create a component equal to a function oh let's not do that actually function new body sure XY u-turn car let's say local body is equal to let's include the component like that make it equal to component new and here when you pass an ID so we're going to say body that's very important that you memorize those IDs because they need to match up with the system it needs to be installed saying basically return body body dot X is equal X body I go to why we're going to do an x and y for now um and then function new rectangle renderer and then all it's going to do is return a component you might want to have like a component like a actually rectangle component it's a little bit of a bad name whatever you know this is just for testing so we got two components here this rectangle component also going to do is going to say yeah draw the entity um we could add a color in there we could add you know stretching we could add but maybe even like a shader or whatever but we're not going to do any of that so I've got two components with add it to the entity a new body put them out one hundred one hundred new rectangle component the other picture we're good we are good so now let's create a system to render this stuff it we careful when I type alright just like that it's include system so now when you only have like a few components this doesn't seem like a very effective saddam very effective you know the engine component doesn't seem very effective right it doesn't seem like it saves you a lot of time but when you have like 100 different components and stuff like that and you want to snap together entity like instantly like let's say you create a sprite and you just want to test it out once they're writing a new class compiling and all that craft you can just literally just write a table and give it the animation that you want and it just works it's really nice equal to system new let's pass some table of requires so it's gonna require a body and then the rectangle and this corresponds to these tags right here like that to turn the renderer let's extend it to the renderer draw function first things first axis make sure that our entity is being a it is found by the system so let's say print found one sure laughs we build it we do not have a thing because we need to register the system so world register a cowboy a new render system OOP open up a new window accidentally all right so we're not doing anything let's make sure that we're actually yeah I'm going to do a live debugging and stuff lives just so you guys can see my process I process socks by the way for Lua okay so we are looping through that Oh okay so it looks like the destroy tag yeah I don't know why I set that to true that's really strange okay so we found one but we have an error system ten so let's go over to system check out ten entity get require stuff the requires is feel to know um over there let's check out attempt to index the entity so are we not passing in the entity correctly see what the entity actually is all right so it is a table did I match entity all right let's say print entity get body alright so we are getting the table we are get a table ah was there ever happening so it's starting in okay so it's in the draw function okay so we got issues there gotcha yep yeah obviously we need to create the entity right there so we found one we're not rendering anything and that's because we didn't actually draw anything in this end right here so we want to get the body right so we want to know where to draw it let's say love graphics through rectangle let's still body X body dot why let's make them size of 3232 because we didn't specify that in the rectangle all right so we're drawing an entity that's awesome now let's make sure it looks like if we remove this rectangle on we shouldn't be drawing him because he doesn't match the the component then if we say entity add component new if we just add a random component oh we need to make sure we have an ID hello it'll still match with the system because it still has the required systems of body and rectangle so I hope you guys enjoyed that living of a long episode next time we will be creating entities on the fly using tables and stuff like that umm and then third episode again we're going to be creating a game with it so I can show you how to actually use it why is this why this is so effective and all that but anyway guys thank you for watching please subscribe if you haven't I give its video a like and stay tuned for the next episode anyway he's up
Info
Channel: SkyVaultGames
Views: 14,844
Rating: undefined out of 5
Keywords: Love2d, RazorGameDev, game development, video games, coding, programming, lua, CoronaSDK, ECS, gamedev, computer science, gaming, tutorial, video series, code, Lua, C++, c#, Monogame
Id: dZ_X0r-49cw
Channel Id: undefined
Length: 27min 51sec (1671 seconds)
Published: Mon May 15 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.