Beginner C++ Game Programming DirectX [References / const Correctness] Tutorial 11

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
and everybody I'm chilly welcome back to beginner C++ tutorial 11 now there's been a change of plan I am splitting up the material for tutorial 11 because it ended up being like over an hour when I recorded it this deals getting worse and worse all the time so today's topic is references and I can't get up it's an older reference but it checks out as a little bonus I'm going to show you how to use some useful stuff in the Chile framework like the color class and how to do Mouse input so let's get right on to it in the tutorial 10 in the homework I gave you a mission and your mission was to draw the rectangle so we're gonna start off with that code if you don't have it for whatever reason you can get it on the wiki it's no biggie so this is what the code basically looks like you got a loop inside a loop you can draw a rectangle it's all good what we want to do now is we want to give this routine its own function ah so well let's take a look at what it looks like let's just run this mother I don't know why I set it to release but I did it's a thing that I did and now it's done here we go so I got your rectangle right and what we're doing here is we are drawing it basically basically based on a position x position Y position and on the dimensions of the rectangle the width and the height now that's one way you can draw a rectangle the other way you can do it is you can specify the corners so you can specify the top left and the bottom right corner and draw it like that and that's what we're going to do for our function now I say let's make a function where do you think you're going to put it I would imagine maybe a lot of you would think to put it in here in-game but let's think about this the the draw a rectangle function this is a basic general graphics routine that you're going to use in almost in lots of different applications that you make so what I propose is that instead of putting it in our game class we put it in graphics class because it is a graphics operation so we'll go void well passing four parameters for the top left point and for the bottom right point and then we're going to pass in the color but we're not going to do RGB three integers what we're going to do is we're going to use the color class so we're going to pass in a single object of the color class by value and then we're going to you know put a semicolon here and now we got to implement this so I'm going to create definition here we'll promote that to a document and we just want to copy paste out this stuff here so we'll copy that go back and we'll paste it in here alright and now we got to change some stuff so the start position of the loops is just going to be the position of the top left corner and the end value of the loop the ending condition is going to be the the second point all right now I have a little challenge for you what I want you to do is we've got a problem here with graphics it doesn't like it so I want you to figure out why we have a problem and what you have to do to fix it alright did you figure it out well here it is graphics is undefined because there is no graphics we're writing a writing a member function for the graphics class right but there is no member called GFX in this whole class GFX is in the game class but we're not writing a member function for game here so there is no GFX so what do you got to do well we don't need GFX because we are the graphics class and so all we have to do is call put pixel without specifying any object when you are in a member function function calls are assumed to be of that class so this is going to call put pixel from the graphics class you don't have to specify GFX dot put pixel all right now let's go into game dot CPP and now we got to replace this with a function call to graphics dot draw rect and we're just going to pass in X pause and Y pause for the first point and for the second point we're going to put in X pause plus width and Y pause plus height now the final parameter is color so we're going to do is well one way we can do is we can create a color object and then we can set the channels of that object so we can set C dot we can do C dot set R and we can set red to 255 and we can do the same for green and blue and then we can pass this color object on to draw rect and that'll work fine alright let's test it out and make sure it works here we go well we can draw we're drawing the rectangle and we can resize it so that's fine but the color it's white and I mean red and green do not make white they make yellow I believe so something's up let's go back to graphics dot cpp and check it out and here we see okay yeah i it up because i'm taking of color parameter here but I'm just passing 255 s to put pixel so we want to pass color in to put pixel remember there are two versions of put pixel there's the version that takes where is it the person that takes RGB and then the version that takes color and if you want to know the version that takes RGB you just calls the version that takes color so it takes these are G and B it creates a color object and then it calls color so now that we've made it so that it actually uses the passed in color value things should look a little different yeah here we go okay now we got our yellow rectangle now this ain't the only way you can use color you can also do something like this you can pass the values into the constructor like this and create a color that has those values for its channel and I've also created a list of predefined colors and you can do that by accessing the colors namespace so type colors and then double colon and then you've got a list of colors in here and you can pick one like you know I don't know magenta and that's like the ugliest cover color in the world but there you go you got your magenta rectangle it's all good but yeah that's the colors class and we're going to be using it mainly because it's cleaner and it's probably a little faster - not a big deal either way though alright so that is our function written now now what I want to do is I want to be able to control the rectangle with the mouse so first things first we are going to change the variables here so we've got x position Y position and width and height we're going to change that to points so X 0 and X 1 like this and we're also going to change the second point obviously if the points are all the same you're going to have an invisible rectangle and so we're going to change these ones to 200 well I guess we got to rename all this and now comes the interesting part I want to keep the control of the top-left point by using the keyboard so replace these position with just you know y 0 X 0 and then we're going to delete these ones because there's no more width and height and instead what we're going to do is we're going to control the second point with the mouse so what we're going to do is we're going to check to see if the left mouse is currently being pressed so if window dot Mouse dot left is pressed and inside the code block we're going to set the position of the second point equal to the position of the mouse some window dot mouse dot get position X and the same for the Y and there you go Bob's your uncle we run this stuff there we go we got our rectangle and we can move the top left corner with our arrow keys and if we click down we can drag and move our rectangle around wherever we click there our second point will be set to and that's awesome but there's one thing that just irks me just a little bit here so if I drag it up above the position this is point one this is point one right or point zero point one if I drag point one above point zero rectangle disappears I can't drag it up into here but I want I want to be able to draw my rectangle up here too so what do I have to do in order to enable that functionality well first it's kind of important for us to understand why the rectangle disappears when 0.1 is above point zero so you look here we've got our loop here we're looping first through Y and we're starting at point zero and looping until we reach point one adding every time as soon as we are above point one we stop and we exit this function well the problem is here if point one is above point zero the first time we enter this loop Y is going to be greater than y1 and so we're automatically going to exit and we're not going to draw a single pixel so the loop is going to exit even before it completes its first iteration now what we want to do is we want to be able to draw our rectangle regardless of the relative positions of 0.08 point one so point one is above point zero in the Y space we should still be able to draw and the way we do that is well right now we're drawing from point zero down to point one what we should do is we should check to see if point zero is 0.1 is above point zero and if point one is above point zero then we want to draw from point one down to point zero now one way we can achieve that is we check to see if y 0 is greater than y1 and if y 0 is greater we can swap them so we can put the value of y1 into y 0 and the value of y 0 into y1 and now we'll be looping from the lower one down to the bottom one so as long as we test and swap we can use the same algorithm and no matter what the position of the points are so and we'll do the same for X so we're going to do a test and swap operation twice now what I want to do is because we're going to be doing this operation twice let's create a function that will do that operation for us so we'll go into graphics and we'll just create a function here void test and swap and we'll go into a and int B and we're going to create definition here and let's see here so first things first we check to see if a is greater than B and if so we go constant int temp is equal to a so we store whatever is in a temporarily in temp because we're going to be assigning B into a so whatever was in a is going to get lost unless we keep track of it and then we take that value that we temporarily stored and we put it into B so the end result is a and B's values are swapped but only if a is greater than B and then we're going to do that up in draw rect for X&Y and that will look something like this and this should work nicely it should reorder our X's and our wise so that we're drawing from we're looping from the lower one the smaller one to the larger one and we're looping from the smaller x to the larger x like this and so this should allow us now to draw any rectangle we want yeah no it doesn't of course it doesn't well me so we can run the debugger on this and see what's going on we'll just start the debugger here we go we'll set it up so that the Y is going to be y1 is going to be less than y0 and then we'll pause and we'll go to graphic so we are in graphics let's find our draw rect put a breakpoint here and then we'll continue hit the breakpoint all right so now X 0 X 1 that shouldn't be a problem we didn't set those and y 0 Y 1 okay so y 0 is 100 y 1 is 38 so this should swap them and it doesn't it doesn't do anything Jack and so let's continue again to the next frame and let's step over and let's step into test and swap all right so a is equal to 100 B is equal to 38 that seems about right a is greater than B it is so we set temp so remember a is a hundred B is 38 we run this code now a is 38 B is a hundred so we did swap them and B were swapped but when we leave the order of y0 and y1 hasn't changed one bit well what the now I'm sure some of you already know what's going on because I have already mentioned this issue before basically when you call a function let's say you call a function with y0 and y1 what happens is that function isn't acting on y0 and y1 directly what's happening is you load the value of y 0 you load the value of y1 and then you pass those values to test and swap those values gets poured into local variables a and B of test and swap and then when you operate on them you're operating only on the local copies of a and B and yeah so you swap them but that doesn't mean for the variables in here there is no connection they just happen to have the same values because the value is loaded from y0 and y1 we're stored in a and B but there's no connection between these variables so you can't have test and swap well I guess we are bone then aren't we or so the Germans would have us believe now time for something completely different it's the Halloween season here as I'm recording this so let me show you something spoopy what I'm going to get you to do is create an INT we'll call it V and we'll set it to 69 now create another thing typing int and then type in ampersand and we'll call this R and we'll set it equal to V good are you with me so far now we're going to do R plus and equal 420 and we're going to do V minus an equal 69 now let's see what happens when we run this alright so we got our we got a debugger all hooked up here V is currently set to some number value because it hasn't been initialized yet r is weird it's got like a weird X on it panel let's step over shall we so we step over we set V to 69 so far so good now we set our equal to V now equal to 69 okay that makes sense right now let's add 420 to our and holy it just changed both of the variables whoo spooky and if we subtract 69 from V we get it again it happens to both of them what black magic is this whatever you do to our also happens to V and vice versa so here's the deal this declaration int ampersand here this does not create an int variable it creates a reference it creates a reference to an integer and this equals V is saying okay this reference R is going to be referencing the variable V now reference isn't really like a normal variable you can think of it like I don't know like an alias or like a remote control it gives another way of accessing the variable V so if we are doing something are we're actually working on V in other words it allows you to manipulate a variable indirectly dance-pop now reference has to be initialized to a variable otherwise it makes no goddamn sense it only exists to reference something else so if you try to just declare int reference are nothing you you can't do it requires an initializer and if you try to initialize it to like some value like let's say 20 again you're going to get an error because that makes no goddamn sense the only thing this the reference does is it attaches itself to a variable and once initialize it acts exactly like a normal variable in syntax they're virtually indistinguishable so now you might be thinking okay Chile so what why would I need two names for the same variable that's just confusing here's where things get interesting because we can use references in function parameters and this is called passing by a reference so we can do is we can take our test and swap function here and in the parameters we're going to put a ampersand in front of the type name and then we're going to switch over to here we got to do the same thing in the implementation got to make sure they match and if we do this we'd have to change anything else and let's run the program and see what happens so I don't want this breakpoint there did I did I save it here we go all right now if we move it above holy and mother works would you look at that don't go off the screen no because it gets funky but doesn't matter it works you arica this is I mean it's pretty cool it's cool when works right I think so so what's the what's the deal well because we're now passing in x0 and x1 by reference a and B are actually just you know different names now for x0 and x1 or y0 and y1 depending on what was used to call the function and so you can use a and B to remote-control these guys so when you swap in B you're swapping x0 and x1 or y0 and y1 and that is one of the true powers of use passing by reference you can actually control the values of the parameters that you are passing in now as I have already gone over many many times a normal function call passes a value right and you might ask the question okay so what is being passed in this situation here when we're using reference parameters what's actually being passed from the caller to the callee and the answer is well you see each variable exists in a specific location in Marie and every location has a unique number associated with it called its address and it's that address that's being passed to the function and the address is the thing that the reference uses to remotely control the variables and access them if you have someone's address you can with them just ask any twitch streamer now if you know anything about pointers all this talk about addresses might sound familiar and references are basically pointers dressed up and you know given a shave think of pointers like the the crazy cook snorting promiscuous party people they can be fun but they might also give you the bad aids now to be honest with you normally I wouldn't make a separate function just for this here so we can you know delete this and we'll go into tested swap delete that and no no you all right and so what I would normally just do is I would just go you know if X x0 is greater the next one and then I would just swap inside the if statement now there is thing in the standard library there's actually a function called swap and interestingly enough if you look at the act the function here you can see that you see these ampersands here so the swap function the standard library swap also passes in by reference because you know that's the way you do it so we can just call swap and we go x0 x1 and that'll get us the same thing there and we can do the same for y0 and y1 and if we run it there we go no no problem all good okay we are now able to do something in the poo game that I wanted to do before but wasn't able to so go back to the poo game and if you don't have it you can download from the wiki page so what I want to be able to do is I want to make the poo class responsible for drawing the poo object right now the poo drawing code is just floating around in game but I want to bind that functionality to the actual poo checked so well let's just see what we can do here what I want to do let's go to pooch and we'll add a function we'll call it void draw I'll just start off with draw and then we'll create definition of draw and what we're going to do is copy the code from game dot cpp so we'll go draw poo cut that out and we'll paste it in here and then what I'm gonna do is promote this document and I'll get whole bunch of here now so it's not game it's going to be poo not pluie it's going to be poo it's gonna be me there we go yeah no parameters that should work that has linked up with the other version but the problem is is we don't have any graphics right we don't have access to graphics because graphics is a member of the game object so the problem is this is the reason why I couldn't do this before we didn't have any access to graphics now you might say well chilli what if you just pass past the graphics in by value so we do graphics like this and first off function has to actually know what the function is file has to know about graphics so we can go include graphics dot H and then we're going to go over here and we're going to go graphics GFX and all right that makes this happy this looks fine looking good so far let's let's go to game and let's find out where we actually draw the poo so that's going to be in compose frame right now why is dropped I said compose frame bastard all right here we go drop ooh so instead of doing draw poo we're just going to do draw on the poo objects like this to zero draw graphics and here we see right away we get an error GFX and cannot be referenced deleted function and just this probably doesn't make any sense to you whatsoever but the reason why we can't do this is this function that it's saying here it cannot access this function is the copy constructor this is the function gets called when you try to make a copy of an object so when you try to pass graphics by value you're going to make a copy of it to copy it to the local graphics variable in the function but you can't copy you can't copy graphics it doesn't make any sense think about it graphics represents the actual window the screen of our window that we're drawing to there is only one of those you can't make a copy of it it doesn't make any goddamn sense and that's why we can't pass graphics by value but what we can do is we can pass it by reference so put an ampersand here and toggle header and code file go to draw put an ampersand here and there you go Bob's your uncle and this should work let's go back to game no more tears let's go to these guys here we'll change it to puh one Pooh 2 and if we run it it will work and there you go no problems whatsoever and now we have our drawing code inside of Pooh where we like it now there's another function I see here that could use a little pass by reference love and that function is process consumption I see we passing a whole bunch of different values but they're all related to the same dude so instead of passing in four different values like this why don't we just pass in a reference to dude soldiers passing dude reference dude now this thing doesn't know about dudes or at least it probably doesn't know about dudes so it's safe to go into here and include do H so that it'll understand what dude is and how to abide and so forth so now we're going to toggle get rid of that so process consumption so now we've got I should copy and pasted that so we set a single parameter in by reference that makes this underline go away and it makes a whole bunch here but this is really easy because of the way I named them all I got to do is put a dot in here and in here and it's all good oh yeah in here here that's it there we go sweet and if we try to build it we see yeah we got a problem here because the call the place where the function is being called it's using the wrong parameters so we just change it in passing single dude every time and now if we build this no problems all good now here's the thing about passing in the dude into the process consumption function technically we don't even need to pass this one in by reference we could pass it in by value which is build that oh wait and I got to change it in the implementation as well like this and so we build that and that works fine there's no problems that'll run so yeah because you can make a copy of a dude the dude and when you copy the dude all you're going to copy actually is the X and the y but in general your entities your objects in your game are going to have a lot more variables than just you know to intz they're gonna have maybe like hundreds of bytes of data and so if you pass them by value you have to copy all that data and that can add up quickly to make your program as slow as so in general when you're passing objects and you're probably going to want to pass by reference now one final thing I want to show you guys here in this is this is kind of important it's a very good practice to learn and that is I've mentioned before it's called Const correctness and basically in the the process consumption function here we're passing dude by reference but we're not doing that because we want to change the external dudes values or anything we're just reading this is a read-only operation we're only getting information from dude and if we're doing that you should always make it so that the reference is a constant reference so cons dude ampersand this and you got to do the same thing over here and what making a reference const does is it says i am not going to change any of the values in this object i'm only going to read it makes this a read-only reference and that's good because we are only reading so what this does is this makes it so that you can't accidentally you know maybe change something that you weren't intending to change and you know that's that's good anything you do to reduce the chance of an error a bug creeping into your code is a goddamn good thing this is also communicative if you have a function and it has dude ampersand the person who passing dude in is going to assume that you're going to try to change dude so if you put a Const now the person calling this function looking at the function can say oh he's just getting information from dude he's not going to change it and that changes the way they write their code it's it's a kind of communication very important so always if possible make your references Const the only time they shouldn't be Const is for example with our swap function if you have to change it you can't make by the way you can't make this one Const because graphics we're calling put pixel and put pixel is actually changing the graphics function is mutating that so you can't pass graphics in with Const you have to pass change standard reference because we are doing something that will affect the graphics object but there is something else we can do for this draw function so draw function it effects graphics it mutates graphics so we can't pass graphics in by cons but the draw function doesn't affect the puh class it doesn't affect any of X Y vxvy it only reads these values it doesn't change any of them and if you have a member function that does not change any of the members of the class you can make the member function constant and that's saying this function doesn't change any of these members it is not a mutator right process consumption update they change these variables so they are called mutaters but this is a non mutating member function so we specify it with Const at the end and we toggle here we do the same thing here Const wait no is draw it was draw my bad my bad here we go and it's the same idea as with constant references it it helps prevent you from yourself over helps prevent other people from you over and it is a good communicator it says oh this function is not going to change any of the members of the object on which it is called good to know so to recap there are basically you can break it down to two usage scenarios where you want to be passing by reference scenario one is you can't or you don't want copy an object and that would graphics here the draw function would that would fall under that case we can't copy graphics so we have to pass it in by reference and for the dude is it's the same idea we could copy it but we don't want to we want to pass by reference because we don't want to copy all of its members like I said in this case it's only two members that are being copied but in general it's going to be a lot more so when you're passing your objects you pass by reference generally now the other usage scenario is passed by reference because you want to be able to modify remotely some variable outside of the function and again draw falls under this category because we want to be able to modify graphics we want to call put pixel and change the contents of the screen another example of this one would be our test and swap we want to be able to swap those external variables so we had to pass by reference so two usages campur don't want to copy or want to be able to modify some variable outside of the function now as for passing in by value you generally pass things like you know single integers and boolean's stuff like that in by value there are cases where you want to pass in objects in by value and one example of that is if you look at our draw a rect you see we're passing coloring by value and the reason for that is if you look at the color object itself it only has one data member and that data member is a single integer so you're better off passing this one in by value because you're only passing in one integer right it's no different than passing in a single int and when you're passing a single int you prefer the passing by value but for heavier weight objects definitely pass by reference all right now it's time for the homework I've got two tasks for you this time first task in copy yeah guess but we move the drawing code for the poo into the poo class now I want you to do the same for the dude that is task number one task number two is I want you to create a second draw rect function and this one is going to take a single point plus the width and the height so it's not going to take two points but it's gonna take a single point and in the width and the height so create a second version of the draw rect function and it's up to you as to how you're going to accomplish that as usual I would give you my solution in the next video but until then that's that's tutorial 11 you know leave a comment here let me know what you think I'm always interested in hearing your feedback making better tutorials and all that until next time thanks for watching and special thanks to all my patreon supporters and I will see you soon with some more C++
Info
Channel: ChiliTomatoNoodle
Views: 30,624
Rating: undefined out of 5
Keywords: C++, DirectX, Direct3D, D3D, programming, game, lesson, cpp, how to, beginner, guide, code, tutorial, coding, introduction, introductory, software, development, windows, visual studio, game programming, game development, game dev, chili, for beginners, visual studio 2015, references, const correctness
Id: VzXco2FqpT8
Channel Id: undefined
Length: 35min 39sec (2139 seconds)
Published: Wed Oct 19 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.