welcome everyone this is another chris
chorus with your host chris and today
we're going to be coding
[Music]
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
[Music]
you