Drum Machine with Python and Pygame – Full Project Course

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
You're about to learn how to create this cool  beatmaker application from scratch using Python   and pi game. This is a great project for  both beginners and experienced developers.   Pete Lawmaster created this course first, Pete  will show off the project. And then he will teach   you how to code the project line by line, check  the description for a link to the assets you need,   plus the final code. Good luck with this project.  And feel free to leave a comment with anything you   learn in this tutorial. Alright, so I'm super  excited to show you guys this project showcase.   This is one of the coolest projects I've  ever built. And I think you could really   enjoy building something similar as well.  So the key features of this app include   the ability to be able to quickly create and  edit brand new beats as well as the ability   to modify the speed at which your loop plays  and the total number of beats in that pattern.   The buttons on the bottom gives you the ability to  quickly Pause or Resume playing the beat or clear   the entire board out when you're ready to restart  you can turn entire channels of instruments off   so that you can edit certain parts of your  beat while keeping the whole thing playing.   Then when you get something you really like the   Save menu lets you save that  under a name of your choosing   that you can load it back in later and  revisit some of your favorite creations   this tool lets you create some really unique  sounds and I hope you enjoy the project.   So follow along with the tutorial, grab the code  if you want to from the link in the description   below. Leave a comment letting me know what  additional features you'd like to see in this   kind of project. Or what you'd like to see on the  channel in the future. If you enjoy the video,   be sure to leave a like on the video and subscribe  to the channel for tons more great content.   Now let's get into the tutorial. All right, super  excited to bring you guys this tutorial. But it is   a long one. So let's get right into it. And I'll  explain what we're doing as we do it. So step   one is going to be importing Pygame. If you're  familiar with the PIP module, then you can use   PIP and do pip install PI game. Or if you have  an IDE, good one like pi charm, which I use,   then you usually can do an import statement  like that. And as long as it rec recognizes your   module name, it'll take care of the import  for you. And then I would say because this   is a heavily music themed application, import  the mixer right up front. So Pygame dot mixer   is kind of pi games associated sound effects and  music handling tool. So we're just gonna do that   right in the beginning. And then we're going  to do pygame.in it to kind of initialize it,   which will need for fonts and using a lot of the  built in functionality. Okay, so that's just how   we're going to start it. And next, let's set up  our screen. And since this beat making software,   if you think about it, it's kind of you want  the same dimensions as your actual screen so   wider than it is tall, because we're anticipating  the beats kind of stretching across the screen.   So I use 1400 by 800. And I kind of like that, but  you can play around with this stylistically if you   want to. And I just defined a few RGB colors right  up front, because I know pretty much every app I   make, I'm going to use black, white and some  shade of gray, maybe 50 of them along the way.   And so I just do like black, white, gray. And  then when I add other colors later in the project,   like I'll for sure be using some like red and  maybe a gold in this project. I'll add them up   here. But we don't need that right now. So let's  keep going. And then the next thing, we're just   going to focus on getting the screen created real  quick. So it's Pygame dot display, dot set mode,   set mode. And then in square brackets just do  with comma height. There we go. And you could type   those numbers directly here, you don't have to put  them in a variable. This is much better practice.   And if you want to change it later, it's a little  easier to track down. Something else I like to do   technically, this would be considered an optional  step. But I always like to set the caption.   And I'm just calling this one beat maker. You can  call it something else if you want. And then I'm   going to set up a font right here, which I'll call  label font because it's gonna be a little bigger.   But I always create a text right in the beginning  because as soon as you need text in your game,   you're really going to want to have this  initialized already. Otherwise, you're just gonna   have to come back and do this step later. So I  say this in almost every project But if you don't   want to go and get a ttf file, almost everyone's  computer and install of pi game is going to come   with this one that you see right here free sans  bold that TTF. That's like a built in. So you can   use that one, if you just want to follow along  and you don't care too much about style, I went   and grabbed a free one off the internet, that's  just called Roboto bold dot TTF. You can see right   here in my file structure. So if you want grab  a font for your project and make it your own,   just drop that file right in there  and then call it just like this.   Okay. And then the only other thing you have to  give it here is font size. So we'll give it 32.   And that's, we're also going to do FPS. So that's  our framerate, and we're going to set up a timer,   which is going to control the speed of our game,  which for a music based application is super   important. So we'll do timer equals pi Game dot  time dot clock, some people will call this clock,   some people call it time, some people will just do  this directly in the game loop. I don't like doing   that. But make sure you have something along this  line. And let's go ahead and create our what I   call the main game loop. So we go just underneath  this. And obviously, there's going to be a lot of   stuff going on in between are kind of our variable  library and our main game loop. But just to get it   just to get it started, we're going to do this.  So we'll set this variable run equal to true.   And then we're going to set up a while loop that's  wall run. And the first few things you always do   while run is timer dot TIG at your frame rate.  So now this is saying as long as run is true,   we're going to execute this code 60 times  per second. So that's the purpose of FPS.   And since a lot of our functionality is going to  be move on to the next beat every second, every   you know, half second, whatever. This timer  dot tick is super important for this app.   So frame rate, you want to keep it at 60. If not,  if you use a different frame rate for some reason,   just make sure that when we get to the part  of the math later, where we calculate how   many beats per minute that you use your frame  rate in that math, okay, so then we're going to   do screen dot fill. And we're going to make the  background black, I think that looks pretty good.   And let's go ahead and set up what's I always  call this event handling, but it's basically just   getting all of the occurrences that are  actually happening on your computer.   So it's for event in PI Game dot event dot get.  And this little application here, every code we   put, all the code we put inside this for loop is  going to be checking all the keys on the keyboard,   the movement of the mouse, any any other event  that the computer can process is going to be   inside for event in PI Game dot event dot get. And  the first one you want to set up just so your game   will run is if event dot type is equal to and then  it's pi Game dot quit just like this all caps.   And if that's the case, then we just want run  to be equal to false. And that's all we're gonna   do for now. But we are for sure going to be  putting a lot of functionality in there later.   Okay, and then outside of this, we want to do  Pygame dot display display dot flip. And that   kind of throws everything onto the screen. And  then we'll do this last one is just going to be   Pygame dot quit just like that. So outside of any  other code, just on the off chance it gets to that   point. Okay, so reformat the format. So now we  should just get the shell of our project, and it   closed right away, because I said robot bold,  and the file is Roboto bold. So there you go.   Alrighty, there we go, we've got our outline.  And I think that looks pretty sweet. But let's   go ahead. And now let's start drawing stuff onto  the board. So we will get to sounds pretty early   in this project. And I will kind of go over  how those are used. Because obviously sounds   are super important. But first, I'm going to set  up a function that I'm going to call draw grid,   and it's just going to kind of draw all of the  static things onto the screen. So I'm going to   do that right below my screen dot fill, is I'm  going to call it draw grid. And then then we're   going to come up in between, like I said, the  variable library and the main game loop. And   I'm going to define this variable draw grid, and  we're going to start building this out together.   Excuse me. Okay, so let's start with  draw grid and just kind of think of the   space that we're going to have in this game.  So I'll start I'll call kind of the left menu,   left box. And that's if you've ever seen like  a beat layout, like that kind of app. That's   where you have the instruments and sometimes you  have the ability to like turn tracks on or off   or adjust volume of the specific instruments.  So we'll create kind of a left menu I'll call   it left box and We'll put it on the screen, and  we'll make it gray. So that's why I call that   color in the beginning. And then we'll start  at the top left corner. So at the very corner,   it will make it 200 wide. And we'll make it  the full height of the screen. So these are   the four arguments, you give rectangles, x and y  starting coordinate in the top left of your box,   and then width, and then height. And then after  that, these are now optional. So this would just   give you enough right here, let me see if I run  it should work, we get this left box, which looks   fine. But now if we add one more argument, we're  going to say how wide we want the edges to be,   which is going to make it a hollow object. So it's  going to have a width of five. And I think that   looks better as a left menu. Personal preference,  you can leave it totally thick, if you want.   But then let's also add a bottom menu, which  I'll call bottom box, and we're going to pi   Game dot draw dot rec, this is where we're gonna  put like our player controls, like start and stop   the loop of the game. So like play pause, I  guess I say game, you understand it's an app.   But we're gonna put like play pause, and then also  like save and load. So the options to save your B   or load in a previously saved beat, or adjust the  speed, or how many beats are in your app total,   will put them in this bottom box.  So we're going to call that screen,   gray. And then for this rectangle,  let's put at the bottom. And actually,   let's make it just 200 high. So height, minus  200. So that's going to be the starting position.   And then we'll make it for with the full width  of the screen and 200 high. And let's make this   hollow with five as well. And what you'll see  if I do this, now we're going to have this   kind of weird rectangle, maybe you like that  look, maybe you don't, I'm gonna take my left box,   and I'm deciding I'm gonna stop it 200 High as  well. So now we won't have that like criss cross   overlap in the bottom. I think that looks pretty  good. So we will move on. The next thing I want to   do is I want to start creating the beat. So we are  going to make it so that it's adjustable, how many   boxes are in here. But just to start, we're going  to just set it up so we can get something on the   screen. So what I'll say is, I'm going to create  a little empty variable here that I'll call boxes,   just like that. And I'm gonna create a little  colors library. So colors equals gray, white,   gray. And some of this stuff, we're not going to  touch for a little while. So if you don't want to   follow along line for line, I guess you can skip  that for now. But we are going to come back to it.   Sorry, gray, white, gray. So we're gonna do those.  But now what we want to do is thinking of a drum   kit, the first three most important instruments  are hi hat, snare and kick. So what I'll start   doing is kind of creating space for those. So  first thing I'm going to do is I'm going to   call it hi hat. txt. And now we call that label  font that we have. And it's label font dot font,   or sorry, label font dot render, we already  defined it as a font, and then you give it   the text and for the hi hat, we will just say hi  hat, that should make sense. And then the second   one is like anti alias as a Boolean. It's always  true in my experience, I don't actually know.   I don't know a scenario where it wouldn't  be. And then later when we have the ability   to turn a channel on or off. So you set  up a beat and you want disable the hi hat,   we'll make this a variable. So we will  be coming back to this. But for now I'm   just gonna make it white to not overcomplicate  the early steps of it. And we're going to draw   it on the screen. So screen dot blit. And  you give it what text you want. So we want   high hat text to get drawn on the screen. And that  needs an X and Y coordinate. And I'm gonna move   it a little bit down and a little bit right from  the top corner, even though this is our first one.   And so this should be all we have to do to see the  text hi hat. So I think that looks pretty good.   And now let's go ahead and do let's  just basically take this exact stuff,   C Ctrl V, and let's do snare and kick.  So, hi hat txt. We'll do snare Tex, next,   snare and snare text. And then what we'll do is  we'll move it down 100 So I believe we made the   game 800 High, the bottom menu is 200 high and  we're going to put a total of six instruments in   here. So we're going to do a hi hat, a snare,  a kick drum, crash cymbal and then we'll do   like a floor time and we'll do a clap. Those  are kind of the six most basic beats. If you   want you can grab Your Own soundboard.  And we'll go over that a little bit later.   And make whatever sounds you want, you  can make as many instruments as you want.   I'm kind of giving you the backbone of how to set  it up, though. So that'll be snare and hi hat.   Let's go ahead and do the next two, which will  be we'll call it kick, because it's a kick drum,   but you can call it bass if you want. And what  the heck, we'll say bass drum on the text,   that's probably what people are more familiar  with. And we'll say kick text. Okay. And let's   do after kick, let's do the crash cymbal, and  crash, and crash text. And we're moving these   down 100 for each of them. So 200 300. And we're  just going to have two more. So we have bass   drum and crash. And then we are going to want  to do the clap. And the floor tom. So clap.   And floor tom. Okay. And so we'll go to 334  3530. Now, let's just draw this and see. Okay,   so that looks pretty good. I think what would make  sense is putting lines in between them to, to kind   of delineate those. So why don't we draw those  as well, after this text, we'll just do for i   in range. And I think we want six because  there's six instruments. So for i in range six.   And we'll do this Pygame dot draw dot line screen  will make it gray. So it blends in with the   edges. And we'll start it at zero. And  then for height, we'll want it to be   I times 100. So I times 100. But since we  don't want the first one to be at the very top,   because the box already starts at the very top,  and for for loops, it's going to start at zero,   and that's going to go to five, that's just kind  of how for loops and Python work. They're not edge   inclusive for the number six, so it's going to do  012345. But we want these lines drawn at 100 200   300 400 500. And I guess we don't technically need  600, but it shouldn't affect anything. So starting   position will do, I will do zero, and I times  100 plus 100, I think that'd be a little better.   Or you could just add one to range, I guess that  doesn't matter. All right, and then end position,   we'll want it to go. Let's see, to 200.  Right, that's how wide we made that menu.   And then we want the same y coordinate,  so it's a vertical line. Let's copy that.   And put that in here. All righty. And since  the edges of the menu are five, let's make   these lines five as well. And let's see if that  gives us lines in between all of our instruments.   I did something stupid, I don't know why I have  this square bracket in here, you do not need a   square bracket if you are drawing a line. So  the line arguments are the screen the Color   Start position as an X and Y to coordinate tuple  and position as a to coordinate tuple. And then   line thickness. And let's see if five is a little  too thick. That's okay, let's see if it looks   better as three maybe since these aren't the outer  edges of our menu, maybe that would look better.   Yeah, I'd like three more. You can do whatever  you want, if you want thicker, make it thicker.   But that's good for me for now. And now  what I think we want to do is we want to   start considering how this game is going to  work how this app is going to work in terms   of the beats. So we're going to have a variable  that will set right now in the beginning beats.   And we're just gonna make it equal to eight.  That's a very simple basic setup that we could do.   But we need to use beats in this in this app,  to check how many boxes we need to draw for each   instrument. So to do that we do for i in range,  and then beats. And let's create a variable that   I will call instruments. And we'll use this  a few times throughout just to check how many   rows there are. So I guess you could call  this variable rows if you want. I'm going   to say instruments because there's six different  sounds that we have in here. And I'm also going to   instead of frying range six, I'm going to say for  i in range instruments. But the reason I'm doing   that is because we're creating a grid basically  for ion range beats. And then for J in range.   And this is instruments. And so this is another  way hopefully if you have the interest in creating   this game, so the or app whatever I'll say game  probably throughout this because the module is   called PI game and I do so many games aims.  But so if you want to add more instruments,   we're creating it now to where all you'll really  have to do is adjust how thick each instrument   should be. So you could make it to where it was a  function of that 600 vertical space that we have,   you could give me 50 instead of 100, and then  have 12 instruments totally up to you. But we're   creating nested for loops here. So for Iron Range  beats, and then for J in range instruments, what   we'll do is we will say that, we're going to draw  this rectangle equal to pi Game dot draw dot rect.   And we'll put it on the screen. And for now,  I'm going to just make them gray as well.   And we are going to make the, let's see,  we want to make the thickness of them.   I'm trying to think here, I don't want to  misspeak, we want the thickness of them to be   we want the starting position  to be AI. So that'll be our b,   that's going to be for the x the starting position  will be Ai times, and then we will want the total   width that we have available for beats, which is  the width of the screen minus 200. So we have this   width of the screen, minus 200, put it inside  parentheses like this, and then we're going   to use something called floor division. And  we're going to floor divide by the beats. So   this floor division just makes sure that it's  an integer, because for x&y pixel position,   I guess it's not exactly pixel position,  but it has to be an integer. So like,   let's say this right now would be 1200 divided  by eight, because that's how many beats we have.   This is going to start it at 1200 divided  by eight, which is like 150. But if for some   reason it was like not uneven division, this  would make sure that it stays an integer. Okay.   And then we'll want to move it a little bit to the  right, initially. So as always, as I said, with   for loops, this is going to start with zero, but  we don't want it to start at zero, so we'll add   the first 200 to it. And then I guess it's a five  thick rectangle, so we'll add the first 205 to it.   And this is just our x starting position. So  this rectangle is going to take some math,   so bear with me. For the whi starting position,  it's a little easier because we don't have a top   menu, so it'll be j times 100. And here,  it's actually okay, that starts at zero,   we'll just do plus five, because we're going  to give it a width of five as a border,   excuse me. So actually, we don't need a border  on the top, it can be right up against the top,   and this one will be okay as  well, right up against that menu.   So we'll do just plus 200, and then j times 100.  And then for the actual rectangle, we will say,   excuse me, for the actual width, we want it  to be the again with minus 200. And this can   be really important to make it to make it  adjustable to where it works for any number   of beats because a big function of our app is  going to be that it's adjustable in that front.   So again, just do the width minus 200 floor  divided by the beats, this will always give   you the largest possible width, but still  make each box even. And then for the height.   Since we have six instruments, we could do it this  way. We could do height divided by instruments   divided by instruments, but it's not  exactly height divided my instruments   because we have a 200 width 200 height,  bottom menu, so it would be height minus   200 divided by instruments. And you should  really make this a floor division as well.   But because this is 800, and we know that 800  minus 200 to 600. And we have six instruments,   this is effectively the same thing as putting a  100 here. So if you want to just make the height   100. Go ahead and do that. If you understand  what's going on and you want to do this math,   because you want to be scalable again, then do  that by all means. Okay, so let's see what we   have to do here. Because this format doesn't  look quite right. I think I just need to close   the parentheses. And I'm going to zoom out a  little bit here because this line is a run on.   So let me just copy that into a new row. There  we go. And let's make this a width of five and a   rounded rectangle. Those  look good statement founded.   Let's see why we're getting errors here.  I probably just did something silly on   the formatting. Oh, I have too many close  brackets. All right, I'm not going crazy.   Sorry for a little bit of troubleshooting. It's  just sometimes you put one too many parentheses in   there. So let's just double check real quick for  these rectangles because we're doing some advanced   math here. But once it's set up properly, it's  going to immediately be scalable to the whole app.   So we are starting it at the beat. So if there's  eight beats, it's going to start at 200. And then   it's going to calculate how much room it has on  the screen. And it's going to automatically update   to take as much space as it can. And then it'll  do the same thing based on how many instruments   and we're going to make it a rounded rectangle,  which is what the second five is for. And we're   going to make it five thick, so that it should  be hollow rectangle. Now, let's see, because we   should get eight beats, fingers crossed, that's  not bad, we get, we get eight beats right now per   instrument, and they fill the whole screen. And  that looks pretty good right there. So you can   see we're getting kind of the rudimentary shape of  this fleshed out, which I think looks pretty good.   So let's see, we'll come back and we'll improve  this style later, I think what's going to be   important is we start taking a look at how to  get this kind of functional, because that's   going to be really satisfying, if we can start  actually implementing that a little bit sooner   rather than later. So what I think we want to do,  because you'll remember at the beginning of this,   I created this empty list for boxes. Well, as  we go through and create all these rectangles,   what we want to do is add some information to this  list I made called boxes, because we need to bring   that information back from our function, so that  we can check if these things are getting clicked.   So what we're going to do is we're going to every  time we call draw grid, we're going to empty out   the boxes variable right here, we're going to  make it empty. And then we're going to draw   all of these rectangles onto the screen. And  then we're going to return some information   in this list. So what I want it to be is you  can kind of think of it of it as a tuple. Where   inside the tuple, one of the two arguments is  another tuple. So if that's too confusing for you   think of it this way, we're returning  a couple of things, we're returning   the rectangle of each beat, but then we're  also returning an X and Y coordinate for   it. So we're returning what b it is, which  is the eye and then we're also returning   what row it's in, which is the JE and then  we're actually returning the full rectangle.   And the reason we're doing that is because  we're going to use that for the collision   detection to see if it was clicked on. And then  what we will do next is we will just return   that boxes variable we just talked about. So when  are we called Draw grid. Let me reformat that just   so it likes how many spaces. So when we call draw  grid down here, we need to get boxes back from   it. So let's go back down to our game loop.  And where we get boxes is right here. Okay.   And what we need to do is use that boxes list to  check and see if we clicked on any of the boxes.   So that's not too bad, we just have to add some  new collision detection. So what we do is we come   down into where we have this if event dot type  equals pi Game dot quit. And we do if event dot   type equals, and then this one is going to be  pi Game dot mouse button down, which is what   is if you're clicking the button down, and haven't  yet released it, so there's mouse button up and   mouse button down in Pygame. And that's what we're  going to start with. And we're going to create a   loop that's going to iterate through the  entire list. So we'll say for i in range,   and then the length of boxes. And the reason we're  making it the length of boxes is that list, which   also means actually in the very beginning, this  is important thing, anytime you create a variable.   Even if it's one that you get from a function, if  you're going to use it in your main loop, you need   to have it initialize somewhere, or it's going to  say that it was referenced before it existed. So   for i in range, and then the length of boxes,  and the reason for that is every time we update   the total beat, the total beats, whether it  goes from eight to 12, to 16 to 20, whatever,   that list is going to get significantly longer  or shorter. And so this has to be scalable to   check that whole thing. So for i in range length  of boxes, if boxes and here's where we have to be   very careful about the way that we address each  item in there. So boxes, and I so that just means   we're going through the list of boxes that we  defined, and we're checking each box at i which   is going to call up the whole tuple so rectangle  and then coordinates and then we check zero.   So that's reference Seeing the rectangle that we  stored in there. And that's. So the reason we did   that is because now we can use PI games built in  collide rect function, which is this super useful,   super useful built in tool, which checks if  an X and Y coordinate, which in this case   will be the mouse. And it's checking to see if  it collided with a rectangle. So in this case,   if collide rect with event dot pause, so event  dot pause is the position at which the mouse was   when the mouse button down occurred. So the  position that our mouse is in when we click,   and if it collides with it, so this is already  right here going to check if we clicked on any   of the rectangles that we just defined, so  we're creating a really powerful function.   And we're going to say coords is equal to boxes at  i, and then one. And the reason I'm doing this is   because it's a little bit easier than referencing  the x&y coordinates as boxes, one, zero,   and then boxes one, one like that, this is just  going to give me this temporary variable called   coords, which we're going to use right below to  track whether or not something has been actively   clicked. Okay, so let's go ahead and do that what  we're going to do. And here's where we're going   to need to create a new list. Because we are going  to take clicked at coords. And I guess, actually,   we have to be careful about this, we put the  i and then J, and J is what row it's in. So   actually, we're going to want coords one, and  then chords zero. And I think I missed a box.   There we go. Okay, and we're going to want to set  that equal to the opposite of whatever it was.   So let's go ahead and create the clicked list.  And the reason I say list is because this is   what's going to keep track of what variables have  actually been of what bits have been selected or   not. So at the very beginning, I'm going to  create this list. And we're going to do it   in such a way that we define what's basically  a full list of negative ones. So I'm choosing   to make negative one mean, it's not currently  active, and one means it is currently active.   I think that's the easiest way to do it.  And I think you'll see why in just a second.   So let's do it this way, let's say clicked. And  this is our list of what beats are selected and   what ones aren't. And we'll say clicked for  underscore in because when you're just doing   it right here, you don't really need a variable  like AI or something to reference. So we'll just   do for underscore in range beats. So this is going  to create initially, a list that is that size,   and so for underscore and range beats, and  then it is going to be that for underscore   in range instruments. Okay, so this is going to  create a list as soon as the game starts up that   because beats initially is eight and instruments  is six, it'll be eight negative ones in one list,   and then there'll be a list of six rows of eight  negative ones. So it creates this really useful   array, essentially, a list of lists, that's going  to initially be all negative one. And the reason   I'm doing it this way is because then when you  click on a box, we can set it equal to negative   one of itself, so we'll multiply it by negative  one. So if it's a one, it'll become negative one,   but if it's a negative one, it'll become a one.  And the reason we're going to do it that way is   we can use that list to draw all of the active  screen all of the active rectangles. So if they're   a one, that means they've been selected, and  there'll be green. So this is a really versatile   way of setting that up. But what it does mean  is that we'll have to pass the clicked list into   our draw grid. So we'll just come up here, draw a  grid, and we'll pass in the clicked list, which is   fine. It's not like that's an inconvenience. And  what we'll do is we'll come up and we will say,   now remember, I said we're going to check for each  of these rectangles, and we'll adjust the color   based on whether or not they're active. So  I'm going to add a few more colors here.   I'm going to say green is equal to R, G, B,  Z. It's just all all the greens 0255 zeros.   And actually that'll be playing for now because  we're just going to make it if it's active,   then we will have it draw green. Okay. And we need  to make sure we're receiving the argument clicked.   And sometimes inside of your function, it's not  a bad idea to use a different variable name,   like I know I used boxes, but because we totally  reset it every time, that's not really a problem.   But we're not overriding clicked in the draw  function, we're just using it. So what we'll do   here is we'll come down and say, doop, doop doop  boxes equals colors. Okay, so let's do this for   i in range, beats. And then for J and range  instruments, let's add something down here,   that's going to say, if clicks at, and this is  going to be again, j, then I, because the first   item is going to be what row it is, and then AI  is going to be what column it's in. And we'll say,   if it's equal to negative one, then we'll have  our color that we're currently using be gray,   because it's not active. But then what we'll  say is else and you could say l f. And you could   check if clicks is equal to negative one. But then  we'll say else color will be equal to green. Okay.   And now I'm actually going to keep this one  because this rectangle is essentially the outline   of the rectangle. And there's no  reason to mess with that exactly.   Other than I just want to put a few more stylistic  things in here. So we don't need this second one.   Well, let's make the colorful one, the rectangle  that we actually referenced, so we'll leave this   alone down here. But then what we'll do is  we'll say Okay, on the screen, at our color,   and then we want this one to be solid. So if you  want it to be a rounded rectangle, which I think   would look good, but you want it to be solid, then  just make this argument to zero, and that'll make   it solid. Okay. Now let's see what else we can  do. Since we're in here, I think maybe I'd like   the idea of doing like a gold, just to upgrade  our style a little bit. So since we're here,   and we just made a green, I'll also make a gold  and I pulled this RGB ahead of time to 12 175   55 to 12 175 55. If you have a color in mind  that you'd like to use, just Google RGB value,   and then the name of your color, and you'll be  able to select through everything on the internet.   Finding RGBs is not hard. Okay, so now let's go  ahead and just essentially move this rectangle   that we just made, that is a specific color,  let's move this one inside of the parameters   of this outer rectangle. So here's where we'll  scoot them around, we'll move this one down five,   and in five, and then we'll make it this width,  I think minus 10. So we're basically putting it   inside the frame that we built before. And  we'll make it this height minus 10, as well,   since we're putting inside a frame that's  10 by 10. All right, and we'll leave this   let's make this one, maybe black. And let's  put this gold frame kind of inside of it. So   I'm doing kind of a three tiered effect. And this  is purely for style. So sorry, if you didn't like   this detour, but I think it really adds to the  look of the project. And what we'll do is we'll   make this gold one, a formal a full five by five,  and then we'll put a black like wire inside of it.   So let's just go ahead and load this up before  we do too much and lose sight of the project.   But what you're seeing is none of these have  been clicked. And so what I have currently   is a gold rim of five with a smaller only  two thickness black rim around each of them,   but it gives a really cool depth to it. I think.  Now let's try clicking. OK, we got an error.   object must be wrecked style event.  I totally agree. Let's take a look at   what we're doing here. So we are passing  in the rectangle Pygame dot draw dot rect   Yep, that should be right. And then  we're returning boxes to do four   boxes dot append. That looks good. Oh,  silly mistake because I used collide rect   in this position but it needs to be collide point  because what we're checking is if the rectangle   at boxes is zero is colliding with our mouse  click which is just a point so this needs to be   collide point not collide rekt. Let's load it and  try to click some now. Okay, so there we go. We   get hi hat green, which is pretty sweet. And I can  select multiples. And now can I turn it back off?   Yes, I can. Let's see if I can  select them kind of from all over.   Yeah, so that's perfect. That's the functionality  we want. And now you're probably aware bear that   we do not yet have any sort of movements  across the board to actually play the notes.   If we've selected them, and I promise we're  getting close to actually having sound,   which is really the fun part of it, okay. But  what we need to do is we need to do some math to   essentially calculate, how long should each beat  be. And so what I'll do is I'll come down here,   and I'll create a variable. And I'll call it  beat length. And what is going to be equal to,   and this is where I mentioned right at the  beginning, if you use the different frame rate,   then this needs to be adjusted a little bit more  oops, bpm. So we haven't created a variable yet   called BPM, but that's going to be another  part of this game. So we'll say beats per   minute is going to be 240, initially, which is  four beats per second, which is pretty fast.   But that's what we'll use right in the beginning.  And so that means the length of each individual   beat as our game is seeing it is going to be  3600 divided by BPM, if you have to think of it   this way, you can think of it as your frames per  second times 60, because in each minute, there's   60 seconds, right? And then that's if you're  using a frame rate of 60, that's 60 times 60,   which is 3600. And then we're doing floor division  to make sure we get an integer of how many beats   per minute we want. So this is how many clicks per  minute, essentially, how many loops per minute,   this while loop is running. And so each individual  beat is going to be that number divided by how   many beats per minute they're supposed to be.  And so what we'll do is we'll say, if playing,   we'll do it that way. So we'll create a variable.  And for now, we'll always be playing. So right   in the beginning, we'll set playing equal to  true, but later when we put pause functionality,   and it'll be nice to have a variable that controls  whether or not we're playing. And so we'll say   if playing, then what we'll do is we'll  create a new variable, if active length,   so how long has the beat that we're currently on,  been active. And so right when the game starts up,   we'll initiate initialize that one as a zero.  And so active length is equal to zero right   when we start so if playing while playing,  if active length is less than beat length,   then we want to just add one to active length.  So we have this variable active length, where we   track what beat we're currently on. And we're just  going to add one to it every time that we're not   at beat length. But then what we'll say is else.  And so this means that the beat has just reached   how long it's supposed to be. So just for easy  math, if we said we wanted 60 beats per minute,   once every second, we should move to the next  beat. So we'll say else, and then that would make   active length equal to zero. And now we need to  check if we're at the very end of a cycle, and   we need to go back to zero or if we can move on.  So what we'll do is we'll create another variable,   and we'll call it active beat. And we'll  say if active beat is less than total beats   minus one, so that means we're not yet at the  very end, then we'll add one to active beat.   And it's given me oops, active beat, not active  length. And it's given me a red underline because   we haven't initialized that one either. So  right in the beginning, we'll call active beat   one. And you don't really want to start with  zero because in even though in code programming,   you pretty much always start with zero, for a  beat, it doesn't really make sense to be at zero   at any point, you're always on beat 12341234.  Okay, so active beat, we'll add one to it.   And then we'll use this variable that's just going  to be an on off variable be changed. And we'll set   that equal to true. And we're going to use that in  just a second to actually play the notes on that   beat. So else, then we'll just add, then, whoops.  Else meaning else against this if statement if   active b is less than or equal to beats minus  one. And so we'll say else because in theory,   if the beat was on like 24, or 26 out of 30, but  you decided to reduce the total number of beats,   then it wouldn't work to just say, you  know, else if active beat is equal to beats,   we want to say else covering any scenario,  meaning we're not at the end of our loop.   So this is saying we've gone too far.  Set Active beat back equal to zero,   but beat changed is still going to be equal  to true. Okay, and so, let's go ahead and   I think that should be all we need to do to get  it moving. Let's go ahead and same beat, changed   equals true right in the beginning. Because  technically, as soon as the app loads up,   you would want this on. And now we have to do  something with that active beat variable, we want   to actually draw something on the screen showing  what beat we're on. Okay, so what we'll do now   is we will just say, we want to pass in what beat  we're on. So we're already, we're already using.   Let's see, yeah, we're already using the Click  Variable from the outside world. So we'll just   come down to clicked. And we'll draw active beat  as well. All right, and I want to use a new color   for this one, so that it kind of pops out of pops  out at us. And I'm going to create like kind of a   vibrant, not exactly neon blue, I'll just call it  blue, because it'll be the only thing in my app,   I'll make blue. But to get this color I'm doing,  it's pretty much like a teal or an aqua, it's   going to be a lot of G and B. So it's, it's like  a neon blue, but I'm just going to call it blue.   Anyways, we come into our draw grid function.  And underneath everything else we're drawing,   let's draw this new thing that I'm just gonna  call active, and it doesn't really matter,   it's just so that I know what I'm drawing,  because by the end of this app, there's gonna   be a lot of code all over the place. So that's  just for me, I'm gonna put it on the screen,   we're gonna make it blue. And then we need  to start thinking about this rectangle. So   it's basically a moving rectangle that shows  you what beat you're on. And, to do that,   we'll use the beat variable that we're passing  in times, and then with floor divided by 200   minus 200. Sorry, this bits should be familiar  to you by now. Divided by beats. So we're talking   about where we want to start that beat variables  12345678. So you think about it, when it's a one,   we want to start at 200. So it's going to  be one times this. And then plus 200. So   we need to scooch to plus 200. And so this means,  actually, this might be 200. Too far watch to see   with my storage. We'll see when we load it up.  Because it may be designed to start from zero.   I wonder if that would be a better way to do it.  I'm not worried about right now. That's something   we can tweak later. All right. And then let's see  the why starting position, let's have it start   at the very top of the screen and then go all  the way down to the bottom of the instruments. So   then how why do we want to be well, this one's  easy. It's just with minus 200, and then floor   divided by the beats. So that is just saying we  want this rectangle to be exactly one beat wide.   And then we will make it as tall as  the instruments times 100. So there's   600 Hi, basically, it's just a rectangle, that's  going to be surrounding the entire active beat.   And those are the four arguments the rectangle  needs, except I put the bracket in the wrong spot.   There we go. And then let's make this we certainly  don't want this to be a solid rectangle. Let's   make it a rounded rectangle of border with five  and cornered radius of three. And let's just see   if we correctly have a beat moving across the  screen. So I actually think that's pretty sweet.   It's it is starting in the right spot, it is going  to the end and then immediately goes back to the   beginning. Currently, it's not doing anything  with different sounds, but that is the next step.   So let's go ahead and finally the thing you guys  have been waiting for. Finally, let's implement   some sounds. Okay. And for this, I'll say I have  a folder prepared called sounds. And I have these   six wav files in here. I also have a nother  folder in there with some more wav files that   I'll talk about later. I just wanted to show how  you can switch between kits. But we'll get to that   way down the road for now. To do what I'm doing  you'll need to get six wav files of the sounds.   I use the free online download that I'll leave a  link to hopefully are mirrored put in the video   right here. If not, I'll make sure there's  a link to the website in the comments below.   And hopefully I talked about in the intro of this  video as well. tons of free sound kits on there so   you can download one that works for you just to be  able to follow along with this or honestly you can   make the noises with your mouth and record  record them but you will want to use wav   files mp3 these have some issues with mixer  and they don't work as well in my experience,   okay, so just make sure you've got  this sounds folder and clap, a crash,   a hi hat, a kick, a snare and a Tom, if  you want to follow along directly, and   I'm just gonna make this little area  that all say load in sounds. Okay. Now,   we'll start with the hi hat. And we will set  that equal to mixer. So remember we called   Pygame dot mixer right in the beginning, we  imported it. Now we're going to use it and   to do that we set up this mixer dot sound. And  then all we have to do is give it the file it   lives in. So sounds and then backslash. And I just  call it hi hat dot wav. Okay, so just like this,   and we're going to copy that. And we're going  to make six of them here. So we'll say hi hat,   and then snare, snare. And then we'll call it  kick, and then we'll call crash, in then clap.   And then Tom. Okay. And then in the sounds,  locations, we'll do snare, hi hat do kick,   make sure that your names match up exactly  to what the actual files, say over here.   I always recommend, if they don't  download is something pretty logical,   consider renaming them to something that's  a little easier, a little more logical.   Okay, but just like this, and if you do have  a TTY, or a special character that looks like   an escape character, like a backslash, N for  any reason, just make sure to do this double   backslash, because this is basically what you  need to do to get a backslash interpreted as a   literal in your string. You don't have to worry  about that too much. But if you do get anything   funky, where it like thinks it's an escape  character, just do those DOUBLE backslashes.   And that should work for you. Okay, so now we're  going to come down to where we did draw grid.   And we're going to put in something that's  going to use that beat changed functionality.   And so every time the beat changes, we want to  play the notes. So did you do for iron reigns,   I just want to make sure I put it in a good spot.  screens for Iron Range instruments, draw a line   down in here, boxes, draw the grid. Okay. So  what we want to do is say if beat changed.   And then, so if the beat changed, we'll call this  function play notes. And this is just going to   play the sounds that we just created based  on the beat changing. And then immediately,   we're going to set beat changed equal to false.  So this is how, even though this code the outside   code, this while loop runs 60 times every second,  this loop only runs once per time that the beat   changes. And that's how we control total number of  times that the beat that the sounds get played. So   that's that. Now let's go into let's  go above draw grid. And let's define   the play notes function since the sounds are  right here. So we'll say define play notes.   And this one's pretty easy. It's just for i in  range, and then the length of our clicked list.   If clicked at i, and then the active beat, so  that's all we have to check is if clicked at i,   which is going to check each row. So  each instrument in our clicked list   at the active beat. If it's selected as a one,  then we're just going to check what i is equal to,   and then play a different sound based off of that.  So if is equal to zero, we want that sound that   we created. Just do hi hat dot play just like  that. That's the whole thing you have to do.   And then we'll do Ctrl C Ctrl V. And  even though this one is a little bit   you know, monotonous I would say it's not too bad.  And probably outside of putting these sounds in a   list. And then referring to a specific like, item  index of the list. There's probably not a faster   way to do this. Other than just going through  and making sure you've got the order right for   your stuff. Crash and then clap. And then Tom.  Actually I'm not sure that's how we drew it is   it hi hat snare kick, crash clap and then Tom I  think okay, that is yeah, if i is equal to five   then we'll do Tom dot play. And this right here  what we just set up super fast, super easy,   is all you have to do to get the sounds playing  or It should be. Okay. So let's go ahead and   just load this in and see if we can get just  some sounds. I'll try this hi hat. Okay. And   I'm really hoping I left sound on recording the  computer here. So hopefully you can hear that hi   hat going. If you're following along, hopefully  you're getting this now let's play it. Okay.   All right, maybe it's just me. But I  think the fact that we're here already is   super cool. And you can turn  stuff on, you can turn stuff off.   And try playing around with your different sounds,  once you get to this point. All right, it's so   addictive, I could stay right there forever.  Once you get to that point, that's a really good   time to check that the sounds that you imported  are actually the sounds that you're hoping to   get because you can change those sounds down the  road for sure. But that's kind of your first way   of knowing whether or not you have sounds that  you're going to be happy with going forward.   Okay, so there is one thing that I would like to  do on the mixer. And it's because the default for   your mixer, the default for that, when you  load it in from Pygame is it has a total of   what's called eight channels that it can play  on. So eight total sounds technically that   could be ongoing. But some of those wav files  like the crash cymbal, actually take a couple   loops to finish. So in theory, you could run  into this problem where you run out of sounds,   and so it has to pick what sound it should  let you play because its default is to   only have eight. The way to get around that is  super easy. You just do pi Game dot mixer dot set,   num channels. And then I think general rule of  thumb is that the number of instruments if you   give them each three channels, there should  be no issues here, regardless of how fast you   start playing. Unless you're up to like 600 beats  per minute, then maybe you need to beef this up.   But the reason the eight is the default is  because in general, if like you have a video   game going and you have more than eight  sound effects at once, it's just chaos.   But like for a soundboard, as long as you're  picking sounds that sound okay, together,   having a lot more channels is okay, so you could  do instruments times four, if you really wanted   instruments times three has worked fine for  me in the past. So we're gonna go with that.   Okay. So that's pretty cool. I think we're kind  of at the point, we want to start adding some   player functionality to this. So like, Let's do  play pause, because that should be an easy one.   And then we'll start doing it to where you can add  more beats, and you can add more beats per minute,   or subtract beats per minute. And then we'll add  the functionality to be able to turn on or off   a specific channel. And then we'll start looking  at the ability to save and load files, which is a   it's a lot that we got going ahead of us. So let's  just soldier on. If you are enjoying this video,   I think you've made it this far already. Let  me just say please leave a like on the video,   subscribe to the channel, it would mean a ton  to me, I hope you've been enjoying the content,   I try to roll out high quality content like this  all the time. And the support means a lot. If you   have any questions about what you're seeing or  want to see something specific in the future,   be sure to leave a comment letting me know about  it. Without any further ado, let's soldier on.   Okay, so let's do a play pause button. And we'll  just come down below draw grid. And we'll just add   a rectangle that we're going to draw right down  here. I think it's easier than drawing it on the   I think it's easier than drawing it in the grid.  But if you disagree with me, that's fine. Just   draw it wherever you want. So I'll say lower  menu buttons. And I'm going to create a little   section in my code for this now. And I will  just call this button, the play pause button.   And I will say Pygame dot draw dot rect. I'll  put it on the screen and I will make it gray.   Because it's on a black background. So gray will  look pretty good. I'll move it off from the left   by 50. And then I'm going to raise it up from the  bottom by 150. So it's still squarely within that   menu. And they'll make it 200 wide and 100 tall.  And that should be a good button looking object.   We'll make it solid. And I'll make it a rounded  rectangle, which is kind of normal for buttons.   And I will just yeah, let's do some text to  just let everybody know. So I'll say play text   and we will set it equal to the label font  dot render. And let's give it the text of play   slash pause and let's make it true. And let's  make The Text white, and let's put it on the   screen. So screen dot blit, play text, and then  let's put it inside that button by a bit. So   70 and then height minus 130. So it should be  pretty close to dead on to the middle of the   middle of the button. And now let's add a little  check to whether or not we're playing or not. So   if we are playing, then we'll have play text  to here. So let's do a new font, I'll call it   medium font, because it's not exactly going to  be small. But we are going to come up to where we   defined our font the first time. And let's create  a new font, medium font, and it's going to be the   same. It's just going to be smaller because  I've got this button, that's going to say play   slash pause on it. I'd like to say underneath it,  whether we're paused or playing. So I don't want   to be small, I want to be super easy to read,  but it shouldn't be the feature of the button.   So I'll just make it 24. We'll see how that  looks. And maybe we play around with it later.   Okay, but yeah, so we'll say, alright,  playing text equals medium font dot render.   And then it is going to say  playing if we are playing,   playing true. And we'll make this one I'm  still inside the string, anti alias true.   And let's get a new shade of gray. In our in our  kind of colors library up top. And in general,   the closer to black, your gray is the darker  it's getting. So we have this regular Gray,   I'll say dark gray, and it's going to be just  50 5050. So black is 000. That kind of light,   normal gray we have is 128 128 128. So the lower  the numbers on your gray closer to black higher   numbers lighter, just neat little gray tidbit  for you. Okay, so we'll say play text is equal to   playing if we are active, and we'll say that it is  equal to, so we don't need if playing this is just   else now. Else, it'll be equal to paused already.  And let's see, let's put it on the screen. And   let's put it underneath. So we'll take this screen  up blit Ctrl, C. And right there, and let's put   it height minus one, three, let's put 30 pixels  lower on the screen. So height minus 100. Now it'd   be 100 pixels off of the bottom of the screen.  And it'll say playing or paused. But right now,   we're not actually handling whether or not it's  been clicked. So let's figure that out here we   want to do inside of our mouse button clicking  code, let's add a second section for click up. So   in general, if you want something to only happen  once, then it's usually a better idea to do Pygame   dot mouse button up. Because if you're holding the  button down, then it could technically like do it   multiple times. And you don't really want to mess  with that. So we'll go to if event dot type equals   pi Game dot mouse button up. And we'll say if play  pause dot, and I'm not gonna get wrong this time   collide point. There we go. collide point with  event dot pause, and playing. So the reason we   need the and playing is because if it's if it is  playing, then we need playing to be set equal to   false. And actually, what's probably a better way  of doing this is rather than an playing there,   it will do if playing in here, playing equals  false. And then we'll say L if not playing. And   the reason you don't just want to do else here is  because if it was playing, you would come through   and then it would be not playing and then we'd say  else and then it would see that it's not playing   and immediately set back equal to playing. So  you need to do an L F if you do it this way.   L F playing equals true. And that should do  it. So we already have the active length like   checker stops if we're playing. So let's  see if our pause button works. Oh boy.   play pause. I don't think I updated the  text. Okay, hang on a second play text   medium font dot random. Right here. This is  play text to not just play text. There we go.   All right, that looks sweet. We've got playing  down there. I pause it you can see our blue   rectangle stops and then it keeps going. I think  that's great. Okay, so let's see if I pause it   and I set up a beat. And I'm just doing kind  of a generic rock beat will end with a crash.   posit, and let's add some floor  times because those are cool.   Okay, sweet. So that's, that's awesome. I think  that's a great start, I think maybe the next thing   we should do is make it to where you can add more  beats, more beats and more bpm. So that's kind of   that's going to be kind of complicated, but  just bear with me because I think we've created   a really useful backbone for this project where  actually everything is going to scale really well,   we just have to implement it. And we have to be  careful about getting all the details, right.   Okay, so let's go ahead next. And I think let's  add the BPM stuff. So we have lower menu buttons,   we're in this. We're still in this section, for  sure, lower menu buttons. And we'll do BPM stuff   here. And I just find it helps to split it up with  those comments a little bit. And so first thing   we'll do is we'll make a BPM rectangle Pygame  dot draw dot rect. And we'll put it on the screen   rect hoping on the screen, we'll make it  gray. And we will use more or less the same   size rectangle. So for this one, we'll make it  300 To get it 50 pixels away from the last one,   but it'll still be height minus 150, we'll  still make it 200 wide, and we'll still make it   100 high. And we will still make it solid.  No, you know what, because this one is not   a button. Let's make this one hollow. This one  is just displaying how many beats per minute,   and then the beats per minute, add and subtract  buttons will be to the right of it. So let's make   this one hollow. And then add some text we'll call  BPM text. And that will be the label font now.   Now we better not do label font,  because it's a lot of text actually.   So medium font dot render, and then we're going  to spell out beats per per minute, there we go.   Okay, and let's put it on the screen, inch true   white, and then put it on the screen screen  dot blit. And this is going to be the BPM text.   And then for position, we don't want to move  this one in too much, because beats per minute   is kind of long. So we'll do 308 Just to get in  by a little bit. But we'll still do the height   minus 130, just like that. And then what we'll  do is we'll do a second text that's actually   going to show BPM text to, and that's going  to be the label font, because that can be big,   this is going to show the actual beats per minute.  So not just the text telling you what it is.   So this will be label font dot render. And then  you could make this a formatted string if you   wanted to. If for some reason you want to add  anything other than the beats per minute variable.   I'll do it that way just to show it could be  done. So in theory, you could say like, BPM,   colon and then BPM if you want it to, but I'm  going to put this below the beats per minute text.   And again, true, and we'll make it white. And  let's put this on the screen screen dot blitt,   the pm text to and let's put it just underneath.  So what would make the most sense, probably 373   70. And then I'd say that height minus 100.  Maybe where we put the last second line of   text. Let's just see how that works. And let's  check this out. So beats per minutes 240 I'm a   little surprised because I thought I was trying  a rectangle there. BPM RX green Gray 300 Oh,   I did height minus 1500. We want height  minus 150. Yeah, that looks a little better.   Okay, so that's cool, but we can't just yet can  posit it still, I just think what we've done   so far is really cool. So sorry, if I enjoy it,  this is like the most fun project I've ever made.   Okay, so beats per minutes to 40. But we can  just it yet, so that we're able to do that,   let's go ahead and add two more rectangles. And  this might not seem like the easiest way to do   it. But I actually think this is a pretty  logical way of doing it because in general,   you're not adjusting beats per minute by one at a  time. If you want to, by all means make these plus   and minus ones I'm going to make them plus and  minus fives because most of the time you see speed   beats per minute adjusted in increments of  10 or occasionally five. It's really weird   to see a song that's in like 137 beats  per minute. It's much more normal to   have 120 to 40. So I'm just going to do it  in plus minus fives but you don't have to.   driving a motorcycle down the street scared. Okay,  BPM add rec so this will be the rectangle they'll   let you do plus five and We'll say Pygame dot draw  dot rect, we'll put on screen, we'll make it gray.   And this time, let's go a little bit to the  right. So that last rectangle we made start   at 300. And at 500, this one will just give  it a padding of 10. And then we'll put it at   height minus 150. So the height of the top of  the rectangle, and we'll just make this 148 48,   almost 5050, to where it'll almost these two  rectangles will almost fill the full height.   But not quite, I just think everything looks a  little better with some padding around it. And   then we'll say BPM, sub rect. So this will  be the button that lets us subtract five   from your beats per minute, it will do Pygame  dot rect, put it on the screen, make it gray.   Now this one, still at 510, we want it the same  height, or we want it the same exposition, but   then we'll just do height minus 100. And now since  they're 4848, we have a little bit of padding,   which will be nice, as you'll see when we load  it in. And I really want to emphasize the style   stuff, you can do whatever you want with yours. So  if you don't like the way Mine looks, or you think   it would look better, in some other way, tweak  it change how big fonts are, change your font,   change your colors, do whatever you want, I'm  just trying to give you the functionality.   Okay, so then what we'll do is we'll create some  ad text. And this will be kind of nice, because we   can use it on the beats per minute buttons. And  I guess in theory, we'll want to do just plus   minus ones for the beats. txt. So forget what I  was about to say. Okay, add text is medium font,   dot render, because these are smaller buttons,  so we can't afford to make them huge. And we'll   do plus five for add text, true and white. And  then sub text sub text Nice. That's the thing,   medium font dot render. And then  in string variable minus five,   true and white. And then let's do screen  dot blit for add a text, and let's put that   a little inside. So 520, because the button starts  at 510, and then height, minus 140. So a little   bit down. So we're giving it kind of a bracket  of 10 on the top and the left, and we'll see   how that looks. It'll do about the same thing for  the sub text. So 520 and then height minus 9090.   There we go. All right, and we haven't had any  functionality. So nothing happens if you click   it right now, but let's see if that looks  good. Yep. Okay, so next thing we're going   to do is we're going to make, it's where when you  click that button, it actually adjusts your BPM   by plus or minus five. And that is not hard to  do. So we'll come down into our mouse button up   code where we check if the if the play pause  button gets Wow, that was hard for me to get out.   If the play pause button gets pressed, and  will do if add BPM, add rect dot collide point,   collide point, event dot pause. And so if that's  the case, then we just want BPM plus equal five,   and then we'll do an L if BPM sub rect  dot collide point, event dot pause, be   Pm minus equals five. And actually, we can  make our code slightly more optimized by   making these all LFS because in theory, we know  that these buttons are not in the same spot. So   we can save our code a little bit of time, by  not bothering to check if you click these other   buttons if you already click this button in this  loop, because you're not going to be doing both.   And that's super simple. That should be all we  have to do. So let's go ahead and check it out.   Let's see. I'll go and put some  sound in here. bunch on lunch,   and let's see if we can make it faster   Yeah, it's given me anxiety. Okay, but hopefully,  if you're following along, that's really cool.   That should be like super encouraging. You just  made this happen. You are a programming King.   Good work, keep it up. Maybe I'm just talking  myself, but I think you're enjoying it too.   Alright, so the next thing we have to do is  we have to add beats and that is going to be a   little bit trickier because we have to obviously  update our clicked and update our total grid. So   we have a few lists that have to get updated if  we change how many beats are in the song, but   we can start basically with the BPM stuff that we  just made. So we'll say beats stuff. So, you know,   yes, there's a little more programming we have  to do on the back end, but at least to get the   rectangles drawn, it is not going to be too bad at  all. So we have beats rekt beats, txt, beats. txt,   beats txt to even because it really is, it's  a second. It's a second version of the BPM,   something that you should have control over,  we want them to be able to add and subtract.   So we'll say add text to sub text to add text  to sub text to and we'll do one beat at a time.   Because technically, you could have  any, you could have any time signature,   you could do nine beats total, if you really  want to. So we'll say beats in loop. And   this time we are at we are currently our right  limit, I guess, is 560. Right? So would it make   the most sense to start this at 600? Probably.  So we'll do 600. And then everything else,   I think is fine, this will be 608 670. And then  this one should probably now be 810 810 828 20.   And we haven't added anything for operational  code yet. So nothing happens when we click these   buttons. But that looks good. Let's move  the text to the right. Because this is not   as long so beats in loop can be like 618. And this  can be like six ad I think that will look good.   Yeah, that looks better. All right, moving on. The  actual functionality that we need when we click   these buttons is a little bit more complicated.  So let's take a look at what we need to do when   we collide with the points. Alright, so we'll come  down to these to be BPM, add rect and subtract.   And we need to do an L F beats add rect collide  point and LF beats. And initially, we can kind   of use the same code because we're we are going to  take the beats variable that already existed, and   we're going to add one and subtract one. But that  is not enough right there. Because we have to,   we have to add a full row, a full empty row to  our grid. If it was make sure I say this write   a full empty row to our grid. If we add a B, and  we need to remove the last row in our grid if we   subtract a B, so what we need to do is say for  i in range length of clay clicked length have   clicked There we go, we need to remove a weight,  this is the plus one. So I am going to steal this.   There we go. And so this means  we've just press beats minus one.   And what we need to do is we need to say for i in  range length have clicked clicked at I so this is   going through each row of our clicked list. And  we're going to clicked I dot pop, which is the   python list function for removal. And we're  gonna pop the minus one which means the last   character on the end, so there's this way you  can address this is the index inside that list.   And if you do a negative, it's counting back  from the end of your list. So pop minus one,   this is going to go through and remove the last  item in our in our list for the click List.   And then for the beats plus one we go through  and we do essentially the same thing do to do   so actually, I was on the right track already.  Except instead of pop minus one it's actually   kind of fun, it's append and it's still a minus  one because minus one means not selected. So   this is now everything so I think this is  going to make let's see Fingers crossed.   So we hit plus one and now we have nine on  the screen how cool is that and the entire   screen updates every time we add one so  now we can go ahead and do 12 beats I'm   gonna pause it while I set this up so bass  snare bass bass snare, bass snare crash. Yeah   and this I mean you can play around with it  already if you want but this can keep going you   can make this thing 48 Right here. You will notice  it's a little bit tedious to fill in 48 beats but   it's we set it up in a really smart way so that  this is completely adjustable based on how many   AP how many beats you want in your loop. So I  mean awesome job guys. We are just cruising along   here. Let's add some more functionality. Because  this is going really well, let's add the ability   to turn off a channel so that you can edit it  without it affecting your live loop and turn it   on and off just like that. So to do that, we are  going to come up and we are going to create some   instrument rectangles. So essentially, they are  just let's go down here underneath the beat stuff.   And we'll say, instrument racks. And I'm just  doing this so that we can click on the channels.   And we'll say, instrument, racks, equals, and then  a empty list. And then for i in range instruments,   and I'm trying to make it so that if you copy this  code, and then later on, you want to add some more   channels, I'm trying to make it as scalable to  that automatically as possible. So we'll make   this little rect equal to pi Game dot rect dot  rect. And you'll notice what I'm doing now is I'm   defining a rectangle, but I'm not drawing it on  the screen because we don't need it on the screen.   And for this one, it's a little different,  we're just defining a rectangle. And so   this one needs to tuples instead of a list  of four characteristics. It needs an x&y   Starting position, and so x&y Starting position  will always be zero, and then I times 100. So   just just as we go through the list, it's  going down 100 at a time, but it's staying   all the way on the left. And then the width for  all of these was 200. And they're all 100 Hi.   And then we're going to do instrument  racks, dot append. And that rectangle,   okay, so what we're doing is every loop we're  coming through, and we're creating this list   of rectangles for those buttons. But we're doing  that so that we can come down in our in our   collision detection inside of our mouse button  up clicking. And we can check if any instrument   rectangle was clicked super easily.  So to do that, we'll say L to L f,   we will say for i in range, length of instrument  rectangles, okay. So this is going to check   every instrument rectangle that we define.  And what we're going to say is if, right,   if instrument rats, sorry, I tried to give my  variable names, long descriptive names, so that   as you guys are following along, it's pretty clear  what everything is. But these are maybe longer   than you would want to use in an optimal  project. But so we're going to check if   every rectangle in there was clicked, we'll say  if instrument Rex dot collide point with event,   dot position, then what we'll do now is we're  going to create a new list, and I'll call it   active list. And we will set whatever instrument  was clicked. So whatever is that active list, I   times equals minus one. And so we're going to use  the same kind of logic we had in our clicked list   for our active list, but this is going to be a  little simpler, because it's not really an array,   it doesn't need to be a list of lists. So we'll  go down to clicked and read only if clicked,   I will make another list called Active list, you  could call it active channels, active instruments,   whatever. And in the beginning, I'm going to set  them all equal to true because I actually think   our default will be having all of your instruments  on. And it's just going to be one for underscore   in range of instruments. Okay, and this  is just going to give us a list of six   ones saying all the channels initially will be on.  But if you click on a channel, it'll turn off. And   where we'll update that is we'll go into our draw  grid function. And we'll pass in that active list.   So we'll say actives, doo doo, doo doo down here,  and we'll give them the active list. And now do do   actives. So you remember this colors, gray, white  gray that I made before, I would like the text   of each instrument to be the color of its active  list position. So essentially, if you click on it,   then I want it to be a one meaning it's active,  or a negative one, which is actually going to be   great because remember, a negative one is the last  item in a list. So I just think that's a clever   way to do now. Hi Hat text is going to be colors  zero. Wait, wait a second. Colors, no active   actives. 00 Okay, so let me be super thorough  to explain this item because now it's a little   confusing, we're referencing an index item of  a list in a list. But actives zero is telling   us whether or not we currently want high hat to be  active, right? So is this is going to be a one or   a negative one, depending on whether or not hi hat  is on. And so if it's a one, we want to be white,   if it's a negative one, we want to be gray.  So now we just do this exact colors logic that   we did here, for all six instruments, and we  just make sure we update their index location.   And as soon as I do this, I will load it up and  show you what we're doing. So do 234, and five.   And again, if you need extra  clarification on anything we do in this,   just let me know about in the comments,  I'll get back to you soon as I can.   So if I click high hat, you can see it turns  gray, which is great. If I click snare, it turns   gray bass drum, I can sort of make these inactive.  But what does that mean for the actual code. And   so we need to come into our play notes function  because it's going to impact it in here as well.   So what we need is if clicked i is equal to active  beat. And we need to check and active list at i   is equal to positive one. Okay, so this is all we  have to do now. Because when we check and see oh,   it's time to play the hi hat, because in  my beat that I've set up, it's a one. Well,   we checked and saw that actually hi hat is  turned off. So it is not time to play the hi hat.   And it'll work that way for all of them. So that's  all we have to do there. But it's still going to   look bright green on the screen. And so it might  be a little confusing why it's not playing,   maybe you didn't notice the text was dark gray. So  let's also in the grid, I think I like this idea.   We'll go up to in here where we check the colors.  So if it's not selected, it should be that light   gray, that basic gray already. But then what we'll  do is inside of this else statement, we'll check   if actives at J now it's actually J is the beat  for this loop. So hopefully that's not confusing   for you. But maybe it is, this is checking  what instrument so if our active instrument is   positive, then the color should be green. There  we go. There we go. Okay, but if the actives,   J actually, we can just do an else here. So we  checked to see if it was a one. If not, then we'll   want our color to be equal to dark gray, dark  gray. There we go. So now let me explain what   we just did. But make sure that you're following  along. And hopefully I didn't confuse you too   much. So let's say you have a high hat playing  every beat in your loop. And then you want to   add some bass. But then you want to kind  of see what sounds like without the hi hat.   Okay, you can turn just that channel off. And you  see the squares go dark gray. But what's cool is   that still gives you the ability to edit it. So  you could still be working on your beat. And then   turn it on. So like let's say I want to add some  crash and some clap. I don't know what these are   gonna sound like this could be wacky. But now I  could turn all this stuff back on at any time.   And then you get this whole kind of funky  be actually it doesn't sound too bad.   And I'm gonna turn the bass on the floor toms off.  And we have individual channel control. So that's   really cool. That's another cool feature that like  a standard drum pad would be able to do for you.   So okay, we have play pause, we have beats per  minute, we have beats in a loop, we have all   of the ability to add beats, add speed, add a hi  hat, or turn off individual channels, things like   that we've looked at how to load in the music.  So I think we're getting to the point where we   need to work with an external file to be able to  load and save specific beats that we've created.   So we're going to do that next,  but I need a quick water break.   Okay, so the next thing I want to do  to our app here is I would like to add   a Save Menu and a load menu. And I'm going to put  them on two different menus because I think that   kind of helps separate out functionality, but you  could probably put all this on one. That's just   up to you. But let's get into it. Okay, so let's  start by just drawing the rectangles because from   there we'll start Bill Hang out how this actually  needs to work. So let's come down to where we draw   everything. And we have so many rectangles and  beats and instrument rectangles all getting drawn.   Next thing we'll do is save and load stuff. Okay.   And we can pretty much use the same rectangles  that we've been using in the whole menu,   because there's nothing wrong with them, they  look just fine. So we will say Save button equals,   and that'll be Pygame dot draw rect Skrein. Gray.  And now we need to make sure we keep moving them   to the right, so that'll be this one, we'll  put at 900. And we'll put height minus 150.   And actually, I think it'd look cool, maybe, if  these were one over the other. So height is 150.   And then 200, wide, and we'll only make it 48.  High, kind of like the plus and minus buttons,   because we'll do save above load.  And we'll just see how that looks.   So zero, and five, and then we'll do load button  just underneath it. So my copy the same button   equals Control V and then minus 100.  And everything else is the same. Yeah,   those buttons look pretty good. Let's put text  on them now. So I'll grab actually, I think   these maybe can be label font, I think that'll  be all right. So we'll say save text equals,   and it'll be label font dot render should be pro  at this by now. And we'll just say save, beat.   And we'll make it true. And we'll make it  white. Guys spell things, right, true and white.   And I will take this whole thing, save text.  And we'll do the same thing for load, load text,   load beat, true Drew and wait. And then we need  to put them on the screen. So screen dot blit.   Screen dot blit. And this one, we want to  save text. And we would like to put it just   a little inside the button. So 920 and height  minus 140. And that should give us a nice,   fairly square in the center button kind of thing.  And then we will do screened up but load text.   And then this can be 920 as well. And then minus  90. And let's see, again, we're not pressing those   buttons yet. But yeah, the text looks good. You  can play around with the spacing if you want.   They're on the buttons. So what more do you want  from you guys? Okay, save beat load beat. And the   reason I put them one over another is I want to  add another button. Once we're done with this,   that's clear board. So like let's say you  filled in, like this whole board with squares,   and you totally regret it and you just  want to scrap it and start over, rather   than closing the program and then opening it back  up, we'll just do a clear board functionality. So   actually, that's going to be easier than the save  and load. So why don't we just do that, right now   we'll do like clear board, because that's gonna  be like three lines of code. So clear board, we're   going to add CLEAR button. And it's going to be  same button. Actually, I'm just gonna kind of copy   all these because it's just going to have text as  well. Pygame dot draw dot rect screen. And then   we'll want this 900 It's 200 wide. So we'll want  it at like 1150. Does that make sense? 1150 and   height. And this one can be the full 100 high I  would think and then this text will have it say   clear board. Okay, clear board. And then we'll put  it at 1160 and height minus 130. Let's try that   1160 height minus 130. And this will be clear  text and clear text. All right, so let's see   if that looks. Okay. I would like to move that  down some height minus 120. That'll look better.   Yep. Okay, let's do the clear board real quick,  because clear is way easier than save and load.   Save and Load is going to be a lot of dealing  with external files. And I think just this is   going to be a little faster. So let's go ahead and  check if the clear button collides with the point.   So we'll come down to our LFS because  it fits nicely in here and we'll say   LF CLEAR button dot collide point event dot  pause. So if you've hit the clear button,   then actually what we're going to do  is we're just going to set the clicked   list equal to what it is in the very beginning.  So, you know, we check how many instruments and   how many beats, and we just set them all  equal to minus one. Well, we can just come   under our clear button and do the exact same  thing. And so that is really it. All right,   let's check that out real quick. So we've got a  whole bunch of high hats and some, there we go,   just a random, terrible button, you're like, Oh,  what have I done, clear the board, you're empty,   you're free. There you go. Okay, so we have  clear functionality. That's sweet. Good job.   Now, let's do the save and load. And I want to do  it, where save and load will actually kind of stop   playing the music, and it will kind of make it to  where you can't click the rest of these buttons.   So what I'm gonna do is I'm gonna create  two new variables called Save Menu and   load menu. And we're going to use those kind of  similar to playing to see like, if something is   currently true, so up by be changed, I'm gonna say  Save Menu, and it will be equal to false when the   game starts. And so we'll load menu, they'll  both be equal to false right in the beginning.   But one thing we are going to  do in the beginning as well,   and you'll want to do this, you'll want to  drop an empty text file into your Pygame   project. So if you need to make one in the outside  world and drop it in, that's fine. But if you   have a decent IDE, you can do new file, and then  just call it like, my beats or whatever dot txt.   I already have one called Saved beats dot txt,  and to say like, Hey, we're going to be using this   inside of this program, then you want to start  early in your function and just do file equals   open, and then save beats or whatever the name  of your text file is dot txt, and then comma,   and then since in the very beginning, we want  to read the data. And so let's say you close   down the your session, then two days later,  you come back and you want to do a new session,   you want to read all of the information that's  in there currently. And we'll do it kind of like   a CSV or comma separated values file, where each  line in the file will be all the information we   need for one beat. So it's going to be how many  beats are in it, how many BPM What name did we   give it and then the clicked list of that guy. So  we'll do for line in file, the file that you have,   and we'll make a list called Saved beats dot  append. And then that line, okay, and saved beats   doesn't yet exist. So right above file, let's just  do save beats is an empty list to start. Okay, and   since right now, we don't have any saved beats,  it's just going to be an empty variable until we   do save some stuff later on. But this is how you  open up and store the data from a file initially   already, so let's go ahead and use Save Menu and  load menu. Now if we come down to our buttons,   and the first thing we're going to  do is check to see if you've clicked   on a button. So if you click on save menu, or you  click on Load menu, and one thing that we're going   to add to all of the mouse button logic so far,  is we're going to say if mouse button up and not   save menu and not load menu because technically  everything is going to be there. Even after we   load in a new screen that's going to be covering  it up. So we just want to make it to where you   don't have to worry about clicking the buttons on  the underneath after we've created a new menu. So   all of that's great. And then kind of the counter  to this is once we have save menu or load menu up,   we need to make sure the buttons in there can be  pressed and we'll do that by adding a new line   that's going to be and so Pi game mouse  button up and save menu or and and load menu   and we'll do that a little bit later.  Okay, so let's get down to business   and not save menu and that load menu and then  we'll want some LFS in here checking if Save menu   or load menu are clicked so LF Save Menu, save  button, dot collide point with event dot position.   Then we want save menu to be equal to true  and then we'll say L F load menu dot collide   point To event dot pause, then we want load menu  to be equal to true. And we don't want to run   this code just yet, because it'll disable all of  our buttons. And we won't be able to do anything   but close it. But this is going to make it  to where our Save Menu and our load menu do   get opened up. And when we're loading in, I think,  yeah, we'll just leave it like that for now.   So what I mean, when I say we need to kind of take  this exact same code, but it we're going to need   to do some different stuff with it is we're going  to use this menu. So we'll say l f. Now because   we don't want to run this if Save Menu and load  menu or false, but we'll say L F event dot type   Pygame mouse button up. And we'll  just say we're going to create an   exit buttons. So we'll say if  exit button dot collide point,   event dot position. And we'll use an exit button  on both the Save menu and the load menu just to   get out of it. So even before we actually set up  the functionality of saving and loading, we just   want to have the ability to enter a menu and then  exit the menu. Okay. And we'll just make sure that   playing is equal to true, when you get out  of the menu just on the off chance it pauses,   it shouldn't, because we don't have it set up  that way. But just now we have it. Okay. So   we're not doing anything with Save menu or load  menu yet, but we want to so let's come up to our   other functions, where we draw stuff screened up  fill boxes. Yeah, and so we want to do before even   the box is getting drawn. So screen dot fill is  the only thing that's happened yet. And we'll say   if Save Menu, then we'll do a function  called Draw Save menu. And then we'll say   same thing, if load menu, then we'll say  draw load menu. And just so I don't forget,   we want to make sure we get the exit  button back from both of these. Exit   button equals draw load menu, draw Save Menu,  okay. And that's really what we have to do,   we have to think about this in order of what's  the bare minimum we have to do to get these menus   going. And then we can start adding the actual  functionality to them. Okay, so let's take a look   at, it doesn't really matter which one we start  with, they'll be sort of similar in format. So   we'll come down just below our draw grid. And  we'll do draw Save menu first. So draw def.   Bow, I'm having some trouble typing, def draw  Save Menu. Okay. And we just have to make sure   we return an exit button before anything else.  Let's just make sure we don't forget that.   Okay. And let's honestly, let's just put  that on the screen first. So we'll do   exit button. And let's not call it exit  button. Because we use that so many places.   Let's do exit btn, just to separate out, and  we'll say exit btn is going to be equal to   that Pygame dot draw dot rect. And we'll put on  the screen, we'll make it gray because all of our   buttons are gray. And for x position. Let's put it  at very far over to the right, so with minus 200.   Let's do with minus 200 and height minus 100.  And then for wet floods make one excuse me 180.   So it doesn't quite touch the right side and  90 so it doesn't quite touch the bottom. And   then we'll make it a solid rectangle with rounded  rec tangle edges of five just like we always do.   And let's make some exit text here that's going  to say close menu in label font. So label font   dot render. And it'll just say close and  do to do true and white. Let's do that.   And then screen dot blit screen dot that   exit text, and we want it what do we  want for the coordinates for this guy?   We'll put it with minus 160. So we want inside  that button with minus 160 and height minus one   oh eight minus 70, they'll do a little bit of  cushion there. And let's see, I'm basically going   to copy this entire thing for draw a load menu,  just so initially draw load menu. So initially,   we have the ability to just test out opening up  those two windows. But we do actually, you'll see,   this is gonna be a little weird. If we don't do  another step, so let's say we're saving the beat.   Okay, we're in some menu now. But we haven't done  anything that's going to make it feel like a menu.   So boo pool has no object, load menu dot collide  point oops, this, what did I do? Exit button.   Oh, I did load menu instead of load button.  You Goofy. Goofy. Pete. There you go.   Okay, already. So one thing I want to say we  want to draw a rectangle that's basically the   full screen. So Pygame dot draw dot rect, put  it on the screen, make it black. And make it   the size of the entire rectangle. So start  at 00 Make it the full width and height,   and no rounding no edges, we want to be  solid, and make that the first thing you   draw on your menu and do it for both. So  what you'll see now if I hit Save beat,   well, you'll see nothing because I did something  wrong. Let's take a look. Oh, so it's not working.   Because I put these way too early. You want these  menus to kind of be the last thing that you draw.   So after everything else is getting drawn.  So after the clear button after everything,   we want the drawing of these menus if the menus  are selected. And the reason for that is this   code is drawing things in this specific order. So  the last thing it's doing is right at the bottom,   checking if you have a menu active or not. So  we have this ability now to go into the load   menu and the Save menu just like that. Okay.  And to kind of illustrate, what else we could   do is we could say while we're in these menus, we  can pause this stuff. So the buttons aren't doing   anything but that music is still playing. And if  that bothers you, then super easy thing to do,   would just be set playing equal to false. While  the menus are active, I actually think it might   make sense to have it still active wall while  we're in there. Because if you're saving a beat,   maybe you want to be hearing it to think of  what a good name for it would be. But okay,   this is good. The important thing was that we  were getting those menus to work because now   those menus are blank slates that we can open up  and do our work in. So we can kind of stop messing   with the main loop, which is getting pretty gummed  up. So we'll start by just working in these menus.   And so to start with the draw saved  menu do to do, let's do draw, save,   because it's a little bit simpler drawing the  loading menu, we have to kind of sort through   everything that's been saved. And that can take  a little while. So let's start here, we have the   full rectangle. Let's call this menu text. And  we'll just kind of tell them what they're doing   on the screen. So we'll say render and we'll say  Save menu. Enter a name for current beat, okay.   And we'll make it true as always white as always,  screen dot blit. As always, and let's put the menu   text menu text. And let's pick a good spot for  about 440. And let's see what that looks like.   So save menu, enter names current beat.  Looks pretty good. I'm happy with that.   So that's cool, but we haven't, we haven't really  done anything yet. We've just got that going on.   So next, let's put some, let's put a button  down before we worry too much about the typing   space. Let's put a save button on the screen.  So we'll call it saving button because there's   already a save button. So that's maybe a little  confusing, but that's what we're doing. Okay,   pi game, pi Game dot draw dot rect. And we're  putting it on the screen. And we're going to make   it gray because that's what we do with buttons.  And we'll put it sort of in. We're making it fray.   We'll put it pretty much in the  middle of screen. So we'll do with   that Yeah, width divided by two floor divided by  two, and then we'll do minus 200. So this will be   a real wide one, we'll put it height times 0.75.  So we'll put it three fourths of the way down the   screen. But we'll make it 400 wide and 100 tall.  Because it's a big button, it's kind of the whole   purpose of being on the screen. So we'll make it  a bigger button. Saving button, and then we'll do   saving, oops, gaming, saving text saving txt. And  that will be label font dot render, label font dot   render. And this will have the text be save beat.  And true and white. And screened blit saving text.   And we want to put it at about the same spot.  So around width divided by two, maybe minus   50. This time, because let's say it's 100  wide, maybe, I'm guessing, and that could   be a good spot for it. And then we'll do  height times 0.75. And then we'll do plus   1020 30, we'll put it in the middle of button 30.  And that should give us a big ol button that says   save on the saving screen. Save be Yeah, we  want to move that to the left a little bit.   Okay, but we've got the beat the button on there,  which is important. And let's move it minus   70. I don't know I'm winging it here.  See if beat. That's pretty good. Okay,   so we've got to save beat. And now, one thing,  we're already returning the exit button. But we   also want to return the saving button. Because  we are going to check if we collide with it and   the outside world. So go down to where you are  drawing your save menu. And we'll do exit button   and saving button. And we'll use that later  to check whether or not we're saving the   beat already. And now we'll want to pass in a few  things into this actually, we're going to want   to check the current beat name, because we're  going to be typing in to save a name. And then   we're going to want to check whether or not we're  actively typing. So yeah, it's not happy, because   those are not yet variables. But we'll come up  here. And we're going to make these new variables,   we're going to make beat name. And I'll just be  an empty string initially. And we'll make a new   variable typing, which initially will be false.  And then if we come up into our draw Save Menu,   then you'll see we now are passing in beat  name. And we're passing in the typing variable.   And so to do this, we're going to make a new  like entry box in the middle of the screen.   And so we'll call it doesn't  really matter where we put it,   we'll call it the entry rectangle. So entry rect.  And that'll be equal to pi Game dot draw dot rect.   And we'll put it on the screen and  we'll make it dark gray. And we will,   let's just make it regular Gray, because we use  dark gray to signify whether or not it's been   clicked. Okay, so screen gray. And then let's  just put it at 400 200 600 200. All right,   so it'll be the middle 600 pixels of the screen  200. We'll get down from the top by a little bit.   And we'll make this sucker five by five.  So there's just been a big empty rectangle.   And then we're going to have the entry text,  which is going to be basically telling us   what we've currently typed in. So label  font dot render, F string of beat name.   And there we go true, and white, and we're  going to want to blit that screen, dot blit the   entry text and we're going to want to put it  right inside that variable, that rectangle,   okay. And we need to return the entry rectangle as  well because we need to be able to click on it and   determine whether or not we're actively typing  or not. And I believe that's all we'll need.   Okay, so now let's go back down to where we  call that and make sure that we're passing the   entry rectangle back. So unresolved, draw Save  Menu did accidentally change the name of the   draw Save Menu, beat name and typing, I'm sure I  put Another, oh yeah, I put a semicolon in there,   such as silly goose, okay. And tree rectangle. All  right, so let's do something with these buttons,   I'll show you what it looks like now you should  be running it on your own as well. And you see,   we've got this nice rectangle in the middle where  while we're typing a beat name, it'll load in. So   let's go ahead and close. And let's do something  with all these buttons that we've got. So now we   have to go down and check what to do if all these  different things get clicked. Okay, so we are in   this section now, this L F, type pi game mouse  button up, where we have the exit buttons.   Obviously, to kind of reset everything, and we'll  clear out the beat name. So if you were halfway   through typing a beat name, and then you close  the menu, we'll set it equal to empty. And if   you were typing, we'll set that back equal to  false because now you're obviously not typing.   All right. And so let's start taking a look at the  things that we just defined and in the in the menu   and what we want them to do. So if you click the  entry rectangle, then what are ya, if you click   on that rectangle, then what we want to do is  basically change what state of typing you have.   So if entry rect collide, point event dot  Pause, pause, then we will say if typing,   then typing equals false. And then we'll say L  if not typing. So again, this is where if you   just did an else, you'd get this tricky little  thing where it comes in and says, Oh, if typing,   typing equals false, else, but then the  else is checking if not typing, and so   you'll just get this kind of sticky situation. So  do an lf not typing. Set, typing equal to true.   And we're just going to use if typing to handle  a new type of event. So we'll come down into   the level of this like l f. So this L F, and we'll  say if event dot type, equals and now we'll use   a new type, which is Pygame dot text input. So  that's you've hit a key that has a text value,   and the typing variable is true. And so this  is how we'll handle not modifying the beat name   if you're not actively typing. And then we'll say  plus equals event dot text, because when you hit   a text key, a P or an underscore and apostrophe,  or an M, the value of the actual key that you hit   as it appears in a string is event dot txt.  Okay, and then we'll say if event dot type equals   pi Game dot key down, and we'll check  if so key down is another type of   event. And we're using this to check if this  specific key that was pressed if event dot key   is equal to pi Game dot k underscore backspace, so  we want to check if the backspace key was pressed,   and the length of beat name is greater than  zero. And this is an important step because if   the beat name is already empty, we don't want  to try to remove text from the variable that's   keeping track of the beat name, it's already  zero characters. But what we have to do here,   because there's not really an easy way to just pop  a character out of a string, you have to redefine   it. And so what we'll do is we'll say beat name  now is equal to the current beat name. And we use   this range of characters. And so leaving, leaving  there as no character before, this colon means   start from the very beginning. And then a minus  one means go to the character that is right before   the end of the character. So this is basically  just a way of grabbing the entire string up to the   most recent character. And so just with these two,  we have added functionality that's going to let us   remove and actually we want another and  typing condition there. So now the entry   rectangle should determine whether or not we  are actively typing or not. And then the the   text input and key down characters here should  change whether or not we're able to do anything,   so we haven't handled the actual Save button yet.  We will we will do that next. But now let's go   ahead and see how our menu works. So save. I'll  click in here and now I should be able to type   Pete, Backspace, Backspace, Backspace. I'm  going to type Pete is cool. Now if I click   this rectangle again, And I keep typing. Yep,  it's not doing anything, which is good. That's   what I want. But we haven't visually shown that  anyway. So let's go back into the Save Menu, do   Save menu. And let's add like a dark grey insert  rectangle that says when it's time to type.   So or maybe a light gray would make  more sense. But I'm going to do with   the dark gray because it's my tutorial. Alright.  And so what I'll do is, I'll say before the   entry wrecked, so where was that entry wrecked  here? Yep, Ctrl C, I will say if typing. And   then I'm gonna put this rectangle in here, and  it doesn't need a name, because I'm just using it   to signify whether or not we're typing, and I'll  say dark gray. And I will just make it solid,   in the same footprint, and that's okay, because  we're drawing it first. So your edge will still   show up. And that should now be a good way to  signify so save beat. There we go. We're typing.   Pete, is cool, okay. And if I click off of it,  okay, well, now I'm not typing anymore. And now   I am. And I can do backspace, and whatever.  And if I close it exits, and that's great. So   let's go ahead and handle the Save button.  And I kind of been putting it off because   working with external files and saving data  to a text file is just a few extra steps. And,   and we have to kind of choose what data to  store and in the right format. And it's a   it's a process. So let's get into it. Because  it's very important to the functionality of this,   obviously, being able to save your favorite  beats and come back and use them later is a   huge value add to this kind of thing. So we'll  come down here where we have our entry rectangle,   and we'll add a new one. And we can really do  these as LFS as well. And so we'll say l f.   Saving button, be very careful because now we have  a save button and a saving button. And we'll say   collide point with event dot pause. And if so  then what we want to do is kind of again, file   equals open, and our saved beats dot txt file.  But this time, remember, in the very beginning,   we read from it to store data into that variable.  Now we're going to do a W and that means we're   going to write to it. And what we're going to  do is we're going to take that saved beats,   save beats list that we made in the very  beginning. And we're going to append some   data to it. And if you remember  I know is a little while ago,   we said what we're going to be adding, we  always want to start this with a new line.   Because if you don't, then anytime you  save, then you could potentially be   saving onto the same file. And then the way  we're parsing data with like per line, storing   it as one entry in our list would get messed up.  So we'll do it this way. We'll do name, colon,   and then space. And then we'll do string brackets,  beat name. So this is what you entered will be   underscore name, okay. And then we'll do  comma, and then we'll do beats colon space,   curly brackets, beats, and do pay attention to  the format that you save it with. Because later,   we're going to kind of have to reverse  engineer this for our loading menu.   So we're saving everything we would need. We're  saving everything we would need to be able to   recall this later, we're saving the clicked list,  we're saving how many beats and beats per minute,   and then a name that we gave it to to be able  to save it. And so we're going to add this as   one item to our saved beats list, which means  it's going to be the format of a saved beat.   And then what we'll do is we'll say for i in  range, length of saved beats, there we go.   We want to do file dot write a string of saved  beats. And this is what you have to do because   to write to a txt file, it has to be a string.  So you have to make a string conversion of each   entry of your saved beats list. And then to get it  to save outside of that for loop, we're going to   do file dot close. And that'll close up the text  file, file the new data, and then we will go ahead   and close the menu. So now Save Menu equals false,  capital F false, because if you've just saved your   beat, there's really no reason to stay in there.  And then we'll set typing equal to false because   that's kind of our default and we'll clear out  the beat name variable. So this is kind of saying   you've accomplished what you're here to do. And  now even though we don't have a way of loading it   back in you can see we have an M Do you save beats  txt file right now let's go ahead and make one.   So let's make a beat. I'll just make it the  kind of like generic rock beat, I've been doing.   Sweet, I made a save beat ama call it  generic rock beat. And I'm gonna hit   Save beet. And let's see. Okay, it's  good sign, it didn't close anything.   Let's go ahead now and look at our text file,  so you can get an idea for how we're saving it.   Okay, this is pretty cool. Its name generic rock  beat, beats eight BPM, 240. And then selected   and this is the list, you can tell it's got all  of the hi hat. So that's what this first one is.   And they're all on, which is why they're all ones.  And then this is the snare I believe. And you can   see it's just the threes. So like, 12341234 for  the snare, the kick drum is one and then one, one.   So you can tell this is a list of everything  we would need to do to recreate that beat.   So once we've saved it, we could clear it out,  we could close it and move on with our lives.   And, and that's really cool. But we have no  way of loading it in yet. So that brings us to   the load menu. And I have been putting this  off because it is probably the trickiest one,   we have to take all of that information, we  stuffed in a text file, and we have to reverse   engineer it out of a text file. So let's get  started me complaining about it isn't going to   make it go any faster. So let's go into the draw  load menu function. Take a sip of water here.   Okay, so we have the back rectangle, and we have  the exit button, which is a good way to start.   I'm going to kind of poach the menu text from  up here and the saving text and kind of steal   those because we're going to just reuse them for a  menu text, which now will say load menu and select   a bit to load in, we'll just say load, that's  fine. They know what they're doing. And then   instead of saving button, we will say loading  button. And instead of saving text loading text,   and that will say load beat, and that will say  loading text, but the positions are probably good.   And then obviously, in addition  to exit button and everything,   we are going to need to do the loading  button as well. And I think we will want to   also return a delete button probably because maybe  you've put too many in here now. So let's just   also make a delete BTN. That'll be good. And  so we have a loading button. Let's go ahead   and add loading text. Let's go ahead  and make a delete button, delete BTN.   And where should we put this  Delete button Pygame dot   draw dot rect rect and screen  and gray you know how it be.   And let's put this one on the screen roughly.  So we'll do width divided by two to get the   middle point. And we'll do minus 400.  So kind of scoot ship left from there   with minus two minus 400 That'll be the starting  position. We'll put it a little bit lower. So   height times what should we do point nine. I don't  know get a little delirious is a long tutorial.   Okay, we'll make it solid. We'll make it round  rectangle. And we will just see where that is   how that looks and kind of go from there. I  don't know why I would put this at point nine   it should be at the same height as the load  button. But let's see. So if this is starting   at with minus 200 and this one starts at minus  400. It's 200. That's going to touch our loading   button. Let's try making this 500 I don't know  I'm playing around now I'm in uncharted waters.   Alright, so we need to add some text we need to  do delete text and put that on our delete button.   And that'll be label font dot render. And this  time we will do delete beat for the text. Delete,   beat. Okay, and then it should be white. And  first we need to do true for the anti alias   white. Come on Pete you knows and then screen dot  blitt and then delete text. delete text. Okay and   And for location on this, we just wanted to kind  of steal the x&y starting position from up here   CTRL C to the text and scooch it a little bit  inside. So let's see with now minus 500 instead   of 500. Let's do like 485 and then height  times oh, point seven five my friend. Okay.   And then plus 10. Let's, let's just see what we've  done. I think this is hideous, but let's do the   load menu. Load be honest, not the worst thing  in the world is it? Okay? That looks alright,   let's go ahead and scoot delete beat down a  little bit. What did we do for the other one   plus 30. We'll do plus 30 again. Okay, and now we  need to if exit button tuple has no attribute do   collide point well, who's a tuple? Here?  Exit button Pygame dot draw dot rect. I   don't fully understand why I  got that air. Load beat. Close.   Oh. So tuple object has no attribute  collide point I understand what that means.   But exit button is right here. Draw load menu,  exit button loading button, delete button. Oh,   maybe it's because we haven't told the  loading button function. It's getting a   few things yet. So hang on, we're returning  exit button loading button, delete button,   come down to where you call those menus.  And it's exit loading button and delete   button. And now the Close button should work  unless I'm crazy. And I am not. Alright. Good job.   Well, I might be but let's move on. Okay, so back  in the loading menu, we need to kind of set up a   area that is going to be where we display the info  from our loaded beats. So load menu, select a beat   to load we say that we put the text on the screen.  But we do not show currently, like the area where   the beats might be. So let's draw I think like  kind of a holding pen, like a rec outer rectangle   where all the data is going to be displayed. So  let's just do Pygame dot draw dot rect. for that.   Let me think what the right  way to do this would be?   Yeah, let's draw a holding pen, if you will.  And let's say pi Game dot draw dot rect. And   let's put it on the screen. And let's make it  gray. And let's give it 190 100 Plus, which   let's start at 190 200. Let's just see how that  looks. And let's make it I don't know, 1000 high   and 600 wide. I don't know I'm kind of conflicted  here. Because I want this to be I think like a   outline. But I don't know if it makes more  sense to have it like as a solid rectangle   for displaying the loaded beats. So whatever I  did that's hideous, let's fix this. Okay, let's   fix this rectangle, I think 190 90 We can make  it 1000 height will be fine. 600 should be fine.   Five and five is probably okay, I think what  we'll want to do load beat I think what we're   gonna do is just move load and delete lowered down  because I do like the idea of being able to show   quite a few different beats. So maybe instead  of point seven, five on these, we do try like   point nine or close to it. Let's scoot these down  and do like point. I don't know, eight, seven.   Let's try that point eight 7.8 7.87 plus  30. Let's take a look at that load beat.   There we go. That's not bad, actually.  Kind of that entry rectangle. And so   let's go ahead and call that something.  Let's call that. I don't know.   Beats rectangle. Loaded rectangle. We'll call it  loaded. Rectangle. rec angle. Yep. And I think we   want to return that too. Because if you clicked  in there somewhere, you'd probably be selecting   a beat. Okay. So let's come down to our  function where we grab stuff back delete button,   and we'll say load rectangle down there. Okay. Or  loaded it doesn't really matter. All right, and   And let's see about actually parsing data in this  draw load menu. So we have to kind of check on   what index has been selected. So first, you  know, we should do we have a text file with   one saved beat. Let's go and make a second  one. Okay, so let's just make this stupid.   It's not the worst, not the worst thing  in the world. But I'll just call this   Tom and clap. Save the beat. And let's go  ahead and close that and look at our text file.   So now you see we've got these two. And let's  say we have the load menu. And we want to parse   through the data of those two and show them on the  screen, we want to show how many beats they have.   We want to show their name, and everything. So  what we need to do is we need to start checking   on, like, how do we get the specific stuff inside  of those. And so let's just dive into it. There's   no easy way of doing this. So here's what we  do, we start and we say for beat, in range,   length of saved beats. So remember, save beats  is a list, where each item in the list is a long   string that has one of those saved beats in it. So  for beat in range length of save beats, and let's   just set up our rectangle, the display 10. So if  b is less than 10, meaning we'll start at zero.   Okay, beat clicked, is going to be equal to an  empty list. And we just kind of have to set up   some stuff to parse through this, it's a really  long string. So row text is going to be equal to   medium font dot render, and we're just going to  show what row this is. So it'll be F, and then   that's a format string, and there'll be bt plus  one, because it's going to start at zero. But   again, I don't really think we should say anything  is the zero with beat, it'll be the first beat.   And we'll say true and white. And we'll put that  on the screen. So screen dot blit. And we'll give   it the row text. And we'll put it at 200 100  plus the beat 200 100 plus the beat times 50.   So that's how we'll make this work for every  for 10. Because the rectangles like 600, high.   Alright, so that should be all we have  to do to put the row text on there.   But we have to start getting some indexes. So  this is where if you're familiar with string   manipulation, in Python, you'll be a little bit  ahead of the curve, because a lot of what you're   about to see might not make a ton of sense, unless  you're familiar with strings. So we need to figure   out where to start the name. And so we'll say  saved beats. So that is the list of all the beats   that we've saved, and then beat so we're calling  our specific string. And then we need to find the   index value. So this is where in that string,  we first see this specific substring. So the   index of name colon space, and you'll see why I  was so particular when we set up that write that   right instruction to the list, because we have  to replicate that in reverse to tear it apart.   Okay, and then because there are six characters  in this string, and a m, e, colon and space,   we're going to add a six right there. And  then the name index end, doo doo doo doo,   and is going to be equal to saved beats at beat  dot index. And then it's going to be so this   now is going to be where the next thing in our  string is added in. And so if you think about it,   I'll actually pull up the text file here. Name  ends when we get to colon space beats. So we   kind of have to do this thing where we check where  each piece of it starts and stops by doing this.   So beats just like that is going to be  where we want to end it. And then name text.   The actual text for each of these is going to be  equal to and we'll make this medium font so that   we can put it on screen dot render. And then the  text for it is going to be saved beats from apt   beat so that tells you which item to use. And then  we need to do what's going to be from name index   start and then colon name index end. And so this  might seem a little confusing, but we just what   we just did is say okay, take the list of all  the safe beats, choose it for the specific one   we're looking at and Then from where this name  text stops. So basically, the next character,   after this name, colon space appears all the way  up until this colon space beats appears. That is   the actual text that is the saved name for this  beat. And then we want it to be true, and then   White, and then we're putting it on the screen.  So screen dot blit. And it's going to be the name   text. And it's going to be comma, and then 240.  And then 100 plus bT times 50. That's not the   times there we go. Beat times 50. And so this  is just where we're putting the Rotex as well.   And let's go ahead and just start there. Because  I think if you're familiar with how this works,   when we go to the load menu, you can see we have  generic crack, beat, Tom and clap. And those   are the first and second names. That's really  great. So that's awesome. What we have to do now   is we have to figure out how to  parse the rest of the data because   that is just one of the items. And that's  great for showing them on the screen. But   we also need to figure out how to get the beats  per minute and the selected list out of there. So   this is going to be a little tricky. Bear with  me. And again, if you get lost in specifics,   be sure to slow the video down, rewatch the  parts that confuse you and feel free to ask your   questions in the comments below. All right, so  now what we're going to do is we're going to say   if zero is less than or equal to index, and we're  gonna get to this index variable we're about to   make in just a second. So if it's greater than  zero and less than the length of saved beats,   I'm typing all over the place, Shift Tab, get out  of here, there we go. And less than the length   of our saved beats file, so this means that you  currently have a beat selected, we're going to use   index as a way of selecting a specific beat. So  this, I'm going to put it up here, so we don't   forget to pass it in. But we are going to select  by clicking on one of those beat names, we're   going to select which one we want to load in. And  that's going to be the index variable. And then   based on what's been selected, we're going to need  to do some additional work. So we're going to need   to figure out where the index and for the beats  is. And that's going to be equal to saved beats   at our specific beat. So that's why we still want  it to be do wait a second, let's save beats. And   we want to add a second  condition here, and B is equal to   index. So that's why we're putting  this inside of our for loops still,   because this will check and see if while  we're getting the names for each beat,   this will check and see if we've also actively  selected a beat. And so and b is equal to index.   All right, then what we'll do is we'll say at that  dot index, so just like before, and now the next   one starts at colon space, make sure your string  in a string variable colon space BPM, because   this is where the beats per minute variable  starts. And so that makes the loaded beats,   loaded beats, which is a new variable  equal to integer of saved beats dot   beat, try and be very careful here because we have  to do this kind of double indexing thing again,   so it's not safe beats that be it save  beats at beat. And then we have to do from   name index end plus eight to beat index. And  so the reason it starts at name index end is   because or name index n plus eight characters is  because this is going to start with the colon. And   it's going to end eight characters later, which  is when the actual beats value starts. And that's   why we put an iron T in here to convert it to  a number. So what it's doing is we're indexing   from this character to this character, and we're  turning into a number so even though it looks like   eight as a number, this is actually inside  of a string. So it's just another string   character until we do that i n t. But now we're  getting back the loaded beats, which is great.   And we have to do basically the exact same thing  for the BPM so the BPM index end BPM, do index   end, which has a new variable as well, is going  to be equal to saved beats at beat. And then   it's going to be dot index. And this one is  going to be now when colon space selected,   I didn't put it in quotes again.  Here we go. When that appears,   that's going to be the index that's going to say,  Okay, this is the end of the BPM section selected,   and that's going to make the loaded be PMS equal  to pretty much the same thing as this loaded   beats just with different index value. So I'll  grab that. So this one is going to go from the   not from the name index, and but from the beats  index and and it's not going to be plus eight,   it's going to be plus six. I think I typed in  eight again, and then this one is going to go   until BPM index and beats index and interest,  dang, oh, it's just beat index. And there we go.   Okay, and so now we have the BPM, the beats  and the name of it. And what we don't have   is just the trickiest part, which is going to  be the selected list. So we have to now loaded   clicks, right, because we call it clicked  in the outside world. So loaded clicks,   and I'm gonna differentiate it at loaded clicks  as a string is going to be equal to saved beats,   at beat. And then we already actually have  all the info we need for the rest of this one,   it's going to be BPM index, and, but then this  one is going to be plus 14, okay, and I'm about   to explain why it's plus 14. And it's going to  go essentially to the end minus three characters.   And the reason for that is we need to do what's  called splitting the strings out. So if you say,   this is where it started, so 1-234-567-8910 1112  1314 characters before we get to the first one,   or minus one in our list, and then if  you go to the very end, we have a space   and then to end brackets at the very end, which  is why it goes to minus three, that's gonna give   us a string of all of our values. Now we have to  split that string into a list. And to do that,   we're going to use the built in Split function,  but we have to tell them what to separate each   list item on. So we're going to split it, we go  down to loaded, clicks, and we're going to call   this now a row rows, because we have to split this  twice, right, it's currently just one long string,   we need to split it into a list of strings, and  then we have to split each string into actual   ones and negative ones. So to do that, we create  this intermediate list, which will be loaded   clicks rows, and set equal to list. And then  inside of this, we do loaded, clicks string. And   then dot split is the built in function to split  a long string into a list. And it's going to be   open bracket like that, and then comma, and then  space, and then close bracket or backwards, close   bracket, comma, space open bracket. And the reason  for this is again, if we look at the text file,   what splits up in between each entry, each item in  that selected list is a closed bracket and then a   comma, and then a space and then open bracket. And  so that's what's going to split each item into its   own list item in here. Okay, so now, we get to  do some more complicated stuff. So bear with me.   And once we're through this, maybe really take a  look at what each line is doing and think about   what it's doing. And really trying to make sense  of it and then ask me if you still have questions   after that. But so for row in range, length of  the loaded clicks rows list that we just made.   So we're setting up a for loop to go  through there. And we're going to say,   if loaded. Clicks do to do here  we go. If loaded clicks row,   item. So item is just checking. We don't  want this to be row we want this to be item.   I'm getting ahead of myself that we do want  that to be row and we want to say loaded.   Clicks row Okay, is equal to, and I'm just going  to create another intermediate variable just to   get my head straight, because there's a lot of  words going on. So we'll say load clicks row   is equal to loaded, clicks, rows plural at that  specific row. And then what we're going to do   is we're going to split that row item split  out. And we're going to do it based on   a comma, and then a space. And the reason I  add the space is because when you do a split,   it's going to give each thing in between those  its own item in the list, but it's going to get   rid of this text that was in the string. So  we do it this way. And then that's going to   split it up and make a new list and that we're  going to store that and loaded clicks row.   And then what we're going to do is go through and  say for item, because they're not yet integers   in range, and it'll be the length of  the loaded clicks row that we just made.   Okay. And what we're going to do is we're  going to check if loaded clicks row singular,   at item, is equal to, and we'll check  if it's equal to the string of one,   or the string of negative one. And the reason  we're doing this is once this has been sorted   once, we don't want to run it again. So we'll say  or if loaded clicks item is equal to negative one,   because in theory, those are the only two  things the items should ever be equal to.   And we don't need another if we just need an  or. So if it's equal to a string value of one   or a string value of minus one, then what  we do is we say that loaded clicks row item   is equal to the integer value  of loaded clicks row, at item.   And the reason we're doing this, if check  is because once it's become an integer,   this won't execute anymore. So we don't have  to execute this anymore, because everything   is already an integer. All right. So that's why we  do that. And then we come out of the if and we say   that we want to track what beat was, what what  loaded in beat is, let me say this correctly,   we want to make a list of the clicked values of  what was loaded in. So if we have this loaded,   collect list that basically reflects the  outside clicked world, then we want to   make sure that we are appending at the right  time. So we'll come back up here to where we   did this beat clicked list. And we will  append each list in here. So we'll say   let me make sure I got my indentation, right  beat clicked dot append. And we're going to add   loaded clicks row, each time we do another row.  And then we'll say loaded click is equal to   beat clicked, there we go. And we'll  want to as well as the loaded rectangle,   we'll want to return the loaded clicked. But we  actually we need to return the loaded clicked,   and we need to return the beats and the BPM.  So let's make another variable out here.   And let's call it loaded info. And let's make  it a list. And so it'll have loaded beats in it.   It'll have loaded BPM in it, and it'll have  loaded click in it. Alright, but what we need   to do, because right now there's a reasonable  scenario where nothing has been selected yet.   And so these might not exist, because right now  the only place we define them is if something's   been selected, if we've set that index value, so  what we want to do in the very beginning, is just   initialize them like you would in the beginning of  your program, but we'll do it inside the function.   So loaded clicked equals zero, loaded beats equals  zero. Load collect is an empty list, not zero,   but you get the idea. And loaded BPM is equal to  zero. Okay, so we need to do those three things.   And then we pass it all back in loaded info. And  so we'll pass that back instead. So this was,   I know, one of the more complicated things we've  done manipulating strings like this is a little   bit tricky, but we actually did some really  advanced stuff here. So if you're a beginner,   you should congratulate yourself if you just  managed to follow along and understand most of   what we just did, because that's  some pretty tricky string work.   Now, we get to kind of go down to the event  handling and actually set up what we want   each of these things to do. So we come down  here to the area that's outside of checking   that it's not the Save Menu and load menu. So  it's the second part. And we will come on down,   doo doo doo doo if saving button client point  length file. Okay, so mouse button is up entry   rectangle. What we want to do now is we want to  say do L F, and what do we say loaded rectangle.   So if loaded rectangle was clicked, then we  want the index to be equal to, and we're going   to use that event position at one, which is the  y position, minus 100. And then we are going to   floor divide that by 50. And this will give us a  value one through 10 Telling us like where on the   wire on the y axis we just clicked. And we'll use  that index for what the active beat should be.   So let's come back up and loaded menu and use that  index to draw something that's going to indicate   the actively selected beat. Okay, so back in  our loaded menu, we're passing the index in,   let me make sure we're actually passing  it in though. Load menu drop down menu,   here we go. We want to make sure we pass that in.  And actually we don't, we don't initialize it in   the beginning, do we so let's call it up here,  we'll just say, index is initially equal to 100.   That way, it's not selected. Okay, and draw load  menu will say, Okay, if load menus is there,   but we want to use the index to draw a  rectangle on the screen, if it's in our range,   so underneath load rectangle, I will say if the  index if zero is less than or equal to the index,   and it's less than the length of our saved  beats list, so this is checking that we have   one is less than the length of our list, then  we will Pygame dot draw dot rect the screen,   we will make it let's do a light gray. So  this will be the last gray I add, I swear.   And we'll make it 190. And then we'll  have it start at 100 Plus index times 50.   And we will have it 1000 wide and 50 tall. So  light gray. Let's go ahead and define that up top.   And this again, it's moved in the opposite  direction of our basic gray. So light gray,   and this will be like oh, like a 171 7170 Okay,  and now I'm hoping when we do the load menu,   load beat broke something too many  values to unpack expected four,   because I don't think I told it to expect  loaded info coming back yet. So let's see.   Law load menu loaded info, and load  rectangle loaded info. Correct. There we go.   Load info. Alright, so now let's open up loaded  beat. Generic rock beat. Oh, string has no. Yeah,   sure did mean index I sure did. So let's go check  that out. And which one did I put index for?   index, index index. There we go. Alrighty, let's  try that again. Load beat, hey, we got a light   gray rectangle. If I click the top one, if I click  second one, if I click third one goes away great,   because there's no beat there. And I click those.  That's sweet. But we are not able to delete things   yet. And we're not able to load things in  yet. So let's keep working on the buttons.   All right, back to our event handling down here.  And there are maybe ways I could have set this   up differently. But I kind of did them as we got  to each event. So let's come down here and say,   All right, we have all these LFS  LFS loaded rectangle. Let's do l if   delete button dot collide  point with event dot position.   And then if we deleted something then what we want  to do is actually not too bad. It's if index. So   pretty much that same thing. If index is  between zero. So index needs to be greater   than or equal to zero. And index needs to  be less than the length of saved beats.   And I can say less than because the length of save  beats is always going to be one greater than the   largest index value of it. So if there are three  values in there, their indexes are 01, and two.   So what we'll do is we will just save  beats dot pop, whatever was at the index,   and that'll let us delete an entry.  That one's pretty easy. We'll highlight   the functionality of a few of these at the  same time. Once we get them working, Okay,   so next, let's do the loading button because that  one's kind of tricky. And we will do LF loading   button dot collide, point, event dot pause, that  part's easy. The next part is familiar. If zero   less than or equals to index  less than length of saved beats.   Then we're going to set a few of our variables  equal to the information that we pull in. So   beats is going to be equal to the loaded info  that we pass back, which I believe we just   called loaded info. Yep. Loaded info.  At zero, so the first thing was beats,   loaded info zero. And then the second thing  was bpm. And so that'll be loaded info at   one. And then the third was clicked, which will  be loaded info at two. And we will set the index   back equal to 100. So that's like an irrelevant  number. And then we will set load menu equal to   false just like we did when the save button was  pressed, because your work is kind of done now.   And we will, that should be all we have to do, I  believe. So let's go ahead and check it out. Now,   if we have got all of the functionality on  that load button, I think the Close button   was working I think we're able to click in  there. So right now looking at our screen,   we have nothing going on. There's nothing  loaded in if I load that generic rock beat in   well, I hit Load beaten nothing happened. It  did close load beat. Let's try Tom and clap.   Okay, close I can feel it but  no cigar. So what's going on?   Okay, I think the reason the loading button is not  working is we need we just did LF loaded rectangle   earlier, it needs to be LF loaded rectangle dot  collide point where with event dot position. So   I'm really amazed the indexing and highlighting  of the rectangles was working without this. But   that should let us load it in. So let's go ahead  and check load beat generic rock beat load beat.   There we go. And that's really sweet. Now let's  try clearing the board. That's also awesome. Let's   see if deleting one works. So let's get rid of Tom  and clap because this is kind of stupid anyways.   So let's go ahead and see if we can delete it.  And it looks like we got rid of it. Now let's   do something that uses more beats, and more beats  per minute. So let's do 24 Is that like a logical   thing and let's make this a higher number like  480 and see if that works. Okay, so we're at much   higher now. And let's just kind of put I'm gonna  turn it off just so there's not too much noise   for you guys. So that's eight. That's 1216 20.  And then for these last four, we'll do crashes.   Alright, and then let's do bass snare. Actually,  we're going to want to spread these out a little   bit, because it's sort of twice as fast as  a normal rock beat. So we'll do bass bass   snare. Take a pause and then we'll do bass bass,  snare tech pause, bass, bass snare, and then we'll   do Clap, clap, clap at the end. And we'll do four  times at the end. Let's see what the sound like   four times because we're hardcore.   Alright, so I'm gonna save this beef. I'm  just gonna call it out. You're bored CBT   so that's not working. Now. We need to figure  out why our CBT buttons aren't working.   What do we do to mess up the rest  of this collide point? Pause.   I think we don't want these all to be LFS  because technically they're in the same   spots. Let's see if that solves it.  I think that's it. causing us strife.   Let's check that out. Load beat   entry rectangles not to find something  strange is happening. Load beat   we need to check out why entry rectangle is  not defined. It's coming from Save Menu. Oh,   well, yeah, entry rectangle is  not going to be defined. Because   if Save menu is not true, then there's no rect. So  let's come down to the rectangles like this one.   And let's just add something here. That's if Save  menu. And then we'll put all of this inside of it.   And I think we'll want the same thing for these  three, because they're loading only. So we'll say   if load menu. So we do need to distinguish that we  don't want to check for anything with these three   buttons, if that is not true, and then hopefully  that will take care of it. So if we load in   saving button is not defined. But why do you  care? I thought I have you checked out so you   don't care. Oh, we want all of this inside the  same if Save menu. There we go. Let's try that   load beat Tom and clap. There it is. The Beat  load in generic rock beat let's load it in.   Yeah, that's hardcore. Alright, let's just make  it 12. And let's do something stupid. I don't   know it doesn't matter. Let's try to save this as  a longer beat. Let's save it. Let's see if we can   load in longer beat. Yeah, I'll go ahead and clear  this. I'll load in the generic rock beat a load   in the generic rock beat. Okay. I'll clear it out.  And I'll see if I can load in the longer beat.   And it makes it 12. All right. So we have  the ability to turn off individual channels,   we have the ability to play and pause we have  the ability to edit while something's active or   inactive. We have the ability to change how many  beats are in the loop, we have the ability to save   beats, we have the ability to load beats, we  have the ability to clear the board. This is   a really cool app. I had a ton of fun building  it. Obviously it's a challenging tutorial. I   know it's been a really long time. So if you stuck  it out the whole time. I hope you're enjoying it.   If you have any questions about things we  didn't cover or you'd like to see expanded upon,   or you tried this yourself and you're running  into snags, just let me know about in the   comments below. I'll get back to you as soon  as I can. I hope you enjoyed it. If you did,   please leave a like on the video subscribe  to my channel. It helps me out a ton.   And I post tons of great content just like  this every week. So without any further ado,   good luck with your projects and thanks for  watching. Take it easy until next time, bye
Info
Channel: freeCodeCamp.org
Views: 159,544
Rating: undefined out of 5
Keywords:
Id: F3J3PZj0zi0
Channel Id: undefined
Length: 168min 12sec (10092 seconds)
Published: Thu May 19 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.