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