hey guys my name is frank i'm starting a
series on how to program a tile-based
platforming game called rabbit trap it
will feature tile-based collision
detection and response scrolling maps
loading levels sprite animation and
interactive game objects in this first
part of the series i'll be talking about
how to build a strong foundation for the
game the concepts i'm going to explain
are strongly rooted in object-oriented
programming and can be used in any
program to improve organization and
modularity this might seem boring but if
you use this approach it can save you
hours of editing and frustration and
leave you more time to focus on fun
stuff like level design and graphics so
be sure to watch this video
in this video i'm going to talk about
the model view controller approach to
organizing a program and how the
different components of this example
work together in the main js file
then i'm going to talk about how this
structure increases maintainability and
modularity as always feel free to use
the comments section and be sure to
check out the links to the source code
and working example in the video
description and if you learned something
give this video a like
so basically what i have here is just an
example of a model view controller
architecture where you separate out your
game logic from your display logic and
you also separate out your controller
logic so i have my game logic stored in
the game class the display logic in the
display class and the controller logic
in the controller class
and each one of these handles its own
business and it's totally separate from
the other so i'm not going to run into
any issues with having
references to the game logic inside of
the display i'm not going to have the
controller logic referenced inside of
the game i'm going to have all these
different components interact with each
other through their public methods
inside of the main js file context
and by the way each one of these classes
is defined in its own individual file
you don't need to have your own
individual files but it makes it a lot
easier to just
use these different things in other
applications if i choose to for example
the engine i might want to use this
fixed time step engine inside of another
application at some point so it's nice
to just store it in its own file but
anyway what all this code does
for this example is basically the game
class controls color value
right here that's the color
variable from the game class basically
it just increments the different red
green and blue channels inside of a
color value to change these different
colors that you're seeing on the screen
and then it will talk to the display
class which governs things like the
canvas and resizing the canvas when the
screen resizes and rendering and the
game will hand a color value to the
display and the display will render it
on every frame
and the engine takes care of frames as
for the controller i didn't really have
anything cool to do with the controller
for this example so all it does is take
user input from the keyboard and tell
the user which key
he or she pressed so for example i just
press the a key that's key 65.
so
basically what i'm trying to say is i
want to keep things as organized as
possible for this rabbit trap game and i
want you guys to kind of think about
organization of code before you start
developing a game because if you just
jump into things and try to mesh all
this together in one big file with
references going between different
components
it's going to get very messy very fast
and here's an example of that that i
want to show you so i define all my
components i define my engine it's going
to run at 30 frames per second
and i'm handing in the render and update
function down at the bottom of my
main.js file i'm going to start my
engine and that's going to execute the
render and update function 30 times per
second until i stop my game engine
so the render and update functions i
define up here and these are them right
here so the update function is just
going to tell the game
to change that color value and that's
what the update function of the game
does just increments this color value in
a random direction gradually to change
the color
now the render function is also going to
be called on every frame of my game loop
and inside i'm actually going to be
communicating the game's color value
to the display and i'm going to have the
display object draw that color value to
the on-screen canvas
so here is a great example of why this
is so good
so i could just as easily write object
literals to govern my display logic and
my game logic and you've seen that if
you've you've watched my other tutorials
i'm kind of sloppy i just throw stuff
together with object literals here i'm
not doing that if i had written object
literals i could put a reference to
game.color directly inside of the
display's render color function or
better yet i probably wouldn't have even
had a render color function i would just
have a render method that handled
rendering the entire thing the reason i
have two here is because render color
draws a color to a buffer canvas and
then display.render
renders that buffer canvas to the final
on-screen canvas that you see so the old
version of how i wrote my code
or just the sloppy way that i write my
code would just be to put two object
literals on the
main js file and one would be display
one would be game and i would have a
reference to game.color inside of my
render function and display would just
draw that color
directly to the canvas
now the reason this is bad is because
say i want to change the name of my
color variable to hue
if i go ahead and i have a reference to
game.color inside of my display
and i change the variable color to hue
inside of my game object now all of a
sudden i'm editing my game
class or my game object to change that
value to hue
and i have to go into my display object
and change all the references to
game.color to game.hue
now that's a pain i don't want to have
to do that and it's unnecessary so i
don't see why i do it anyway
with this method the mvc approach you
don't actually have to
have any internal references to any
other components the display only has
references to itself inside of itself
the game only has references to things
that it controls
so how do they communicate they
communicate just like this they
communicate through public methods so
display can only communicate with other
objects like game and controller through
public methods that it has so if i come
into the display object here and i take
a look at render color you can see that
just takes a color value and inside of
it it does exactly what i said it just
changes the buffer's fill style to the
specified color and draws that color to
the buffer canvas and then here's the
render function and all this is going to
do is draw
the buffer canvas to the final display
canvas
i'm not going to get too much into
detail on that but you get what's going
on here now i could have just as easily
gone like this inside of this function
and said
game.color had i made these object
literals instead of classes
but that's actually really bad practice
because like i said if i change
something inside a game it might break
my display
object and prevent it from working so
that's twice the editing that i'm going
to have to do because i'm going to have
to change all the values in display as
well as all the values in game
so this is just a much cleaner way of
doing things
so basically this is how you want your
different components to interact and
just take a look at this main js file
it's really short everything is super
clean i just have my two
functions here render and update that i
hand into my
game engine
and here i'm defining everything this is
super clean i don't have huge object
literals to take care of just sprawling
out across my my screen here in my
editor and to instantiate everything
it's real simple i just add my event
listeners for the screen resize and the
the keyboard inputs and i just resize my
screen initially so my canvas fits the
screen when i start up and i start my
engine and everything runs the way i
expect it to
so using the mvc approach or just
separating out the different components
of your game into logical groups is a
really great way to keep your code
maintainable and modular and i'm going
to get into why in the next part of this
video
so now i want to talk about how this
approach makes things more modular and
more easy to maintain so
obviously right off the bat it's a lot
more organized you can see that clearly
i have my different
components reference here and
instantiated here in one single line
each rather than having big sprawling
object literals defined and by
separating these things out into their
own classes i have the option of putting
them into their own files which makes
things even more organized because i
could have all of these different
classes
right on top of each other in one big
file
or i could separate them like i did into
their own files and now if i want to
edit the game logic i only have to deal
with
42 lines of code apparently instead of
having to search through one big file so
that's obviously one way that this
technique lends itself to easy
maintainability then there's the other
thing i mentioned where you don't have
internal references to one component
inside of another component and like i
said then
it's a lot easier to just work with
public methods
and have your components communicate via
public methods kind of like is happening
right here in the render function
display is interacting with game through
a public method called render color
rather than having an internal reference
to game.color which would be a lot
harder to maintain because if i change
game.color in the game object i'm going
to have to go through display and edit
all of those references to game.color so
this is another way it lends itself to
maintainability now what about
modularity
okay well i've got a
engine class down here which is
basically a fixed time step engine
now i can use this engine in any
application that i want to and it's very
easy for me to do that because this is a
totally self-contained class that i
store in its own file now i don't have
to store it in its own file but by
storing it in its own file i can very
easily just
reference that single file in another
application and then all of a sudden bam
i have a perfectly good game engine for
a whole nother game and i didn't even
have to write code for it i already had
it on hand
but if i were to have that game engine
integrated into all my other components
it would be a lot harder for me to
extract the the engine components from
say the game logic and that just isn't
very modular the way i have it set up
now is very very modular and it will
save me a lot of time in the future when
i need a game engine object so
sometimes i write my code this way for
most of my tutorials i just throw stuff
together in one file because i want
everything to be there for you guys to
see
up front i don't want to have to bring
things in from other applications but
this is how i would go about writing a
more structured application and that's
what i'm trying to do i'm trying to
write this game rabbit trap and i just
want it to be very structured and i want
everything to go smoothly so using the
mvc approach and separating my game
logic from my display logic and my
controller logic is just going to make
everything go super smooth throughout
this whole process so anyway i hope this
has been a good explanation of how
everything is going to be for this
rabbit trap thing and i hope you guys
are interested in what's going to come
because i expect it to be a really cool
game
before i wrap things up i want to talk
about my html for this
example so i actually am going to do a
whole bunch of parts in this series and
rather than having to upload the sprite
sheet for this example a thousand times
to my github page or however many parts
i have i don't want to upload this
multiple times my github page because i
don't want to waste memory space so i'm
just going to use the same
graphics i'm going to use the same html
file in css file and i'm just going to
write new javascript files as need be so
that's going to keep the memory
footprint on my github page a little bit
smaller for this whole
series that i'm doing so anyway the way
i'm going about that is inside of my
html i'm dynamically
determining which
javascript files to load based on a url
variable specifying the part number so
when i come into my
actual html page here
and i look at my url to the
rabbittrap.html file at the end of it
there is a question mark and a one which
is the part number for this example now
if i wanted to get to part two i would
just come in and type two
i haven't actually made typed or part
two yet
but
that's how you would access part two so
i'm accessing these different parts with
a url variable that is just the part
and i have a default to where if you
don't specify anything
it just brings you to part one so that's
what i'm doing and this big chunk of
code in the middle the middle of my html
file is taking care of that for me so it
just it defines all the sources i'm
gonna use and that's just these files
here it gets the
url variable or that part number from my
url that 01 after the question mark and
then it goes ahead it checks to see if
it's a viable part
if there is no part specified it just
sets it to part one and then it just
loops through and adds a script tag for
every single javascript file
in the
application so i'm always going to have
controller display engine game main and
manifesto is just my script for the
video
and i'm just going to add a new script
for each one of those and i'm going to
edit i'm going to parse together the
url or the source attribute
to match whichever part i'm in
so hopefully that was a good explanation
of how i'm actually getting these things
in and if you had any questions about
why my html was weird like this
that's the reason i'm just trying to
save memory space on my github page so
being cheap but i kind of figured out
this cool little script to just import
uh javascript files based on what part
i'm in so anyway that is an explanation
of that
this part is going to be on adding a
player object to the screen and
controlling him with the keyboard this
is a vital component of any game so stay
tuned to find out how it's done
in this video i'm going to talk about
the example program what it does and how
the program has changed since part one
then i'm going to show you the specific
code that handles creating the player
controlling him and drawing everything
to the screen finally i'm going to show
you my implementation of a fixed
timestep game loop and how it works if
you have any comments or questions post
them and if at any point while you're
watching this video you get the
sensation that you're learning be sure
to support this video with a like
first thing i want to talk about is what
this example actually does and how this
program has changed since part one so
all this example does is allow me to
place a square which represents my
player on the screen and use the
keyboard to make him jump up and down i
also added some stuff in for collision
detection and to make it look nice so he
changes color on every jump
and he leaves a trail the reason he's
leaving a trail is just because i'm
filling the background i'm redrawing the
background on every frame of animation
with a
a slightly transparent
background so that's the reason i'm
getting that trail if i was drawing just
a plain opaque black ground or opaque i
guess some people pronounce it that way
if i was doing that you wouldn't be able
to see that trail behind them but i
thought that was pretty cool and it kind
of helps you visualize the what's going
on in every frame of animation because
each one of those squares that you see
trailing behind him
is drawn on one frame of animation
all right so now that you know what the
program does
let's talk about what has changed since
part one so in part one i had to find my
three different classes my controller my
display and my game i also had my engine
class and my main js file so all these
are updated for part two that's why the
file name has a o2 after it the ones
from part one like engine i haven't
changed since part one that has a part
one
so that's my naming convention that i'm
using really the only thing that i
changed majorly besides the code that
went into making the example work was i
took the event listeners
out of the display
and the controller classes so the key
down up actual event handler function i
hand into the event ad event listener
method in my main
js file i'm actually defining those
inside of my main file now so this would
be one that i moved out the key down up
event listener and the resize event
listener or actually event handlers
that's what these are so if i come all
the way down to the bottom of my main js
file you can see that i'm adding these
event listeners
to the window object and i'm just
handing in
the
methods that i define inside of my
main.js file into these event listeners
so that's one of the changes i made i
decided to make that change because
i didn't think that my
event handling system was really
something i wanted to put inside of my
individual
classes or my individual components and
the reason for that is a lot of times
inside of these i'm going to have to do
interactions with
multiple components of my game so for
example the resize component actually
needs to handle two different components
and have them interact it needs the
display component which handles drawing
everything to the screen and all my
graphics and it also takes information
from the game component which has
information about my
world's height and width and my player
location and stuff like that
so
that's just a little bit about the
example program and what it does and a
few things that have changed since the
last part of this series
all right so now i'm going to talk about
how i define the world and the game
object and this is basically going to
define
the world that my little player square
can run around it and jump in and it's
going to define the player itself that's
going to be just the rectangle that
defines the player as well as the color
and it's going to handle some collision
detection stuff as you can see i can't
fall through the floor and i can't jump
or walk through the walls so all of this
is going to be handled inside of my game
logic so i'm going to come into the game
part 2 file
and take a look at my game class
but i'm going to keep it expanded so we
could actually look at the code all
right so the first thing i'm defining in
here is a
object literal called world so inside of
my game class
i'm going to have access to this world
object and inside of this i'm just going
to have my background color
and by the way this is that transparent
color so if i come in here and i just uh
change this to something like
zero zero zero zero zero zero that's
gonna be the color for black if i come
in there and save it and then refresh my
screen now i'm no longer going to have
that trailing
graphic
behind my player whenever he jumps
but if i come back in here and change it
back ctrl z a bunch of times get rid of
that and that and save and come back
here
now all of a sudden i get my trailing
graphics behind my player whenever he
jumps in it looks like he has just a
cool trail of fading graphics behind him
so that's pretty cool and it's really
really easy to implement all you got to
do is draw this
semi-transparent background color
to erase your canvas on each frame of
animation so anyway
to get back to the world object i just
want to make a side note of this and how
i did that color trailing feature the
world is just going to have everything
to do with the world so friction and
gravity are going to be defined here the
player is going to be defined here later
on i'm going to define other objects
that are going to be in-game objects
they're going to be defined here the
world boundaries so the height and width
of our level are going to be defined
here if i were to change this let's say
i want to make the height something like
200 and have a really tall screen if i
do that and come here and refresh the
screen now you can see that
i have a really really tall game world
and
that looks kind of stupid so
we're going to change it back
save refresh and now i'm back to my
normal size but basically the world
object just holds everything to do
with the game world including stuff like
collision so this collide object
function is just going to take an object
parameter and for now that's just going
to be handled inside of our game loop on
every update and i'm going to pass clyde
object the player object that we're
defining i'm going to get to that class
later and basically it's just going to
test c is the object
to the left of zero so that's going to
be the far left of our screen and is he
beyond the right side of the screen is
he
above the top of the screen is he below
the bottom of the screen it's just going
to set him to where he needs to be and
handle collision with the boundaries of
our rectangular world here
so pretty simple stuff everything in
this example is actually really basic
take a look at the source code i have it
linked in the description
here i have the update function
now this is actually going to update
everything to do with our world so the
player is going to have gravity added to
his y velocity on every frame this
function is going to be called on every
frame of animation inside of the game
loop
the player has his own update function
and if i come down to the player object
down here we could take a look at it
see what we got here update it just adds
his x and y velocity to his current x
and y position
go back up see what else we got here
so we're going to update the player
we're going to add some gravity to his y
velocity we're going to add friction or
we're going to reduce his x and y
velocities by the amount we defined in
friction which is up here
0.09 it's just a simple pseudo-physics
way to
employ friction in your game then we
have this dot clyde object this stop
player and this is referring to
the world object
that we are talking about
so that's a really simple world object
it just governs everything to do with
the world the dimensions the player the
colors that you're seeing in there
and also in our game class we have added
or i have added rather uh the player and
it's a simple class it's
uh using dot syntax to kind of add this
player class to the game class and
that's kind of just a way to keep things
organized and almost like name space in
there it's not real name spacing but
by doing this i'm not going to have a
a global class called player
instead i'm going to have to reference
it with game dot
player like that so if i have a bunch of
classes that i'm throwing into an
external context say your game is going
to run on another website and it's going
to be part of the global scope of that
website you don't want your classes and
stuff to be just floating around with
all the other variable names and class
names that other developers have defined
so it's good to try to abstract out your
own class names and variable names and
do stuff like put them into anonymous
functions just to keep your code
separated from everybody else's code out
there on different websites
but anyway that's besides the point we
define our player class here he has a
color he has a height he has a width he
has x and y velocities he has a value
for jumping to determine whether or not
he's jumping and he's in the air if he's
standing on the ground we also have his
x and y position and since i'm just
being lazy and i'm not loading him in
from a level map i'm just going to
define his
values all right at the start here when
the player object is instantiate
instantiated with the new operator
so
now i go into the prototype and i have a
couple different functions that govern
govern how he moves i have the jump
function
uh basically just says if he's not
jumping
then we're gonna change the color and
we're gonna make him jump down here so
pretty simple this is the code to get a
random color
and i'm not really gonna go into that
but basically it just makes his color
change every time he jumps every time i
press the up arrow on my keyboard
the jump function is called on the
player and this code runs pretty simple
same thing for the move left and move
right functions these functions are
going to be called in my main javascript
file i'm going to take a look at that in
a second and all it does is just add
half a pixel to his x and y or x
velocity depending on which button you
press if i press left i'm going to
subtract 0.5 pixels from his x velocity
if i
press right on my keyboard i'm going to
add 0.5 pixels to his x velocity and
then finally that update function that's
just going to add his x and y velocity
to his x and y locations in the canvas
respectively so now let's let's take a
look inside of the main js file and
see where all of these are being
employed which is going to be inside of
the update function
so the reason i have my
update functions all over the place i
have one for my player i have one for my
world and i have one in my main
javascript file is because
i'm doing different things inside of all
of them and i want to keep all of my
objects as self-contained as possible so
for instance
uh the
player object his update function is
really simple
it just handles stuff that has to do
with the player my world's update
function only handles stuff to do with
the world so
this.world.update is going to be this
function right here the world's update
function only has to do with things
inside of the world
the main javascripts file
javascript file has an update function
that handles
the controller
as well as the game so i'm mixing these
two major components of my game's logic
inside of this one method inside of my
main.js file and that's kind of where i
want everything to communicate i don't
want to have those internal references
pointing to other components inside of
my game i want all of my code to be
very self-contained and when i have it
interact with other components inside of
my code i want it to be in a safe
context kind of like the main js file
that's where i'm going to do most of my
editing
so anyway
i'm getting information from the
controller i'm just saying is the
controller being pressed are these keys
active on the keyboard and if so i'm
going to execute a corresponding
function function on my player object
finally i'm going to call game.update
and game.update is going to go ahead and
call
world.update world.update is going to
call all this stuff
and that's going to give me these nice
cool physics and take care of all my
numbers and player position and velocity
and whether or not he's colliding and
that's going to take care of all of the
physics logic in my game it's also going
to change the player color
alright so now i just talked about what
actually makes the game logic work and
that is of course the game class itself
stored in the game o2 file so now i have
to talk about how i'm getting
keyboard input and relaying that to the
game class so it can actually take that
input and do something with it so i just
showed you inside the main
file here that i'm i'm conveying the
keyboard's input via the controller
object to
the game object and telling the game
object to do something with the player's
position like move left move right or
jump
and that's all going to happen depending
on what the controller object is doing
so let's take a look at the controller
class and see how that works
so the controller class just has three
objects here a left right and up object
and those objects are going to be
controller dot button input classes so
let's take a look at the button input
class and see what it is it's really
really simple all it is is an object
that has two
boolean values inside of it one called
active and one called down now active is
gonna hold the virtual state of our
button
so
i'll get into that in a little bit
because it has to do with jumping and
down is going to refer to the physical
state of our button on the keyboard so
if i physically press the up key down
down is going to be true and if i hold
that key down it's going to remain true
the active value however is going to
depend more on my actual game's logic so
just remember keep in mind that down
refers to the physical state of the
button on my keyboard and that's what
that is going to track and active is
just going to track
uh what that value is of my button
object inside of my game's code or my
game logic
so now that you know what the button
input class is
these three objects are going to be
button inputs and this key down up event
handler function is going to be called
every time i press a key on my keyboard
whether i press it down or it comes back
up this is going to be called it's going
to check to see what the event type is
key down or key up so when i press a key
down on the keyboard
the type's going to be key down when i
release that key it's going to be key up
and depending on which one it is it's
either going to be true or false and
then i'm just going to use the get input
method of my button input class
and hand in that
down value which is either going to be
true or false
and that's going to look like this it's
just going to say if
the
key
tracker or the
button input object
if that currently is down the state is
currently down
or if the state is not equal to whatever
we're handing in then we're going to set
active equal to whatever we're handing
in and we're just going to set down
equal to whatever we're handing in
because that's going to be the physical
state of the button
pretty
simple maybe not so simple take a look
at the source code and fiddle around
with it because that's really the best
way to get an idea i'm just here running
over everything i'm trying to get it
done quick because this video seems like
it's going to go long i don't want it to
go too long but basically this is a
controller class just takes keyboard
input and i'm adding the event listener
for the controller
component inside not my engine but
inside of my main javascript file at the
bottom if i come all the way to the
bottom you can see i'm adding the key
down and key up listener to the key down
up
function which i'm defining also inside
of my main file and that is just going
to call the controller's key down up
method and hand in the event.type and
the
code which we use to determine
what the type is whether it's a down
press or an up press
and the key code is just going to
determine which key on the keyboard i'm
pressing so 37 38 and 39 are the left up
and right arrow keys on the keyboard
so basically this controller class just
gets keyboard input and then we relay
that input to
the
game component right here in the main js
file
inside of its update function which is
called on every frame of animation
managed by our engine which i'm going to
talk about later on in this video so
really simply just checks to see if the
left right and up keys are active
and then it goes ahead and it calls a
player movement function so move left
move right or jump so where the active
value comes into play here is when the
player is jumping so
notice that i'm actually setting the
virtual state of the controller dot up
button input
to false i'm changing the active value
to false so that's going to give me the
ability to press my key once and hold it
down and not have my player jump again
if i were to come in and comment this
line of code out like this
and just go
like this comment this guy out save my
file come over here to my browser
refresh
now i'm just going to jump up and down
continuously
now this might be desirable for some
people for some games this might be what
you want but for other games you're not
going to want to keep on jumping just
because you have the key pressed down so
if that's something you want in your
game
not having the player jump up and down
continuously as your button is pressed
in
this controller class
right here
and these
button input objects here with this dual
virtual and physical uh button state
tracker
objects here these boolean values
this is going to allow you to prevent
your player from just jumping up and
down continuously and you're going to
get functionality that looks like this
instead you're just going to be able to
jump one time and
only jump when you press the key rather
than jumping just continuously if you
have the key held
down all right so now that you know how
to define the player object and the
world
object in our game class and you know
how to get user input to actually
control this guy and move them around
the screen
the only thing left is how to draw this
guy so how we're drawing the player
object and the world itself to this
canvas element is with the display class
so inside of the display class i just
define a buffer and a context of my
canvas so these are two uh 2d rendering
contexts canvas rendering context
context is the rendering context of the
on-screen canvas that you see on screen
buffer is just an off-screen canvas that
is going to be sized perfectly to match
our world height and width so if we come
back into our game and scroll down here
the buffer canvas is going to be sized
at 72 pixels high and 128 pixels wide
and that is actually going to happen all
the way at the bottom of our main.js
file and the reason for that is just so
everything scales the way it should so
i'm setting that up right here in the
initialization portion of my main.js
file
so let's get back into display and talk
a little bit more about it
so i've added a couple different
functions i have the fill function or
method all it does is take a color and
draw it to the buffer which remembers
the off-screen canvas which is then
drawn by the render function to our
on-screen canvas it draws this
off-screen buffer canvas to the
on-screen
display canvas that you actually see in
the browser window
so the fill method just fills the buffer
with color
render renders that buffer to the screen
draw a rectangle just draws this
rectangle here that's what i'm handing
in in terms of x y width and height and
color
and it just draws that to the buffer as
well i'm actually rounding down the x
and y positions of the rectangle that
i'm handing in this way it doesn't
render it on a half pixel so let's see
what happens when i take this code out
first let's uh take a look at what this
guy actually looks like moving around
the screen
so pretty smooth
nothing weird going on
all the edges look pretty straight if i
come in here and i just put in
x and y though let's take a look and see
if anything changes
as you can see
it looks a little bit funky i mean it's
hard to tell because
i have this background let's actually go
in here and change the background color
of my game to something else here let's
uh let's make it
black instead
zero zero zero zero zero zero that's
going to give me black i'm gonna come in
here refresh my screen
take a look at the player character you
see how his edges are kind of messed up
they're kind of wavering a little bit
kind of looks like he's just fading
around instead of just sitting on the
exact pixel he's meant to sit on well
that is actually because he's sitting on
half pixels from time to time and you
can fix that by rounding down the values
you pass into your draw method so we can
go from this which looks a little bit
funky
to
this
which now looks really sharp and
not so funky at all it's basis basically
the best we can get
on a
html5 canvas so now let me set back my
background color to the way it was
before so we could have that nice
fading effect that follows the character
around refresh my screen
and so that's
what i'm going to use to draw my
rectangle to the screen and round him to
the nearest
full pixel location with math.floor so
he doesn't get that weird blur around
the edges now let's take a look at the
main.js file and that's where all of
these are going to be called actually i
think inside of
actually no i'm wrong let's just take a
look at the main js file and see where
these guys are called
i think it's going to be inside of the
render function i haven't looked at this
code in a little bit
so we have display.fill
and by the way the render function is
going to be called by our game engine
which is our game loop on every frame of
the animation so 30 times every second
so we call display.fill that's going to
fill our background color with this nice
dark gray here we're going to call
drawrectangle and hand in the
game.world.player which is a rectangle
we're going to hand in all those values
as well as the color value
and finally we're going to call
display.render and that's going to draw
the buffer that we just filled with the
background color and drew the rectangle
to and we're going to draw that that
buffer to the final display canvas now
one more thing i want to talk about here
because this is pretty simple stuff is
the resize functionality so the resize
functionality is going to take care of
scaling my on-screen canvas it's also
going to take care of keeping the aspect
ratio of the game world which you
remember has the height and width
coordinates
it's going to keep that aspect ratio
from the game world
and the buffer to the final display
canvas so we get a nice square rectangle
every time so
what's important about that well if we
come down here i told you that we're
going to set our buffers
canvas height and width to the game
world height and width now if i were to
change this and say height times 0.5
obviously that would warp our game a
little bit so let's take a look at that
and what that looks like
oh
kind of cut off half the world but you
can see that when i jump up the player
is actually a lot taller than he is wide
by about twice as much
so
let's set back that that back to normal
and
go ahead and take a look at the resize
function
which i'm adding to the window that
handles all of that stuff so resize is
right here it's going to call
display.resize and it's going to hand in
document.documentelement.clientwith and
klein height it's going to subtract 32
pixels from both of those to give us
this nice 16 pixel margin on either side
of our display canvas which i have to
refresh so it goes back to the way it's
supposed to be so that's what that's
doing those 32 pixels then it's going to
hand in an aspect ratio of our game
world which is going to be just the
height divided by the width of our game
world so now let's take a look inside of
the display
object's resize method and see what it's
actually doing
so here i am inside of the resize method
and as you can see it's not super
complicated it's actually pretty simple
it's basically just going to say if the
height and width ratio that we handed in
from
document.documentelement.com with
incline height minus 32 pixels to give
us that nice 16 pixel margin on each
side it's going to say if that ratio is
greater than the height width ratio of
the world object
the game world
then if that height with if the screen's
height width ratio is greater than the
height width ratio of the world then
we're going to set the canvas's height
to the width times the ratio and we're
going to set the canvas's width to the
width of the screen so right now we have
a max width scenario
otherwise we don't have a max width
scenario we have a max height scenario
and it's going to set the canvas's
height to the max height and it's going
to set the width to the
height divided by the height with ratio
so this code is basically going to allow
me to do
this if i come in here
and i change the scale of my window
as you can see it's always going to keep
it centered right now i have a max
height situation and i have a shorter
width in my game world but the aspect
ratio remains the same
and
here i'm going to go back down somewhere
around here i'm going to change over
from a max height situation to a max
width situation
and now you can see my display canvas
gradually getting smaller in height
so that's pretty cool that's the display
function takes care of resizing the
canvas and maintaining that nice aspect
ratio so our game can scale nicely
across many different devices
alright so now i'm going to do a brief
run through of my fixed time step game
engine and this is the game engine class
it's in the engine file i haven't
changed it since part one of this series
it's exactly the same as it was although
i did add in this accumulated time
variable definition because it wasn't in
here
it was actually being added later right
here so i just fixed that but it's
basically exactly the same
so
what a fixed time step game loop does
is it causes your game to update and
draw
at a fixed rate as time passes and it
does that by taking a time step value
which in this case is going to be 1000
divided by 30 if i come over to my main
js where i actually instantiate this
i am
passing 1000 divided by 30 which is
roughly 33.3
repeating forever and that is going to
be the number of milliseconds that i'm
going to call render and update on so
every 33.33 milliseconds i'm gonna call
render and update
and the render and update functions are
just right here
you've seen them throughout this video
and they're basically just going to
update my game logic
and render the changed game state to the
screen
let's hop back inside of the engine and
talk about this game loop some more
alright so we've got
our time step and that's going to be in
this case about 33.33 milliseconds and
so every 33.33 milliseconds i'm going to
call the update and render function i
passed in they're going to be stored
right here
and i'm going to keep track of how much
time has passed in the accumulated time
variable
so every time
33.33 milliseconds passes hopefully our
our game is updating close to that but
anything that overflows is going to be
stored in accumulated time so let's say
33.33 is our minimum time step and
that's exactly what it is but let's say
uh request animation frame which is what
we're using to update our game logic
fires at 40 milliseconds now we're gonna
have about what is that
seven six something about six
milliseconds left over and we're going
to store that in accumulated time and
when accumulated time reaches our time
step or 33.33
we're going to update or call update one
more time so basically we're storing all
the time that passes in accumulated time
and we're just taking bites out of that
accumulated time we're taking 33
millisecond bytes out of our accumulated
time
the time value is just going to be the
last time our run function executes and
this is just going to be the looping
function this is going to be the
function that loops over and over again
a lot of game engines will call this
cycle
some call it loop i'm just calling my
run because
engines run so this is going to be one
run of the game loop so inside of the
run function
we're adding the current time stamp
that's handed to us by request animation
frame we're
subtracting the current time or the last
time our game executed from the current
time and we're adding that to
accumulated time
so let's say that our the last time our
game executed was at 100 milliseconds
and we're just now getting in a new call
to the run function from request
animation frame and it's going to happen
at
140 milliseconds so we're going to have
140 milliseconds minus 100 milliseconds
and 40 milliseconds is going to go into
accumulated time
so
now we have 40 milliseconds in
accumulated time we're just going to set
the the new
most recent time value to the current
time value but just remember 40
milliseconds in accumulated time here is
where the fixed time step game loop
really shines because this well actually
this is just a safety i'm not going to
talk about but but this is where it
really shines the while
loop
so remember we have 40 milliseconds of
accumulated time
and we have our 33
i'm going to round that down to 33 or 33
milliseconds in our time step
so 40 is greater than 33 so while 40 or
our accumulated time is greater than our
time step we are going to reduce our
accumulated time by the time step we're
going to call update
and we're going to set this updated flag
to true but don't worry about that too
much
so then we're going to loop again and
see if that's true again and we
subtracted 33 from 40 so that's going to
give us
7
and 7 is no longer greater than our time
step so we're not going to update again
but let's say that accumulated time was
equal to 70.
okay so now we have 70. 70 is greater
than 33 so we're going to call update
then we're going to try to loop again
well 70 minus 33 what is that
47 is that accurate anyway 47 is still
going to be greater whatever it is it's
still going to be greater than 33 so
we're going to update again so even if
we didn't have another request animation
frame event fire and we didn't update
the screen again we're still going to be
updating twice on the next time request
animation frame fires and gives us a new
run command or we're going to call run
again so we're going to be keeping up
with time no matter what happens so even
if our game runs really slow and laggy
it's still going to keep up with time
and it's going to run at the same
rate basically on any device regardless
of how slow it is unless the device is
so slow that it just can't handle the
game and then it will crash but that's
that's not something you really should
worry about uh unless your game is
crashing all devices but if your game is
just crashing the you know computers
from
1995 then you shouldn't worry about it
but basically the fixed time step game
loop just says
if too much time has passed or if a
certain amount of time has passed we're
going to update our game at whatever
rate we want it to update until we have
caught up with however much time has
passed and that's a really great
functionality of fixed time step game
loops and it's a great reason to add
them in to any game that you're writing
so now down here we have the updated
flag basically we turn that flag on we
set it to true anytime we do an update
and then if it is true if we have
updated then we're going to call the
render function and that's just going to
draw our game
so
why is this good well let's say
accumulated time only has 20
milliseconds in it but we need 33
milliseconds to justify an update
otherwise we'd be going
faster than we want to update well if
that's the case then this never fires we
never update our game and if we don't
update our game nothing has changed and
anything we draw is just going to be a
waste of cpu or gpu so we don't want to
draw anything that hasn't been updated
or changed so if no update has occurred
update updated stays false
and we don't draw
and finally inside of the run function
we just make another call to the
handlerun method and the handlerun
method is just down here it's just an
arrow function that calls uh the
engine.run method now the reason i'm
using an arrow function is because
if you've worked with event listeners or
request animation frame before the this
keyword inside of
whatever function you hand into
your event listener as your event
handler or request animation frame as
your response to a request animation
frame event firing is going to point to
the object that you request the frame or
add an event listener to so in this case
it's the window so i don't want this to
refer to window
i want this to refer to my actual engine
object so by using this arrow function
i can actually make this refer to my
engine object rather than the window so
that's the only reason i have that kind
of set up as an arrow function there to
make sure that this keyword is referring
to engine instead of window otherwise i
would have to have
a reference to
engine
inside of the engine and that just is
really
it just seems really sloppy to me so i
set up the arrow function and that's
what that does
and anyway i hope that was a good
explanation of a fixed time step
engine
and
probably wasn't the best i was kind of
going through it really fast it's really
cold in this room where i'm recording
and i'm kind of i'm like freezing to
death so
don't hold it against me i should turn
up the heat but
you know just i'm doing what i'm doing
here so hopefully that was a good enough
explanation of a fixed time step game
loop and if not definitely take a look
at the source code i commented
everything in here so you guys can get a
better understanding of the code as you
read through it line by line
in this video i showed you how to lay
the groundwork for any platforming game
so far i've implemented keyboard input
simple platforming physics scaling for
multiple devices and a fixed timestep
game loop to handle updating your game
at a consistent rate no matter what
device it's on which is perhaps the most
important thing you could take away from
this video
i'm going to show you how to draw a
tiled background from a one-dimensional
tile map i'm going to talk about the
example program and what i've added
since part two then i'm going to talk
about how to load the tilesheet image
and store in a tilesheet class finally
i'll show you the tile map in the game
class and how it's drawn
alrighty guys let's take a look at what
has changed since part two if i come
over here in the browser first i'm gonna
real quick i'm gonna go ahead and i'm
gonna pull up part two so you guys can
see it
and that is right here i'm gonna press
enter load up part two
and
this is part two so as you can see i
have some jumping physics i get keyboard
input but there's no tile background and
to make this game i'm definitely going
to need a cool tile background so let's
go over to part three and check out what
we've done there
alright so this is part three
and as you can see it's a lot better i
still have the same
game physics where my character jumps
around and moves around same fluid
physics exact same physics code the only
difference now is the world is a
different size and i have a tile map
inside of it
also the color of the character
is just a solid white and gray the
reason i did that was to more closely
resemble the player sprite we're gonna
be using which is this little rabbit
dude and
basically that's it that's all the
changes that have happened in part three
since part two the files where the
changes occurred are display game and
main
everything else i'm using uh the
controller class from part two
if i come into my directory here i'm
gonna be using the controller class from
part two
and i'm gonna be using that file and i'm
also gonna be using the engine class
from part one
but this is part three and these are the
only three files that you need to worry
about if you've already watched part one
and two so anyway on to the rest of the
video
so the first thing we need to worry
about for this application is how we're
going to get our sprite sheet png image
into our javascript so we can actually
do something with it and have it render
over here on the screen and show up on
the background of our canvas element so
first we need to define some sort of
container for our sprite sheet image and
its different
variables
and we do that inside of the display
class so here's my display class it's
one of the files that has changed since
part two and inside of it
i define a
class called tilesheet i come down to
the bottom here here's my tile sheet
class it's just a really simple object
it has an image inside of it
this image object is going to store our
tile sheet or our sprite sheet
and then it records the tile size and
i'm just going to hand in 16 because
each one of our tiles is 16 by 16 pixels
and the number of columns in our tile
sheet so i think that's eight off top of
my head but if we come over here and we
actually count them
we're gonna have
one two three four five six seven eight
different tiles kind of hard to tell but
there's eight tiles or eight columns
in this map
eight tiles across or eight columns not
just eight tiles in the map obviously
there's more but
so we have to define this tilesheet
class and it's just going to have an
image which is going to be our image
it's going to have the tile size and
it's going to have the number of columns
in our tilesheet image
now that we have this we can actually go
about loading this png image into our
javascript so we can do something with
it where that happens is the main js
file for part three so if i come down to
the bottom of my file here
you can see that
i am
setting the image
of my tilesheet object in the display
class i'm setting the source of that
image to
the rabbittrap.png and that's going to
start loading the rabbittrap png image
here
into the
tilesheet objects image
and when it's done loading it's going to
fire this
event listener for loaded so it's going
to say okay my image just loaded i have
an event listener for that let's call
this function the event handler function
for a load event there i'm going to
resize the screen
that's just going to resize the browser
window or not the browser window but
resize our canvas to fit the browser
window rather and it's going to call
engine.start that's going to start our
game loop off and then we're actually
going to be able to use that graphic
because if we start our engine before
the graphic is fully loaded we're going
to try to draw graphics that just aren't
loaded yet and that's a problem so make
sure that your graphic is fully loaded
with an event listener for load before
you actually start your engine
also down here this extra parameter once
colon true that just tells this event
listener to only fire once and after
it's done it just
junks it
sends it to the trash sends it to
garbage collection we don't have to
worry about removing this event listener
from our tile sheet image because this
parameter here just takes care of it
all right so now that we've loaded our
tile sheet image into our javascript we
actually have to get these individual
images out of this sprite sheet or tile
sheet we have to draw them to different
locations on the canvas to create
something of a tiled map like you see
here
so how do we do that well it starts out
in the game class and i have a
map inside of my game class inside of
the world
and basically it's just a big long array
of values that point to different
locations in the tile sheet so the best
way i can explain this to you is by just
giving you an example and i'm gonna look
down here in the bottom right of my
numeric tile map at these three values 1
43 and 10. now these values correspond
to locations inside of my tile sheet
graphic
and they also correspond to these
locations on the map so this is the one
tile this here is going to be the 43
tile and this
over here is going to be the 10 tile and
as you can see you can kind of make that
connection those three tiles are going
to be in this bottom right hand corner
of the map so now let's take a look at
these tiles inside of the sprite sheet
itself
we're going to have one so that's going
to be for this example it's going to be
at position one in our map normally i
start at zero i start counting at zero
but for this example i'm gonna start
counting at one so
tile one is just going to be this corner
tile and as you can see right here in
the map
it is that corner tile
these two tiles are the same so
tile one is just gonna be this one right
here and if you think about it makes
sense because this is the first tile
index in the map so just go 1 2 3 4 5 6
7 8 9
10
and remember this is tile 10
we have our 10 tile right here
and it's just a plain clear brown tile
and if i come back to my map you can see
that that is in fact valued at tile 10.
so now you kind of understand or
hopefully you understand the correlation
between these values in a
one-dimensional tile map
and
the images on screen
as well as the locations of those images
in the tile sheet image itself but just
because we have the map doesn't mean
we're actually drawing this stuff to the
screen we actually have to write a
function for that and that function is
going to be inside of the display class
and it's a function called draw map
and it's just going to take the map
which is just that array of values so
it's just going to be this i'm going to
hand in
and the number of columns in the map and
we have 12 columns on our map i define
that here 12 columns if you count i
actually have 1 2 3 4 all the way to 12
columns inside of my map if you look at
the screen you can count 12 tiles across
so this draw map function is just going
to take the map and it's going to take
the columns and it's going to loop
through every single value in the map
so it's going to loop through every
single number right here
and it's going to get the value there i
subtract 1 from it and that's going to
if i don't subtract 1 this is what
happens
if i just add 0 let's take a look real
quick and see what happens and i'll show
you a really simple way to remedy this
which i didn't use because i used the
tile map editor to make this because i
have really complex tiles here but this
is what it looks like it's because all
of my tile values are offset by one
now i set it back to negative one the
reason for that is
in my tile map these are all one higher
than they should be so this should
actually be 17
this should be 48 this should be 49
this should be 31.
they're all offset by one that's just
because the tilemap editor i use which
is tiled exports the comma separated
values
uh starting at one instead of zero i
didn't feel like going through and
changing all these so hopefully this
doesn't throw you guys off too much
don't worry about it when you make your
maps just make sure you have the right
value starting at index zero in your
tile sheet so basically instead of this
being one it would be zero and you start
counting from zero
but if you want to use a map editor like
tiled and you don't mind just having
that offset
it's really simple all you have to do is
subtract one from the tile value and
you're good to go so anyway that aside
let's get into how i'm actually placing
those images from the source onto the
buffer and then drawing it on the screen
so i get the different values or i get
the value of the specific tile in the
map that i'm looping over
i get the source
x and y position that i'm going to cut
it out of the tile sheet at
and that's what this code right here
does
it just takes the number of columns in
the tile sheet takes the value
that gets the column and then you
multiply by the tile size
to get the actual position to cut out of
inside of the tile sheet image
oh didn't mean to do that
but that's basically just getting the x
position to start cutting out of uh
come back in here then we have the y
value that's going to get the y position
to start cutting out of and then
when you get the source you're going to
hand in the source x and y which is just
these two values here and the tile
height
and tile width which i just have one of
it's tile size and it's 16 pixels so
source x and source y
are going to get me to the appropriate
tile say i am at tile
8
that's going to put me right here
it would actually be a value of 7 but
that's going to put me right here
and then i'm going to cut 16 pixels wide
and 16 pixels high so the y value would
be 0 the x value would be
128 minus 16 to get me right here to the
left side of this tile and then because
120 is the width of my map and it's just
going to cut this tile out
so pretty simple
come back here display look the rest of
this destination it kind of looks like
the same kind of mathematical formula
i'm just using the number of columns in
my game world which you remember is 12
so that's the number of columns in this
map
and
i'm multiplying that by 16 as well
now i guess i should be using the
game.world
dot tile size but i'm just using 16 for
both so i guess it doesn't really matter
and then finally you're going to use
this information to cut the appropriate
image out of your tilesheet image and
draw it into your buffer which is then
going to be drawn to the final on-screen
canvas so you're just going to say
i want to draw an image to my buffer
from the tile sheet image
and i'm going to cut the image out of
the tile sheet out at source x and
source y
and
tile size width and tile size height i'm
going to draw it to the buffer at
destination x destination y at the
16
by 16 width and height
so that's all that does and then if i
come out here into my main js file and i
come down to the or up rather to the
render function you can see that i'm
calling the
display.drawmap function i'm handing in
the game.world.map
and thegame.world.coms into that
function and that is how
you draw all those tiles to the game
screen
i talked about how to load a sprite
sheet image into your javascript how to
create a tile map array and how to draw
tiles from the sprite sheet to to
display canvas if you're worried that
there was a lot of code i didn't cover
don't all you need to know is how these
basic components work together in order
to build them yourself chances are your
application structure will be different
from mine so don't focus too much on
what i didn't show you and instead try
to build the components i'm talking
about into your own application
this stuff really works and if you need
the source code you can find it on my
github page
i'm going to show you the aspiring game
programmer how to add pixel perfect
professional quality tile-based
collision detection and response to a
platforming game i'm going to talk about
what's changed since part three then i'm
going to go over the three main
components of my collision system
there's the broad phase the routing
function and finally the narrow phase
let's take a look at what's changed
since part three so this is part four it
looks just like part three for the most
part except now i have collision
detection and response between my player
character and the game world so as you
can see i'm i'm moving smoothly across
the tops of the tiles i'm jumping up
along the sides of the tiles i'm not
getting hung up on any of the edges
anywhere i can jump through the bottoms
of these platform tiles basically i have
pixel perfect tile based collision
detection and response and everything
looks and works the way you would expect
it to in a tile-based platforming game
so now that you know what the example is
all about let's take a look at what's
changed in the code so the only two
files that have changed since part three
are the game file which holds the game
class and the display file which holds
the display class
display had a minor change since part
three if you remember part three i had
an issue with the export values for my
tile map because i used the tile map
editor and all the values were offset by
one so i just changed this function and
i changed my tile map values to what
they're supposed to be so i got rid of
the offset as you see i have the comment
no longer subtracting one take a look at
part three so you can see what i'm
talking about also in here in the draw
player class i change math.
floor to math.round in this line and
this line here and the reason is because
it just rounds my player to the
appropriate
spot that he's going to be drawn in more
smoothly so those are two really minor
changes in the display
file inside the game file a lot has
changed i've added
the
collider function i've added my
collision map which is this guy right
here a collision map is different than
the graphical map for the tiles
themselves that you see on the screen
these are for the collision shapes
uh down here i've amended my collide
object function inside of the world
class
to do the broad phase collision
detection and response that are
these functions right here
then i've also added the collider class
the collider class takes care of the
routing function as well as all of the
narrow phase collision methods like
collide platform bottom so cloud
platform bottom would be called whenever
you
physically clyde you're the top of the
player with the bottom of a platform so
i'm jumping up and clyde platform bottom
is firing every time my player hits his
head on the bottom of that tile there
so
that's what that does then i've also
added a bass class for the player object
called object and that's nested inside a
game.world
the object is basically just a simple
rectangle class
and i'm going to talk about x-old and
wild and why we need those
later on in a different part in this
video
but basically the object class is just
the superclass of the player class now
basically the player is going to inherit
all of these values from object and it's
going to get all of these neat little
helper functions to get the different
sides of his
rectangle
so that's all that does and then down
here you can see i'm actually extending
the object class inside of the player
constructor
and
down here i'm actually extending the
player prototype off of the object
prototype with object.sine
so those are all the changes in part
four stay tuned for the rest of the
video
there are three main components to this
approach to tile based collision
detection response and those are the
broad phase the routing function and the
narrow phase and they're all centered
around having a collision map full of
collision tile values each value
represents a different shape or
collision shape so for instance if i hop
over here i can jump through the bottom
of this tile but not fall through the
top of this tile here i can cloud with
the bottom i can collide with the
right side and i can collide with the
top of that as well this tile over here
these two i can collide with the left
side so all of these tile values
correspond to
collision shapes
that have different sides
so the broad phase
gets what tile my player character is
standing on it determines what the value
of that tile is that my player character
is standing on gets that value from the
collision map
it then hands that value as well as the
player object into the routing function
the routing function checks the value in
a switch statement and it says okay well
let's check for instance i'm standing on
top of tile one here
this is tile one so the routing function
would say okay you're colliding with
tile type one
and for tile type one i'm going to call
a certain set of narrow phase collision
detection and response methods so the
broad phase determines what the tile
value is the routing function determines
which narrow phase functions to call and
the narrow phase does the final
collision detection and response
and that's how the system works so stay
tuned and i'm going to go into the code
that makes that stuff work in detail
all right so now i want to talk about
the broad phase collision method and
that is going to be the collide object
function which is located inside of the
game.world class so i'm going to come
down here and show you what this broad
phase does
the whole function all it does is first
it checks for collision with the
outsides of the world and that's going
to be this right here that's from part
three that's pretty simple stuff and
then the other thing it does is it
checks all of the different corners all
four corners of our player character so
i have these four
chunks of code i have one here for the
top left i have one for the top right
one for the bottom left one for the
bottom right and that's the end of the
function
so this is the entire broad phase just
these four chunks
and this chunk up here which does
collision with the boundaries of the
world so let's take a look at the first
chunk that tests
for broad phase collision with the
collision map
with the top left corner of our player
character so
what these are are
a row and a column value inside of our
collision map so top is going to be the
row that the top side of our player is
in and left is going to be the column
that the left side of our player is in
so this is going to be the top of our
player this is going to be the left side
of our player and this is going to be
the row that the top is in
now if i move the player over here this
is going to be the row that he's in and
if i check the left side this is going
to be the column that he's in if i move
him over here now the left side of the
player is in this column
so pretty simple the math that we use to
get the row and column and convert it
from the physical
xy position of the player to the
one-dimensional index
or of a row or column value
it's not really one-dimensional it's
two-dimensional just simplified
basically you just get the top of the
object which is the y position at the
top of the object you divide by tile
size that gives you the row of the top
and then you do the same thing for the
column you just get the left side of the
object which is right here you divide it
by tile size that's going to give you
the column value
and then you're going to go ahead and
convert those
the row and the column
into a
index inside of our map array or
collision map array and you just do that
by multiplying the row by the number of
columns
inside of the collision map ours was 12
and then you add the column that the
player is standing in so that's the row
of the side of the player multiplied by
the number of columns in the collision
map plus the column of the side of the
player
pretty simple
and then you go ahead and you hand in
that value as well as the
uh row and column positions of the tile
multiplied by tile size to give you the
actual x and y position of the tile so
for instance if i was going to get the
top left of my player that would be
right here he's inside of this tile the
top and left values multiplied by the
tile size is going to give you this
position right here which is going to be
the x and y position of the tile so
we're going to hand all that information
into the colliders
collide method and that's going to be
the routing function you're going to
hand in the value you're going to hand
in the object you're going to hand in
the left side of the tile and you're
going to hand in the top side of the
tile
you're also going to hand in the
tile size
and then you just go ahead and you do
this for every corner of the player
so we just did the top left
down here we're going to do the top
right
then we do the bottom left
bottom left there we go and we do the
bottom right
and we just do that for all four corners
now you might be thinking well you're
redefining some values
that you're reusing so
why not just define for instance
here we go let me find a good example
here
right so this is checking the top right
corner right this right here and this is
checking the bottom right corner well
i'm defining right two times but
why would i do that well the reason i'm
doing that is because
here i'm defining right and i'm checking
for collision if i have a collision and
i respond to it my player character is
going to move and right as i defined it
here might not be the same anymore so
down here when i'm getting the right
side of the player again i'm not going
to want to use this old
value for right i'm going to want to get
the right side of my player again
because it might be different than it
was when i checked collision with the
top right
so i check collision with the top right
if there is in fact a collision up here
it's going to move my player
and then i check oh this is the top
right i keep getting confused there but
then when i check the bottom right
if i moved that value is going to have
to be redefined to get the appropriate
new location of the player's right side
after he
had collision resolved with the top
right corner
so
this is the broad phase it's not as
complicated as you think it's really
simple the math is really simple you're
just getting a value out of an array
based on a player's column
and row or
row and column rather and then you're
handing all that information into the
routing function we're going to take a
look at the routing function in the next
part of the video now let's take a look
at the routing function so i'm going to
come down here to the routing function
and that is going to be in the
game.world.collider class and it's going
to be called collide so the collide
function is my routing function and all
it does is it takes the tile value the
object and tiles x and y position as
well as the tile size which is the
tile's width and height
and it takes all that from broad phase
and it hands in the value of the tile
into a big switch statement which then
routes you and that's why i call it a
routing function it routes you to the
appropriate narrow phase collision
methods and it also does some tweaking
to the tiles so
for instance
case one if i move my player down here
i'm actually gonna be standing on a one
tile i know for a fact this here is a
one tile
and
it's gonna call collide platform top and
it's gonna hand in the object so that's
gonna be my player character it's going
to hand in tile y not tile x because we
don't need it in this case we just need
to know what the top of the tile is
going to be
now if i want this to be a little bit
lower say i want to make a half tile i'm
just going to hack this right now but
i'm going to put in
plus 8 and i know for a fact that 8 is
half of my tile height so that's going
to be
didn't mean to do that
that's going to be my change that i made
i saved my file i'm going to refresh my
screen
now as you can see all the one tiles
that i'm colliding with are going to
have half height
so this tile right here i'm now going to
be colliding with a value that's a
little bit lower
interesting so i can take my narrow
phase functions and i can tweak them a
little bit inside of my routing function
and that's going to give me the ability
to create a whole bunch of different
tile types
however i want so all the different
shapes are going to be defined basically
inside of the routing function
and all it really does is gets the tile
value and links it to
a certain set of narrow face functions
let's take a look at
let's see what i got here let's take a
look at something a little more complex
first i'm going to have to see what
tiles are what because i can't think
right off the top of my head what those
values actually stand for but if i look
at my map
i'm going to come over here to a 13 tile
and that looks to be
at the left side of this t right here so
13 is going to be oh wait i forgot to
refresh my screen let's refresh and get
functionality back to normal so 13 is
going to be this tile right here that
i'm standing on now
so let's take a look in the routing
function at
the
13 tile
all right here we go it's going to call
the methods
collide platform top clyde platform left
and collide platform bottom and the
reason for that is because i'm going to
collide with the
left side
of this tile cloud with the left side
maybe if i can actually hit it with the
left side i'm going to cloud with the
bottom and i'm also going to collide
with the top so those are the three
sides that i'm going to be able to
collide with if i happen to meet a
tile with a value of 13.
now the reason i have some of these
functions nested inside of if statements
is because i can only collide with one
of those sides of a tile at a time
so i can only collide with the top and
if i do i can't possibly be climbing
with the left or the bottom certainly
not the bottom if i'm coming from the
top how would i cut with the bottom so
i use these if statements to early out
of my routing function and not have to
execute checks for these other two
functions which is great because for any
given tile we're only checking
collisions on sides until we actually do
collision and then we just exit out we
don't have to check the rest of the
collision so
clyde platform top is going to be in
this if statement
if i collide with platform top then i'm
no longer going to have to check for
colliding with the left side or
colliding with the bottom side of the
tile
now inside of my narrow phase
my function returns true if i do in fact
have a collision and it is resolved and
returns false if no collision was
detected and nothing was resolved and if
that's the case if it's false it'll just
jump down to this next
narrow phase collision method call that
if there's no collision there it will
jump finally to the last method in the
case
and call that and if that doesn't return
true then there is no collision and
nothing gets resolved
so that's the routing function pretty
simple that's how it works uh in
previous tutorials on how to do this
systems tile based collision system i
used an array
and i used um
objects object references to get these
but actually it's much much faster to
use a switch statement
so that's why i made the switch to a
switch statement pun intended there so
anyway next step onto the narrow phase
now let's look at the narrow phase and
that is going to be
farther down inside of the collider
classes
prototype so inside the cladder classes
prototype i have four functions and
those are collide platform bottom
cloud platform left
clyde platform right and cloud platform
top and
awesomely enough with these four
functions we can do collision detection
and response with all of the different
tile types basically any tile that has
four sides we can take these four
functions and combine them
to get all kinds of different
combinations up to 15 combinations which
is as many combinations as you can have
with a
four-sided tile
so
let's take a look at let's see here
clyde platform top where i think i was
on alright let's take a look at cloud
platform top and see how this actually
works so from the routing function
you're going to get the object and
you're going to get the top side of the
tile so top side of the tile is just
going to be whatever the top of the tile
is that you're standing on so right now
i'm standing on this tile i have my
object i have the top of my tile and
we're just going to run an if statement
that checks to see if the bottom of our
player character is greater than the
tile top and if it is
then we run this code but wait there's
more there's an and in here so we've got
to see what that is too we're also going
to check to see if
the bottom
of the player from the last frame of
animation is above the tile top now if
you didn't include this it would still
work but
it would not work as smoothly as you see
here so let's go ahead and comment this
out and see what happens when we don't
use the old position
from the last frame of the player
character i'm going to comment that out
i'm going to save i'm going to come in
here i'm going to refresh and now let's
see what we get
everything might work perfectly but oh
wait how about that i just jumped right
through that tile now the reason for
that is
the when i jump up the top left and top
right corners of my player are going to
enter into this tile space the broad
phase is going to detect that it's going
to hand the information to the the
routing function and the routing
function is going to call
collide platform top
now cloud platform top
without
doing this check on the last position
that the bottom of the player was in the
last frame of animation without that
it's just going to check to see is the
bottom of the player greater than the
tile top and if it is
set it to
the
top of the tile so that's what's
happening
when i enter into the tile it detects
that the player was
below the top of the tile and it just
sets it right to the top so that's the
functionality you're gonna get
without this
when you add this in basically what's
happening is it's saying
hang on let me refresh real quick
basically it's saying
okay
the
bottom of my player may be inside of
this tile but if on the last frame it
wasn't up here and therefore entering
into this tile between frames so on
frame one he's going to be here on frame
two with the force of gravity he's going
to be down here inside the tile he's
going to be entering in through the top
and collide platform top is going to
detect that inside of this if statement
because the bottom on the current frame
is going to be below the tile top
and the bottom on the last frame is
going to be above the tile top
so
that's going to be true and then we're
going to get the appropriate response
that we expect and we're no longer going
to jump through the bottom of the tile
and get that kind of glitchy looking
collision response
so
now let's take a look at what happens
after we do that after we collide with
the top of the tile so i'm going to
cloud the top of my tile here
this is going to be true the bottom on
the current frame is going to be
slightly below the bottom on the
previous frame is going to be above
and
what i'm going to do is i'm going to set
the bottom of the object i'm going to
set this bottom of the object to the
tile top and i'm going to subtract this
little value here i'm going to get into
why i subtract that value in a minute
i'm going to take a look at another
function because that better explains
why i do that i'm going to set y
velocity to zero this way gravity
doesn't keep increasing
and eventually pull me through the tile
altogether i'm going to set jumping to
false so i can jump again
and i'm going to return true so i can
tell the routing function not to do any
more narrow phase collision calls
so now let's take a look at this little
value and see what it does but i'm going
to do it in the context of the
collide platform left function because
that also has a similar problem cloud
platform write and cloud platform bottom
don't have this problem and it has to do
with rounding so let's just comment this
out and see what happens but first i'm
going to show you the desired
functionality so right now i'm colliding
with the left side of these two tiles
and it's calling collide platform left
to do that collision resolution
so as you can see i can jump up and down
and it's as you would expect i'm jumping
up and falling down nothing is broken
yet so let me comment this out and break
the code i'm not really breaking the
code it's all going to work the same
it's just not going to have the desired
effect i'm going to refresh my screen
and i'm going to come over here and i'm
going to do this again now when i jump
i land on top of the tile and the reason
for that is because when i'm falling
down i'm actually going to be in this
tile space with the right side of my
player
so the right side of my player when i'm
falling down into this tile space is
actually going to be in this tile space
just looking at it with a naked eye it
looks like he's fully inside of this
column but really his right side is just
barely inside of this column over here
so unless we subtract
that .01 or some tiny number doesn't
have to be 0.01 it could probably be 0.1
or 0.001 if you prefer
because we subtract that
we are pushing the player character out
of this tile into this column and he's
no longer touching this after he enters
or exits collision with the left side of
this tile space so let's refresh
and see what that
good functionality looks like now i'm
colliding with the left side of this con
this tile right here it's pushing me out
of collision and it's actually pushing
me out of the tile space entirely by .01
pixels so when i jump
i am fully inside of this column as you
would expect and i'm no longer going to
be colliding with these tiles unless i
press right on my keyboard and move the
player into them
so that's why i have to subtract that
little value now before i stop talking
about the narrow phase collision let me
just talk a little bit about
object.getold right and how we actually
do that so
basically all we're doing is on every
frame we are saving the
last frames player position and we're
getting the new frames
new player position so
where that happens is
inside of the player object we actually
come out here and
look so we can actually see the code a
little bit the player class now extends
the object class and inside of the
object class we have this is the
object class right here
inside of this we have some information
to describe a rectangle
and
we're also going to have the x old and y
old values
so keep that in mind we have a x and y
location we have the x and y location
from the previous frame of animation so
if i come down here to the
player class
and i come down here to his update
function this is where we're going to be
keeping track of this
x old and y old are going to be updated
on every frame of animation to equal
that frame's current x and y position
and then we're going to update x and y
to be
as fresh as possible in the new frame so
we're basically just keeping track of
the player's old x and y position from
the last frame and his current x and y
position from the current frame and that
allows us to calculate his angle of
trajectory and we can see
based on that trajectory if he was above
a tile before he entered into it
and that will give us the ability to
get rid of that broken functionality
that you saw where i would jump up and
just
almost teleport through this tile and
sit on top of it so that's why we have
to keep track of this this is also great
for interpolation which is something
really useful for smooth animation but
i'm not going to talk about that in this
video anyway that is the narrow phase
it's really simple the functions are all
really really simple if you just take a
look at the source code i urge you to go
to the link in the video description and
check that out on my github page
and that's it
i'm going to show you how i added sprite
animation to the game so you can take my
example and use it to put sprite
animation into your own programs i'm
going to talk about what's new in part
5. then i'll give you a very simple and
brief refresher on how sprite animation
works when using a sprite sheet and
finally we'll take an in-depth look at
the animator class and how it works with
the player's movement to render the
appropriate animations
alrighty so the first thing i want to
take a look at in part 5 is the example
program and as you can see in this
example program i no longer am working
with the little white and gray square
now i am working with this animated
rabbit and he looks a lot better it's
starting to look a lot more like a game
that you can actually play just minus
power-ups and items and stuff like that
so
basically not much has changed other
than i've added an animator class that
does the sprite animation and i've also
tweaked his physics for jumping and
stuff like that a little bit but that's
pretty pretty common sense stuff
kind of know how to do that if you're
already to this point in the tutorial
series so i'm not going to worry about
the specific changes i made for this
video instead i'm just going to worry
about showing you guys how the animator
class works to get this guy animated on
the screen if you do want to see what
has actually changed in the code since
part four take a look at the source code
that i've linked in the video
description at the top of each file that
has changed and for part five it's just
these three the game the display and the
main files for each file that has
changes in it i've added a bulleted list
in the comments at the top of each file
that outlines what exactly has changed
specifically in the code so if you want
to find out what's changed take a look
at the source code and take a look at
these comments but in this video i'm
just gonna focus on the animator class
and how to get this dude animated on the
screen so stay tuned and i'll show you
how it's done now let's take a brief
look at how sprite animation actually
works when you're using a sprite sheet
so this here is my sprite sheet images
the png has all my tile graphics and it
has my sprite images in it now each
sprite animation is just a compilation
of these different
unique images so each image can be
considered just a square that you would
cut out of this bigger image and then
put on the screen in quick succession to
give yourself an animation so for
instance right now my player character
isn't doing anything he's just sitting
still this frame is literally being cut
from
this position right here if you notice
this and this are exactly the same image
so currently he is displaying this frame
of animation if i were to move him to
the left now he's going to stand still
he's going to be displaying this frame
right here
when he's walking it's going to give me
an animation so i'm going to be playing
those frames over and over again in
quick succession
it's kind of hard to tell because he's
walking so fast but he's basically
playing when i walk to the right he's
playing this set of frames right here
he's stepping through these four frames
right here and that's going to give me
my animation so what's happening is
on every frame that i draw to the screen
i'm going to see which
frame that my player characters
class is determining that he should show
based on his movement pattern
it's going to take that frame it's going
to go into this tile sheet image is
going to cut that specific frame out of
the tile sheet it is then going to take
that frame and draw it to the player's
location on this
display canvas this canvas element that
i have in the browser window and you're
going to see whatever frame that is
supposed to be displayed and that's
going to give you animation so that's
basically how it works basically you're
just cutting different images out of a
bigger sprite sheet image and you're
displaying those smaller images
at the player's unique location on the
screen now we're going to take an
in-depth look at what makes the code
actually work or i guess we're just
going to take an in-depth look at the
code because the code makes the code
work so here i'm going to start with the
frame class now the frame class is just
going to define a rectangular region
that we are going to cut our sprite
images out of the tile sheet width so it
has an x value y value width and a
height and that's just going to be the
source rectangle that defines the
individual image inside of our sprite
sheet so i'm going to use one of those
frame classes to define each rectangular
region
for each one of these individual images
so that's what the frame class is going
to be for and just bear with me as i
explain all these different classes and
you'll see how they fit together at the
end of this part of the video
so don't worry about the offset x and y
positions just yet i'll tell you about
those later just keep in mind it's just
a rectangular region for the moment
now we're going to look at the tile set
class and this used to be the tile sheet
class inside of the display file but i
moved it over to the game file basically
the functionality is exactly the same i
just renamed it and its location is
different basically just keeps track of
the number of columns and tile size of
our rabbit trap sprite sheet image
and
that's it
where animation comes in here is with
the frames array so now we just talked
about the frames class which is down
there the frames class is just a
rectangular region with an offset
position
each one of these values inside of this
frames array is just going to be one of
the rectangular regions that corresponds
to a specific graphic for our animation
so for example this frame is where the
idle left graphic is inside of our
sprite sheet
this frame is where the jump left
graphic is inside of our sprite sheet
this group of frames is going to be
where all of the individual graphics are
for the walk left animation down here we
got the walk right animation so
basically all i'm doing is defining each
rectangular region for every one of my
sprite animation components or basically
these individual images
so now you know where the individual
frames are going to be defined inside of
the tile set class now we're actually
going to have to define
what those animations are so the
animation itself is going to be defined
by the object that's using it so the
animation for this rabbit or for the
player is going to live inside of the
player class so every unique animation
the idle
frames the walking left and right frames
the jump frames
those are all going to be stored inside
of the player class
inside of its prototype so i'm just
scrolling up to that here we have the
player prototype and inside of it we
have an object called frame sets
and inside of frame sets we have all the
different
animations
for the player we have as idle left jump
left move left and then the right words
motions for those different animations
so each one of these values corresponds
to a frame inside of our tile sets
frames array so for example idle left
is going to
have a value of 0 in it and 0 is going
to be the frame index or the index
inside of our frames array where
the
rectangular region is defined to cut the
image out of the sprite sheet for the
idle left animation and that's just
going to be here so this is index 0
inside of our frames array it's idle
left and that's what we're going to use
for the idle left animation of our
player
and that's why that value is going to be
a zero
so as you can see each one of these
values just corresponds to a different
frame inside of the frame's array and
what a frame is it's just a rectangular
region that we use to cut out our sprite
sheet images from the sprite sheet
so how do we actually animate these
that's going to be our next class that
we look at and that's going to be the
animator class so i'm going to scroll up
to the animator class and i'm going to
take a look at what this guy does
so
here's the animator class it's a
frame rate dependent animation class so
what that means is
the rate of frames that you see for each
animation is going to be totally
dependent on the game engine's frame
rate so if you don't want that kind of
functionality this probably isn't for
you but if you're just going to run your
game consistently at 30 frames per
second across all devices this is
probably what you want to do and for
html5 games that's a pretty good bet so
this will probably work for you so
i define a couple different values in
here i have count delay frame set frame
set is going to be
those different frame sets or those
different animation arrays that i define
inside the player so for example frame
set could be
i'm going to scroll down here it could
be
any one of
these animations it could be idle left
it could be this array right here it
could be move left
which is that array right there could be
any one of those and basically it's just
going to use that information and loop
through it
when it does my animation
think i went too far here we go so the
frame set is just going to be one of
those arrays with those values and those
values of course correspond to our
different frames that we use to cut the
animation image out of the sprite sheet
frame index is just going to be where we
are or where the play head is so to
speak inside of that frame set array
frame value is going to be the value
of whatever
index we're in inside of our frame set
so for idle left remember that was value
zero the value was zero
so for that particular animation it
would be at index zero inside the frame
set and the value would also be zero for
the idle left image
and then we have mode mode right now for
this example
there are only two modes we have pause
and we have loop
now pause and loop are just going to be
the two types of playback that we want
our animations to do
so
pretty simply i'm going to just explain
that as we go i'm going to come down to
the loop function
all it does is
it just changes the playhead position
every so many frames that pass in our
game loop so count is going to increase
one time on every cycle of our game loop
until
it reaches the delay that we specify so
for the walking left and right
animations i've i've defined a delay of
five
inside of the player class
so every five frames of our game loops
animation
or cycle
we are going to
run the code inside of this while loop
so count we're just going to decrease
that by delay and that makes us wait
again
frame index this is where we set the
frame index or the playhead inside of
our animation basically this we're just
going to say is the frame index
currently less than the frameset.length
so let's take a visual look at what's
going on here
inside of our rabbit trap png so let's
say the frame set that we're going to
use has values that correspond to the
walking right animation which is going
to be these four frames right here
so
frame index at zero is going to yield a
frame value of this image right here at
frame index of one i'm going to move
over one it's going to be a value that
corresponds to this image right here
when i move it over again it's going to
correspond to this image right here so
basically what the code inside of the
loop function is doing
is it's just increasing my frame index
by 1 until it reaches the end of the
frame set
and when it reaches the end of the frame
set the next time it goes to increase
instead it just sets it back to zero so
inside of my
loop function
all that we're going to do is just say
set the frame index equal to
the frame index plus one if it's not yet
past the end of our frame set length and
if it is past the end of the frame set
length just set it to zero to restart
the animation loop over again
then finally what we do is we get the
frame value that's just going to be
the value that corresponds to the
specific rectangular region that we
store in the tile sets frames array that
corresponds to the image that we're
going to be cutting out of the sprite
sheet so the frame value is just going
to be set to whatever our frame set
array is and we're going to hand in the
index of
the the playhead so whatever frame index
is that's going to give us the value
inside of our frame set that we're
currently at in the animations loop
cycle
all right so that was a mouthful and
hopefully i'm explaining everything
quite well i think the next place we
want to go is probably the render
function but first i want to just touch
on uh this functionality here the change
frame set function inside of the
animator class and basically what this
does is it just changes what frame set
we're using so whenever i press left on
the keyboard i'm going to call change
frame set it's just going to change the
frame set to the left animation which is
that array inside of the player class
that defines which frames to use for the
left animation
uh when i press right it's going to call
change frame set i'm going to hand in
the player's right
movement animation if i jump to the left
i'm going to call change frame set i'm
going to hand in the left animation you
kind of get what i'm saying here then
the only other function in here
is going to be the animate function it
just checks to see which mode we're in
loop or pause
pause is gonna be for
no animation so pause is gonna be called
on the idle animation so idle right
and idle left pause is gonna be the play
method that we use for the walking
animations we're going to be using the
loop method because we want to keep
animating that cycle of frames over and
over and over again and basically this
is just called on every frame and it
just calls the corresponding method it's
pretty simple
so now that we know how we're animating
our frames let's actually take a look at
the render function which lives inside
of the main file and we're going to take
a look at how we actually use that frame
information to cut our image out of the
sprite sheet itself
so
the first thing we do we're actually
going to have to jump to another section
of code real quick because i'm using an
assets manager to load my tileset image
so real quick i'm just going to jump up
here check out the assets manager class
all it is is an image
and i'm going to load in an image with
our
rabbittrap.png image inside of it so
really all that we're doing here is just
using the assets manager to load our
tilesheet
really simple so
that's all that is don't worry about it
too much you could write your own code
you don't need an assets manager all you
need is to load up the tilesheet image
to use it for drawing from that tile
sheet image
so
here we go
here's where we get the frame value so
frame we're going to get the the frame
remember is just that rectangular region
but we're going to get to it
through all those classes i just talked
about so the animation class is going to
give us a pointer to
a frame value which lives inside of the
frames
array inside of the tile set class and
then the tileset class is going to be
using the frame class to define its
rectangular regions to cut images out of
the tilesheet image
so
how we get the frame is we just
get the frames array from our games tile
set
then we go ahead and we hand in the
player's current frame value which is
kept up to date on every cycle of our
game loop inside of the update function
we're going to be calling player dot
update animation and that's going to
update our frame value
inside of the
loop function most likely of our
animator class
so
draw object is going to take all this
information and put it together to give
us the appropriate image that we need to
see to make our animation work on the
screen so
what we're going to do is we're going to
hand in our source tile sheet image
then we're going to hand in the actual
source frames x and y position to cut
from
then this is going to look a little
complex but it's really not we're going
to hand in the players x location and y
location
and we're just going to add basically an
offset where we want the frame to show
up and be drawn to the screen so
right now the player's frame is slightly
offset from the player's real location
and the reason i want that to happen is
so when i stand on the edge of a tile i
actually fall through and if you look
his ears on the the frame are actually
kind of moving through the tile if i go
over here this the image itself is
actually overlapping the tile i don't
want it to be pixel perfect like that i
want it to be
functional i want the player to have fun
i don't care about pixel perfect
collision as much as i do the player
having fun so
this code basically what it does is it
just repositions the frame a little bit
to center it on the player's position so
we can more easily move him around the
screen without that
pixel perfect collision that makes his
hitbox seem a lot larger than it needs
to be
so all this does it gets his exposition
it adds
the
center
or it gets the center of where i want to
draw that frame on top of the player by
just getting half of his width
subtracting half of the frame source
frames with and then it just adds the
frames offset x position
if i don't add that offset x position
and remember i was talking about that
for the frame class if i come back into
the frame class all the way at the
bottom here
we define the offset x and offset y and
then when we actually instantiate each
frame we're going to add
negative 2 which is the going
offset y position
for this player if i don't add negative
two
this is what happens i just set it to
zero i saved i'm going to come back in
here as you can see now that was the y
offset he's now two pixels deep into the
ground and that does not look quite
right so that's why i have that offset
position all it does is add a slight
offset
when i draw the frame to the screen to
make him appear in the appropriate
location
so that's it that's all that does you
don't need this stuff like i said i i'm
using a
frame based approach you could easily
use a tile based approach where you have
all your graphics inside of one big grid
kind of like the tiles are instead of
having them all close together and
cutting them out specifically the reason
i do this is because if i were to add
let's say my my rabbit has a sword and
the sword comes out to here
now my sprite is going to be different
and it's not necessarily going to fit
uniformly into a box or into a grid row
and column cell with all the other
sprites so i do it this way because
sprites change they change in size they
vary in size depending on what animation
you're doing so this is just much more
flexible for me so
now let's get back into the rendering
function went off on a little rant there
so
basically all the draw object function
does of the display class is just draw
from the tile set
from the frame's x and y position
and it draws to the screen whatever
frame is currently in the animation in
the player's animation draws that frame
to the screen at a slight offset
position
then we call display.render and that
draws everything to the screen including
the tiles and whatever frame of
animation our player is in
alright so now let me just quickly see
if i actually missed anything here i
think i went over everything how
everything works let me take a look
inside of the
player class itself and actually see how
we're doing the players animation how
we're actually deciding which frames to
display and which frame sets to use
this is going to be done inside of the
update animation function
so update animate animation is going to
be called on every cycle of our game
loop and it's basically just going to
check to see what direction the player
is facing and it's going to choose an
animation based on that so the very
first if statement inside of update
animation is going to be
is the player moving up which means is
the player jumping up so if i press up
on the keyboard the player is going to
move up and if you look closely you can
see that the up animation or the up
frame is played briefly while he's
moving up while he's moving down it
switches back to
idle
left
so
if he is moving up and if his direction
which is determined just by which
direction he's facing so when i press
the left key his direction is going to
be negative one when i press the right
key direction is going to be positive
one
so
if his direction is negative one so if
he's facing left i'm going to change his
animation frame set to jump left
if that's not the case and he's facing
the right i'm going to change his
animation frame set while he's jumping
to jump right i'm going to do that in
the pause position
now for these other ones basically is he
moving to the left if he is
and his velocity is a certain
amount
then we're going to
play the
move left animation if the velocity is
not a certain amount or less than that
basically if he's basically stopped and
his velocity is very small we're going
to play idle left instead now this is
cool because
what this functionality allows us to do
is it allows us to have our player
gradually stop walking even though we're
not pressing the walk key anymore so if
i were to come in here and change this
code to
let's say this is the left walking
animation
what is this move left let's change this
to
two negative two
and i saved i'm going to come up here
refresh my screen
now let's see what happens for the walk
animation
because i have to be moving at
2
a velocity of 2 to the left the move
animation doesn't actually run unless i
hit that
2 pixels of movement velocity per frame
so what this allows me to do is it
allows me to create an effect where i
gradually walk to a stop instead of just
halting to a stop really hard like that
so a better
a better kind of example would be if i
used one instead and i refresh the
screen up here
let's see what that looks like
now i start walking right away because i
hit a velocity of one to the left really
quick but as soon as i stop
i go into the idle animation and that's
not really good because it looks like
i'm sliding too much or maybe you do
prefer that and that's the great thing
about this code you can just do whatever
you want i kind of like it where i'm
just gonna gradually stop walking until
i'm completely stopped i don't prefer to
just automatically stop and slide on my
feet like that so what i've done is i've
just set a very small value
for the
velocity check and if he is moving
slower than negative 0.1 pixels to the
left
then
he's going to idle and if not he's going
to continue walking until he just comes
that gradual stop like that
so that's pretty cool so basically the
update animation function is fired on
every frame after you do collision
detection with the player in the world
and
it just determines what way he's moving
and depending on what direction he's
moving it runs a certain animation
now this is actually really important
it's more important than you think not
necessarily for the player because you
can
have fine control over the player but
for non-player characters who move on
their own
you have to determine their animation
based on how they're moving because you
don't control them you can't say play
the run animation when i press the run
key because you're not pressing a key
for a non-player character for those
non-player characters you have to keep
track of
what direction they're moving how
they're moving and based on that you
have to set their animation so that's
what this code does
it just automates the process of setting
the animation it doesn't rely on key
presses or user input it just sets the
animation depending on what direction
he's moving
before i go any further with this series
i want to address something called
tunneling it presents major problems for
any physics engine and tile based
engines are no exception
tunneling is sure to affect you
particularly if you are writing your own
physics engine so stay tuned while i
talk about how to overcome this pesky
glitch
alright so let's take a look at what
tunneling actually looks like so this is
the part five example program and i
haven't changed any of the code since
part five
but i just want to show you this one
glitch that happens underneath this
t-shaped structure of tiles when i am
running into this tile from the right so
i'm pressing down on the left key and i
jump i actually pass into the tile
now i can actually jump down below the
tiles and walk around because of the
nature of my tile-based collision code
but obviously you don't want that to
happen
this actually isn't a problem with the
collision code itself this is just a
problem with tunneling and it seems to
happen just in this one scenario so in
order to show you guys better what's
actually happening first i'm going to
explain what tunneling is just using my
mouse pointer as an example and then i'm
going to show you in slow motion when i
slow this game down i'm going to show
you what's actually happening with the
player and why tunneling is happening in
this particular instance
so tunneling is when the object moves
too far in one frame to actually collide
with a collision shape so
let's say that
this tile is going to be my collision
shape and the mouse pointer is going to
be my object so this is frame one on
frame one my object is right here where
the mouse pointer is and on frame two
i'm going to move my object a little bit
to the left so this is frame one this is
frame two my object has moved about 16
pixels to the left now this is okay
because i'm not moving more than one
tile space
i'm actually going to be over top of
this tile space it's going to detect
that i'm colliding with it and it's
going to move the mouse out of the
collision and put it back into an empty
tile space that's how it should work
tunneling happens when the mouse moves
much farther than
one tile space or 16 pixels in this case
over the course of one frame so if this
is frame one and i move in frame two all
the way to here
what's happening is i'm jumping right
from here all the way to here and i'm
never detecting a collision with that
tile because i'm never landing in it so
tunneling is basically just moving a
player object or any object too quickly
to detect collision with a stationary
collision object
so
now that you kind of understand what
tunneling is let me slow this down and
show you
in action what the tunneling looks like
with the player character so i'm going
to save my code i'm going to set the
frame rate to one frame per second
that's going to slow things down a lot
and i'm going to refresh now as you can
see things are really really slow
so
i'm going to run over here into the
corner and it's going to take a while so
just bear with me but i'm going to show
you this glitch in as slow motion as i
think it should be i don't want to go
any slower than this or would take
forever
so here i am i'm standing next to the
tile i'm going to press
up and i'm just going to jump straight
up
so i jumped up and immediately this tile
up here resolves collision and throws me
right back down below it
but if i jump up while i'm pressing the
left key
i jump up
and i move slightly to the left
now
that's when the tunneling occurs so the
tunneling isn't actually happening on
this tile right here it's actually
it's kind of a special case but i'll
show you why so i'm going to run back
out here and i'm just going to jump up
the tunneling is actually happening when
i jump because the player character is
moving about 20 pixels upwards
as soon as i start jumping and you'll be
able to see that
when i jump here in a moment
so
i could actually get this thing to
comply it's just moving so slowly
all right so i'm gonna jump and just
take note of where this player actually
moves to when i jump
so
this is the
top of the player right here this would
be 16 pixels from the ground right here
when i press the jump key
immediately my player is above that 16
pixels his feet were about right here
and he clearly moves more than 16 pixels
which is our tile space so if he can
potentially move
past one full tile space without
stopping in it he can tunnel because
tunneling is basically when on frame one
we're out of collision on frame two we
jump over
a collision object and never touch it
so what's happening here is when he
jumps
imagine what happens if he were standing
right here he's going to jump up
on the first frame
his the top of his hitbox is actually
going to be over top of this tile and
the bottom of his hitbox is going to be
inside of this tile so what's happening
is when he jumps and he's standing here
he's going to jump up he's not even
going to have a chance to clyde with
this tile because the top two corners
that i'm checking out on his hitbox are
over top of this tile even
the only reason collision happens on
this tile is because his two bottom feet
or his two bottom corners are inside of
this tile
and he can still technically move to the
left while he's in this tile because
collision is only going to happen in
this tile with the bottom side of the
tile and it does when i'm standing
underneath this tile
it does do collision but just on the
bottom side i can still move to the left
so when i jump up underneath this tile
i'm going to jump i'm going to hit my
head on the bottom and it's going to
send me right back down again
but remember i'm jumping 20 pixels high
so
what's going to happen is just my feet
are going to collide with this
when i jump i'm actually going to move
up here then it's going to place me back
down there and i can still move over to
the left so when i jump up and press
left
i'm actually going to be up here and i'm
going to fall back down into this tile
on the wrong side of the collision
boundary
so that's what tunneling is and there's
a really easy way to fix it if i come in
here and i set this back to
let's see
30 frames a second
that ought to do let's see what that
looks like
30 frames a second things are back to
normal what i'm actually going to do is
i'm going to come out here and i'm going
to change the
speed at which he jumps and that's
actually going to fix everything
so if i can find where that is oh it's
actually in the game object here
jump i'm actually setting jump whenever
he jumps i call this function and it
moves him 20 pixels up it sets his y
velocity at negative 20 pixels so what
i'm going to do is i'm going to set it
to negative
15 pixels and that's going to prevent
him from ever moving
more than one tile space
and actually i'm going to set this back
to one frame so you guys can see that in
action as well let's go back to one
frame
per second refresh and now we're going
to zoom in and take a closer look at
this guy jumping so
this is what 16 pixels looks like when
he jumps
as you can see his bottom feet are no
longer way up here on that first frame
on that first frame they're down here so
he'll still end up colliding with this
tile right here so when i move back into
collision and i'm going to speed things
up for this
set it back to 30 frames a second save
come over here refresh my page and
now tunneling can no longer happen
so collision is going to happen as i
expect it to so that is the problem
and i guess i kind of showed you how to
fix it in the first part but i'll go
into more detail on how to fix it in the
next part
okay so we just looked at part five's
example program where we had this glitch
where actually i fixed it but very fresh
we had this glitch
i'm gonna leave that in actually so if
you ever check out part five that glitch
is gonna be left in there but now i
wanna show you a better way to fix it
and this is a sneak peek if you will at
part six where i actually did fix this
problem so here's the same exact tile
structure same scenario in part six
without the glitch now how i did this
was i basically just clamped his
movement velocity to
never exceed 16 pixels or one tile space
now if you just reduce the amount of
velocity that he jumps at
it can cause problems so for instance
here i'm going to take a look at part
five again here's part five i can jump
up above this tile if i have a a y
velocity of negative 20 pixels per frame
when i jump so obviously if i reduce
this to
15 and i save
it's gonna it's going to eliminate the
possibility of tunneling
that's great but now i can't jump up on
my platforms anymore so how do i fix
this well the way to fix it is to go
ahead and change your gravity and
friction
at least that's one way to fix it so i'm
going to save that so it's back the way
it was i'm going to come over here and
i'm going to take a look at the code
excuse me let's take a look at the code
inside of part 6.
so
in part 6 i'm still using a velocity of
negative 15 when i jump
the only difference is now i'm clamping
my movement velocity when i
update the player's position
so basically to do that i'm just saying
if the absolute value of the player's x
velocity or y velocity is greater than
some max velocity and that's going to be
16 or 15 basically our tile size or
maybe one less just to be safe
if it's greater than that then we're
going to set our velocity to
the max velocity and actually this code
is wrong because i don't want to change
the sign
of my velocity
i just want to change the
amount of my velocity so but you get the
idea part 6 is still in development
basically what you want to do is you
want to clamp your movement speed
and
to get the same jump height
with the different y velocity what you
do is you just reduce
gravity and friction so here is
what a jump looks like in part five
as you can see he jumps a lot faster
it's kind of almost too quick so this is
almost an improvement for visuals as
well this is part six where i've kind of
changed it up so he can
have a clamped velocity and he just
moves a little more smoothly if you look
at it it's a little more smooth
here's part five again
jumps really far really fast it's a
little bit
too quick
part six
a little more smooth hopefully you can
pick that up with my my video recorder
here because sometimes it doesn't quite
match the frame rate of the game when
it's recording
so
basically what you want to do to fix
tunneling is you want to clamp your jump
speed
so
the amount of velocity that you apply to
a jump and that's going to be where a
lot of your velocity comes into play
high velocities when you're jumping
that's going to be a thing you wanna
clamp it to
an amount that's less than one tile
space
then in order to
get the height of the jump that you want
you're gonna have to reduce uh gravity
and friction
so for me i came in when i defined the
world object
what i do is i just have
gravity and friction defined here so for
example friction if i change the value
of friction to say
0.9
0.99 that's going to be really low
friction so if i come over here and
refresh
now i'm going to have really really low
friction
and as you can see i'm just moving
really fast all over the place jump
really far really fast because there's
no friction
so i don't want that but that's
basically how you fix tunneling you just
basically have to clamp your velocity to
a certain speed and to get the jump
height that you want you just
mess with friction and gravity and
that's gonna do it for tunneling
i'm going to show you how to create
level data files using json how to load
level data and use it to populate the
game world and finally how to trigger
subsequent level loads by colliding with
doors
let's take a look at what has changed
since part five and part five and a half
so this is part six and everything is
basically the same
i did make quite a few changes but most
of those changes pertain to loading
different levels so when i jump up into
this area here and walk off the side of
the screen it's actually going to load a
different level as you just saw so how
how this is working is i have a little
door hit region just off the right of
the screen here and it's just a
rectangular box and when the player
character's center point hits that box
it loads the level and places the player
in
whatever location he needs to be to
start this level out when walking
through that door from the other level
so basically in part six i just have a
couple different levels and i've defined
a couple different types of doors
they're all just rectangles you just saw
two small rectangular doors this area on
the bottom of this level is one big
rectangular door so i can jump up
through it at any point
in this rectangle so this system works
great for any size door doesn't just
have to be one tile it can be any size
rectangle that you define
so that's basically part six so now that
you know what the example program is
about let's get into how this works
before we get into the javascript code
let's actually take a look at the
different level files so this would be
level zero zero or i call it zone zero
zero so the file to load this level that
you see on the screen is this file right
here zone zero zero and basically it's
just a couple of
different json structures so i have a
doors array and inside of that i just
have the doors that are contained in
this level so for this level level zero
zero or zone zero zero i have one door
just to the right of this tile the door
would be right here off the level that
you see on the screen
and
this json here defines an array of doors
and this object inside of it will be
that door object that resides right over
here
so that's my doors array down here i
have some information about the maps
each map has 12 columns and 9 rows i did
not format this so you could actually
see it in kind of a 2d
row and column format i just have it in
one big long array but if i were to line
this up so each
row had 12 columns in it you would see
that the maps are 12 columns by 9 rows
but this is my graphics map so these are
all my graphics tile values this is my
collision map so these are all the
collision values for the tiles
and then finally i have id and that's
just going to be the level id so like i
said this is zone zero zero so when i
load zone zero zero this just tells my
world object that
it's
zone id zero zero
so
now let's take a look at zone two and
we'll just take a look at zone two's
code really quick just so you get it in
your head that this is what the the
format is
so here's my doors array zone two has
two doors there's a door right here to
go back into zone zero or actually it's
zone one excuse me
because i start labeling a zero but this
is zone one and it leads back into zone
zero zero there's a door right off the
left side of the screen
here and it goes into zone zero two with
a door right over here on the far right
side of the screen so inside of my doors
array i have defined two door objects
and then same as before i have my
columns and rows and my two maps and the
id that just indicates what zone this is
so
if you know how to write javascript you
know how to write json for the most part
it's really easy and it's a really great
natural fit for
writing information that you're going to
load into your javascript game because
it's so similar to javascript already
and you have the built-in
json.parse method to parse this
information into usable javascript
objects so now that you know how to
write the level data let's get on to the
next part of the video
okay so now that we know how to define
our level data we need to figure out a
way to load it and the best way to load
it is with
xmlhttprequest so
inside of my main.js file i have a class
called assets manager and it basically
just has a function called request json
inside of it
so in order to load my json file i'm
going to call this request.json function
i'm going to pass in the url of the file
to load so basically i'm just if i want
to load zone 0 0 i'm going to pass in
the string
zone00.json and i'm going to provide a
callback function but i'll get to the
callback function later so first thing
i'm going to do is create an xml http
request i'm going to give it an
eventlistener for the load event
and i'm going to have an event handler
for when it loads which is just going to
call my callback and hand in the parsed
json
string from my json file so
i'm going to send off my request to the
server it's going to process it it's
going to hand me back the
file content
remember that file was
zone00.json
it's literally going to hand back
this stuff in response text or just text
format
and i'm going to take that response text
or the content my json file i'm going to
use json.parse to turn it into a
javascript object and i'm going to call
the callback
so that's the request json file that
we're going to use to actually load our
data so now let's take a look at where
we first load up a level when we first
start the game and that's going to
happen all the way at the bottom of the
main js file in the initial the
initialization section
so
this is where we're using the request
json file to load up our very first
level so when i click refresh
my code is gonna run in main.js
and this
right here is gonna be responsible for
loading up zone zero zero which is on
the screen right here so let's just take
a look at what we're handing in
calling assets manager dot request json
zone prefix that's just gonna be the
string zone for the first part of our
url
game.world.zone id
when i first instantiate
game it creates an object called world
so game.world is a world object and that
has a default value in it of
0 zero for world zero zero or zone zero
zero so that's where we're going to get
the zero zero from this is going to be
zero zero and zone suffix is just gonna
be
dot json so i have the zone prefix of
zone plus the game dot world dot zone id
which is zero zero plus zone suffix
which is going to be dot json
so i'm going to hand in that url to
request json it's going to send a
request to the server when the server
returns
the json data inside of zone zero zero
in text format i'm going to parse it
into a js or a javascript object
and then i'm going to hand that
javascript object into my callback
function which is just going to be
defined here i defined it in arrow
function format
so
this is my callback function and
remember that i passed in json.parse
request.responsetext so that's going to
be the javascript object that i created
from my
zone file
and i'm going to hand that into
game.world.setup so let's go ahead and
take a look real quick at
game.world.setup
and also where we
create the very first
default value for zone id so let me see
if i can find where i'm at here i'm
inside of the game file
and this is the
game.world.prototype so
let's go up a little bit more
game.world this is where we define
game.world let me real quick just take a
look at the default value for zone id
so remember the default value for zone
id we're going to use that right here
when we're loading our first level
so that's just going to be defined right
here
right now the default value is zero zero
so when i refresh the page
the first level it loads is zero zero if
i change that to say zero one and save
it
and refresh the page keep an eye on the
level map it's gonna load up world zero
one if i change it again let's go world
zero two save we're gonna load up and
it's gonna immediately well it dropped
us in world two but we fell down into
world three so basically this sets our
default level to load initially when we
boot up the game
so
that's where we defined that but now
we're going to take a look at
game.world.setup where we actually put
all the information from our zone file
into our game.world object which we use
on every frame of animation to do stuff
with our game so
down here is the
setup function this is game.world.setup
and it takes one parameter which is the
zone which we just parsed into a
javascript object from our
zone00.json file
so
basically all we do is copy over all the
values from our newly created zone
object and we copy those values into our
world object
pretty simple
the only one we don't copy directly is
the doors array
and the reason for that is because i
want to use
a door object that i defined i'll talk
about that in the next part but we do
loop through all the doors in the zone's
doors array and we just create a new
door from the doors that we loop through
so inside of this
zone file we have an array called doors
every object inside we get and we
convert this data
into
a
game.door object so this class here
we're just going to create a door object
from the door data inside of our
zone.doors array so whatever door we
loop over in that doors array gonna be
converted into a game.door class and
that's what we're gonna use for our
actual game
logic and game physics when we collide
with the doors and stuff
now we finally know how we're setting up
the very first initial level
i'm getting out of breath here i'm
talking so much but
now we need to know one more thing and
that's how to actually go ahead and load
a level
on the fly when we when we walk into a
door so
where we do that is inside of the update
function for the game so on every cycle
of our game engine
on every game loop so to speak we're
going to call this function from inside
of main and this is the update function
so the first thing we do is get some
user input then we call game.update
game.uptake
takes care of moving the player takes
care of all the world collision
and inside of the game.update function
is the world.update function so let's go
ahead and take a look at
world.update real quick
already inside a world
uh game.world.prototype so this is the
game.world.update function which is
called inside of the game.update
function which we're calling right here
so basically this function is going to
call this function
so
first thing we do is update the player's
position we collide the player with the
world this refers to game.world
so we're going to cloud the player with
the world so all the tiles and then
we're going to come down here and we're
going to loop through all the doors in
the world in the current region or zone
of the world
we're going to get each door
and we're going to test for collision
with the door and it's just basic
rectangular collision i'll cover in the
next part of the video basically if we
do collide with the door so if the
player actually collides with the door
we're going to set
this dot door or game.world.door
equal to that door that we just collided
with so
normally this dot door is undefined
so out here in our update function which
is called on every frame
we're going to
test to see if game.world.door is not
equal to undefined and the only time
it's not equal to undefined is when for
a split second we actually walk into it
and
then this if statement returns true and
we go ahead and load the world that was
specified by whatever door we collided
with so let's just go through this real
quick and see what happens the first
thing that happens when i run into a
door
so if i run into a door the first thing
that happens is i stop the engine
i then make a request with request json
to
whatever zone that door
brings you to so if i come up here into
my zone00.json
we're in zone zero zero
the destination zone for this specific
door located at an x of 192 which is
about there and a y of 64 which is about
there has a width and height of 16. so
right off the right of the screen here
is a box that's about 16 by 16 pixels
and when i collide with it it's gonna
load
zone zero one and it's going to put the
player at destination x of zero and
negative one just means we're not going
to use destination y so the player's y
destination remains the same but i'll
get into that in the next part
um
so basically we're gonna request
the
destination zone specified by that door
so
this door here that we're about to walk
in right to the right of the player will
tell us to go to world or zone zero one
so when i walk into it
this code loads up zone zero one
pretty simple the same thing that we did
for the initial level load we're just
doing again right here even have the
same arrow function with uh
the zone parameter specified inside then
inside of our callback after request
json requests the level data the server
gives it back to us in text format it
parses that into a json object called
zone and hands it back to us we're just
going to call game.world.setup
and it's going to get all the
information out of the level file and
put it on the screen basically
so there is one difference this time
however because now we're going to have
to use some information from a specific
door so let me go back inside the
game.world.setup function real quick
i'm going to scroll up to it
right here game.world.setup
and we check for the case that we are
colliding with the door because remember
when we
enter into collision with the door we
set the world's this dot door property
equal to the door
so when we call setup this dot door is
actually going to be equal to whatever
door we just collided with so if i come
over here
and collide with the door that's right
over here
it's going to be equal to that door that
i just clouded with and it's basically
it's just going to set the player's x
and y center position to whatever the
door's destination x and y values were
that's it really simple everything else
works the same as the initial level load
the only difference is when you walk
into a specific door
you reposition the player according to
that door's destination x and
destination y so stay tuned for the next
part where i'm going to talk about the
door class specifically the collision
and all that kind of good stuff
now i want to take a look at what a door
actually is so if i zoom in here i'm
going to look at what a door is inside
of my zone00.json
file i've got an x position and a y
position a width and a height so
basically my door is just a rectangular
region on the screen somewhere that the
player object can collide with
then i also have a destination zone
that's going to be where the player is
going to go what level i'm going to load
if the player hits the door and i have a
destination x and a
destination y for the player as well so
this is where i'm gonna put the player
in the newly loaded zone when it loads
if i have a negative one that just means
destination y does not get used and the
player's y position remains the same
same thing for x if i have a negative
one
the destination x position isn't going
to be used the player's x position is
going to remain the same so we can see
this functionality over here
if i fall into this world
i'm not being repositioned on the y-axis
or on the x-axis rather because i don't
need to be i just want to fall right
through and naturally have my player end
up where he has to be
based on where he was in the previous
level i don't want to jump through this
floor door right here and end up at the
very start of the door over here in the
next level if i jump through over here
like if i jump through right here i
don't want to come out in this world
right here because it just wouldn't look
right
so that's the only reason i have a
negative one there but anyway let's look
at the door class the game.world.door
class and actually see what that looks
like and the collision code that i'm
using to have the player in the door
actually collide so if i could find that
wherever that is
scroll scroll scroll
hopefully i'll come across it soon
ah this is it right here so it's a
really simple object
i'm gonna
correct that small formatting error
there
really tiny object basically is the same
exact thing as this right here it just
has a prototype
defined with the collide object function
inside of it so
this is the door class and i'm going to
call object on it object all it is is
a rectangle class that has some
functions for helping me determine the
sides
of a rectangle so it has functions like
get left get right get top get bottom
just defining a rectangle here
inheriting from the object class then
i'm going to set the destination x y and
zone to whatever those are from the door
object that we hand in and that's just
going to be whatever is defined inside
of the zone file
then inside of the prototype i have a
function called collide object and
that's just going to test to see
if the object's center points
are
inside of the rectangular region of the
door so
this code right here just tests to see
if the player is not colliding with the
door if he's not then i'm going to
return false and that means we didn't
have a collision with the door if any of
this is true
or actually if any of this is false
then we know that we have collided with
the door and in that case we're going to
return true so where do we actually use
this that's going to be inside of the
world.update function so if i come down
here to worlds
world.update
right here there we go
okay so inside of world.update i have
all the doors defined inside of my
world.doors array i'm going to loop
through
every door in that array
i'm going to get each individual door
i'm gonna test to see if the door is
colliding with the player object and if
it is
i'm just gonna set the world's door
property equal to that door and then
just like in the last part we're going
to go into the
update function for our main game loop
game loop and inside of that we're going
to have an if statement that just checks
to see is game.world.door defined and
the only time it's defined is right
after we collide with the door so we're
going to stop the engine we're going to
load the level defined by the door by
the door's destination zone more
specifically we're going to set up that
zone in game.world.setup and we're going
to restart our engine now inside of
setup
i know i'm recapping stuff that i just
talked about but inside a setup we have
this is the inside of the setup function
we have an if statement that just checks
to see is this door or game.world.door
defined is it not undefined if it's
defined and we have a door in there
we're going to set the player's x and y
coordinates equal to whatever those were
defined
as by the door object and if it's not
equal to negative one then we know we
can set it up if it is equal to negative
one we just leave it alone so that's
like in this case here where i'm not
changing the player's x position
so for both of these doors this door up
here and this door down here for each
level respectively
the destination x position for that door
is going to be set to negative 1 because
i only want to change the player
character's y position
this way i don't have him jump through
here and start out over here on this
door
so that's basically it that's how i
define my door objects and
that's how to load levels with doors
i'm going to show you how i define the
carrot and grass objects in the level
data file their respective classes and
the basic collision detection used to
collide with the carat objects
the first thing i'm going to talk about
is what this example program is all
about and where the carrot and grass
objects are defined because since the
last installment of this series i have
since added carrot objects and grass
objects you can see that i'm running
into the carrot objects and when i
collide with their hitbox i collect a
carrot i have a carrot counter at the
top left of the screen and then down
here i have some grass
objects and all the grass objects are
are just
objects with an x and y position and
they have an animator inside of them
they extend the animator class and it
just updates the image on every frame of
the grass to give the impression that
the grass is actually swaying back and
forth so
just some basic objects i've added and
if i come over here and take a look at
the zone file
you can see that
this is my level data file and i have an
array for carrots i have an array for
grass and basically they're just little
arrays inside of here that define an x
tile position and a y tile position so
if i come over here to my map and i
refresh this carrot is going to be at
position
1 comma 2. so the x tile is going to
start at 0 and go to 1 because this
right here is 1 2. so x tile of 1 y tile
of 2 so if i count from zero i get zero
one on my x tile axis and for the y tile
axis i have zero one two so i know that
from this map i wanna carry it at
position one two and that's that carrot
same thing for the grass my first grass
tile is at x position two y position
seven
and that's going to be this grass object
right here
so pretty simple so when i load my level
up i'm gonna actually have to loop
through these arrays here get the x and
y tile positions from them and then
create an object
from that x and y tile position and if i
am looping through the carrots array
i'll create a carrot object if i'm
looping through the grass array i'll
create a grass object so let's go in and
check out the setup function of the
game.world object
the setup function just runs i come over
here and refresh my screen the setup
function runs right after the level data
is loaded so right after i load this
level data and i get access to it with
json.parse
i then call the setup function i pass in
the json object that i just parsed after
i loaded that level data from json and i
go ahead and i set up all of the game
objects
and the graphics and collision map and
everything for this level
and then i'm going to go ahead and i'm
going to loop through the zones carrots
array and the zones grass array and
basically those are literally just going
to be
these two arrays right here
so i'm going to loop through them and
i'm going to create a new carrot and a
new grass object for every instance of
one of those little
x and y tile arrays that i come across
inside of the zone file so what that
looks like is i'm just going to use a
for loop i'm going to go ahead and i'm
going to loop through all the carrot
objects inside of my zone's carrots
array which is just the little tiny x
and y tile arrays
i'm going to create a carrot
object or not an object but a variable
to store that x and y position from the
zone.carrots array and then i'm going to
store a new game.carrot
inside of
my
game's actual carrots array that i'm
going to use on every frame of animation
inside of my game cycles for my game
loop so what i'm going to do is i'm
going to feed it in x position in pixels
not in tile space so i'm going to take
the x tile position of the carrot which
is located at position 0 inside of that
array that we loaded from the
level data and i'm going to multiply it
by the tileset.tile height which is 16
pixels plus 5 is just going to give me
an offset so if i were to
come out here and make this plus 0
and save
i come over here what's going to happen
is i'm no longer going to i'm not going
to have an offset of 5 pixels anymore so
you can see they're kind of offset to
the left by 5.
if i come back in here and i undo that
the z control z
save come back over here and refresh now
all my carrots are in the right position
pretty much
i do the same thing with the grass
basically i just loop through all the
grass in the level data file and i
create a new instance a new grass object
and i just position it based on the x
and y tile values stored in my level
data so that's it next i'm going to take
a look at the actual classes that we use
to make the grass and carrot objects
now we're going to take a look at the
grass and the carrot classes
respectively so first i'm going to start
out with the grass class and all it is
is really simply an animator object it
inherits from animator this way i can
animate the frames
and it also has an x and y position if
you look at a grass object which is just
this right down here obviously all it
does is sit in a location so that's
going to be my x and y position and it
is animated so it's going to have to
inherit from the animator now the
animator class is the same class that i
use to animate the rabbit it can be
reused for all different kinds of game
objects to give them an animation so
really simply the grass class just has
an animation and a position and the
carrot class kind of does too but it
also has a lot more so let's go up and
take a look at the carat class
and see what makes it move and how we
collide with it with the player object
so here's the carrot class and it
inherits from the object class the
game.object class as well as the
animator class so the animator class
just gives it the animation
the object class is what's going to give
it its x and y position as well as its
width and its height and in addition to
those things it also gets the collide
object function which is going to
be responsible for allowing us to
collide with a carrot and actually
collect it so
that's important to note
then some cool features about the carrot
we have the base x y and position x y
values so base x and base y are just
referring to
the
center position that the carrot is
rotating around or making that figure
eight around so that's going to be the
base x and base y position the carat
does still have an
x and y position that's going to be
where it's actually drawn to the base x
and base y are going to be just the
point that it rotates around
position x and position y are going to
be
vectors that the caret is placed
by the amount of the vector on whichever
axis away from the base x so to explain
that a little more clearly
if base x is in the center position x
and position y are going to be distances
away from the base on their respective
axes and that's what's going to
determine how far from the base the
carrot is
and we're going to i'll show you how i'm
using position x and position y in a
second
just going to move down here but i set a
random value up here
and
that basically just
makes all the carrots kind of have a
different um path because otherwise if i
just set this up to be
let's see
zero
all the carrots would have the same
rotation pattern they'd all be
synchronized basically so if you look
now you can see very clearly that
they're all synchronized and that's kind
of a bad look so
just go back to how it was before
save and now you can see that they all
kind of move independently and it's a
lot less jarring to look at because
before it was almost like there was a
big
just
solid image of carrots with the
transparent background just moving back
and forth on the screen that's not what
we want to go for we want to have
independent movement we want to have
things looking like everything is random
so also speaking about that up here the
frame index
if you notice all the carrots on screen
are not sharing the same uh
animation sequence well they they're
they're sharing the same frames
obviously but
if you look at two you can see that
they're animating at different rates
i just have to find two that are going
at offset values here
these two this one and this one they
display the
opposite frame from one another so when
this one is on frame zero this one's on
frame one when this one's on frame one
this one's on frame zero that keeps
things looking fresh so
if i come up here and change this to
just be
zero
it's going to reduce the
randomization and we're just gonna have
everything animating the same exact way
almost like it's updating from the same
exact animation object so that's not
what we want either we want things to
randomly update their animation not
randomly but look like they have their
own unique animation even though they're
displaying the same frame so to do that
all i'm doing is i'm starting off the
animation at
a
randomized frame index
alright so now let's take a look at what
actually makes these things rotate
around the base x and base y position
inside of the game.carrot.prototype
which is going to be the prototype for
our charact class i have a function
called update position and that's oh
that's the only function for this class
and this is going to be called on every
frame of animation we're going to talk
about this in the next part
but
all it does is it updates the position x
and position y value
and
sets the actual x and actual y value of
the carat object which we're going to
use to draw it to the screen so
excuse me position x and position y what
it does
is it's just a distance from the base so
you can think of it as a vector distance
from the base
so
oh actually well that is true but
when i'm updating these
it kind of controls the speed of the
animation so if i were to make this five
and this
nine and save we're gonna see the
carrots move a lot more quickly so when
i press refresh up here
now they're really moving like those
guys are jumping around quite a bit
there so that controls the speed at
which things move because on every frame
of the animation i'm adding uh 0.5 or
0.9 to these and that's going to make
the thing move a lot more quickly
obviously
so let's get back to how things were
save come down here and look at how we
actually use these
so
math.cosine and math.sine are what's
going to give us that circular motion
and we just plug in position x and
position y into cosine and sine
and over here we have a multiplier of
two
that's going to control the distance
that the carrot sways on the x-axis so
if i come over here and refresh to get
things back to normal
you can see that it sways a little bit
further from side to side than it does
from up to from top to bottom there
so the reason for that is because of
this two
if i were to make this a 10
and save that
the carrots are going to sway a lot more
from side to side than they do right now
so now you can see they're really
swaying from side to side but that looks
kind of ridiculous so we don't want that
but basically what's happening here is
we're just increasing we're incrementing
up position x and position y
uh math.cosine and math.sine
give us a nice uh
rounded or circular
kind of effect there and then the
multiplier is just going to be how big
is that distance vector from the base
position
i guess it's actually a scalar because
it's only one single value but together
they make a vector so
let's just put that back to two
so on every frame i'm going to call
update position and this code is going
to run and it's going to make the carrot
move back and forth
now if i refresh
everything's back to normal so next i'm
going to talk about how we actually do
the collision between the carrot and the
player
to do the collision detection between
the player object and the carat object
we need a function that basically just
does collision detection between two
square hitboxes so where that function
is is inside of game.object so i'm going
to scroll up to game.object
and we're going to take a look at the
function that we used to do that hit
detection so here's the
game.object.prototype
that's just the prototype for our game
the object class and we have collide
object
and what collide object does is it just
tests for square collision detection
between two rectangular objects so
this object is going to collide with the
parameter object that i hand in
so basically i'll be able to hand in two
objects
and
determine whether or not their hitboxes
are overlapping so
just wanted to show you this function
and
now you'll kind of know where the
collision detection function is coming
from
where i'm actually utilizing all this is
going to be inside of
game.worlds
update function so i'm going to come all
the way down to the bottom
all the way down past the player object
pass the tile set object to the world
object inside of the
not the setup function
but the update function so here we are
inside of the update function and here
we are going to call all of this code on
every frame of our game's animation
and we start up we uh we update the
player's position we collide the player
with the game world to get the tile
collision going and then we're going to
start colliding with carrots so we have
a carrots array that's going to hold all
of our carrot objects that we created
inside of game.setup or game.world.setup
rather we're going to loop through all
of those carat objects so just these
guys here and we are going to update the
carrots position we're going to animate
the carrot
and then we're going to say is the
carrot colliding with the player with
the clad object function
if that function returns true we're
going to splice that specific carrot out
of the carrots array
and we're going to just remove it
completely and we're going to add one
two carat count and it's as simple as
that we're just going to test for
collision between the player and the
carrot
if collision occurs we're going to just
remove the carrot carrot object is
totally gone it will be garbage
collected later on assuming that i
removed all references to it and i think
i have so then what's gonna happen is
i'm going to increase carrot count by
one
and carrot count is what we're using to
update this p element's inner html right
here so where does that happen that
happens inside of the main js file
if i come down to the render function i
have a p element it's referenced with
the p variable
and
i just set its inner html to equal
carrots plus
game.world.carrotcount on every frame
and that's it
so i hope you guys learned something i
hope you enjoyed the video and i'll see
you guys next time