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. Subtitles by the Amara.org community