Complete Front-End Project: Build a Game Init the Project
Transcript from the "Init the Project" Lesson
>> All right, so we're here on Init the Project. So we're going to go into our VS Code here. So I'm gonna save a new file here inside of my source directory and it's gonna be called init.js. So here's kind of my first kind of theory of round doing front-end development in particular.
[00:00:24] I always try to have like one defined entry point to my app that the browser loads. And then everything else behind it, I try and make those modules. The reason being is that I can put all the garbage in this init.js that I'm not gonna test, right? Like a really good example of something that would go in this init.js would be like all this stuff setting up analytics, like Google Analytics or something like that.
[00:00:46] I'm not gonna test Google Analytics. I assume they test their own crap because that's their product. It's not my product, right? So all that kind of fluffy stuff goes here in init.js, I don't have to test init.js. I just know this is code that gets run in the browser and I can stop thinking about it.
[00:01:03] Okay, so what I'm going to start doing in this is I'm gonna start the clock. So if you remember back in our game, going back here, there has to be some sort of clock that's going. Let's refresh the page here. There has to be some sort of clock that's going here, right?
[00:01:24] That's gonna be dictating is the fox hungry, is the fox idling, is the fox, doing that kind of stuff, right? And so we're gonna have a clock that ticks every three seconds. That's going to advance the game every three seconds and we're gonna be basically running on this timer.
[00:01:42] Now you could try and write this game using set timeouts. And I strongly advise against that because there's just bears of synchronicity problems that lay down that path. I don't know if synchronicity is a word, but it is now. So what we're still going to do, we're going to standardize on one clock that we're going to run because then we're in control of how the project advances.
[00:02:09] Okay, well, that was a very sad game. Sorry, [LAUGH] warning, fox death ahead, okay. So on this init.js, we're going to make some sort of tick rate, const tick rate. And for now we're going to have that equal to 3000, which is going to be 3000 milliseconds. So everything in this is gonna be done in milliseconds because that's how the browser keeps track of time.
[00:02:37] Now, you might be, this is called screaming case. Why am I putting this in screaming case is because it's a constant. This never changes. So anywhere that I see my code in the screaming case, I know this is a constant tick rate that never changes, it's not a variable.
[00:03:13] So it's gonna be called function tick. And all we're gonna do right now is console.log tic and we're gonna put our date. So date.now, which is just gonna print out what time it is basically. So the first thing that you might be noticing is these have underlines, and that's our es lint kicking in to say, hey, tick rate is assigned and never used.
[00:03:37] Which we know, we will eventually but for now that's an error, but it's good to know nonetheless. Same with tick. We created it, but it's never used. Now the yellow underline here says you're using a console log here. I'm gonna warn you about that but I'm not gonna error out.
[00:03:55] So that's what that one did when we added that. The next thing we're gonna do here is we're gonna make a function called init. This is the function that we're going to call to start our program. So we're gonna make the function and then immediately underneath it we're gonna call it.
[00:04:31] I don't think I actually do it anywhere in this course. So you can put it there, you can not. It's not gonna do anything for you right now. So I'm just gonna throw out here a console.log('starting game'). It's just a way for me to let myself know I'm starting right now.
[00:04:49] Okay, and then we're going to kinda get this clock rolling. So let, and we're gonna put nextTimeToTick = date.now. So we're gonna create this variable called nextTimeToTick, which is how we're going to track next time we're gonna call tick. Okay, so the first time I'm gonna tick is whenever this starts, that's how we're going to set it to date.now.
[00:05:24] Inside of our function here, we're gonna say function, nextAnimationFrame. So again, function within a function that's fine. It's called a closure. We're gonna be using a closure to keep track of our time. And inside of our closure, we're gonna say const now = date.now And we're gonna say if nextTimeToTick >= now, then we're going to tick, like that.
[00:06:05] And then we're going to reset our nextTimeToTick = now + TICK_RATE. And then at the very end of this we're gonna say requestAnimationFrame(nextAnimationFrame). Okay, almost done here. The next thing we have to do is we want to call requestAnimationFrame(nextAnimationFrame) here as well. So let's talk about animationFrame for a second.
[00:07:16] So, the key here is it's saying, hey, browser when idle do this. And that's important because if you'd use something like set timeout or set interval, it's saying, hey browser, drop everything, stop what you're doing and run this function at exactly this time. When in reality, it doesn't actually matter if it runs now or in one millisecond.
[00:07:37] Cuz it almost never, in fact, I can guarantee you it doesn't take much more than like two or three milliseconds for the browser to idle because it's frequently idling. But that way we can basically guarantee ourselves we're not interrupting stuff when we call animationFrame. Now, this happens a lot, like really frequently.
[00:07:57] animationFrame is gonna, in fact, we can just show you how quickly it happens. So let's just do this for fun. Well, let's go ahead and first see this working. And then I'll show you how frequently requestAnimationFrame happens. Suffice to say, it happens a ton. So what we're doing here for nextAnimationFrame, which is going to be called by requestAnimationFrame, we're saying, hey, is it time to tick yet?
[00:08:27] It's not, cool. Don't do anything, just schedule me again. So that's what this is doing right here is it's saying, cool, I'm calling myself back, just call me the next time you have an idle second. And so it's doing that a lot until eventually this if statement is true, which is the next time we're going to advance our clock, then it's gonna call tick, right?
[00:08:46] And tick is where we're gonna do all of our business logic of advancing the game, doing new stuff, making the fox hungry, all that kind of stuff. And then we have to call it again here at the beginning cuz we have to schedule it once. And actually, you could even make this easier if you wanted to.
[00:09:05] You could just say, nextAnimationFrame, you could just call it directly first. It doesn't matter. Okay, so let's talk about the closure. This might be a little bit confusing of, why do we have a function within a function? We have this nextTimeToTick, which is like we have to keep track of when it's time to advance, right?
[00:09:24] We have to keep track of one three seconds from now because that's constantly going to be advancing. That's actually why we use let here right, because it's going to be changing over time. We use the closure because this closure can refer to nextTimeToTick which is outside of its own scope.
[00:09:39] So it's going to survive it right? We're using closure to encapsulate that state. And so that way when we say nextTimeToTick, if this was inside of it this would get reset every single time this gets called. We don't want that. We want that to survive the calls of this.
[00:09:57] That's why we're using closures to advance the state here. So let's go see this in action. So we have an init.js, we have to go back to our index.html. And we're going to say, down here at the bottom, or sorry, inside of the body. Last line inside of the body.
[00:11:00] So if I look down here, I still have parcel running. So if you don't have parcel running, make sure you have npm run dev, so that parcel is running here in the background. If you do need to stop it for any reason, you can hit Ctrl+C and that'll stop the server.
[00:11:15] And I can just say npm run dev again, it'll start it back up. So now if I go back to localhost:1234. And if I look at the console here at the bottom, which I just did with Cmd+ Option, I think it's K or J. So you probably are seeing an error here that says regenerator runtime is not defined.
[00:11:39] That's expected. And that's a quirk of how parcel is rendering our code. I want you to go back to your package.json really quick. And we're just gonna put one last line here underneath devDependencies actually doesn't matter the order. I'm going to put it underneath devDependencies. And this is going to be called browserslist like that.
[00:12:03] Make sure you do not forget the s there, browserslist:, it's gonna be an array. And then we're just gonna tell parcels, here are the browsers we are targeting. Don't include anything that we don't need for that. So our problem right now with the regenerator runtime thing is it's trying to target old browsers and old browsers don't understand async functions.
[00:12:28] But my Firefox, your Chrome, Edge, Safari all understand async functions. So we're just gonna say, hey, don't try and target those browsers. So inside of that, you just put square brackets for an array. And here we're gonna say last 2 Firefox versions, or you could put Chrome, whatever you want to put there.
[00:12:51] I'm using Firefox so I say Firefox it doesn't matter. It amounts to be about the same thing. Now, don't ship code that only targets the last two Firefox versions. That's a terrible idea. But when you're writing code for yourself totally fine. Okay, so now if we go back to our code, you can see we see it's ticking every couple of seconds, Which is exactly what we want, right?
[00:13:21] So now we have a real clock that's working for our code, which is great. Last thing I'll say, if you're still seeing some issues here, just a pro tip for making it work. So I'm just gonna go start my server really quick, Ctrl+C here. Something you can do that sometimes helps, you can say rm -rf.cache end dist, which will clear out all of the built files for parcel and it can kinda reset its memory.
[00:13:51] So if I do that, and then I do npm run dev again. That's only if things aren't working. You don't have to do it if things are working. But in any case, if I refresh my page again, you can see it's still ticking every three seconds. All right, so this is kind of giving us the temporal framework, if you will, to work within, right?
[00:14:22] This is going to allow us to advance our game every three seconds. And you can, these are just the rules that I made for myself. If you wanna make this tick every second and have more granular time, you can do that. If you wanna make it tick every five seconds, that works too.
[00:14:37] That's totally up to you, however you want to architect this game. I'm gonna give you all the variables and then you're welcome to play with them afterwards.