 And here we go with the Ultimate Python Total Graphs Game Tutorial Part 15 drawing text. So let me show you what I mean by what we're going to do in this particular lesson. So I'm going to go back to the demo, and I'm going to run that real quick. And what I want to talk about is this text here. Okay, so you can see this is kind of an old school looking text. Everything's made out of straight lines. And I custom designed this myself. And you may be wondering why would I do something like that? So let me get rid of that. And the reason is that even though there is a built in text method to draw text to the screen, it really slows down the program. I don't know why it just does. If you've seen the introductory videos for this, I talked about it at length and I did some comparisons. So I'll try to remember to put the link down below. It's pretty interesting stuff actually. So what I'm going to do is I'm going to show you how to make your own custom font and draw it. So let's get started. So the first thing I need to do is I'm going to be creating a new class. And I'm going to call this character pen, not call it class, character pen. And it is not a child of any other class, I'm going to leave that blank. I could also just leave it like that, it doesn't really matter, but I like to put the parentheses there. And when we initialize it, what I want to do is put self and then I want to say color. And watch what I do here. I can't remember if I've done this earlier in this tutorial or not. And scale equals, let's see, 1.0 and some or a colon there. I've been doing a lot of C++ and C programs. You might see me throw a few semi-colons in here and there where they don't belong in Python. So what I've done here is I've said that we need a color and we need a scale. But by setting these default values, I've actually made them optional. So it's just kind of pretty cool. I'm going to say self.color equals color. And I'm going to say self.scale equals scale. Now I need to create a dictionary to hold all of my character data. So this is actually the long, hard part of this whole thing. It's not hard, just time-consuming. So for example, what I want to do is I'm going to make a character. And I'm going to make characters for the number one. And how I'm going to do that is I'm going to encode it in a tuple as a series of tuples representing relative x, y coordinates. And I'll explain that in a second here. So let me just leave that like that. I'm going to go over to this. So what I did was in my mind I said, OK, I'm going to make a default size for my characters. And I want them to be taller than they are wider. And I just came up with 10 wide by 20 tall. So I basically have this imaginary border here. So now in the case of the numeral one, what I want to do is I want to start here and I'm going to go over to here. So I'm going to go ahead and color that in. And I just did this all kind of in my head. Again, I'm not a font designer, but it kind of worked. And then I went over to here. And the way I have this working is it's got to be so that you don't pick up the pen. And that was a challenge in some cases. So there's my one. Now I could have put it here and gone out. I could have added a little bit extra. But that's what I want to do. So what we have to look at are the starting and ending points. I'm going to go ahead and color those in. I'll say make those orange so we know where and what they are. And again, it doesn't really matter exactly where you start as long as you can get there without picking up the pen. Now I know a way to get around that, but for this exercise, since I've already done it once, I'll just leave it this way. So what I want to do is, if you remember, 0, 0 was our center. So what I want to do is I'm going to start the pen at wherever the center is, negative 5 and 10. So I'm going to start here. Then I want to go to 0, 10. I want to go to 0, negative 10. I want to go to negative 5, negative 10. And then 5, negative 10. So these are just the x, y coordinates of the start and end of each line. So I've already done this in the other code. So there's no point in me typing everything over again. But let me just do that part with you again. So it was negative 5, 10. Then I went back to 0, 10. Then I went to 0, negative 10. Then I went to negative 5, negative 10. And then I went to plus 5, negative 10. So those are the x, y coordinates, again, of these spots. So basically what I did, we're going to be drawing the lines. It's actually way, way faster to draw these lines than it is to actually render the text normally, which is shocking. So I have all the characters. Now, I'm not going to sit through and go through them all. I've already done it. And so I'm just going to go ahead and copy that from my original version. So here's my one. And I'm just going to go ahead and copy this. And I didn't do all the characters. I just did the ones that I felt that I needed for the program. But you can feel free to go through and do whatever you like. And so I'll put this code in the link down below. So you're not trying to copy this from the screen, because that would be crazy. So this part here, again, it's just x and y, relative x and y coordinates from the center. And the relative part's really important, because we don't know where we're going to be drawing the characters on the screen. So that's the first part. So I've defined all of my shapes. Now, there's a way to do this with the built-in turtle module. But because I want this to be modular, I want to be able to port this to other platforms. You may port it to Pygame or something else like that. I use these numbers the way I did them. So next thing is I need a method to draw a character. And so what I've got to do is I do self, because again, this is inside of a class. Then I need to do I need a pen. So what pen am I going to be using to draw it with? I need the character, and I need its x and y coordinates. Now, this x and y coordinate is the center of that character. So remember, we're looking at this center. So all my x, y coordinates that I just entered are relative to the center. So the center is actually at 0, 0 on the screen. And of course, it's very easy to calculate these. But if we put a character over here on the screen, again, we have to calculate a little differently based on its starting location. So I need to set the scale, because we might want some characters to be bigger than others. And what I've done is to make sure I do this. Character equals character.upper. And what that does is it makes sure that every character is uppercase, because if you look here, I've only defined uppercase characters. I haven't defined lowercase characters, so we can't really use them. But actually, I'll talk about that in a minute. I do have a way around that. So what we need to do that is, first, I'm going to check if the character is in the dictionary of characters, because otherwise we'll get an error. So character in self.characters, otherwise we'll get an error. I'm going to say pen.penup, because we have to move to the start. And I'm going to say xy, what should I do here, equals self.characters.character, it's a little complicated in here, 0. So xy equals self.characters character 0. And what that does, if my character is a 1, it gives me this set of coordinates. So my xy is negative 5, 10. So what I can do here is now I'm going to say pen.goTo, and it is x plus xy, 0. Now watch this one, times scale, in this case, scales 1, so don't worry about that one. And y plus xy, 1, times scale. Let me explain that real quick, and I think we're good there. So I've taken this x-coordinate, so wherever I want to draw it on the screen, so this is the screen x, plus the relative xy, 0, which is in this case, it's going to be the first number, so this is the x. So in this case, it would be minus 3, so the center minus 3, times the scale. So if it's double scale, it would be minus 6. So I can actually make any size font out of this, which is pretty cool. And then I go to the screen y-coordinate, plus xy, 1, which gives me, in this case, it would be a 0, times scale, which is 0. So that's the center of that particular object. So I'm going to go to the starting point, and then I'm going to say pen.pendown. So now I'm going to put my pen down. So if I go back to here, wrong. If I go back to here, in Firefox, it's going to put me right here. So now I just got to draw all of my lines. So you're going to see a little loop here. So for i in range, oops, i in range, that's index, in this case, i in range, so this one was a little complicated, 1, because I'm starting at this character, not this set of coordinates, I'm starting at 1. And then I'm going to the length, self.characters, character. So the length of that particular character, because in this case, you can see a minus only has 2, but a z has 1, 2, 3, and 4. There's four different lines. And then all I got to do is go, basically just copy this. I can go, I can just copy this whole thing, because I'm going to be doing the same thing. Let's put x, y equals self.characters, pen.goToScale. And then when I'm done, I'm going to say pen.penUp. So that way I can go to the next character. Wow. Why don't we go ahead and test that, just to see if it's working. Well, first let me run this and see if there's any syntax errors. And this is always a good practice to test things. Over here, function f5. Sorry, it's been a while since I've used this, because I've been programming C++. All right, so it's still working. That's a good sign. I'm happy about that. So let's go ahead and just draw a character somewhere on the screen. So what I have to do is I have got to create a character pen somewhere in my game. So I think what I'm going to do is I'm going to go down to, I'm going to put it right here, just to make it easy. And I'm going to say character pen equals character. And note the capitalization. And what I want it to do, I'm going to make my letters. I can go ahead and make my letters red. But that's all right, let's just leave it as it is. So let's go ahead and do red. And let's do a scale of 3.0. So we'll make it kind of bigger on the screen. And then I can say character pen. Actually, if I do that, it's going to get erased. So let's go ahead and so I'm going to go down to my main loop. And just before update, so I'm going to put it here. And I'll explain why in a little bit. So draw the text here. So I'm going to say character pen, pen dot draw character. And I'll just put it in the middle. So I think it was pen. So it says here, self pen character xy. OK, so I'm going to draw a big x in the center of the screen. And we'll put it 0, 0. OK, so let's test that and see what happens. OK, character pen has no attributes. Draw a character. Now what did I do wrong? Character pen, draw a character. I spelled it wrong. Character, no I didn't. So let's go up to the class. Character pen. Oh, this is indented. So that was indented wrong, my bad. Very common mistake here. People email me constantly about indentation errors. I have a little video about it. That's what I'm going to send you if you email me about an indentation problem. So because it was indented under this, it was never actually defined. So let's go ahead and try that again. Catacors. So how many of you guys saw that before I did? OK, 141. Care actors. OK, and this is why we test our code. So function f5. OK, and I do not see my x. I do see this. So something's gone wrong, unfortunately. So it is working, but it's not drawing it how we would like it to draw it. Let's go ahead and take a look here. And OK, pen. Good self-character. OK, and let me make sure I did that correctly over here. Down here. The pen capital X, 0, 0. That is where I want it. And so let's go ahead and make sure. Let's make sure A that we have an x, which I think is pretty safe to assume. We find if I just forgot the x. No, there's the x. That's a good sign. And then scale. Yeah, we did that. Care for that upper. Character in self.characters. Now, if you've solved it, good for you. Ah, OK, that's why I went wrong. Character I. OK, that should be an I there, not a 0. That's one of the dangers when you copy and paste if you forget to make the necessary changes. So I don't want to draw it from the first set of coordinates to the first set of coordinates to the first set of coordinates. I'm going to draw it from here to here to here to here. So again, now notice, I made a mistake. I just looked through the code. And there's only one possible place where this problem could have been. It was either in the class or it was down in the other statement. So let that be a good lesson on debugging. OK, and there is my big x on the screen. It's a little bit big. So that's stage one. So that lets us draw a character on the screen. But what we need to do, this is a bit of a long one, is we also need to be able to draw multiple characters on the screen. So I'm going to say def draw, I'm going to call it drawString. And it's going to be self, of course, pen. And then we're going to be drawing a string. So it might be a word like player or something like that. And then again, x, y. Now in this case, this x, y is going to be, just to make life easy, is going to be the center of that string. So watch what I do here. So I'm going to set the pen.width to two pixels. I'm going to say pen.color to self.color. So that's whatever color I set my object to earlier. And watch what I do here. I'm going to center the text. Now if you recall, the width of the character was 0 to, so it's 10. So what I need to do then is I need to add a little bit of extra space between the characters. So what I'm doing is it's going to be 10 plus 5 more. So there will be a little bit of a gap between the characters. It'll be consistent between each characters. So I'm going to say x minus equals 15 times self.scale times, because we might make it bigger. So self.scale times the length of the string minus 1 and divide it by 2. Now again, I've calculated this all out ahead. That's why I know it. But it took me a very long time to get this to work. So basically, we're looking at the length of the string. So if there's 10 characters, we're going to move all the weights to the left by 9 divided by 2 characters, so 4 and 1 half. Again, I just calculated this. It works out really, really well. You can play with that if you feel it doesn't. You don't like it. So then once we've set the starting point, the x starting point, but y is not going to change, we're going to say 4 character in str. And then watch this, self.drawCharacter. We're going to use this method here, penCharacter. And that's going to be x comma y. So the y doesn't change. Y is always going to be the center of where we hold it. And then we say x plus equals 15 times self.scale. And that's it. So this little piece of code will let us draw text anywhere on the screen. So I'm going to test this out by going down to my thing here. So instead of draw a character, I'm going to draw a string. And I'm going to say, I'll say, call it at Tokyo eddeck. And let's see what happens. So hopefully that will draw that right in the center of the screen. And there we go. There is my font that I created. And it stays on the screen. Again, we don't want it there for now. But it is something. And you see how this got changed. You might want to fix that later. But anyway, so that, whoops, sorry. I accidentally stopped the screen recording there. So I think I was saying, so that is how we put some text on the screen centered. So what we've got to do is to use that to display that side, I don't know what you want to call it, side panel. So I'm going to go ahead and run this. I'm going to show you. OK, I'm going to get past that. So what I want to do is I want to work on this section here. So I want to put the game name here. I'm going to put score, enemies, lives, and level. OK, so I'm going to close that. OK, let's get rid of that sound. So what I want to do is in my game class. Oops, I want to go back to spacer into 15 here. Sorry, that was the demo. So in my game class, which is way up the top, I'm just going to click here, I'm tired of scrolling. So you see where we have render border? I'm also going to make a method called render info. So I'm going to say def render info. That's going to be self. And I'm going to say pen, score. And I think later I'm going to add active enemies. But I think for now I don't really have that. We haven't calculated that yet. So I'm going to go pen.color. And again, this is just the color that I used. And you can use HTML hex codes. So this is that blue color that I chose. Pen.penup and pen.gotue. Now again, I calculated all these things a long time ago when I did the demo. So I just had to play around with it until I got it right. So I'm going to make a pen shape square. I'm going to say pen.set heading to 90. And this will make sure that the square is aligned vertically and horizontally. And then pen.shapeSize, I'm going to set it to 10 by 32 and no outline. And you'll see what that does in a second. I'm going to put pen.stamp. So what I want to do is I'm going to go all the way back down here. And I'm going to say, I'm going to get rid of this thing because I don't need it anymore. But what I want to do is I'm going to say game.renderInfo. Oops, I think it was pen. And I think the score, we'll say score of 0, we'll say enemies with 0 as well. So I'm going to run that, see what happens. Bad color string. OK, I've got too many things there. Game.renderInfo. And this is where this starts to come in handy. You're not scrolling constantly. Put too many 2s in there. Let's try that again. So that gives us this thing over here. And now you can see we still have the radar. Now as you see, the problem with the radar is now invisible. So let me go ahead and find, where did I do the radar? So radar, radar, radar, radar, yeah, render. And where is the drawRadarCircle? So I forgot to set the color. I'm just going to say pen.color, white. So let's test it. OK, and there's the border of our radar. Now the reason earlier, I think I mentioned it in passing, was I didn't put the rate. I put this before I put the radar. Because if I do that, watch what happens. I run it now. The radar is hidden. It's actually behind this big panel. So we're putting stuff on top of stuff, on top of stuff. So the order that we render is really important. So I'm going to go ahead and put that back where it belongs. And so now I just need to finish up this renderInfo method. So I'm going to go back up to game and renderInfo. Oops, where was it? There it is. So then watch what I do here. I'm going to say pen.color, white. And oh, actually, I'm going to put that line there for you. Pen.width, 3. Pen.goTo, 300, 400. And again, I calculated all these things earlier. Pen.penDown, and I'm going to say pen.goTo, 300, negative 400. So let's just run that, just to show you what I did. So what I did is I put this down here. And so now we have a nice panel. And then notice, even though I move this around, I don't see it because this is drawn after this section of the screen. It's there. It's just you don't see it because we drew all this on top of that. So that's pretty cool. And then the next part we've got to do is pen.penUp, pen.color, whites, I'm going to put it to whites. It may not matter, actually. Pen.goTo, I'm going to do 400, 250. I'm not sure what this is. And pen.goTo, I'm not sure why I'm doing this. I don't think I need that. Let's get rid of those. I had them in the original program, but I think I don't need those anymore. So let's try this. So then I'm just going to start drawing stuff. I'm going to say my character pen.scale equals 1.0. So I don't want my text to be too soft. So I'm going to say character pen.drawString, pen. I'm going to say space arena. And that's going to be at 400, 270. 400, 270. So I'm just going to test it. So that works. Then we can use that as a model. And there is my space arena text. OK. And then I'm just going to go ahead and draw all the rest of the stuff. Some of this may or may not work because the program is not done yet, but let's give it a shot. And so I'm going to go ahead and delete that. Delete that. So I can just copy and paste it. Oops. That's not what I wanted to do. And this is a pretty long one. But I think it's pretty interesting how this worked out. I mean, I spent so much time. I mean, I spent like a couple of days on this thing. This was crazy. Score. So score. And oops, I can't do that one. parentheses.format.score. And we'll fix all this stuff later. And again, I just played around with the numbers till I got what I needed. And the next one is going to be enemies. You can see here why I used active enemies. You can see why I used the centering because it makes it easier. And we could make that an option if we wanted to. That's something we could code later. Enemies, lives. And actually, I'm going to leave it like that. You'll see there's going to be some problems here. Format. What did I put here? Player.lives. Do we do lives yet? I'm kind of losing track because I haven't done anything on this for a week because I've been so busy with grad school. 180. Again, I'm just kind of copying this from what I did before. And I think level is the last one. And that format, I think it was game.level. And that one's going to go at 450, 450. I think it was 30 between each of those. And then this one we don't need. Now I'm going to go ahead and run this. I'm going to show you where there's a slight problem in the program. Something's missing. But we'll fix that in a sec. Invalid syntax. CharacterPanDrawString. CharacterPanDrawString. And that is line 104. So probably what I did was I missed a parenthesis. Yeah, missed a parenthesis. Let's try it again. And there we have our text. Well, actually, so everything did print out, which is kind of cool. I forgot I had to fix that. But what I wanted to do is I wanted to give the ability to actually print lower case letters. And that's a very easy fix. So I'm going to go down to my character class. And what I can do here is I can go if character in, vcd, def, gh, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, n, z. So if the character is in that list of lower case characters, what I'm going to do is I'm going to say self.scale times equals 0.8. So I'm going to temporarily, not self.scale, I'm going to say scale. So I want to make the lower case character 80% the size of the upper case character. That's it. So let's go ahead and run that. And you can see now they are a little bit lower. You may not like that effect. You might, you might not. It's really up to you. So I'm going to go back down to the bottom here. Or I'll say I'm going to back up to the top here. And in the render, I'm going to make everything capitalized. I think it looks a little bit better, to be honest. But it does have that option if you'd like to use it. And I think that's really it for this particular lesson. This is a long one. So I'm going to go ahead and just run it real quick, show you one more time what we did. So we went ahead and we created a character pen class. We created a character pen. We made some methods, such as draw character. We defined our characters as x, y coordinates, or changes, or delta x and delta y, really, from the center of the character space. And then we drew it going across using the draw string method. So again, this whole program here, 15, it'll be in the GitHub, link is below. I'll put the actual just this. I think you can just go ahead and copy it from there. If you want to try it yourself, you can go ahead and just copy this out of there as well. And that'll keep it simple for everybody. And that is it. That is how we draw our own custom font. So you can go ahead and make your own custom font, which is really, it's actually really fun to do. And you can really, really customize it to look as awesome as you would like. OK, so I hope you learned a lot. Stay tuned for more, subscribe for updates, and click like. Thanks, bye-bye.