Pacman Game Tutorial with JavaScript and HTML5 Canvas

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome everyone this is another chris chorus  with your host chris and today we are going   to be developing no other than pac-man so how do  we develop a game like this well you'll see over   here i have a handy to-do list for us the very  first thing we're going to need to do is set   up our project with the correct files we're going  to need to generate map boundaries so pretty much   everything you see right here with the blue pipes  we're going to go ahead and generate that using   code we're going to need to add a pacman with  movement of course we can go about our level   we're also going to need to add collision  detection so we can go ahead and move in and out   between these pipes and these different pathways  with the exact same movement you see right here   you'll see we're not actually going through these  pipes at all so we're going to need to add some   advanced collision detection there we're also  going to need to swap out these boundaries with   images so right now these are images but we're  going to start with squares just in the beginning   we're going to need to generate pellets that we  can collect we're going to need to add a score so   whenever we collect these pellets the score goes  up we're going to create these little ghosts that   move on their own with their own artificial  intelligence and then we're going to create   a power-up you'll see one down there in the bottom  right corner if i get it the ghosts turn blue for   a small period of time and then they eventually go  back to normal and then we're going to go ahead at   a wind condition so that when we collect all these  pellets we get a cons log that says you win great   win condition i know and then we're going to go  ahead and lay out a full level like this we're   going to start basic and then also we're going to  add in the famous pac-man chomp you see right here   there will be a premium course for this as well  it's going to resemble more of what you see   in the actual pac-man game so this is the actual  pac-man game available in arcades we're going to   do some things such as adding ghost sprays as  you see right here multiple lies pipes that go   to opposite ends of the screen we'll be doing  that in the pre-tutorial but none of that let's   just go ahead and get started with this free one  so let's go ahead and start with project setup   so in order to set up a project what i like doing  is i like heading inside of my finder i go into a   web directory of my choice i like going inside  my web directory for any web project i have   and i like creating a new folder so to create  a new folder using hotkeys i'm just going to   hit command shift n and that should be ctrl  shift n if you're a windows user and you'll   see i just created this new untitled folder  right here if you want to change the name   i'll just click it once it's going to allow  me to change the name now i could call this   pacman this is just going to be my pacman game so  now here's my folder and now i want to create some   files inside of it so in order to create these  files what i'm going to do is i'm going to drag   this directory i just created on top of sublime  text and that's going to go ahead and open up   my folder within sublime text i can now begin  creating files within this project so in order to   create a file what i can do is i can go to file  new file or hit command n and here is my first   file so now that i have this i can hit command  s where i can go to file save right here and   now i'm going to save this as what well i'm going  to save this as index.html the base for our game   so i want to make sure i'm saving this under web  and then under pacman where we just created that   new file i hit save we have our index.html file  so what i can do now is double click index.html   and we just start at the base for our game but of  course we have nothing inside of this if i right   click and inspect you're going to see we just  have an empty body tag and this is populated   by chrome automatically because we don't actually  have anything within our file so what do we need   to create a pacman game well we're going to need  a canvas element it's going to look like this we   have an opening tag and a closing tag for a canvas  element we save and refresh and now that is placed   within our game so looking good but what else does  a canvas game need well we're going to need some   sort of javascript file for us to write all of our  code so in order to do this we can go ahead and   create a new file with command n or control n for  windows and here i'm going to go ahead and save   and call this index.js saving it within my pacman  directory and now that i have this i can go ahead   and select our canvas within index.js how  do i do that i'm going to create a constant   called canvas and set it equal to i'm going  to select our document object and then call   query selector that's going to allow me to grab  any element within our html over here that's   currently available what element do i want to  grab well no other than our canvas element so go   ahead save that and i want to go ahead and console  log out canvas to make sure i'm actually pulling   this in and that this is being logged out within  our console so if i save index.js and i refresh   over here you're going to see this is not being  logged out why is that well you need to make sure   within index.html that you don't just create  a canvas element but you also create a script   tag like so and you reference the source of the  script that you want to call within your html   so the source of the script i want to call is  right here it's going to be index.js so i can   simply put in index.js since we're within the same  folder as index.html save and refresh and there is   our canvas element being logged from index.js  so the next thing i'm going to do is select our   canvas context this is what's going to allow us  to call all of our different canvas draw functions   pretty much a requirement for any canvas game  you're going to do so in order to select this i'm   going to create a const called c arbitrarily named  which stands for context i like it really short   because i use this so many times and i'm going  to set this equal to canvas dot get context with   a capital c and now what kind of context do  i want to get a 2d or a 3d context basically   what api do i want to get well i want to get the  api associated with the 2d functions this is going   to be a 2d game so i just go ahead put 2d as a  string right here within our argument and now   if i save and console.log out c and refresh we  have our canvas rendering context so we did that   correctly as well so the next thing i want to do  to set up our game is if i inspect one more time   over here and let me go ahead and put this console  at the bottom if i inspect our canvas you're going   to see it is not taking up the full width and  height of our screen so that's the next thing we   want to do is make sure this is taking up the full  width and height i always like doing this within   javascript i'm not a huge fan of doing it within  css so in order to do this within javascript we   can select our canvas element and that is just  referencing this right here within our html   and we can go ahead and set its width equal  to what enter width i do that save and refresh   and now you see our canvas is taking up the full  width of the screen instead of that smaller amount   now for those of you new to my courses where  does enter width come from well it comes from   a window object the window object is provided  by default bar browser window and it comes with   all these different properties all these different  methods that'll help us throughout our development   so if you're using a property such as enter width  that comes from the window element well you can   go ahead and get rid of window dot because the  browser is smart enough to know that this is a   property on top of that window object so if we  want to clean up our code a little bit we get   rid of window dot we just reference enter with and  this is more of an advanced technique because you   need to know while inner width is coming from that  window object in the first place but it does clean   up your code a little bit because you get rid  of window dot so i'm going to go ahead and keep   enter with because i'm used to having it and then  i want to go ahead and make sure we're setting not   just our width but our canvas height as well so  i'm going to go ahead and reference canvas height   and say that this should be equal to inner height  that is going to be the window dot inner height   property so on save and refresh inspector canvas  and now you'll see it is indeed almost the full   width and height of our browser why is it not the  full width and height well because we have this   gutter on the top and also the left hand side  of our screen where is this gutter coming from   well if i inspect our body tag right here within  the elements tab of chrome you're going to see the   body tag if i'm inside of styles has a margin  of 8 pixels by default so if you don't apply   any styling to index.html on your own google and  chrome are going to put in 8 pixels of margin on   your body tag by default so we need to tell chrome  not to do that in order to tell chrome not to do   that i'm going to head into index.html create a  style tag now i can start writing css inside of   this if you're new to css you can always take my  css master class it is quite helpful for getting   you up to speed but since this is going to be  a canvas course we're just going to do this   pretty quickly we're going to go ahead and  reference our body so basically we're referencing   this tag right here and now that we have body  selected we can go ahead and select margin   like so and set it equal to zero so basically  we're going to override the browser default   we just need to make sure we save and then if we  refresh and inspect our canvas you'll see there is   no gutter around it anymore our canvas is going  to be the full width and height of our screen   now the very last thing i want to do for  project setup is i just want to make sure that   our background is black because if we look at the  original pacman game while the background is black   not white and it's a little easier on the  eyes so let's go ahead and make our body   have a background color this is a css property  of no other than black we can put that directly   in there and then if we save and refresh now  we have a black background and we can begin   working on our game so if we go on over  to to do we can go ahead and check off   project setup so the very next thing we're going  to do is generate our map boundaries so if we   look at the original example i showed we have all  these boundaries on the outside of our level we   have some boundaries on the inside we're going to  be generating all of these but we're not going to   be using those pipes that you see right here we're  actually just going to be using basic squares so   in order to do this we're going to head back on  over to index.js and here we're going to create a   class called boundary so simple enough we'll  go ahead and add some opening closing curling   brackets and this is going to have a constructor  associated with it because each boundary that we   create needs to have a differentiating property  associated with it specifically for its position   so what kind of properties does a boundary  have well if we go back to our game over here   let's think to ourselves well basically each  boundary is a square connected to the next one   so if we say that this right here is one square  and then the one next to it is also one square   well we know that our properties for the square  are going to be a position so this is position   one this would be position two and we're going  to have a width and then a height associated   with each boundary each boundary square that is  so for our properties within our boundary what   we want to say is that each boundary is going  to have a position associated with it this is   going to be a variable position so instead of  setting this statically like so setting an x this   would be a static position instead of doing that  we're going to go ahead and set it dynamically   by declaring that this stop position should be  equal to position and if i ever want to go ahead   and do this dynamic referencing like we're doing  right now we need to make sure that through our   constructor argument that we're passing through  this position we're referencing so we could go   ahead and write position right here as the first  argument but i don't really like passing arguments   through a constructor this way instead i  like passing them through within an object   as a property and this means i only have to  pass through one argument within our constructor   and the ordering of our properties within this one  object right here do not matter if i did not have   this one object right here and i were to add other  arguments such as let's just say velocity while i   would need to memorize the order in which position  and velocity are placed within our constructor   function but if i were to place velocity within  our first object as the first argument well i no   longer need to memorize the order when i actually  create a boundary i can go ahead and interchange   these two if needed and it makes our job a lot  easier to actually develop this whole thing   so that's besides the point but a little bit of  coding tips for you to help better yourself as   a developer so we're going to go ahead and pass  through a position when we create a boundary what   else did we need well we needed a width associated  with the boundary and we're going to go ahead and   set this to a static value this should never  change i'm going to say this is equal to 40   and then we need a height i want this to be  a square so if we want to square our height   should be 40 the same as our width so those  are all the properties we really need for our   boundary to start but how should we actually draw  out a boundary what should it look like well in   order to determine what a boundary should look  like i'm going to go ahead and add a function   inside of our class called draw so draw right here  is going to determine what a boundary looks like   it's important to note that this draw function  is arbitrarily named i could literally name this   anything and this would still be a valid function  but it makes sense to us to call this draw because   we are drawing out our boundary it determines  what a boundary looks like so within our draw   function how do i actually draw a square well  what i want to do is select our canvas context   so i'm going to go ahead and grab that with no  other than c and now i can call the function   the method fill rect what does this take as  its arguments well it's going to take an x a y   a width and a height and what do you know we have  all those available to us within our constructor   function so let's go ahead and grab our position  of x we're going to do that with this dot position   dot x we know we need a y we're going to  select that with this dot position dot y   and then we need a width so we'll go ahead and  add this.width and then for our fourth argument   we're going to add this dot height so if i were  to create a boundary and actually call this draw   function we would indeed draw out a square but if  we don't determine a color right here that square   by default is going to draw out as black square  draws out as black on our black background we're   just not going to see it so before we actually  fill this rect we want to go ahead and call a c   dot fill style with a capital s and set it equal  to a string that determines what color it should   be so i'm going to go ahead and say by default  our outer boxes should be blue and now this will   draw a blue square on the screen when we actually  call this draw function so if i save and refresh   nothing happening just yet we need to  actually create a boundary to start   so just to show you that this is rendering  correctly let's go ahead and create a boundary   i'm going to create a const called boundary  with a lowercase b and set the sql to a new   boundary which references our class right here  and then i can go ahead and add some parentheses   and now you can see that it takes one argument  it's going to be an object with a property of   position so i'm going to add that object in  there with an opening and closing curly bracket   and then i can add the property of position and  now if we look at position within our code we're   referencing an x property and a y property so  position should be equal to an object with an x   set that equal two let's just say zero to start  and then a y which will also set to zero this   means it's going to spawn at the top left-hand  corner of our screen so go ahead and save that   and refresh still nothing and that is totally okay  because in order to draw this out we need to call   our new boundary object that we just instantiated  and then call the draw method on top of it   so now if i do that and refresh we have our  first boundary in place right here i'm going   to exit out of our console this is what everything  should look like to start we successfully drought   our first boundary within our game so there are  a couple of ways in which we can draw out a full   map with our boundaries one we could continue what  we're doing right here of creating consonants and   then eventually calling the draw method so what i  could do is i could copy this paste it below call   this boundary two and then make sure i'm placing  it to the right of this one that we just created   so we know the width of this is going to be about  40 pixels if i want to place directly to the right   i'll say position for x should be 41 and then make  sure i'm calling boundary2.draw now we have this   directly to the right of our first boundary now  why shouldn't we do things this way well it's just   really inefficient and it also muddles up our code  a lot we're creating all these different constants   we're calling the draw functions it means we have  all these different concepts to remember it's just   not a good way of doing things so what is one way  we can do this better what we could do is we can   go ahead and create a const called boundaries set  equal to an array like this so what we could do   is we can take these new boundaries we're creating  so i'm going to copy everything from new boundary   down to the ending statement right here cut it out  i'll delete const boundary i'll delete boundary   draw and what i just cut out i'm going to paste  inside of this boundary's object like so i'm going   to do the exact same thing for boundary two copy  new boundary and then make sure that i add a comma   because this is going to be a second element  within the boundaries array if i had a comma   here i could put a new one in there so i paste  that second one in i can get rid of this code   save and refresh and our boundaries are gone but  now we can do this a little more cleanly we can go   ahead and call our boundaries const loop through  it with a for each statement and we want to say   for each boundary within our boundaries array  i want to call an arrow function a callback   function that says to do what well i'm going to  select that one boundary object we're looping over   so the first iteration of the loop i'm only  selecting this one and if i only select this   one what can i do i can call boundary dot draw  and then eventually this for each loop is going   to go to the next one and call boundary.draw for  this one so if i save and refresh now everything   is still there but we cleaned up our code a  little bit because we're only declaring one cons   instead of what would have been many const so  if we wanted to create our full map what we   could do is we could go ahead and add a comma  here right at the end of our second boundary   paste in a new boundary and keep on going but  another issue with this is while we have to keep   track of all the different x and y positions the  order of this doesn't really matter in regards   to where we're placing these out on our map and  it's also going to give us just a ton and ton   of code if we want to go ahead and create a full  thing so although this method is better than the   last one it's still not perfect we can do a step  better so what else can we really do well we're   going to do and i think this is the best method  to create a map is we're going to create a const   right above our boundaries and call this map this  is also going to be equal to an array so what do   we do with this array well within this array we're  actually going to create a representation of what   our map should look like within our canvas so  here's how we're going to do it within this array   right here i'm going to create an additional array  so you'll see right here there's an array within   an array now that i have this nested array what  i'm going to do is i'm going to add a string and   then what i'm going to do is i'm going to use  a dash right here to say that whenever i loop   over this dash i want to generate a new square  this will make more sense as we go just stick   with me so we have this one dash string i'm going  to go ahead add a comma next to it and then paste   in a new dash string and i'm going to go ahead  and paste in let's just say about six of these   so save and refresh this is what it should look  like i'll expand that a little more we have   one row so each of these dashes is going  to represent one box within our game so to   take this further what we can do is we can select  this first array that we created within the array   and we can add a comma at the end of it and paste  in a second version of this array and i'm going to   add in a few rows so add a comma there paste in a  new array with all the dashes and then paste in a   new one you can go ahead and indent format this to  look exactly like what i have right here right now   if we were to render this out we would draw out a  six column by four row grid every time we have a   dash we're basically saying create a box so even  in the center we would have boxes so instead of   having boxes in the center we could go ahead and  add a different symbol here let's say we just want   a blank space we can go ahead and get rid of the  dash just put a space here instead we only want to   use one character so everything aligns perfectly  within these arrays i'm just going to go ahead and   get rid of all these dashes within the middle  of our game so within the third row i want to   go ahead and get rid of these dashes as well so  now if we look at this we have these dashes which   represent boxes and these boxes are creating  an outer perimeter with all this open empty   space in the middle so what we can do is we can  begin looping through this map and based on which   symbol we are currently looping over we are going  to determine whether or not we should place a box   or just keep it empty space so what we can do is  we can get rid of everything within our boundaries   array right here we're still going to keep our  boundaries array because as we loop through this   map we're going to be populating our boundaries  array we're just going to do it dynamically   so we also want to keep our boundaries for each  code down here because we need a way to call   the draw method on all the boundaries we're going  to be populating so we'll keep this as is but   right beneath boundaries what we're going to do is  we're going to select our map right here so we're   selecting this constant we want to begin looping  through it so we're going to call for each so for   each what what is the first array represent within  our map what's going to represent a row so what we   could say is for each row within our map we want  to call a callback function an arrow function like   so and now what do we do well we need to select  within our first row every symbol within the row   so how do we actually do this well the same way  we access any other element within an array we're   going to select our row so we have the first row  right now in the first iteration this one right   here and now we can go ahead and call for each for  each what within the row well these are going to   be symbols so it makes sense to call this what a  symbol arbitrarily named can be whatever you want   but we're going to go ahead and add an arrow  function to the end of that and now if i console   log this out just our symbol right here and then  i head on over to our browser refresh open up   our console you're going to see that all of our  symbols are logged out in the direct order they   are placed within our map so now that we have  our symbols selected we can begin populating   our boundaries array based on where each of these  is placed so in order to do this what i'm going   to do is i'm going to write out a switch statement  that says i want to switch out the symbol that we   are currently on so let's just go ahead and focus  on this first one symbol is going to be equal to   a dash so i'm going to create opening closing  curly brackets we're switching symbol out for   what what case well we need to go ahead and write  case and then specify what we want to switch out   so we're going to create a string of dash and say  whenever we hit a dash right here we're going to   call a colon and then activate some sort of code  after it and once we activate that code once   we're done with it we're going to call break which  breaks out of the switch case statement and then   we'll proceed us on to the next loop iteration of  our for each statement right here so i want to say   if we're looping over a dash within our map  i want to select our boundaries array and i'm   going to push into it a new boundary what does  boundary take it takes an object with a position   property which is equal to an x and then also a  y so if we were to save this as is and refresh we   have all of our boundaries drawn in the top left  hand corner because all our positions are x and y   but i can guarantee you we have more than just  one boundary being created because we specified   that we have one two three four five six seven  probably like 15 to 20 different boundaries within   this array right here but in order to make sure  that they're drawn in the correct spot we need   to understand first what row are their associated  symbols in are they in the first row second row   third or fourth and then what column are they  in zero one two three four five six which row   and which column are they in how do we get the row  and column indices well within for each we have a   row being passed through but we can add a comma  to the end of this right here this argument and   then we can go ahead and add in an argument for an  index so we can call this whatever we want really   doesn't matter but for me whenever i loop through  something i just like short handing it with i   this stands for index you can go ahead and write  index out as well that's totally okay but i'm just   going to use i because we're going to be using a  second index within this voyage nevertheless this   i right here represents what row are we currently  on within our for each loop so we're going to be   looking through row zero row one row two and row  three so we know with our rows when they go down   we're dealing with a y coordinate so what we can  do is we can go ahead and select the width of one   of our boundaries what was the width of owner of  boundaries well it's going to be 40. and now let's   think about this since we have this index remember  if we loop through the first row right here   our index is going to be equal to zero so on  the first iteration of this loop 40 times zero   it's going to make sure y is zero it's going  to put our first one right here but if we go   to the next iteration of i this is going to be  equal to one so we get i right here equal to   one multiply it by 40 then we're going to push y  down by 40. the next iteration of our box is going   to be right beneath it so if you think about it if  we multiply 40 by our row index i save and refresh   you're going to see our rows were just created  for the left side right here the reason they   haven't been created for our columns as well  as you see right here with our map is simply   because we haven't set x equal to anything other  than zero so each boundary has a width of 40   and we know that once we're within a row we're  looping over each symbol so what is the index of   this first symbol it's going to be zero what is  the index of the second symbol it's going to be   one then we have two three four five we're just  going to keep going until we finish through this   whole array within the first row if we want to  go ahead and grab the index associated with each   symbol we can go ahead and add a comma to the end  of symbol right here and then add in j and now we   have the associated index so once we're looping  through the indices we can go ahead and multiply x   by j right here save and refresh and now we have  a perfect one-to-one representation of what we   see in the map if we wanted to recreate this using  one of the other methods well we'd have to create   probably around 15 to 20 new boundaries within our  code and so what would have been probably around   100 lines of code we did it in about i want to  say just 20. so a lot easier it's going to save   you a ton of time and it's going to make things  way easier for you in the future if you want to   generate multiple levels for your pacman game  super super cool way of doing things so before   we go ahead and check off generating boundaries  within our to-do list i want to do two more things   the first thing i want to do is i want to lay out  a little more of a level i just want to go ahead   and extend this by one row and then draw out some  boundaries right here within the middle of this   actual map we created and that way we get a little  bit of flexibility for developing our collision   detection so in order to do this i'm just going  to copy one of the lines right here within our map   i'm going to paste in that new one and then i know  right here is the very center of our map so i can   go ahead and get rid of the space add a dash in  the places i want a box drawn i can save and then   refresh and now we have this little corridor in  which our pac-man will be able to travel through   it's going to be really good for development  to get things set up this way as we do our   collision detection and now the very next thing  i want to do is you might note right here we are   using a static value of 40 for both our width and  height to move the position of our blocks around   so although we could just use 40 here if we  come back to this code at a later point in time   it's going to be hard for us to remember  what this value actually represents   so instead of just referencing 40 we want to  reference some sort of variable that references   our boundary width so how do we get our boundary  width while we could create a new boundary   like so above and assign it to a variable but  that's just extra code it's unnecessary what we   can do instead is within our class right here we  can create a static property so what i'm going to   do is right beneath boundary and above constructor  i'll go ahead and declare i want a static property   by adding the static keyword and then what  property do i want to be static well a width   property and i'm going to set this equal to 40  like we have down below and then i'm going to do   the same thing for height so now that i have these  static properties i no longer need to create just   a new boundary in order to set this position right  here instead i can just go ahead get rid of the 40   and reference our boundary class like so and then  i can call on top of it the static property we   want to get which is going to be width and then  the same thing for our y coordinate right here   it's going to be our boundary dot height so these  are both equal to 40 but i don't have to create   that object and i'm still referencing the exact  boundary with right here we just have to make   sure they're the same within our class not that  big of a deal so if i save and refresh everything   still works correctly but now when we come to  this code later on we'll have a lot easier time   understanding because we replaced our static  value with something that's actually readable   so now if i go back to our to-do list we're  going to go ahead and check off generating map   boundaries so the very next thing we're going to  do is add a pac-man with movement we're just going   to spawn a circle right here and then we want  him moving around we're going to go outside the   boundaries to start we just want to make sure we  have a pacman that's moving and then once we do   that we'll add the collision detection to make  sure he can only stay within these boundaries   so let's go ahead and add a pac-man so in order  to add a pac-man what i like doing is creating a   class called player you could go ahead and call  this pac-man i'm just so used to creating a class   called player for the main thing i moved i'm going  to go ahead and call my class player this is going   to have an opening closing curly bracket and  then i'm going to create a constructor like so   and then i need to determine what makes a player  what makes a pacman well we know our player needs   to be drawn and moved across the screen so if  you ever need something drawn on the screen   you're almost always going to have a position  property so we'll add at this stop position   and set it equal to a dynamic position will pass  through our constructor we're also going to have a   velocity so this dot velocity we'll go ahead and  also pass this through and velocity just means our   player is going to be moving so that's why we're  adding that and then we know pac-man is circular   so we're going to need some sort of radius we'll  add this.radius and let's just say pacman is   going to have a radius of about 10 pixels to start  we'll go ahead and tune this as needed so now that   we have our properties in place that should be all  we need to draw to pac-man we'll add a draw method   like so now how do we draw out a circle whenever  we call draw well we're going to want to call   our canvas is arc method but before we call that  arc method in order to use this we need to call c   dot begin path to tell our canvas context we  want to begin a path such as an arc so now   that we have begin path in here we can call c  dot arc this takes quite a few arguments you'll   see right here the very first is going to be an  x position second is going to be a y position   so let's go ahead and take care of those two to  start what is x going to be equal to well this   dot position dot x our second argument right here  is going to be this dot position dot y what comes   next well we have a radius which is equal to a  number what do you know we have a radius property   within our player so we'll go ahead and reference  this.radius and then we come to the hard stuff   it's going to be star angle and angle so these  two arguments right here these are going to be   in radians just a fancy version of degrees so if  you need to learn a little bit more about ratings   and drawing circles you can check out my video on  circular motion and it goes pretty in depth with   ratings and also things such as sine and cosine  to create circles but nevertheless we're going to   go through this pretty quickly we know the star  rating should be zero which means we just start   at one point of the circle if we want to create  the full circle we're going to reference math   dot pi and multiply it by two because in radians  math.pi just means have a circle we multiply that   by two we're going to get a full circle we don't  need the sixth argument in there so we can just   call c dot arc then we want to call out c dot  close path so we seem to be in good shape but   one thing we need to do is to declare the fill  style of our pacman so if i go ahead and say c   dot fill style is equal to yellow right before  we close the path well now i have the fill style   in place i need to actually call c dot  phil to fill up this arc we just created   so go ahead and call c dot phil like so save  and refresh no pacman simply because we have   the blueprint for our player now we actually need  to create an instance of our player to draw it out   so in order to create an instance of our player i  can go ahead and create a const and i'll actually   do this right beneath boundaries i'll create a  const called player lowercase p equal to what   a new player object and this doesn't take any  constructor arguments because we haven't specified   any so let's go ahead and make sure we do that we  want to pass through one argument an object which   has two properties a position property and then  comma velocity property so now that this is within   our constructor when we create a new player  we can add what one argument with a position   we're going to set this equal to an x that is  equal to let's just say 40 to start and then we're   going to say our y should be equal to 40 as well  and then we need to right beneath our position   at a velocity which is also going to have an x and  y i don't want this moving at all so let's set x   equal to zero and then y equal to zero as well  so we took care of the two properties within our   constructor right here and now all we need to do  is draw out our player so right beneath where we   are drawing out our boundaries i can call player  dot draw save and refresh we have our player   drawn out on the screen perfect so in regards  to positioning if we want to make sure that our   pac-man is drawn right here instead of this little  corner where the boundary is what we can do is we   can go ahead and alter its original position so  right now this is 40 40 but if we want to go ahead   and spawn it there we can be a little cleaner with  our code so instead of referencing 40 how do we   reference 40 when we're creating boundaries we use  the static property of boundary width and boundary   height we're going to do the exact same thing for  player so instead of referencing 40 right here for   x we'll go ahead and say place it at boundary  width that's going to move us on the x-axis   over to about here and if we do the same for a  height we just move down on our y-axis to where   we are right now but how do we get this position  right here well if you think about it if we move   over half the distance of one of these boundaries  on the x-axis we're going to be placed right in   the middle right here and if we move down half the  distance on the height of one of these boxes we're   going to be placed right where we want to be so  for x we could say add on the boundary dot width   and divide it by two and this should push us right  about here save and refresh we are there and now   we want to do the same thing for height add on our  boundary dot height divided by 2 and we are in the   perfect location we don't actually fill up much  of this actual corridor though so let's go ahead   and increase our radius for our player to not 10  but rather 15 we save and refresh and now we're   filling up a good chunk of everything we see so  how do we get our player moving now that we have   it drawn out on the screen well we need to listen  for events within our keyboard we're going to move   our player using the wasd keys that's pretty  standard for any movement within a video game   so in order to add these event listeners  we're going to go to the bottom of our file   and then call window dot add event listener  this takes a string as the first argument   of what event do we want to listen for well  we're going to want to listen for a key down   event so whenever a user presses down on our  keyboard we want to call some sort of function   as our second argument so for a second argument  i'm going to add in an arrow function like so and   remember anytime you have window dot like we have  right here you can just go ahead and get rid of it   because the browser is smart enough to know that  we are calling out event listener on top of it   and make sure you spell listener right like me or  else this won't work at all so i add the e there   we should be good to go i can go ahead and console  log out some code just anything within a string   refresh open up our console the shortcut for that  within chrome by the way is command option j which   is how i'm opening it up so quickly and you'll  see right here if i refresh again we don't have   anything within our console but if i click on our  game and i start pressing down on all of our keys   well each time i press down on a key we're logging  out to this code right here so we are successfully   listening for key down events now we only want  to listen for events and where we press wasd so   in order to do this within our callback function  right here we can pass through an event object   let's go ahead and console.log this out i'll  console.log out event save and refresh hit some   keys and we're logging out to this keyboard event  so you'll see inside of this this has all these   different properties associated with the actual  pressing of a key maybe too much for something so   simple right so if we scroll down we have things  such as code we have things such as whether or not   the control key was pressed along with this and  then we also have what key we pressed so you'll   see right here key is equal to d i just hit the d  key and event right here was smart enough to know   that so if i want to go ahead and just select this  one property within console log i could reference   event dot key like so but we can make our code  cleaner because we know we're going to be using   event dot key for multiple keys and instead  of having to prefix key with event every time   within our argument right here we can go ahead  and add opening and closing curly brackets   to destructure this property we can say as long as  we have curly brackets right here we only want to   grab the exact properties we specify what property  do we want to grab here well we want to grab   the key property that is from our event object  so all we have to do within these curly brackets   is type key and now we have the key property  you can see this as i call it log out just key   refresh and then start pressing on our keyboard  asd w we just logged out to the exact key we are   pressing down but we don't need to reference that  event object makes our code a little cleaner and   easier to read so now i want to call different  code for each key that we press here for wasd   so what i'm going to do is i'm going to add  a switch case statement that says to switch   out whatever key we're pressing if we press  down a case of let's start out with the w   key which means we should go up we add a  comma to the end of this and then we break   in between this case and this break we can  specify what we want to happen so what do we   want to happen whenever we press w we want to  go ahead and change the velocity of our player   to be going upwards so here's what i'm going to  do i'm going to go ahead and select our player   select its velocity on the y-axis and whenever  you want your player to go upwards on the y-axis   you should set the value equal to something  that's negative because on canvas with the y-axis   when we reference a value up here for y we're  going to start at zero and the further down you   go the greater these values get so the y-axis is  reversed simply because when we're dealing with   web development things start out at the top of the  page rather than the bottom so we know that our   player should be going up when we press w so our  player velocity should be equal to something like   negative five we're going to push our player  upwards so that's going to take care of the   case for w when we press w now we can go ahead  and copy these three lines paste a new one below   and say what should our case be for a when  we're supposed to go to the left well our   player velocity on the x-axis should be negative  five so that just means we're going to the left   we want to do the same thing for s and d so we're  going to go ahead and add a case right here for s   and really quickly i'll go ahead and paste in  another case for d so let's go back and focus on   s when i hit s i know i want to go down so we're  going to select our y axis and whenever we go   down we're going to be adding a positive value  we're going to be assigning y a positive value   and then for d we should be going to the right  so on our x-axis right here we're not going to   go in a negative direction we're going to go in a  positive direction over to the right so what i'm   going to do here is i'll delete our console log  actually i'll cut it out and then i'm going to   paste it beneath our switch and then i'm going to  log out our player dot velocity save and refresh   and now when i hit w you'll see our y velocity  is set to negative 5. if i hit a now we have   negative 5 negative 5 s is going to be negative  5 5. basically all these velocities are changing   based on which key i'm pressing the thing is we  haven't actually set our player to move based on   these velocities so we need to go back up to our  player class right here and we determine what a   player should look like when it's drawn out on  the screen but we haven't determined how our   player should move when we call an update function  so what we're going to do is add a function called   update and basically we want this to be called for  every frame of an animation loop so within here   what are we going to do we're going to go ahead  and draw out our player we're calling this.draw   which just calls all this code right here and then  we're going to select our position on the x-axis   and for every frame we loop through we're going  to be adding on our player's velocity so this   dot velocity on the x-axis we want to do the exact  same thing not just for x but also for y for each   frame that we loop through so we have this update  function which determines how our player should   move over time let's go ahead and find where a  player has been drawn right here replace draw   with update save and refresh and start moving  around on your keys and you're going to notice   nothing is happening our player is not moving  even though we just updated that update function   why well it's because this code right here where  we're drawing out player update and boundary draw   it's only being called once on initial load of  this index.js file we need to create an animation   loop that calls this code for each frame of the  animation it's just going to keep calling itself   until we tell it to otherwise so to create an  animation loop i'm going to go ahead and create   a function called animate create some opening  and closing curly brackets and now inside of this   function i want to call request animation frame  comes from the window object takes one argument   what is the function we want to loop through well  it's going to be the parent function that this is   inside of so it's going to be animate whenever  we complete one frame we're going to call this   animate function again is what it says it's going  to create an infinite loop for us until we tell   it to stop otherwise and we can always test  that this is working by adding in a console log   and let's just add some gibberish right here and  then we need to activate the animate function   by actually calling animate and then adding  these ending parentheses to call the function   so if i save and refresh now we have this looking  through super fast we just created an animation   loop but we want to go ahead and make sure  that we're drawing out our boundaries and we're   drawing out our player for each frame of this  animation loop so i'll get rid of the console log   and replace it with our boundaries for  each code and also our player update code   we save and then refresh that's all being drawn  out and now when i hit d on our keyboard we call   that update function which should be adding  some sort of velocity onto a player's position   over time for each iteration of this loop watch  what happens i hit d our player is moving super   quickly across the screen and we're actually  creating some sort of artwork on here as well   and you'll see if i refresh if i hit down i  could press all over the place to create this   pretty crazy artwork this might be pretty cool  but obviously it's not what we want for our game   the first thing we want to do is make sure that  we don't create these lines as we move through   our screen so every time we call animate we're  drawing out our player in a new position but   we're not actually clearing our canvas which is  going to give us a completely blank slate to drawn   so whenever we call request animation frame  right after it we want to clear the canvas   we're going to do that with c dot clear rect and  then this takes an x a y a width and a height so   from which position do we want to clear our canvas  i'm going to say from the very very start of our   canvas for x so right over here or both x and  y at the very top left corner of our canvas and   then i want our canvas to extend the full width  and the full height of what we have right here   i want to clear the whole canvas width and the  whole canvas height for our fourth argument and   with this if we save and refresh and start moving  we no longer have that drawing issue although we   definitely have some sort of issue with moving now  that we're going diagonally in all these different   directions so our player is moving diagonally  whenever we hit multiple keys on the keyboard   because within our key down function right here  if we hit w we might be going upwards setting our   player velocity y equal to negative five but if  we go to the right at the same time by hitting d   we're also setting our player velocity x to five  as well so we have a velocity of five for x and   negative 5 for our y that means our players  should be moving diagonally not in just one   linear direction where we're going down left  top or to the right so here's one way you may   think to fix this is we can go ahead and copy this  event listener we have right here this whole thing   and right beneath it we're going to go ahead and  paste it and then instead of listen for a key down   event we're going to go ahead and listen for a  key up event so if we think about it if we hit   right on the keyboard if we hit d we're going  to set the player velocity x equal to 5 which   means we go to the right but if we key up on d  maybe we should set our player velocity on the   x axis back to zero so it stops moving so let's go  ahead and try that out for each key we lift up on   i'm going to go ahead and set the velocity  equal to zero and then i'm going to save   refresh and let's go to the right i'm going to  hold down on d we go to the right i'll lift up   and it stops let's test for going down  and hit s lift up and we stop hey right   lift up we stop hit up lift up we stop now this  works great if we were to only be pressing down   one key at a time the real issue here comes  when we try holding down two keys which we're   definitely going to be do when we try navigating  this course so for instance if i start going back   and forth between the left and the right  watch what happens i'm going to go all the   way to the right to illustrate this and then  when i try going back and forth really quickly   you'll see i'm holding down a and eventually only  get started after holding it down for a while   and that only even happens because i have it  on my keyboard so that when i'm holding down a   it's actually just repeating that input  over and over and over again really quickly   if i didn't have that in place while we'd just  be stopped because our key up code is interfering   with our key down code if we're holding down both  a and d to go left and right at the same time well   of course it's going to be equal to a value but if  we lift up on one of those while both of them are   down we're going to be setting the velocity equal  to zero even though we might be meaning to go   in some direction so in order to alleviate this  we're not going to be setting our velocities right   here within our event listening we're actually  going to be setting them within our animation loop   but we need to know which keys are currently  pressed down and what was the last key we   pressed down in order to get the correct effect  so here's how i like doing this is i like creating   i'm going to do this right above our map right  here and before i create this i'm actually going   to go ahead and move map right above the four  each just to make our code a little easier to read   but i know right here this is where i want  all my implementation variables to go so i   know i want to create a const called keys this  is going to be equal to an object that's going   to help us determine what keys are being pressed  down so i want to start off with our w key create   a property called w and then within this w object  i'm going to have a property called no other than   pressed is the w key pressed by default no it's  not so we're going to set it equal to false i'm   going to do this for w a s and d so i'll go ahead  and copy w add a comma and i'll do this four times   so i have w a s and d and just make sure you have  a comma everywhere that is needed and now we have   this set up correctly to track which key is  currently being pressed so if w is pressed   where should we be changing this property right  here well within our event listener so whenever   we press down w we're no longer going to change  our player velocity but rather we'll go ahead   and select keys what key do we want to select  well this is going to be w is it pressed down   yes it is so we're going to set that equal to true  so we can grab this line of code right here delete   and then paste in keys not w but a dot pressed is  equal to true we're going to do this for s as well   delete the velocity we're not selecting our a key  we're selecting our s key and then when we press   down d we want to say that d is pressed down so  we also need a way to determine when the key is   not pressed we're going to do the same thing for  key up we're just going to set these back equal   to false so i'm going to go ahead and grab keys.w  pressed delete velocity right here and let's set   this equal to false and i'm going to do this for  each key that we have for our game set keys dot a   dot pressed equal to false and then i can do the  same thing for s set this equal to false and then   do the same thing for d we're going to set this  also equal to false so now we have a way to track   when multiple keys are pressed down at the same  time and when each one is lifted up so instead   of console logging out player velocity i can  count log out keys dot d dot pressed and i'll   also console log out not just d but also let's  go ahead and say s and then i'm going to also   also log these out whenever we key up so if i save  and refresh that and i hit our d key well you'll   see the first value right here d is equal to true  and then the second value is equal to false and   then when we lift up we have a false and false  which means we're both lifted up but if i press   both of these at the same time both d and also  s we're getting double trues which means that we   have the ability to track whether or not keys are  pressed down at the same time so using this we can   begin moving our player within our animation  loop instead of within these event listeners   so to do this we're going to go ahead head on  over to animate and beneath player.update i can   go ahead and say if keys dot w is pressed meaning  that it is pressed down what do we want to do   we want to go ahead and select our  player specifically the velocity   on what the y axis we want to go ahead and set  this equal to a negative value so we're going to   set it equal to negative five just by saving and  refreshing if i hit w we start going upwards and   this never actually goes back to zero because  we never set it well to zero if we wanted our   player to stop when we lift up well we can simply  call player.velocity.y right here whenever we go   through our animation loop before we actually  alter our velocity and set this equal to zero   so it's always going to be zero to start but it  might get overwritten which means we're going   to be moving our player so if we go ahead and set  this equal to zero refresh hit w again and lift up   we stop because we set it equal to 0. so now let's  go ahead and add in our other keys we can add else   if what well if our keys dot a is pressed like  so what do we want to do we want to go ahead   and set our player.velocity on the x-axis equal to  negative five means we're going to go to the left   and now we can simply copy this else if statement  paste it twice and now we can go ahead and select   not keys dot a but keys dot s that means we're  going down so we want to affect our y velocity   and say we want this equal to a positive  value that's going to push us downwards   and then if we press keys dot d we're going to  be going to the right on the x axis so we're not   selecting negative five we're selecting five this  should give us some pretty basic movement using   the animation loop instead of the keydown event  listener so i save and refresh i hit s we're going   down i lift up we're set to zero again i hit d we  go to the right i lift up while we're not stopping   simply because player velocity on the x-axis is  not set to zero so we'll copy this line right here   change y to x set that equal to zero before we  actually go through this refresh and i want to hit   d and i lift up we stop hit s we lift up stop we  can move in all these different directions using   this simple code right here within our animation  loop and you might be thinking well we should be   good to go with this right well not quite we  need to add a last key property as well why   well if we're going through this if else if the  first statement right here is going to be called   before the next ones if they're pressed at the  same time so let's go ahead and start at the very   bottom i'm going to go ahead and press s and d to  our player is right here let's go ahead and say i   start going upwards by pressing w and then i  want to go to the right i'm going to hold up w   and then press d which means we should be going  to the right watch what happens i press w press   d and we just keep on going why well because  we're only calling this first line of code   because w is pressed a is pressed as well that was  the last key we pressed down but this code is not   going to activate simply because this one comes  first this is the priority so in order to make   sure that we go the direction of whatever the  last key was we need to add that last key property   so in order to add this i'm going to go up  to where we are adding all these properties   and instead of declaring a const i'm going to add  a let set it equal to last key and then this is   going to be a empty string by default so with this  last key property i can begin setting it within   our event listeners so whenever we press down w  i'm going to set last key equal to a string of w   and i'm going to do this for every single case we  have so we'll copy this line paste it in a change   w to a paste it in s change w to s paste it in d  and change w to d so each time we press down on   one of these keys we're basically overriding the  last key that we pressed down no matter if two   three or four have been pressed we don't need to  do anything within key up we just need to track   the last key that was actually pressed down  so now we have this in place we can add on to   our conditional here that says if w is pressed  if we're supposed to go up and our last key is   equal to w then we want to go up but if our last  key is not equal to w and we recently pressed d   while w is being pressed up well then we want to  call this code instead so we're going to go ahead   and add this and statement onto the end of keys  a dot pressed and say if our last key is equal to   a then we want to go to the left actually i think  i might have messed that up nevertheless we're   going to go ahead and add this conditional on  to each condition that we have so let's go ahead   and paste that on in there we'll say this one  right here is not referencing the last key a but   rather s so we'll change if the last key is equal  to s we want to go down and then if our last key   is equal to d which we see right here we want  to go to the right so just by adding this code   saving and refreshing we're going to  start off in the same spot down here   so now when i start going upwards by hitting w  and if i hit d while w is pressed we should go   to the right instead of just continuing upwards  so i hit w hit d we go to the right and now i   can have multiple keys down and start moving in  all these different directions and weird stuff   isn't going to happen with our movement like  it was earlier without last key and when we're   just activating our player velocity within these  event listeners so this is going to set us up for   success when we're moving our player around our  actual level right here so i'm going to go ahead   head on over to to do and say that we added a  pacman with movement so next up we're going to   go ahead and add collision detection so that we  can only stay within this boundary right here   okay so how do we add collision detection  into our game well we're going to need to know   circular to rectangular collision detection now i  don't have a video on specifically that but i do   have one on rectangular to rectangular collision  detection it's probably helpful to view that even   before going onto this one so you can check it  out right here but let's get right on into this   so essentially what we want to do is we want to  loop through every boundary we have within our map   and we want to check whether or not our player  right here is overlapping any of those boundaries   if they are then we want to stop our player's  velocity altogether so where within our code are   we looping through all of our boundaries well it's  going to be right here so we can continue writing   this collision detection code directly within this  for each statement specifically for our boundaries   so we know we're grabbing one boundary at a time  how do we determine whether or not one of these   boundaries overlaps with our player while we can  write an if statement and then we want to go ahead   and compare the sides of our player to the sides  of one individual boundary so let's go ahead and   start with the top of our player how do we grab  the top of our player when our position point   is directly in the center well to get the top of  our player we'll go ahead and say if our player   dot position not x that gives us the center of our  player minus the player dot radius that is going   to give us the top so we want to say if the top of  our player is overlapping with the bottom of one   of these boundaries how do we go ahead and get the  bottom of one of these boundaries well first let's   let's finish our conditional right here we want to  say if the top of our player is less than or equal   to one of the bottom of the boundary so getting  the bottom of the boundary we're going to go ahead   and get our boundary that we're looping through so  this right here specifically the position on the y   axis so that's going to give us the top  of a boundary and then we want to add on   our boundary dot height and that is going to give  us the bottom of a boundary but before we proceed   make sure you don't do what i did right here we  are currently referencing the top of our player   so we want the coordinate on not the x-axis but  the y-axis this will give us the top of the player   this gives us the bottom of one of the boundaries  so we know if the top of the player is less than   the point right here where the bottom boundary is  we know the two are colliding we also need to add   a code for whether or not the right of a player  is colliding with the left of a boundary as well   so let's go ahead and do that we can add an end  statement right here and we're going to select our   player position on the x-axis and to get the right  of our player we're going to go ahead and get our   player radius add it on to our position.x and then  we want to say if this is greater than or equal to   the left side of our boundary so we're going to  get our boundary dot position dot x that'll give   us the left side then we know we are colliding  with the left side of the boundary we want to   keep going let's go ahead and do the bottom of our  player we'll add an ad statement in here that says   if our player does position on the y-axis plus our  player dot radius so now we have the bottom of the   player is greater than or equal to our boundary  dot position dot y that's going to give us the top   of the player then we know we're colliding on the  y-axis specifically for the bottom of the player   and the top of a rectangle so we have one more  the leftover player let's go ahead and add an and   statement that says if our player.position.x so  that's going to give us the center of our player   minus our player dot radius that will give us the  left hand side is less than or equal to what well   we need the right side of a boundary so we'll  select our boundary position.x that gives us a   left side so we need to add on the boundary  width that'll give us the right side of the   boundary then we know our player is colliding with  a boundary this is all the code we have to write   to get accurate collision detection in place so  within this if statement i can go ahead and say   console.log we are colliding if this is true so if  i save and refresh and we look within our console   you'll see this is not being logged out  but as soon as i start overlapping we are   currently colliding when the top of our player is  overlapping the bottom let's go ahead and check   this for all of our sides if we overlap with the  leftover player we're getting that and then if we   overlap with the right we're getting that and then  if we overlap with the bottom we're getting that   as well so we have accurate collision detection  in place but now we need to go ahead and stop our   player not when we lift up on a key but when we  hit one of these boundaries so we know by default   we're setting x and y equal to zero because before  we wanted to stop our player whenever we lift it   up on one of these keys the pacman movement the  player always moves until it actually hits a   boundary so we're actually going to comment these  out we're probably not going to use these anymore   but we do need to comment these out to get the  effect where we stop whenever we hit a wall   so if we are colliding what should happen well  let's go ahead and set our player dot velocity.x   equal to zero inside of here and we'll go  ahead and set our player velocity dot y   equal to zero as well we're just going to stop  our player completely if they're colliding with   one of these boundaries so let's go ahead and  save and refresh and then we go to the right   and now we stop completely but you'll notice if  i try to go down after we collide with the right   side of our player i'm hitting s right now nothing  is happening i'm hitting up nothing's happening   i'm hitting right nothing's happening i'm  hitting the left nothing is happening why is that   well now that we are overlapping with the wall  over here this code is continuously being ran   we can't change our position if this is just  continuously going to be true so what we have to   do is within this equation we need to take into  account our player is going to have a velocity   so if we add velocity into this collision  detection equation we can detect whether   or not our player is about to overlap with a  wall over here and if they are about to overlap   then we are going to set their x and y velocity  equal to zero but it's still going to allow us   to continue calling this code down here so right  here this is the top side of our player we want   to go ahead and say if the top of our player  plus our player velocity on the y-axis so plus   player dot velocity on the y-axis is less than the  bottom of our boundary and the reason we're adding   on our velocity right here is because this value  is going to be negative whenever we're moving up   velocity dot y is negative so basically  if we add a negative value onto this we're   essentially subtracting it so that takes care  of the top side of our player we want to do   the same thing for the right side of our player  we're going to add on our player dot velocity   dot x and now for the bottom of our player  we want to add on our player dot velocity   dot y and then we want to make sure for the  left side of our player we add on our player   dot velocity dot x so now we're only going to  be colliding if one of the sides of our players   plus its current velocity is overlapping with the  rectangle so our player is never actually going to   overlap but it will allow us to set our velocities  equal to zero setting this equal to false and then   allow us to follow the coloring code and render  it all out so if i go ahead and save and refresh   and i try hitting the side over here you're going  to see we actually stop before we hit it because   we have that velocity added into our collision  detection code but since our velocity on the   x-axis is zero now this is going to be set equal  to false so if i go ahead and try heading down   we're going to be allowed to move down now instead  this actually works in all directions no matter   which keys i press we never get stuck and we're  limited to this little grid that we have right   here for movement so this is looking great but we  do want to test for if we have a gap somewhere in   the center so if we're moving and we're holding  down we should be able to pass through that gap   so let's go ahead and add one of those in order to  add a gap into our game well it looks like we're   going to need to create one more column right here  so to create a column what i can do is i can go   ahead and copy one of these guys at the top within  our first row paste it in and then i'm just going   to do the exact same thing for our other rows  just paste in that same character and you see   on refresh now we just have this big wall right  here so we'll go ahead and change the dashes on   the inside to spaces because we know we want our  player to be able to move out freely through these   so i'll change those right there looking good and  we want to fill in this one spot there so i'll go   ahead and do that now replace our space with a  dash and then right here in the middle i want to   make this dash a space so i'll do that save and  refresh so now we have this little gap which we   should be able to travel through so you'll see  with this if i try getting inside the center   it's really hard to do because whenever i go to  the side and i hit up well that time i got it but   whenever i go to the side i hit down or up on the  bottom it's just not exact i have to really time   it exactly to get in there and we're not actually  moving we stop whenever we hit one of these blocks   we want to make sure that we never stop and that  when we're holding up while we travel side to side   that we actually move through this right here  so we need to go into our animate loop and add   some conditionals that predict the movement of our  player in all directions basically we're going to   be moving to the side and as we hit up right here  we need to predict whether or not we are about to   collide with this one boundary right here if we  are about to collide we're not actually going   to be changing our y velocity so that we do and  we stop we're just going to make sure that our   y velocity is equal to zero but if there are no  collisions while we're holding up that is when   we're going to change our y velocity to five so  the code we need to edit in order to do this is   going to be our if statements where we're holding  down on one of the keys now it kind of makes sense   that when we're altering our player's velocity to  call this before all of our rendering codes i'm   actually going to move it right beneath clear rect  that way i can read our code more clearly and say   whenever we press down on one of these we're going  to detect for a collision right after we change   this velocity so it's just a little easier to  read at least for me i'm going from top to bottom   within my code so let's start with trying to get  through the gap when we're on the bottom here   so as i move to the side we have this collision  detection in place that allows us to go side to   side of course but when i go to the right and  i hold up i want to be able to hold w without   affecting our player velocity dot y because as  soon as i do this this code down here is going   to trigger because we're going to be colliding  with this one boundary right here and what happens   when we collide with it while we set our x and  y velocity equal to zero it just makes us stop   completely we don't want to do that we want to  go ahead and predict if we're going to collide   into this and if we are then our y velocity is not  going to be equal to negative five it's going to   be equal to zero but if we're not colliding with  anything then we are going to set this then we're   going to start moving up so how do we detect  how do we predict into the future that we are   colliding with a boundary well we just simply need  to use this exact code that we have right here   now if i were to go ahead and copy this and say if  within our w key we go ahead and calls collision   detection code it's going to make our code very  very messy so if you're just going to reuse a   conditional like this it makes sense to create  some sort of function to make your code a lot   cleaner so right above animate i'm going to  create a function called circle collides with   rectangle because this is circular and rectangular  collision detection i think that makes sense to   call it that and then i want to go ahead and  return that exact conditional that we had for   our collision detection so i'm going to go ahead  and wrap these in parentheses and then just make   sure that i delete this if statement down here so  i can auto format my code and it's going to look   like this so when we use this function we're  going to want to go ahead and pass through   an object with two properties because we're  going to be passing through two objects   into this to test whether or not they collide what  is the first property the first object we want to   pass through it's going to be a circular object so  call it circle and then the second one is going to   be a rectangle so we're going to pass through a  rectangle property as well so now that we have   these properties within our function we just need  to make sure that we refactor this conditional   right here so what i'm going to do is any place we  have player i'm going to go ahead and select each   of these by hitting command d with player selected  in sublime text you see as i keep hitting that we   keep going to the next iteration of player and now  if i go ahead and change these and paste in our   circle instead this function is going to work the  same way but we need to make sure we're doing the   same thing for our boundary as well so wherever  we have boundary we want to replace it with   no other than rectangle so i'm going to select all  of our boundaries with command d and sublime text   and then paste in rectangle and now we can  begin using circle collides with rectangle   so right here within our f statement let's go  ahead and make this about five lines of code we're   going to change it into probably three or four so  we're going to call circle collides with rectangle   we know it takes a property with a circle  what is our circle it's going to be our player   and then it takes a rectangle this is going to  be our boundary so if i save that and refresh our   code should function exactly the same which  it does so that is great but now we can use   this function right here in other places such  as within this if statement right here so as   i mentioned we want to predict whether or not our  player is going to collide before it actually does   so let's start with nw when we're going up to  predict this we want to write an additional if   statement with the circle collides with rectangle  code and then i'm going to add open and closing   curly brackets and we'll just throw this inside  of there for now just to get the ball rolling so   if we look at this code what is missing while we  have a circle which is equal to our player we're   referencing boundary but we don't actually have  a place in which we can pull boundary from right   here down below is where we're looping through  and getting this boundary object so whenever we're   pressing up on w we also want to loop through all  of our boundaries to detect for a collision so in   order to do this we can go ahead and copy this  line right here where we're looping through our   boundaries and then we can go ahead and wrap our  if statement inside of it so i'm going to do that   and then i'm going to add an ending curly bracket  and then ending parenthesis should look something   like this so right now this is saying if we're  hitting up on the keyboard and we collide with   any of these boundaries while we're going up while  we're going to set our player velocity on the   y-axis equal to should it be negative 5 or rather  zero because whenever we collide with something   well it should be zero but if we're not colliding  with anything we want to write an else statement   and this is where our player velocity is going  to be equal to negative 5. this is when we should   actually be able to go up so if i save and refresh  this i go down i go to the right well we still   have the same issue why is that because we're  not actually predicting the next move we're still   using the very same move we're on getting the same  velocity from our player that we're getting down   here where we're actually setting everything to  zero so how do we predict the next move here's how   we're going to do it we need to edit this player  that we're passing through and or a function and   we just need to edit the velocity property just  that so how do we pass player through right here   while only editing its velocity property well we  can use some really cool javascript syntax if i go   ahead and wrap player and an object like so well  now we're just creating an object with a property   called player assigned to player that's not what  we want we want to go ahead and use the spread   operator which is just dot dot dot so all the  properties and methods right here within player   are going to be put directly within this object  we're basically just duplicating our player object   but by doing so it's going to allow us to edit one  of the properties how do we edit just one of the   properties with the syntax well we can add a comma  to the end of dot dot player and now we can go   ahead and reference a velocity property which we  know is on player so right now we're only changing   a property for velocity all the other properties  associated with players such as position   those are going to remain intact but if we want  to change this or velocity we could say we know   our velocity x is going to be equal to 0 because  we don't want to test in that direction when we're   pressing up on our keyboard but for y we want to  go ahead and edit our velocity to be negative five   are we colliding with any rectangles in the next  frame if our velocity is equal to negative five   and we know when we're down here and we hit up  we are definitely colliding with this rectangle   so this code should be activated and y should be  equal to zero which means we're not going to stop   we're not colliding with this we're going to keep  moving to the side because remember we only stop   if this code down here is equal to true but it's  not going to be equal to true if player velocity   on the y axis is equal to zero so we're going  to keep moving but only when it has this opening   right here when our player is not colliding with  any boundaries is when we are going to set its   velocity on the y-axis equal to negative five so  if i save this and try this out refresh go down   hit right and hit up well we're still getting the  same issue even though if you think about this   code should be working right well what is going  on well right now when we're looping through all   of our boundaries we're literally looping through  every single one of them so even though we only   want to test whether or not we're colliding with  this boundary right here we are testing for every   single boundary that is within our actual game and  even though we might be testing true for this one   meaning we're setting y velocity equal to zero we  are definitely not colliding with this one we're   not colliding with this one so therefore we're  still setting our velocity.y equal to negative 5.   so as soon as this triggers right here as soon  as we figure out that we are colliding with at   least one boundary we need to break out of this  loop altogether because we do not want this to   be set so how do we break out of a for each loop  once this is equal to true well the typical way   would be run through a for loop and call break  like so and this means we're not going to run   through the rest of our loop the thing is if we're  using for each syntax like we are right now this   break statement just doesn't work unfortunately so  instead what we want to do is we want to go ahead   and refactor this for loop to be a traditional for  loop where we can actually use break and get out   of it all together if we are indeed colliding with  something so instead of referencing boundaries.for   each i'm going to delete this line right here i'll  also delete the ending of that for each loop and   now what i want to say in place of that at the top  is four i want to declare a let called i this is   going to be our iterator set it equal to 0 to  start and then i want to say if i is less than   or boundaries.length then i want to go ahead  and add 1 onto i until i is greater than this   value right here which means we are basically  successfully looping through all of our boundaries   so i can create some opening and closing curly  brackets and make sure at the end of this you add   the closing curly bracket right here so all this  code is right inside of it and now we just need   to reference a boundary so in order to reference  a boundary with a traditional for loop like so   we can just go ahead and create a const called  boundary and now we can reference this from this   but we just need to set this right here equal to  what while our boundaries i because we're grabbing   our iterator we know that whatever iteration  of the loop we're on we're going to grab it   based on the iteration set it in here and test  whether or not this one boundary is being collided   with our pac-man right here we're going to do that  for every single boundary using this new style of   for loop and if we do collide with one we're going  to call break we're not going to call this code   we're just going to run on to the next code down  here so with that we go down and then we want to   check when we're going to the right whether or  not we are colliding with any of the rectangles   specifically this one if we are our velocity on  the y axis is not going to change we're going to   set it equal to zero which means we keep going  to the right because this isn't going to fire   but as soon as we are no longer colliding we're  setting our y velocity to negative five we're   going to go up this is going to fire down here  setting our x velocity to zero but we're still   going to be going up because we're pressing  up on w and we're setting our y velocity equal   negative five so let's test it out we go to  the right and we hit up and we go directly up   let's try it again hey right and this works just  perfectly we're no longer stopping when i hit up   on the bottom side down here and if i go to the  left and hit up well now we have that perfect   motion we're looking for but right now we only  implemented this for when we are hitting up so   when we are going from the bottom upwards if  i try this from the top and i try going down   well we still have the issue where we stop along  the way when i hit s on the keyboard that is our   down button so we want to make sure that we do the  exact same thing for s right here and in order to   do the exact same thing we can simply grab this  for loop and then delete this line of code with   an s paste in this new for loop and we want to  monitor whether or not the bottom of our player is   about to collide with a boundary beneath it so if  we want to go ahead and test that out we'll change   our velocity right here equal to five so now we  know if we are about to collide with a boundary   below well our velocity on the y axis should be  equal to zero meaning we're not actually going   to stop our player at all and then we break out of  it but if we're not colliding with anything player   velocity dot y shouldn't be equal to negative  five because remember that's going to push us up   we want to go down so our player velocity.y  should be five instead of negative five   so on save and refresh we go to the right we  hold down and we make it through the gap let's   try it again go down try from the left go down  we are no longer stopping we're going directly   through the gap we have the exact movement we  want with this collision detection in place   so the next thing we need to test for is going  through a gap but from the left and to the right   so we need to go ahead and create a gap somewhere  in order to do this we're going to create two   more rows and we're going to create a gap right  through the middle here which we can test out our   collision detection so to create this gap this  is pretty easy it's a lot easier than creating   columns we're just going to go ahead and copy one  of these rows so i'll copy that then we're going   to paste in two new rows so now right here we can  determine where do we want extra boundaries placed   well i know i want one space beneath this one  so we're going to keep this space here but right   beneath that space i want an additional boundary  i save and refresh that we have exactly that let's   go ahead and add a square over here we're going to  go two to the right of the boundary we just added   and then add in that additional boundary save and  refresh and now that is generated so now if i try   going down well we had the exact same issue we had  before we are not predicting whether or not our   player is colliding with boundaries on the side so  therefore we just stop the x velocity altogether   it stops our player from moving so all the code we  wrote right here we just want to go ahead and copy   the for loop and then make sure we insert it for  when we're going to the left and when we're going   to the right we'll go ahead and take care of our a  key first so we'll get rid of this line right here   paste in that for loop and now we know we're  looping through all of our boundaries detecting   whether or not they are colliding with our  player but we don't want to predict whether   or not they're colliding when we're going up on  the y-axis we don't even want to deal with the   y-axis so we'll set y equal to zero but we do want  to detect whether or not we're colliding on the   x-axis so going to the left so in order to do that  we're going to change our velocity to negative 5   and then we want to go ahead and set our player  velocity on the x-axis equal to 0. if there is a   collision and then we want to break out of this  but if there is no collision we want to allow   our player to go through the gap so nothing is  colliding right here we're going to set our player   velocity dot x equal to negative five that means  we're going to the left when we press the a key   so we'll go ahead and test out the a key i refresh  go to the right go down and hold down a and this   works quite perfectly we're not stopping anymore  when we go to the left last thing we have to do is   make sure we're not stopping when we go to the  right so we'll just copy this for loop simple   enough and then down below within this else if for  our last key of d we can paste that in and then we   just need to change our velocities on the x-axis  from negative 5 to 5 like so and this should work   exactly as expected so i refresh i go down and  we're no longer stopping in any directions and   we have perfect movement through all these paths  we just created so really cool stuff here with   pathing and collision detection for our pac-man  game so if i head on over to to do we can go   ahead and check off adding collision detection  one of the hardest parts i hope you guys were   able to make it through that with the best of my  explanations but it's going to get a lot easier at   least until we get to creating ghost so next up  we're going to go ahead and swap our boundaries   out with images we're going to make sure that  these squares right here look like actual pipes   that we see in some of the traditional games so  to swap out boundaries with images we're going to   want to head on over to our boundary class let's  go ahead and find that search for boundary and   this is where it is so if we want to swap this out  with some sort of image we're going to add in an   image property and say this dot image is equal  to an image we passed through our constructor   so i'm going to add an image as a property within  our constructor function and then within draw   we're going to want to comment out this rectangle  code and we're going to want to use c dot draw   image instead what does this take well it takes an  image so we're going to reference this dot image   what else does it take what's going to take an x  and a y and this is basically the x and y position   in which we should actually render out the image  we have those so we're going to reference this   dot position dot x for the x coordinate and  then for y we can reference this dot position   dot y this is really all we need to get started  with drawing images so now if i save and refresh   we're just going to error out because we're  trying to draw an image but this dot image is   never actually set because when we are creating  boundaries we're never passing through this image   property so where are we creating boundaries  well we can find this by searching for   new boundary this is the only place we're  creating one we're only creating these little   dash boundaries right here so we want to make sure  that we're passing through not just a position but   also an image object and this is going to be set  equal to obviously some sort of image but where   the image comes from well we need to actually  produce it in the first place so for this tutorial   i went ahead and i created a bunch of different  images that we can use for pipe layout and this   is what they look like and i exported each of  them inside of a folder called pacman assets this   will be available within description of the video  within a google drive link so you can feel free to all these different downl that are representing  pipes in which we can connect these and create   the exact layout we want so what i'm going to do  is i'm going to copy all of these assets i'm going   to select the top one and then select the bottom  one by holding shift and clicking and then i'm   going to hit command c go inside of our pacman  project and now i don't really have a folder   for images inside of here so i'll right click  hit new folder call this img this is where our   images are going to go i'm going to paste in all  those images so now i can begin using them within   my pacman project so i can go ahead and minimize  these finders right here open up our project again   and open up sublime text so now you'll see we  have this image folder and we can begin using   all these images so right here when we pass  through an image into our boundary class we   need to make sure that this image is of an html  object essentially so in order to get this in   that format we're going to create a const and just  to start we're going to call this a const of image   this is going to be equal to a new image this is  a default javascript object in which we can create   basically an html image element so now that i  have this concept of image i want to go ahead and   set image.source the source of the image equal to  whatever file i want to pull in so if i want some   sort of horizontal pipe like we have right here  look at this we have a pipe horizontal image so   image.source is going to be equal to a string that  goes inside of our image folder so i'm going to   reference that with dot slash img we're going from  the current directory inside of the image folder   and then we're going to reference pipe  horizontal make sure the casing here is correct   and then add dot png so once we set the source  of this image now we can actually use it as the   image element within our boundary and draw image  should technically work so if i save and refresh   now we have all of our horizontal pipes drawn out  on the screen obviously this looks quite terrible   though we might want to use some of these other  pipe elements we have to create something that   actually looks cohesive so what we can begin doing  is adding in different symbols that represent   different images of our piping so right here  this little dash it makes total sense for this   dash image to be a pipe horizontal image but if we  want to go ahead and have a vertical pipe instead   it makes sense to have something like an actual  pipe character instead of the dash placed there so   let's go ahead and replace these side dashes with  vertical pipes to do that i know i want a vertical   pipe right here so i'm going to line that up with  our map and i'm going to go ahead and insert the   pipe character so i'll delete that and then i'll  hit that pipe character this is what it looks like   and i want to make sure that i replace all  the dashes on the left with this pipe so   i'll copy my pipe and then start replacing those  dashes with the pipe and basically just creating   a layout within this little array right here  that represents exactly what i want over here   so i'll do the same thing with the right side only  on the inner pieces replace the dashes with pipes   we save and refresh and now we lose the pipes on  the left and right hand side because we're only   checking for dash is right here so this is where  the switch case comes in handy we can go ahead   and create a new case by copying the current one  pasting it in and let's say we want to look for   pipes instead and when we're looking for pipes  we can go ahead and use a different image but   our boundaries are still going to function exactly  the same really cool stuff but the thing is if i   want to go ahead and import a new image while  i need to go through this whole process all   over again where i create a new image assign it  to source really tedious and like i showed you   in the beginning for creating boundaries really  going to muddy up our code so what we want to do   is create a function instead i'm going to create  a function called create image this is going to   take a source as an argument so what i can do  is i can go ahead and cut this code right here   paste it into create image so every time we  call create image we have a scoped constant   which we're going to set to the source not equal  to this right here but rather the source we're   passing through as an argument so we'll add source  right here instead and then we just want to return   the image being processed in here so in order  to get this to work with the horizontal pipe   like we just had now all we have to do is instead  of reference image right here we can call create   image because we know that returns an image and  now we can just pass in that pipe horizontal   source save and refresh and things are going to  bug out simply because we don't have an image   constant anymore down here we can go ahead  and add in a pipe vertical instead of image   by pasting in the create image function and we're  no longer going to reference pipe horizontal we   should have a pi vertical here i think i  forgot to export it just give me a second   so i just added that into our folder of pacman  assets i'm going to drag that in to our pacman   folder specifically within img i'll paste that in  so now it's there great now that it's available   you'll see it is in our project now so now we  can actually reference pipe vertical like so and   we're creating a new image element that's been  passed through right here so now let's save and   refresh now we have vertical pipes and we have  horizontal pipes we're starting to look better   but we're not there just yet one of the main  things making this look so off is we don't have   any corner pipes in place so you'll see right here  i have a pipe corner one top left pipe corner two   top right pipe corner three bottom right and then  pipe corner four bottom left we're basically going   in a clockwise direction in regards to these  corners and the numbers associated with them   so since we have these corners we can go ahead and  insert them just in these locations so where are   these locations well the very first one is going  to be this first dash and if i want to go ahead   and use some sort of symbol to represent pipe  corner one i guess we could go ahead and just use   a number one if you know a better symbol that's  just one character be my guess and change it with   whatever you would like it's totally arbitrary but  i think one makes sense i guess i'm gonna go ahead   and put it there and now i know over here i want  the second pipe corner so our very last corner   element i'll replace that with two down here  should be three so i'll go ahead and replace that   with three and then over here is going to be our  pipe corner four so i'll put four there as well   save and refresh they're no longer there because  we need to add them into our switch case to say we   want these specific images whenever we have a case  of one two three or four so go ahead and add in   four more cases i'm going to copy this one right  here and paste it in four times one two three four   just makes my life a little quicker and  now i can replace this first pipe with one   the second pipe with two third pipe with three  and the fourth pipe with four but we don't want   to use pipe vertical we want to use for pipe  number one we're going to use pipe corner one   a quick way to do this is i can just go ahead and  copy this string replace all three pipe verticals   right here with that string and then i can just  replace pipe corner one with pipe corner two   this one with pipe corner three and this one with  pipe corner four so just by doing that if i save   and refresh now we have perfect pipe corners in  place it's starting to look a lot lot better we   have another issue is we should have blocks right  here not horizontal pipes so where we have those   horizontal pipes within our map right here i'm  actually going to go ahead and replace these   with b i think that makes sense for standing for  block just a block element that has all four sides   on there so we're going to go ahead and put that  there and you'll see we do indeed have a block   image so i'm going to go ahead and create a new  case i'll go ahead and paste that on in replace   4 with b and now i can go ahead and replace  pipe corner 4 with block.png save and refresh   and now we have a very good looking map compared  to what we had before so you kind of get the gist   in regards to how to create your own game map and  then switch out different images based on the case   symbols that they have so i don't waste  your time too much what i'm going to do is   i'm going to go ahead and create the rest of  the cases for all these images behind the scenes   i'm going to create a game map behind the scenes  as well with all those different images integrated   and i'm going to include them within a github gist  which you can just go ahead and copy and paste   both the map and the switch case statement so you  can use these within your game without having to   type out all this work yourself okay so it took  me a little bit time but i did exactly that   and to recap exactly what i did all i did was i  created a lot larger of a map and i added a bunch   of different symbols in here as well basically  i replaced all the spaces with these little dots   which are going to represent pellets later on  i added these little brackets right here which   are going to act as caps so this bracket right  here represents this bracket on the left side   this bracket on the right represents the right  bracket the 7 in the middle represents a 3-way   connector with the down part open and this little  underscore right here represents a bottom side cap   this little guy right here the top carrot a  top side cap the plus sign a four-way connector   you kind of get the idea with everything that's in  here all these additional characters that i added   within our map you can see they're added into our  switch case down below we have the brackets which   are cap left and back right underscore  cap bottom little carrot thingy cap top   plus sign pipe cross five is going to be a pipe  connector top that's the three way one six is   going to be pipe connector right three-way and  then all these other ones are three-way as well   so just using all these images over here with  a switch case as long as you know what these   cases actually produce image wise you can create  really really cool maps and since we laid out our   collision detection code the way we did we were  smart about it we always take into account when   we are colliding with some sort of boundary  everything is still going to work with this   new map we generated so if i go ahead and start  moving throughout this perfect collision detection   and movement throughout the whole thing no issues  whatsoever so really really cool stuff here with   generating a new map and creating a whole new  landscape for our character to go around in   so if you want to get up to speed with me make  sure you add those additional cases and make   sure you add in that new map code available within  the description on the github just completely free   so let's go on over to to do and now we're going  to check off swapping our boundaries with images   we've definitely achieved that so next up we want  to go ahead and generate pellets and then we want   to go ahead and remove these pellets whenever  we collide with them so these are basically   the collectibles for pac-man to go around the game  in each so we can increase our score so how do we   actually generate pellets well we're going to want  to start with a pellet class and what is similar   to a pellet well simply our player our player  is circular our pellets should also be circular   as well so in order to save us some time i'm  going to go ahead and duplicate our player class   paste it down below and this is not going to be  player but rather palette instead so should a   pellet ever move have you ever seen moving pellets  in a pac-man game i personally haven't so we're   going to go ahead and get rid of velocity we don't  need that we do need a radius associated with   these pellets and they shouldn't be the same size  as pac-man they should be a lot smaller so we'll   say our radius is going to be three and we should  be good to go with that let's go ahead and go   down to draw what should the fill style of these  pellets be i believe within the pac-man games they   are yellow so we should be able to leave this as  is but if we want to go ahead and just make sure   they're a little differentiated from our player we  go ahead and call them white there's no big deal   with that so let's go ahead and change yellow to  white and do these pellets have an update function   are they going to move no they're not we can just  go ahead and get rid of update and now we have   pretty much everything we need to create a full  pellet pretty awesome stuff so in order to render   out our pellets we're going to need some sort of  array to hold them all so right above boundaries   i'm going to create a const called pellets set  it equal to an empty array now we have that empty   array in which we can store all these new pellets  in but when do we actually want to generate   pellets well we could do it the hard way and go  ahead and create pellets within this pellet array   using the pellet class but that is way too time  consuming we're actually going to go ahead and use   the switch case that we're using for a map because  you'll see i replaced each of the spaces with dots   these dots are now going to represent pellets but  if we look within our switch case i never actually   added in a case for if we hit a dot meaning a  pellet so we're going to go ahead and do that   ourselves at the very bottom of the switch case  i can go ahead and copy one of the cases and then   paste it in and say when our case is dot a period  meaning our case should be a pellet well we don't   want to push in a new boundary we want to actually  select our pellets array and push in a new pellet   instead and we know our pellet doesn't take an  image it just takes a position so let's go ahead   and call this and see what it looks like refresh  nothing showing because remember whenever we   create a new array like this we need to make sure  we're rendering out all the objects inside of it   so we're going to go ahead and select  our pellets array head on over to animate   and now right beneath our key functionality  where we're rendering everything out   it's going to be right here above our  boundaries for each i want to go ahead and call   pellet dot for each and say for each pellet within  the pellets array i'm going to select it within an   arrow function and say i want to call pellet dot  draw so i save and refresh now we have pellets on   our game really cool stuff almost that easy you'll  see they're not in the correct position though   so we want to go back up to our switch case where  we just added these in it's going to be right here   and you'll see these pellets are  almost spawning in the correct position   how do we get them in the center of where they  should be spawned well remember how did we get   our player in the center of this location we went  ahead and onto our boundary width we also added   the boundary width divided by two because if we  want this pellet right here to be in the middle   well we're going to get the width of one boundary  so here to here divided by two that's going to   place it in the middle we're going to also add  on boundary dot height divided by two and just   with that all of our pellets are perfectly placed  really really cool stuff so that's really all we   need for generating our pellets and if we look at  to do we just went ahead and generated pellets so   now number seven we're going to remove these  pellets whenever our player collides with them   so in order to do this we're going to have some  circle to circle collision detection code so what   we're going to do is go to where we are looping  through all of our pellets because we want a   monitor for each pellet whether or not they are  touching our player so it's going to be right here   within pellet stop for each and right beneath draw  we can begin our collision detection code so how   do we do circle to circle collision detection well  we're going to write an if statement that says if   math dot hypot that stands for hypotenuse so what  is the hypotenuse well it's simply the longest   side of a right triangle and here is basically  going to be the distance between the center of   one of our pellets and the center of our player if  you'd like to learn more about hypotenuses be sure   to check out that circular motion video i got goes  over all this in depth but to keep this as quick   as possible basically what we need to put inside  of mat hypot is going to be the difference between   two x coordinates and the difference between  two y coordinates specifically the difference   between our player and the pellets coordinates  so here within math.hypot hypotenuse we want to   go ahead and get the difference between  our pal location and player location   so to get our palette location we'll get to  pellet dot position dot x and then subtract player   dot position dot x and there's going  to be a second argument here as well   so we want to do the same thing for the y-axis  what is the distance between the pellet on the   y-axis here and our player up here well we're  going to get that with pellet dot position dot y   minus player dot position dot y that is going to  give us the distance between our pellets and our   player no matter where they are on the screen but  we don't want the distance between the center of   each of our circles we want the distance between  the radii so we want to say if this distance is   less than our pellet radius plus our player dot  radius then we know they are indeed touching so   we can say right here if this is true we can count  log out touching if i save open up our console and   refresh that we are indeed touching something  and if i keep going you'll see that this is   just going to be logged out forever because if  i move while we're always touching some sort of   pellet we want to go ahead and start removing  these pellets instead of just always touching   them so what i can do is say if we're touching  a pellet we're going to select our pellets array   and then we're going to splice out the pellet  that we're currently touching so to get the   pellet we're currently touching we need to get the  pellet index and to get the pellet index we can go   ahead and select there for each loop the second  argument right here is going to be the index of   the pellet we're looping over so i'm going to say  that it's going to be equal to i i want to splice   out that i one item from that distance so if i  go ahead and save and refresh that and refresh   we're only touching once because we removed that  one pellet we were touching last time if i begin   moving throughout this well i begin moving pellets  all over and you'll see this is only called each   time we actually touch a pellet so this indeed  will work for every pellet that we have within   our screen but something weird you might notice is  when i move to the side if you look really closely   well these are actually flashing and it just  makes our game look a little unprofessional   so first placing out pellets from the beginning  of an array and we try to render out one that   might have been shifted because of the splice well  it's going to give us this little annoying flash   right here so we can fix this by setting this  in a set timeout function that's set to fire   after basically one frame or what we could do is  we could run through this loop backwards and i   honestly think it's probably cleaner for us to  run through this loop backwards so we're going   to go ahead and do that instead so how would i run  through this loop backwards well here what i would   do is i would go ahead and create a standard for  loop so i'm going to go ahead and reference four   and when i go ahead and declare my iterator i'm  going to start it off at the length of the amount   of pellets within our pellet array so i'm going  to say for let i by default it should be equal to   pellets dot length minus one because remember when  we're selecting pellets within some sort of array   we start off at zero that's why we're subtracting  negative one here so we're able to access that   zero element and then we want to say we want to  run this as long as 0 is less than i so this is   going to be something like 30 i would guess and  we're going to keep running this as long as i   is greater than zero and for each iteration of  this loop we're simply subtracting one from i   so we're basically going from 30 down to zero and  that gives us one iteration of the for loop when   we go through our animation loop again we're going  to call this again and test for our collision all   over again so basically what we see right here  with pellet for each we want to get rid of this   we're going to add opening and closing curly  brackets right here for our for loop and then   we need to select the pellet that we actually want  to draw and test for a collision so we can create   a const called pellet set it equal to pellets and  then use i so that we're iterating backwards from   all the pellets within our pellets array because  remember this is going to be something like 30 so   if we select to the 30th element with our pellet  array probably going to be the very last one but   as we're going in reverse from the very end of  our array if we go ahead and splice the current   one out well the position of everything before  the one we splice out is not going to change   only the stuff after it which we've already looped  through which we've already drawn so the thing is   when we do it this way when we're looping from the  back well we're not causing any weird rendering   issues due to the change of position with elements  later on within our array so all we need to do now   is make sure we delete the end of our previous  four each down there and then i'm going to go   ahead and copy all this code that was within our  for each loop and paste it within our standard   for loop so now if i save and refresh you're going  to see everything still functions as it did before   but we're no longer getting any weird flickering  because we are looping and removing from the back   so very very cool stuff so now if i go to  to do we can go ahead and check off number   seven removing pellets on collision so next  up we're going to go to number eight we're   going to start adding a score so that whenever  we collect these pellets we add on to our score   by something like 10. so to add some sort of score  i don't really like doing it within canvas i just   find the text it's really hard to read and a lot  of times it's just way easier to do it within your   html file and i pretty much always recommend doing  it that way so here's the way we're going to do it   we're going to go within index.html and what i'm  going to do within here is create a paragraph tag   above our canvas tag and inside of this i'm going  to create one span with score inside of it add a   colon and a space and then right next to this i'm  going to create another span this is going to be   equal to 0 to start so if i save that and refresh  well now we have our score text up here but you'll   definitely see that is going to be black instead  of white so we can't see it it just blends in   so for a paragraph tag what i can do  is i can add a style tag on top of this   and then i can just say i want the color of this  paragraph tag to be white saving refresh like that   now we can definitely indeed see that but this  definitely looks a little old-timey we want this   to look a little more new age and actually  match our pac-man game we want to get rid   of these little tails on each of our words so we  can go ahead and add another style called font   family and set font family equal to sans serif  that's going to basically mean without the lines   so if i save that and refresh no more lines but it  does look a little goofy with our score that big   i always find that a score with a text size of 14  pixels looks pretty good for my game so i'm going   to go ahead and say i want one more property  in here make sure you're separating these with   semicolons like so this property is going to  be font dash size set it equal to 14 pixels   save and refresh definitely smaller looks quite  good to me but i want to style this a little more   to get it as perfect as possible so if i go ahead  and inspect this element by right clicking on it   hitting inspect and then i hover over it within  our console it's going to be a paragraph tag   you're going to see the orange right there means  we have margin on the bottom that's just too much   margin for me i want it to be a little tighter  so i'm going to go ahead and say i want the   margin for our paragraph tag to be something  like let's just say 6 pixels save and refresh   and that is looking a lot better to me but if we  just go ahead and set margin like we are right   now this is going to add margin on all four sides  of our paragraph tag so instead i just want to go   ahead and effect not margin but margin bottom  save and refresh it gets rid of the margin on   the left and it definitely brings our game a bit  closer to our score right here and the margin that   was coming from our paragraph tag by default  is applied from the browser so i just didn't   want that much margin for the browser so i  overwrote it with margin bottom six pixels   now this text and our game are a little close  to the side and you might be thinking well we   got rid of that space on the side with margin zero  but if i want padding on the inside of an element   it's better to use padding instead so let's say i  want 10 pixels of space from the top of our score   element right here from our body i can go ahead  and say our padding is equal to 10 pixels and   if i want even more padding added to the left and  right hand sides of our canvas what i can go ahead   and do is add a second value right here and say i  want it equal to 20 pixels so this first valley is   going to give a spacing on the top and bottom of  an element and the second value is going to give   us spacing on the left and right hand sides so  watch what happens if i save that nothing just   yet but that is just because it shifted us to a  different position if i go ahead and scroll to the   left you'll see that we are indeed in the correct  spot we have some padding on the left we have an   adequate amount of spacing on the top and if i  exit out of the console your game looks like this   it's just because we just resized our screen but  remember within index.js we are setting the size   of our canvas to be the initial inner width and  height all you have to do is refresh you'll see   that padding is in place because we scroll to  the left and the top and this is looking really   good for a score label within our game we don't  really have to do much more styling within css but   what we do want to do is every time we collect the  pellet is change this right here this span of zero   so we want to go ahead and select the span  within javascript we're going to give it an id   and say this is equal to our score l stands for  score element so i'm going to save that and now   i know i want to pull this within index.js we're  going to pull this the exact same way we did with   our canvas i'm going to go ahead and select this  line right here and beneath our c i'm going to go   ahead and say i want a const of score l and to get  this i don't want to select our canvas element i   want to select our element with an id of score l  so to select an id i can add a pound sign and then   i just need to specify what is that id it's going  to be this right here score l make sure you have   index.html and also index.js saved and the test  that you have this you can console log out score l   save and refresh check your console and there  it is we are good to go so now we can begin   changing this within our game so that is going to  represent our view element but we also want some   sort of variable within our code that actually  tracks the numbers being added on to our score   so right beneath the last key i'm going to add  in a let called score and this is a let because   i know i want this to change we're going to start  off at zero but over time as we begin collecting   pellets this is going to increase so where  are we collecting pellets if we scroll down to   animate it's going to be at the very bottom  about right here this is when we're touching a   pellet and then splicing them out we can even  add a comment above our for loop that says   touch pellets here to help us understand this  code better so now within pellet splice we know   this is where they're being removed we can go  ahead and say our score should have the value   of 10 added onto it so if i save and refresh well  score isn't changing up here because although our   score let might be changing in the background  programmatically we need to go ahead and change   our view element that we pulled in to our file so  we're going to go ahead and get that with score l   grab it's inner html inner html is just going  to be everything inside of this element so just   the zero we want to set it equal to the score  in which we're actually altering so that is the   programmatic score that we're adding 10 onto  so if i save and refresh and i can start going   you're going to see for each pellet i get our  score increases by 10 and we update it on our   front end because we're calling scorel.enterhtml  setting it equal to the actual programmatic score   and this will just keep going until i collect all  the pellets on the screen and basically there are   no more so we can increase our score right so  if we go on over to to do we can go ahead and   check off we added the score okay so now we're  going to create a ghost we're going to create an   enemy that moves by itself throughout our course  and then if we hit it well we lose the game so   how do we go ahead and create this ghost well  let's think what does a ghost look like i want   to make it look like our player over here just  a different color so it makes sense to find our   player class within our code and i'm just going  to go ahead and simply copy and paste this below   and then i'm going to change this as needed so  really what needs to be different from our player   class to create a ghost well of course we should  change the class name from player to ghost like   so and then i just want to say that the color of  our go should be different but i'm going to leave   everything else the same for now at least so in  order to add some sort of dynamic color to our   ghosts we can add in a color property right here  set it equal to some sort of default value in case   we don't want to provide one i'm going to call  this red and then finally we can assign a property   of this dot color equal to the color we're passing  through and now we can utilize this within our   other functions so instead of referencing just  yellow i'm going to go ahead and reference this   dot color so great we have our ghost class let's  go ahead and create one now i'm going to go down   to our pellets and boundaries arrays i'm going  to create a new const call this ghost and set   the sequel to a new array so now i can begin  populating this with a new ghost so inside of   this i'll write new ghost this is going to take  an array and the first argument is going to be a   position so i'll go ahead and say for a position  on the x-axis i want this equal to 0 to start   same thing for y that's going to spawn or goes  somewhere up here for our velocity this also   takes an object with an x property which i'm going  to set to zero to start meaning our ghost is not   moving on the x axis and then y should also be  zero so our ghost isn't going to move at all to   start and then finally we have a color and we set  that default value within our class equal to red   so we don't actually need to define that but on  save and refresh we're not seeing anything because   we need to call the update function within this  ghost we just created so we know this is within   our ghost array so we want to basically loop  through this within our animation loop to get   it rendered out on the screen so i'm at the bottom  of our animation loop right here and right after   player.update i want to get rid of these two  comments they're kind of unnecessary right now   and i just want to go ahead and loop through that  ghost array so i'm going to select the ghost array   and i'm going to call for each like so i want  to say for each ghost within this array call the   following arrow function and now that i have this  one ghost object selected i can call ghost dot   update and we should see our ghost rendered out  on screen so i save and refresh there is our ghost   but we want our ghost rendered right about here so  let's go back to where we created our ghost with   new ghost and we know that we want to basically  change these two position properties of x and y   now our player is in a pretty good spot right here  and we placed our player using our static property   of battery with boundary height i think it makes  sense to copy this line right here both of these   lines actually and then paste them in to our  ghost position as well so if we were to do that   save and refresh now our ghost is where our player  is placed but we can go ahead and move our ghost   over by one two three four five and then actually  six because we're adding on where we are right now   by multiplying boundary width by 6. so if i were  to do that and refresh now we're placed perfectly   in the spot we want to be so now we can begin  adding movement to our ghost so that it moves on   its own and it begins choosing which path it wants  to take completely randomly it's going to create   this really cool ai movement effect so how do we  actually do that what's the algorithm associated   with this well we need to actually track our ghost  collisions at any point in time so if our ghosts   were placed right here what would the collisions  be well our collisions would be we're climbing   with the top if we were to move up and we're  colliding with the bottom if we were to move down   we're not climbing with the left we're not  climbing with the right simply because we don't   have some sort of boundary on the left and right  of our ghost but if we were to move our ghost over   here and let's do that with the code change six  to seven mover goes to this spot what would the   collisions be here well we can move to the left we  can move to the right we can now move down but we   still can't move to the top so our only collision  would be colliding with the top so what was the   difference with the collisions here compared to  the collisions in the previous location the only   difference is we lost the down collision so we  want to go ahead and find the difference between   the previous collision and what boundaries we  are colliding with right now and based on that   difference we're going to choose which direction  we can take so since down is missing we know now   we can go down and we can actually also go to the  right but we're going to add that in dynamically   because it's going to be based on the movement  of our ghost it's going to make a lot more sense   as we actually go through this so let's go ahead  and move our ghost back by changing seven to six   we're in a good spot and now let's start detecting  for collision i'm going to go back to where we are   looping through our ghosts at the end of  our animation loop so right here and now   for each ghost that we have within our ghost array  i want to detect for collision for every single   boundary within our course so i'm also going to  select our boundaries array within this for loop   and say for each boundary within this array i want  to start detecting for a collision so how do we   detect for collision as if we're predicting where  we would collide if we were to move in a certain   direction well we know we did that with our player  we're predicting whether or not we're colliding   upwards whether or not we're colliding left right  or bottom so it kind of makes sense to find that   code up above you'll see right here within this  else if statement when we are pressing the d key   we are testing whether or not our player is  colliding with the left side of a boundary   so what we can do is we can copy this if statement  right here i'm just going to grab the if portion   and then i'm going to paste it within our  boundaries for each loop so i want to go ahead and   add some opening closing curly brackets and i'm  not going to put anything inside of this just yet   but we want to test whether or not our ghost right  here is colliding with any of our boundaries at   any point in time so instead of testing for  our player we're going to test for our ghost   this is basically predicting the next frame in  the future our velocity right here if we set x   equal to 5 we're predicting would we collide if we  moved our ghost over by five pixels to the right   no we wouldn't in this case but we still want  to test this everything else here is fine   what we want to say is if we are about to collide  with something on the right side here we want to   select a collisions array and push into this  a string of right but we don't actually have   a collisions array created just yet and  we know we want to detect collisions for   every ghost we're looping over so i'm going to  create this collisions array right where we are   looping over these goes so i'll create a const  called collisions set the sql to an empty array   and now we can begin pushing in the collisions  based on where our ghost is and where we would   be colliding if we were to move in a certain  direction so we just tested for collisions if   we were to move to the right let's go ahead and  test for collisions if we were to move to the left   all we have to do here is copy this if statement  paste it below and then we know if we're moving   to the left x would be a negative value so we'll  set that equal to negative five and if we were to   collide with a boundary on its right side or goes  to left side then we would push in collision left   and then we want to do the exact same thing for  top and down so i'm going to go ahead and say if   we are moving upwards on the y axis we shouldn't  be moving on the x axis so i set that equal to   zero but if we're moving upwards y will be equal  to negative five and then i know our collision   is happening on the top so i'm actually going to  call this up instead of just top and then i just   want to detect if we're colliding with anything  down so i'll go ahead and copy and paste this one   more time and say if we're moving downwards  y will be equal to five instead of negative   and then we know we are colliding with something  beneath our ghost so perfect so i'm going to go   ahead and go outside of our for each loop for our  boundaries and then i'm going to console log out   what well are collisions what are we  colliding with at this current point in time   so if i do that save and refresh and then  open up our console you'll see our collision   detection code for a ghost is indeed working we  are colliding with a boundary on the top of our   ghost and the bottom of our ghost so perfect but  let's go ahead and start adding some velocity on   our ghost right here to see what happens over  time so to add some velocity i'll find where   we're creating a new ghost and we know if we want  our ghost to move we have to change our velocity   to something greater than zero so i'll change x to  five save and refresh and our player goes off the   screen which is fine because we haven't told it  how to react to these collisions but you'll notice   right here we're pushing in multiple instances  of the same direction into this array it doesn't   really make sense to have duplicates such as up  in here twice so we want to make sure that we   can only push one direction into this array at  any point in time so i'm going to go back down   to this collision detection code for a ghost that  we just created and i want to say well yes i want   to go ahead and push right into our collisions  right if we're colliding with the right side of   our ghost and the left side of the boundary but i  only want to push this in if right does not exist   within our collisions array in the first place so  within this if statement i could say if collisions   includes the string right and we are colliding  with the left side of the boundary then i want to   go ahead and push this in but this code wouldn't  work because we want to actually say if collisions   does not include right which means it's only going  to be in there once then we want to push it in   their array so what we want to do is copy this one  line of code right here and add it into all of our   other conditionals so say if our collisions array  does not include left because this is relating   to our left right here and then if collisions  array does not include up for up version of it   and then finally if collisions array does  not include down for a down version then we   want to be able to push it in so with this quick  check right here for each of our if statement if   we refresh you'll see that we have a small issue  here it says collisions.include is not a function   this is just a small mistake on my part  this is actually includes not include so   we'll go ahead and add an s to the end of each  of our statements right here no worries at all   so let's go ahead and add s to the end of each  of these and now if we save and refresh now we   don't have any duplicates within this array the  max we can have is either up right left or down   no duplicates of up anywhere so great so now what  we want to do is compare our previous collision   with the current collision we know when our  ghost was placed right here we had two collisions   top and bottom where it goes was right  here we had one collision just the top   so what we can say with this algorithm is if  the amount of current collisions is less than   the amount of previous collisions well we know  something opened up and that is indeed the case   because we know the bottom opened up we can now  move downwards if we would like but we need a   place to store the previous collisions and i think  the best place to store these is actually within   each ghost instantiation itself so what i'm going  to do is i'm going to go up to our ghost class   and i'm going to add an additional property  in here called this dot prev collisions just   stands for previous collisions and i'm going to  set this equal to an empty array and now that   i have this empty array i can begin storing our  current collisions into it so we're going to go   ahead check where we are colliding with all of our  boundaries and then once we break out of this loop   we can go ahead and select our ghost dot  previous collisions and set it equal to the   current collisions that we just detected and  really we do want to wrap this inside of an if   statement that says if our collision's length is  greater than our ghost.previous collision's length   like so then we want to run this code because  remember we might not be colliding with anything   at all such as if our ghost is here and we're  detecting collision for this one boundary in   the top left corner we're not colliding there  so it doesn't really make sense to set an empty   collisions right to ghost.previous collisions  we only want to detect for collisions with the   boundaries that we're actually colliding with  which are going to be these two right here so   we want to make sure that we're only setting this  value if we're actually colliding with something   and we know we're colliding with something  if collisions.length is greater than ghost   previous collisions.length so we're just simply  going to add this conditional in here so when we   run through this the first time collisions is  going to be eagle 2 up and down based on where   it goes is right here so therefore we're going to  be setting ghost.previous collisions equal to that   but the next location which our ghost is is  going to be right here collisions is going   to be equal to just up so now we want to compare  whether or not these two arrays are equal because   although we're going to be colliding with top and  bottom right here want to move over here we're   only colliding with top something changed  which means we can change the velocity of   our actual ghost so we want to say if these two  arrays are not equal to each other by saying if   collisions is not equal to ghost dot previous  collisions we can go ahead and begin affecting our   ghost velocity but if we were to console log add  some code right here just anything such as string   i'm going to comment this one out save and refresh  and you're going to notice this just keeps console   logging out over and over again by default since  these are two separate arrays they are never going   to be equal to each other we want to be testing  that the array and everything inside of it are not   equal to each other so in order to do that we can  stringify this whole array so to stringify this i   can call json a native javascript api object and  then i want to call stringify this is just going   to change our array into a string it's going to be  the perfect way to tell whether or not the ray and   its contents are actually equal to each other or  not so i want to do the same thing for or ghost   previous collisions so i'll call json stringify  make sure i'm wrapping previous collisions in that   save and refresh and now you'll see that's really  only called twice when we're actually within our   map and then of course it's called over and over  again when we get over here but previously it was   just logging out go no matter where we were at  any point in time but here you'll see once we   hit here and here we're going to log go twice so  watch very closely i'm going to refresh one two   and then it just keeps going once we go outside  the map that is perfect that is exactly what we   want we know right here and right here are where  we can determine which direction our ghost is   going to move so we have our conditional written  out correctly now we just need to write the code   that actually changes our ghost velocity based on  this condition so when our ghost hits this right   here we know we have two pathways in which we can  go to we have down or to the right so we want to   go ahead and find those pathways within this if  statement so let's go ahead and just console log   out our collisions within here first and then  i'm also going to console.log out beneath it   console.log or ghost dot previous collisions just  so we can compare the two and we're just going to   focus on these very two first logs up here so  you'll see when we moved to this position right   here our collisions was equal to just um we were  only colliding with this up boundary right here   but previously we know we were in this position  what were we colliding with well no other than   up and down that makes total sense so what is  the difference between these two arrays right   here well the only difference is down does not  exist within the first one so down is going to   be our potential pathway we know we can go down we  can also go right we're going to add that in but   this is the first step we need in order to create  this functionality so what is a smart way to get   this down value right here well in order to do  this we can go ahead and create a const called   pathways these are all of our potential pathways  we can select our ghost dot previous collisions   we want to filter out any collisions that don't  exist within this first array so we're going to   go ahead and loop through every collision within  our previous collisions array and then we're going   to go ahead and return a conditional that says  whether or not this collision we're looping over   exists within the first array so i'm going to go  ahead and say if our original collisions array   includes the collision we're currently looping  over and actually want this to be the inverse   so i want to say if the original collisions array  does not include the collision we're looping over   that's going to give us this down value right  here let's go ahead and console log this out   if i console log are available pathways and  i'm going to wrap this in an object like so   just so i have a nice way to view what  pathways actually is within our log   if i save and refresh this you're going to see our  pathways is equal to an array of one right here   and i look inside of this and we only have that  down property because we use this filter function   to filter out the values that we never needed in  the first place so looking at this yes we can move   down when we move right here but we should also  be able to move to the right and we can't really   detect that we were colliding with anything on the  right previously because we're not going to detect   that till we actually get to this point so we want  to go ahead and add into our previous collisions   array before we call this filter function based on  the velocity in which our ghost is actually moving   and by doing this it's going to open up this other  pathway over here and say hey our ghost can move   to the right and it can move down so in order to  do this i'm going to write an if statement right   above our pathways code and i'm going to say  if our ghost dot velocity on the x is greater   than zero meaning we are moving to the right what  do i want to do well i want to select our ghost   dot previous collisions and push into it that  we could potentially collide with something on   the right eventually but we're just moving the  direction we can't we need this to make sure we   are filling up the pathways code correctly so if  i just go ahead and save that and then refresh   and scroll to the top so we can see this code up  here now pathways is full of two items and i look   at this and it's down and right simply because we  added right to the second array right here we're   actually consolidating this out before we do that  so if we were to go ahead and move this beneath   our if statement save and refresh scroll to the  top you'll see within our previous collisions   array we now have the value of right which is  perfect now we have within pathways two potential   pathways we can go down to the right and if we  replicate this code for every direction we're   moving in well it's going to make sure that we  are creating that extra pathway in which we might   be able to go so we're giving our ghost a truly  randomized effect into which pathway they actually   choose so what i can do is i can copy this if  statement paste it below call it an else if   and say if we're moving to the left if it goes to  velocity on the x-axis is less than zero then we   know we're moving to the left there's a potential  to collide on the left-hand side of our ghost i'm   going to copy this elsif paste it below say if our  y is less than zero our potential collision is up   and then finally if y is greater than zero on  this fourth else if then we know our potential   collision is going to be down so that's not going  to change much for our current functionality while   we're moving to the right by default but if  we were to move to the left or somewhere else   within our map this would indeed take effect  and put us in the right direction for filling up   our pathways array with the correct directions so  now we have this pathways array we need to choose   a random path from it so here's what we're  going to do i'm going to go ahead and say   const direction is equal to our pathways array and  then i just want to go ahead and select a random   direction so in order to do this i can call math  dot random this will give us any value zero to   one and i can go ahead and multiply this by our  pathways array length so since our pathways are   right length on this first value from here to here  is going to be two we're getting any value zero to   one with this code but the thing is we can only  select an object within our pathways array if we   have an integer index so if we're trying to select  it with something like 1.5 within this array it's   just not going to work we need to make sure this  value right here is an integer so in order to   do that i'm going to call math.floor and wrap  math.random and pathways.length inside of that   that just means if we get something like 0.5  for a random value we're going to floor it it   means we're going to get 0 for a result but if we  get 1.5 we're going to floor that we're going to   round down to 1 and that's going to give us the  perfect integer value we need to get some sort   of direction so now if we constantly log out our  direction the random direction we want to go in   save and refresh and i scroll to the top you're  going to see that initial direction we wanted   to go and was to the right but if i refresh you  should see that changes that is down it's just   completely random because we told it to do so  you see it just toggles between down and right   that is absolutely perfect that is what we  want so based on this direction we're going   to change the actual velocity of our ghost  so what we can do is we can add a switch case   that says we want to switch out the direction  we just chose with what well if our case is   going to be something like down what do we want  to do well we want to select our ghost velocity   on the y axis and we want to set this equal to  five that's going to start pushing us downwards   but we also want to make sure that we select our  x-axis because we shouldn't be moving to the right   anymore if this is our new direction we should set  this equal to zero to make sure we stop completely   and just move down between our boundaries right  here and then we want to add a break to make sure   we break out of this case and we want to do  the same thing not just for down but also for   if we get up as our case we'll go ahead and  change y to negative five we can leave x at zero   we want to do the same thing for if our case is  going to the right so y will be equal to zero and   we want to change our x to five which just means  we're moving to the right and finally if our case   for our direction is going to be left our y should  be zero and our x should be negative five so this   should move our goes in the correct direction  randomly which is perfect that is exactly what we   want but we want to make sure that after we call  this code that actually changes our ghost velocity   that we reset our ghost collisions because  remember we're going to have some sort of new   collision once we actually start heading in that  direction we want to go ahead and set our ghost   dot previous collisions equal to an empty array  and that's just going to go ahead and reset the   whole process restart the algorithm so things  should work as we continue to go through all   these different corridors if i go ahead and save  and refresh just like that we have pretty much   perfect movement for our ghost throughout this  whole maze like thing and it's completely random   you'll see each time i refresh our ghost tends to  go in a different direction this is exactly what   we want for some sort of basic ai in the game so i  hope that wasn't too confusing that is definitely   going to be the hardest part within this tutorial  so i really think it's going to be a lot easier   from here so i think we want to do two things  here one we want to make sure that our ghost is   going a bit slower because this might be way too  hard for someone just starting out in the game   we want to go ahead and change our ghost velocity  not to five but let's just go ahead and say two   now it's kind of annoying to have to change this  in all four spots here and wherever else we're   using five for our ghost's velocity so instead of  using five here i'm just going to go ahead and say   our ghost velocity should be equal to ghost dot  speed instead and that's basically going to serve   as our base velocity for x and y so each place  that i have five within the switch case i'm going   to replace it with ghost speed and then i just  want to go ahead and scroll up in our code here   and see if we're setting or goes velocity to five  anywhere and it looks like we are testing for our   collisions using this five velocity right here  so i'm going to replace five with ghost speed   and all these different locations where we are  testing whether or not we're about to collide   with something and that seems to be the only  place where we declared that within our collision   detection code so i know we also created a new  ghost up here we set its initial velocity equal   to five but if we want to go ahead and set our  velocity equal to ghost speed right here we don't   have a ghost in which we can actually reference an  individual speed property here we would actually   need some sort of static property that we  can reference directly from our ghost class   so i'm going to change this lowercase g to  uppercase g just right here we're going to   create it in both locations so we can leave  everything else we just did the same but let's   go ahead and change that lowercase g to an  uppercase g and now we just want to find our   ghostclass we're going to create two properties a  static one outside of the constructor called speed   by default i'll set it equal to two to slow this  guy down and then i want to go ahead and create a   property within our constructor since we use that  within some of our other code i'll call this.speed   eagle the two as well now we only have to change  it in two places compared to eight if we want to   go ahead and affect our speed later on if i were  to go ahead and save that watch what happens   refresh and it looked good but now our code is  just thrown out of whack why is that well when we   decrease our velocity to two and we're detecting  for collisions such as if our ghosts respond here   if we're detecting upwards and downwards well a  velocity of two wouldn't be enough to actually   push us into one of these boundaries therefore  our collision detection code is saying we're not   actually colliding with these two boundaries right  here when we are spawned here so if we want to go   ahead and decrease our velocity we need to change  our collision detection code to take into account   padding above below to the left or to the right  of one of these boundaries so what we're going to   do is we're going to go down to circle collides  with rectangle and inside of this we're going   to go ahead and create a const called padding  now this is going to be equal to our boundary   dot width divided by two because what we need to  do here is we need to get the amount of spacing   between our player or our ghost and our boundaries  so this little gap right here of black space this   is what we want to go ahead and add into our  collision detection code so if we go ahead and   get boundary with we're going from here to about  here we want to go ahead and divide this by two   when we divide this by two we get the distance  from here to the middle of our player but now   we know we can get this small distance right here  by subtracting our player or our ghost radius that   is going to give us a small amount of distance so  here i'll grab the circle that we're using within   this function specifically the circle's radius and  this should give us this little amount of space   but we do want to subtract at least one pixel  because we don't want our player or ghost to be   colliding with the space by default so we're  going to go ahead and subtract one from this   padding and now we can begin using this constant  within our return statement so let's go ahead and   look at this our circle position y minus circle  radius that's going to be the top of our player   we want to say if this is less than what well our  rectangle position plus our rectangle height that   gives us the bottom of the rectangle plus  our padding that's going to add that small   amount of padding right here then we know we are  colliding with this boundary we want to do the   same thing for all four directions so the second  condition right here is going to say if our circle   position x plus its radius that's going to be the  right side is greater than or equal to rectangle   position.x minus our padding that means our player  or our ghost is colliding with the padding on the   left side of one of these boundaries then we  know we are colliding this condition right here   is going to monitor the bottom of our player  and also the top of one of our boundaries we   can say the top minus our padding and then  we can deduct if the left side of our player   is less than the right side of our rectangle plus  our padding then we know we are colliding so if   we go ahead and affect our code like this to take  that padding into account for collision detection   save and refresh well now our ghost goes back  to normal we don't have that weird code in place   everything functions exactly as expected  except we can use this new speed   you can also use the old speed i already tested  it so perfect for increasing the difficulty of a   level but now we have something that's a lot more  doable at least in the beginning stages of the   game to make sure that we get all these pellets  without our ghost just completely destroying us   so now that we have this movement in place let's  go ahead and make sure that whenever a ghost hits   our player that we just end the game to end the  game we're going to just console log out the text   you lose and then we're going to go ahead  and just pause our animation altogether   and that's all we're going to do for this so in  order to do this what we want to do is create   some sort of animation id and i'm going to make  this a global variable i'm just going to declare   this right above our function of animate so i'll  call this let animation id you don't have to set   it to anything to start but within animate request  animation frame is always going to return the id   of the frame we are currently on and we need that  in order to cancel or pause our game when we are   ready to so here what i want to do is i want  to store request animation frame the id that it   returns inside of our animation id let this is all  i'm going to do and i'll save and refresh this is   going to function exactly the same but if i were  to console log out animation id like so you're   going to see the animation id is in place this  just stands for whichever frame we are currently   on so now that we have this animation id we can  begin detecting for a collision between our ghosts   and our player so here i'm going to go down to  where we are looping through all of our ghosts   one more time and this is going to be right here  and before we even go to the boundaries we can go   ahead and say we want to test for a collision  between the current ghost and where our player   is at any point in time so where did we use  circular collision detection before well we know   whenever we run over one of these pellets we are  removing it from our game that is where we use   circular collision detection and that is going to  be right here where we are touching the pellets   so what we can do is we can just grab this if  statement right here and begin refactoring it   for collision detection between our ghost and our  player so if i were to grab that paste it beneath   ghost.update make sure i have opening closing  curly brackets let's go ahead and look at this   hypotenuse function i want to say if the position  between not our pellet position x but our ghost   position x minus our player position x and then  our palette position y not to pull up position   y but ghost position y minus player position y is  less than our ghost radius plus our player radius   then we know the two are touching but if we know  these two are touching right here what do we want   to do we want to go ahead and call the function  cancel animation frame and this takes one function   it's going to be a number the current frame we are  currently looping over for animation frame where   are we getting that no other than animation id so  we have that in place let's also console log out   you lose to really rub it in our phase so if we  save that and refresh when our ghost touches us   we should get that text logged out and our game  stops completely we're no longer logging anything   and we get the dreaded text you lose so now  we know our score we can restart the game by   refreshing if we would like but we have that  functionality in place for collision detection   between our ghost and our player to actually  create some sort of formidable enemy so the last   thing i want to do in regards to ghost creation  is just create a few more ghosts and based on the   way we set this up this is going to be super super  simple so where we created a new ghost originally   all i have to do now is just copy this new ghost  add a comma to the end of it and paste in a new   one and here i can either change the position and  or the color so i'm going to change the color for   this one to pink and i want this ghost to spawn  somewhere down here so i'm going to multiply its   height by something like three if i go ahead and  save that with a new ghost in this ghost array   you're going to see now we have a pink ghost as  well it's already coming after me pretty scary   stuff but if i go ahead and touch this pink  ghost our game ends just the same so now we   have an even harder level for us to play in so i  think that's pretty good if we go over to to do   we just created a ghost so now let's go ahead and  create a power up so that when we retrieve it we   can go ahead and chase our ghost and eventually  that'll expire and they can come back at us so   in order to create a power up i'm just going to  go ahead and copy the closest thing to what a   powerup would be which is actually going to  be our palette i'm going to copy this class   and paste it below and i'm just going to  call this power up so don't get too confused   with the abstraction of the pellet class i  always like making these a little different   just personal preference so this power up is  just going to be a simple circle but i'm going   to make sure that it's a little bigger than the  normal pellet i'll say that its default radius   is going to be equal to 10 and we can actually  leave the fill style for this power up white i   think the radius will differentiate it enough and  now we just need some sort of array to store these   power ups so i'll go ahead and create a new const  called power ups set it equal to an empty array   but i'm not going to create a new power up  directly within this array like we did for   our ghosts i'm actually going to go ahead and  create this within our switch case statement   using our map so right down here within this giant  map we paste it in right here i have a key for p   this stands for power up you might have noticed  this is in here it doesn't actually spawn anything   in the bottom right not a pellet or anything  else so what's supposed to go here is going to be   the power up that we create so we know if our case  is p we want to push in a new power powerup pellet   within that one spot so within our map.for each  code where we are determining what goes where   based on our map we can go to the very bottom and  then copy the very last case paste a new one in   and say if our case is equal to p we don't want a  new pellet we want to go ahead and reference our   power up to array like so and we want to create  a new power up inside of it and we can actually   keep position exactly the same this should put  us in the exact correct spot for where this   should be spawned so if we were to just add this  case of p in here and refresh you're not going   to see anything just yet because i guarantee  you this power ups array is populated we just   need to make sure that we're rendering it on the  screen so where we are rendering out our pellets   we can search for that by looking for pellets we  can also go ahead and loop through our power-ups   so to look through our power-ups i'm just going  to go ahead and copy this for loop right here   paste it above and create an ending curly bracket  and here i'll go ahead and say this is where our   power-ups go and now i know i should be equal  to not pellets.length but powerups.length we're   just looping through all the powerups within  our powerups array this is a good way to do it   with this for loop and now since we're looping  through each powerup i can select the const   of powerup for the individual powerup we're  looping over currently select our power ups array   and then get the index to get that one exact power  up so now that i have that one power up i can call   the draw method on top of it i save and refresh  and still not being drawn there unfortunately and   that is because if i look at our for loop really  closely we just have to add one little thing in   here which i forgot if we want to make sure we're  looping through everything within our power ups   array using this sort of for loop we want to make  sure that this should be less than or equal to i   it should actually be the same for a pellet for  loop right here so we'll change that as well and   that's just going to make sure we loop through  everything and if we just had zero is less than i   then we wouldn't actually be looping everything  if we only have one item in there so we just want   to make sure that we change that and now and  save and refresh there is our power up pellet   that might even be a little big for my  liking so where we declared its radius   power up right here we're going  to change this to 8 instead of 10   and that definitely looks different enough from  our pellets and different enough from our goes   to tell while this might actually be some sort of  power up so now we want to go ahead and detect for   collision between our player and this new power up  so we're actually going to jump right back down to   our for loop that we just created that's going  to be right here where our ups go and in order   to detect for a collision between two circles we  know we can grab this if statement with math hypot   and just paste it inside of our for loop right  here it's going to have an opening closing curly   bracket we want to detect foreclosure not  between our pellet but for our power up the   current one we're currently looping over so i'll  replace pellet in every location with power up   and now this will say if the two are colliding our  player and our power up what do we want to do well   we want to go ahead and splice our power up out of  the scene we can just use the same exact code that   we have right here for our pellets if i copy this  line and then change pellets to power ups we're   going to splice it out there's not going to be  any flicker or anything like that because we're   looping backwards using this for loop save and  refresh and i go for that power up down here grab   it it spliced out of the screen there was no flash  or anything like that but now we should activate   either a power up property on our player or some  sort of disadvantaged property on our ghost such   as a scared property so i think i'm actually going  to activate a scared property on our ghosts and   based off that i can also change their color so  we know right here this is where player collides   with power up inside of this we can also make  ghosts scared so how do we make her go scared well   we want to loop over every ghost so we'll grab  our ghost array and then say for each ghost within   this ray we'll call some sort of callback function  and now we can go ahead and set a ghost dot scared   property equal to true we know we don't want our  ghosts to be scared forever so inside of this we   can also add a set timeout and this is going to  take an arrow function for the first argument that   says what should we do after some amount of time  has passed well we want to go ahead and select our   ghost set a scared property back equal to false  and this should happen about after three seconds   we can console log this out to make sure that it's  actually happening after those three seconds occur   i'm going to go ahead and cause log out go scared  for one when we change this property in the first   place when we touch our power up and then two for  when this power up expires so i would go ahead and   save that and refresh and grab our power up down  here you're going to see we had true logged out   right there and after three seconds now we have  falls that power up has worn off that's all we   really need to do so i can go ahead and get rid of  these console logs now that i know that's working   and now i want to go up to our ghost class so we  know we have a scared property associated with   our ghost we'll go ahead and add that in say  this.scared by default is equal to false and   now we can use this property to affect our ghost's  color so a cool way to do this is with fill style   right here i can reference this dot scared and now  if this is true i'm going to add in this little   question mark which says what do we want to assign  to fill style if this not scared is equal to true   well if it's equal to true i want to assign to  fill that style a color of blue just a simple   string but if it is false i can declare the false  statement by adding in a colon right here to say   well if they're not scared i want to assign it the  initial color of our ghost which is either going   to be red or pink or whatever we assigned to it so  this is all we have to do to change the color of   our ghost using this cool little ternary operator  that's what it's called with question mark and the   colon so i save and refresh i grab our little  power up down here they turn blue immediately   because they are currently scared and then after  three seconds they go back to normal so great now   when they are scared we need to remove them from  the game and make sure they don't hurt our player   when the scared property wears out so how do we  do that we're going to go back to our collision   detection code where our player collides with our  power up we know all this is happening down here   and i think that time limit of three seconds is  a little short based on what i saw so i'll change   our three seconds to five instead just so we can  test this out really well and then we want to   go ahead and scroll down to where we are testing  for a collision between our ghost and our player   and it's going to be within this ghost stuff for  each loop right here so i can say ghost touches   player for this conditional we know we lose right  here but we only want to lose if well this is true   but also if our current ghost is not scared so we  want to add an exclamation to this to say we're   not scared or at least the ghost isn't scared and  now if i save and refresh and grab that power up   you're going to see when i touch a ghost  there's no issue we don't lose the game   but eventually when they come back to normal  and we touch again well now we actually lost the   game how sad so if we touch a ghost while they  are scared we want to remove him from our game   before removing ghosts from our game it pretty  much makes sense to always loop backward with   our ghost array so we don't get any weird flashes  because if we were to go ahead and remove a ghost   while we're within this for each loop we're pretty  much changing the structure of the ghost array and   it makes for some really weird stuff to happen in  regards to flickering and other sorts of messes   so instead of doing this collision detection code  right here within this ghost for each i'm going   to actually cut it out and i'm going to go up to  where we are looping through our pellets and our   power ups and now i can create a for loop like  this specifically for our ghost so here we'll   say detect collision between ghosts and player  and now i just want to go ahead and duplicate   one of these for loops but first i'll go ahead  and paste in that conditional that we just grabbed   and now i'm going to grab this  for loop right here paste it above   add an ending curly bracket save so that's  inside of it but now i know i'm not looping   through our power ups i want to loop through our  ghost array this is just going to loop from the   very end of our array and now i need to actually  grab a ghost by declaring a const called a ghost   set it equal to ghosts i that's going to give us  the ghost we're currently looping over and now   we're going to go ahead and call this code right  here which determines whether or not we lose but   we also want code within this that says whether  or not we should remove a ghost in the first place   so what i'm going to do is i'm going to get  rid of this and statement that we just added   and inside of this i'm going to write an  additional if so i'm going to say if our ghost   actually is scared then we want to splice it from  the screen so go ahead and say ghosts dot splice   where do we want to splice this from while the  current index we're looping over from the very end   of our ghost array which is i as you can see right  here this is where we're looping through that is   the index so i want to go ahead and splice one  out from that specific position so basically we're   saying if we're touching a ghost that is scared we  go ahead and remove them from the game else what   do we want to do if we touch a ghost that is not  scared we lose the game we cancel our animation   frame we lose end of story so if i go ahead and  save and refresh now and i grab that powerup   they are scared they are blue if i touch one  we just remove them from the screen altogether   and then eventually they go back to normal i touch  it and we lose the game so if i go back to to do   we just created a power up and we added all those  cool effects with our ghosts being scared removing   from the game really cool stuff with that power  up so pretty much all we need to do now is add   a win condition and then add the pac-man chomp  animation kind of already been number 12 but   let's go ahead and add a win condition what we're  going to say is if we go ahead and eat all these   pellets we're going to cause log out you win and  we're just going to pause the game as well really   simple win condition for a basic version of the  game so we don't go too over time here all we   need to do here is go to some sort of empty spot  within our animation loop i'm just going to do   this right after this for loop we just wrote  and i'm going to say when condition goes here   and in order to detect whether or not we are  winning we just need to write an if statement   that says if our pellet dot length is equal  to zero meaning that we ate all the pellets   we won the game it is that simple so i'm going  to go ahead and write some opening closing curly   brackets create console log it says you win and  then we know if we win we also want to cancel our   animation frame to stop all movement because our  ghost might still be moving around and if i save   and refresh that and then finally catch all the  pellets let me do my best to do that without dying you're going to see once i get this very last  pallet right here we win the game we stop it   all together we have our win condition in place  so now what we could do if we wanted to continue   this within this if statement right here we  could proceed to a next level we could affect   the amount of ghosts within our ghost array  change their velocity to make our game harder   or generate a completely new map we will be doing  a little bit of that within the prime of course   but this is definitely a good way to get going for  showing you how to get that win condition in place   so if we look at to do's we're going to check  off at win condition we already laid out a full   level i believe we did that when we were swapping  out boundaries with images so we'll check that   off as well so now all that is left and i want  to make sure that i include this in this game   is the pac-man chop animation because that is a  classic can't really have a pac-man game without   that so how do we make sure that our little circle  right here is chomping like pac-man we're going to   go over to our player class and this is actually  going to be maybe a little easier than you think   we don't need a sprite or anything like that all  we need to do is edit our c dot arc function over   time so the c dot arc function right here zero and  math pi times two determine the arc in which our   circle is drawn so if we were to increase this  value here or decrease this value right here   we actually wouldn't have a full circle watch  what i mean by this if i go ahead and change   2 to something just like nothing just math pi  you see now we just have half a circle but if i   were to go ahead and subtract 0.75 from 2 save and  refresh well now we have almost a full circle it's   just a little bit is cut off and it's always going  to be that way if we just use arc right here so at   the end of our arc what i want to say is i want to  add in c dot line 2 and draw a line from the end   of our arc right here to the center of our player  so i want to go ahead and do that i can just say   our line 2 should go to this dot position.x  because that is the center of our player and   then this dot position dot y when we do that save  and refresh now we have what's the beginning of an   open mouth for our pac-man so we know subtracting  0.75 from this value right here opens up a little   bit of our pi let's go ahead and add on 0.75 to 0  right here for our first ratings argument and if i   do that now we have pretty much a fully open mouth  for our pacman so really what we want to do is we   want to oscillate this value right here between  0 and 0.75 this one right here as well these are   going to be a radians property so right beneath  the radius i'm going to go ahead and say this   dot radians is equal to 0.75 and now that i have  this that radius in place i can replace 0.75 in   both of these locations with this.radians and now  i can begin changing this property over time to   make sure it's oscillating between 0 and 0.75 so  to do this i need some sort of open rate how fast   should our pac-man mouth be opening and closing  i'm going to go ahead and say beneath this.ratings   i also want an open rate and i'll set this equal  to 0.12 and you'll see how fast that is once we   actually add it in and within our update function  i can say if this dot ratings is less than 0   or this.ratings is greater than 0.75 so these  are basically our oscillation values what do i   want to do if we go beneath 0 or above 0.75  i want to go ahead and grab our open rate   and set it equal to a reversed version of it so  we're basically going to be oscillating between   these two values at all times and now that i have  open rate going back and forth what i can say   is i want to go ahead and add on to this.radians  both this dot radians and also this.open rate and   that's going to make sure that this radius right  here is always pulsing between 0 and 0.75 so if i   save and refresh now you see we pretty much have  the perfect animation for a pac-man no sprites   or anything like that just the perfect opening  and closing mouth still works whenever we move   but you'll notice one issue if i start moving  down our pac-man doesn't rotate to go downwards in   that direction to make it look like he's actually  eating the pellets below so we need to apply some   sort of rotation effect based on which direction  our pac-man is currently moving in so it's been a   few days since creating this tutorial and i don't  actually remember if we covered rotating or not   but let's go from the beginning rotating on canvas  is a pain in the butt they don't have any good   function in which we can just turn our pac-man  and have him move in the correct direction so   in order to rotate something on canvas here's how  we're going to do it we're going to go inside of   the draw function which we want to rotate the art  of and before we actually call any art or drawing   functions i'm going to call c dot save and at the  very end of these i'm going to call c dot restore   because basically what we're about to do is we're  about to apply some sort of global campus function   to this code right here and if we weren't to use  save and restore at the beginning and end of this   while the global function would affect everything  on our screen we only want it affecting this code   right here which is why we're wrapping this in  save and restore so now we have that in place we   need to call a c dot rotate function which  is a global canvas function but by default   c dot rotate rotates from wherever our canvas  starts which is going to be right here so if we   were to call this code basically we'd be rotating  a pacman but not from the center would be rotating   from this position we want to make sure that we're  rotating our pac-man from the very center of it   so what we can say is we can call c.translate  which is another global canvas function   and we want to translate our canvas to the center  of our pac-man position so we can translate on   over to this dot position dot x and then this dot  position dot y for the y value that's going to put   us directly within the center of pac-man now we  can begin rotating it based on some value these   are radians i'm just going to put 0 in here  for now but then once we rotate our pac-man   we want to go ahead and move our canvas back  to this position so the rest of the code fires   correctly so to translate our pac-man back i'm  going to go ahead and call c dot translate again   but we're going to go in the negative direction  of this position x and this stop position y so   now if i wanted our pac-man to face the opposite  direction i would change this value here to math   dot pi this is in radians when you have radians  of math.pi that means you're going 180 degrees   counterclockwise i believe it's counterclockwise  shouldn't matter anyways but if we go ahead and   put math up pi and c dot rotate now with all that  translate code in place you'll see we're facing   the opposite direction but when i move we're  still not facing the correct direction so what   we want to do is add a property called this dot  rotation we'll set it equal to zero by default so   we're facing the right but now we can get rid of  math.pi and reference this dot rotation within c   dot rotate and we can begin changing this based on  which direction we are currently going so we could   go ahead and change our rotation all the way on  the bottom within our event listeners right here   but i almost always find there to be some sort of  issue when i try changing player properties within   here so instead i'm just going to do this directly  within our animation loop this is the end of   animate right here so i know inside of this i can  reference which direction our player is currently   going by asking if our player dot velocity dot x  is greater than zero i know i'm going to the right   so our player dot rotation should be equal  to zero and i can go ahead and say else if   just by copying this and adding an else to the  beginning of it else if our player velocity x   is less than zero our player rotation should  be 180 degrees which is math.pi in radians   and then i'll copy and paste and say if our y  velocity is less than zero then i want to go up   that is math.pi divided by two in radians i'll  copy the line again and let's say if we're going   down we should be facing downwards and in order  to get this we can go ahead and multiply math.pi   times 1.5 and that should set our player rotation  in the correct direction with all of our draw code   in place as well so i go ahead and save and  refresh if i move down well it looks like i   have that reversed actually if i go up okay i  definitely reverse those two lines of code no   problem looks like left and right work so really  we just need to go ahead and say this right   here math.pi divided by two should be when y is  greater than zero and then when we multiply by 1.5   it should be when it's less than zero so if i  go ahead and save and refresh i go down we face   the correct direction go up we face the correct  direction and this works within any corridor we   go in so pretty cool stuff for creating our very  first pac-man game so that's going to be it for   this one guys i hope you enjoyed be sure to check  out chriscourses.com for any future updates but   really enjoying this game myself and i hope you  guys did too i'll see you in the next one peace
Info
Channel: Chris Courses
Views: 121,629
Rating: undefined out of 5
Keywords:
Id: 5IMXpp3rohQ
Channel Id: undefined
Length: 154min 57sec (9297 seconds)
Published: Tue Feb 01 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.