How To Code The Snake Game In Javascript

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone in this video I'm gonna show you how you can build this snake game by using just plain JavaScript no libraries no frameworks just JavaScript HTML and CSS and there is a ton to learn in this video about game development and also web development as a whole so with that out of the way let's get started now have you ever wanted to work fully remote but have a hard time finding remote jobs well luckily for you remote work today's video sponsor has a huge listing of remote only jobs where you can go and find your dream remote job they have tons of different jobs across all different spectrums including programming and they're with tons of different companies all across the world so you can really find the perfect job that fits your exact need on top of that they have different types of jobs from full-time part-time contract and even internships so it doesn't matter your skill level you can find a job on remote dot work so make sure to check out remote dot work using the link down in the description below welcome back to web dev simplified my name is Kyle and my job is to simplify the web for you so you can start building your dream project sooner so if that sounds interesting make sure you subscribe to the channel for more videos just like this now to get started I have a working version of the game on the right and you can see as soon as I click one of the arrow keys the snake is gonna start moving and I can click another arrow key and of course if I eat one of these food pieces the snake is gonna grow and continue on like this until for example I run into myself or wall and then it says that I lost and I can click OK and it's going to restart the game for me so it's a fairly basic game overall but there's a lot of extra customization in configuration we do for example I can change one a single variable I come in here and now the snake is gonna move twice as fast as it was moving before I can also change another variable if I just change here this and I click refresh you can see when I eat a piece of food the snake is going to get longer by three pieces at a time instead of one so there's a ton of different ways you can customize this based on how the code set up so it's a really great project to see how you can make modular and refactor a bull code so to get started with making this project the first thing we need to do is to create an index.html file and then inside of here hit exclamation point and tab and that'll fill out all the boilerplate HTML you need to get started we're just going to give this a title of snake here and inside the body we actually only need one single element it's just going to be a single div and this Dib is going to have an ID which is just going to be a game board just so we know that this is where we're gonna put all of our different game pieces and sometimes you may see games made with canvas instead of with actual HTML elements and the reason we're using actual HTML is because CSS grid is perfect for making snake so we're going to use CSS grid heavily to take advantage of how we can use it with snake so now speaking of CSS grid let's get some of styles in here and I'm just gonna do these inside the HTML because we don't actually need that many styles the first thing we want to do is Center this grid content inside the middle of our screen so we want to select our body and we're gonna set the min height equal to 100 VH whoops VH just like that and we want to set the width the same way 100 V W and let's just make sure we set the height to 100 VH we're never gonna have any scrolling so we don't need to worry about min height if we change the displayed here to flex set justify content to Center and align items to Center we're essentially going to be centering our grid section inside the middle of our screen so this game board is going to be in the dead centre of our screen lastly let's just remove all of our margins so we'll set our margin to 0 and we'll put a simple background oops background color which is going to be black as you can see we have the black outlines around our grid border here now we can select that game board and for our game border let's just set a background color here which is going to be CCC that's this grey color that you see on the right and to get our width and height set up let's just set our width here to be 100 V min and what this is going to do is this going to take whichever direction is going to be the narrowest for example our width right here as the narrowest so V min is our width but if we for example were to expand our screen you can now see that V min is our height because our height is the shortest width so now our width is going to be 100% of the height and our height is going to be 100% of the height and the reason that we're doing this with v min is so that way always we're going to have a square shape that's going to be as large as possible to fill our entire screen so with just that setup what we can do is actually run this with live server so we just right click open with live server that's going to open up on the right hand side here and as you can see we have that gray section which is going to scale perfectly based on the size of our screen now the next thing to do is actually to set up our grid so we want to change this to be display of grid and we're going to change it so that we have twenty-one columns and twenty-one rows that are all the exact same size and we want the browser to automatically calculate what size this is we don't want it to always be 50 pixels or 40 pixels we wanted to just be 21 even squares that way no matter what size our browser is the snake game is always going to have the same 21 squares so in order to do that it's also fairly straightforward we change here our grid template rows and we're going to set this to repeat which repeat and we want to repeat 21 different times and we're going to give them a width of 1 FR which is just going to be essentially all the rows are going to be the exact same and we could do the exact same thing here with our columns so with this one FR + 21 we now have 21 rows and 21 columns and each one is going to be evenly split up so they're all the exact same width and the exact same height so now we can actually see this by just inspecting over here and if I just hover over our game board you can see this grid appears on the right side of our screen and that grid is our 21 by 21 grid where entire snake game is going to take place now the very last thing we need to style is going to be our different elements for example our snake piece and our food piece so let's just come down here and select our dodge snake and we're going to select our food and our snake is going to have a background color which is going to be that blue color that you see which we're just gonna say HSL 200 100 % and 50% that's that blue color and for the food we're gonna do a very similar thing but we want to have a yellow color which is just going to be 50 as our HSL and then lastly we're gonna need a border and I actually want those a border to scale with the size of our grid so when we have a real the big screen our butters gonna be bigger and we have a really small screen our borders going to be smaller so in order to do that we can set it based on our V min s weeks at 0.25 V min and that's going to be the size of our border then we can say in here that we want it to be a solid black border and we're going to give that to our food as well so now we have our snake piece and our border for the food piece set up properly and that's all of the CSS and all of the HTML we need for this entire project so we can move on to the most enjoyable part which is going to be our JavaScript so let's create a javascript file called game EAS this is where our base JavaScript is gonna go and in order to import this we're just gonna import it up here in the head I'm gonna say script we're gonna want this to have a source which is game is we want to defer it so it loads after our body and we also want to set the type here to be module and the reason for this is that we're actually going to use import and export statements to have multiple JavaScript files so we can break apart our logic for our snake and our food into different files to make it easier to work with and easier to reason with our code so we're going to use this module here of our type just so the JavaScript and our browser knows that we're going to be using import and export to make different files instead of just one giant javascript file so now if we save that we can close out of this index.html and move on to our game touch is now the very first thing we need to do in our game j/s is set up what's called a game loop and a game loop is just a function that's going to repeat itself over and over and over again on a very set interval that way you can constantly update your render so for example as our snake moves we can constantly update our snake position as well as constantly update our food and do all of the game calculations we need on a very set time so in order to set that up what we need to do is create a function so we'll call this function main and this function is going to take in the current time this is essentially the exact timestamp of when this function runs so inside of this function we're going to have that current time and then we want to recall this main function essentially immediately so that way we can set up another loop that's going to happen after this essentially our main function is just going to loop over and over and over and over and over again forever that's the purpose of a game loop so to do that we can use window request animation frame and we're gonna pass it in that main function and what this does is this says okay browser tell me when I can actually render my next frame I such I'm requesting a frame to animate my game and this is going to tell us what the current time is when we actually go to render that frame so it's going to say okay I want to render frame it's gonna wait till it can render a frame then it's going to call our main function with the current timestamp of when that frame is going to render so when we do this we just put in here at console that log of current time and make sure that we do one last window request oops window request animation frame of main this is just so we can start our loop the very first time now if I come over here and inspect our page and go into the console you can see we're getting printed out the time from when we first initially decided to run our window dot requestanimationframe it's just constantly counting up this is in milliseconds so in order to take advantage of that we want to figure out how long it's been since last time that we rendered so we're gonna create a variable we're gonna call it last render time and by default that is going to be zero and then we're going to update our last render time down here so down here we're just gonna say last render time equals and we're going to set it to our current time so essentially every time we come through here we're setting our last render time to our current time so that will we are constantly having a new last render time and then what we can do is we can come in here and get the number of seconds since last render so we can say seconds since last render is going to be equal to our current time - our last render time and we want to divide that entire result by 1000 since this is in milliseconds and we want to convert to seconds so now let's actually log that out down here at the bottom and if we do an inspector real quick you can see inside of our console we're getting approximately it looks like you know 0.006 2.0 oh seven seconds of delay so essentially six to seven milliseconds of delay between each one of our render frames and with our game we don't need to run that fast we don't need to update the snakes position every six milliseconds I mean if you look over here if i refresh this real quick you can see the snake really doesn't move that fast so in order to actually update the snakes position instead of running this every single millisecond or every six milliseconds we're going to essentially not do anything in our main function unless we hit a certain threshold and we're gonna call that our snake speed which is going to be a constant variable so we'll say snake speed we're going to set it equal to one for example to start with this is going to be how many times the snake moves per second so let's actually set that to two so it's going to move two times per second so in order to calculate if we need to actually move all we need to do is get our seconds a sense last render and all we need to do here is check if the second since our last render is essentially less than the time between our renders which would just be one divided by our snake speed since our snake moves at two times per second one divided that would be the number of seconds between each move so we have a half a second between each move and if the time senseless render is less than half a second then we don't need to move our snake so we can say if that's the case all we want to do is just return out of here immediately what we want to make sure that we always request our next animation frame no matter what and we only ever update our last render time if we actually get below this check here because that means we're actually going to render our snake so instead of here we can just put the text of render and now if I come over and inspect the page you're going to notice that inter console about two times per second we're getting the text render printed out and if we increase our snake speed to for example 20 and I come over here you can see this is being printed 20 times a second and if I drop it down to 1 it's going to be printed out once per second so we can directly control how fast our game actually updates based on this snake speed variable here and at the beginning when I was changing one variable to change how fast our snake went it was this exact variable here so now that we have all of this under code setup let's come down here and actually set up our logic for our game almost any game you work on is going to be broken into two different steps you're going to have an update loop and this update loop is going to update all of the logic for your game and then you're going to have another loop either called draw or render and this is what's actually going to draw everything on the screen based on this update loop so this update loop is going to move the snake to the correct position but not actually draw it it's going to update if we ate the food or not so it's gonna make the snake longer or shorter it's also going to determine if we lost the game because we ran into our own tail or ran into the edge of the screen and then in the draw what we're gonna do is take all of the logic from update and say okay where is our snake now let's actually draw him in the correct position let's draw the food where it needs to go in all of that stuff so we broke this into two distinct separate sections so let's create those functions real quick I'll just come down here a little ways we'll say function update and we're going to have another function for a draw whoops and inside of each one of these all we need to do is update our snake and our food and then draw our snake and our food so let's first get started with our snake we'll create a new file we'll call it snake jeaious and inside here is going to be where all of the code for our snake goes so let's actually take this snake speed and move it into snake jeaious and we're going to export this so that we can use it inside of here so we can just come down here import then we want to import snake speed from Dodge slash snake dot J s just like that and if we come over here and make sure whoops that we render and inspect this it should still be printing out render just like that so everything is still working and now inside of our snake J s we want to have a function for update this is going to be for updating our snake any function for a draw for drawing our snake and again we're gonna need to export in both of these functions so that we can use them inside of our game J s so let's make sure we import these we're gonna import update and we're gonna call this update snake and we're going to import our draw which we're gonna call draw snake just like that if I spell snake correctly and now we can actually do is take these functions update snake and draw snake and just call them in our main update phone so we have update snake and we have draw snake so now we just remove this render here instead of our snake I can console.log draw a snake if I come up here and do the same thing but for update you should see when we inspect that these are being rendered out first update and then draw and as you can see us has update draw update draw and this happens every second based on our snake speed that we set so we can change this to 5 and now you can see it's 5 times quicker to put that back to 1 for now and we can close out of this and the first thing that I want to work on is going to be actually drawing our snake because I think that's going to be the most visual and most interesting but before we can start drawing our snake we need to figure out how we're going to represent our snake and the brilliant thing about using a grid-based system is that we can represent our snake as essentially an x and a y position so let's create a variable I'm gonna call it our snake body and this is going to be an array of XY positions because our snake essentially is just a bunch of different segments and these segments all are in its particular XY position on the grid in the very center of our grid is going to be at X 11 and at Y 11 so I want to draw our snake at X 11 and Y 11 right at the very start in the very middle of the screen to begin with so in this draw function what we can do is take our snake of body and we want to loop through each one of our different segments is what we'll call them essentially each piece of the snake we want to loop through and I want to draw this to this screen but of course I need to draw it to our game board so we're gonna need our game board passed into this draw function so we can actually add our snake to it and then what I want to do is create essentially an element we're gonna call this our snake element and we're going to set this to document dot create element and this is going to be a single div and this is going to go inside of our game board at a particular X y coordinate and since we're using grid we can directly set that XY coordinate very easily we can say down here our snake element dot styles or dot style I'm sorry dot grid start a good row start and that's going to be equal to our X so we can say segment X is our row start and we can do the exact same thing but we want to do OUP's grid style back grid column start and this is going to be our wide position so now we've set the x and y position based on our grid row start and our grid column start and then we can just say game board dot append child and we want to append that snake element and in order to make sure we can visualize this we can take our snake element and we can set the classes so we need our class list we can add in our snake class just so we can get that nice blue color now if I save and come back over here you're gonna notice nothing actually work shed and that's because we need to pass that game board in so down here let's pass in our game board and we first need to grab that game board by sign Const game board is equal to document dot get element by ID and the ID is game board and as you can see our snake has popped up which is exactly what we want now let's focus on how we get our snake moving and to begin with I'm going to think about how we would move our snake if we for example had a three segments snake so let me create a three segments bake just so we can think about this we're gonna do in X 10 here and X 12 so this is just going to be a straight line snake and if I save you can see we have a straight line snake and now let's say that this snake moves up one position so it's going to have its new head right above its current head the way that this works is that we're going to move its current head up one to the new position and then where does the body part go well the body is also going to move up one and then other body piece is going to move up one so that's pretty simple we just add one to every single piece to move it upwards but what if the snake head moves to the right well we don't want to move all of the body pieces to the right because if we did that for example we made our snake move all of its body pieces to the right it's not going to look right because the snake is going to move as a whole piece when in reality it's supposed to follow its head around so an easy way to get around this problem is we move the head to the right one and then we move the body piece right behind the head to where the head used to be and we move the body piece behind that one one as well to wear the old piece used to be so essentially we're just shifting our array up one and then making the head the correct position where we want it to be so inside of our update function that's exactly what we're going to do we are essentially just going to take the position of a given segment and the segment after that is now going to move into that new position so let me show you how that works inside this update function real quick because it's a lot easier to see inside the code so we're going to need a for loop here because we only want to loop through every segment essentially except for our last segment because the last segment of our snake is going to essentially disappear the position where our bottom of our snake is is no longer going to have a snake in it ever so we don't need to worry about that position so what we can do is just say let I equals snake body dot length minus two this is going to give us the second-to-last element in our snake so we're going to start from the bottom and work our way up then we're going to say when I is greater than or equal to zero we're going to stop our loop and we're going to subtract one from I each time and now inside of this loop what we're going to do is we're going to take our snake body of our I plus one element this is going to be the element before the one we've selected so on the very first iteration I is going to equal the second-to-last element and I plus one is going to be our last element so we're going to take essentially our previous element in our case our last element we're going to set it equal to our current element in that i position here and we need to make sure that we set this as a brand new object so we're just going to spread out this object into a new object that way we don't have any reference problems this is going to create a duplicate of our snake at position I and set that to our snake at position I plus one we're essentially shifting our entire snake so that everything moves forward of position it moves to where its parent essentially is in the snake's body then once we've done all of that the very last thing we have to do is update the head based on where we're moving so we can say snake body of zero this is going to be head and we're going to update the X by adding two it's some kind of movement let's just say one for now we're going to hard-code this as one and for the Y position of the head we're just going to plus equal this with a zero we're not going to move the Y position so now if I save this you're gonna notice something interesting as you can see our snake is moving but it's moving down instead of to the right so clearly our x and y are flipped and as you can see down here our row should be set to our Y and our column should be set to X so if we save that we should now see that our snake is moving to the right which is exactly what we want but you'll notice this weird thing where it's kind of showing all of the pieces of where the snake used to be and this is because when we draw our snake we aren't removing all of the previous pieces of the snake what we need to do is take our game board and set the innerhtml to nothing this is going to clear everything in our view so now if we save and you can see we render our snake is going to move without actually showing any previous pieces behind it so this is exactly what we want and in order to make this look a little bit better let's actually add one to our Y instead of our X and as you can see it's much better properly following the snake as it's actually making these turns as opposed to just always moving the entire snake in one direction we can see that a little more if we add even more segments to our snake it should be even more obvious so let me just add these extra segments and we'll save one more time and you should see that it's going to move down and each one of the pieces of the snake is going to be following which is exactly what we want and one thing that's kind of interesting you'll notice is as Y increases we actually move down that's an important thing to realize because when we're going to input our input system we need to make sure that negative 1 for Y is moving up and positive 1 for Y is moving down that's something that I always mess up myself and speaking of input let's actually work on making a Sorak keyboard is going to work and actually allow us to do inputs instead of hard-coding our movement inside the update function for now I'm just going to comment this out so our snake doesn't move all over the place and I'm going to create a brand new file which is going to be called input a yes this is what we're going to get all of our input information from so inside of here we want to create a variable which is going to be called our input direction we're going to set that just to X 0 and it's going to be y 0 by default we don't want our snake to be moving anywhere and then we want to create a function we're just gonna export this there's gonna be called get input Direction and all this is going to do is return our input direction just like that so now instead of our snake here we can call that get input a direction function and it's going to import that for us automatically which is really nice and then that's going to give us our input direction so we can say Khan's input direction it's going to be equals that down here we can update our snake position based on our input direction so we'll say input Direction X in input Direction Y and now if we save you should see that a snake doesn't move anywhere but of course looks like we're getting an error so let's inspect and actually see what that error is in our console it says failed to load resource the server responded with the 404 it looks like my automatic import didn't include the Jas so if I save that we can now see our snake is right where we wanted to and you do notice some weird movement with it that's just because our snake right now is longer than it should be let's clear this out so we just have one snake piece that's 1111 just like this and now if we save what a snake right in the middle it's not moving it's not doing anything it's just staying exactly where it should and now instead of our input here we can actually set up the code for modifying this input direction whenever we click a key so we can just add an event listener to our window for key down this is going to get an event and inside of here we're just going to use a simple switch statement based on our Y key and this key is either going to equal arrow up down left or right so we can say case of arrow up and then we want to do it put a colon after here and inside of here we're going to have our actual case we're going to set our input Direction here which is equal to X which is going to be a 0 and of Y which is going to be negative 1 because remember negative 1 moves us upwards and then we just want to break out of here we're going to do this essentially a few more times one for each of our different types of cases let me just fix the indentation here and there we go so this one is going to be arrow down which in our case is going to have a positive one in the Y direction then we're going to have arrow left which is going to be zero in the Y direction and negative one for X and lastly we're going to have arrow right which is one in the X and zero in the other direction there we go all of our indentation should be fixed just like that so now we have our input Direction being set and with this we can actually just save this and now whenever I click an arrow key like up you can see the snake moves up left and it's going to move to the left down it's going to move down and right it's gonna move right but one immediate problem you'll notice is I can move from right to left or I can move from up and I can move back down and that's something you can not do any actual snake game your snake can't reverse onto itself so we need to set up some checks to make sure we can't actually move from up to down or from left to right so we actually need to store our previous input Direction based on the last time we got our input so inside of here we can just set a variable called last input direction we're going to set it to our input direction and let's create that variable we'll say last input direction and by default we'll just set it to zero zero and then in our arrow up we can say if our last input Direction dot Y was not equal to zero then we essentially want to break out of here what this is saying is if we are currently moving up or down just ignore this we don't actually want to worry about up press because we can't press up when we're already going down we're gonna do the same thing for our arrow down if we're already moving up we can't actually start moving down and then instead of here we're going to make this X because if we're already moving to the right we can't move to the left and down here same exact thing now if I save and I press up you're gonna notice I start moving up and if I click down nothing's actually going to happen I'm not going to be able to move down and if I move left I can move left just fine but I cannot move to the right I can move down I can move right I can move up but I can't swap Direction 180 degrees so we fixed that bug which is really important now the next thing that we can work on is going to be our actual food but before we do that I'm gonna bump the speed of the snake it's really slow right now so we'll bump this up to five just so it's a little bit more enjoyable to watch as it moves a little bit faster that's much better and now we can create a new file called food j/s and inside of here we're gonna do a very similar thing we did to snake we're gonna have an update and a draw function I'll actually just copy these over clear out the update function is gonna be a lot different but our draw function is actually going to be very similar we don't have a snake body anymore to loop through so we can get rid of that and we're going to have a food element instead and this food element is going to be based on a variable we're gonna create which is going to be called food and we're just going to set this to an object which has an X of 0 and we're gonna give it a Y of 0 for now eventually we'll make this random but for now we'll just hard code it into X 0 and y 0 and now we have our food element and our food element style for the grid row and column start right here they're going to be exactly the same that's why in this X but it's going to come from food instead of segments so we can set our food here and we want to add a class of food to this instead of snake and then make sure we take our food element and add it to our game board so now we have that done inside of our game we can actually import that so we can say import food as I'm starting out food update as update food and we want to get draw as draw food and we want to get those from Dodge slash food is whoops Dodge is just like that in denim here we can say draw food past it in our game board and we can call update food as well now if we save you can see our food is in the top left corner if we change this to for example X of 10 you can see it's going to move over to the 10th row or the 10th column I'm sorry in the very first row and actually something super important to note is that CSS grid starts at 1 so instead of this being 0 we actually need to make this a Y of 1 because those are actually different positions on the grid they look identical over here but they're actually different so we need to make sure everything is going to be between 1 and 21 and 0 is actually technically outside of our grid so that's an important thing to note now the next thing that we need to work on is what happens when the snake eats the food if I move the snake all the way up here over top of the food you can see nothing actually happens I just go right underneath of it clearly that's not how you're supposed to play snake so what we want to do is set up some form of expansion rate we're going to set a constant variable called expansion rate and this is going to be how much the snake grows when it eats the food we'll set it to one for now which means it will gain one new segment every time it eats a single piece of food then what we're going to do is instead of our update we want to check if the snake is currently over top of our food because that means that they can eat it so we can just come in here and say if on a snake which is a function we're gonna create which is going to pass in a position on the grid for example our food and it's going to check is this on our snake and if so it's going to return true otherwise it's going to return false so if we're on top of the snake then we want to execute some code to eat the food so we want to first expand our snake so we'll call a function called expand snake and we'll pass it in that expansion rate so we want to expand our snake by one and then we want to set our food to a new position in our case we're just going to hard-code this to an X of 20 and we're gonna set it to a whoops Y of 10 just for now it's going to be hard coded there but eventually we're going to have to update this to somewhere else we're gonna have to make sure this is random but before that we need to make an expand stake and a non snake function so in our snake let's export expand snake this is going to take in a number for how much we expand make sure we call this a function as well and give it here an amount and we're going to essentially take a variable called new segments and we're going to add in that amount just like that so let's create our new segments we're gonna default that to zero because by default our snake is obviously not growing then we're going to export another function called on snake this is going to take in a position and it's going to determine if this position is on our snake we can just come in here and return snake body dot sum and we want to loop through each one of our segments oops I'm sorry segment just like that and for each one of our segments we want to essentially check if it's on our snake so we're going to compare our position with our segment position to see if they are equal so to do that we're going to create a function which is going to be called equal positions and we're going to pass it in a segment and a position and let's just create this function down here for now eventually we're going to move this out but we'll create equal positions I was going to have position 1 in a position - and all we want to do is return if some criteria is met so position 1 X is equal to position 2 X and position 1 dot Y is equal to position 2 dot y just like that let's just put this all in one line actually I think it'll all fit there we go and now essentially if our two positions are exactly the same this is going to return true and if that's the case for any of our snake positions that's what dot sum means so if any part of our body equals this position we pass in then on snake is going to return true so let's import that in our food here we can say import on snake and expand snake from - last snake J s and as you can see everything renders over here and if we come up and eat this food it should disappear and move and that's exactly what we got but of course our snake hasn't expanded itself yet so let's make sure our expand snake is actually working so essentially in our update we need to take our new segments and add them on to our snake so let's create a really simple function we'll do it all the way down here at the bottom we'll call this add segments this function all it's going to do is is going to take our new segments and add them onto the bottom of our snake and we're gonna call this every time we update so in here we're just gonna call add segments just like that so now instead of our add segments function we want to just loop through all of the segments so we can say let I equals 0 I is less than new segments and I plus plus so for each one of our new segments all we do is we take our snake body and our snake body dot length this is going to be essentially one more index than our current snake length so this is going to append a new element onto the end of our snake we're just gonna set it equal to our snake body snake body dot length this one it's going to be a brand new duplicate of this this would be essentially the same as if we did snake body dot push we just want to append that on to the end and this is a little bit more clear so we'll go a snake body dot push so we're just taking the very last element of our snake and duplicating that onto the end of our snake so if our snake is currently one position it's going to duplicate that one position and that as our snake moves it's going to slowly expand itself outwards so we have our add segments done and instead of our update we also have our move code done so let's save this and go up and see if this actually works and as you can see our snake is constantly expanding itself so clearly this is not what we want and the reason this is working like this is because we're never actually getting rid of our new segments so what we need to do inside of this add segments function let's take our new segments and we set that down to zero now what's going to happen is it should no longer add any more elements to itself other than the number of elements we told it to and at our food we change our expansion rate to five you should see that now our snake is going to increase by five instead of just increasing by one so if we eat this you can see it's now five longer than it was before and as you can see everything is moving exactly as we wanted to so now let's move on to the problem of actually randomizing our food position let's create a simple function called get random food position and what this is going to do is return to us a new position for our food every single time it gets eaten and it's going to return a position that is not already on the snake that's the most important characteristic of this so we can just create a variable called new food position just like that and in order to make sure we create a food that's not on the snake we're going to use a while loop and whenever our new food position is equal to null or whenever we are not on the snake with our new food position so we can say currently whenever our food is null or our food is on the snake already then we want to essentially get a new food position so say new food position equals random grid whips Crandon grid position which is a function we're going to create we're just going to give us a random XY value inside the grid so what this function does is every single time that executes it's going to get us a new food position and then if that new food position is already on the snake it's going to get another one and another one and another one and it's going to loop like that forever until it finally finds a value that's not already on the snake so we can set our food equal to that and get random food position we can do that up here for our default first food and down here when we set our new food they're both going to be randomized and now the only thing left to do is to create this random grid position function to do that we're just going to create a grid dot J s and inside of here we'll export that function which is going to be called get random whoops get random grid position and actually this is just called random grid position there we go and all this does is going to return to us a new X and a new live value and this X is going to be based on a formula for calculating a random number between 1 and the size of our grid which is 21 so we can say math dot floor of math dot random and this is just going to give us a random number between 0 & 1 and it's always going to be slightly less than 1 so 0 and 0.9999 99 repeating forever we're going to multiply that by our grid size which is 21 we're gonna put this inside of a variable just to make it easier to work with so we can say up here Const grid size equal to 21 and then what we want to do so we have a number between 0 & point 9 9 9 9 we're multiplying it by 21 so that's going to give us a number essentially between 0 and 20 point nine nine nine a nine a nine a nine and we're getting the floor of that so right now we're getting a number between 0 and 20 so in order to get a number between 1 and 21 we just need to add one to the end of this so now we have a number between 1 and 21 which is going to be on our grid and it's going to be completely random we'll do that both for X and for our y now instead of our food we just need to import that so we can say import random grid position from whoops grid ojs and we can make sure it's dot slash like that and now you can see our food position should be randomized every single time we pick it up so that regard food move down here completely randomly now it's moved up there completely randomly and all the way down there and you notice it's never going to land anywhere that the snake already is because we're checking that down here and our get random food position we're checking to make sure it's never on the snake it'll get a new random position if it can't find one so right now our game is mostly complete we have our snake moving around eating food and the only problem is that there's no way to lose the game I you know just refresh here you can see I can run into the wall and it doesn't matter it just works no errors are throwing everything's fine I can even move the snake around moving back up try to get them off of this it really does it doesn't make any sense none of this actually works we need to add in a failure state so to do that we're gonna go back to our game Jess and inside of our update we're gonna check for failure so we're gonna say check for death if this is going to happen if the snake runs off of the grid or if this make runs into itself I will just create that function down here to make sure we check for that failure state and in this failure state we're gonna set a global game / variable equal to either if we are outside the grid or if our snake has intersected itself we'll say psych intersection so this outside grid we just want to check if the head of our snake is outside so we're gonna create a function called get snake head we're just going to give us the head of the snake and if the head of the snake is outside the grid we lose or if this make intersects itself which is another function we're gonna create on the snake to determine if the snake head has intersected with its body and we're gonna create that game / variable all the way up here so we'll say game over we're gonna set that to false to begin with obviously then to actually do our game / state inside of our game loop we're just gonna check if game over then we're just gonna for now alert you lose we're gonna set this up to actually restart our game but for now we'll just say you lose and we're gonna make sure that we return here just so we don't actually run the rest of our code and now if we save we need to make sure we implement this outside grid snake intersection and this get snake head so let's do outside grid first and that'll go inside this grid j/s so we'll say export function outside grid and essentially all we need to do is check to see if the position that we pass into this is going to be greater than our grid size which is 21 or if it's less than one which is our minimum grid size so let's just come in here we can say return I'm going to return position dot X is less than one or the position dot X is greater than our grid size or if our position dot Y is the same thing less than one or our position dot Y is greater than grid size so essentially if we're anywhere outside of our grid this will return true otherwise it will return false so that's outside grid taken care of the next thing we need to work on is going to be the function called and get snakehead so in our snake wishes export a function called get snake head and this is just going to simply return snake body of zero pretty straightforward we know the first element our array is always going to be our head now the very last thing inside of our game is going to be snake intersection and this one's a little bit more complex so it's export the function snake intersection just like that and essentially the way to determine if the snake has intersected itself is by determining if the head of the snake is touching any of the other body parts on the snake so we can just return on snake we can pass in the head of the snake but one problem is that this is going to loop over the head of the snake so of course it's going to compare if the head of the snake is the same as the head of the snake and that's going to always return true so we want to ignore essentially the head of the snake so we'll say ignore head is going to be set to true this is an option we're going to pass to arm snake we're going to have here ignore head which is by default going to be equal to false because if we don't pass it in we want this to be false we're gonna make sure that we pass in an empty object by default in case we don't pass anything then what we can do is take our segment and the current index and if down here if whoops if ignore head is true and our index is equal to zero which means we are on the head we just want to return true we're just saying ignore the head completely I'm sorry this should actually be return false because we don't actually want this to say that the snake head is on the snake head because we already know that we don't need to worry about that we're completely ignoring the head now this snake intersection is going to check the head against every other position on the snake and if any of them are the same then that means that this make has touched itself and you obviously lose so let's import all of these different functions we're going to have get snake head we're going to have snake intersection and we also need to import here from our oops in ports let's see what that was called it was called outside grid so we're gonna import outside grid from our docks last grid Jas now if we save you can see our everything is rendering so that's good news it should work let's go up and click some food to make sure that works as you can see this is all working exactly as we want let's try running off the screen as you can see we get an error saying you lose so that's exactly what we want we'll click OK for now and just refresh manually now let's go up here and see if the snake intersection works so we're gonna collect a bunch of food and then just run into ourselves so just like this if we run into ourselves you can see it says you lose so again our error check has worked this is exactly what we want now the last thing for us to do is to make this game over actually reset our game so it's actually pretty straightforward to do that what we need to do is put an if here we're gonna use something called a confirm that's going to be a box that pops up which is going to allow us to get a true or false result so we're gonna say you lost press ok to restart there we go and essentially if this return is true we want to do something otherwise we're going to do something else if we returns false and if it returns true rest up the window dot location equal to essentially the current location that we are already on and this is just going to refresh our page which is essentially going to restart our game and down here we just want to make sure that we return because if they don't press kay and they actually just fix it out by hitting cancel we don't actually want to continue to run the game we want the game to be stopped so we're going to save and we're going to refresh this to see if this works let's just go up and immediately lose and you can see it says you lost press ok to restart and when I click OK you can see it refreshes the page and if I go up here and instead of hitting ok I click cancel you can see it just gets rid of that pop-up and our game goes back to how it was but it doesn't start moving again it's just completely frozen because this is the lose state and we don't want everything to start moving again and that's all there is to creating this snake game if you enjoyed this video make sure to check out my other videos linked over here and subscribe to the channel for more videos just like this thank you very much for watching and have a good day
Info
Channel: Web Dev Simplified
Views: 221,352
Rating: undefined out of 5
Keywords: webdevsimplified, snake js, js snake, js snake game, snake game javascript, snake game js, javascript snake, javascript snake game, javascript game, js game, js game dev, javascript game dev, js game development, javascript game development, js game tutorial, javascript game tutorial, js snake code, javascript snake code, javascript snake tutorial, javascript snake game tutorial, js snake game tutorial, js snake tutorial, js project, javascript project, js, javascript, wds
Id: QTcIXok9wNY
Channel Id: undefined
Length: 46min 27sec (2787 seconds)
Published: Tue Jun 02 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.