1 00:00:00,000 --> 00:00:00,315 2 00:00:00,315 --> 00:00:02,190 SPEAKER: So with pong2, we took a look at how 3 00:00:02,190 --> 00:00:05,190 to actually get something more visually interesting on the screen. 4 00:00:05,190 --> 00:00:08,537 We ended up using love.graphics.rectangle with the line 5 00:00:08,537 --> 00:00:10,620 and fill options just to illustrate the difference 6 00:00:10,620 --> 00:00:12,150 to get paddles onto the screen. 7 00:00:12,150 --> 00:00:13,989 Now they're not actually functional yet. 8 00:00:13,989 --> 00:00:16,239 And that's going to be part of the goal of this update 9 00:00:16,239 --> 00:00:17,790 to actually move the paddles. 10 00:00:17,790 --> 00:00:19,590 We also ended up drawing the ball. 11 00:00:19,590 --> 00:00:22,200 And we chose a different custom font, and we 12 00:00:22,200 --> 00:00:24,210 put that a little bit higher up on the screen. 13 00:00:24,210 --> 00:00:26,850 Now you'll notice this is pretty largely similar here 14 00:00:26,850 --> 00:00:28,392 on this exact example, the slide. 15 00:00:28,392 --> 00:00:30,600 We can't really illustrate the moving of the paddles. 16 00:00:30,600 --> 00:00:33,392 But we also are going to add the score in the middle of the screen. 17 00:00:33,392 --> 00:00:35,520 And we're going to use a larger version of the font 18 00:00:35,520 --> 00:00:37,710 that we imported from the last example. 19 00:00:37,710 --> 00:00:39,460 And it's incredibly easy to do so. 20 00:00:39,460 --> 00:00:41,760 And it will also let us illustrate how to actually sort 21 00:00:41,760 --> 00:00:44,280 of flick those state machine switches to change 22 00:00:44,280 --> 00:00:47,110 the font-rendering mode of the program. 23 00:00:47,110 --> 00:00:49,860 We only have one important function to talk about in this example, 24 00:00:49,860 --> 00:00:52,180 and that's love.keyboard.isDown. 25 00:00:52,180 --> 00:00:57,210 It takes a key as a parameter, which is a string just like love.keypressed. 26 00:00:57,210 --> 00:01:00,420 The difference between love.keypressed and love.keyboard.isDown 27 00:01:00,420 --> 00:01:03,240 is love.keypressed is a function, a callback function, that we, 28 00:01:03,240 --> 00:01:05,340 ourselves, sort of override, we implemented, 29 00:01:05,340 --> 00:01:07,530 and we sort of defined the custom behavior. 30 00:01:07,530 --> 00:01:10,890 Love.keyboard.isDown is just a function we can call anywhere 31 00:01:10,890 --> 00:01:13,260 and returns a Boolean, depending on whether or not 32 00:01:13,260 --> 00:01:14,528 that key is pressed down. 33 00:01:14,528 --> 00:01:16,820 We can call that in any other function that we want to. 34 00:01:16,820 --> 00:01:21,150 Another difference is that love.keypressed is actually 35 00:01:21,150 --> 00:01:26,070 just a single fired function, so it'll only fire if we press a key one time. 36 00:01:26,070 --> 00:01:28,920 And we can't check to see whether a key is actually being held down. 37 00:01:28,920 --> 00:01:32,760 Now when we move our paddles, we do want the movement to be more continuous. 38 00:01:32,760 --> 00:01:36,407 If up is being held down, we want to move the right paddle up and down, 39 00:01:36,407 --> 00:01:39,240 as long as it's being held down, and same thing for the left paddle. 40 00:01:39,240 --> 00:01:42,060 And we're going to use WNS for that. 41 00:01:42,060 --> 00:01:46,620 So I've already set up a distro here, sort of a folder here with some code. 42 00:01:46,620 --> 00:01:51,420 We took the code from the last example but given in the distro for pong2. 43 00:01:51,420 --> 00:01:53,760 And we're going to add our own custom functionality. 44 00:01:53,760 --> 00:01:56,610 So the first thing that I want to do is we have a small font 45 00:01:56,610 --> 00:01:59,560 for Hello Pong written at the top. 46 00:01:59,560 --> 00:02:01,687 But I want a different font for the actual score. 47 00:02:01,687 --> 00:02:04,020 So what I'm going to do is I'm going to say a Largefont. 48 00:02:04,020 --> 00:02:07,080 We can call this scoreFont, which is probably what it is in the distro. 49 00:02:07,080 --> 00:02:08,788 So actually, that's what I'm going to do. 50 00:02:08,788 --> 00:02:12,370 I'm going to say scoreFont is equal to love.graphics.newFont. 51 00:02:12,370 --> 00:02:15,720 We're going to actually use the same file, font.ttf. 52 00:02:15,720 --> 00:02:18,600 And I'm going to say that this should be a 32 pixel size font. 53 00:02:18,600 --> 00:02:25,110 So now what we do, if I say love.graphics.setFont of scoreFont here 54 00:02:25,110 --> 00:02:26,790 just as a test-- 55 00:02:26,790 --> 00:02:27,290 whoops. 56 00:02:27,290 --> 00:02:28,480 And that did not work. 57 00:02:28,480 --> 00:02:30,930 So let's go ahead down here. 58 00:02:30,930 --> 00:02:34,710 And I'm realizing that this is actually still derived 59 00:02:34,710 --> 00:02:40,290 from the older distro, which doesn't have everything divided by 255. 60 00:02:40,290 --> 00:02:41,350 You do have to do that. 61 00:02:41,350 --> 00:02:44,343 So there we have Hello Pong written out in large text. 62 00:02:44,343 --> 00:02:46,760 Now we don't want that obviously for our final thing here. 63 00:02:46,760 --> 00:02:48,635 So what I'm going to is I'm going to go back. 64 00:02:48,635 --> 00:02:54,840 I'm going to set the font here to the smallFont. 65 00:02:54,840 --> 00:02:58,920 And the scoreFont is only going to get set when we draw the score. 66 00:02:58,920 --> 00:03:02,610 So actually, I'm going to get rid of this all together, 67 00:03:02,610 --> 00:03:04,740 the love.graphics.setFont. 68 00:03:04,740 --> 00:03:09,180 I'm going to come down here and where I actually draw the Hello Pong, 69 00:03:09,180 --> 00:03:13,500 I'm just going to say love.graphics.setFont smallFont, which 70 00:03:13,500 --> 00:03:15,150 functions identically, more or less. 71 00:03:15,150 --> 00:03:16,620 But now it's more localized. 72 00:03:16,620 --> 00:03:19,948 So when we actually are going to draw Hello Pong, we change the font. 73 00:03:19,948 --> 00:03:22,740 When we want to draw the score, well, that's a different situation. 74 00:03:22,740 --> 00:03:29,430 So here, I can say love.graphics.setFont of scoreFont. 75 00:03:29,430 --> 00:03:34,888 And let's say I want to draw love.graphics.print. 76 00:03:34,888 --> 00:03:36,930 I'm just going to do love.graphics.print for now. 77 00:03:36,930 --> 00:03:38,370 I'm not going to do printf. 78 00:03:38,370 --> 00:03:41,575 I'm going to say, well, actually we need a score to draw. 79 00:03:41,575 --> 00:03:43,950 So why don't we go ahead and set that up here at the top? 80 00:03:43,950 --> 00:03:47,790 So I'm going to say here in love.load, I'm 81 00:03:47,790 --> 00:03:52,770 going to say player1Score is going to be equal to 0, 82 00:03:52,770 --> 00:03:55,710 and player2Score is going to be equal to 0. 83 00:03:55,710 --> 00:03:58,900 So now we have a score that we can actually draw to the screen. 84 00:03:58,900 --> 00:04:00,260 So let's go ahead and do that. 85 00:04:00,260 --> 00:04:03,660 So I'm going to say love.graphics.print player1Score. 86 00:04:03,660 --> 00:04:08,610 And I want to print this at, let's say, VIRTUAL_WIDTH divided by 2 minus 50. 87 00:04:08,610 --> 00:04:13,200 And let's say VIRTUAL_HEIGHT divided by 2-- 88 00:04:13,200 --> 00:04:15,330 let's say VIRTUAL_HEIGHT divided by 3. 89 00:04:15,330 --> 00:04:17,860 Let's draw it about a third of the way down the screen. 90 00:04:17,860 --> 00:04:21,870 And let's do the same thing here, love.graphics.print of player2Score-- 91 00:04:21,870 --> 00:04:22,800 if I can type-- 92 00:04:22,800 --> 00:04:24,180 player2Score. 93 00:04:24,180 --> 00:04:27,120 VIRTUAL_WIDTH divided by 2 plus 30. 94 00:04:27,120 --> 00:04:30,770 VIRTUAL_HEIGHT divided by 3. 95 00:04:30,770 --> 00:04:32,120 And let's just test this out. 96 00:04:32,120 --> 00:04:33,427 Let's see if it works. 97 00:04:33,427 --> 00:04:34,010 Let's do that. 98 00:04:34,010 --> 00:04:36,380 Yeah, and it works pretty well, pretty perfectly. 99 00:04:36,380 --> 00:04:37,000 Awesome. 100 00:04:37,000 --> 00:04:39,440 So let's go back to over here. 101 00:04:39,440 --> 00:04:44,190 Now the next thing that I want to do is actually get the paddles moving. 102 00:04:44,190 --> 00:04:47,555 In order to do that, what I need to do is say-- 103 00:04:47,555 --> 00:04:49,940 well, first of all, we've already been keeping 104 00:04:49,940 --> 00:04:52,980 track of where the paddles should be drawn on the y-axis. 105 00:04:52,980 --> 00:04:57,260 And this is important because the paddles are only aligned to the y-axis. 106 00:04:57,260 --> 00:04:59,750 They don't move left and right, which is the x-axis. 107 00:04:59,750 --> 00:05:01,307 They only move up and down. 108 00:05:01,307 --> 00:05:03,140 So we need a way to sort of manipulate that. 109 00:05:03,140 --> 00:05:06,080 That should be a variable now, instead of just a static number. 110 00:05:06,080 --> 00:05:10,520 What we've done thus far is actually set this VIRTUAL_HEIGHT minus 50 111 00:05:10,520 --> 00:05:13,130 and VIRTUAL_HEIGHT divided by 2 minus 2-- 112 00:05:13,130 --> 00:05:15,020 sorry, that's the ball. 113 00:05:15,020 --> 00:05:19,490 The paddle here is at 10, 30, so 30 being the left paddles 114 00:05:19,490 --> 00:05:24,560 y-axis coordinate and VIRTUAL_HEIGHT minus 50 being the right paddle's 115 00:05:24,560 --> 00:05:25,145 y-coordinate. 116 00:05:25,145 --> 00:05:26,520 So I'm just going to change that. 117 00:05:26,520 --> 00:05:28,670 I'm going to say that this should be player1, 118 00:05:28,670 --> 00:05:32,840 let's just say Y, and player2Y right here. 119 00:05:32,840 --> 00:05:33,710 Just like that. 120 00:05:33,710 --> 00:05:35,780 Now we don't have those declared just yet. 121 00:05:35,780 --> 00:05:37,447 So I'm going to declare them right here. 122 00:05:37,447 --> 00:05:40,410 I'm going to say player1Y is going to be equal to 30. 123 00:05:40,410 --> 00:05:45,588 And player2Y should be equal to VIRTUAL_HEIGHT minus 40. 124 00:05:45,588 --> 00:05:46,880 So let's go ahead and run this. 125 00:05:46,880 --> 00:05:47,750 Make sure it works. 126 00:05:47,750 --> 00:05:50,540 It looks like it still does more or less work the same exact way. 127 00:05:50,540 --> 00:05:55,160 Now, the trickier part is going to be actually manipulating this value. 128 00:05:55,160 --> 00:05:58,280 And this is something where we actually haven't used this function yet. 129 00:05:58,280 --> 00:06:01,910 But this is a very important part of the game loop that we alluded to before. 130 00:06:01,910 --> 00:06:03,650 And this is the update function. 131 00:06:03,650 --> 00:06:07,430 So anytime, you want to actually change the position or the configuration 132 00:06:07,430 --> 00:06:11,240 or anything about your game, typically depending upon user input 133 00:06:11,240 --> 00:06:13,310 but also dependent upon the sort of AI that you 134 00:06:13,310 --> 00:06:17,750 have running in the background, you want to override love.update, which 135 00:06:17,750 --> 00:06:19,910 should take in a parameter called dt. 136 00:06:19,910 --> 00:06:22,400 Now dt is very interesting. 137 00:06:22,400 --> 00:06:25,400 dt is what actually allows you to move things 138 00:06:25,400 --> 00:06:29,412 independent of the frame rate at which you're running your application. 139 00:06:29,412 --> 00:06:32,120 It's often the case, or was often the case, that back in the day, 140 00:06:32,120 --> 00:06:34,145 especially for older consoles like the NES, 141 00:06:34,145 --> 00:06:36,020 even to this day really for hardware that you 142 00:06:36,020 --> 00:06:39,950 know is going to run a particular way, you can just calculate everything 143 00:06:39,950 --> 00:06:43,220 on a per frame basis and not worry about how much time has 144 00:06:43,220 --> 00:06:45,140 passed since the last frame. 145 00:06:45,140 --> 00:06:47,120 If you're running this on multiple computers 146 00:06:47,120 --> 00:06:49,370 that might be at different speeds, then the frame rate 147 00:06:49,370 --> 00:06:53,150 might actually vary depending on the power of the CPU and the GPU. 148 00:06:53,150 --> 00:06:57,980 So in order to sort of normalize this, you multiply all of the calculations 149 00:06:57,980 --> 00:07:00,950 that you want to have happen by the amount of time that's 150 00:07:00,950 --> 00:07:02,720 passed since the last frame. 151 00:07:02,720 --> 00:07:08,600 So this might be 0.016 or whatever the amount is, every 1/60 of a second. 152 00:07:08,600 --> 00:07:10,548 It might be like 30 frames has passed, or it 153 00:07:10,548 --> 00:07:13,340 might be like it's calculating 30 frames because twice the time has 154 00:07:13,340 --> 00:07:15,350 elapsed since the last frame. 155 00:07:15,350 --> 00:07:19,080 And so you might want something to move twice the distance to account for that. 156 00:07:19,080 --> 00:07:21,710 Otherwise, you'll experience slowdown in your game 157 00:07:21,710 --> 00:07:23,918 because fewer frames are actually elapsing over time. 158 00:07:23,918 --> 00:07:26,418 It gives you the feeling that your game is actually lagging. 159 00:07:26,418 --> 00:07:27,380 So that's what dt is. 160 00:07:27,380 --> 00:07:29,330 It's sort of a normalizing scale factor. 161 00:07:29,330 --> 00:07:32,270 And we're going to use that to calculate our movements such 162 00:07:32,270 --> 00:07:34,970 that it's uniform across all computers. 163 00:07:34,970 --> 00:07:41,780 So what I can do is I can say if love.keyboard.isDown, let's just say w. 164 00:07:41,780 --> 00:07:46,070 So for WASD, it's very common for games on computers to be WASD for movement. 165 00:07:46,070 --> 00:07:48,980 We're going to also use the arrow keys for the right paddle-- so WASD 166 00:07:48,980 --> 00:07:50,660 for the left, arrow keys for the right. 167 00:07:50,660 --> 00:07:54,710 So if love.keyboard.isDown w then. 168 00:07:54,710 --> 00:08:01,910 And then, we'll also say just in advance elseif love.keyboard.isDown s. 169 00:08:01,910 --> 00:08:03,980 So they're mutually exclusive in this case. 170 00:08:03,980 --> 00:08:06,350 One or the other will trigger but not both. 171 00:08:06,350 --> 00:08:11,600 And I'm actually going to also set it up here, love.keyboard.isDown of up, 172 00:08:11,600 --> 00:08:19,100 so up for the arrow key up then elseif love.keyboard.isDown down then-- 173 00:08:19,100 --> 00:08:21,470 and you'll notice the elseif does not have a space. 174 00:08:21,470 --> 00:08:24,560 That is a Lua syntactical feature. 175 00:08:24,560 --> 00:08:26,810 Make sure that there is no space therein. 176 00:08:26,810 --> 00:08:32,782 So if love.keyboard.isDown w then, well, we need to manipulate the player1Y. 177 00:08:32,782 --> 00:08:33,740 So we can say player1Y. 178 00:08:33,740 --> 00:08:37,130 179 00:08:37,130 --> 00:08:39,020 And w means up. 180 00:08:39,020 --> 00:08:41,720 So remember y going up is actually negative, 181 00:08:41,720 --> 00:08:45,440 so we need to subtract some value from the player1's y-axis. 182 00:08:45,440 --> 00:08:48,450 So we'll say player 1's y-coordinates. 183 00:08:48,450 --> 00:08:52,790 So we'll say player1Y equals player1Y minus. 184 00:08:52,790 --> 00:08:55,805 And then we need some value, some sort of speed. 185 00:08:55,805 --> 00:08:56,930 So let's define a constant. 186 00:08:56,930 --> 00:08:59,270 Let's just say paddle speed up here. 187 00:08:59,270 --> 00:09:03,080 So we'll say PADDLE_SPEED is equal to 200. 188 00:09:03,080 --> 00:09:06,380 And this is going to equate to 200 pixels per second. 189 00:09:06,380 --> 00:09:09,200 So we'll say PADDLE_SPEED is equal to 200. 190 00:09:09,200 --> 00:09:13,280 We'll say minus PADDLE_SPEED if I can type. 191 00:09:13,280 --> 00:09:17,300 And then, again, this needs to be scaled by delta time 192 00:09:17,300 --> 00:09:19,730 such that it's uniform across all frame rates. 193 00:09:19,730 --> 00:09:22,520 So we're just going to multiply PADDLE_SPEED by delta time. 194 00:09:22,520 --> 00:09:24,350 And that will have the effect of ensuring 195 00:09:24,350 --> 00:09:28,100 that the paddle moves at 200 pixels per second regardless of the frame rate. 196 00:09:28,100 --> 00:09:31,250 Even if it's at 1 frame per second, that dt 197 00:09:31,250 --> 00:09:33,740 will become 1 because 1 second has elapsed. 198 00:09:33,740 --> 00:09:36,730 Therefore, it'll still move 200 pixels per second. 199 00:09:36,730 --> 00:09:38,480 We'll do the same thing here with player1Y 200 00:09:38,480 --> 00:09:45,420 is equal to player1Y plus PADDLE_SPEED times delta time for going down. 201 00:09:45,420 --> 00:09:46,730 So again, up is negative. 202 00:09:46,730 --> 00:09:48,140 Down is positive. 203 00:09:48,140 --> 00:09:54,590 And then we'll say player2Y is equal to player2Y minus PADDLE_SPEED times dt 204 00:09:54,590 --> 00:09:55,820 here. 205 00:09:55,820 --> 00:10:03,770 And player2Y is equal to player2Y plus PADDLE_SPEED times dt here. 206 00:10:03,770 --> 00:10:08,120 Now just make sure that I have also set player1 and player2Y there, 207 00:10:08,120 --> 00:10:08,750 which I have. 208 00:10:08,750 --> 00:10:11,090 And let's run this just to make sure it works. 209 00:10:11,090 --> 00:10:14,580 And I'm pressing up and down, and the paddle is moving on the right. 210 00:10:14,580 --> 00:10:17,660 And if I press w and s, the paddle is moving on the left. 211 00:10:17,660 --> 00:10:21,620 Now you'll notice, we can move beyond the edges of the screen, which 212 00:10:21,620 --> 00:10:23,630 is probably not desirable behavior. 213 00:10:23,630 --> 00:10:26,070 And we're going to get to covering that very soon here. 214 00:10:26,070 --> 00:10:29,270 So let's go over to the slide deck and then just as a teaser. 215 00:10:29,270 --> 00:10:31,490 The next section-- before we actually get 216 00:10:31,490 --> 00:10:35,030 into clamping the value of the paddles, and we actually 217 00:10:35,030 --> 00:10:36,920 might explore that in the next section, we're 218 00:10:36,920 --> 00:10:39,253 going to talk about how to actually get the ball moving. 219 00:10:39,253 --> 00:10:43,040 So you'll notice that, currently, the ball is still completely static. 220 00:10:43,040 --> 00:10:43,890 That's not changed. 221 00:10:43,890 --> 00:10:46,098 And that's really the main driver of our application. 222 00:10:46,098 --> 00:10:49,100 So in the next update, we're going to apply a random velocity 223 00:10:49,100 --> 00:10:53,030 to our ball such that we have now not the paddles but also the ball moving. 224 00:10:53,030 --> 00:10:55,885 So stay tuned for pong4. 225 00:10:55,885 --> 00:10:57,000