Handmade Hero Day 277 - The Sparse Entity System

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone and welcome to handmade Hero the show recode a complete game live on stream we have a new member of the handmade hero family today I am pleased to say as you know since starting the series we have had Allen Webster create an editor that we now use on the stream so we no longer use canoe Emacs we use for coder on the stream and it turns out that we now are able to switch over to our own drawing program as well and let me be it's called Milton and it's actually on the handmade Network site much like for coder is and I wish that I could pronounce that I'll tell you a little story I as well I won't say used to because we probably will do more episodes in the future but every so often myself and Jeff Roberts we do a podcast called the Jeff and Casey show and on this podcast quite some time I believe before a hand made hero even was the thing we got an email from someone named Sergio and I tried we liked would read mail on the air like when we receive letters to the show we'd read them it for the episodes and it just so happened that for some reason I wanted to try and say like Sergio in like a in like a sexy Spanish I want to be like say Akio or something like this and I and I was like but I don't know how I was like I don't have any Spanish skills whatsoever like I I have no idea how to say Sergio properly let alone sexily and so it was just it was a bit of a joke at the time but point being that happened well fast forward to after handmade hero and it turns out that this paint program is actually made by the same and I'll just say Sergio so I won't try to pronounce his name in the sexy fashion because I I have been informed that I already failed at it but point being if you scroll down on here Milton handmade network you will get to him here he is let's let's say it's Sergio Gonzales Sergio I don't know you know what Sergio send me a wave file of you saying your name if you want to say it sexy you can say it sexy if you wanted to say it regular you could say it regular but least it'll be pronounced correctly and so I can finally like you know get past that problematic pronunciation that I did on the Jeff and Kate show which was horribly wrong and not sexy at all but point being you can go and you can check this out this drawing program yourself it's basically a replacement for what we have been using you know it's got like infinite canvas and stuff like that just like mischief did but it's actually quite a bit better than a mischief in a number of ways like it automatically saves your progress and stuff so you don't have to worry about any of that so it kind of seems like it might actually be a little bit better than then mischeif was much like for coder is starting out to be better than the new Emacs so upgrades all around and point being he did not have a patreon when I last checked but it looks like this is actually happening now alright so there is a brand new patreon that you can support as well I will be supporting it immediately after this and and yeah I always try to like any products that we use on stream I try to put some money from the handmade here at patreon over into those every month to help the folks who are making stuff that we can use and so here is the package some really cool stuff about it actually is I love that the old-school deluxe paint interface kind of thing where if you hit the tab key everything goes away I really like that and it doesn't have the bug of alt tab switching to eyedropper mode which is a huge pain in mischief so already like you know this is a bit of an improvement but there's still some kinks to work out so we're just trying it out we're gonna try it for a while mostly the only thing that I noticed is the the tracking speed seems a little laggy and I think that might have something to do with well actually I don't know yet yeah the source code is actually available so I was gonna go take a look at it on this particular machine this graphics card is is awfully old too and so you know anything that's that's not just so maybe causing it to be a little bit hiccup II so we'll see but as it is it seems like it's pretty easy to do like you know I can go ahead and say de 277 just like before and I can write so like I said kind of cool that we're eventually switching over to all handmade stuff and like I said the source code to this is actually available as well so we can actually go check it at some point maybe if we do a stream and see what's happening in terms of the the refresh rate on this machine there might be some things we can do to to fix it on this machine for speed because that was the only thing that I noticed that was different I liked everything else more and it doesn't have that that nasty bug that always kind of plagued me which is pretty great so there we go so that's a new member of the team here at handmade hero and so now really I guess we just have to figure out some way if the debugger you know if we can replace Visual Studio we're down to almost nothing I guess we got the compiler but you know we're getting close to no tools but the compiler really that that aren't from the handmade hero community itself which is pretty pretty awesome if I do say so myself but all that being said we still have some programming to do that is you know we've got to get down to business and say 277 so if you want to follow along with the programming at home you're gonna want to unpack day to set 276 is source code into a directory somewhere and that will be right matching up with where I am myself now what we ended on last time was we had pretty much gotten the hoppin under control in terms of what I wanted and basically we're waiting for probably some some new art and so what we'll probably do is revisit the hopping to when we get new art because I've kind of got it all shrunk down and and and scaled all weird and stuff because that's sort of the roundness that I expect or need the art to be eventually so like I said that's gonna be something that kind of has to get taken care of with art assets but for now the feel is actually feeling okay so the actual playability of it seems pretty reasonable to me and of course it's hard to say that until I actually start interacting with the game proper so we'll see how it goes but it's at least good enough at the moment for us to sort of for me to feel comfortable moving on to other parts of the game and bringing them up to speed I'm pretty confident that we can make this work as it is with you know with more tuning and more artwork we can figure out a way to make that happen all right so what are we going to do next well I think what I would like to do next is I would like to sort of try to move the entity system and the structure of the world mode I'd like to start trying to move those towards something more real like it's always kind of been a dumping ground where we just been like okay whatever we're doing it's fine doesn't matter and we kind of have to sort of start making that a little bit more real and we need to do that in two ways one way is we have to actually upgrade sort of the logic side of that and how it's working to be a little closer to what I think is a proper system because we've always sort of put the enemy system off and I think now is a good time to actually make it happen so we need to do that and then the other thing that we need to do is I would like to get the rendering under control now that I know exactly what we're going to be doing in terms of how scenes are basically so as far as I like layers are composited we want to sort of going and clean out that Z and all that sort of stuff so I think what I'm gonna do is I'm gonna partition us into a couple sort of passes through the code base the first thing that I'm gonna do is I'm gonna start by cleaning up the entity processing like that whole just the whole logic side of things I'm gonna start by doing some passes over that to sort of get that into a more reasonable place and that includes like the storing of the you know it's where things are stored and how and how they get unpacked and repacked and all those sort of things I want to take that and give that a good sort of once-over and then what I'd also like to do is ping pong after that over to the rendering thing and get seams rendering properly so that now that we know like how rooms sort of work I want to get that sort of nailed down as well and then we can come back and start really working on the entity stuff once that render part is complete and that'll be you know working on stuff like how we generate worlds and how we do AIS and that sort of thing and just basically putting in the gameplay stuff the kind of code that I hate as you know because it's really kind of arbitrary and doesn't have much to do with anything but you kind of have to do it so anyway that's what I'd like to do and so right now I just probably want to spend some time taking stock of where things are and I want to talk to you a little bit about sort of how I'm conceptualizing this stuff working and it's a little bit crazy and so I'm going to sort of tell you what my plan is going forwards and so here it is so in fact I I'll get some good usage out of out of Milton I think just to say the least so here's the deal there's lots of ways you can do entity systems right there's and you know what I might do - I might change this brush size a little bit I don't think it needs to be quite so big that's a little better yeah so there's lots of ways you can do entity systems and to the best of my knowledge oh wow I didn't draw that right to the best of my knowledge it's really not the case that there is canonical good and bad and you know that there isn't like some holy grail of enemy systems that somebody figured out at some point and if you just do it this way everything works out great I've never really seen that to be the case people have arguments about these sorts of things there's the object-oriented parts of the arguments of things but there's also all these other sorts of things people throw on the term component en Mnet's or entity component system they all these names for stuff but really a lot of it is is pretty underbaked right it's not like this is this isn't you know compiler Theory this isn't something where people have really codified like what an entity system actually is what it does what the different ways to do it are what the complexities of those are like it's an that it's a real like black art kind of a thing and you know like many things just because people like to get into arguments about something or claim that they have a very good way of doing something or somebody says that this is the way to do it and don't do it this way you know people like to have those arguments but only in some cases is there any actual back you know sort of sort of looking for actual theory or proof to back it up a lot of times they're just kind of spouting stuff and these systems are pretty much that way now there has been a lot of different kinds of or ways that people write in these systems obviously there's there's ones that look a lot like a traditional object-oriented program and the way those work is you know there might be some base class right that is just like oh these are you know this is entities just in general and then you know under here you know maybe we've got you know orcs right and then we've got humans or something like this you know and then under here you know we've got things like oh yeah there's you know there's the Prince you know or whatever and then there's the like you know and I don't I don't know what there would be over here oh there's a night for something like that you know there's the different types of things that are in here and over here there's you know there's the necromancer or whatever I don't know why this a necromancer or something like that but anyway you see there's been attempts of doing things this way and in general this style of sort of really really old-school object orientation for stuff pretty much nobody thinks is a good idea anymore as far as I know right like I don't see many people offering this as like a pretty good way to do things and the reason for that is because usually in games there are not rigor like like really rigid categorizations for things usually the units that you create in a game or the entities that you create in a game they borrow from lots of places right so you know it isn't like there's all unique code in Printz all unique code in human and all unique code in entity so prints is just a prince human entity code base and it all just works like usually that's not the case usually there's some stuff for example shared between the necro and the prince right and there's also stuff shared between you know the night and the necro but that the knight and the prince don't share but then there's stuff in the print right and so trying to break things into a class hierarchy often falls apart and so you know again that's separate from you know I rant about obturator partnering all the time you know week that's all separate stuff this is literally like forget whether you're even thinking of joining or not let's just say it doesn't mean they do it that you're just saying I'm going to classify these things hierarchically just that act is kind of fraught with peril and doesn't work out particularly well so what people tend to do nowadays in a lot of circumstances is they sort of dispense with this kind of notion to a large extent and instead they use you know sort of a for like a more compositional approach if you will which is to say okay you know yet maybe if I'm doing object-oriented programming so maybe I'm a during a program and I still do a little bit of C++ or maybe you're someone like John Lowe for example who does things this way who isn't really much of an auditorium programmer doesn't super like it but typically does like to have dispatcher and stuff handled for him and a few other things like this you know maybe you get rid of all that but say we still have we still have one any big class but then everyone else is is just the thing that comes off of that right you know there's a necro the prince and the knight and so on and now what we're gonna do is those things if they share rather than before thinking of it was like Oh a prince and a knight both have certain things that they share because they're human and we'll put that in here right rather than try and do that because it breaks down when then this guy wants to share one little piece of that but doesn't want to share the rest of it or whatever rather than do that what they do is they sort of put these things inside these objects as sort of like components so you can think of it as you know I have my my struct well this is struct necro and maybe it's got an inheritance of entity so maybe it does pull that in and again that's optional if you're not an option area programmer you wouldn't have that if you are you would and then in here you would have some things like oh well my necro uses you know the the burn you know burnable thing and that's like what you need if you're gonna be someone who can catch on fire let's say right and so burnable is in here and and you know if it needs to catch on fire then you can use this or add that to a list or you know whatever you want to do right and so what ends up happening is rather than stuff going into inheritance it goes into containment right it's like I'm Kurd struck in this thing and I put the things that I want for this guy in there okay that's you know been certainly one way another way that's been looked at for these sorts of things yet another way is like the act react model which was something from Looking Glass and this is sort of like it parallels in a lot of ways the AOS versus SOA thing so remember when we talked about an array of structure as versus a structure of arrays and we sort of talked about like oh well okay so a necro like what is that well that's you know like one burnable and and one you know health attribute or whatever you know and so on so it's got these things in it right it has its a has a relationship as you would say if you were in a land right they would do it this way and that's very much like the array of structures method right so when you do things like you can imagine in vertex land we were doing things like okay we've got a struct for our vertex and then we have an some real 32s in here for X Y Z and W right and that we called array of structures because we have an array and each entry in the array is a structure containing the components that we needed right but when we started talking about Cindi programming where you want to operate on all the X's at once all the Y's at once we'll disease it once we you know sort of went into this other way of doing things SOA which was like okay now instead of having like a vertex star for our vertices instead we have a pointer for each of the different types of vertices let's say and maybe we don't actually really quite do it that way but you know what I mean conceptually speaking where we have pointers for each of these right and now all the X's come together all the Y's come together all the Z's come together and so I use a specific index to refer to my particular one I'm talking about what vertex I want but it's in a different array for each element and that's to facilitate processing them you know in bulk well the act react system is very much the analog of that this was introduced by looking glass on theif the dark project and that's a way of basically rotating this concept so that instead of saying I have a struct it's got these things in it instead I say well actually what we have is the burnable table right for everything that's burnable has its burnable there and then i have the health table right and so on and these things get processed individually so the burned stuff does it's burning update the hell stuff does its health update whatever and then if I want to ask what a particular entities state is with respect to whether it's burning or not I look up in this table using it's like entity key whatever its ID is right so it's much more like a sort of multi table database sort of a thing the way that it's sort of conceptualized and again is the implementation deals I'm just trying to give you sort of the broad picture right so there's been lots and lots and lots of ways that people have approached this problem and you can see why it's a tricky problem the reason it's a tricky problem is because you are inherently trying to sort of compress down the information in a very sort of flexible broad space gameplay is a very flexible broad thing you typically want everything to be able to happen everywhere except when you don't right and so it's this very weird mix of like oh I did want that being fire but not if the guy has this thing and oh there should be this rule that if two things are on fire an extra so they should do this and and OH fire effects health and health effects fire right so you kind of have this really crazy space of just it's whatever the human imagination that was designing the game wanted to have happen no matter how crazy and theoretically unsound for any other particular reasons those things maybe that is nonetheless what the game design is and you need to get it working if you would like to ship that game as opposed to some other game so you have this very difficult problem of such a flexible crazy you know not clearly delineated set of operation that it's very very tricky to figure out the right ways of structuring these things cleanly so that you don't have problems okay so let me tell you some very basic problems that you have typically if you do lockdown sort of things in in you know in various ways so for example let's say I was going to do a struct necro this way okay it would be very very fast to process this truck necro for any four any code that was specific to how a necro worked it'd be pretty easy to write that code here because the compiler knows exactly where those things are it doesn't have to get them from anywhere you can just do what it needs to do and it's nice compiled C code you know it's gonna be really fast okay but compare that something like this where every time I want to talk about some aspect of it I gotta go go to a table right so I want to press this necro alright well to press the necro the first thing I do is look up its burnable second thing I'm gonna do is look up its health right there's two queries right there and then maybe I got to do even more who knows how many a file in a you know and you might have ten twenty thirty properties that matter you know it can get there can be a lot of overhead all of a sudden in processing one of these things because I'm doing all these lookups but because it's this general table system where you can just say oh does this entity have any of these things well now it's completely dynamic at runtime as well right like when I say necromancer well maybe it started out as a necromancer but if I wanted to add some property that it didn't have before like maybe I want to add you know ballerina to it or whatever cuz it's got you know or like ballet state which is the state of it's like dainty dancing all of a sudden I can because all I have to do is well we know that if this is something the game understands there'll be a Balor valeria that's good let's cut it again they'll be a ballerina table and wow I can't I can't spell today ballerina there we go there'll be a ballerina table and all I have to do is just create a new record for whatever this person's key is inside that table so I can always just dynamically add properties to any entity and that's obviously very valuable because that adds a lot of flexibility to the game that wouldn't have been there if you had to rigidly define what these trucks are now maybe you don't care right like maybe you're doing a game where that's just not relevant in which case this is not a win but you can see why it might be a win because if you want that flexibility for things to be sort of mutable you have that that sort of need there right so yeah and of course this system already explained the downsides of this systems just you know I don't really think anyone really takes that serious anymore but you know you've got systems like these sorts of things and that's sort of one example of how those might work another way that those might work is you can imagine doing something another sort of transmission on this where it's like okay I don't want to go this route but I do want to have the EULA dynamically add stuff so maybe instead of having these be wrote in here I have like a prop list in here instead and I just add props to this array or whatever it is right so all that stuff is eminently possible there's you know various ways we could store it etc etc so what I thought we would do on a handmade hero because I think this is probably one of the more interesting parts if that makes sense is I think we should just do a new entity system one that as far as I know and no one's ever done before and that way we can sort of see well okay what is it like to create one of these from scratch what are the trade-offs what do we do well and what don't we do well and how did it come out and so you can sort of see that from first principles and I think that would be pretty cool and since it forms the backbone of the entire game experience it's something that's worth spending time on and worth you know being a major part of the development process of handmade hero because it's what will drive everything in the game as far as logic is concerned right okay so I'm gonna introduce this concept and like I said I don't know of anyone ever having done this before doesn't mean no one has a lot of times in development or in programming in general you'll find that just because you do something from scratch and you've never heard of it and even if many people you know haven't heard of it that doesn't mean that someone somewhere hasn't done it maybe they just didn't tell anyone or maybe you just didn't hear about it I'm gonna do something and there are a number of reasons why this is a absolutely crazy idea but I'm gonna do it anyway I'm gonna do something I call the sparse entity system oh wow Franklin what's happened there sparse entity system and what this thing is is it was my way of trying to come up with sort of a different way of looking at entities that preserved all of the speed of how you would write code in C to deal with stuff when you know what you are dealing with but still have all the benefits of having entities that can do anything and become anything in any way right and so this is what I came up with and it's kind of a crazy idea but the only way you know whether idea is truly crazy or not is to try it and see if it works and if it works it wasn't that crazy so here's how it works first I would like to say a little bit about inheritance because there's something about inheritance that I say often and people look at me kind of funny but it's it's like obviously true I think so I don't think it's like contentious I think I just don't often take the time to explain it and it's not the way people maybe think about it normally so I'm just gonna say it here because it bears on what I'm about to say with smarts any system so inheritance is this concept that if you're a C++ programmer you've come to understand as meaning something relatively specific and now it doesn't necessarily mean something quite that specific in the general operating context but either way we can use this as sort of a point something to get the point across and what that is is inheritance is sort of like saying well I've got this struct right and I'm gonna call it foo and in that struct I have an integer X and I know that anytime I've got this integer X that there are some things that I might want to do on that integer X right so I have algorithms that depend on this integer X and maybe to make it a little bit more realistic typically you know we're gonna be bundling something so we have an integer X and then we've got some other thing here which is like a boolean I might as well use my types on s 32x and ab32 which is like you know is it fat is it fatty right is it is it kind of like a bloated thing so I've got these two pieces of information here and then I've written these algorithms right that depend on those two things being together so X and fat are both supposed to be there and then I can write things in CC lets me write things very cleanly in ways that understand this so I can do something like you know make a function called D fatty Phi which takes one of these things in right here's my foo and this D FATA Phi is gonna do something like if you know the foo X is you know less than 10 then we'll just just a state from now on that the fat is is not fat anymore okay now again I know this looks really simple but I really want you to think about what is going on here because it's very very important and it's the cornerstone of understanding a lot of how architecture actually works at a low level okay there is no difference in terms of actual what we are doing theoretically right between writing D fat if I like this and writing D fat off' i in the equivalent way like this okay oops does that make sense now you can see it how it looks there right and on the left side we have something where we pass in a foo and we're going to say if the X in the foo is less than 10 then set the fat in the food to false but the logic and what this function does change is not at all if I were to just pass a pointer to an X and a pointer to a fat right now what has happened when I do this operation when I go from here to here is I've made this function more flexible right because now it can operate on any pair of X and fat instead of having to operate on ones that were right next to each other okay so in a sense this is an optimization of this it's an optimization in two ways first it optimizes our ability to semantically write the program because now it takes us less time if we know that we often have X's and fats occurring together in a meaningful way now we can use that foo everywhere instead which saves us typing and keeps our code more organized and reduces the errors we might make right but it also helps the compiler optimize because now it knows well I can just pass one pointer and know that there's a fixed offset for getting from the food from the X and the fat right and so I can do less work in the resulting machine code to accomplish the same operation okay so this is more cumbersome and slower potentially right it's both of these things potentially then this is and so typically we prefer this even though this is more powerful right it can do more things because instead of I only have to call it with a foo you could do it this way and so this function there'd be times when you have to bundle these things together pass them in and then unbundle them on the way out right it can do the other operations that this can do necessarily without essentially writing all this pre and post amble write very very obvious like I said there's nothing particularly interesting happening here I just wanted to get that out so you can see that right so now inheritance is essentially the same sort of understanding if I am now to say that I would like to inherit from struct foo and I would like to make a struct bar all right then obviously what I could do with really no loss of generality or anything else is I could just make a food pointer here that says well there's a foo right or it better yet I could just contain the flu entirely myself right and then anytime I actually want to use this this foo I just take the address of it right and I pass it through to the person who wants to use it right so I can call all the things that I would have called on bar on the foo and that will just work okay now when I do this I typically presumably want to add some more information here so maybe I add a real 32 here which is like you know swim pee it's half scrimpy the thing is right you know is it particularly swim pee I don't know maybe there's a zero to one number that's a swim penis right so I'm going to add that in here and so now what we're going to do is say well all right if you look at what happens when I try to you know when I try to construct this it starts to become a little bit cumbersome for me because now every time I have to call Dee fat if I on one of these bars I have to take the address of the foo inside it in order to call it right and that's kind of annoying so really all I want the compiler to do here for me it's just could you do that automatically you know that foo is the first thing in there right and so if you knew foo was the first thing you could just go ahead and pass the same pointer because a pointer to a bar and a pointer to foo are the same thing they always have a flue at the top right and so inheritance was just saying oh okay you know well if I have a bar I want to be able to say that it's got a public foo inside of it right that's probably should be lowercase there it's got a foo and then I only define the new things here right and now the compiler knows Oh anytime someone was expecting one of these I can just pass you know it regularly and it'll just work so it's all good okay and the reason that happened is because we preserved the condition that we needed to do the optimization just like here we know the relative offsets of things from the base pointer so everything can just be compiled with that knowledge in place right there's no difference we could have just stuck with this and every time we want to call D phat affiance something passed those pointers to the actual internal parts that we care about but it's just semantically much more much easier to use the inheritance way right and it's faster using this way because we know where everything is and that is why of course the base inheritance mechanism in C++ is so rigid and is so you might say underpowered compared to the inheritance mechanisms in other arbitrary to program Ed's for example it's because it was trying to retain this fast property of knowing where everything was relative to the base pointer so now let's look at precisely why this starts to fall apart and what it was actually doing when it fell apart or what it was trying to preserve when it fell apart that maybe we don't know preserve well I don't want a spoiler warning it too much on it looses say let me show you some more things all right so here are my structures I was talking about typically what happens now is when we start talking about this in the more realistic context you can start to see why inheritance begins to break down a little bit in the cases that we wanted to talk about above where we were talking about oh we've got burner bulls we've got health we've got those sorts of things so now if I want to start talking about something and I wanted to create one of these structs right like let's say I wanted to create one of those necros like I was talking about well now I want to do some inheritance here and I want to say it's I want to use it with things that expect you know a health thing there right and I also want to be able to use it with something that that supports you know a burnable right and and there's all these things I might want to inherit from okay because I my way of saying that I use functionality comes from inheritance okay I want to be able to grab all the functionality that I want well this obviously starts to break down very quickly and it's why you know this is the multiple inheritance case right that's very terrifying to C++ programmers because it's so wacky but you can do it multiple inheritance is very problematic because now you can no longer use the trick that si was using we can't just say well I want to be able to pass this thing around to any function that expected one of the things that it it like kind of does it kind of looks like right it's a healable thing it's a burnable thing it's a whatever thing I can't keep using that trick because the trick I used was to put it first but only one thing can come first right and so now a pointer to a necro is no longer also a pointer to a health and a pointer to a burnable and a pointer to everything else because only one of those is actually going to be first so yes passing it to a health a thing that affects health that may work because that's the first thing let's say but passing it to a burnable that won't work the pointer has to be adjusted because the burnable is in a different place relative to that top necro pointer so when pointers get passed they have to be readjusted right and so now things start to break down and it starts to be a little more cumbersome but you can do it right you could still do it and you could lean on the multiple inheritance system and try to make that work believe me people have done it but now we get to the final problem and the one that's obviously just never works in C++ and that is if we wanted to make this dynamic if I built my whole code base around C++ as multiple inheritance and now I want to say oh you know what I created a necro he was running around and then he had the spell cast on him that gives him this extra property that normally doesn't have right uh what do I do I I can't add new inherited things to a C++ struct at runtime right that's not a capability that the language allows and for a good reason the language is a compile-time language the inheritance is compile-time oriented all of these things with the offsets and the pointer fix ups that I just talked about which have gotten much more complicated with the multiple inheritance all get baked into the code so now it's it's an answer I literally can't just choose what things I want to add to it and expect those to work and furthermore it wouldn't even make sense because where in the code would it ever be called there's there's so many reasons why that doesn't really work right so now comes the part about inheritance that I want to say that people don't usually understand when I say it but I'm so I'm gonna say it here what I normally say is inheritance is compression it's a compression algorithm and that's it that's all inheritance it's it's strictly a compression algorithm it doesn't do anything else and let me tell you what I mean by that let's say that I was to take every possible thing that could ever be contained in an entity right so let's say I've got all these properties right and I don't know how many there are let's say there's there's 200 of them okay let's say I was to take those and just actually put them all in one big struct right just they're all in there so I just have a giant struct and instead of anything to instead of trying to be clever here I was just to say okay I just have one giant struct and inside the struct is every last property that there is all of them right so here's you know the what did I have I had an S 32 that was my X component I had to be 32 for the fat I had that our 32 for the was ask wimpiness I had the squid penis right so I had all of these things in here down down down atomic everything that could possibly occur in an entity was all in there in fact much like what we have going on in here where I just said let's just stuff it in there and not care about it for now it's just anything that anyone ever wanted is sitting there it's giant right it's like a 64k structure or something it's just huge well if I had that that could be the thing that I pass to any function because any whatever the function was whatever it was gonna do it'll work the stuff it's looking for is there and furthermore it's much more powerful than any of these because it can actually operate across different any two pieces or more if it wants to grab something from the health and something from the burnable I don't need to make a health burnable class that's a thing that has member functions for those in or any of the other things I don't need to do any of that I can just say hey go look at the health and go look at the burnable there alright in this big struct right so what you're doing when you create an inheritance hierarchy in an object-oriented programming language is you're just compressing things that's all you're doing you're doing compression on the Struck's that you have by saying instead of putting everything into one giant struct I'm gonna take just the sub configurations that I believe actually ever get used in the program that I need to actually talk about I'm gonna take just those and make those out of the inheritance hierarchy right so hey stuff there are some things that have an X of fat in ask Wimpy so that's why we had a foo in a bar underneath it right and there's other people who need just ask wimpy so we made one of those but there's never somebody who needs a you know I don't know like carrot top and ask wimpy so that never occurred together and we just don't have that right so essentially if you imagine all of the data right so if you imagine this is all the data that could possibly occur and maybe we could even we could even take this into the theoretical realm and just say even if that means it is infinite meaning it doesn't even matter how big it is every possible configuration of stuff that could occur we've made it so that it can all coexist together in a giant struct if we took that and we specialized it by just picking out the ones the combinations we actually ever use that is what an inheritance hierarchy is doing right to the data now we can talk about dispatches separate and dispatch is just a function the glorified function pointer so hopefully there's going to be too much talk about that but that's what we're actually doing to the data so data wise inheritance is just a compression algorithm it lets you not store a ton of stuff you don't need that is it right now this is where the sort of object oriented programming lunacy comes in because a lot of people would be like well you know it's it's it's good programming to like high data that isn't necessary from other functions mostly like okay if that's your thing you know go away I don't want to hear from you like go have your weird party over in la-la land assuming that you actually care about what the CPU is actually doing at the end of the day this the thing that inheritance actually was gonna do for you was it was going to make it so that you aren't storing data that you don't actually need to store which isn't necessarily a waste of time right that's important again for cash concerns and all this stuff even if we don't care because we have plenty of actual memory which we don't always have either you know we care about the footprint of things and that is what inheritance lets us do but it comes at that very specific drawback of having a very hard time mixing things in very ways because we have to pre declare all the different mixed kinds that we might want rather than just letting them happen organically at runtime we have to care about that right and now opportunity to program programming languages that are dynamic and that aren't like C++ in that compile time way they obviously take a speed hit but they get around this problem by saying well we'll still keep the idea of having that sort of inheritance kind of crazy thing but now we'll just let you decide who derive from it run time or do other things like that that get around that problem of having to decide everything at the outset right okay so my idea for this ridiculous enemy system that's the one that I the third of the architecture I want to try first is to do exactly this so what I want to do is I want to make a struct entity and this struct is going to be epically huge okay it is going to have everything in it like so 64 K think yeah it is a 64 K entity struct maybe more okay it is really really really really large epically huge that's actually gonna be what it is and what we're gonna do is we're just gonna say alright look we know that we can't possibly have every entity in the game taking up 64 K all the time and furthermore we don't really want to process 64 K worth of any data all the time but we already know that the structure of our game involves sim regions we simulate a region where we load everything up and then we simulate it and we put it all back right that's already how it works so that we can pull things into a common unified euclidean space do some stuff and then put it back right so my idea is well let's make a thing that has everything in it that's the over entity it's a has all the possible properties it has everything it's the most ridiculous think you know binding of issac after 17 hours and it's got all this crazy stuff on it can do everything it's it's everything that everything could possibly be that is what this is and what we do is when we go to start simulating we do a decompress to get this entity structure and then we do a compress when we're done so what happens is we decompress out of a storage basically our - like cold storage if you will into our MV structure we then compress the energy structure back out when we go to store it and what this will be is we've got this sort of you know we've got this these world chunks and what this will be is essentially a streaming system well swim a bunch of entities and then we'll go which entities fall into this you know we're writing them out to a world chunk we open up the world chunk we write out all the entities by compressing them in okay and then that world chunk is closed and it's stored right when we then want to simulate that world chunk we open it back up again and we decompress them out okay now what do I mean by compress and decompress well I don't mean try to run like LZ on them or anything although maybe that's a smarter way to do it than what I'm thinking I don't even really know it could be that that's actually quite a good idea for all I know like some kind of simple compressor and we'll see when we start testing things what I mean is more like and the reason I called it sparse mate as far as entity is because I'm thinking more like a sparse matrix solver so basically this entity has a bunch you know maybe it's got you know a thousand things in it right a thousand properties or something well what I want to do is basically just mark off which one of them's which ones of them we decompressed and then when we simulate the end of the we mark any ones that we've added and we D mark ones that we remove and then when we compress we only look through we only grab those ones that are actually there make sense now you may be asking why do this right why try this it sounds like it's strictly worse than just keeping a list of property sort of like this sort of a system up here that I talked about right here why not just put those things into a list and forgo this whole sort of operation well the reason is because now all of the simulation code right the simulation code that's going to access this all of this simulation code just gets written in straight C style where it knows the offsets of everything it can be written at full speed it doesn't have to do any lookups it's based and it has free rein to do whatever it wants any single piece of simulation code can pull it doesn't have to go oh does it have a health property doesn't have a burnable property okay well if it adds both of those properties it doesn't do any of that stuff it can just ask directly by literally looking up into the thing and just grabbing out what it is right that's the idea and again this mirror is basically what a sparse matrix solver does as far as matrix solver says well I've got this big array potentially in in memory of what this matrix is and I may actually store the whole matrix right like I may say that I actually have like memory reserve for let's say 64,000 entries this way and 64,000 entries this way right but I actually only go poke in certain values and I remember where those values actually were and then later when I want to store this matrix out again I just grab out just the ones that I know that I put in there right but because I've done that anybody who wants to do something like oh what's my symmetric element can still just do a direct look up on the - you know the M and n you know the tooth on J indices of this matrix can still do direct lookups and get exactly the value right back out again right so everything still full speed when you're looking at the matrix itself but when you unpack and pack it you're only looking at those specific cherry-pick values right so that's the idea and so that's what I would like to play with I would like to make a little thing we'll go take our world chunks will actually make them some storage will have a decompress step and an entity structure and then will have a compressed step and will have it so that there's just a giant entity thing that has every last thing we want our enemies to have and that way there are no limitations on what an entity can be if you have a tree and you want to start walking around no problem if somebody casts the walking thing on it it just becomes a walking tree because anything that you could have done like walking or hopping or shooting or punching or jumping or anything else they're all just properties of the same entity and you know that they all you know operate on the same strike so it's always free to just go ahead and turn on whatever the thing is that you want on any entity ever anywhere right which basically gives us the complete flexibility to have the game design do whatever it wants right and I think that is really the goal of this particular part of the of the game so that's what I'm gonna try and I can't say ahead of time whether it will work because I've never tried it before I can't think of any immediate reason why it might not work I mean why it wouldn't work but I can't think of reasons why it might not work for example the traffic for this decompressed compress might be too great right the memory footprint for storing you know however many 500 of these might be too big right maybe that's too much I don't know that cache concerns are really such a big deal they might be I'm not sure but since we're only touching it sparsely it's not like we're ever actually touching the 64k unless we actually need to use all of it there is a some false sharing problems because you know things are not packed tightly so we do lose some cache throughput but not as much as not nearly much as you might think because again we're not touching the whole city for K or anything so it's hard to say so there definitely are reasons why I think it might not work but nothing that's an obvious red flag where I'm like it's I wouldn't try it and so we will try it that's about it for today I'm glad I got that all explained I wasn't necessary planning on explaining that today but now I did means we can start on tomorrow which is nice I will see if I can go ahead and start the Q&A here xD a FAL can you talk about the dynamic dispatch yes I can certainly talk about the dynamic dispatch so so what are we what are we trying to trying to find the place Rev run's okay so what are we trying to do with dispatch okay so hopefully data data is the part I actually cared about and this the part that's relevant to the suggestion so I skipped dispatch but I'll talk about dispatch briefly see what dispatch is is saying okay I want a way to associate a function with a memory location that is essentially what dispatch is right because normally what happens is the other way around I call a function and I pass it some data this is a case where I have some data and I want it to tell me the function right that's that's sort of what we're talking about here so the typical case right is you know going back to our foods and bars if I have a struct foo and I have a struct bar then it's very simple for me obviously to write some code and that code looks like you know do foo and it takes a foo and does something and then I have a function that's called a do bar and that takes to something right probably make that it be so we call these in code and anywhere at the point where we're gonna call it it's a fixed thing right it's like at the point where we might call one of these we know which one we're calling we're calling do foo or do bar and we're passing it a foo or a bar right but at some point we may want to say okay instead of me telling you at this location in the call write it so I'm at some point in the program I call my do foo at that point in the code maybe I don't want to know which function I'm actually calling I know I want to call a claw family of functions I know I want to call the do family right I want to do something but what I want to do is going to be based on the the memory location I'm talking about so if this memory location happens to exist over here that I want to do one thing if it's this other one over here I want to do this other thing etc and so forth right and so what I will do right if I'm writing this myself is I will just add a function pointer okay and so what I might do and I can even say that this I don't even need bar for this part of this example if I can just say okay in here there's some function pointer and the function pointer is whatever the do is for this foo and so now I can just say oh all right if I have a foo I can psych foo arrow do and I can pass itself to it and off I go right what this has now let me do is this has let me associate a function with a particular block of memory so this this storage the actual data now also has information about how it might be processed under certain circumstances right and you've seen us do this in a couple different places in hand-made here are actually well may or not a couple but at least two maybe that's a couple and so you know once in a while you do want this it's not that it's not as common in fear a new plan that's all over the place right but it's not that common really in real code it's not super important but there are times when it is necessary right or or it is appropriate so that's what this is let me do now obviously I may want to do something where now I've got two different types okay they have different information in them this one has an r32 right here's my value this one has a be 32 and here's my value and so I want to now not even know which one of these two I'm talking about right well now I can actually still use this because even if the thing was a bar and I thought it was a foo it doesn't matter because it's the first element in the structure I'll still call the do and if the do happens to be a function here that takes a bar where little call the right function and don't think it's a bar and do the right thing so I can actually I don't really have to do very much to make this work if I wanted to but you know you get the idea okay so basically at this point once I settle on the standard of I'm gonna put the function pointer at the top of the thing then what I need to process it I just call that function pointer now it's free for me to create as many of these as I want with all sorts of different data in them and anybody who needs to invoke do on them can do so trivially because all they do is look at the first thing in it and they invoke that on it and off they go right and if they don't have to ever care what type they were actually handed they know how to call that that thing right okay so that's dynamic dispatch in the basic sense now C++ for reasons that nobody understands right and I have no idea why I wish I could go back in time and or maybe ask somebody be like what were you thinking they picked the worst possible way to implement this that I think anyone probably ever has I mean maybe you could find a language that implemented it worse than this I don't know but what they decided as well okay this is a sort of thing that programmers will do programmers often will create function pointers and they'll put function pointers into two structures so that when they are going to use that structure they can call the function pointer now remember there are many many different things we could have done here right and I'd like to tell you what they all are first of all just just so you can be aware of exactly how bad C++ this implementation of it is and this again has nothing to do with object-oriented programming this is literally a problem with C++ specifically and that is several things I could have one structure right or I can have two structures they can have one pointer or they could have two right and maybe this guy has them as well okay so we can have multiple structures we can have multiple functions in the structures that we might call write multiple met you you know these are like methods in C++ or whatever or member functions I should say right could have multiple of those there's many things that we might do what C++ decided was the only one you were ever going to get to do because for some reason they just couldn't conceive that there were others or they didn't know or they had never programmed a computer before I don't know they decided that you only got one of these and what it was was you could have a bunch of functions in a static table right it's a table somewhere off in the distance and the only thing you get is at the top of a thing you get a pointer to one of these tables that's it now in doing that they gave up a tremendous amount of functionality oh and by the way you don't ever get to see this pointer can't change it it's not there as far as you know now in choosing to implement it that way they basically lost almost all of the power of dynamic dispatch the actual dynamic dispatch support you get in C++ is the weakest possible dynamic dispatch you could ever imagine right you cannot change anything about it at runtime at all right so for example if I wanted to when I have this old way what if I implement it by hand I can set due to whatever I want whenever I want I want to change this particular one I could change it right make sense so any given object can change what it's due function was at any time dynamically that is a great feature gone completely gone in C++ forget it can't add that right I can furthermore change things independently right so I could say oh I want to change its other pointer but not its due pointer so I'm going to change only one of his member functions rather than both of them for example that's double gone because everything's in a table in the C++ version so I can't do that either right you can't touch the table pointer and furthermore if I did want to implement it this way so let's say I did a flip teal pointer but at least I put the table pointer in there then I could at least switch the type of the object between tables at runtime I can even do that right technically I can by going around the C++ spec and not worrying about breaking stuff because I could just go in and rewrite the table pointer manually but technically to the original spec of C++ when they designed it back in the day in the 80s or whenever you can't do any of those things so you lose all of the power of dynamic dispatch completely goes away in C++ you get the weakest possible kind right and again what did it see it seems like what they cared about which is not probably what they were cognitively thinking but it ended up being that compression is really the only thing they got this is the most compressed way this could possibly work really is having the table pointer point to a static table because then any two instances of an object don't need to have a whole table of function pointers they each just point to that table however all the things you give up for that are myriad right it's slower because you got a double dereference everything whatever you're gonna jump it's less flexible because you can't set it per object if you want to right and furthermore they made the weird decision of not letting you ever touch that table pointer which is absolutely ridiculous right now if you don't want to expose the table pointer directly okay that's one thing but at least give us some built-in functions that can switch like what's in the table or what the tail is pointing to like that would be pretty obviously right that you would do and they didn't even do that right so the C++ dynamic dispatch is a complete complete complete waste really really bad I don't know why anyone ever uses it but it's for some reason they still do so if you actually want dynamic dispatch I highly recommend doing it this way meaning I would just make it yourself because it's so much more powerful you can do so many more things with it that I don't know what that this simple syntactic sugar of not having to actually put the function pointer in there doesn't seem to me to be enough of a reason to give it up but you know I don't know different people I guess have different preferences but so the dynamic dispatch that they are talking about is literally just the kind that can be derived from one of these hierarchies and that is the like sort of baked at that compile time but that is not really very useful dynamic dispatch in my mind dynamic dispatch is much better handled by saying what is my program actually need from this dispatch what matches that most directly for example maybe I have only one type of strap maybe I don't even have multiple types of trucks but I do have multiple types of operations well then I want dynamic dispatch just like a function pointer in there right or a couple function pairs in there maybe I do have lots of different types and maybe they all have the same kind of dispatches between them so I'm going to use that like a table based method but I'd like to be able to switch them at runtime because sometimes I want this object to have these sorts of just practices sometimes I want to have these other types of just answers right then I'm going to use that table pointer scheme right Ambala and only if you're actually talking about a completely immutable table based you know system that operates on a hierarchy would you ever use C++ is dispatch which is never I don't know when you use that you don't as far as I know so yeah in our system we are not going to use dynamic dispatch probably at all and here's why the reason that I don't probably want to use much dynamic dispatch is because entities in our system again I'm going for that really rich bizarreness kind of an entity system I don't ever want to define what an entity is I don't want to say this entity is the hero this entity is this type of villain what I want to do is say this entity has this set of parameters strewn throughout the 64k thing and when I render it I draw from those parameters to come up with this visual representation but at no time do I actually want to know what it is because if at any time I lock it down and say this is this subclass of this thing with this pointer to this function suddenly I've lost the ability to have that fluid weird like mutability and I'm just I'm going for mutability first in this one I want everything to be miscible I want every ending the game to be able to turn into any other type of entity I want every property we ever glommed on every other property I just want to be the complete most flexible thing possible and I'm willing to give up other things I'm willing to for the code to be harder to write I'm willing for it to be difficult to debug I'm willing for it to be slow if it has to be I will optimize those things and work those things if I can get that sort of holy grail of everything is super weird and dynamic and unchangeable right so I want to try and do the system that way and so you know maybe there are some cases where function pointers make some sense there but I think more likely what we'll be using is a lot of enums and then to figure out what we're gonna do we'll look at a couple different enums and say oh you know what type of walking does this entity do oh it's this and like what type of this is do okay grab those together and then say oh they're not probably you know I should draw some legs on here or maybe I should do this right and so I want to kind of make it so that it can look at multiple things where as a function pointer you don't usually test function parsers I mean as you could but it's more like I want to take multiple piece of information and use that to synthesize who we call and so that's going to be more logic based and probably less function point based popcorn do you use the struct entry method in your current game my current game does not have any entities kind of scroll down to the cue Collins SSS McGrath have you seen my pseudo hacked discriminated Union inheritance system that I use in my game on stream it's pretty cool no I haven't but I like discriminated unions as you can tell from the fact that like 99% of the things in handmade here are discriminated unions so I'm probably in favor of whatever it is you're doing but I don't know what it is at the moment but I would probably like it I guess is what I'm saying what made you choose this approach over an AO s style Plus story indices of each separate component in the main entity struct okay so basically the reason that I didn't want to do that is because I want all of the code to have hardwired offsets like I want it to just be straight C code fully optimizable by the compiler to just go in and grab what it needs and do its stuff on a flat piece of memory always if that makes sense Juden basement I missed it what about the matrix IJ I was confused there so what I was saying there is that it's essentially like if you think of how matrix operations work a lot of times matrix operations need to look at particular elements like what's one above me or what's my reflected element in this matrix right and if you have sparse storage for your matrix that just says where those things are then either you have to constantly do lookups in there or you have to scan one or the other and they're both very slow so instead sometimes what you would do in the old days and this is less true potentially now but what you do in the old days is you would just say oh I'll just make a big block of memory and I'll put things in there and I'll basically like initialize it all to zero once and then all the operations I do I'll just put things in there and then remember to take them back out again when I'm done so that I can always do direct lookups right it's kind of like a perfect hash table for the matrix entries in that sense parsnip how and where would you go about checking if a property existed on your mega struct whenever you want to do your operations with the allbeing they'll present undefined so there's none of them are pointers it's actually the data for the property so the whole all the data is actually in there and they're all just initialized to there this thing isn't happening State so if it's like how on fire am i it's zero right and so then when you go to to ask how much fire is there you always get back the answer whether it's on fire or not it's got a value in there that says that that makes sense tea Terrace what are you going to use to track which strecht members have been touched / setback - no to be honest I'm not sure yet I need to do some testing probably during development depending on the speed of it I may not meaning I may just always actually scan so you just actually walk the full 64k which is going to be slow right or I mean I don't know it's gonna be slow because who computers are so fast these days it's going to be slower than it would be and then when we sort of get further down and we're worried about potentially optimizing things then I will think about based on what we have how I want to go about making it so that we track Jesse Meyer what portions of this design could you foresee causing pur issues well like I said the fall sharing is probably the single biggest concern and what I mean by that is you know if if well let's tart with this so basically you can think of a struct as being broken up into 64 byte chunks okay so here is my struct entity and then we start listing the members in here and I'm just gonna make stuff up but let's say I've got you know a v3 position right and I've got an r32 alpha I don't know why right and an r32 you know movement T or whatever and as you start to add these up right you start to get a sense of how big they are right this is four bytes this is three times four bytes right so that's 16 bytes right there and so then you know you could imagine if this is 16 bytes here imagine some other blocks here here's another 16 and maybe here's 32 bytes so here's a 64 byte chunk okay and then after that's another 64 byte chunk maybe there's I don't know why there's a there's a name field here that's 16 bytes long I don't know why we would have that but we do all of a sudden and then we have like a bitmap ID and that's more so we just have imagine just lots of 64 byte chunks okay that is how the cache to a first approximation sees this entity right now there's all sorts of things like aliasing and all there there's a whole host of issues that are like super complicated crazy things but to a first approximation if you want to know how cache friendly this entity is that's what you're thinking about inside every block of 64 bytes if we are to touch one of these during processing we have to bring all 64 bytes into the cache right so if I want just the T value and that's all I use in this particular entity none of these other things are valid now why that would be I have no idea cuz I was in peas gonna be Valhalla but pretend that was true right all I wanted to touch was this T well that's four bites but I actually had to touch sixty extra bites that I didn't use so what that means is depending on how our structures organized and depending on how the sparseness works out in depending depending depending we could have a lot of extra memory bandwidth getting used that is not actually doing anything right it's wasted and so it's a gamble right you don't know maybe that's okay because most of the time you are able to pack things well that they happen to work out so you don't waste too much memory maybe it's horrific and you're oftentimes getting into this sort of nightmare scenario it's really hard to say and so that's certainly one huge reason why I don't think it's a slam-dunk of an idea by any stretch of the imagination because it's like well there's a pretty clear reason why you know this could be bad fortunately it's the kind of could be bad thing that is not super dangerous because entity processing in this way you know how many entities are there going to be well there's not going to be a hundred thousand entities on the screen and this is processing for the things that we actually see and immediately around it right so we don't have to worry about a processing a hundred thousand entities at 60 frames a second right but we probably have to worry about processing like 300 entities at 60 frames a second maybe right or at least 30 frames a second so you know it's still it's it's not so few you know there are certain games that have so you know let's say it was Street Fighter right well there's like two you know maybe miles morning to but you know how many eighties are there really gonna be 10 20 not very many so you wouldn't care it would not matter but you know as that number gets up to a couple hundred or even if it's a thousand right you're starting to get a little nervous because now it's like well if I blow half two thirds of my memory bandwidth they're pulling these things in that's kind of uncomfortable potentially right so I don't know so we'll see we'll see I don't think it's dangerous enough that I don't want to try it but it's definitely not safe enough that I'm happened that I'm comfortable saying oh it won't be any problem don't worry about it like we won't have to worry at all be great you know it's two kids could still go wrong Connor rents what are some alternatives to an entity system well there is really no alternative to an entity system if the game has entities in a sense that no matter how non system E it is you still have one I mean you know if you went back to maybe pac-man or something like this then you could say well there's no any system right there's just some specific code where you know you've got an array of like four ghosts and you are gonna do a third thing to each one of them and each ghost that certain thing you can still call that an ende system right and it has two types ghosts and pac-man or whatever right or you know those sorts of things so you know I mean any action game like that has an entity system because it is inherently about a bunch of discrete things that you know shoot at each other or touch each other and do something and so pretty much the basis of any traditional action game in that sense is going to be an entity system now if you're doing something else right you know maybe you're doing something like a walking simulator where nothing happens right it's called nothing happens the game which there are a lot of on steam maybe you don't need one because maybe the it's about something else and so really there's just a huge static world and you don't ever have this notion of entities that's not a thing right or maybe you're making a game like we are 1935 at Mali rocket it's you know it looks and plays kind of like a movie and your interaction is about interacting with a dialogue well entities aren't a thing anymore right it's not an there's no nobodies we don't do collision detection to find out if two entities interacted with each other right like none of that is happening it's about you know a very different thing so you can see why that would be presumably well that would be presumably not necessary in certain titles Allen Webster are you already thinking of a back-up plan for the entities and how you would transition to that system if you had to know because you know typically speaking whatever we write if there is a problem with it we will see that problem occur and have a measure of it like if it's the cash problem or if it's something else and what the problem is and where it's occurring will presumably drive our solution in how we will modify the system to avoid that right so you know it's like I said it's not we're not going for super high throughput here this game is not about processing as many and as easy as possible so I'm not really that worried that we wouldn't be able to solve it at all with something in the ballpark of this right but what it will exactly look like by the end I don't know because I just don't know exactly how some of those trade-offs will play out so alright looks like we're done um do I play Street Fighter who is your favorite character uh no I do not play play Street Fighter I was always a Mortal Kombat guy I really liked Mortal Kombat 1 I've never liked any of the subsequent Mortal Kombat's although I only played two and three or something I never played any beyond that so I don't know but I really really liked the original Mortal Kombat I never really liked the original Street Fighter or Street Fighter 2 or any of the subsequent follow-ons you know what kind it's what it is really is I don't like animation pause I can't handle it I can't handle animation pause you know when like when like somebody like uppercut somebody and it freezes and then it continues having that in a fighting game ruins bunningham I can't play it so it was always a bit of a rough thing for me and I just didn't like the feel of Street Fighter for whatever reason so I couldn't get couldn't get into it which is too bad because that was the more popular one so we used to play at the arcades I used to like playing you know versus other people and I used to play against other people in world comment one all the time but there just weren't enough people it was very easy in my hometown and surrounding areas to be the best person at Mortal Kombat 1 let me tell you that right now whereas it probably would not have been as easy to be the best Street Fighter I'm guessing because more people would would have been playing that well the enemy system include things such as particle effects no part of the VEX are a graphical effect that typically get launched so the enemy system would spawn particle effects but it's not going to process them because they're very specialized and designed for very high throughput and they typically don't have on they don't have mutable property that's like okay if this is a thing that like spawned some fire then the fire just particle spawn up it doesn't like those don't change to water in like of their own accord somebody like reaches in from somewhere else and makes that change right do you play bomberman these are not on topic people you can't stand this sweet fritter pause but you like the Myrtle count Rose cape no I didn't like the Mortal Kombat rotoscope either well first of all snot rotoscope it's just it's actually just video but I like the fact that it doesn't pause right because that affects the feel the look is a separate from the feel right and I didn't I don't like the look of either game I think both games are not good looking really but if I had to pick one obviously streetfighters better looking the Mortal Kombat I think certainly but I don't really like the look of either but I like the feel of Mortal Kombat better because it doesn't have that pause I could never get past that pause drove me nuts so yeah oh and as far as I'm just grabbing a thing I know this wasn't a question but someone was saying it does seem unlikely that you get 300 undies meaning 60 frames a second simulation and you know it's yes and no because again the whole world in this game is kind of made out of entities in some sense like each ground element will be an entity so you know if there's you know let's say that we're doing a 17 by 9 tile well there's gonna be something like you know if there's two entities on every tile the tile itself and then something standing on it well that's three hundred and six entities right there right and maybe they've each got a bullet so you know I could see 600 entities being a reasonable entity load for this game and I wouldn't want to necessarily say that we shouldn't have that many that that's too many so I would say like you know I will probably want to stress test this with a thousand IVs at 60 frames a second so you know if we're talking about oops if we're talking about 60,000 entities or something like that then doing the back of the envelope like three times a thousand times a thousand times a thousand so if let's say it's a three gigahertz machine or something and I want 60 frames a second and I want to have 600 or sorry a thousand of these you know that's not very many cycles right that's just not that many cycles now thankfully I've got multiple cores to play with potentially but still it's just it's it's you know it's it's something to be nervous about I guess it's what I would say since this is GPU accelerated you know we don't have a lot of work to do graphics wise so that's good but 50,000 cycles per entity is is not a it's not a abundance right it's not like so much that you'd never be worried about anything going wrong in it so you know it's it's you know yeah we'll see well we'll see what happens all right so my understanding is I don't actually have to do anything here because this actually just saves itself which is kind of awesome so I'm gonna go ahead and close these guys down and see here thank you everyone for joining me for another episode of hand made here it's been a pleasure coding with you as always if you would like to follow along with the series at home you can always pre-order it on handmade hero org using this handy dandy button and it comes to source code so you can play around with it yourself we also have a forum site you can go to if you want to ask questions we have a patreon page you can use if you want to support video series and we have a schedule bot which will announce the schedule so that if you're trying to get the series live you know what it is finally we have a episode guide if you're trying to catch up with videos in this series from the past that is a great place to go and and check those out that is about it that that is that is it for today I will be back here tomorrow 5:00 p.m. Pacific Daylight Time and we'll start taking a look probably at implementing the entity system exactly the way that I just said it and seeing how that starts to to shake out that's it for me have fun programming everyone and I'll see you guys on the Internet
Info
Channel: Molly Rocket
Views: 29,283
Rating: undefined out of 5
Keywords: Handmade Hero
Id: wqpxe-s9xyw
Channel Id: undefined
Length: 89min 0sec (5340 seconds)
Published: Thu May 05 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.