 Hello everybody and welcome back to another C++ SDL programming tutorial in the last tutorial We built a we built a pretty simple class Just a sprite class that will display kind of an image on the screen an SDL surface on the screen force. It keeps track of Properties like X and Y values because of its its rectangle and we built the functions to be able to draw and update with it So we have a pretty basic framework for a sprite system in any games that we make I'll show you how it works when we actually run it once we've compiled it I can just bring over the the program that runs you right now We just have a sprite with an origin in the center centered at the center of the screen obviously so cool very very cool Now we have to get into the question though as to what will happen when we have multiple sprites how do we keep track of them all how do we be able to draw each one on the screen where it needs to be and Maybe even determine which sprite is in front of what and that sort of thing so What this actually breaks down to is is a new concept and even eventually a new class that we have to create called a Sprite group now I was telling you guys in the last video in the in the last tutorial that I have been basing a lot of the Ideas in the code in the logic flow for this series off of the ideas in the logic flow and stuff off of pi game and My pi game python programming tutorial series, so Pi game has in its sprite little submodule it has a sprite group Along with a sprite class, so the sprite up here has functions update and And and draw it doesn't actually have draw but we put it in in our in our sprites So we can be able to work with it actually that sprite in particular in our code So it has add this will add it to groups. It has removed it will remove it from groups and Kill and alive also have to do with groups. Oh And look it even says the base class for visible game sprites drive classes want to override the sprite that update function Which is a guy through what we did in our code. We had that we had that update function that can definitely be derived and Changed, okay And just uses the same sprite that image and sprite that wrecked attributes that we set up. Okay Next we'll move into the group actually I remember I was telling you sprite groups this container is a class that holds and manages multiple sprite objects So we want to go ahead and kind of copy this copy this idea copy this framework It has a list of the sprites It's using copy function add function and all these things that will remove sprites and add sprites and that sort of thing So we need to be able to contain and hold and manage multiple sprite objects now I'm sure you're thinking okay. Well, we do this with a list, right a list of multiple values and variables that we can keep track of and In C++ you've got a list, right? You've got the array but that doesn't really You can't change the value as you go along. You can't change the length of the array We have to use a vector We have to use a standard template library vector that will be able to dynamically change as we add more and more things to the list and to the Container so what we have to do over at the top of our code here We have to include and use our less than a girl in symbols to denote We're using something from the standard time at library. We want to include vector now I'll hop it over back to the internet and look up C++ vector Just so we have the documentation ready and active for us Vectors are sequence containers representing arrays that can change in size. So it's got a lot of good Values properties members functions and stuff that we'll be using throughout the rest of the the series Not so much the series, but at least a tutorial today and right now Okay, enough of me blabbering. Let's actually write some code. We want a new class We want this class to be called the sprite group Have our code block and here and of course we want the private and public data type variables Okay Just like I told you we want to use a vector since we've included that we can use it Oh, actually, I should save a new file 0 6 0 7 a sprites sprite group Okay, cool. Sorry just had to save over that lost my train of thought we are using vectors So that's what we want to use here. Remember, we are using namespace standard So we don't have to include standard colon colon for the C++ scope operator we can just type in vector and Remember this uses the less than and greater than symbols to denote the type that we want to use and of course We're going to be holding lots of sprite objects Now here's why I have to bring up an interesting point normally At least like here's an example if you were to pass Any information into a function, right? If you pass a value into the function if you pass a variable into a function it passes in a copy of that Variable and that value now this makes sense, right? Because if you change if you change the value of the variable inside the function if you go out of the function You access that same variable It's not going to have the the value that you set in the function because of scope right unless you're using a Global variable and changing the function you're not going to have the same results as what you've been using in the function So this is kind of similar with vectors We when we pass in when we add a sprite object to the vector We're not actually really passing in that object itself We're giving the vector a copy of the sprite object But we don't want to do that Because if we're going to be using this sprite group to draw multiple sprites at the same time if we're going to be Using this to update multiple sprites at the same time to move even multiple sprites at the same time Well, we need we actually need The object itself we need the real legitimate object that we've been trying to keep track of So we actually need the legitimate object and the way that we receive it The way that we access it is by accessing these variables in memory So we have to use pointers and that was a big long spiel Just for me to say that yeah, we need the freaking asterisk right here It's a vector that is full of pointers to sprite objects So that we can actually access the sprite object itself rather than a copy of it So this vector this this data type this this variable anyway I'm just going to call mine sprites. You can call it whatever you'd like You can call it sprite group sprite list It doesn't really matter and I'm just going to keep track of the sprite size in a in its own separate Variable this way we don't have to repeatedly Look for the sprite size by accessing the function of the vector because you know this this function has it In the vector documentation the object of a vector itself will return its size Just with this dot size function But I'm gonna keep that in a in a variable just so we don't have to keep calling it back and forth because we have a Lot of functions. We actually are going to loop through everything in this in this group in the vector Okay, now if we hop on back over to the pie game kind of listier Sprites is a list of sprites that the group contains so the way that we actually really kind of set that up is by creating a new function and that new function is going to be called in our case get sprites What this does is it's going to return the vector So we actually need the the same type that we had right up here vector sprite with that that that pointer vector sprite get sprites and This is very very simple. All it does is it return Returns the sprites the variable that we've been working with all along Next we have sprite dot group copy and this will duplicate the group. Well, okay, that's pretty simple It'll do the exact same thing. It will create a new sprite group object so well obviously the return type then is a sprite group and This function will be called copy doesn't really take any parameters, but we'll leave some white space in there and We want to create a new group. So let's have a variable new group That's obviously going to be the type of the sprite group and let's fill that with Everything inside our group already. So we do this with a for loop. We're going to loop through everything We're gonna say for int i equals zero I Is less than sprites size and notice we're using this variable here rather than actually calling Sprites dot size so we don't have to keep calling that function over and over again We can just access the variable and we'll increment I cool Now what we'll do is we'll do new group dot add sprites Index at I at the current position and then we'll go ahead and return the new group Cool. So this function is done pretty easy, right? Well, you might be asking me what the hell and Some of you might not know what I'm referring to here But what the heck am I talking about with this new group dot add function if we're using a sprite group Object, we haven't even created this add function at all. So what are we doing? Well, you're right. We haven't created that add function yet. Let's do that Is it next? Yeah, it's next. All right, cool So let's add that pretty pretty simple, right new function void Doesn't do anything doesn't return anything all it will do is it will add Obviously the argument of the sprite that we're adding it takes it as a pointer remember because we're adding a list at least a vector of sprite objects and inside this function what we do is we push back and That's a function for our our vector sprites dot push back with the actual sprite And then of course we'll we'll get the size for it sprites size can equal sprites Size cool now push back if you haven't seen this before It's just the the simple simple simple function that will add anything to the vector It adds it at the very end. I believe I want to see add an element at the end push back Yep, just a simple function Really really easy just adds it to the vector. That's all we need to do for that function. Cool Let's see. What do we got next here? We've got Remove okay remove sprites from the group. This is where we get a little bit hectic. Let me show you why Void remove it's not gonna return anything. It's just gonna remove it from the group sprite And obviously needs to know what sprite we're removing and let's say sprite object I'm not gonna use a pointer here now. You might be asking me why and I'll I'll tell you in a second here Create this code this code block and we'll start to loop through the list for int i equals zero You know the drill here. Okay, so now we're looping through the list looping through the the group We got to test something we got to test on the strange We're gonna test if the sprite that we're currently looking at in the loop is actually equal to the sprite object That we're trying to remove in that case then we can actually remove it then we can get rid of it in the list in the sprite group Well, how are we gonna do that? We created our own we created our own class We created something out of scratch right we cured this this sprite class How are we gonna be able to test if something is equal to another one typically you just be all like okay if Sprites I is equal to sprite object Right, that's typically what you do Well, we can't really do that because I mean we just created this sprite object. It doesn't have that operator We just made it Well, this is one of the fascinating benefits of C++ and C where we actually go ahead and create our own operators and the way that we do this is By creating a new function inside the sprite object class obviously under the public definitions here What this is it's gonna return a boolean variable boolean value whether it's true or false and we're gonna test on an operator That's a special keyword. You can see it just lit up change to be the blue color And we're gonna use is equal to or these two equal signs for the operator Now the arguments here have to be constant because when we're testing if something is equal to another Obviously neither of those are going to change because we're actually doing it on the fly. We're just doing it in the code So constant co nst Sprites and now the other has to be a pointer The it has to be a legitimate object that we're looking at in memory So I'm just going to use the ampersand and call it other Now you will know, okay, that's why he didn't actually include the per asterisk here Because we're not looking at another pointer in the other case. We're looking at the reference that we've already seen here with the ampersand so constant sprite other with the ampersand to look at the actual reference value and This has to be a constant function itself So after those parameters in that parameter list with the parentheses type in the word co nst again Now we can actually go ahead and create this function and here's an interesting thing that we're going to do we're going to return Have open thing parentheses here. We're going to return whether or not the image if this sprites Image variable if it's value this SDL surface is equal to The others other dot image Now You might be noticing something Thankfully, thankfully for us anyway, thankfully for us We are very fortunate that this SDL surface does support this operator because otherwise we would have any idea what to do But you're noticing that image is a private variable We were not going to be able to access it in the other object So we have to account for that We have to create a new function that will return its internal private parts SDL dot surface. It's obviously going to return a surface pointer just like the actual image itself is And I'll just call mine get image you can call your function or whatever you'd like here It's not going to take any arguments. It is going to be constant So include co nst and let's just return the image of that object now We can use other dot get image and run that function So we're going to be returning whether or not this sprites image or its SDL surface Place in memory is equal to the other one that we're actually looking at if it is then okay Yeah, the sprite on this side of the equal sign and the sprite on the other side of the equal sign are the exact same sprite Hooray whoop-de-do wonder if I can at least compile this first of all g plus plus 07 a Sprites group dot CPP. Oh, no, I'm forgetting something. Yeah, I forgot a semicolon right over there Okay, so now that we're all done editing this function. We can go back down to our a remove function in the sprite group Object and what we'll do is we'll be testing if the sprite that we're currently looking at if this is a pointer keep in mind So we include the asterisk right here if that sprite that we're looking at is equal to the sprite object that we're actually trying to find what we will do is we can erase it from the sprites and this is a Vector function if we head it back over to our documentation You'll notice right over here. We've got a function erase erase elements and what this does is it actually takes an iterator as As a variable so we can actually very very easily access this iterator by just adding to the Vector dot begin function and then adding to where we need to be in the index So like I said, that's pretty simple Sprites dot erase Sprites dot begin to access the iterator and then go ahead and add I to it because we want to get to the current index And we're actually looking at awesome Now let's break right out of there break out of that for loop and sprite size is obviously being changed here So we have to remember to actually go ahead and Reset the variable cool Now we've got some more functions to add we've got a sprite group test of a group has sprites Well, that's a pretty easy thing to do all we have to do is creating new boolean function bool has And this will take a sprites. I'll call mine sprite object again And this will kind of have the same functionality as the remove function We'll look through there if it is equal what we will do is we will return True. Yes, it is the same function. It is the same sprite. Otherwise, we'll return false That means if it has this object if we found it in the group it does exist the group does have that sprite Update well update thankfully We'll just recall the update function of all the sprites in the group because this is something that all sprite objects have Super duper cool. So Let's create a new variable here a new function. Sorry This isn't gonna have a return type. It's just gonna be void It'll be update and It's not gonna take any function and any function parameters or function arguments loop through all of it The thing that we have to test first before we actually loop through all of it is whether or not the group Is empty and the way that we do that is we test if not sprites.empty and Again, this is a vector function. You can sign in the documentation empty right over here is A function to determine whether or not the vector is empty It's a boolean variable that returns. It's just simply yes or no So if it is not if it is empty, we won't do anything if it's not empty Then it will do Is we'll go ahead and loop through all of it Actually, we don't need this return false loop through all of it and go ahead and Use the sprites dot I Remember it is a pointer. So we actually have to use the pointer selector Update function Super duper cool. What else have we got? What other functions have we got? I don't know what a pie game Update draw draw is pretty simple. It does the exact same thing as update. We'll recall all of the other sprite object functions okay, and What else? Clear draw back or no, it's well. I won't bother with that It's gonna have to we don't have to waste or type of that empty though empty something that we can do That should be pretty easy. All that does is return all the It doesn't return anything but it removes all the sprites and we can do that with a very very simple Vector function and that one is sprites the vector dot clear Does exactly what the function's name is other than empty itself So void empty sprites are clear and obviously that's changing the size so we want to set size equal to sprites dot size BAM, okay, I Believe we're done Actually, I will add however a small function in size and that'll just Return sprite size so that way we can see the sprites the group size outside of the actual class itself Now looking through all this code. I think we're good with this sprite group That took freakin forever, but I think it's finally done Let's let's do a few experiments. Let's bring it down into our main event loop our Main function and rather than draw or then draw the sprite object that we've created What we'll do is we'll create a sprite group I'll call mine act. I'll come on active sprites. You can call yours. Whatever you'd like. Let's do active sprites Dot add Now remember we created this function and what it does is it'll actually take in a Pointer so we have to pass in the reference to this object reference the variable itself The way that we do that is with the ampersand so let's pass an object cool now we can run active sprites dot draw On the screen and no matter how many sprites we have in our active sprites group It will be drawn on to the screen in this case It's only the simple object the single solitary object, but it will be drawn onto the screen Hopefully this works for us. Let's check it out. Let's find out I don't know where my terminal I'll g plus plus 07 a sprite group. Hopefully this compiles. No, it doesn't okay. Damn it Oh, yeah, of course the draw function is going to need an argument there In our sprite group, we've got a draw function And what this takes is an SDL surface pointer for the destination And of course we pass this right into our draw function right here So super duper cool Now we should be ready. Let's try and compile this Cool that works just well for us eight on out if I move this over Boom, we've got our object right here fantastic Let's do this with a few more objects just so we see how this works with multiple sprites I'm gonna add a new color. I'll call this blue and Of course are it'll be zero zero for G and two five five four B for blue Get a new object Another I'll call it another and the color will be blue window width minus 100 window height plus 20 Now we add this to our active sprites list another And we should be good Let's run this compile and run bring this right over and whoa There's our other object other our other sprite It's in the group and it's being drawn automatically without us having to invoke it It's particular object itself. Let's do let's do something else. We'll do if active sprites Let's see remove Object This way we won't draw the red object But only the blue one because we've added to the screen and then we've gone ahead and removed it check it out Let's see if this works for us Compile and run and no more red sweet our move function works. That's awesome draw works remove works We haven't been able to play with update yet everything at least so far Let's let's do some output. Let's do active sprites dot has object Let's do and L. Hopefully this will work for us Compile and yes, we see the value one right here It the program knows it does see that okay the object the red object is in the group if we Don't add the another object the another sprite Comments it out that line if we check does it have another Well compile it run you'll see that it's zero. It's false. It doesn't have that So that function works very easily just as well for us as well. So Man, we are freaking on a roll here took forever It took a long long time to create that class. It's been a long video, but it works for us We've got something that's that's that's flexible It'll be able to keep track of all of our sprites and and work well for us in our in our program So man, we are good. We've got the freaking group sprite group class Man, I just tried to lean back put my head on my forehead and I'd like threw my microphone off me. Oh Thank you for watching everybody. I hope you enjoyed this I know it took a long long time, but I hope you enjoyed it because now we can move on to the whole rest of the C++ SDL programming tutorial series and Well, I hope you're enjoying if you are enjoying, please like the video maybe comment Please subscribe if you're willing and hopefully I'll see you again. Adios