welcome everyone this is another chris chorus with your host chris and today we're going to be coding
your very first fighting game we'll start off by learning how to code some basic fighting game
mechanics we're going to start off with some rectangles that know how to fight each other
once we develop these fighting rectangles then we're going to go ahead and change these
rectangles into sprites with animation we'll learn how to create sprites for both our background and
our fighters and then we'll touch up our interface design making this game ready for live on the web
so without further ado let's get started so the first thing we're going to do is focus on project
setup this just means we're going to set up our folders our files pretty much everything we need
to get up and running so to do this what i like doing is within sublime text i like going to file
new file and then i have a new file open all i need to do now is hit command s to save it
and now i need to go ahead and create a directory so i'm going to go inside of
a folder that is familiar to me that is a web directory that i created personally and
inside of here i can go ahead and create a new folder and i'm going to call this fighting dash
game so with this new folder created now i can go ahead and save this as index.html and hit save we
have our first file created great so now inside of index.html what kind of html element do we need to
create a game well no other than a canvas element so we're going to go ahead and create that now
so once we have a canvas element in place we can hit command s and we should be good to go
in regards to opening this up within a browser so to open this within a browser we can go to finder
and then go inside of our web directory specifically the folder we just created which
is going to be fighting dash game and this is the file we just created index.html so all i need to
do here is double click it now we have it opened up within a browser so i go ahead and inspect this
element by right clicking and hitting that inspect element tab you'll see we have a canvas within our
browser and all the html elements which are pretty much put in there by default thanks to chrome so
we have our canvas element within our html but now we need a place in which we can actually write
code so we're going to create a javascript file to do that back in sublime text we can go to file
new file that's going to create a completely new file for us once we're here we can hit command s
and then we want to go ahead and create a new file within our fighting game folder called index dot
js then we're going to go ahead and hit save and now we pretty much have all the files we need
in order to get started with this game it's that simple so it's pretty useful to have both index.js
and index.html open at the same time so in order to do that we're going to go to file open and then
we just want to go ahead and find the folder in which we want to open rather than one specific
file so once we have just this folder open we don't need to click either of these we can simply
just hit open right here and then we're going to see our project opens up we have our folders
on the left hand side going to be a lot easier for game development if we have this open at all times
so let's go ahead and start by resizing our canvas so it's the correct size for our game it's going
to be 1024 by 576 i typically find this a good ratio in size to make sure that our game fits on
most computer screen sizes so in order to do this we're going to go inside of index.js and we're
going to go ahead and create a const called canvas this is going to be equal to document
dot query selector we want to go ahead and select an element from this list over here whether it be
html head body or canvas which element do we want to select well simply the element that has a name
of canvas so all we're doing is grabbing canvas from right here and storing it within the const
of canvas simple enough the next thing we want to do is select our canvas context this is what's
going to be responsible for drawing out shapes and sprites onto our game so it's important
that we go ahead and pull this in to pull in our context we'll create a const call it c
set it equal to our canvas const and then we want to call a method on top of this called get context
and then what kind of context do we want to get a 2d context 3d context those are mainly our options
we want to go ahead and get a 2d context because we know this is going to be a 2d game
not a 3d game so with 2d inside of here we can go ahead and save and now we have our two main const
ready to go canvas and c c just stands for context and the reason we're calling this c is because
we're going to be using this so much it's going to be really tedious to keep calling something
that's long typically i never recommend creating variables that are just c or something really
short like this but this is the one exception i'll make for canvas context it is okay to call this
c so we have our canvas const and our c const our context but we want to go ahead and resize our
canvas and we're just going to use javascript to do this i typically find css models things
up a bit when creating canvas games so we're just going to do it the standard way within javascript
we can do that by selecting our canvas cons and then we want to go ahead and select the width
property on top of this so once we go ahead and assign any value to this whether it be a thousand
two thousand we're basically just saying our canvas width is going to be equal to that amount
of pixels so a good value for width is going to be 1024 and then beneath this we want to go ahead
and select our canvas height as well and declare that our height is going to be 576. this is a 16
by 9 ratio and by having a width of 10 24 we're going to make sure this fits on most screen sizes
so if we save this go back to our browser and refresh we're not going to see any difference
in our canvas size just yet because after we go ahead and save index.js with all this
code right here we need to make sure that this is pulled into index.html so right now
we only have our canvas element but when we're inside of here we can also create a script tag
that has a source equal to index.js so go ahead and type in index.js save go back to our browser
refresh and then you can see our width and height are taking effect i can hover over this
you'll see it's pretty much taking up the width of 1024 the height to 576. so we're pretty good
to go in regards to the size of our canvas if we want to go ahead and see the full width
we can always move our dev tools down by clicking these three icons right here and then clicking
this little tab icon dock to bottom that's going to move it to the bottom you can hover over our
canvas again and you'll see that's how much width it actually takes up now in order to see
our canvas background well we need to be hovering over this canvas element down here to emit that
blue highlight onto our screen let's go ahead and make it so our canvas has a white background
by default just so we can differentiate it from our actual browser background so within index.js
we can go ahead and select our canvas context this is what's used to draw shapes onto the screen
once we have our canvas context we can begin using the canvas api so what is an api method that we
can call to draw a white background well we can call c dot fill rect we're going to create a
big rectangle we're going to use it to fill up the entire width and height of the canvas so fill rect
takes four arguments the first is going to be an x position so i go ahead and put the x position at
zero and then the second argument is going to be the y position so i'm going to go ahead and assign
that to zero as well all this means right here is to draw starting from the very top left of our
canvas this is a coordinate of zero and zero back over in our code we want to add in a third and
a fourth argument so third argument is going to be the rectangle's width how large do we want to
draw this well we want to go ahead and draw this to full width over canvas so go ahead and select
our canvas width and then for our fourth argument we want to go ahead and put the height in there
so let's say this is going to be a rectangle that takes up the full width and the full height of our
canvas which is assigned right here on lines four and five so let's go ahead and save this we'll go
back over here to our browser and refresh and now we have a black background so that actually
takes care of the need to differentiate our canvas from the browser background and i'm
actually using a browser called min it's just a minimal browser that still uses chrome devtools
if i go ahead and close out of this you'll see our background is white but our canvas is black
that is totally fine to start we know where our canvas is we know where our background is
we can begin developing our game as needed because we know our drawing area is going to be this giant
black rectangle so as long as we have a folder with index.html and index.js we can go back to
our to-do list and we can go ahead and check off project setup that is all we need to get started
with our project the next thing we're going to do is create a player and an enemy and we're going to
start off creating these with just pure rectangles a lot of games are created that way developers
just insert rectangles into the game and they code the functionality between those rectangles before
inserting sprites we're going to do the same thing because it's pretty complicated to add some
sprites using just vanilla javascript and canvas it's more important to learn the functionality
and the basics behind a fighting game before we go ahead and get to the sprite portion
so in order to create a player and an enemy we want to make sure that we're within index.js and
although we could create a rectangular player just using fill rect we don't want to do it that way
we want to use object oriented programming because we need these rectangles interact with each other
and have their own individual properties that act independent from one another so in order to create
an object we're going to go ahead and create a class this acts as the blueprint for the object
before we actually create it so this class is going to be called sprite because later on when
we begin using images and replacing our rectangles actually moving things while moving images and
games are basically called sprites we're going to call it sprite in advance but within this
we're just going to start with the rectangles so whenever you create a class you need some sort
of constructor method which is basically just a function within the class and constructor is
fired for every time we create a new object from the sprite class and so whenever this is fired we
want to define the properties associated with a sprite so whenever you're doing game development
one of the main properties that you want to put on pretty much any object is going to be position
and whenever you create a property within a class and a constructor you need to make sure that it's
prefaced by this dot so each time we create a new instance of sprite it's going to have a property
of this stop position it's going to have some sort of position associated with it which we can place
it on the screen but we know our sprites might have positions independent from one another and if
that's the case we want to go into our constructor function and we want to pass through an argument
so we want to pass through an argument called position and each time we instantiate a sprite
while this position is going to be assigned to the position of the individual sprite we are creating
so now that we have a class of sprite with a constructor we can go ahead and begin creating our
player and enemy let's start with our player we're just going to create a const called player and set
this equal to a new sprite this is how we create a new object from this class right here so now that
we're creating a new sprite we can look inside of our constructor and see what argument this takes
so it takes a position argument and this is just a position we want associated with our player now
position can be any data type it could be a number it could be an object it could be a string but
in our case we want to go ahead and make this an object so i'll go ahead and put an object in here
and say that the x for our object should be equal to zero to start and the y of our object is also
going to be equal to zero this just means within our game we're going to place our sprite at the
top left hand corner of the screen to start and if we save this and then console log out player
save that head back to our browser open up our inspector and then hit the console tab and then
finally refresh you're going to see our sprite object is logged out we successfully created one
instance of our sprite class that is perfect that is exactly what we want but now we need some sort
of way to define what a player actually looks like so we also want to do that within our sprite class
inside of here i'm going to go ahead and create a draw method and this is arbitrarily named we could
call this whatever we want but it makes sense to call it draw because we know what we call this
we're going to draw out our sprite so whenever we call draw what should our sprite look like
well our sprite should just be some sort of rectangle as a result we want to go ahead and
call c dot fill rect to create a new rectangle so what we can go ahead and do is we can say well i
want the sprite to be drawn at whatever position is passed through our constructor right here
so basically what we're doing is we're creating a new sprite we're grabbing this x and y
we're going on up to our argument right here where positions being passed through
we're passing position through into this right here and then finally position is
going to be stored in this dot position which is the individual property we're creating for
our player const right here but now that we have this object right here being stored in this
stop position we can go ahead and reference this opposition within other methods within our class
so now that we have this opposition we can use it within c dot fill rect to say that our x value
should be this dot position dot x so now this right here is just referencing this x that we
passed through our second argument is going to be this dot position dot y that's going to reference
this y value right here and then finally we need some sort of width and height associated with
our player to start we can go ahead and just put these in as static values i'll go ahead and say
our player is going to be 50 pixels wide and about let's say 150 pixels tall so now we need some sort
of color associated with this draw method in order to make sure that it differentiates itself from
the black background of our canvas as a result we can put in c dot fill style and set this equal to
a string of simply red and if we assign fill style to red right here right before we call c
dot fill rect it's just going to make sure that we're filling in a rectangle with a red color
so if we save this nothing's going to happen if we go back to our browser but what we can do is
we can select our player const and then on top of this call this draw method that we just created
so now with player.draw below if we save go back to our browser and refresh you'll see this is
what our player looks like great that is exactly what we want to start so we have our player there
let's go ahead and create an enemy we'll put our enemy somewhere over here on the right side of
the screen kind of makes sense for fighting games put an enemy over there instead of right next to
us so in order to create an enemy we'd simply just duplicate the code that we created for our player
so we're going to create a const called enemy and set the sequel to a new sprite so what properties
does a new sprite take well we know it takes a position the position is stored within a position
property and we're just saying that we're using an x and a y property within this object we're
passing through so i'm going to say that our x is going to be equal to something like 400
just an arbitrary number off to the right and then our y value can either be zero or we can add some
numbers onto this to make sure that our enemy is pushed down we're going to say our y value
is going to be equal to 100. so now we have an enemy created in order to draw this enemy out we
just need to call enemy.draw save this go back to our game over here refresh and there's our enemy
not exactly where we wanted it since it's not all the way on the far right side of the screen
but this is close enough just to get started this is all we need so now we know our player and our
enemy are going to be moving objects and whenever you have moving objects within canvas it's pretty
standard to add a velocity property onto your sprite class velocity is just going to determine
in which direction should these be moving when they're inside of an animation loop so let's
go ahead and add some velocity and gravity to make sure that our player and our enemy right here fall
to the bottom of the screen and they stop once they hit the bottom of it so in order to get these
moving we need to create some sort of animation loop to create an animation loop we can go to the
bottom of our file and create a function called animate totally arbitrarily named by the way
you can call this whatever you want animate just makes sense because that's what we're about to do
now we can call window dot request animation frame which just says what function do i want to loop
over and over and over again i need to select one well we really only have one function created and
that is going to be animate so we can go ahead and take this name right here and paste it within
request animation frame so now right beneath our function if i go ahead and call animate
with animate and then some opening and closing parenthesis what's going to happen is we're
going to call requestanimationframe and then it's going to say we want to call what will animate
so we're going to go ahead and go right back to calling this function so we call
this function again what happens while we call request animation frame we call animate we're
basically just creating an infinite loop that we want to go on and on forever until we tell it to
stop so you can begin animating your objects frame by frame so if we really want to test that animate
is working we can just put a const log inside of it and i'm just going to put any string inside of
here it doesn't really matter what and i can go ahead and save this and make sure you're calling
animate down below for this to fire and then off in our browser if we refresh and then right click
hit inspect element and then open up our console tab right here you'll see we are logging out go
over and over and over again that is how fast our function over here of animate is being called
just really really quickly so we can begin moving these objects over time as this loops
through itself so now that we know that's working we want to go ahead and alter our sprites position
so that both our player and our enemy begin to move downwards they're going to be affected by
gravity so as i mentioned a little bit earlier we want to go ahead and add a velocity property onto
our sprite to do this right beneath position we can add in a new property called this dot
velocity and this is going to be equal to a new velocity that we're going to pass through as an
argument so if you need another argument within your constructor you can go ahead and add a comma
at the end of position and then pass through velocity as the second argument but one issue i
have with this is eventually as we begin adding more and more properties onto our constructor
well we need to remember the position of our properties first we need to pass through position
and then velocity we can't pass through velocity first and we can't pass through position second
and as this gets bigger and bigger it's going to be hard to remember the order of everything
so what i like doing to fix this is i like wrapping these two arguments within one singular
object like so so now we're only passing through one argument but within this object argument we're
going to be passing through a position property and or a velocity property they're not required
and the order does not matter anymore because we're passing them through as properties within an
object nice little trick to make your code cleaner and easier to manage so now that we're passing
through a position and a velocity this way we need to refactor our sprite instantiation down below
before we were just passing through one singular object so this right here is just equal to our
position but we need to define that we need to go ahead and wrap this one object in another object
so i'm going to go ahead and do that wrapping it in opening and closing curly brackets and then
inside of that first opening curler bracket i want to hit enter and i'm going to assign the
second object equal to a position property so your first sprite should look like this and now
this is a lot more legible as well we know that this object right here is equal to our position
so we need to pass through a second property and that is going to be equal to velocity so i'm going
to add a comma here and say that our velocity is also equal to an object with an x and a y property
because we're going to have two dimensional velocity to make sure that our object can move
left and right and also up and down so by default our player is going to have an x velocity of zero
and a y velocity of zero as well this just means that our player is not going to be moving by
default so this is the correct way to instantiate our player now let's go ahead and do the same
thing for our enemy we know that our enemy has a different x and y and x a 400 and a y of 100
but if we want to do this as quickly as possible we can simply just copy our whole cost of player
is equal to new sprite get rid of our const of enemy and then paste in a duplicate of player
now all we need to do is change the console player to a const of enemy and then set its position back
equal to 400 and 100 and now this is instantiated in the correct way but using a lot cleaner syntax
because we added in this object destructuring within our constructor function right here
so if we save this go back to our game everything should be the same we refresh it is that is great
it works with all of our new code but now we can begin using our velocity to move these objects
now when i have things moving around typically i like creating an additional method within my
class this method is going to be called updates when i want properties updated to begin moving
my spray across the screen this is where i'm going to call it is inside of update so whenever i call
update the first thing i want to do is call draw we're going to go ahead and call these two lines
right here and to call draw we can simply write this dot draw this just means we're referencing
this right here now if we want our player and our enemy to fall we need to go ahead and select
their position so we're going to select them with this not position dot y and then we're going to
add on to this over time with plus equal all plus equal means is that we're using this dot position
dot y and adding something onto it over time this is the exact same thing as this dot position dot y
plus equal to 10 it's just shorthand syntax to make our code a little cleaner so we're going to
use a shorthand syntax get rid of this line right here save and now what we're saying is over time
our position.y is going to have 10 pixels added onto it for each frame we loop over but in order
for this to take effect we need to make sure we're calling update within our animation loop down
here so let's go ahead and get rid of player.draw because those are only going to be called when our
file first loads we want to make sure that they're called for every frame within our animation loop
so inside of here we can call player dot update instead of draw because remember update is still
calling this.draw so we'll call player.update and then we'll call enemy.update as well
we save this go back to our game over here and refresh and you're going to see these are now
moving across the screen although it's creating a paint like effect instead of showing the
individual objects so in order to fix this we need to make sure that we're always clearing our canvas
for each frame we're looping over otherwise we're going to get that paint-like effect so before we
update our player and our enemy right before that we're going to call our canvas context with c
and then we're going to call clear rect on top of that make sure that second r is uppercase so this
is just going to be the same thing as fillrect but clearact just means we're not actually
drawing anything when we call this method so how large of a rectangle do we want to clear well we
have to start at zero zero the top left hand corner of our canvas and this should take up a
width of our canvas width and a height or canvas height so we save that and refresh and those are
indeed falling but we lost our black background because we're calling clear act instead of fill
erect well i guess clear wrecked just make sure nothing is shown in the background at
all so let's go ahead and change this to fill rack to my apologies let's just call c dot
right to make sure we get that differentiation of our canvas and the background and now what
happened while our background is red because the last thing we set for fill style was red right
here within draw so right before we call c dot fill rect we want to set c dot fill style equal to
black so that means when we call c dot fill right right here it's going to be a black rectangle
but then when we call player and enemy dot update they're going to have a fill style of red to make
sure that those differentiate themselves from the black background so i save go back over here
refresh things are looking a lot better although our player and our enemy are going off the screen
now so to get these two to stop at the bottom right here we're going to want to focus in on
our update function the first thing we want to do is change his static value of 10 equal to the
velocity we're actually passing through for both our player and our enemy sprite because if we want
our sprites to stop moving we're going to have to set our velocity equal to zero at some point
so what we're going to do here is instead of adding on 10 we're going to add on this
dot velocity dot y so for our position on the y axis we're adding on our y velocity we save this
and refresh now they stay in place because over here our y velocity for both our player and our
enemy is equal to zero but if we go ahead and change our player velocity equal to 10 on the
y axis and refresh now our player is moving down so you can kind of see the benefit of using object
oriented programming is it allows you to go ahead and change individual object properties
independent from one another right now only our player is moving down because we said for its
y velocity that should be equal to 10 while our enemy's velocity should be equal to zero so that's
a start but now what we want to say with an update is we want to write an if statement that says
if this dot position dot y that is going to go ahead and give us the top of one of our sprites
so this right here so if this dot position dot y plus this dot height now we don't have a height
property yet on our sprites let's go ahead and add one to add a height property right below
velocity we'll just add on this dot height we go ahead and set this equal to the static value we're
currently using down here of 150 and now we can swap out this location with this dot height within
our draw method but now we can also go ahead and reference this within our update method as well
so this position.y plus this dot height what is that equal to well that's going to be equal to the
bottom of a rectangle right here so if the bottom of our rectangle plus our sprite's velocity is
greater than or equal to the bottom of our canvas right here then we're going to go ahead and set
the velocity of our rectangle right here equal to zero and that's going to prevent it from falling
down past our canvas so with that in mind over in our code we have the bottom of our rectangle
we also want to add on this dot velocity on the y we want to say if this is greater than or equal to
the bottom of our canvas which we can get with canvas dot height because on canvas y coordinates
at the top start at zero and the further we go down the greater they get so down here will be
576 pixels which is equal to our canvas height then what do we want to do well we want to go
ahead and select this.velocity.y and set that equal to zero we want to stop our player from
moving downwards all together so we go ahead and save this and refresh and that falls down and then
it stops right before it hits the bottom so you'll see there's a little gap right here we're going
to go ahead and take care of that using gravity so what is gravity well it's simply just acceleration
onto our y velocity so that just means over time as long as our object is up in the air
we're going to keep adding a value onto this velocity until it hits the ground and if we keep
increasing our velocity over time the faster it's going to get the longer it falls it's just like
real life gravity so to create gravity right above our class we can create a global const called
gravity and set the sequel to something like let's just say 0.2 to start that should make
it fall relatively on the slower side so we'll go ahead and save that and we want to keep our code
right here the same but right before we affect our position on the y-axis we can go ahead and say
that this dot velocity dot y is going to have some sort of value added onto it over time and that is
going to be gravity it's going to be a value of 0.2 so now we don't need to say our velocity on
the y-axis is equal to 10 because this is going to be affected by gravity over time it's going to
add that downwards acceleration to our objects so we save this and refresh let's watch what happens
we refresh and that gravity is looking pretty darn good you'll see that it had that acceleration as
it was pulled downwards but we do have an issue while our player and our enemy are going off the
screen that is not a very good fighting game so to fix this what we can do is we can grab this
code we just put in and say we don't want to call this for every frame otherwise we're just going to
keep forcing our player downwards but rather we want to call this if this is not equal to true
so if we go ahead and add an l statement right here and paste in this.velocity.y plus equal
gravity for that else statement now we're only going to be adding gravity onto our y velocity if
our player and the enemy are actually above this value right here which is our canvas height so
let's go ahead and save that and refresh and you'll see both of these are pretty much in
the perfect position there's no gap beneath either of them because gravity took into effect to make
sure that these are pulled to the very bottom of the screen over time and that they're not pulled
down any further as long as this is equal to true so with this we are looking to be in great shape
and that leads us back to our to-do list we can go ahead and check off create a player and an
enemy so now we're going to go ahead and move our characters both our player and our enemy using
event listeners we're going to go ahead and make this a two-player game to start because coding ai
is pretty dang complicated so we're going to go ahead and just focus on the essentials
at least to start maybe in some premium tutorials later we'll go ahead and add an ai
let's go ahead and get our characters moving both our player and our enemy using event listeners
so within our code we want to go ahead and add an event listener this is just a snippet of code that
listens for some sort of specific event so to add in an event listener we can call our window object
and then on top of this call add event listener like so so this is going to take one argument
just a simple string which declares what kind of event do we want to listen for so there are
things like click there are things like touch we want to go ahead and listen for an event of
key down this is an event that occurs whenever we press any key on our keyboard
so here we're going to add in an arrow function as our second argument this is what's going to
be fired for any time we press down on a key and within this arrow function we can pass through an
event object like so and then console log out within our arrow function this event object so
we can see what's inside of this so we're going to save this right click hit inspect element and then
open up our console and then make sure that we clicked on our canvas and then we press down on a
key i'm going to go ahead and press k you're going to see that we just logged out that event object
so this is a keyboard event and if i open this up we have a bunch of different data properties
associated with that event so here you can see we pressed a key of k here we press the key of k
a lot of the stuff i don't even know why it's here but the thing we want to focus in on is what key
are we currently pressing so this property right here of key is what we want to bring into our code
so right here we can reference event dot key save that go back over to our game refresh click on our
canvas and then start pressing keys you're going to see i'm logging out each key that i press down
on a keyboard that's exactly what we want because we want to determine which keys should move our
player in which direction so if i go ahead and move this off to the right side by clicking these
right here clicking dock to right now we can keep our console open while seeing both our player and
our enemy as well so back within our code within this keydown event listener i want to go ahead
and add in a switch case statement within this switch i'll go ahead and reference event dot key
and say for a case of what well a case of d then i want to go ahead and call the following code
and then call break so what i'm saying right here is i want to go ahead and grab the key
we're currently pressing with event dot key and if that key is equal to d on the keyboard then
what do i want to call well i'm going to want to call some code that moves our player so whenever
i press d i want to select our player and then i can set our player's velocity on the x-axis
equal to about one this means we're going to be moving one pixel for every frame we loop over
within our animate loop so if i save this and refresh and then hit d while we're not actually
moving even though i'm clicking the key because we need to define how our player should be moving on
the x-axis if we look within our update function right here we only define how our player is moving
on the y-axis we need to do the same thing for the x so right above this.position.y i'm going
to reference this dot position dot x and over time we're going to add on this dot velocity dot
x so with this simple line of code if i save that and refresh now when i go ahead and hit d on the
keyboard we have our player moving on over to the right simply because i hit d on the keyboard now
this is just going to keep going because i didn't declare what should happen when i lift up on a key
so back within our code we're going to want to add in a new event listener right beneath this one
but to add in that event listener i want to copy this one we just created so go ahead and copy that
paste it down below and i want to listen for an event of key up rather than key down so whenever
i key up well i want our player velocity on the x-axis equal to zero so i save that
refresh and then hold down d you're going to see that's firing we're moving over to the right but
as soon as i lift up you're going to see we stop because we set our player's velocity on
the x-axis equal to zero so this is a great way to get our player and our enemy moving to start
let's go ahead and make our player be able to move to the left as well so to get our player to move
to the left all we need to do is copy this case statement paste it down below and then say when
should our player move to the left well when we have a case of a we know when we press down the
a key our player should be moving leftwards but in order to move our player leftwards
we need to make sure that our player velocity on the x-axis is a negative value rather than a
positive one so we're going to set our player velocity on the x-axis equal to negative one
and then when we key up we're going to set that back equal to zero no matter which key we press
but we need to make sure that we add in that additional case for when we lift up on the a key
so we go ahead and lift up on the a key as well our player velocity on
the x-axis is going to be equal to zero so i save that go back over here and refresh
now when i hold down d we start moving to the right i let go we stop and then when i start
holding down a we go to the left when i lift up we stop so that's cool and you might think we're done
but there's something i want to show you if i go ahead and hold down d well everything looks great
right but now if i keep holding d down and i press a to go to the left looking great but i have a
lift up on d i'm still holding down a but we're not moving to the left that is because within
our code even if we're holding one of these down we're saying whenever we lift up on either d or a
we're setting our player velocity x equal to zero this occurs after one of these occur so therefore
we're stopping our player from moving just by lifting up on any key as a result we don't want
to set our velocity within our key down or key up function we want to go ahead and set it within our
animate loop instead to make sure we have the most accurate movement possible within our game
so i already have a pretty good method for doing this this is by creating a const and i'm going
to do this right above function animate a const called keys this is going to be equal to an object
that declares all the keys we want to use to control our game so the first key i want
to use is going to be a i'm going to create a new object assigned to that and then i want to
go ahead and create a pressed property and set it equal to false to start so this is what our first
property is going to look like and now i also know i want a d property to move our character to
the right so i'm going to monitor for a d key by copying this property right here adding in a comma
and then pasting in that second object say instead of a i want to reference d by default this
is going to have pressed equal to false and now within animate i can say if keys dot a dot pressed
is equal to true well i want to go ahead and set her player dot velocity on the x-axis equal to one
and then i can write an else if in here that says if keys dot d is equal to pressed
what do i want to do well i want to go ahead and call player dot velocity dot x
is equal to one here actually so if we go and look at a well a means we should go to the left
this should actually be set equal to negative one instead of one but let's go ahead and save that
nothing's going to happen on refresh because we need to set a dot pressed or d dot pressed equal
to true when we actually press down on one of these keys so to set a dot pressed equal to true
we're going to do that within our q down event listener and right here when we press down a we're
no longer going to set our player's x velocity rather we're going to grab keys dot a dot pressed
and we're going to set this equal to true because we know we just pressed down on our a key but
whenever we lift up on our a key down here we want to select the same thing so keys dot a dot pressed
but here we're going to set it equal to false let's go ahead and do the same thing for our d
key i'm just going to copy this line of code right here within our case of d
i'm going to get rid of player.velocity.x equal to 1 paste in keys.a.pressed equal to
true but instead of referencing a this should be our d key which we assigned right about here
and then when we're listening for key up we want to go ahead and select keys.d.pressed
and instead of setting our player velocity x equals zero
we're going to set keys.d.press equal to false whenever we key up on our d key so now for each
loop of our animation we're going to be listening for whether or not one of our keys is pressed down
and it doesn't matter if we key up now we're still going to be moving either left or right
because our key up event listener is not responsible for our player's actual velocity
on the x-axis let's go ahead and save this and refresh and see what that looks like
so now if i go ahead and hold down d we're moving to the right but watch what happens if i lift up
we're still moving to the right that's okay but if i go ahead and press down a now we're going to the
left but we keep on going even though both hands up i'm not actually pressing down on any of the
keys so right before we actually set our player velocity equal to either negative one or one
we need to make sure that before this we set player.velocity.x equal to zero so the default
value for our player's x velocity is going to be equal to zero but if one of these is equal to true
then we're going to set it equal to one and move our player in that direction it's going
to make sure that we stop whenever we lift up on one of our keys save and refresh now if i go
ahead and hold down d we move to the right but if i lift up both hands up we stop moving great
if i go ahead and hold down a we move to the left now watch what happens when i hold down d
and then i press a while i'm holding down d we start moving to the left but if i lift up d
we keep on moving so we fix that issue in which our player stopped if we lift it up on one of
the keys now you might think we're good to go but there is one more improvement we want to make here
to give us the most accurate movement possible so i go ahead and move our player over to the right
and i stop and i hold down a and then i hold down d well they're both pressed down but we're moving
to the left even though i just pressed down d why is that happening well if we look within
our code specifically this portion right here let's analyze this while if a is pressed we're
moving to the left but if a is not pressed then we're going to go ahead and move to the right
if d is pressed only if d is pressed the thing is if i go ahead and press down a
first we're going to be calling this code right here and then when i press down d yes we do want
to call this code but only this first if statement is going to be called because this value right
here is still pressed down to fix this we want to go ahead and add in some sort of let some sort of
variable that tracks the last key that we press down to make sure that we get the most accurate
movement possible and that when we go ahead and press down on our d key while a is also pressed
the d key overwrites that and we make sure that our player moves to the right because that was
the last key we pressed down so to do this right beneath our keys const i can go ahead and create a
lut and this is going to be called last key i'm not going to assign anything to this to start
but whenever we key down and have a case of d i want to select our last key and set that equal to
d just a simple d string and then right here for our case of a i'll go ahead and select our last
key and say the last key we pressed down was a so now keys dot d dot pressed and keys a dot pressed
those can be equal to true at the same time but last key is only ever going to be equal to one
value and that is going to be the last key that was pressed down we don't need to do anything
with in key up we just want to know what was the last key we pressed down so nothing within key up
now that we are monitoring which key we press last we can use this within our if and else
if statement so if keys.a.pressed is equal to true and our last key is equal to a then we're
going to go ahead and move our player to the left else if keys dot d dot press is equal to true and
our last key is equal to d then we're going to go ahead and move our player to the right
so that should fix our issue with overriding which direction our player should be moving so i save
that i go back to our game i refresh and i begin holding down d looking great i hold down a we're
now moving to left lift up on d and then i start holding down d that overwrites a even though i'm
still holding down a at the moment so that's how we're going to add pretty much perfect movement to
our game using event listeners and our animation loop at the same time now let's also add a jump
effect to our player to add a jump effect while we want to listen for on key down another case
this is going to be a case of not a but rather w this is going to be our player on the left
hand side screen whenever we press the w key we're going to jump upwards so we want to go ahead and
select our keys object specifically a w property which we haven't created yet but we will and then
our last key is going to be equal to w that's the last key we press down when we key down on w then
within key up we know we need another case to listen for whether or not this key is currently
pressed when we have a case of w we know keys.w dot pressed is equal to false so we just need to
go ahead and create this property right here and we can do so within our keys object by setting w
equal to an object with pressed equal to false so to create a jump effect the first thing we want to
do is add in a new case whenever we key down what case do we want to listen for well simply a case
of not a but w we're actually going to do this a little differently from moving our player to the
left and to the right we don't have to monitor for whether or not this key is pressed and we don't
have to use a last key what we want to do is just go ahead and select our player velocity on the
y-axis and set this equal to something ridiculous so let's just say something like negative 10.
we're going to set this equal to negative 10 whenever we press down on w we go back to our
game refresh let our player fall and then we go ahead and hit w on the keyboard you're going to
see that our player just moves upwards and falls down perfectly because we added gravity into our
sprite class right on up here right here we know we're always adding on gravity to our y velocity
if the bottom of our player is above the bottom of our canvas so as long as our player is above this
we're going to keep on pulling our player down by altering our player's y velocity and since our y
velocity is always being added onto our player's y position over time when we set our velocity.y
equal to 10 we're just shooting it upwards we're basically just saying move upwards as quickly
as possible using a velocity of 10. and then over time we're pulling that back down because we know
we're calling else and when we call else we're adding gravity back on to our velocity until it
hits a velocity of zero which is going to keep our player on the ground so that's how that works down
here is we're setting our player velocity y equal to negative 10. when we press w on the keyboard we
move up and then gravity pulls us back down that's all we have to do to create that jump effect
so now let's go ahead and move our enemy over here using our arrow keys so to monitor for our
arrow keys we want to listen for a case but we might not know what case an actual arrow key is
so if we want to go ahead and monitor that case we can go ahead and console.log out our event object
specifically the key property if we're going to save this go back to our browser and refresh and
then we only press down on some of our arrow keys so i'm going to press the right arrow key
you're going to see that gives us a value of arrow right i know i also want to press down
on our left arrow key it's going to give us arrow left and if i press up that'll give us arrow up
so these are the values that we want to listen for within our case statement so i'm just going
to go ahead and duplicate these three and then we're going to go ahead and paste in
three new case values so d should actually be arrow right with the exact same casing that we saw
over here in the browser which that is correct and whenever we press down on arrow right while keys
dot arrow right dot pressed should be equal to true now for last key well we don't want set last
key equal to arrow right because this is going to be our second player essentially we don't want to
overwrite our first player's movement by setting last key equal to something like arrow right
as a result it makes sense to add in a last key property onto our sprite class because we know
this property is going to be independent for both our player and our player 2 enemy objects
so instead of referencing last key like this i'm actually going to go into our classes sprite and
say that this dot the last key is going to be a property within our sprite class but it's not
going to be equal to anything by default but now that i have that declared i can say within
arrowright i want to go ahead and select our enemy specifically the enemy's last key property
and set that equal to a string of arrow right and now i can delete this last key right here
so now i just need to make sure i do the same thing for arrow left so i'll get rid of a
and say whenever we press down arrow left keys dot arrow left dot press should be equal to true
and not our last key but our enemy last key should also be equal to arrow left and then finally we
need to say what happens when we press on the up arrow key so when we have a case of arrow up we
want to go ahead and select our enemy dot velocity dot y and set that equal to negative 10 instead so
that takes care of our key down event listeners for our enemy and we need to make sure that we
add in our key up event listeners as well so we'll go ahead and duplicate the switch case statement
right here for key up for our player we can go ahead and comment this out to say this is our
enemy keys right here we're going to paste in a duplicate of that and say whenever a case of error
write is keyed up on then we want to go ahead and declare keys.arrowright.press is equal to false
whenever a case of arrow left is lifted up on then we want to go ahead and say keys dot
arrow left dot pressed is equal to false as well so that'll take care of key up
now we need to go ahead and add this into our animation loop so this statement is going to
be player movement we can go ahead and duplicate all this code right here paste it below and say
that this is going to be our enemy movement so to move our enemy if keys not a is pressed but rather
arrow left is pressed and our enemy last key is equal to arrow left then we want to go ahead and
select our enemy's velocity on the x-axis and push it over to the left then within this else
if we want to select our keys dot arrow right if that is pressed and our enemy last key is equal to
arrow right then we're going to set our enemy velocity.x equal to 1.
so what do we need to do now well within our keys up here we need to make sure that we're adding in
arrow right that's going to be equal to an object with a press property equal to false
we also need to add in arrow left that'll also be equal to an object with a pressed property
equal to false and we should be good to go with that so let's go ahead and save refresh over here
and then we're going to test out our arrow keys so if i go ahead and hold down on the left arrow key
you'll see our enemy over here is moving to the left i hold down on right well now we're moving
over to the right and you're going to have to excuse some of this movement right now because i
have this console open just kind of messing things up a bit when i press down on those but we do have
the same issue in which our enemy continues moving even though both hands up i'm not pressing down on
any of the keys so back within our game right here we're setting our player velocity x equal to zero
we also want to make sure we're setting our enemy velocity x equal to zero as well to make sure that
we stop for every frame we're not holding down on a key i save that i go back hold down on the
right arrow key lift up we stop hold down the left arrow key lift up we stop but if i go ahead and
hold down d for our player that moves as well and now watch what happens when i press on the right
arrow key we can move both of these at the same time independent from one another it's a pretty
classic game style where you used to have to sit next to your friend and use different keys on the
keyboard to actually get things moving around so to finish up this movement with event listeners
i just want to make sure that our enemy and our player move a bit quicker throughout our scene
and i also just want to go ahead and refactor some of our player code real quick let's go ahead and
do that first let's refactor that player code what code do i want to refactor well it's going to be
within our event listener right here we don't want to listen for last key anymore because we
don't need that independent variable we created a property for our sprites so instead we can
reference our player last key set that equal to d right here and any place where last key is by
itself we're going to make sure that we prefix that with player so these two locations right
here are going to be player dot last key and then we would listen for last key within our animation
loop we're going to say and player last key for a and player last key for d and then finally we can
get rid of this line right here because we know we created that property within our sprite class
so we save that refresh hit down d we move to the right lift up good to go hold down a
lift up good to go so just a small refactor to get rid of that lut that we no longer needed now let's
get everything moving around a bit quicker we want everything to move around quicker we just need to
increase these values right here so i think a good speed for a fighting game instead of ones is going
to be five this just means we move at five pixels per frame instead of just one so each location and
which one is currently at within our animation loop i'm going to change that equal to five
save and refresh over in our browser now if i hit down d we move a lot quicker for both our enemy
and our player if i jump well that's pretty slow still to make sure that our enemy and our player
fall down quicker we just need to change the value of gravity so up above when gravity is
equal to 0.2 we fall down pretty slow but if we increase this to something like 0.7
save and refresh and then start jumping you're going to see we fall down pretty quick
although we don't jump as high so how do we go ahead and fall down at this rate but jump higher
well we do want to go ahead and increase gravity we'll keep it at 0.7 for now but within our event
listener specifically when we key down on either w or arrow up we just want to set this equal to a
higher value so i'll go ahead and set it equal to 30 for both w and arrow up save and refresh
and now when i go ahead and press w you're going to see well maybe a little too high
right there we're going into outer space it's going to decrease it to something like 20.
just say that both of these should be equal to 20 save and refresh and then jump i think that's
pretty good for the jump in our game so now we have some really responsive movement between our
player and our enemy and using a good method to make sure that our keys over right which one is
supposed to control the direction in which our character or enemy is moving so with that we are
going to be able to check off move characters with event listeners so now we're going to go ahead and
create attacks for both our player and our enemy how's this going to work well over here when we
go ahead and move closer to our enemy on the right hand side eventually we're going to go ahead and
press something like spacebar what this is going to do is it's going to activate a rectangle that's
drawn on top of our player this rectangle is going to represent our attack whether it be a sword
swing or a punch it's going to represent either one of those so what we want to do is monitor for
collision between this rectangle and our enemy is this rectangle currently touching our enemy
no it's not so we're going to say the attack missed we're not going to do anything
but if we go ahead and move our player a little closer now our rectangle when we go ahead and
press spacebar should indeed be touching our enemy therefore our enemy has been hit we're going to
go ahead and subtract health from our enemies health bar so to get this effect we need to go
ahead and create this rectangle on top of both our player and our enemy for when our enemy wants to
use an attack so to create that rectangle we're going to go back to our code over here and we're
going to focus in on our class of sprite so that rectangle i'm going to add it in as a property of
this dot attack box like so now what is an attack box well it's going to be eagle 2
and object it's basically just a rectangle so what properties does a rectangle have well they're
going to have a position property and they're also going to have a width and a height so we'll add in
properties for width height and position right here now what should position be equal to well i
want our attack boxes position to always follow our player around therefore i'm going to make
it based on the position of our actual player it's going to be starting at the top left hand
corner right here to make sure that i always follows our player around well we can assign
position right here equal to this dot position by default whenever position changes right here
our tag box position is also going to change as well that's perfect that's exactly what we want
now for our width i'm just going to go ahead and give this a value of 100 to start and for height
i'm going to make sure that height is equal to 50. so now if we want our attack box drawn out we're
going to have to go inside of our draw function right beneath this code right here i'm going to
create a comment that says this is where attack box is drawn and i can go ahead and draw this with
c dot fill rect so the first argument is going to be the position of the attack box so this
dot attack box dot position dot x the second argument is going to be this dot attack box dot
position dot y so the y position of our attack box and then we need the attack boxes width and height
which we can get with this dot attack box dot width and then our fourth argument is going to be
the height of our attack box and we can get that with this attack box dot height so if we save this
and then refresh our game over here you're going to see now our attack box is drawn on top of our
player and our enemy so it's kind of hard to tell right now what is our player what is our
attack box so right before we're drawing out the c dot fill rect we can add in c dot fill style
set that eagle to a different color such as green save that refresh now we know what our attack box
is and what our player is so now we need to detect for a collision between this attack box right here
and our enemy is this attack box touching our enemy well now it is we need to detect for that
and tell our game what should happen as a result now to detect for a collision it's going to be a
little hard to tell what is our player and what is our enemy as we go about doing this so i want
to make sure that our enemy is a different color from our player just so we can see where things
are relative to each other as we go about coding this so we want to change the color of just our
enemy what we can do is we can set this fill style right here equal to an argument we passed through
our constructor so instead of referencing red i want to go ahead and say that this is going to
be equal to this dot color which means we need to create a property for this dot color right up here
within our constructor so this dot color is going to be equal to color which now we're going to pass
through as an argument right here so we're going to pass through that argument of color by default
i'm going to set this equal to red so we save that and refresh still going to function exactly
the same but now that we have this as an argument what we can do is down below where we're actually
creating our player and our enemy when we go ahead and create an enemy we can say that we want the
enemy color to be equal to a string of blue if we save this go back over here now we can easily
differentiate between our player and our enemy because our player is red our enemy is blue this
is going to be really good for when we go ahead and detect for collision let's go ahead and do
that now to detect for a collision we need to go inside of our animation loop right beneath where
we're sending our player and our enemy movement we're going to go ahead and detect our collision
right here so detect for collision we need to go ahead and write an if statement and what does
this if statement say well we need to go ahead and say is the right side of our attack box right here
greater than or equal to the left side of our enemy if this is past this point right here
we know the two are colliding in that case we're going to start off with that so how do we get the
right side of our tack box we're going to go ahead and get that with our player attack box
dot position dot x that's actually going to give us the left side of our attack box so this right
here we need the right side and to get that we can get it with player dot attack box dot width
that is going to give us the right hand side of our player's attack box perfect but now we need to
say is this greater than or equal to the left side of our enemy so we can do that with greater than
or equal to plus side over enemy which we'll get with enemy dot position dot x now if this is true
we can go ahead and cause log out any text such as just go it doesn't really matter what we put here
but if we save this go back to our game right click hit inspect go to console now we're not
actually console logging out to go until the right side of our attack box is greater than or equal to
the left side of our enemy right here as soon as i go off of that you'll see that stops logging out
that is perfect that's why we want to begin detecting for collision
but now watch what happens if our attack box goes off of our enemy but keep moving even though our
attack box is not touching the enemy while we're still constantly out go so now we need to add in
an additional conditional what is that conditional going to be well we need to detect for whether or
not the left side of our attack box right here is less than or equal to the right side of our enemy
we're basically just going to do the conditional in reverse that we just wrote
so to get the left side of our attack box we want to go ahead and add in an and statement that says
is our player dot attack box dot position dot x that is the left side of the attack box is this
less than or equal to what while the right side of our enemy we can get the right side of our enemy
with enemy dot position dot x that'll actually give us the left side but to get the right side
we add on the enemy's width and that's going to make sure we get the right side of the enemy
but if we're referencing a property of width on the enemy and we look within our class up above
right up here you'll notice we never actually assign a with property to our sprite class
we need to make sure we do that in order for this collision detection to work properly
so right above height i'm going to add in a property called this dot width and i'm going
to assign that to the 50 we're currently using to draw out our player so width is going to be equal
to 50 here we can replace 50 with this dot width and if we save that go back to our game now our
collision detection should work as expected on the x-axis so we're no longer consolidating out
go which is great now when our attack box touches our enemy we're logging that out but if i go past
our enemy over here we're no longer logging out to go until the left side of our attack box
is past the right side of our enemy so eventually we go to that point now we are touching we know
that our enemy should be hit in this case now we're also going to want to account for the y-axis
you'll see if i begin jumping and i move into our enemies area we're still logging out go even
though our attack box isn't necessarily touching the enemy so we need to make sure that we monitor
for collision on the y-axis we want to say is the bottom of our attack box right here greater than
or equal to the top of our player in this case it definitely is so we want to say that these two
are colliding but as soon as we jump up that's not the case we want to set that equal to false
so let's go ahead and write this conditional we want to get the bottom side of our player let's
go back to our animation loop this is where we're detecting for collision we want to add in an and
statement that says get our player dot attack box dot position dot y we want the bottom of our
attack box though this right here is currently the top of it to get the bottom we'll add on
our player dot attack box dot height we want to say if this is greater than or equal to the top
side of our enemy which we can get with enemy dot position dot y then we know the two are colliding
but we do need to add in one more conditional to make sure that this is as accurate as possible
we want to get the top side of our player's attack box which we can get with player
dot attack box dot position dot y if this is less than or equal to the bottom side of our enemy
which we can get with enemy the position dot y plus enemy dot height then we know the two
are indeed colliding on the y-axis for sure so let's go ahead and save this refresh over here
and now when we go ahead and jump up and down when we're overlapping our enemy with our attack box
that's going to go away that's exactly what we want we know our collision detection is correct
for when our attack box is overlapping on top of our enemy so right now we're basically walking
around with our sword out at all times that's not really a fun fighting game we can't just walk into
an enemy and say hey you got hit we need something that actually activates our sword to say that this
is the exact moment in which our enemy can be hit so within this conditional we're actually
going to add in one more and statement that says if our attack box is colliding with our enemy and
our player is attacking then we know our enemy did indeed get hit so basically we need to add a
property onto our player that says whether or not they are currently attacking let's go ahead and
add that property on we'll go on up to our sprite class and then here we'll add in a property called
this dot is attacking we're not going to assign it to anything by default it's going to be equal to
false but in order to activate this to true right beneath update we can add in an attack method
and whenever we call attack on one of these objects we're going to go ahead and set
this dot is attacking equal to true now we should only be attacking for a certain period of time
we're going to set this equal to true without setting it back equal to false well it's going
to say we're always attacking at all times we only want to activate this for a certain
period of time so we're going to call a function called set time out it's going to take an arrow
function as the first argument and a time as the second argument for the time we're going to put in
100 which should be equal to around 100 milliseconds i do believe that is but
basically within the set timeout arrow function we can set this stun is attacking equal to false
so when we call attack this dot is attacking is going to be equal to true then after 100
milliseconds this that is attacking is going to be equal to false so just make sure that we set
this back equal to its original value at some point in time but we do need a way to activate
this attack method we're actually going to do that within our event listener down below where
we're listening for key down so if our event key for our player which are these cases right here
has a case of space we're just going to include an empty space right here for a case which just means
we press down on the space bar what do we want to do when we go ahead and press down on space
well we want to go ahead and say that our player is going to attack whenever we press down on the
space bar so if i go ahead and save this and go back to our game and i walk into our enemy
you're going to see that we're no longer console.logging out to go but as soon as i press
space it's going to set is attacking equal to true which means we're going to activate our collision
detection code which should console.log out go so let's go ahead and press space and you'll see
for that brief period of time that conditional was true our attack box was overlapping with the enemy
so we constant logged out go for that period if i go ahead and move off our enemy and i press space
we're not logging out because our attack box is not touching the enemy if i go back over here
press space we're logging it out once more because we know we're currently attacking at that point
in time so you'll see goes being logged out a couple of times that means our enemy has been hit
but we know our enemy didn't get hit four or two times in a row they only got hit once
so whenever we go ahead and detect for collision and we call it log out to go we immediately want
to set player that is attacking back equal to false and just with this if we go back over
here and refresh and move inside of our enemy and then hit space you're going to see that now we're
only logging out go once that's exactly what we want to subtract the accurate amount of health
from our enemy when we hit them now it doesn't really make sense to show our attack box at all
times it's kind of confusing actually so back up in our sprite class we can make sure that we're
only showing it when we're actually attacking so where we're actually drawing out our attack box
we can write above it if this dot is attacking if this is equal to true then we want to go ahead and
call the draw code inside of it otherwise we're never going to draw it so if i save
and refresh and hit space you're going to see that our attack box only shows for that brief period of
time and we're only going to log out that this got attacked if we're currently overlapping with our
enemy so that is exactly what we want to begin creating attacks within our game so that's how
we're going to add attacks for our player let's go ahead and add attacks for player 2 or our enemy as
we've been calling it to make sure that this blue guy over here can fight back towards the red one
so to get our enemies attack box position in the correct spot i'm actually going to comment out
this statement we just wrote just so we can see the attack box at all times so you can refresh
and that's looking good but we do want this attack facing towards the left so we need to move this
attack box over some to change the position we need to make sure that our attack boxes position
is not completely dependent on the position of our actual player or enemy entity so to do this
we're going to go ahead and change position right here equal to an object with an x
and a y property and then x by default is going to be equal to fighter's position which we can get
with this.position.x and this stop position dot y now when i save this and i refresh you're going to
notice that our attack boxes are staying up in the sky that is because with this change we no
longer have a shallow copy of our parent position when we don't have a shallow copy what that means
is position.x is no longer going to be directly linked to this stop position we need to go ahead
and make sure that our attack boxes position updates manually based off position of the
parent so to do this we just need to head inside of update and right beneath
this dot draw we'll say this dot attack box dot position on the x axis is going to be equal to
this dot position dot x and then we'll do the same thing for attack box position on the y-axis
it's going to be equal to this.position.y so i save that and refresh now those follow accordingly
which is great but we do need to offset our enemies attack box so to add in that offset
we're going to want to focus in on where we're setting our attack boxes position on the x-axis
so we're setting it equal to our current parent position but we also want to subtract from it some
sort of assay if we go ahead and subtract 50 from here save and refresh you'll see that moved over
a little bit for our enemies attack box but it also moved over our player's attack box as well we
don't want that we want this value right here to be dynamic based on what we're passing through our
constructor so instead we're going to go ahead and subtract from this this dot attack box dot offset
dot x so we need to create this offset property and we're going to create it within our attack box
right here so we'll add an offset and this offset is going to have an x and then also a y what is
x going to be equal to well whatever offset we pass through within our constructor it's going
to pass through just one offset object we'll add it within our constructor and offset property
and then we can go ahead and just set offset equal to that property we're passing through
so offset is going to be equal to the offset we're currently passing through and if we want to use
shorthand syntax we can actually get rid of this colon and offset because since these two have the
exact same name we can simply get rid of the colon offset this right here is the exact same thing
as this right here it's just shorthand syntax to make our code a little cleaner but now that we're
passing through an offset argument we need to make sure we're doing that whenever we're creating a
sprite so right here we're going to add in an offset argument we're just going to have an x
and also a y our x for our player isn't going to be anything it's going to be zero and same thing
for our y we're just going to keep it where it is at the moment but if we want to pass through
an offset argument for our enemy right here we can say that our offset for our attack box on
the x-axis is going to be negative 50. so we save that now this negative 50 should take effect
by being set to offset right here which means when we go inside of update we're going to call
attackbox.offset on the x-axis this right here is going to be equal to negative 50. so we don't want
to subtract the negative 50 but rather add it on that's going to give us the correct effect that
we want and if we save that and refresh now our attack box for our player is in the correct spot
and our attack box for enemies in the correct spot as well just need a little bit of refactoring and
where this rectangle is drawn so now we want to monitor for a collision between our enemies attack
box and our actual player over here so to do this we're going to focus in on where we're currently
detecting for a collision between our player's attack box and our enemy we simply just want to
go ahead and duplicate this code but refactor it for our enemies attack box and our actual player
but this code is kind of hard to read because we have so many and statements inside of here
it would make a lot more sense to refactor this into its own function that detects for collision
as a result i'm going to go ahead and copy these first four conditionals which are actually
detecting for that collision and right above animate i'm going to create a new function called
rectangular collision this is going to detect for a collision between two rectangles
and inside of here i'm going to return some parentheses and paste in those four conditions
i just copied so now if these four conditions are true we're going to return true if they're false
we're going to return false but in order for this to work we need to make sure that we have
a player.attack box to reference and that we have an enemy.positioner reference as well so whenever
we call rectangular collision we also want to pass through an argument it's just going to
be a singular object which takes a rectangle one property and then a rectangle to property as well
so what is the first rectangle we want to detect for collision with it's going to be our player
rectangle so everywhere we have player i'm going to go ahead and replace player with rectangle 1
and then every place we have enemy it's going to be in these couple of locations right here i'm
going to replace that with rectangle 2. so now we have a reusable rectangular collision function in
which we can use to detect for a collision between our attack boxes and our fighters but it's also
going to be usable for when we want to use it with our enemy so down below when we're detecting for a
collision we can get rid of these first four conditions and then we can call rectangular
collision what does this take it takes one argument which is going to be an object and inside
of this we have two properties it's going to be rectangle one what is the first rectangle equal
to what's going to be eagle 2 or player and the second rectangle is going to be equal to our enemy
so if our player's attack box and our enemy are colliding and our player is attacking we should
cause log out go let's save this and refresh to make sure this is working have our console open
move closer and then i hit space that indeed is still working but we want to make sure that we get
this going for our enemy as well so what we can do is we can copy this if statement paste it below
and now our rectangle 1 is going to be our enemy we want to text for our enemies attack box and
what will our actual player this is the case and our enemy is attacking then we know enemy dot is
attacking is equal to false eventually because we know we hit them but we should cause lock out
enemy attack successful so the last thing we need to do is determine what button we want to press
down in order to set enemy dot is attacking equal to true we're going to do that within our key down
event listener and say we're going to add in a new case let's just go ahead and say our down arrow is
when our enemy attacks so for arrow down i want to go ahead and select our enemy and say is attacking
is equal to true so now whenever we press down on the down arrow key our enemy is going to be
attacking so i save that and then i refresh moves off the side just a little bit and i move closer
towards our player as long as our attack box right here for our enemy is inside of our player
and i hit down you're going to see our enemy attack was indeed successful we're just getting
a bunch of console logs over here at the moment because we're constantly hanging out our event
keys we no longer need these console logs let's just go ahead and get rid of them in both key down
and also key up and refresh and do that one more time move over towards our player
hit down to attack enemy attack was successful and now since our player is also overlapping
their attack box on our enemy if i hit space we're consolidating that out as well we know that these
two methods are now working for attack so to finish this off we can go back up to our class
and we can uncomment this code where we actually draw out the rectangle for when we're attacking
save that and refresh now when i go closer towards our player you can see that our enemy attack box
is showing enemy attack was successful when i hit space for our player now we're consoling out to go
that means our player attack was successful so with that we can go ahead and check off attacks
next we're going to add in a health bar interface so what we're going to do is we're going to create
some html elements that look like this essentially this bar on the left is going to indicate our
player's health and this bar on the right is going to indicate our enemy's health we're
going to have a timer in the middle but it's most important that we just lay this out correctly so
that when we start hitting something like our enemy while their health decreases over time
so how would we recreate this effect that we have going on at the top here well to create
that interface we're actually going to want to head inside of index.html and we're going to start
laying this out like a real html document so i'm going to wrap our canvas tag and also our script
tag inside of a body tag so we know that these are our body elements and basically what we want
to do is we want to wrap our canvas tag in one large div this is going to be our container div
so this div that we just created is going to represent the full width and height of our canvas
all the way from up here to down here and we want to go ahead and place all of our elements inside
of this one large div because all these elements need to be relative to the div we just created
we don't want our elements relative to something like our browser window otherwise they might be
placed somewhere like down here outside of our canvas we want to make sure they're always placed
within our canvas width and height which is why we're wrapping everything in that one div now
within this div we also want to place one more div inside of it and this is going to take up the full
width of the parent div but it's also going to be the location in which we want to put our health
bar and the timer right here so we're going to add one more div inside of that div we just created
and this div right here is equivalent to this red rectangle that sends a full width that we
just created so what's within this one smaller red rectangle while we have one rectangle here we have
one rectangle here and we have one rectangle here so essentially we're going to be creating three
more rectangles inside of that div we just created so over here inside of this div we'll add three
more one two three this first one is going to be player health last one is going to be enemy health
and the third one is going to be the timer so to start styling these divs let's go ahead and add
a style attribute onto these and here we're just going to write inline styles to do this because
it is the easiest method so our styler right here is going to be equal to background dash color this
changes the background color of whatever div we're currently on we're going to assign this to yellow
to make sure that we get this yellowish color for the background this is what we're creating
by the way there's just this one rectangle right here with the red inside of it with our
background color equal to yellow we can go ahead and give this a height of something like 30 pixels
and if we give this a width of something like 100 pixels let's go ahead and see what this looks like
let's save go back over here and refresh you're going to see we just created the beginning of
our health bar perfect we're going to notice that the health bar right here is pushing our
canvas down but we don't want that we want that overlaid on top of our canvas what this means is
we need to select the main container div right here that's going to be the largest red rectangle
and we need to add a position of relative on top of that that's going to be the first requirement
you're going to see why i'm doing this soon enough so this is going to be the red container dip we
can even comment this out red container div to help us out in our code a little bit and within
this div we're going to add a style attribute and here we can go ahead and add a position
of relative onto that so if we were to save and refresh nothing's going to change by default but
we do need this in place to get the effect we're going for so now we're going to be able to get
this yellow health bar on top of our canvas how are we going to do that well what we can do is we
can select this child div inside of it this is the smaller red container div we want to go ahead and
select this add a style attribute on top of it and give this a position of absolute so if i save that
and refresh now by default this is on top of our canvas so whenever a child element like this has a
position absolute basically what that means is we want to take it out of the document flow when it's
taken out of document flow other elements such as our canvas element right here aren't going to
be affected by the width or height of that one individual element so we give it a position of
absolute and since it's container div the large red rectangle that's containing the whole canvas
has a position of relative basically what we're saying is this element with a position of absolute
should be relative to that main container div with the position of relative which it is now
because that container contains our entire canvas it's drawn in the top left-hand corner of where
that container div begins so perfect now before we make this the correct width let's go ahead
and draw our timer box in there it's going to be focusing in on this div right here right below
timer we're going to add in a style give this a background color let's just save red to start
we're going to give it a width of 100 pixels and then a height of 100 pixels as well
so we save that and refresh this is going to be the container div for our timer so
obviously this is placed beneath our health bar right here when it should be next to it
so how do we move these two discs next to each other rather than placing them on top of each
other well by default if we go ahead and look at these two elements right here within our inspector
we see we have our health bar div and we have our timer div if we look down below by default
divs have a display of block what does the display block mean well it means the elements are laid on
top of each other like blocks they're stacked on top of each other so by default the div is always
going to be stacked on top of another div but the thing is if we go ahead and add a display of flex
to the parent div then these disks are going to be placed next to each other by default rather than
stocked on top of each other a parent div with a display of flex affects all elements within that
parent div so we're going to go ahead and find our parent div for these two elements right here
that parent div is going to be this one with a position of absolute we're going to add a
semicolon to the end of the style and then add into this display style equal to flex so now that
this parent has a display of flex it's saying take all the children elements and place them
next to each other by default even if they have a display of block so we save that refresh over here
you'll see now these elements are next to each other perfect we're getting closer and closer
finally let's go ahead and add in our enemy health to do this i'm simply going to copy this div
and paste it right beneath enemy health saving refresh and we're getting closer and closer to
the style we're going for to match up with what we should have right here now this display flex
that we just added is pretty magical because there are a bunch of subclasses that work in tandem with
display flex so by hovering over this div you'll see that it doesn't take up the full width of our
canvas we definitely want to make sure that it takes up the full width simply because we
want our health bars to expand so we can see the exact amount of health either our player
or enemy has left so by selecting this element within our browser right here we can test this
out temporarily to see what this would look like with a width of 100 percent so as soon as i give
this a width of 100 we don't see any changes but if we hover over this you'll see now the div is
taking up the full width of the canvas that is perfect that is what we want to start because
if the parent has a width of 100 it's going to allow our children elements to grow based on our
needs so adding a width of 100 right here in the browser is just temporary if i'm going to refresh
you're going to see that width disappears so we do want that width on that element that we
just placed it on which is going to be the one with position absolute and display flex
we want the width of this to be 100 so we'll add that in right there save and refresh you'll see
that takes effect permanently and now we can begin affecting the actual widths of our health bars
so we don't want a static width of 100 for our health bars right now they're equal to 100 pixels
we just want to make sure that they take up the full remaining space of our actual canvas so right
here where we're using width of 100 pixels we're no longer going to define this as 100 pixels but
rather 100 percent we save that we refresh and now you'll see right here this player health is taking
up 100 percent of the remaining space the thing is we can eagle this out with our enemy health
by changing our width right here of 100 pixels to 100 as well save and refresh that and now
you'll see these are taking up an equal amount of space because both of them have a width of 100
and they're also inside of a div that has a display of flex now by adding that width of
100 you'll see that our timer div right here even though it has a width and a height of 100 pixels
well now it looks to be at 47 pixels wide rather than 100 so by default flex elements will shrink
based on their neighboring elements since their neighboring elements have a width of 100 and this
one has a static width this one element is trying to shrink to accommodate for all that other space
that is being taken up if you don't want a child element within a parent that has a display of flex
to shrink here's what you need to do you need to select the element you don't want to shrink
and then add in a style called flex shrink and you're going to set this equal to zero so if
you set this equal to zero zero basically means false it says do not shrink this and save that
and refresh you'll see now that it's correct size it's no longer shrinking simply because we set
flux shrink equal to zero so now let's go ahead and get our health bars in the middle
of our timer to represent more of what we have over here within our initial design so to get
those centered we're also going to be adding on an additional flex property this one is going
to go right next to display flex on the parent so the style is going to be called align dash
items so this style right here only works if the element has a display of flex if we were to get
rid of display flex right here align items would not work at all you need to make sure that it has
a neighboring display flex in order for this to work what is something that we could set align
items to well center basically what this says is we want to take all the items within this div
going to be these three divs right here and we want to align them vertically in the center
of this parent div right here so by adding a line item center we're going to center
all the children vertically let's go ahead and save that and refresh and you'll see
those children elements are centered vertically we're starting to look even closer to our design
over here so now it's important that we see what this looks like without the inspector open so
we're going to go ahead and hit the x right here you're going to see well that definitely looks
wrong so let's go ahead and fix this i'm going to go back to inspect element but i'm going to move
our inspector to the bottom now i can see exactly what this looks like and can figure out what is
going wrong so if i hover over this div right here you'll see it's taking up the full width of our
browser window if i go up one higher this is also taking up the full width of the browser window
we only want this taking up the full width of our canvas and the reason this is taking up the
full width of our browser window rather than the canvas inside of it is because a div by default
has a display of block a display block element takes up 100 of the parent div which in this
case is going to be body which is also the full width of our screen right now so we don't want
a display blocked to this div what we want to use instead is going to be display is equal to
inline block an inline block means that the element can still stack on top of other elements
but it's only going to take up the full width of whatever children are inside of it
so this child right here this div that contains our health bar has a position absolute it doesn't
actually affect the width or height of this parent div right here but this canvas element
has a display of block so it does affect the width and height of the parent element as a result when
we put a display of inline block on this parent element it's saying that it should only be the
full width and height of the canvas that's inside of it so that's all we have to do with
our code is find our parent div which is going to be right up here and then add in a display
of inline dash block so if i save that and refresh now you'll see this is within our
canvas even when i exit out of our inspector it's in the correct spot it's starting to represent
our health bar even more accurately now before we start subtracting from our health bars i think it
makes sense to add some padding around this just to give it a little bit of breathing room from
the edges of our game so we want to go ahead and add padding into our health bar while we'll grab
our small red container div and here we can add in a property of padding and here we're going to
set this equal to something like 20 pixels we set this equal to 20 pixels we're putting 20 pixels of
padding on every side of this one container so we want to go ahead and make sure we save that
go back over here and refresh now you'll see we have padding all around this but you'll notice
that adding the padding here is pushing our box outside of our canvas we just added around
40 pixels of padding onto the overall width of the container which means it's being pushed
out well something that we need to do in order to fix this is we need to add in a custom style that
says we don't want our overall width affected by our padding so to do this we're going to create a
head tag above our body tag and this is where all your site's metadata typically goes but inside of
here we're going to add in some style tags and now we can go ahead and begin writing some more
traditional css the css we want to write is going to start with an asterisk and then an opening and
closing curly bracket this asterisk means we want to go ahead and apply the following style
to every single element within our web page what style do we want to apply to everything
well it's going to be box dash sizing and we're going to set this equal to border dash box so
if i save this and refresh over here now you're going to see that this is aligned correctly why
well by adding that border box property padding is no longer going to be taken into effect
when calculating the width of elements you should pretty much always have this on every site you
create i don't know why it's not on browsers by default but you pretty much always want
that there to make sure that your padding isn't messing up the overall width of your elements
so that's all we have to do to make sure that we have padding in place to give our interface some
breathing room so we can begin subtracting health from both our player and our enemy so now whenever
our player hits our enemy let's go ahead and start subtracting from our enemies health bar up above
to start subtracting from this health bar we're going to want to go ahead and add an id onto it
so right here this is our enemy health we can add an id onto this div by declaring our id should
be equal to some sort of string what is a good identifier for our enemy health well other than
enemy health like so this is how we're going to reference it within our javascript
so now we can head over to index.js and start on scrolling down to where our enemy gets
hit so this right here is where our player is attacking this means our enemy is getting hit
instead of cause logging out to go we're going to go ahead and select our enemy health bar
we can go ahead and grab that health bar with document dot query selector and then we're going
to select the id we just created it's going to be indicated by pound sign that's how we select an id
and then the name of the id which is enemy health and here we want to select the style on
this specifically the width and now when our enemy gets hit we can set this equal to something like
20 percent and that should shrink the health bar down from 100 to 20 just to illustrate how this is
working so i save this and refresh move over and then hit our enemy you're going to see while the
width of this definitely shrunk down to 20 percent but it kind of just looks like our timer moved
over to the right because of this new change so we want to take this into account when styling these
health bars right now the positioning of our timer is dependent on the width of these health bars in
the background let's go ahead and refresh get that back to its original position what we're going to
need to do is add in a new div that is not part of this little mini layout we have going on here
this new div is going to have a position absolute and it's essentially going to cover
the full width and height of one of these health bars so since this new div is no longer part of
the layout when we change the width of this div with a position absolute well it's no longer
going to push everything around just this one div is going to be shrinking as a result so let's go
ahead and add in that position absolute div we're going to go back on over to index.html and to add
in a position absolute div right beneath enemy health we'll add in a new div give it a style
of position absolute like so we'll say the background here
is going to be equal to blue so since we're using a div with position absolute we want to go ahead
and wrap these two divs right here inside of a parent div to make sure this position absolute div
can be relative to the parent so for the parent we're going to add on a style of position relative
and then since this parent div is now going to be responsible for pushing elements around it's
going to be responsible for our layout we want to make sure that we declare for the parent div this
is where the width and the height should be 100 so i'm going to copy these two styles right here
well at least cut them out not copy and then i'm going to paste them in within the parent style tag
so if i save that and refresh we lose our health bar over here but that's totally okay that's
actually what we want in order to get this working correctly you'll see if i right click and hit
inspect and hover over that div we just created this is what it looks like which is perfect it
represents our health bar but if we look inside of our children elements right here well they don't
take up the full width and height of this parent div like we want them to so our current enemy
health criteria has a width of 442 that's great but it doesn't have any height associated with it
so if we want to go ahead and make sure this has a height associated with it we can just make it the
same height as the parent by adding in height 30 pixels and that should show this div again we save
that and refresh and indeed it is back but now when we select our enemy health down here that
has a background color of yellow this div right here if we begin affecting this width instead
set it to something equal to like 90 you're going to see that decreases over time so let's go ahead
and refresh our game and then we're going to attack our enemy we hit space you're going to
see that shrinks down to 20 immediately that is great but one thing is we don't know the full
extent of our health bar because we don't have any background dave right here saying well how much
health was there to begin with you'll see this a lot in traditional fighting games there should be
some sort of background div right here indicating how much health was there originally we actually
set this up by adding in the second div right here with position absolute and a background of blue
so we want to make sure that this div right here takes up the full width and height of this parent
div with a position of relative and to do this we can go ahead and say that the top style is equal
to zero that the right style is equal to zero that the bottom style is equal to zero and then finally
that the left style is also equal to zero so i save that and refresh well now we see our blue
element is overlaid on top of our yellow basically what top right bottom and left indicate are
how far from the parent div should this rectangle be placed so we're saying that the top of this
rectangle we're creating should be placed zero pixels from the top of the parent div zero pixels
from the right of the parent div zero pixels from the bottom of the parent div and zero pixels from
the left at the parent div and by doing that we're basically just saying for this position absolute
element take out the full width and height of the parent so if this element is going to be on top
this is actually what we want to subtract to show our player's health decreasing so what we're going
to do is we're going to move this id right here from this first div onto the second div which has
a background of blue we're going to paste that on in save and refresh and then when we hit our enemy
you're going to see the blue div decreases but the yellow stays in the background yellow is just
going to be the full indicator of how much health was there while the blue is going to be well how
much health do we have currently that's exactly what we want but we don't want to be decreasing
this so that this goes directly down to 20 percent we want to make sure that this decreases over time
based on how many times we hit our enemy so back within index.js we don't want to go down by 20
but rather by the enemy dot health so we're going to use a property called health we need to make
sure that we're adding that on to our sprite class up above so go ahead and say that this
dot health is going to be equal to 100 to start so our enemy and our player are going to have
100 hit points to start and then back down here whenever we hit our enemy we need to make sure
that we select our enemy.health and we subtract from it a value of something like let's just
say 20. so for each time we hit our enemy we're going to subtract 20 hit points from enemy.health
and we're going to set our health bar equal to that new percentage but if we want to set this
equal to percentage we need to make sure that we add on a string of percent and now when we save
and refresh that if we begin hitting our enemy you're going to see that decreases incrementally
over time so now let's go ahead and do the same thing so that when our enemy hits our player
the player health bar decreases as well we're going to go ahead and use the same methodology
that we used before for our enemy all we need to do here is simply copy our enemy health divs
all the way down here and we're going to go ahead and replace our player health
with those divs the only thing we really need to change is the id we're going to change this
to player health but this is going to set us up for success to use the same technique that
we just had prior so now that we have an id of player health right here we can go into index.js
and now we want to detect for collision when our enemy is attacking is going to be right here we
can simply copy this line of code and then paste it into when our enemy is attacking and say we
want to select not our enemy health but our player health instead and then set the width equal to not
the enemy health but our player health as they get hit so we do need to subtract our player health
each time our player gets hit so to do this we can copy this line right here paste it down below
and then say that each time our player gets hit we want to subtract our player health by 20.
and with just this let's go ahead and see what happens let's refresh
and we're going to take our enemy and hit our player you're going to see that decreases over
time though it is in the wrong direction we want to make sure that this decreases from the left to
the right rather than from the right to the left like we did for our enemy so to get this moving
towards the right instead of towards the left we're going to select the parent div right here
and set its display equal to flex once we do that we can say for all the children elements
we want them aligned to the right so that's what we're going to do to get this effect
is we're going to select that parent div over in index.html that's going to be this div right here
we're going to add in a style of display flex so i add that in save and refresh still looks the same
and if i go ahead and attack our player still the same functionality although our yellow health bar
is gone that's totally okay for now we just want to make sure that this is going in the correct
direction so we want to align this to the right over here since we have a display of flex on this
parent div we can add on a subflex property called justify dash content this only works if you have
an element with a display of flex so now we have this we can say that we want all children elements
to go to the very end of this container by adding in a property of flex dash end so once we say we
want all of our children elements aligned to the right all we need to do now is get rid of left
equal to zero because we don't want the left hand side of this div always touching the left hand
side of the parent div we want this to decrease over time so we're going to go ahead and get rid
of left and we want to set our width right here equal to 100 percent by default so if i save this
and refresh over here everything still looks the same but as soon as i hit our player we're
going to see that starts decreasing in the correct direction because the parent div has a display of
flex and its justify content is set to flex end but we are missing that background element now
all we should have to do here is add in a width 100 to the stiff with a background color of yellow
can save that and then hit our player a few more times you're going to see that stays in place that
looks great for our player when our player fights back that looks great for enemy so with that we're
going to be able to check off our health bar interface so let's take care of game timers and
game over functionality so basically in our game over here we're going to put a timer right in the
middle of this red box it's going to decrease over time and then eventually when it hits zero
depending on who has the lower amount of health we're going to go ahead and determine who won
and then display some text in the middle right here that says either player one or player two
one so to add that functionality the first thing we need to do is head inside of index.html and we
need to find where our timer is it's going to be right here as indicated by this timer comment and
inside of this div we can go ahead and insert a time so we're going to say our game is going to be
10 seconds long to start simply because we want to go ahead and test this pretty quickly relatively
quickly at least so with 10 seconds inside of here we'll save we'll go back to our game refresh there
is our timer let's go ahead and make sure that this is centered right in the middle of this red
square to center this we're going to go ahead and add a display of flex onto this div right
here and then we want to go ahead and use some of those properties we were using earlier including
align dash items this is going to be equal to center that means we're going to center
the text inside of this vertically we can save this and then refresh to see how that looks and
that is indeed centered vertically now we just need to center this horizontally so to center
this horizontally in the exact same location all we need to do is add a justify content style and
we're going to go ahead and say that we want to justify our content in the center this means
we're going to align our content in the center of our container on the x-axis so we can save that
go back to our game and now that is in the correct position so perfect so let's start getting this
timer counting down towards zero to do this we want to make sure that we can select this div
within javascript and to do that it makes sense to add an id onto this div this is going to be called
timer simple enough and now that we have an id on this we can head on over to index.js
we're going to create a function right above animate that is responsible for decreasing
this timer as time continues so this function is going to be called decrease timer whenever
we call this function we want to go ahead and decrease this number by one so to do this we need
to start with a variable we're going to create a let called timer let's set this equal to 10 that
is the time we currently have over here so now that we have timer equal to 10 each time we call
decreased timer timer is going to subtract one from itself but we should only be subtracting one
from itself as long as timer is greater than zero because we don't want to get into negative values
so right now what we're saying is if timer is greater than zero we're going to subtract one from
it but we want to make sure that this is occurring over and over again and to get this call multiple
times we can go ahead and call set timeout inside of this make sure you have a capital t for the
second t right here and then what function do we want to call we're going to call the same function
that's right here it's called decrease timer so basically we're creating an infinite loop
it's basically the same thing as we have down here within our animate loop with our quest animation
frame we're just living through this set timeout is going to be the same thing but we can go ahead
and determine what interval do we want set timeout to be called as the second argument so the second
argument right here is going to be in milliseconds so this basically just creates a loop right here
for our function and we can go ahead and test this out simply by calling decrease timer right beneath
it so we call this out save and then refresh we're not going to see anything actually because
right now this is only programmatic our timer is decreasing but we can't see it unless we can't log
it out we need to associate this with the label we actually have inside of our red square right here
so to get that association we'll also say if timer is greater than zero we're going to add some
brackets right here so we can write multiple lines of code we're going to subtract one from timer
and then we're going to go ahead and select our document get our query selector
and then what do we want to select well let's look within index.html
we just created an id of timer so let's go ahead and grab that with a pound sign and then we'll
select timer and we could say the enter html for this element so whatever is inside this
element right now is just a text 10 we want to go ahead and set this inner html equal to
the timer that we're currently subtracting so as long as we have this code right here
we save it and then refresh we're going to see that this decreases over time for every second
until we get down to zero and once we get down to zero we should see this stop and we should
not proceed into negative values which indeed we stop at zero we are good to go so looking back at
our code it really only makes sense to continue calling set timeout if timer is greater than zero
otherwise there's really no point so also i'm going to go ahead and add this inside of here
and then right beneath this if statement is where we're going to determine who won is it
going to be player 1 or player 2 that actually won the game it's going to be dependent on who
has the most amount of health so right beneath this if statement we can write an additional one
that says if our player health is equal to our enemy health then what happens while we know
we want to go ahead and say that there is a tie if they have the same amount of health when the game
ends based on the timer we're going to have a tied game but it doesn't really make sense to cons log
this out because someone playing our game is not going to have their developer tools open at least
they probably won't so we need to create some sort of label that we can change and display onto our
game so within index.html we need to find a good location to put some sort of display label and i
think a good place to put it is right above our canvas because i don't want this associated with
our health bar user interface i actually want this right here in its own separate container so i'm
going to create a div right above canvas and then inside of this i'm going to go ahead and write out
tie i just want to go ahead and see where that is so i save that and i refresh and it's going to be
placed up here by default but we can get this on top of our canvas by making this have a position
of absolute so let's go ahead and do that next all this div we're going to add on a style tag and say
the position here should be absolute and if we go ahead and make this absolute if we look at
this text it's currently black and our background is black for our canvas we need to make sure that
we have some contrast here by changing our text color equal to white so right after a position
i'm going to add in color and set this equal to white so i want to go ahead and save that
refresh over here and now tie is overlaid on top for canvas but we might want it centered directly
in the middle so we need to write a little bit extra code right here to do this what we're going
to do is we're going to add a display of flex on this element and can you tell me what comes next
well we want to use aligned items center to get this centered vertically and then justify content
center to get to centered horizontally so you might think if i save this and refresh it's going
to be run in center but unfortunately it is not let's go ahead and inspect this i'm going to go
ahead and right click hit inspect element and then i want to inspect our tie tag right here
so i look at this this div with a position absolute is not taking out the full width or
height of the canvas right now it's only taking up the amount of space of the text inside of it
which is just tie but our canvas is full width and height right here so we need to make sure
that this div takes out the full width and height of the canvas as well and in order to do that
since we have a position of absolute we can go ahead and add on the top right bottom and left
properties to say that we want the top left bottom and right of this one div to expand the full width
and height of the parent container so to do that we're going to say top is equal to zero right
is equal to zero bottom is equal to zero and then finally left is going to be equal to zero as well
so let's save that and refresh over here and now we're going to see that tie is directly in the
center because now our div starts from zero from the top zero from the right zero from the bottom
and zero from the left of our actual canvas this is looking to be in a great spot right now
so we don't want this showed by default you'll see right here when i'm refreshing we see the text
tie let's go ahead and hide this i'm going to give this a display of none and if we give this
a display of none we need to make sure that we delete display flex right here because we don't
want to show this at all right now we'll keep everything else but as long as this has a display
of none we're going to see that's hidden and that doesn't get in the way of anything so the next
thing we want to do is head over to index.js and when our playerhealth is equal to our enemyhealth
when our timer runs out then we want to go ahead and select that text to select that text we're
going to use document.queryselector and then we need some sort of id to select that one div
so within index.html we need to add an id right here we can go ahead and call this id display
text this is what we want to go ahead and change back within index.js
so we can select this width a pound sign get display text and we want to change the inner html
equal to tie not only do we want to set this equal to tie but we also want to select it again so i'll
go ahead and copy this line right here and set its style specifically its display property back equal
to flex so we're no longer hiding it when this is true we're going to set it equal to flex it should
indeed display when the time runs out so to make this a bit quicker let's go ahead and decrease our
timer to five save our code and then refresh over here we're decreasing downwards and it looks like
we're already showing tie right here that's not exactly what we want we need to make sure this
if statement only fires if timer is less than zero so technically what we need to do we need to make
sure that this text right here only shows if timer is actually equal to zero not for each iteration
of decreased timer so we can go ahead and wrap all this in an if statement that says if timer
is actually equal to zero then we want to call the following code so we save that and let's go ahead
and test this i'm actually going to go ahead and hit the enemy right here you'll see that decreases
and now we're no longer showing that text because the health bars are no longer equal
this conditional right here is just not true so we're not going to fire these two lines of code so
now we need to take into account what happens if a player's health is greater than the enemy's health
we can write an else if right after this that says if our player health is greater than our enemy dot
health well we want to show some different text we're going to select these two lines right here
and paste them in below and instead of saying that our inner html should be equal to tie we're
going to say player one wins now this code right here is duplicative of the code above when we're
setting style display equal to flex if we see some duplicate code like this what we can do is we
can simply take it out of the location where it's being used i'm going to cut it out right here and
paste it in a location where it's only going to be called once so when timer is equal to zero i know
i want to show our display text but then based on whether our player health is equal to enemy health
or greater or less than that is when we're going to change what text is actually inside of this div
so we can also delete that other query selector with style display equal flex right here and now
we saved ourselves two lines of code made it equal to one instead so let's test out what happens when
player 1 wins we'll save this refresh and now we need to hit our enemy and enemies health decreases
and now we're displaying the text player 1 wins simply because player 1 has more health
than our enemy now we want to do the same thing for when our enemy wins so we'll simply add in
another elsa statement right here and say when our enemy help is greater than our player health
right here and that is when player 2 wins instead so save and refresh and then i'll hit our player
with our enemy now our enemy is going to win now player 2 wins so great that is perfect so we're
looking to be in good shape with the timer but what happens if our enemy or our player
decreases one of the others health down to zero before the timer runs out we need to
write some code for that to tell what happens so we're going to go ahead and increase our timer
to something more standard like 60 seconds that way this doesn't actually call before we're ready
so we refresh with that and you'll see this starts decreasing and now we have 60 seconds in order
to end our game based on health rather than time running out so when we go ahead and get our enemy
down to zero then we want to go ahead and display that same text that we were showing earlier for
when our timer ran out so to monitor for that we're going to go inside of our animation loop and
this is going to go beneath where we're detecting for a collision for both our player and our enemy
because we know these are two places in which we are decreasing our enemy and our players health
so beneath this second if statement we're going to go ahead and end the game based on health and we
want to say if our enemy dot health is less than or equal to zero or our player dot held is less
than or equal to zero then we know our game should be over and we should show some certain display
text right here so to determine what text we should display basically what we can do is we can
go ahead and change this conditional into its own function and then call that function down below
so let's go ahead and refactor this a little bit we're going to add a new function above decrease
timer that says determine winner this is going to take well one argument it's going to be an object
with two properties inside of it what are the two properties well it's going to be your player
and also our enemy and now that we have these two in place we can go ahead and call this code right
here so i'm going to cut it out of this location simply paste it in determine winner and now we can
go ahead and use determine winner in that exact location where we just cut that code out so right
here we're going to call determine winner we know this takes one argument it's going to be an object
with a player and an enemy property so i'm going to add player right here an enemy right here and
now based on whether or not our player health is equal to our enemy health we're going to show tie
or player 1 or player 2 wins it's just a nice little abstraction to make our life a little
easier when we want to do the exact same thing down below within our animation loop so if enemy
health is less than zero or player health is less than zero then we know that we should be calling
determine winner right here this also takes an argument it's going to be an object with a player
and an enemy and based on all this we're going to go ahead and display that text that we were
showing prior with our timer now before we actually go ahead and save and refresh let's
go back up to determine winner and we just want to make sure that we also put this code inside
of it right here that sets our style display equal to flex otherwise it's not going to show
so within determine winner we're going to go ahead paste that in and now when we save and
refresh over here and we'd be up on player two eventually when we get them down to zero you're
going to see now player one wins we display the correct text so same deal let's go ahead and beat
up player one now get them down to zero now we know player two wins before the timer runs out
we still have our timer functionality in place although i suppose when either player one or
player two wins we need to make sure that we stop this timer all together so let's do that next
so to stop a timer we need to get the timer id that's returned from set time out so we're going
to create a lut right beneath timer called timer id and we don't actually need to assign this to
anything by default but when we're calling set time out we're going to go ahead and say timer
id is equal to the return value of set timeout so for each time we call set timeout this is
going to return a number it's going to be either 0 1 2 3. it's just going to keep increasing over
time that's going to be the timer id and since we associate that with this let of timer id we
can use this to cancel our loop altogether to make sure that we're no longer calling decreased timer
so within determine winner we're going to add in an additional argument it's going to be timer id
and then as the very first thing right here we're going to call a function called cancel time out
and it's going to take that timer id that we passed through so we just make sure we're passing
this through within determine winner right here we're going to pass through timer id and that's
going to prevent this from being called when our timer runs out but we need to do the same thing
down below within our animation loop so when we go ahead and determine a winner right here we're also
going to pass through the timer id so we'll go ahead and save and then refresh over here and then
be up on player two get them down to zero and it doesn't look like it's stopping so let's go ahead
and whenever this happens you always want to go ahead and right click inspect element and then see
what's happening in the console looks like cancel timeout is not defined it's a dumb error on my
part let's go ahead and find where we're calling counts timeout it's going to be within determine
winner it's not actually cancelled timeout i don't know why this first thing that comes to mind for
me but it's actually going to be clear timeout instead just a little bit of a syntax difference
so we save that we try again over here get out of the console and then be up on player two one more
time you're going to see that stops completely because we called clear timeout correctly we also
show player 1 wins which is great we can test the exact same thing for player 2 when they win
we're going to see that stops completely and we're still displaying the correct
text so perfect and i think with that we can go on over to to do and check off game timers and game
overs we just created the basic functionality that we needed to get a basic fighting game
set up so now we're going to go ahead and move on to sprites and animation so we're going to
be inserting images into our screen and also animations for our characters our background
and a little bit of our ui so we're going to go ahead and start off with our background sprite
what is a background sprite well it's going to be simply an image we put in the background like this
although this is not what our game currently looks like it really looks like this with just a black
background so we want to go ahead and get that image into our game how would we go about getting
this image in the first place well over on itch.io this is a website specifically for game assets
and a lot of these assets are free provided to us by really talented authors such as brew love
right here i went over to itch.io and i went into the oak woods environment asset pack so this is
completely free to use on personal and commercial projects if you want to go ahead and download this
yourself you can go ahead and hit download now and i really recommend leaving a donation for
the author because they definitely put a lot of effort into creating this artwork but if you just
want to download this for free you can click this right here it's going to lead you to the downloads
you just click download and it's going to go ahead and initiate your download so i already downloaded
this and all the assets i want to use in our game actually moved into a folder within finder
it's going to be called fighting game assets so you see we have a folder for a character named
kenji a folder for a character named samurai mac and then a background and then a shop so this is
going to be available to you within the google drive link within the description of the video
but the main thing we want to focus on right now is going to be background.png
so you'll see i took this image from the asset pack and i resized it down to 1024x576 so it's
going to go ahead and fit our screen perfectly it's going to cover up the whole black background
if we want to go ahead and use this in our game what we're going to do is we're going to simply
select all the assets within this folder i'm going to select shop hold shift and then i'm
going to click on kenji to make sure that i select everything and then i'm going to hit command c to
copy these it's going to be ctrl c if you're a windows user but once you have these copied
you can head back to your web directory or wherever you store this project
i'm going to go inside of fighting game and then inside of here i'm going to create a new folder
called img for images and then i'm going to paste that in by hitting command v control v if you're
a windows user so that's going to go ahead and paste these within our project and then if we look
at sublime text you're going to see that we have an image folder with all those images available
to us that we can now use within our code so we want to go ahead and make use of background.png
right here how would we go about inserting that into our game well i made the sprite class for a
reason i want to use this class not just for our fighters but also for our background images our
shop image whatever it may be but at the same time this class currently has a lot of functionality
related to a fighter rather than just rendering out a simple image onto our canvas as a result
it kind of makes sense to refactor this class into a separate clause we're going to keep this as is
called sprite but we're also going to create a class called fighter which is going to resemble
our player and player 2. so what we want to do here is is basically duplicate our class all the
way down to the very bottom i'm going to copy that and paste and then i'm going to call this class
fighter so this is actually going to be the class that we use for player one and player two
but this class up here of just sprite we're going to go ahead and refactor this so this
is just responsible for rendering out an image so we go ahead and look at this class of sprite what
do we need and what do we not need well we know a sprite is not going to have any attack method
associated with it so we can go ahead and delete that within update well what does a sprite need to
do over time well it's going to need to update its frames if we want to add in some sort of animation
but a lot of this is related to our player's attack and gravity we don't want any of that
we just want to go ahead and make sure that we're drawing this and we're going to be using update a
little later on to update the variables associated with each of our sprites if we scroll on up we
have draw right here now what does a sprite look like well they're not going to be rectangles
because we're actually drawing out images onto our screen we don't need anything related to drawing
out rectangles we're just going to delete all this we're going to go ahead and edit
this within this individual lesson and then if i scroll on up what else do we not need for a sprite
we can get rid of health because sprites are not going to have health that's going to be related
to our fighter his attacking is also related to fighting we don't need a color because we're going
to be using images we do not need an attack box we can get rid of that we don't need a last key
but we do need a width and a height associated with our image at least later on so we're going to
leave this right now and we don't need a velocity either because these aren't going to be moving
around the screen at least not yet that's mostly going to be just our fighter down here so with all
this in place what do we need to get rid of within our constructor argument we get rid of velocity
color and also offset so we just have a very basic sprite class at the moment so we added
this class in and now we have a class of fighter and it's kind of muddying up our code a bit within
index.js we have our design in here but we also have code related to our game implementation
so it kind of makes sense at this point if you're having trouble finding certain things within your
file to refactor this into a separate file and that's exactly what we're going to do
for code maintenance purposes so what i want to do is i want to go ahead and make sure that our
classes are in their own separate class file in order to do this i'm going to go to file
new file and then i'm just going to hit command s to immediately save this
and then i want to save this as classes.js but i'm not going to save this within our root
i'm actually going to go ahead and create a folder called js all of our new js files are going to go
inside of here so i'm going to save that and now we have a folder of js with classes.js inside of
it so great now we can go ahead and select our classes go with class of sprite all the way down
to class fighter i'm going to cut these out with command x and then over in classes.js i'm going
to paste that in with command v i can hit save save on index.js as well but this isn't going to
work if we save and refresh everything because we need to make sure we're pulling in classes.js into
index.html in order for that file to be read so we want to make sure that we pull this in before
index.js and we want to reference classes.js so in order to do this we need to go inside over js
folder and then reference classes.js so now our classes within this file right here are going to
be available to us within index.js so we save this we want to go back to index.js and here you'll see
that we're currently creating our player and our enemy from our sprite class we know we created
within classes.js a new fighter class that's what we want to reference for our player and our
enemies so here we're going to change new sprite to new fighter for both our player and our enemy
if we save everything index.js index.html and classes.js accordingly if everything went well and
we refresh over here well we have our player and our enemy in place and everything still functions
as expected so great so now that this is cleaned up a bit it definitely makes it a little easier
to focus on what we need to focus on so within classes.js we want to focus in on this class of
sprite so sprite like i said is just going to be an image and it can be animated over time
but we're going to do the most basic one which is just going to be a static image to start
so in order to render an image on the screen what we're going to do is whenever we create
a new sprite we're going to pass through an image source so src and we're going to use this image
source to create a new image whenever we create a new instance of sprite so we're going to create
an image property called this.image and to create an image within javascript we can use a native api
object called new image so this basically creates an html image but within a javascript
property such as this dot image and once we have this available to us well we need to set
this dot image dot source equal to the source of the image we want to actually show so it's
going to go ahead and store the image within the property of this dot image but if we want
to go ahead and draw this out we need to use a canvas function within our draw method right here
so the canvas function we're going to use is going to be c dot draw image like so so the first
argument here is going to be an html image element and that's already created for us right up above
with new image stored in this dot image so that's going to go right here as the first argument
this dot image and then for our second argument we want to go ahead and add in an x coordinate
thankfully we set this up already when we're creating our fighter class and duplicating this
so we can get the x coordinate with this dot position dot x and then we need a y coordinate
which we get with this dot position dot y this is all we need to do to create an image and draw
out on the screen using canvas so we save that now within index.js we need to do the actual
implementation for this class so we can either do this above our players beneath our players doesn't
really matter i'm going to do it above them i'm going to create a new const called background i'm
going to set the sequel to a new sprite so this is going to take one argument with a few properties
inside of it what properties does this take well it's going to take a position so we'll put in
position for a property position is going to be equal to an object with an x and a y property so
what is the x coordinate of this background well i want to start at the very top left hand corner of
our screen so that's going to be 0 for x and also 0 for y now what else does a sprite class take
well we can always look within classes.js we see it takes a position and it takes an image source
so now we just need to add in an image source attribute and this is just going to reference
the file location in which we want to put on the screen so it's going to be a string and
from index.js how do we get background.png right here well we need to go inside of img and this
dot slash right here just means we're starting within the directory of index.js so we go from
this directory we go inside of image and then we need to reference background.png so background.png
so we want to make sure we save that and now we have a background sprite in which we should be
able to render out on the screen with either draw or update update right now does the same exact
thing as draw but that's okay because we're going to be using update later on so within index.js we
can scroll down to our animation loop right about here and we're going to put this as the very first
thing before playerupdate and before enemy update because we want this drawn in the background
not on top of them we're going to reference our background and then we're going to call
update on top of it which in return is going to call draw and the draw image method
so we save that go back over here and refresh you're going to see now we have a background in
place so great that is how you want to render out a sprite or at least a static sprite onto
your screen so there's no better time than now to continue refactoring our code and make it as clean
as possible how would i continue to refactor this while scrolling down i noticed that there was a
lot of code in between that wasn't really related to the actual implementation of our game but
more so just making our code cleaner specifically these functions right here such as decreased timer
determine winner rectangular collision those are more utility functions rather than stuff that's
actually directly related to our game as a result i think it makes sense to put these in their own
separate files so i'm going to grab all these functions and their associated luts and const
and then i'm going to save it i'm going to keep decreased timer in here because that is part of
implementation it helps make our game actually function but once i cut those functions out
i want to go ahead and create a new file so i'm going to go to file new file and i'm going to
paste these on in so once i paste these in i can hit command s and then i'm going to save these
inside of our js folder and i'm going to call this utils.js for utilities so i'm going to save that
and once i save this i just need to make sure that i put it within index.html so that all these
functions that we created are still available to us and we know that this should come after js
classes.js but before index.js because they're really only used within index.js in the first
place not so much within classes and i'm actually going to go ahead and put this before both
of these because even though utils.js only has functions that is used within index.js right now
maybe we'll use these later on for classes.js but even though it's not required at the moment
we're kind of just preparing for the future right here so we just want to make sure that we save all
these files and then refresh everything still works and functions the same so great but our
code is a lot cleaner within index.js for sure so we have our background sprite in place but
what else what do we want to do here well it looks like our background right here has a ground for us
and our player and our enemy are currently at the bottom of our canvas let's go ahead and make him
stand on this actual ground how would we go ahead and do that well we're going to go ahead and fake
it essentially we're just going to say that we want our player and our enemy to fall as long
as they are above 200 pixels from the bottom of our canvas rather than the
bottom of the canvas directly so we want to go into classes.js specifically our fighter class
because we know within here within update this is where our fighters are affected by gravity
we are saying we want our fighters to continue falling as long as their position plus velocity
are greater than our canvas height right here so this right here is determining when should
our fighter stop moving when should they hit the ground it's going to be this value right
here that determines that so we're saying right now they should hit the ground when they reach a
value of canvas height which is right here at the very bottom but what if we go ahead and subtract
something like 200 from our canvas height maybe we can go ahead and get them to stop right about
here so we go ahead and do that from this location within classes.js we save canvas.height minus 200
and refresh over here you're going to see that it's 200 pixels from the bottom of our canvas
so obviously that's way too high up let's go ahead and decrease that do something like 100
we're just going to eye this until we get this perfect and that is definitely a lot
closer but if you look really closely you can see there's still a little bit of space right
there so we can go ahead and get rid of that by subtracting a smaller value like something like 97
we'll save that and refresh and i think that is directly touching the floor maybe one more pixel
96 and yeah i think that looks pretty good we're definitely on the ground right there it looks like
we're actually traveling across this background we created which is really freaking cool in my
opinion so that's going to go ahead and allow us to check off background sprite now we can go ahead
and do the shop sprite with animation so what does this mean well if we look within our finder
specifically within our image folder you're going to see that we have a shop.png and this is what it
looks like if i go ahead and bring this up you're going to see that it contains multiple instances
of basically the same image the only difference is going to be if you look at the smoke stacks
you're going to notice that it's different for each frame that we go through and if we go ahead
and loop through these frames continuously it's going to give off the effect of animation that's
kind of how video in general works actually as we just go through a bunch of frames and
as we overlap these frames on top of each other we create some sort of movement effect
so we're going to use this shop to create an animation and we're going to place this shop
right here with this empty area i used the asset pack to create this background and i
left this open space specifically so we could put the shop right here and create some sort
of cool background animation so the first thing we're going to want to do is simply place the
shop right here and we're going to show all frames of the image and then we're going to
go ahead and animate it from there so let's go ahead and get our shop placed right about here
so to get our shop.png rendered out into our game we can go inside index.js and we want to
find where we created our background essentially we're just going to create a new sprite and what
we can do is we can simply copy this constant background with new sprite paste it down below
say this is going to be our shop sequel to a new sprite we're going to start it off at a position
of zero zero let's just do that to star to get it rendered on the screen and then our
image source is going to be image shop.png so now that we have this created we want to go on down
and where do we want to render this in relation to everything else well it makes sense to render this
after our background but before our player and our enemies we're just rendering these out in layers
on top of each other so we're going to reference shop dot update save that and then we can go back
to our game and refresh you're going to notice this is where our shop is on screen so now we need
to do two things the shop is pretty small at the moment so what we want to do is scale it up so it
fits in this large area right here and once it's scaled up we just want to make sure that we place
it in the exact location so how do we go ahead and scale this image up well we need to focus on
our sprite class within classes.js so if we go ahead and add some arguments on a c dot draw image
we're going to add a fourth argument right here this is going to be the width of the image
so if i go ahead and make this something like 300 i'm going to add in a fifth argument this is going
to be the height of image i'm going to make this something like let's just say 200. if i'm going
to save this right here and refresh you're going to notice both our background image and our shop
right here change to that exact dimension so we don't want to add a static value within our sprite
class because we know our background is not going to have the same dimensions as our shop we want
to make sure that these right here are determined by the image we're actually pulling in using image
source and this html image object so to do that instead of referencing 300 right here we're going
to reference this dot image dot width someone off right and then for our height we're going
to reference this.image dot height so let's go ahead and save this and refresh and you'll see
that takes care of things in regards to the width but now that we have this width and height listed
out right here for c.draw image we can go ahead and multiply this by some value to scale it up so
within our sprite class we're going to add a new property called this dot scale and this is going
to vary based on the sprite that we're currently using so we want to make sure that we're passing
this through as a constructor so within our constructor arguments i'm going to add in scale
and say by default this should always be equal to one but we have the chance to change this later
on if we want to so now that we have this that scale in place we want to go ahead and multiply
this.image.width by this dot scale to scale up an image same thing with height just multiply it by
that scale so this isn't going to do anything by default if we refresh everything looks the same
but it gives us the ability to increase this number right here to something like two
and it's going to increase the sizes of our images as you can see but we only want to increase the
size of our shop so we want to make sure scale is always by default one and then within index.js we
can find where we created our shop which is going to be right here we can say that our
shop is going to have a separate scale from our background by assigning a scale property
equal to something like 1.5 let's go and see what that looks like let's save that and refresh it
now you see our shop is a little bigger maybe we can make this even larger let's go into up to 2
for our shop save that and then refresh and you'll see that looks pretty good but i think
we can make it even bigger let's go on up to 2.75 save that and refresh so you see this definitely
loses some clarity but i think for our game it's okay because it definitely has a pixel art style
showing some pixelation is definitely okay at least in my case so we're going to go ahead and
say this is going to be the size of our shop now we want to make sure that one frame of the shop
fits right over here so we're going to go back to our shop or at least where we're creating it
and where do we want to position this well let's just start guessing we're going to put
in 300 for x save and refresh moving a little closer maybe we want to double that up to 600
save and refresh that seems to be in a pretty good spot i'm going to go ahead and keep that
for now let's go ahead and focus on the y-axis let's put 300 for y so 300 pixels from the top
that seems to be way too much obviously so we're going to go to 100 getting a little closer
let's go ahead and add 20 to 100 so 120 and now let's start adding smaller numbers such as five
it looks like we just need like two three more pixels so i'm going to put 128 right there
and that seems to be in a pretty good spot for our shop so now that this is relatively within the
right place we want to begin animating this and animating sprites can be a little tricky at first
but once you get the basic concepts it's going to be a cinch so basically to get this animated what
we're going to do is we have our whole image rendered out currently and that's totally okay
we're going to keep this rendered out but we're going to do is we're going to crop this so that
we only show one frame at a time so when we crop this we're only showing this first image and then
what we're going to do is over time we're going to animate this so our crop location starts moving
through these images so we're going to say shift this over one frame to the right and then render
out this version then eventually we're going to shift it over to another one and then another one
and then another until we get to the very end and we're going to shift back to the beginning
and over time as we do this we're going to create the illusion as if the shop is actually animating
and any other sprites that we might use within our game but that's basically the gist of it we
want to go ahead and crop this whole image down to this little square right here and then we're
going to go ahead and push this crop through the whole thing to create the illusion of animation
so to create this crop we're going to go over to our sprite class we're going to focus in on
c.draw image so we want to go ahead and crop this while we need to change up the arguments a little
bit it's a little confusing with canvas unfortunately but it's nothing we can't
deal with so the crop location is actually going to be these first four arguments and
these four arguments that are here currently are going to be pushed down by four arguments
so these still remain the same this is going to be the x and y position of our image and also the
width and height of the overall image but if we want to go ahead and crop this we need to add in
four more arguments before these i don't know why canvas does it this way but it does so the second
argument now is going to be the crop location so where do we want this crop mark to start
we want it to start at zero zero from our image because that's going to be right about here and
then we're going to determine its width and height to only cover just one of these shop images so x
is going to be zero y is going to be zero it's going to start our crop mark at the top left-hand
corner what is our width going to be well we can base this off of this.image.width we want to go
ahead and grab this paste it in right here we know that our crop height should be this image
dot height well make sure we add a comma to the end of that but this is what our crop code
is going to look like now when we're cropping our image by its image width and image height the full
width of our image right now is this entire thing so we don't want to crop it by the entire thing we
only want to crop it by this small section right here so if we get the entire image width which is
going to be from here to here and we divide it by the amount of frames within the image so 1 2 3 4
5 6 we're going to get the exact width of just one of these frames so let's go ahead and do that over
in sublime text we're going to divide our image width by 6 specifically for our shop save that
and refresh and that's going to initiate the crop but you'll see everything is just completely
stretched out that is obviously not what we want why is it being stretched out well if we look
back at our code over here this line right here is going to determine the actual width of our image
so we're grabbing this by getting this.image.width we're saying the full width of our image should
still be the size of this even though we just cropped it down so we want to make sure that
this is also dependent on the amount of frames within the actual image so i'm going to divide
this by six as well i'm gonna make sure that we do this first before multiplying it by scale
and if we save that and refresh you're going to see now our shop looks pretty perfect that is
cropped perfectly so you want to go ahead and crop an image you need to make sure that you set the
crop location the crop width and the crop height this is also going to be dependent on the amount
of frames within the actual image and then down here you want to say well what width and height
should the image actually be well it's going to be the image width divided by the amount of frames
times the scale so that's how you're going to do it but you're going to notice that affects
our background image as well now our background image is 1 6 the size of its full width so if we
want these two to work nicely together what we need to do is edit this so the six right
here the amount of frames within our image is variable rather than just always being six
so what i'm going to do is i'm going to create a new property for our sprites this is going to be
called frames max so what is the max amount of frames that we have within our image and this
is going to be variable so we want to make sure that we pass it through as a constructor argument
so right here i'm going to say frames max can be passed through and by default this
is going to be equal to one which just means we have one image such as our background image
for this sprite so this stop frame's max is going to be equal to frames max and now when we go ahead
and divide by six instead we're going to divide this by this dot frames max in both locations
so we want to go ahead and save that and on refresh you're going to see our background
image is back to normal but our shop is not how annoying but this is really easy to fix now
because we set this up correctly now we can pass through a new frames max specifically for our shop
so over in index.js we want to find our shop we're going to set the frames max equal to well what are
the max amount of frames within our shop we said it was six so we save that and refresh
now everything is laid out correctly we're setting ourselves up for success when we want to go ahead
and animate the shop so if we go ahead and compare this to our actual spreadsheet within finder
we are currently at this position right here we took our large image showing the entire thing
and we sized it all the way down to this location this is the step we're currently at the next step
is going to be actually moving the square through our entire sprite sheet so to do this we want to
go back to closets.js and basically what we want to do is we want to move the x-coordinate of our
crop mark so this is our x-coordinate if i were to go ahead and change this to something like 200
and refresh you're going to see we basically moved that crop mark over to the right but we want to go
ahead and move this perfectly to give off the illusion as if the shop is actually animating
rather than just shifting it to side slowly so how many pixels would we have to move this crop
mark over by in order to get it to exact location right here we can do a little bit of math within
our code to get this exact result so we're going to go ahead and get this dot image dot width
and if we divide that by our frames max well we're going to get the exact amount of width we need
to move over by so we'll divide this by this dot frames max and if we save this and refresh you're
going to see that our shop looks the same but i promise you the smoke stack is a little different
we just move the crop over by one frame and it's in the perfect location to where we're
only showing one part of the image once again our background image is gone we need to take that into
account based on this new code we added in for a crop mark so the reason our background isn't
showing right now is because our background image has a width of 10 24. and if we divide that by one
well that's going to be equal to 10 24. so we're saying we want to move our whole crop mark for our
background image to the right by 10 24 pixels obviously there's nothing there for our first
image because well there's only one specific frame for that background image so all we need
to do here to make sure that this works for both our background image and our actual shop
is we need to multiply this by a current frame so i'm going to add in here this
dot frame current and i want to make sure that these two equations over here
are performed before we go ahead and multiply that by frame current and then we need to actually
create frame current up above so here i'll say this that frames current is equal to zero so i
just wanna make sure i actually call this frame current sorry about that so this is going to be
equal to zero which means now by default we're multiplying this equation over here by zero so
we're no longer moving that crop mark over for a background image let's save and refresh background
image is back this is back to its original location as well but we're still continuing
to set ourselves up for success we're making a completely reusable sprite class for the future so
now over time if we increase this value right here from zero to something like one and we use that on
our shop class well we're effectively moving over our crop mark by one frame if we increase this by
two we're going to be moving it over by two frames and we can keep going until we hit the frame's max
and that's when we're going to go back to the very beginning and reshow this animation but if we're
never increasing frames current in the first place well the image is going to be static which is for
images like our background image so if we go ahead and focus in on our shop we'll just say by default
each frame is equal to 200 pixels and that is the result of this right about here that's going to
be equal to 200 but if we multiply that by frames current and the default is zero we're going to get
zero so there is no crop but if we go ahead and change the zero right here
to one instead well now we're going to move that crop location over by 200 so we're just going to
keep moving that until frames dot current is equal to frame's max which is going to be six or five i
can't remember which but once it hits that we're going to go back to zero and repeat the process
so that our crop mark moves well back to zero so to get this effect we wanna make sure that we're
increasing frames current over time which we're going to do within update so after we call draw
we're going to add onto this dot frames current one frame but we only want to do this as long as
frames current is less than frames max so here we'll write if this dot frames current is less
than this dot frames max then we want to go ahead and call the following but we want to add in an
else statement here that says if this is not true what do we want to do we want to set this that
frame's current so the current frame back to zero and that's going to repeat the animation process
so let's kind of save this and then refresh and you're going to see well we definitely have some
sort of crazy animation going on here so one issue is is our background is animating for
some reason it seems to be flickering between the background image in black why is that happening
well frame's current starts at zero so we can actually render out our background image and
set our crop x position equal to zero but right now our frame's max for our image is one because
we still want to make sure that we're showing that background image in the first place so when we go
ahead and run this if statement down here frame's current is equal to zero and then frames to max is
equal to one therefore this is still true for our background image which means we're adding one onto
our frame's current therefore we're pushing that crop mark off of our background image so we're
showing black and then we're going back to the background image which is creating that flicker
effect so to fix this we just make sure that we're subtracting one from frames max over here save and
refresh that fixes background image and now we have our animation in place for the shop although
it is really really fast we want to make sure that we slow this down to create something that looks
a little more realistic and a little less jank so how are we going to slow this animation down
well to do this we're going to go ahead and add in two more properties they're going to be this
dot frames dot elapsed and then this dot frames hold so this stuff frames the lapse is going to
be how many frames have we currently elapsed over throughout our whole animation this is just going
to increase over time as our game continues to run and then our frames hold is for how many frames
should we actually go through before we change frames current the actual animation so by default
this is equal to 1 with our current animation because we're just looping through every frame
but if we set this to something like 10 what we're saying is for every 10th frame we're going to loop
through this animation rather than for every one frame so how do we go about using this right here
well we know frames elapsed should be increasing over time so within this dot update we're going
to add in this dot frames elapsed is going to have one added on to it for every iteration of update
and now that that has a value being added onto it at all times we'd say if this dot frames elapsed
modulo this dot frames hold is equal to zero then we want to go ahead and call
the following if statement so what does this mean right here well basically what this means is take
frames elapsed divide it by frame's hold and if the remainder is zero then we want to call the
following code that's the difference between the modulo operator and the division operator like so
but we just want to make sure we get the remainder so we're going to go ahead and use the
modulo operator so we go ahead and save this and refresh you're going to see just by adding that
in our animation is way slowed down and this looks way more realistic in regards to a shop animation
and you can always change the speed of this by changing your frame's hold value right here the
lower it is the faster it's going to go so if i change frames hold to five second refresh you
can see that looks even better than before but if you want to make this super slow you just increase
this number it can be 50. now for every 50th frame this is gonna go but i think it looked good at
five so i'm going to go ahead and keep it at that now later on we are going to have different frame
holds for different sprites so we're going to change this and add it into a constructor
at some point but we don't need it right now so we'll leave it as is and we'll head back to to do
and we'll check off shop sprite with animation so now we're going to go ahead and add in a sprite
for our player specifically one named samurai mac so we're going to start with the idle animation
for this and this just means we're going to be standing but moving up and down to show that
our character has some movement so where did i get these sprites well over on itch.io i search
for some fighter sprites and this is what i was able to find was marshall hero by lewis mello
he supplied this sprite and the other spray i'm going to use in this tutorial for completely free
but if you want to go ahead and donate to him make sure you click download now and then send him a
donation so if you want to go ahead and get the sprites for this you can either download it here
or it's going to be within a google drive link you'll see that we already pulled that into our
project within the samurai mac folder so we have a bunch of different sprites associated with
animations related to our player right here we have attack sprites we have a death sprite a false
sprite an idol sprite jump sprite run sprite take hit sprite and so forth you kind of get the idea
these are all the animations associated with the movement of our character
so the one we want to focus on is idle and if we look really closely right here
you'll see this is what an idle animation looks like we're kind of just bobbing up
and down it's actually kind of hard to see but you'll see once we actually get this animating
that our player is going to be bobbing up and down so let's go ahead and get this into our game
so we know we already pulled samurai mac into our image folder earlier on and now we have a couple
of animations in which we can use so to begin using this we want to go ahead and extend our
sprite class because right now our fighter class does not use any images we need to make sure that
the fighter class is able to use the same code that we have up above for our sprite but the
fighter class is going to be a little different which is why we have it in the first place
so we can go ahead and call things like attack and different update functions so we want to go ahead
and make sure that our fighter clause can use the draw method associated with our sprite class
we just go ahead and extend the fighter class by adding extends right here and then declare we are
extending the sprite class so by extending this we're going to take all the methods within sprite
and put them within our fighter class if they are not available if they are available within
our fighter class then our methods are going to overwrite the same ones that are within sprite so
we need to determine what do we want overwritten and what do we want to keep directly from sprite
well we know our fighters are no longer going to be rectangles unfortunately so sad as a result
we can go ahead and get rid of this draw method right here and if we get rid of this within our
fighter class that means since we're extending sprite we're going to use the draw method up
above instead but in order to use this draw method directly within our fighter class we need these
different properties available to us we just added a ton of properties into our sprite class up above
such as scale frames max we need to make sure that these are available within our fighter class as
well so we're going to go ahead and inherit these but before we inherit these we need to make sure
that we can pass them through within our fighter constructor so we're going to take the properties
that are not currently available within fighter it's going to be image source scale and frames max
we're going to go ahead and copy these we're going to add them to the end of our constructor
for fighter just paste those on in once you have those added in we can go ahead and call a function
called super what does super do well it simply calls the constructor of the parent so since we
know the parent of fighter is sprite we're going to go ahead and call this constructor right here
which sets some properties for us such as scale image frames max frames current you get the idea
but we have to declare what properties we want to set within that parent constructor so we
list them out within super and to call the parent constructor we know it takes one argument which is
going to be an object and here we're going to list out the properties that we want set within the
parent so what are the properties we want set well let's start off with image we want to go ahead and
set that what else do we want set scale frames max and frames current let's add those in scale
frames max and then frames current and then what else we also have frames elapsed and frames hold
so we'll add those in two frames elapsed and then finally frames hold so we know that these
are going to be set with our parent constructor is there anything else within our properties right
here that can be set by the parent there is one it's going to be positioned because we know our
parent sprite has a property of position being set right here so what we can do is we no longer need
this line of code we can simply just put position within super instead to say we're going to inherit
that property directly from our parent sprite so we want to go ahead and save that and refresh
over here to see what things look like we're going refresh looks like our game is just broken this is
a great time to inspect our elements go to console and see what's going on so right here we just have
the issue of images not defined online 55 within classes.js so we want to make sure within super
we're not referencing image we're referencing image source because that is the actual property
we're passing through right here and so we just want to make sure we set that correctly we save
go back again and we have one more issue it just says frames current is not defined so if we go
back to our code you're going to see that this is the issue right here frames current is not defined
because we're trying to pass it through our parents constructor right here but we don't
actually have anything set to that by default right now frames current is being set to a
static value and if you want to call super and make it work well we need to make sure
that zero right here is actually set to 2 frames current passed through as an argument right here
so we can either change this right here and add an argument to our parent class i think that's
a little overkill though instead what we can do is we can just go ahead and copy anywhere where
there's a static value so these three lines right here we're going to go ahead and copy those and
then we can get rid of these within our super method so these three right here then we can
paste them on in directly within our fighter class it's all up to you on how you want to do this it's
more of a preference in my opinion rather than a strict standard so let's save that and refresh and
things are back to normal we have errors in here but that is totally okay because we never actually
passed through an image to our fighter objects so that's going to be the next thing we want to do
so over in index.js we know that we just refactored our fighters to take an image source
so i'm going to grab our shop image source and i'm going to put it in where our player
is going to be created now i don't want the image source for our player to be sharp of course that
wouldn't make sense to have a shop as a fighter so instead i want to go ahead and reference samurai
mac specifically the idle.png image so to get that i'm going to go inside of our image folder
i'm going to say i want to go inside of samurai mac and then i want to go ahead and get idle.png
so if we look at idle.png how many frames is this image well let's go ahead and count one two three
four five six seven eight so it's going to be an 8 frame image as a result we want to make sure that
we set our frames max equal to 8 for our fighter a samurai mac so let's go ahead and save that go
back over here and refresh you're going to see we have a fighter sprite on the screen cropped
almost perfectly because we're not showing the eight different frames we're only showing one
we just need to go ahead and make him bigger make him animate and then i'm going to show you how to
crop this perfectly so that he's touching the ground so to make him bigger that's going to
be quite easy all we have to do is pass through a scale property let's set sailrite max scale to 2.5
save and refresh that and definitely bigger but we're still falling down a little bit
and the reason we're falling down is if we go ahead and look at this actual image
you're going to see that there is a lot of space around each instance of samurai mac
each frame is image right now is actually about this large this means we have padding on the top
left bottom and right of our image and we need it this way because later on when we go into one of
our attack sprites that attack is going to extend almost the full remaining width of the square
right here so we need this extra space but when we have all this extra space around our sprite
while the calculations are going to be off when we're trying to run collision detection between
the bottom of our sprite right here and the actual ground on our game so what we need to do
is offset our sprite right here so we're going to move our sprite from this location
to the very top left hand corner of where we're cropping it and we need to define what is the
width and height of one of these images to get the correct collision detection so let's start
by translating our actual image towards the top left hand corner of our crop to do this we're
going to head over to classes.js and this is going to be actually within our class of sprite we want
to do it here because we might be using this not just for our fighters but for other sprite
sheets in the future so i want to add in an offset property and here i'm going to set this dot offset
equal to offset and now that i have this offset in place i want to go ahead and use this within c dot
draw image so all i'm going to do here is from the position in which we're actually placing our image
i'm going to subtract from this this dot offset dot x and i'm going to do the same thing for
this dot offset dot y now right now this the offset.x and y is equal to undefined because
we never actually passed anything through our sprite constructor as a result if you want this
equal to a default value and you don't want to go ahead and subtract something undefined from
something that actually exists we can go ahead and set the offset equal to an object with an x
a 0 and a y of 0 because by default images should not be offset by any value and then
finally if we want to use this within our fighter class we need to go ahead and take this argument
put it within our fighter clause constructor put it within super to make sure that we set that
property up above and we should be good to go with just that so now over in index.js we can define
the offset in which we want our player moved so we can move it to the top left-hand corner of
all that padding so here i'm going to say that our offset is going to be equal to an object with an x
and also a y what is our x going to be i already did the calculations on this it's going to be
215 pixels and then y was around 180 we're going to fine tune this as needed so now we
have offset being passed through if we look within classes.js it's being passed through right here
going into super being called above and you'll actually notice offset's being defined twice
right here within our constructor we want to make sure that is not the case let's get rid
of this first offset make sure that we only have one that's set to a default right here and then
we're going to save and on refresh you'll see this is looking a lot better so we essentially got rid
of that padding on the left hand side that's fine to start let's go ahead and make sure that we get
rid of more padding on the bottom right here so to get rid of that padding we want to decrease our
offset value right here let's go to 170 that should reduce us by 10 pixels on the bottom
looks like we're getting a little closer let's go down to 160 save and then refresh
and then let's subtract about 3 pixels from that so 1 57 save and refresh that and now
we are touching the floor so perfect now let's go ahead and get our sprite moving up and down why is
this not moving up and down currently well within classes.js if we go ahead and look with an update
we don't have any code responsible for moving frames elapsed or frames current through their
iterations we need to make sure that's happening in order for our draw method right here to go
through our sprite sheets correctly so how do we go ahead and add this code up above with an update
into the update function down below well what we could do is we can simply just copy all this code
right here and then paste it into update like so save and refresh you're going to see now we have
that perfect animation in place that's totally fine well the only issue is we repeat our code
if we're trying to follow do not repeat yourself principles well it makes sense to put this in its
own method rather than just duplicate it in two places so rather than duplicate it right here
i'm going to delete that and then up above in sprite i'm going to add in a new method
called animate frames because that is exactly what this function does if i go ahead and paste this
code in there well now in update i don't even need to call all this code i can simply call the method
animate frame should actually be animate frames miss s right there we're going to call anime
frames right here which calls this in return and now that this is within the parent class of
sprite i can go ahead and use this method within the child class down here i don't even need to
define it i can just call right within the update function this dot to animate frames and it should
still work accordingly so let's save that and refresh and that still works we have clean code
because we're using do not repeat yourself principles now one issue is well if we try
moving this character with wasd we're not able to move and if we inspect the element and go
into console while we're getting a bunch of red errors regarding classes.js and line23 we're not
able to draw some sort of image do you know what image that is well it's going to be our player
2 over here we never actually set an image for player 2 and that's ok because we're not ready
to do that but we do want to make sure we're not getting that error so we can make sure that our
game functions accordingly for what we have right now so to make sure that our player is not being
rendered out on the screen we're going to go down to animate and we're simply going to comment out
enemy dot update so we do that save and refresh and then start moving well now we can move again
and if we right click and inspect element we no longer get any errors within our console because
we just commented out our enemy and since our enemy did not have an image source associated with
it it was just trying to error out continuously so that's going to allow us to check off the idle
animation for our player sprite so next up we're going to go ahead and implement our run sprite we
want to be able to switch between being idle and then running back and forth so how do we go about
implementing this sprite right here where we're going to be using a running animation well we're
going to want to start off in classes.js and we want to find our fighter class so we're going
to be adding a property within our constructor right here and this is going to be called sprites
essentially this is going to be an object that contains all the sprites for our specific fighter
so since we're putting sprites right here now we can go ahead and use it as a property within the
constructor saying this dot sprites is equal to the sprites that we actually passed through
so let's go ahead and save this and then go to index.js so we can actually begin passing these
sprites through into our fighter class so we're going to focus on passing this through into our
player right beneath offset we'll go ahead and add a sprites property and this is going to
be equal to an object so what kind of sprites is our player going to have well right now we
have an idle sprite and we also want to have a run sprite so we're going to list those out right here
let's start with idle this is going to be eagle 2 an object and it's going to have an image source
and that is going to be equal to the same image source we used prior so this one right here and
this is also going to have a frames max associated with it this has 8 frames associated with that
idle.png sprite and then we want to go ahead and do the same thing not just for idle but for run
as well so i'm going to go ahead and copy that property paste it below and change idle to run
now what is the image source of run right here well it's going to be samurai mac and run so
we're going to go ahead and change idle right here to run to reference the correct image and how many
frames is run png going to be well we can go ahead and open this and count one two three four five
six 7 8. so lucky for us this is the same amount of frames as our idle png sprite so we don't
actually have to change anything for frames max right here so how this is going to work is we're
going to switch between these sprites by setting this dot image to whatever sprite we want to go to
so where is this.image once within our parent class up above you'll see we are setting an image
equal to a new image based on the image source in order to switch between these sprites we need to
make sure that we create a new javascript image based on those sprites and then switch this that
image to the new image we just created sounds a little confusing but let's go ahead and do this
within class of fighter so we just passed our sprites through they're now equal to this dot
sprite well we need to go ahead and create that javascript object for each object within this main
sprites object so we're going to go ahead and loop through our sprites object by saying for sprite
in sprites so what is this going to do well if we look within index.js this is what sprites looks
like and basically we're just going to be looping through each object within the object of sprites
so first we're going to loop through idle and then we're going to loop through run that's all
this means within classes.js when we use syntax like this now our goal here is to essentially
create an image property dynamically that is going to be equal to a new image object we're
going to go ahead and do that as we loop through sprites over here within classes.js so to add on
a property to this object we're currently looping over we can go ahead and select our main sprites
object and then we're going to reference which object we want to grab with sprite right here
so sprite right here is actually going to be the object key so when we reference sprite
we're actually referencing either idle or run that is the key of the object so when we go ahead and
use this syntax right here we're basically saying this is the object we're currently looping over
and if we want to add a property onto this we can simply type dot and then say what property do we
want to add well we have to add an image property and this is going to be equal to a new javascript
image object so now that we have this we want to go ahead and set the source of this right here so
we're going to paste this below and say that the source of this image is going to be equal to what
well we can go ahead and grab sprite's bracket sprite and then say that the source of this should
be image src and make sure that s is capital so let's go ahead and save this and at the very end
i want to go ahead and copy this dot sprites and looking at this well let's go ahead and make sure
we're referencing this. sprites right here within our for loop so we're going to loop through this
dot sprites get the individual sprite and then set everything we need down here and then finally
we're going to log this out and before we save and refresh this just make sure that you declare
a sprite right here as a cost because sprite is never actually going to change you need to make
sure that you declare this as a cost far or left when you're looking through this for the syntax to
work so we're going to go ahead and save that go over here and refresh and then open up our console
to see exactly what we're cause logging out so right now it looks like we're console logging
out to this object we'll open it and now we have an idle object and a run object you'll see right
now we have an image set to a javascript image for both idle and run so technically
we should be able to use this and switch back and forth between these two different actions
within our fighter sprite now let's delete this console.log and think to ourselves what is going
to determine when we switch between either our running sprite or our idle sprite well we're going
to determine that within index.js specifically within our animation loop because we know whenever
we press a or whenever we press d we want to go ahead and run rather than idle so since we just
set up everything within classes.js whenever we move to the left what do we want to do well we
can select our player dot image and we're going to set our player image equal to our player sprites
specifically the sprite of run and we want to go ahead and grab that exact javascript image so on
top of this we need a reference dot image and with that when we press a we should switch over to the
running sprite let's save this make sure you have classes js saved as well refresh and then when we
go ahead and hit a you're going to see now we have a running sprite and i can go ahead and
move back and forth because we're not switching back to idle when we let go of it so technically
this works whenever we hold down d or a we can see this is what the sprite looks like and since this
is eight frames it just works right out of the box not too much extra we have to do right there but
we do know we want to go back to an idle state when no keys are being pressed so what we can
do is right above player movement we can grab this line of code where we're setting our player image
and what we're going to do is say that our default player image is going to be equal to
player.sprites.idle.image instead of run.image so now if we save and refresh that we're going
to idle and then if i move to the left we'll go into a running animation as soon as i let
go we're going to go back to idle because we're setting that for every frame we go into but now
if i hold down left we're only in running if i come back over here you'll see we go back to
idle so that's how we're going to be switching back and forth between these to start but we
do want to make sure that we're running to the right whenever we hold down d as well so let's
go ahead and make sure that we switch our player image whenever we hold down d2 so i'm going to
go ahead and paste that on in there and we can save that and refresh and then hold down d and
now we're running to the right whenever we hold down d running to the left when we hold down a
and then when we stop we're going to go back to that idle animation so now we can go ahead
and check off run so now we're going to go ahead and switch to a jump animation how do we go about
doing that well we want to go ahead and within our player const we want to add in a new sprite
into our sprites object so to do this really quick i'm going to go ahead and copy run
and then add a comma at the end of run paste that on in and then i can call this our jump
sprite right here so i just need to make sure i'm referencing our jump image right there so instead
of run i'll call jump and i need to see how many frames does this jump image actually consist of
so if i look within jump.png that's actually going to be two frames it's going to be our first frame
switch within our sprite switching right here so i'm going to change frames max equal to 2
and now what i need to do is determine where do we want to switch to a jump animation so i think it
makes sense to switch to jump animation with our animation loop when our velocity is less than zero
because that means we are currently going upwards in the air and when we're going upwards in the air
while it makes sense to switch to a jump animation so where are we going up in the air with our
animation loop but we don't really have anything directly in our animation loop so we need to make
sure we add that right beneath player movement i'm going to add an if statement that says for player
dot velocity on the y-axis is less than zero this means we're currently up in the air so if this is
the case we can go ahead and select our player image and set this equal to our player sprite
jump image and that's going to go ahead and switch us on over there but if we save and then refresh
and try jumping you're going to notice well that looks very weird not very good because whenever
we go ahead and jump we need to make sure that we're also switching our player dot frames max
equal to our player sprites jump frames max basically we're just sending this eagle to two
frames because if we try using our sprite sheet animation logic with a frame rate that is greater
than the actual sprite sheet well it's just not going to work we're going to get this effect we're
getting over here where we don't actually see the image in place so we want to make sure that
we switch that on over to 2 but we're not done just yet you'll notice if i save this refresh
try jumping well we have a jump animation in place when we go up but then we get some sort of weird
effect where we get a duplicate of our player and it looks like honestly they are teabagging
the ground not very good for what we are going for so one of the reasons this is occurring is because
our frame's max right here is now set equal to two we're trying to set our player image equal
to our idle and a run image when those have eight frames associated with them but right now we're
saying that our frame's max is equal to two so we're just running the animation really quickly
and it throws off the whole width calculation that actually keeps our crop mark in the correct place
so we want to make sure that when we go ahead and set player image equals something like idle
or run that we also set the frame's max back to those original values as well we only want to do
it once too because it's kind of inefficient to be setting this for every frame when we're in the air
when we really only need to set this stuff once for that action so with all that in mind if we
look at this this code is kind of getting hard to read and understand just at first glance so
this is a case in which we want to go ahead and abstract this to abstract this i'm going to go
inside of classes.js and i'm going to add onto our fighter class what am i going to add i'm going to
add a method called switch sprite this method is going to be responsible for switching between our
different sprites it's going to take an argument which sprites do we want to switch to and then
i'm going to add a switch case statement that switches out to the sprite we're passing through
and then finds a case as something along the lines of idle and a break statement for that
we're going to add in a case of run break there and then add in a case of jump as well we want to
break at the end of this too so now when we call switch sprite we want to do all that setting code
that we currently have within our animation loop and we're going to detect within here to make sure
that we only do it exactly once for each action we take so let's start off with our case of idle
within index.js we know we switch over to our idle state with this line right here where we set
player image equal to dot sprites.idle.image let's go ahead and cut this out from here and
instead let's go and select player dot switch sprite what sprite do we want to switch to
well we want to switch to a sprite of idle so now we're calling this within classes.js essentially
we're going to run whatever code is within this case statement right here i want to paste in that
line we just cut out and we can't really reference player because that is an instance of the class
instead we need to make sure we're referencing this that image and this dot sprites so this
is the exact same thing as we had before except we're going to call that switch sprite makes a
little more sense it's a little easier to read but within classes.js what we can do is within
a case of idle we can add an if statement that says if this dot image is not equal to
this dot sprites dot idle dot image then we want to switch our image to idle we're only going to do
it once with this if statement as soon as this is set this will no longer be called but we're still
going to be running a case statement with our animation loop but we're only switching over to
that sprite sheet just once now so let's go ahead and refactor run we're going to go into index.js
and where are we setting our player image equal to our run sprite it's going to be right here
so i'm going to cut this out and then i'm going to call player dot switch sprite equal to run instead
so let's save that go back to classes.js and then within our case of run i can write an if statement
that says if this dot image is not equal to this dot sprites dot run dot image then i want to go
ahead and set this.image equal to our run sprite so we can save that go back to index.js and then
we want to go ahead and call this right here as well because this is just basically duplicate code
let's paste that on in there and now finally we want to do the same thing for when we're jumping
up in the air for our jump sprite we're going to go ahead and cut these two lines out right here
select our player dot switch sprite method and then call jump on that so now that we're calling
switch sprite jump in classes.js we're going to run whatever is within this jump case right here
we're going to paste in that code and say instead of player for these four instances we're going to
reference this so we're switching our image over to our jump image and then we're setting our
frames max equals to the jump sprites frames max which is going to be 2. so we're going to go ahead
and make sure that we're setting this frames max within each if statement right here for run and
idle so if we're going to use more than one line within an if statement we need to make sure it has
brackets and then we can go ahead and set this dot frame's max equal to that sprites action which is
going to be run so we want to switch jump right here to run frames max property then we're going
to go back to 8. so let's go ahead and do the same thing for idle we'll go ahead and take this
line of code right here add some curly brackets into this if statement and then right beneath
where we're setting our image we'll say that our frame's max is going to be equal to our sprite
of idle dot frames max property now it's important to note within this jump case we want to make sure
we have this exact conditional within here too so we'll add if dot this dot image is not equal to
this dot sprites dot dot then we want to go ahead and call the following code to set our image and
our frames max just once so before we go ahead and save this and check it out let's go ahead and make
sure that we're setting everything to the correct action so it looks like right here for idle we
are indeed referencing all idle instances for run we're referencing run run we want to make sure we
definitely change jump right here to run otherwise we're going to have the wrong amount of frames
being rendered and then for jump we're referencing jump we need to change run right here to jump as
well jump and jump with this we should be good to go so make sure that all those are correct
save that and then save index.js and let's test it out so on refresh we start moving it
looks like running and idle are good to go so perfect now if we jump if i hit w we do have a
pretty good jump animation but you might notice there's a little bit of flashing going on right
there what is that flashing why is it happening well what's happening here is is during our run
animation we're going to go from one to two then to two to three then to three to four and we're
going to keep going until we hit eight and then we're going to go back to the beginning but the
thing is we might leave off on our fourth frame if we try to immediately switch to the fourth frame
of our jump animation down below while there is no fourth frame therefore we're going to be rendering
out just a blank space which is what's causing that flash effect to occur we need to make sure
that whenever we switch between run and jump or some other sprite that we reset our current frame
equal to no other than just zero that means we're going to start at the beginning of our animation
so whenever we call switch sprite over in classes.js and we actually go through the
process of switching the sprite within these if statements we want to go ahead and say that
this dot frames dot current so the current frame is equal to zero when we switch to a different
sprite so let's go ahead and copy this and paste it within each case paste it within jump as well
save that head over here refresh and now when i jump we're no longer getting that flash in place
when we start running to the right you're going to notice we kind of lost a running animation right
here that is because we are furiously trying to switch between our idle and run animation
we're always going to switch back to idle because this is the first thing we call but if we go ahead
and press down a or d we're going to switch to run which just means we're still switching back
and forth between these different sprite sheets we want to make sure that we only switch back to
idle if we're not pressing down a or d so to do that we want to make sure this is inside of an
l statement next says if and else if so we'll paste in player that switch sprite to idle if
we're not moving on the x-axis so now if we save that and refresh we look good in our idle position
we begin running and the running animation is back we can even jump we still get that jump
animation right there so to finish off our jump animation we want to also add a fall animation
for when we're going back down right now as soon as our y velocity turns positive we switch back
to our idle animation we want to switch that over to a fall animation to give off a realistic effect
so to do this we'll find where we're creating our player specifically the player sprites
it's going to be right here and i want to add into this a fall category as well
so i know i need an image source and a frame's max for this i'm going to copy these two lines
paste it into fall and then determine what image do i want to reference for our fall sprite
it's going to be fall.png this is going to be two frames so we'll go ahead and change jump to fall
for the fall sprite and we can keep frames max the same right here but now that we just added
in a sprite we also need to determine what happens when we switch over to a sprite within closet.js
so we need to add in a case statement paste this down below and say when we have a case
of fall then we want to switch everything to the fall sprite so all we need to change here
are these three instances of jump i'm going to do it at the same time with sublime text by
selecting one instance and holding down command d to select those three and i'll change jump to
fall instead which is now available to us because we added that in when we were creating our player
fighter in the first place so now we just need to determine when we call switch sprite
fall that's going to be within index.js when our y velocity is going to be positive so right here
when we're jumping we're going to want to add in an else f that gets our player velocity on
the y-axis and say if this is greater than zero then we know we are currently falling so this is
a perfect time to switch to not a jump sprite but rather a fall sprite instead so let's save
that refresh and then we jump now when we fall we have a fall sprite in place so that's pretty cool
but you may notice when we go ahead and hit the ground while we switch between it looks like idle
and our fall sprite really quickly so why is that well if we look within classes.js we're
going to want to focus in on our fighter's update class so this right here is our gravity function
and this is actually what's causing that error to occur so when we look at this position y plus this
dot height we are getting the bottom of our player right here and when we're falling down towards the
ground we're also adding on this top velocity which is increasing over time so eventually this
could be something pretty big like 21 for our velocity so if the bottom of our player plus 21
which is going to be down here is greater than our ground which it indeed is then we're going to
go ahead and set our velocity equal to zero which means next time we go through this update function
we're going to go ahead and run this if statement again so that means the bottom of our player is
going to be around here plus this.velocity y and since we set our y velocity equal to zero well
this whole statement right here might no longer be true because we're adding on such a miniscule
value even though we might be a little farther up in the air so since this isn't true as a result
we add gravity back onto this.velocity.y what happens when we add gravity onto our y velocity
while we switch on over to the fall animation so we're going from our idle animation to our fall
animation and eventually this is going to be true again but our position is going to be low enough
to the point where we're not switching between if and else if and we go back to the idle animation
fully so i know that's a little confusing but here's how we're going to fix it when this is
true we're going to set our y velocity but we're also going to set the position of the player to
be in the exact location in which it can no longer move so what i'm going to do is beneath this i'm
going to cause log out this dot position dot y i'm going to save that and then open up our console
and then i want to refresh just to see what that is so we want our y position to be set to around
3 30 for this to not fall any further without any weird velocity issues going on so not only
are we going to set our velocity y to zero we're also going to set this dot position dot y equal
to this exact value right here in which we're no longer moving up or down it's going to be 3 30 so
let's go ahead and set that equal to 330 and now we can go ahead and delete this console.log save
and then refresh makes it out of this and now when we jump and hit the ground you're going to see we
no longer get that weird flash effect when you're switching between our idle and our fall sprite
because we took care of that small little gap that was appearing due to our velocity and gravity code
so now we can run we can also jump and fall and then we go back to an idle position no matter
what we let up on so now we can go ahead and check off jump so now let's add in our attack animation
so to do this we're going to go to index.js and find our player and then our sprites object so
at the very bottom right here we want to add in a new property and this is going to reference attack
dot one so we can see right here this is one two three four five six frames now with an index.js we
can reference our image source which is going to be attack one change our frames max equal
to the max amount of frames within that sprite sheet which is six we always want to make sure
that we change the property name to the exact same name as we have over here it's going to be attack
one so now that we have attack one in place we always want to go to classes.js and then add in
the corresponding case statement so at the very bottom i'm going to copy this case right here
paste in a new one and say for the case of attack one then i want to make sure that i switch our
image over to not fall but rather attack one for these four lines of code and now when do i want to
activate attack one well if we go into index.js we want to look for our event listener where we press
on the spacebar so if i scroll on down we're going to see when we key down on space right here we're
calling player attack that is perfect which means within classes.js where we actually defined attack
right here we can also call this dot switch sprite equal to attack one so we're just calling this in
a different location but this is going to activate this code right here so if we were to save this
and then refresh and then hit space bar well it looks like we're trying to attack but we're not
able to fully that is because within our animation loop we're saying as soon as we activate the
attack animation we'll go directly back to idle because we're not moving left or right and we're
not jumping currently it shouldn't really matter if we're moving if we're jumping or standing still
when we press spacebar we only want to show that attack animation and nothing else so basically
when we activate an attack we want to make sure that the switch case code can no longer be called
so we're going to do this with an if statement we're going to say if this dot image is currently
equal to this dot sprites dot attack 1 dot image then we're going to go ahead and return we're not
going to call any of the following code which might switch us to a different sprite sheet
if we save this refresh everything still works but as soon as we activate our attack with space
we're going to get that attack animation and that's pretty darn cool but you'll see
my hands are up and this just keeps going over time what we want to do is say when this attack
animation completes just once then we're going to reactivate our sprite switching code so we can do
that by extending this conditional right here by adding an and statement saying if this dot frames
current is less than this dot sprites dot attack 1 dot frames max and we want to subtract 1 from
this because frames current starts at zero while our frames max is the actual amount of frames
starting at 1 and now in all what we're saying is if our image is the attack image and our current
frame is less than the frame's max of the actual sprite sheet then we just want to return we don't
want to call any of the following code but as soon as frame's current goes above the frame's max
right here then we're going to continue allowing us to switch back to either idle run jump or fall
or even attack one if we decide to press spacebar again so by saving this going back over here and
refreshing all of our jump code run code idle code seems to work if we hit space
now we're only attacking once because we added in this conditional right here
so that's how we're going to add in our animation for our attack we're going to implement decreasing
our health bar with this new animation once we get our second player in there and if we look at to do
we'll see that's coming up next so we have our sprites for our player but now it's time to
bring our enemy back into the game and replace our rectangle with an actual sprite sheet so to
do this we want to go to where we are creating our enemy it's going to be down here on line
73 for me we need to add in all the properties responsible for adding sprites into our fighter
so those sprite properties are going to start at image source within our player instance right here
so we can grab everything from image source all the way down to where our sprites object ends
and we're going to copy this and paste it into our fighter instantiation so now we want to go ahead
and reference a different image not samurai mac because well they should be different from each
other these are different fighters so instead of referencing samurai mac we're going to go into a
kenji directory and then reference the idle image from there so if we look at the idle image for
kenji it's going to look like this we're facing to the left and we only have four frames within
the sprite sheet so now within index.js we can say our default frame's max is going to be 4 and for
our enemy we're no longer referencing samurai mac we're going to reference kenji instead so we're
going inside of this folder we want to make sure that we change each instance in order samurai mac
to kenji to make sure we're referencing the correct image name so now we just need to go into
each image and make sure that the frames match up with the actual image so we know for idle we just
change this up here to have a frames max of four if we're going to check out run for kenji as well
we have one two three four five six seven eight so that's going to stay the same if we check out
jump that's two stay the same and then if we fall we also have two that's going to stay the
same as well and then finally we have attack one this is going to be a four frame animation
so over in index.js we just want to make sure we change attack one to have 4 frames max instead
of 6. so with all this in place back down in our animation loop you can see we commented
out enemy.update because we were getting some errors before just rendering out a rectangle but
now that we have all the sprite animation stuff in place we can go ahead and uncomment this out
save and then let's refresh just to see what happens well looks like our sprite is already in
the game we're not really in the correct location because it seems the sprite is supposed to be a
little taller than samurai mac over here so let's go ahead and fix that now in order to make sure
that they're placed directly on top of the ground we can go ahead and change the offset value for
our fighter so we're going to go ahead and change this y value equal to 167 instead of 157 and
that should raise us a little bit if we refresh we're definitely more on top of the ground now
but if i try moving our enemy with our arrow keys you're going to see that we are stuck in this idle
position no matter what i do if we run if we jump even if i attack we're not actually doing anything
so we need to go ahead and add the implementation in for our actual enemy and it's going to be
really easy since we already did this for samurai mac if we scroll on down into our animation loop
we can see that this code right here all relates to samurai max sprite switching this code right
here relates to our enemy movement but we're currently not doing any sprite switching for our
enemy all we need to do is grab one of these lines right here where we call player.switch sprite
and then paste it into one of these estimates where we're holding down our arrow left
or arrow right the only difference is going to be we're no longer switching our player sprite
but rather our enemy sprite we want to make sure we do this in both locations right here and we're
basically just replicating the code above but for our enemy player so if we look at samurai
mac we have an l statement right here for idling we're going to add in the l statement right here
for our enemy this is going to be kenji so our enemy should switch the sprite over to idle when
we're not moving on the x axis and then we need to take into account jumping as well i'm just going
to copy these five to six lines right here paste it beneath our enemy movement and then say when
our enemy's velocity is less than zero meaning we are currently moving upwards we want to switch the
enemy sprite over to jump and then finally for our fall animation we just want to make sure that when
our enemy velocity is greater than zero meaning that our enemy is currently falling we're going
to switch our enemy sprite over to fall so now that's all we have to do if we save this go back
over here and refresh we start running we switch over to our running sprite for kenji if i jump
we have a jump sprite and when we fall we have a fall sprite all that is implemented all we have
to do now is make sure that when we press down on the arrow key that we actually launched the
attack so let's check out where we are currently attacking with kenji it's going to be within our
event listeners on key down this is where player 1 is attacking this is going to be samurai mac but
when we arrow down well we're no longer using this method down here where we're setting is attacking
equal to true we're just calling dot attack on the fighter instance so here we're going to call
our enemy and then call attack on top of that and that's automatically going to activate attack one
so it's going to save this refresh and then when we hit down on our keyboard now
you're going to see now kenji attacks so perfect and we can move these two independent one another
attack at the same time so we really has some good physics in place with spray animations as well
to make sure that our fighting game is set up for success so with that i'm going to go ahead
and check off enemy sprite so now we're going to go ahead and react to our sprite attacks
so thankfully we set this up a little bit when we're dealing with just rectangles but you'll
notice over here when we try attacking well it really only works sometimes so we need to go ahead
and edit that functionality to get our attack box in the correct location so that it's overlaid
directly on top of our player's sword attack so the first thing we're going to do here is go into
classes.js so we want to get that rectangle overlaid on top of our sword so we want to
go ahead and show that rectangle again to do this we can go into our fighter clause and we're going
to go into our update function right here this is what manages our attack box position on the x and
y axis currently so it's the perfect location to actually draw this attack box back out so right
beneath where we set our tack box position we can call c dot fill rect to bring back that rectangle
that was overlaid on top of our rectangles previously so we want to create an attack
box rectangle and we can do that with this dot attack box dot position dot x for the x coordinate
the y coordinate is going to be this dot attack box dot position dot y our third argument is going
to be this dot attack box dot width and then our fourth argument is going to be this dot attack box
dot so we're going to save this and then refresh we're going to see our attack box is drawn back
out so right now it's way over here rather than on top of our player because this is affected by our
attack box offset remember we added that in when we are still dealing with rectangles but we went
ahead and we created a new offset property which actually determines the offset of our
sprite relative to the actual image as a result we need to add in a new property that actually
references the offset of this one attack box right here rather than the offset of our sprite
so we're going to go back into our fighter class and we're going to add in a new property
called attack box so this is just going to be one object and we can go ahead and define a
default right here to see what this looks like and inside of this object we want to add in an offset
property that's going to be equal to an object and then we also want to add in a width which we
can set to undefined by default to start and also a height which will also set equal to undefined
we're only using this for visual purposes we know exactly what an attack box consists of
so we know we want to pass through a property of attack box whenever we create a fighter but if
we go ahead and pass this through then down here where we actually define our attack box property
we want to make use of what we're passing through so our offset for our attack box is actually going
to be equal to our attack box dot offset which is going to be this object right here then for our
width this is no longer going to be equal to 100 to start it's going to be equal to our attack box
dot width and then down here for height we're going to say our attack box height
should be equal to the height we passed through our attack box object so now that
we just set this up we need to make sure that we're actually passing through data related to
our attack box for each fighter so we're going to do that within index.js find our player fighter
and at the very bottom right here beneath our sprites property we can go in and add in
an attack box property this is going to take three properties inside of it it's going to be
the offset we're just going to have an x and also a y i'm going to set these equal to zero to start
we're going to have a width let's go ahead and say this is equal to 100
and then a height we'll say this is equal to 50. so now we can go ahead and define a different
attack box for an enemy and we're going to do that now we'll just copy this property right here that
contains all of our attack box data copy that and then within our fighter beneath our sprites
object we're going to go ahead and paste in a tag box so if we save this and then refresh well now
this is placed in the correct location because our attack box offset is based off of what we
just passed through into each individual fighter and this will still function the same you'll see
if i go ahead and hit space to attack well we're only going to go ahead and subtract from our enemy
health when this attack box is actually touching our enemy so i go ahead and move over to the right
now when i attack it's going to decrease but only when this is touching so we want to set the offset
for this to make sure that it covers the full width of our attack so we're going to go ahead
move it in front of our player and then we're going to extend the width of our attack box
so that it extends all the way to where our sword ends so to go ahead and set that we're going to
go up to where our player attacks and we're going to focus in on the attack box property
so we know our offset should be around 100 pixels i believe that is the width of our player we can
just go ahead and kind of guesstimate this if we save and refresh that that is definitely in front
of our player and i'd say that's a good location in front of our player in which this attack should
actually activate it's not too close to the player where they wouldn't actually be hit by a sword
but it is far away enough where we actually see the animation in place where someone gets hit
so i think this is an okay location but we do want to go ahead and move this attack box down in the
middle of our player so you might be thinking can't we just go ahead and add on 50 to y right
here save and refresh well you're going to notice this didn't actually move at all because if we
look within classes.js we never take into account how our attack box should be affected by the
offset of our attack box on the y-axis and you can see that directly within update specifically where
we're dealing with our attack boxes right here so for attack box position y we're saying we want to
go ahead and offset the position by our attack box offset on the x-axis but we never actually
did that for position y right here so we're going to add on to this this dot attack box offset y
and that's going to go ahead and make sure our offset actually affects the attack box position
on the y-axis so we save that and refresh now that has moved down by 50 pixels it looks to be
in more of a correct location so now we just want to make sure this extends the full width of this
attack so we're going to extend the width over in index.js by saying our width of our attack
box should be equal to let's go ahead and say 200 to start refresh and it looks to be a little too
large we'll subtract 40 or 50 from that let's go ahead and start with 40 by saying our width should
be equal to 160 save and refresh and that looks to be almost perfect so now when we move forward and
we attack our enemy with our attack box over them you're going to see health is subtracted and when
we move back and this is not touching nothing happens so we're just going ahead and edit our
attack box to work with this animation but you're going to notice that this health bar goes down
at the very beginning of our animation it doesn't actually go down when the sword hits the enemy
watch again when i hit it immediately goes down rather than when the sword hits the enemy
so we want to go ahead and fix that we want to say we only want this to go down when we're through
the fourth or fifth frame of our actual attack animation so where we're detecting for a collision
it's going to be down here within our animation loop right here this is where we're detecting
for collision with our player we do want to run these conditionals but we also want to add in
another condition now this condition is going to get our player dot frames current so the current
frame we're on within this animation we want to say we only want to go ahead and subtract from our
player health if this hits the enemy when player frames current is equal to about four because that
is going to be the exact frame in which the sword actually comes out and we can always check this by
looking in simran max attack one you're going to see this is going to be our zeroth frame this is
going to be your first second third and fourth so our fourth frame is what we want to monitor
to say this is when we should actually subtract from the health of the enemy so with the index.js
we want to make sure player that frames current is equal to four when we actually subtract our health
and if we save this and refresh and try attacking well you're going to notice this doesn't really
work unfortunately why is that well this shouldn't be true technically but if we look at when player
is attacking over in classes.js we're going to be setting that whenever we call this attack
method right here so we're setting this equal to true as soon as we press down on the spacebar and
then after about 0.1 seconds we're setting that equal to false so we're setting this back equal
to false before we even get to frame 4 within our animation and as a result it's causing that
conditional to not fire so to make sure this isn't set back to false immediately we can go ahead and
increase the time right here to something like a second but that's not going to be as accurate to
say when our animation actually ends we want to make sure that we set his attacking evil
falls when our animation actually completes whether or not we hit our enemy so we're going
to go ahead and remove this set timeout right now so now if i go ahead and hit our enemy you're
going to see that only activates when the sword actually touches him but now watch what happens
if i go back here and i attack nothing happens but if i run into our enemy without attacking
we decrease their health because is attacking is equal to true still we want to make sure that we
set that back equal to false when we miss our enemy with the attack so we're going to do this
within index.js so this right here says when we detect for collision but beneath it we can say if
player misses then we want to call the following conditional we can say if our player is attacking
and our player dot frames dot current is equal to 4 meaning we're at the end of our attack
then we're going to go ahead and set player that is attacking back equal to false
so we're going to go ahead and do that anyways but this is only if we're actually touching our
enemy with our sword but right here in case we missed then we want to set it back equal to false
so we don't accidentally subtract from the enemy's health it's going to save that
and then refresh and test this out so we should miss first which we do and then when we run into
the enemy we're no longer attacking so we don't subtract from their health now if we go ahead
and cover this attack box with our enemy right here attack you're going to see that subtracts
go back here attack and run into them no more issues regarding that so now let's go ahead
and add in the attack for player 2 over here we want to make sure that this attack box is over
our sword swing so we're going to go back to our code and find where we are creating
player 2 which is our enemy we want to focus in on this attack box property so our offset for x
is going to be around negative 100 because that's going to make sure we shift that over by the width
save that and that seems to be in a pretty good spot in regards to its x position
but we do want to move it down a little bit as well so let's go ahead and say that y is going to
be down 50 pixels save and refresh and now i like the looks of that let's go ahead and extend this
so that it actually reaches the end of this white little slash we're going to say the width
for this should be eagle 2 150 save and refresh that and now since we're increasing the width
right here the offset also needs to be taken into account because objects on the canvas are drawn
from the top left hand corner and we're kind of trying to do this in reverse for this attack box
so we're going to subtract 150 here for our offset and now almost there we need to add about 10 to 15
pixels onto that width which means we need to do it for right here and width we'll say that's
but we also need to subtract 165 as well so we go ahead and save that and then attack you're
going to see almost there let's go ahead and add on five more pixels and i think that should do it
so our width is going to be 170 and then our x offset is also going to be 170. so now when we
save that that pretty much reaches the end and i think that's a good location to say this is when
we should actually hit player 1. so now if i go ahead and move over and move that over our player
start attacking you're going to see that decreases over time but we have the same issue that we had
with player 1 you'll see if i attack and then just run into player 1 with this attack box
your health goes down anyways we want to make sure we prevent that we're going to do that
within our animation loop the same way we did it for player one so we want to copy this code
right here go beneath our conditional for if we actually hit player one which is right here and
paste that on it but now we know we're dealing with our enemy rather than our player so we're
going to go ahead and switch all instances of player with enemy that is attacking instead
we want to make sure that we select the correct frame in which this attack should hit so we can
always look within kenji that attack 1 and here we're going to say well this should actually be
frame two so kenji has a little bit of an advantage because their attacks are a lot quicker
basically we can say samurai mac is going to be slower but more powerful kenji is going to
be quicker but weaker in regards to damage so we want to make sure within index.js that the
frame's current is equal to 2 that is when the enemy sword attack is basically over we want
to do this right here and we also want to add in this and statement into this conditional so that
we don't just subtract from our player's health immediately we need to wait at least one frame
by adding in this and statement that says enemy.frame's current should be equal to 2
before we actually go ahead and subtract from our player health so we save that and refresh now
if i go ahead and attack over here and run into player 1 we don't subtract from their health but
if i go ahead and move this attack box over them then attack that's all i'm going to go
ahead and subtract on frame 2 instead so now really the last thing we need to do is simply
remove these boxes so to remove these boxes we can go to classes.js and all we need to do here
is find out where we actually drew them out it's going to be this.c dot philrect we can go ahead
and say this is where we draw the attack box and then we don't really need this code right now so
we can go ahead and comment it out save refresh and now our attacks should work and subtract as
needed but without showing that attack box so i attack with player 1 right here you're going
to see that subtracts and then when i attack with player 2 that subtracts as well so we're beginning
to finish up this fighting game but using attacks with actual sprites so now we're going to go ahead
and add in a receive hit animations like these two in on you both receive hit death animation
but we want to go ahead and react whenever our player or the enemy is hit so when we go ahead
and attack there should be some sort of reaction right here for our enemy how are we going to go
about implementing that well we're going to start by heading on to where we are creating our enemy
so that's going to be right here on line 81 for me and i know i want to add in a new sprite
for this animation so i'm going to go to the bottom of sprites right here and i'm going to
call this take hit so this is going to be equal to an object and this object has two properties
image source and where do i want to go ahead and grab this image well simply within
our image directory so img and then i want to go ahead and say this is referencing kenji
and i want to get this right here it's going to be slash take space hit with a lowercase h dot png
so we look within take hit right here you're going to see this is a three frame animation and it's
just kenji reacting to getting hit going backwards so back within index.js we want to say that our
frames max the max amount of frames we're going to have here is going to be equal to 3 because that's
how many frames we're within take hit right here so now that we have this here within our enemy
constructor we need to go into classes.js and define a case for taking a hit so i'm going to
go ahead and copy this case right here right below paste in a case of take hit with a capital h and
then i want to say if our image is not currently equal to the sprite of take hit and i want to make
sure that i change out attack one in each location where it is currently swap that out with take hit
then we're going to go ahead and swap that image change its frames max and set the frame's current
equal to zero so this is going to actually give us an option to take a hit and activate that
animation but where would we actually call switch sprite to activate take hit well within index.js
we want to scroll on down to our animation loop and right where we are detecting for collision
we know that this is currently where our enemy gets hit so we can add a comment here that says
and enemy gets hit so within this if statement we also want to go ahead and select our enemy we're
going to call a new method on top of this because although we could write the code directly in here
sometimes it's good to abstract things to make our code more readable so we're going to say enemy
dot takes a hit so take it right here when we go ahead and collide the attack box with our enemy
now for enemies going to go ahead and take a hit well we're going to go ahead and subtract from
our enemy health that's already happening right here but if we want to go ahead and simplify
this we can go ahead and take out enemy health minus 20 cut that out we're actually going to
go ahead and paste it within a take hit method directly within our fighter class so let's go
to classes.js if we're scrolling up right beneath the tag we're going to add in a method of take hit
now we can go ahead and paste in dot health minus equal to 20 but we can't reference enemy anymore
because that actually referenced the direct object instead we need to reference this fighter's health
so this will function exactly the same as we have right now when we go ahead and launch an attack
but what else do we want to do when we take a hit we want to go ahead and switch our sprite over to
take hit so you'll notice if we go ahead and save this and refresh and then we hit kenji
over here but we're not actually going back to that take it animation even though we are
definitely calling switch sprite to take hit why are we not showing that animation well we need to
make sure that we're not reverting to this idle animation at any point in time when that take hit
animation activates we're basically going to do the same thing that we did for creating attacks
you'll notice when i jump up in the air and credit attack when i move forward and create an attack
well that attack animation always goes because we're overriding all the other animations
available to us when we take a hit we also want to override those animations so that's exactly what
we're going to do so where are we overriding those animations it's going to be right here within
switch sprite you'll see this estimate right here it's actually representative of overriding all
other animations with the attack animation so we want to do the exact same thing not for when we
attack but rather override when fighter gets hit so if we're not currently attacking with
this right here we can proceed onwards to this if statement where we're going to say if the current
image being displayed is equal to this sprites dot take it dot image and what else if this dot frames
current is less than the frames associated with the sprites of take hit we're going to get that
with dot sprites dot take hit frames max -1 is basically the same thing we have up here we're
just using take hit instead of attack one we go ahead and add in this if statement we can go ahead
and return basically what this means is if we're not attacking but we are getting hit we don't want
to run any of the following switch case statements we're going to go ahead and force ourselves
to return if we're currently in the take kit animation and we're only going to allow ourselves
to go onwards if the current frame is greater than the max amount of frames associated with our take
hit sprite if that's the case then we can go back to switching over to a different sprite including
back to an animation such as idle so this should be good to go if we're going to save this and
refresh over here and we try moving while we're not actually able to move at all none of our keys
seem to be listening so let's go ahead and inspect our element and we'll head over to our console
and you'll see we have an error right there that says cannot read properties of undefined reading
image let's go and click into this well basically that code we just added in for the if statement is
not being read why is that well although we have a take hit sprite associated with kenji right here
we do not have a take hit sprite associated with samurai mac over here on the left so
we need to make sure that we add take hit and two sprites specifically for samurai mac so to do this
we'll go over to index.js and find where we are creating our player which is basically samurai mac
it's going to be right here on line 29 for me and we want to head into our sprites object we're
going to be adding in a new sprite so we can just go ahead and copy one of these properties and then
we're going to paste in a duplicate but we don't want to create a spray of attack 1 but rather
take it make sure this is spelled exactly the same as it was within our enemy right down here which
it is so we'll scroll on back up and say that our image source for take hit for samurai mac
is going to be in our samurai mac folder that is great and we want to go ahead and select either
take hit white silhouette or just take it let's go ahead and look at these if we look at take hit
you're going to notice samurai mac goes backwards a little bit when he gets hit but the white
silhouette we have samurai mac getting this white silhouette laid on top of him and i would actually
prefer this version simply because it shows better that he has been hit it's kind of like a hidden
animation where the player flashes once they've been hit it just indicates better that they've
been hit so we want to go ahead and use this version instead of just a normal take hit png
so for our image source we're going to say we want to reference inside of our samurai mac folder
take space hit capital h on this one we're going to add a space and a dash and then another space
and then white silhouette and i have trouble spelling that so i'm going to need to look at it
silhouette dot png so just make sure this matches what you have over here and then we need to
determine how many frames we have in here so we saw that had not six frames but rather four so
let's go ahead and save that and then refresh and now if we try to move we're able to move once more
if i go ahead and use our space bar you're going to see that now we have that react
animation in place for kenji let's go ahead and attack samurai mac with kenji instead
you're going to see we do have an issue here with samurai mac not reacting
why is he not reacting well because when samurai mac gets hit we need to activate that take
hit method right now that is not happening so let's go ahead and make it happen to do this we're
going to go scroll on down back to our animation loop and we'll keep on going until we find our
collision detection this is where our enemy gets hit but right here above this if statement this
is where our player gets hit so we know inside of here we want to call player dot take hit that's
going to automatically subtract from our player health so we don't need this anymore right here
now if we save that and refresh with take kit in place and we attack samurai mac you're going to
see now we have that hit animation in place move them out a little bit so we can see it better
and that looks really cool for being attacked so great we have react animations for when both
of our characters get attacked so over in to do we can now check off the receive hit animation
so now let's go ahead and take care of the death animation that's supposed to occur when our health
bar reaches zero so the first thing we're going to do to add in any new sprite is find where we have
our constructors for both our player and our enemy we're going to do this in both spots early on just
so we don't have any bugs as we proceed so right up here i'm on 29 this is where we're creating our
player sprite i want to go into our sprites object and i'm going to add in a new property and this is
going to be called it's going to call this death so this is going to be equal to an image source
any frames max i'm going to go ahead and grab this from take it paste it into death and i want to say
the image source of our death is going to be for samurai mack to simply death with a capital d
so instead of take hit white silhouette we're going to go ahead and get rid of that
and say we're referencing death dot png how many frames is our death let's go and select it
it's going to be one two three four five six frames so let's go back to index.js
and change our frames max equal to six now we can go ahead and take this death object copy it from
our player go inside of kenji's sprites object right here and at the end of take hit add in a
comma and then this new death object but we know we don't want the same death for samurai mag we
want one that's referenced from our kenji folder that's going to be death capital d dot png as well
how many frames is this it's going to be one two three four five six seven it looks like so back
within index.js we could say our frame's max is equal to seven for when kenji dies now whenever
we add in a new sprite right here we need to go over to classes.js and focus on our switch sprite
method we need to add in a new case so i'm going to copy the take hit case paste it down below and
the case of death is going to go ahead and switch our image over to the sprite of death in all these
locations and it's going to change our frame's max equal to the max amount of frames associated with
this death animation so when should we actually switch to a sprite of death well we can actually
do this whenever we go ahead and take a hit after we subtract 20 from our health we can
go ahead and say if this dot health is less than or equal to zero that means we know we're dead
well we can go ahead and call this dot switch sprite specifically over to the death sprite
else we can go ahead and switch our sprite over to take hit so we're going to go ahead and paste
that within our else image right here now similar to take hit and when we actually launch an attack
we need to make sure that our death animation does not allow anything to override it as a result
we're going to go into switch sprite and none of these animations should run as long as our death
animation is activated we should never be able to come back to life unless we refresh the game
so in here we're going to say if this dot image is currently equal to this dot sprites dot death
dot image then we're going to go ahead and just return we're not allowed to run any other code so
we're going to save this and refresh we'll start beating up on kenji over here eventually when he
goes ahead and hits a zero for his health you're going to see that we activate that death animation
now it's just running over and over again because even when we hit the ground our frame is resetting
back to zero once it resets back to zero well it just runs the animation even if the sprite sheet
is currently overriding everything so really all we need now is a property that declares our player
dead and if they are dead well we are not going to call what well animate frames anymore because
that's what's responsible for creating this kind of movement we don't want any more movement as
soon as they hit the ground so for our fighters we're going to add in a new property called this
dot dead by default it's going to be equal to false and then what we can say is if this dot
dead is not true so we are not dead then we want to continue animating our frames so now we just
need to determine the location in which we set this dot dead equal to true and that's going to
be down here within this if statement that we just wrote so let's wrap this in curly brackets like so
so we can write multiple lines of code within this and we want to say if this dot frames current is
equal to this dot sprites dot death dot frames max -1 then we'll set this dot dead is equal to
true our fighter has officially died how sad so let's refresh and then we're going to go ahead
and beat up kenji some more and once you hit zero you're going to see that death animation activates
we can still move around a little bit that's okay for the time being but let's go ahead and
test whether or not samurai max death animation is in place correctly so we're going to go ahead
and beat up on him and eventually when he hit zero hit seems to be in the correct spot too although
he can move around as well so the last thing we'll do here for our death animation is make sure that
we can't move or jump around like this even if one of our fighters is dead and we can do that within
index.js specifically at the bottom of our file where we write out our event listeners so within
key down we can write an if statement that says if our player is not dead so we need to preface
this with an exclamation point then we want to be able to run the following switch case statements
which activate player movement jumps and attacks but if our player is dead well the enemy should
still be able to jump around and celebrate a little bit so we basically need to split up
the switch case statement right here so that our cases for our enemy are in a separate switch case
so i'm going to go ahead and grab these last four case statements and then beneath the switch i'll
add in a new one and say when event dot key has the following cases which i'm going to paste in
then we want the enemy to be able to attack and move so if our player is not dead we're going
to go ahead and activate this switch right here but if our enemy is not dead preface by
an exclamation point then we want to be able to call the following switch case right here as well
so we'll add that in save go back to our game and refresh and now we go ahead and beat up kenji
bring it back down to zero we can no longer move on kenji when i'm pressing any of the arrow keys
and we can test this with samurai mag as well when i go ahead and bring him back down to zero
now he falls and i can't really move around at all pressing any of the arrow keys but i can still
move with kenji so with that we can go ahead and check off our death animation so we're going to go
ahead and work on interface design and animation next so basically what this means is we want to
go ahead and make this up here our health bar and our timer look a lot better make it mesh into our
game to make it seem like it's part of that rather than something that's just thrown on there so the
first thing i want to do is change this yellow to red because that is going to represent the amount
of health we have left kind of represents blood i would suppose but you typically
see that within fighting games is the further health bar goes down the more red it becomes
so let's go ahead and do that first in order to do this we're going to go into index.html and we're
going to find where we have our player and our enemy health let's go ahead and start with player
health first so we know right here we have a background color of yellow this is our background
bar we just go ahead and change this to something like red refresh and then we start hitting samurai
mac you're going to see that now that is red that is more representative of health that is left
we need to do the same thing for kenji's health as well though so we'll scroll on down until we
find enemy health and wherever we have yellow it's going to be right here we're going to change that
to red save and refresh that and now when we hit kenji that is red as well so that's looking great
but now i kind of want to change this blue color to something more purple just so it meshes in with
the purple that we have within our game so if i need a good place to choose a certain color what
i like doing is i like opening up a new tab and searching for tailwind color palette so tailwind
is a css framework but with it comes a lot of great color palettes that we can use within our
game so this first result right here is going to be tailwindcolor.com and if we click on that
you're going to see that we have all these different colors that we can use within our game
so i kind of want something that's purplish i'm going to go to indigo and let's go ahead
and choose about 400 i'm just going to click on this and what this does is is it stores a hex code
to our clipboard so where we have a background in blue for enemy health let's get rid of that
paste it in and the hex code is going to be 818 cf8 this is just a hex code representation of
that color indigo so if we save this go back to our game and refresh you're going to see that now
we have it indigo color bar i think that meshes in with our background a lot better we hit kenji
we still have that red so i really like where this is going it's going to make our blue over
here that indigo color as well we're going to copy this hex code to make sure we still have it in our
clipboard and then find where we have a background in blue specifically for our player health and
it's going to be right here we can replace that with the hex code save and refresh and that's
already looking a lot better now the square up here takes up a lot of space and i don't really
think it makes sense to keep it red because that's really directing our eyes towards that the timer
is important but it's not that important it's not the main thing we should be looking at so we want
to go ahead and detract the user's eye from this we can go ahead and darken this to something like
black or gray we're just going to go ahead and use black here so let's go ahead and find our timer
and where we have a background color of red we're going to switch this over to black so we do that
save and refresh and now our eyes are definitely not attracted to that as much let's go ahead and
make this smaller to further de-emphasize this location we're going to decrease the height of
this let's make it to around 50 pixels and now that's even less apparent which is great but we
can't see our timer inside of it because the timer has a text color of black as well so on top of the
same div we'll add in a style of color say that our color should be equal to white so i'm gonna
refresh that now we can see our timer and this is already looking much better than what we had prior
but we can still take it a step further to really give it a nice look so i think our health bars
would look good with some sort of border around them same thing with our timer in the middle so if
we wanted to go ahead and add a border we would go over to our player health bar and find this parent
div right here so we're going to add in a style of border and this is going to take the width of the
border we want to say around 4 pixels it's going to be what kind of border do we want to use is
it going to be solid is it going to be dashed we pretty much always want to use a solid border then
we want to go ahead and choose the color of the border i'm going to go ahead and make this white
so we save that and refresh we do have a white border around this bar but you'll see it kind of
threw things off a bit now our red bar is below our indigo bar up here we want to make sure that
the indigo bar is always on top of this red bar so what we can do is for this parent to do we're
currently assigning it a height of 30 pixels but it doesn't really make sense to do that
since our child div right here already has a height of 30 pixels this parent div is always
going to be the height of whatever is inside of it as long as it does not have a position of absolute
so we're saying that the parent div right here should be the height of this div because
it is the one div that does not contain position absolute so we'll get rid of height 30 right here
save and refresh and that automatically fixes that issue i go ahead and hit samurai mac we still get
the same effect everything is looking great so now let's go ahead and add a border to our timer
as well if we want to add the same border we can simply copy that style find our container
for our timer it's going to be right here paste in that same border style save and refresh and
now that has a border as well let's go ahead and add a border for enemy health bar over here
our enemy health is right here and we want to add this on the parent div so we're going to add it
right here at the end of our enemy health parent div we go and save and refresh that
and we get the same issue here because our parent div currently has a height of 30 pixels
we're going to make our parent divs height dependent on this div right here so we can get rid
of height equal to 30 pixels saving a refresh and that fixes that as well now with our
borders it looks a little silly for us to have a border on the right side here of our health bar
when we already have a border on the left hand side here of our timer instead of having two
borders touch each other let's go ahead and make sure that we only have one border there
so to do this we're going to go ahead and find playerhealth right where we added that border
now we don't want to just say we want a border on all four sides and that's what the border
property does it says add a border on the top left bottom and right sides of this container instead
what we're going to do is say we want a border on the top i'm going to duplicate this style
say i also want a border on the left i'm going to duplicate this paste it in and then say i want a
border at the bottom as well so now we don't have a border right property here and that is perfect
because if we refresh now we have only one border right here on the left hand side of our timer it
looks a lot better we're going to want to do the same thing for enemy health bar over here
so let's find our enemy health bar it's going to be down here and we currently have one border set
to all four sides to be four pixels solid and white let's say we only want this to apply on
the border top i'm going to copy this right here add in a semicolon paste it in again say
now i want this on border bottom as well and then finally i want to add in one more border on the
right side so when i add in border right save and refresh and now that fixes that issue right here
so this is already looking pretty great one more thing i would want to change here is
the font of this text this is just the default font that comes with your computer at the moment
but i think it would look a lot better if we actually use some sort of 8-bit text so how do we
actually go ahead and change this to some sort of 8-bit font well if i ever want some sort of free
font to use on either personal or commercial projects i like searching for google font
we're just going to go ahead and click the first result right here at fonts.google.com
so this is going to give us a list of free fonts that we can use within our project
and the font we're going to want to use is called press start so if i type that up here it's going
to filter out the fonts and this is the one we want you'll see this is a nice 8-bit font that
would be perfect for our game so we're going to go ahead and click this this is going to bring
us inside that direct font what we want to do is click select this style right here this is going
to open up a tab on the right hand side and what we want to do is copy these link tags right here
if i go ahead and copy all these with command c head back to our project and then within
index.html scroll to the very top right above our head tag i want to go ahead and paste these on
and you'll see this consists of three link tags that reference google fonts and specifically
our press start font so now back within google fonts if we scroll down a little further on this
right-hand sidebar they'll give us some css rules in regards to how we can use this font so to use
this we can copy this line down here go back to index.html and say what elements do we want to
use as font within our css well we know right here we're selecting all elements with this asterisk
so we can just go ahead and paste in font family is equal to press start 2p and now this is going
to work because we're actually pulling the font in before we actually call this style
so if we save this and then go back to our game and refresh now we have that really cool font
in place where we have that 8-bit styling you can see even when we get rid of kenji or samurai mac
we have that font in place as well so great now i think the very last thing i would do
to finish up this game is add a little bit of contrast between our players in the background
because even though we do have a good amount of contrast we can still see kenji in front of the
shop it wouldn't make it easier to see him if we added a white overlay behind kenji and samurai
mac and on top of our background layer just so we can really see our players and not have any
issue in regards to where kenji or samurai mac is at any point in time so to add that layer we
don't actually need to add in any image we can do this directly within index.js we're going to
scroll on up to our animation loop we're going to find where we're currently drawing out our
players it's going to be right here for our enemy for our player for our shop and for our background
so if we say right after we update our shop we want to call c dot fill rect specify we want this
at the x coordinate of zero the y coordinate is zero and we want this to fill up our whole canvas
with a canvas width and canvas height as our last argument and right before this we declare a c dot
fill style equal to rgba and specify that our red is going to be 255 our green is going to be 255
and that our blue is going to be 255. this last value right here is going to be the alpha value
so if we use 255 for all three colors right here red green and blue that's going to give us a color
of white that's how colors work if we mix those three together at full strength it's going to
give us a color of white but for this last value of alpha this is going to determine the opacity of
this white so if we bring this down to something like point 1 save and then refresh you're going to
see that our background just faded out a bit with that white overlay on top of it it becomes even
more apparent if we increase this alpha value to something like 0.7 save and refresh now we really
have that white opacity in place and we really see our players but it just looks kind of silly
at this point to go this drastic so i think a good medium for this game is going to be point 15
save and refresh that so now we do have a white overlay but it helps our player contrast from
things like the shop a bit better than it was prior so i think this is a good addition to
our game to really make sure that we can see our players overlaid on top of this background
with colors that might not contrast as well together now the very last thing i want to do here
to add a little more pizzazz to the game is that when samurai mac or kenji attack each other i want
this health bar to animate downwards rather than it being so drastic and sudden so to get
this to animate we're going to do one more google search and this is going to be a google search for
dsap cdn so gsap is an animation library it's pretty much the go to for any project on the web
and we want to go ahead and click cdnjs.com this is pretty much always available to us and a cdn is
just a link that we can grab from the internet and directly insert that library into our game
it's super easy to do which is why we're doing it so we want to make sure that our version right
here is 3.9.1 we're going to grab this first link by clicking on copy script tag right here
so we'll click on that and then if we want to import this we'll head on over to index.html
we don't want to insert this within our head tag because typically scripts go at the bottom
of your file so we can say right above our custom scripts we want to paste in that script we copied
and by doing that we're going to import gsap into our project so to make use of gsap we want to find
where we are actually decreasing this health bar right here and it's going to be within index.js
where we are selecting a specific element so you'll see this is where we're selecting that with
document.query selector for our enemy health we're not going to decrease our enemy health this way
but rather the gsap way so make sure that you have index.html saved with that new gsat file pulled in
and once it's saved and pulled in you can now reference it with gsap and use a method like two
so the first argument for two is going to be the element you want to animate what is the element
we want to animate what's going to be enemy health the same thing that we have right here
the second argument in usap.2 is going to be what do you actually want to animate well we want to
animate the width so we're going to add in a width property right here and to what value do we want
to animate this to well our new enemy health with a percentage sign so we can copy that paste
it into gsab.2 and now we can get rid of this document.queryselector which sets our width let's
delete that save and then refresh and then when we hit kenji we should see this animate downwards
now that definitely does animate downwards it's a lot smoother than that drawing animation that we
had before but all we need to do now is make sure that it occurs whenever we hit samurai mac as well
we can just simply copy gsap.2 and find where we are selecting our player health it's going
to be right here we're going to paste in what we just copied and then swap out enemy health right
here for player health instead and now we can go ahead and get rid of this document.queryselector
the last thing we want to do is make sure that we're not referencing our enemy health
but rather replay our health instead save and refresh that and now when we hit samurai mac
that animates downward as well it's really that simple what we use something like gsap
so i think with this we have a complete game in which we have two characters that can jump around
attack each other and then get their health bars down to zero and eventually when one hits zero
we have a winner the first player cannot win we can still move around and then we can start
a new game by refreshing to take this to the next level you'd probably want to have more characters
you probably want a restart button but i think this is a really good base version of this game
to show you exactly how a fighter would work with attack boxes animations and collisions so
with that we're going to be able to check off interface design and animation so the very last
thing we're going to do is push our project live to the web so you and your friends can
play it live so how would i go about doing this while we're going to go ahead and use a platform
called nutlify simply because we can push it up to the web for free under one of their unique
urls so to begin doing this we do need to know a little bit about github so i do recommend watching
some sort of basic github video but i'm still going to walk you through the entire process
so we need to go ahead and create a git repo to do this we're going to go on over to github.com
and once you're here you want to make sure that you have an account and that you are logged in
as soon as you log in you're going to be redirected to a dashboard like this you can
go ahead and hit new to create a new repository which is basically a new folder in which your
game exists it's just going to be stored within github on the web so once you're here you want
to create a repository name we know our game is called fighting bash game we don't really need
to do anything else in regards to description we can make this a private repository meaning no one
can see our code so it's going to do that and then if we scroll down we want to make sure that we can
create a repository and sometimes we just need to make sure that we reselect this that github knows
yes this is available of course it is and then we can go ahead and hit create repository so that's
going to go ahead and create the location in which we want to store our game online and now what we
need to do is activate a few commands within our terminal so i'm going to copy these lines right
here and then i want to open up my terminal on mac so if you're a windows user you're going to
open up powershell and you should be presented with something similar to what we have right now
right now we have a squiggly which just means we're within our home directory on our computer
and this is just a one to one representation of our finder you'll see right here if i list out
the contents of the squiggly or home directory the contents of this directory are the exact same as
the content within my home directory within finder these folders over here match up with the folders
listed out within this directory so we want to change our directory within terminal to where we
have our game and we can do this pretty easily we want to search for our game within finder
i'm going to go to web and then find fighting game right here so once we find this directory
we want to type cd into our terminal which means change directory and then what we can do is drag
this folder on top of that cd within our terminal and this is where our game is currently located
so if we cd into this now we are currently within our fighting game so now what you would want to
do is paste in all that code and then hit enter and it might ask you a few prompts such as what
is your github username and what is your password if you just set this up just go ahead and enter
those in i promise it's safe and it's going to go ahead and push that up to your git repo the reason
i am not inserting this is because i already had a git running within our game for tutorial purposes
so if you already had to get running within your game you just want to select these other commands
so i'm going to go ahead and grab those paste those in and that's going to go ahead and push
everything up to github so once this finishes running i can go back to github and refresh
and you're going to see our game has officially been uploaded to github and this is really all
we need to do to start getting our game live on the web so once that's in place we want to
open up a new tab and then we're going to go to netlify.com so nullify is going to host our game
and if you're new you're going to want to sign up it's completely free i already have an account so
i'm going to go to login i'm going to log in with my github account so that's going to take me to
my team which is reserver and that is pretty much my company in which i manage clients i'm going to
go ahead and push this site up to this as well i'm going to go over to the sites tab and once
i'm here i want to go over to add new site and i'm going to import from an existing project
so whether or not you have a team already you should eventually come to this screen
and you're going to want to go ahead and connect to your git provider our git provider is going
to be github so we'll select that and now if it's going to ask you for authorization
so if you're not automatically redirected back you can simply exit out of this tab and you'll see now
we are currently authorized so i authorized all my repos to be available within netlify so i'm going
to go ahead and search for my repos specifically for fighting dash game you're going to see there
it is we want to go ahead and click on this and then this is going to ask us for a few settings to
get this set up and deployed so the owner is going to be our team name that's reserved that's totally
fine which branch we want to deploy well we only have one branch associated with our project which
is main you don't really have to worry about this too much just go ahead and select main right here
and then it's going to ask for build settings so if you're using a site generator such as veet or
webpack or something to build your project then you would go ahead and specify where is the output
directory right here we're not really using that so we don't really need to do anything right here
we don't need a base directory we don't need a build command we don't need a publish directory
we're just going to hit deploy site with all that that's going to begin deploying our site
from github so whenever you push changes up to github nullify is going to make note of those
changes and automatically update your site on their platform so after about a minute or two
if this is not updated automatically you can always refresh with the command r you're going
to see as soon as i refresh while our site has already been deployed and you can see a preview of
it right here so perfect so this is the url they gave us we're going to go ahead and click on that
and now our site is live on the web at that exact url and our game works exactly as it
did before because we pushed everything up with github keeping our code the exact same
so that's pretty much all we need to do to get this live on the web one more thing you could do
to make this a little better is change this domain right here so if we go over to domain settings we
have the ability to add in a custom domain and a custom domain is something like chriscourses.com
that is the root domain if you don't want to use nullify.app you would go here and add a custom
domain but to keep this as simple as possible we're just going to go ahead and change the
sub domain name right here i'm going to go to options and then edit site name so now we can
edit this to something that makes more sense such as chris courses fighting game obviously that's a
lot easier to read than whatever nonsense they put in there by default so now i can save this
and now when i visit chris corso's dash fighting game at netlify.app i have a game in which i can
play live on the web for completely free so finally that's going to allow us to check off
pushing live so that's going to be it for this one folks and i hope to see you in the next one
you