-
Hello and welcome to a coding rainbow
coding challenge. Today's coding challenge
-
I'm going to attempt to make a flappy
bird clone which I admit it is kind of
-
like a bit of a cliché probably at this point
don't know how many people have made
-
flappy bird clone tutorial whatever's on
in the world but it was requested I
-
think it will be fu,n I'm going to give
it a try, I'm going to do it in
-
JavaScript I'm going to try to do it
fast
-
but with time to explain and time to
relax and just enjoy myself and
-
hopefully you might enjoy watching this. So umm
-
if you're not familiar with flappy bird
then I would say pause this video and go
-
familiarize yourself with it.
I actually don't think I've ever
-
actually played it before but I am
somewhat familiar with the gameplay
-
we'll see how well I do, I've got a live
chat going on and you guys can tell me
-
how I'm doing
-
if you're watching this is a YouTube
archive you won't be able to follow
-
along live but that's fine.
-
Ok so I'm using p5.js which is a
JavaScript framework has a function setup
-
it has a function draw and so the only
thing I've got so far in the browser is
-
just a canvas
-
that's 400 x 600 pixels and a black
background on that canvas
-
so the first thing that I want to do I
actually have a separate javascript file
-
called bird.js and I'm actually
going to make this a constructor
-
function and the bird.. all the bird
really needs is a y-value, right? The bird
-
moves up and down
and it stays in one spot
-
so I'm going to give this.. bird.. I'm going
to start the bird off in the center of
-
the window and I'm going to write also a
function called show where I draw the
-
bird and again I'm gonna.. my design is
going to be very poor so it's going to
-
be up to you to take my code which will
be linked in this description and make
-
something more beautiful and interesting
and reef off with this so I'm just going to
-
say let's make a white circle and you
what let's get this bird and x-position
-
as well even though it will be fixed but
let's just try
-
25 for right now and I'm gonna never
forget the.. ♫this dot♫ you always need
-
this dot in JavaScript. So let's make this
bird a circle and let's say in the
-
main program now
-
var bird and we're going to say bird
equals new bird and bird.show(), so we
-
should have something a little bit more
interesting now there it is
-
bird.. width/2 you know would probably
makes more sense if I want the bird to
-
be in the middle to be height/2
-
so let's fix that. I'm gonna say height/2,
I think the bird could be a little bit
-
bigger and the bird could be a little
bit more in on the screen
-
so there we go this is the beginning of
flappy bird now what happens to the bird
-
without you doing anything?
-
the bird falls down. So oops oops wrong window
-
so I'm going to go here and I'm going to
say this.update equals function and it
-
would be good to have some sort of
variable called gravity and gravity
-
being the force that's pushing that bird
down and let's say that the gravity
-
here is going to be one
-
I also need a velocity, right? I need a
velocity so gravity is the force that's
-
causing the velocity of the bird to
increase so I'm gonna say
-
this.velocity equals 0 and now I'm going to
say this.y changes by this.velocity
-
and this.velocity changes by
this.gravity
-
ok so now we have a function that's
going to push that bird down so I'm
-
gonna go over here and I'm going to say
also bird.update();
-
there we go bye bird it flew down. Now
-
we should probably do something where the
bird stops when it gets to the
-
bottom of the window
-
that makes sense so I'm gonna go back to
the bird and I'm gonna say.. I'll just do this
-
in the update function, I could write a
separate.. and I'm gonna say if this.y
-
is greater than height then
-
then I'm just gonna keep the bird
on the screen I'm going to say this.y
-
equals height and I'm also going to set
that velocity to zero so we can see here
-
that bird stops. I don't know if that's
actually what happens in flappy bird but
-
I just kind of want to do that anyway
-
and you know what I'm going to do that
also for the top of the window because
-
ultimately I'm going to be able to push
the bird up
-
so let's do that for less than zero,
now of course...
-
oh ok so now what.. How does the game work?
-
I think it's a mobile game right you
could tap your mobile device.. this is my
-
mobile device
-
so I mean as a tap I'm going to just
use the spacebar on my keyboard so in p5.js
-
I can write a function called
keypPessed and I can check to see if the
-
key is the space bar
-
and let me just make sure this is working
I'm just going to console log something
-
right now so I'm going to run this and you
can see each time I press the spacebar
-
it says here in the console, it prints out,
SPACE. So that works
-
so what do I want to do I want to cause a
force to cause that bird to go up so I'm
-
going to say bird.up and so what's
going to happen with this bird.up
-
function?
-
What do I want to do.. I want instead of
the velocity being pushed down by
-
gravity
-
I want to say this.velocity minus
equals, I want it to go up or I could say
-
plus equals but some minus amount
-
now what if I just said minus this.gravity?
Let's try that for a second just to see
-
what happens
-
Come on! Wait oh you know what's a little bit
annoying, I have to.. oh I took off that
-
console.log(), hold on.
-
Let's say minus equals this.gravity
times 10 so nothing's working here and I
-
have a kind of a sneaking suspicion that
I've done something totally wrong
-
bird.up let's make sure this
is happening.
-
I'm gonna say print line this.velocity
-
ok so you can see that's working so
let's try to tune.. I think there's sort
-
of an issue here we've got to sort of
tune the numbers
-
so let's make the gravity just for right
now a lot less strong so it's not going
-
so fast
-
now you can see though that this isn't
really doing very much
-
let's make a this.up force
-
let's call this lift and we'll say it's
negative 10
-
so I'm going to say this.velocity
plus equals this.lift; not left lift.
-
There we go, so you can see there's a
sort of an element of tuning those
-
numbers
-
so now it doesn't really feel like it's
falling fast enough but me pushing the
-
spacebar is kind of working out.
-
What happens if I hold down the spacebar?
so that's good ok so that lift is too
-
much. Let's make the gravity 0.6 and
let's keep the lift there but now I'm
-
going to need to make the lift a little
bit stronger.
-
There we go, so this..
-
so now I have, I sort of have the game
going and lift is a little bit too strong
-
let's make it less strong
-
so this you know, something something
that I could do is actually limit the
-
top speed or also like give
it some.. something that I could also do
-
is add some like air resistance in
general which I could say something like
-
this.velocity times equals 0.9
so that actually like helps with things
-
quite a bit because it's just there's
some sort of like a limit to what the
-
speed is so now I've got something that
is a bit more kind of like reasonable to
-
play here. So you could spend your time
tuning this even more but I think just
-
like keeping the velocity keeping some
like air resistance by always shrinking
-
the velocity a little bit
-
tuning how much the lift is versus the
gravity those types of things you can
-
kind of play around with.
-
Ok, so now we have the basic game
mechanic here which is just a falling
-
circle and each time I press the
spacebar
-
I can kind of like have it lift up a
little bit. Now what do we need to add? We
-
need to add those pipe things that kind
of come from the right of the screen,
-
I'm only at eight minutes by the way
which is pretty good; the pipes things
-
that come from the right of the screen
and you have to steer your way through.
-
Let's see if we can do this. So let's
think about this, I'm going to also
-
create a pipe object with a constructor
function and let's think about what
-
does a pipe need?
-
So a pipe needs, I would say it's going
to extend from the top to somewhere in
-
the middle of the screen and then
somewhere further down to the bottom so
-
I need, I'm going to say like a value
called top which is going to be some
-
random amount between the top of the
screen and the middle of the screen and
-
let's say this.bottom is some random
amount also between the middle of the
-
screen in the bottom of the screen and
the pipe also needs an x-position
-
which is always going to start at the
edge of the screen and then let's
-
write a function called show where I
draw the pipe
-
as a white.. fill white and I draw a
rectangle at this.x, 0 all the
-
way with a width of like, let's say the
width is 20 and let's actually make that
-
a variable and this..
-
a width and also the height then is this.top
and then I need another rectangle
-
which starts from the bottom
-
minus how tall it is and let's make.. minus
this.bottom and its height is this.bottom.
-
Okay in case this isn't
making sense to you
-
that's actually.. let's actually do a
quick diagram here. What I'm trying to do
-
is create something that looks like this
-
so I need two random numbers this length
is what I'm calling top, this length is
-
what I'm calling bottom and then this
length.. this width is what I'm calling w.
-
So I first draw a rectangle from here
with this width with a height of top and
-
then I draw a rectangle from here which
is height
-
minus bottom which is this point with this
width and then the height of that
-
rectangle is bottom.
-
So this is what I'm getting and if these
values are random I'll sometimes get stuff
-
that looks like this
-
etc. Now I could be more
thoughtful like right now the way that
-
I'm doing it
-
there's.. this.. you could never get
something that looks like this. So it
-
probably would make a.. I could probably
do something different where I pick like
-
a random empty amount of space and then
I pick a random starting point for that
-
empty amount of space. That might be
interesting to do, we can make that as an
-
improvement later but let's just stick
with what I have right now which I think
-
is good enough
-
ok am back over here and let's just see
now I need a function like this.update
-
and all I want to do in this.update is
say this.x minus equals some speed
-
this.speed. So let's say this.speed
is always going to be 5. I'm gonna just..
-
so all of these are always going to
move to the left. So let's look now here
-
in sketch I'm going to create an array
called pipes and what I'm going to do is
-
say
-
pipes.push a new pipe; and then in draw
-
I'm going to say for all of the pipes in
the array
-
yeah I also have a problem with this,
somebody in the chat is saying, where I could
-
technically have a pipe with no space in
it. So all that stuff can be corrected
-
later and I want to say show and I want
to say update.
-
So let's run this now and see. There we
go, that's moving quite fast.
-
So let's go back to the pipe and let's
just make the speed 1. So we could see
-
aah look we basically have
flappy bird already
-
it's so easy to play so it's moving
kind of slow now but of course I only
-
have one. So let's think about this,
-
what.. couple of things that I want to do;
one is I want to I want to say something
-
like if frameCount, I want to have a
pipe every like so often, modulus 40
-
equals zero which means every 40 frames,
the modulus operator being the remainder
-
of division. So anytime a number is
divisible by 40 with a remainder of 0 is
-
0 40 80 120 160 etc
-
let's add a new pipe and
let's see how this looks
-
that's a lot of.. that's a lot of.. every
40 frames is quite a view. Look at this, oh
-
I'm pretty good at this
-
♪ta da da da♪ I need some like
music to play along with this. Okay so
-
that's no good obviously. Lets umm
-
let's make the pipes move a little bit
faster, twice as fast, and let's uh let's
-
say every hundred frames. So obviously
you can see uh how the speed of the
-
pipes, how frequent they are and we can
see basically I have the game right now.
-
I've made a very easy version of the
game to play
-
it's not very hard but one thing that I
haven't done is figure out when I need
-
to actually., you know this, i'm doing a
great job here so let's actually add
-
something that shows us when the circle
hits the pipe or doesn't hit the pipe so
-
and also by the way I should be getting
rid of the pipes at some point so one
-
thing I should do is I should I should
say
-
if pipes index I is finished and I can
actually just say x is less than zero..
-
you know what I'm going to write a
function. I'll write a function called
-
offscreen so if the pipe is off the
screen
-
I want to say pipes.splice(i, 1)
-
so splice is a function that deletes an
element from the array. So I want to know
-
if the pipe went off the screen, get rid
of it
-
I don't need it anymore. Now of course
there's a little bit of an issue here
-
which is one is there's no such thing as
a function called offscreen that's a
-
function I have to write.
-
There's another issue here which is that
when I'm deleting stuff out of the array
-
I really should go through the array
backwards and I've covered that in other
-
videos but basically the array slides..
the elements slide back and if I'm going
-
forwards, the elements slide back while am going
forward I could end up skipping things.
-
So I'm just going to switch my loop to
saying greater than or equal to 0 and
-
i minus minus, and then
I'm gonna.. if I run this, right?
-
no function named offscreen so I have
to go into the pipe and I have to write
-
a function called this.offscreen is a
function and this is very simple, I can
-
just say if this.x is less than
negative w, right? because I want it to be
-
all the way off
-
so it's width has to be all the way off;
return true else return false and now I know
-
all of you watching this video are
going to complain to me and just say, "But
-
couldn't you just say return this.x is
less than negative w because that
-
evaluates to true or false."
-
Yes, I could do that but you know what
sometimes I like to write my code this
-
way. I like it to be long-winded, multiple
line, I love the way that curly brackets
-
just nest themselves so beautifully, I love
to say a return true return false
-
you can write your code a different way
but yeah and now I sort of feel like I
-
should change it but I'm not going to
-
I'll do it later. Okay, so coming back
let's see now we should see.. oops w is not
-
defined
-
so I have to say ♪this dot this dot♫
-
I always forget the this dot. Ok,
now we should see.. now I can't really
-
tell if this is working, I can only
assume this is working but if I do
-
something where I say like this
-
oh pipes.length, if I look at the
length of that array it's two and it's
-
always two.
-
So even though I'm adding more and more
they're getting deleted, ok, so we can be
-
pretty sure that that's working.
-
Ok now let's see, now we've got to do the
exciting part here .. I mean this whole
-
thing hopefully is somewhat exciting but
we've really got to get the gameplay
-
mechanic where you..
-
it's going to give you some visual
feedback if you hit one of those pipes.
-
So let's think about how we might write
this, ultimately here's where I have
-
this single bird that says bird.update
bird.show
-
and I'm also looping through all the
pipes so one thing I could do, I don't
-
really need to do it this way but I'm
gonna I'm gonna move this loop first
-
just so the bird comes after and I'm
going to say here I'm going to say if
-
pipes index i hits the bird
-
then do something. I'm just going to say
console.log("HIT"); so I need to have a
-
function that determines if a pipe has
hit the bird
-
so if looking at this bit of code you
can see here what do I need to write?
-
I need to write a function called hits
and that function is going to be part of
-
the pipe object and its going to receive
a bird object as an argument
-
so I'm gonna go to the pipe object and I'm
going to write, I'm just going to write
-
the function up there.. here, this.hits
-
I called it hits equals function bird and
now I just need to check. What do I need
-
to check?
-
I need to check if bird.y is less than
the top and bird.. or
-
or bird.y is greater than height
-
minus this.bottom. So if the bird is ever..
-
if I come back here to my whiteboard if
the bird is ever, right?
-
less than top or greater than height minus
bottom here then it's kind of it's
-
hitting that.. it's hitting that pipe.
-
So let's come back over here. Did I get
that right is greater than height.. okay, so
-
then I want to say return true
although this isn't good enough, right?
-
It's also got to be within the actual
x-position
-
so we should also say and I uh I could I
mean I could be much better about how I
-
construct this but I'm gonna
put it inside here
-
so let's just say it's within that stuff
also lets now check if bird.x
-
it's x-position is greater than this.x
and bird.x is less than this.x
-
plus this.w
-
so I'm also just checking if it's in
between the actual x-position of the
-
pipe
-
so if all of that is true I'm going to return
true. You know am just working it out we
-
could.. I could.. this double if statement
is kind of an awful way to write this
-
and I could probably be more clever and I
could write a separate function that
-
just tests intersection between a circle
and a rectangle but right now this will
-
be good enough for us right now and I
look forward to hearing your
-
improvements and suggestions in the
comments
-
so let's just see here if.. whoops,
-
right now I'm not seeing anything. Hit hit ahaa
-
so this is basically working, you can see
that anytime,
-
this is gonna be hard; so
let's actually give ourselves some
-
visual feedback
-
if this is the case, let's write a
variable called highlight set it equal
-
to false
-
let's also say this.highlight equals
true and then under fill.. under show I'm going
-
to say if this.highlight
-
I'm going to say fill(2..), I'm gonna make
it red
-
so let's just see if this gives us some
nice visual feedback. Oh you know what I
-
never said highlight equal to false so
watch it hits it
-
so you know that's fine but I might want
to actually also say
-
this.highlight equals false, hope it's
not hitting it, so now here we go
-
it hits it you can see. So now I could add
things like score
-
I could be more careful about like I'm
really only checking the center
-
go go go
-
tada dada dada.. this is way too easy to
play, oop, there we go. Okay so you get the
-
idea so I i think that I've kind of
completed this and there's a lot of
-
improvements that would want to make to
this in terms of being more thoughtful
-
about checking that intersection to be a
bit more precise good enough though..
-
be a bit..
-
I could do a better job of picking the,
the way that.. oh here's a difficult one;
-
a better job of how I pick the top and
bottom heights of these rectangles
-
I could add score, right? You start with
a score maybe as time goes on your
-
score goes up every time you hit a pipe
the score goes down, all those things.
-
I would say umm ask me your questions in
the comments, suggest, make versions of
-
this and tweet me your exciting,
doesn't you know.. you could make a nice bird
-
design you can reimagine this entire
game to not be a bird and pipes but to be
-
you know a flower and rainbows I don't
know how that would work
-
so ummm
-
tweet me and share with me all of
your interesting variations on this and
-
I'll maybe come back and do some Q&A
video where I follow up on some of your
-
questions and make some improvements to
this flappy bird challenge. Okay, thanks
-
for watching and I will see you in a
future coding challenge.
-
Goodbye.