(bell dings)
- Hello, it's (laughs) Throwback Wednesday.
I don't know when you're watching this.
It's probably not even Wednesday,
but it is Wednesday right now.
I am going to do an old-fashioned
Coding Train-style Coding Challenge.
(train whistle blows)
I'm going to attempt to make the bouncing DVD video logo (DVD Screensaver),
and I'm going to attempt to do it in 10 minutes.
I'm sure this one's going to go horribly wrong.
I should never use this timer.
Nothing ever, no good never comes from it,
but I'm going to try.
Here's the one thing I'm excited about
here with this challenge.
If you're a beginner, if you have never programmed before,
I'm hoping that this is a coding challenge
that you could follow
and actually possibly create yourself, but,
so beginners, welcome!
I'm going to try to talk through all the concepts,
and I'm going to use very few, the basic beginner concepts
of programming in JavaScript using the P5 library.
Go to editor.p5js.org.
I'm going to pull that up in a second
where I'll be typing the code.
So this is the bouncing DVD logo,
and I think I got plenty of time.
I'm going to wait like 20 seconds just to see
if it hits the corner.
Come on, come on, oh no.
Okay, anyway, I should probably move on.
So what do I need?
Oh and I wanted to also do a quick shout out
and thank you to Mike Boyd who learned to code
from a lot of different resources including
possibly the Coding Train, I think.
Check out this video, he makes this really awesome game,
and also at some point tries to make a bouncing DVD logo
which is where this idea came from.
So let me move over to the white board,
and just talk through a couple concepts.
So I'm going to create something in HTML called a canvas,
and I'm going to use the p5 library which has a nice function
for doing that called Create Canvas.
And I'm going to make my canvas 800 by 600
because this is four, has an aspect ratio of four by three,
400 times 200 is 800 by 600.
And that's the aspect ratio of old timey television tubes.
Not like this fancy YouTube
with your like 16 by nine aspect ratio.
Whoa, it's so fancy.
And then, I need to draw an image of that DVD logo,
and I need to place it randomly somewhere in this canvas.
Its location is going to be defined by the corner,
that's going to be sorry, it's x,y location,
and then I need to determine when it hits the edge
and have it bounce off that edge.
And according to my research, I actually did some research,
into the science behind this DVD logo thing
which actually there's all sorts of formula
to calculate the probability
of when it's going to hit the corner,
and all sorts of stuff like that.
I'm going to include a link to that article
in this video's description.
It is always moving in a direction
where its x-speed, and y-speed are equal.
So essentially at a 45, it always starts
at a 45 degree angle pointing down,
and then ricochets off the edges
and maybe someday, hits the corner.
I got seven minutes left, let's go.
Alright, so the first thing I want to do is,
I already forget.
(laughing)
Oh, go to the p5 editor.
This is editor.p5js.org, and you can see here
I've made a canvas, it's 800 by 600,
and I've drawn a background of zero, that means black.
So this draw function is looping over and over again,
and setup is happening just once.
Set up the canvas, draw that background over and over again.
So what I need is I need to keep track of that x,
and the y position of the DVD logo.
So I need a variable, I need x to store the x-position,
and y to store the y-position.
And by the way, the way the canvas works
is zero,zero is in the top left here,
this is X equal zero, y equals zero,
all the way up to x equals 799, so it's 800 wide,
zero through 799, think about that.
I know I'm going too fast.
Check my other tutorials where I speak hopefully,
a little bit slower.
Alright, so I'm just going to set x equal to 400
and y equal to 300, and I'm actually just going to draw
a rectangle that's 80 by 60.
Sorry, a rectangle at x and y,
so this, I want to draw a rectangle at x and y,
and I want the width of the rectangle to be 80,
and the height of the rectangle to be 60.
These are p5.js, the JavaScript live p5.js functions
to draw things like rectangles and circles and lines.
You can look them up in the reference
which I will also link to in this videos description.
Okay, there we go.
Look, there it is, wahoo!
Now I need to have something that tells me
its rate of change along the x axis,
and rate of change along the y axis.
I should note that y points down.
Y points down, x points to the right.
So if this were three, this were three,
I heard somebody say, "oh, in the actual thing,
"it moves like 10 units per frame."
I don't know, but we can think of how many pixels
does it move down and to the right?
So let's try with 10.
So I'm going to call that xspeed, and I'm going to have yspeed.
These, by the way, are known as global variables,
so they're variables that I can use throughout the program.
I want to initialize them in setup
and then use them in draw.
So I'm going to say xspeed equals 10,
yspeed equals 10.
I need separate variables because when it bounces
on one side, the y continues to go down
but the x reverses direction,
or when it's on the top the y changes direction,
but the x stays the same.
So then, what I need to do,
let's just make sure this runs.
It runs, what I need to do is say x equals x plus xspeed,
y, and let's just do that.
So every time draw is looping, x equals x,
oops goodbye, it's gone.
Run that again.
Look, it's moving.
Oh, it's gone.
So x is changing every time draw loops,
which is like around 30 frames per second.
And then I want to say y equals y plus yspeed,
and there we go.
It's moving down, you can see that, it's moving down
and to the right.
And now, for the exciting part.
I mean, isn't this all exciting?
I need to figure out how do I turn it around?
So I need to check, there's something in programing
called an if statement.
When do I want to turn it around?
I want it to turn around if it hits the edge.
If it hits the edge, change the amount,
change the value of xspeed, reverse it's direction.
So if xspeed is positive,
then xspeed should be negative.
So I can say if x equals,
and this is a little bit flawed
but I'm going to do this right now,
equals the width.
Width is a variable, by the way,
that's keeping track of the width of the canvas,
which is 800, then xspeed equals xspeed times negative one.
Multiply any number by negative one,
10 becomes negative 10, negative 10 becomes 10.
Oh, I only have three minutes left,
got to keep moving here.
Okay, there we go, look oh boy.
Let's add also,
a y, if y equals the height, see what happens.
Oh it kind of, what, oh what's going on here?
Let's change where it starts.
I'm just going to let it start a little bit higher
so you can actually see.
Look, it bounced.
But one thing I'm not taking into an account
it's x y position is this corner,
so when it equals the edge,
it's actually sitting here off of the screen.
So I need to know when this corner.
So actually what I want to say is
when x plus it's width, which is 80,
plus 80 equals width, then reverse its speed.
Look at that.
And then when y plus what?
60 equals height, oh whoa.
Oh, but I don't want to change the xspeed,
I want the yspeed to change when it's y.
Boom, boom, oh this is looking good, okay.
Now I've got to do the other spots.
Well, I can use something called an else if,
so you can say else if x equals zero,
xspeed equals xspeed times negative one.
But you know what, there's another way I could do this.
I could actually say or, or if x equals zero.
I want to do the same thing.
So this weird double pipe symbol means or.
So and by the way, to test if something is equals,
I have to use two equals, two equals,
and I can actually use three.
That's a whole other story,
in a one minute I don't have time to get to it.
But there's a reason why you might use double equals
or triple equals, but just more than one equals
is asking the question.
So now I'm going to say or y equals zero.
Let's look at this,
and then I need a closed bracket, and then let's see.
What's going on, I'm missing something here.
Oh, I've got an extra parenthesis.
There we go.
Okay, there we go, okay.
Let me give myself a little more room here.
A little more room here, okay.
Here we go, let's run this.
Oh!
Line 32 token, missing token unexpected.
Okay, here we go.
Oh no, the bug happened.
Oh no.
Oh no. (static fizzing)
(bell dinging) Oh hi, I said
I wasn't going to edit anything
but I had to take a little like short break there,
because my code disappeared in the browser
then the timer went to zero, but now my code is back.
It was some mystical magic floated into this room,
but this is where I was a moment ago.
I now have two if statements checking to see
if this rectangle hits the right side,
the left side, right side or the left side,
reverse the xspeed, the bottom or the top
reverse the yspeed.
And Simon loyal viewer, Simon,
pointed out that another way I could write this
is just like this.
Set the speed equal to negative of itself,
and there we go.
Now, now for the really exciting moment.
Let's get that DVD logo.
So I've already downloaded this png file
of the DVD logo itself,
and what I'm going to do is I'm going to click
on this little arrow here,
I am going to add a file,
then I'm going to drag the DVD logo file here.
Upload it, I'm going to say I am done.
We can see now the DVD logo is part of my project.
So I'm going to add some new code.
I'm going to have a variable called DVD.
I'm going to add something called preload.
Preload is a block of code, a function,
where it's good to write things you want to happen.
Like I know I said setup is stuff that happens
in the beginning, preload is like the pre-setup,
and something that I want to do there
is like load media assets.
So I'm going to say, what did I call it, dvd_logo.png.
By the way, in the meantime,
I selected this auto-refresh thing,
so that it's rerunning the code every time I make a change.
And now what I can do is instead of drawing a rectangle,
by the way this is a way I can turn off a line of code,
it's really called a code comment.
I'm going to say draw the DVD logo,
and I can take this exact line of code
but instead of saying rectangle,
I can say image, and then I can say image,
or what did I call it?
DVD, at the same location.
So look at that, there's the DVD logo.
Now I might have messed with it's dimensions,
I can actually just use it's native dimensions.
Oh, but now it's not bouncing correctly,
so let's actually look at what it's dimensions are.
I can just in the Apple finder, I can see it's
128, oh I guessed it, 128 by 76.
So I can change those numbers,
but the true of the matter is it's not such a great idea
to have hard coded numbers in your code,
like 128 and 76, but the nice thing is
I can actually day dvd.width.
So the image itself the DVD image
knows it's own width, and I can also say instead,
plus a dvd.height.
And now it, whoa.
No?
Oh boy, I have done something bad.
I have done something bad, terrible, big mistake in coding.
Ah-ha!
So it's generally not such a good idea
to check if something's exactly equal,
because you never know, I'm saying oh, of course.
Ah, and oh my goodness.
This is really, really bad.
So it only worked by accident
because oh, I can't believe I didn't think of this.
Because that the multiple, right,
if this starts at like 100, and I'm adding
10 to it every time, and this width is 800,
I am going to, at some point, get to the fact
that it's equal to 800.
But this width is like 128, x plus 128
plus some multiple of 10 is never going to
actually end up equaling 800.
So I just want to basically, just check
if goes passed the width and the height.
And I'm not sure.
Or what I probably want to do is resize the image
to be something but this is now going to be fine.
Okay, so I can move this console down,
I should do this again.
(laughing)
This is actually what programming is, by the way.
And now, here we go.
Bouncing DVD logo.
Some things I want to do to this.
Number one, is I want it to start in a random position
every time, so I can use the random function.
So this will now, every time I run the code,
it'll start, oh look at that.
It's stuck, oh, oh, oh no.
Oh God.
Everything, oh this is the worst.
This is the worst.
Alright, there's another problem here
(groaning)
'cause now I'm not using integer math,
and I'm letting a random.
Oh, this is what I need to do, let me separate this out.
I'm going to say, I'm going to be very strict
about this DVD logo.
I'm going to say if it goes passed the width,
reverse its direction,
and set it to that spot.
Shuffle it back, and I got to do this now separately.
I got to do the same thing,
then I'm going to set it back equal to zero.
So there's this issue that can happen
where it can go kind of like passed the edge
and then make it all the way back on, I think.
And so, I'm going to do this now for the x, the y.
But I am now made this little bit more complicated,
but I'm saying okay, when it gets to the edge,
if it went passed the edge just slide it back on
before you turn around.
Right, just set it back to this location
and this is not right.
Width minus dvd.width.
Right, that's where I want to set it back too.
Otherwise, if it gets to the left
set it back to the left and keep going.
If it gets to the bottom,
and this of course, is height minus,
it's y plus dvd.height is greater than height,
then set it back to height minus dvd.height.
Okay.
(drums banging)
Yes!
Okay, now we got to do something else.
We got to do something else.
I've got to add a red, green and blue value.
So I'm just going to say r, g, b.
You can declare three variables at once,
by the way, with commas.
And then, I want those values to be,
you're going to see why, I want those values
to be some random number between, zero and 255.
And then, I'm going to say
tint r, g, b.
So tint is a function that allows me to tint the image.
Look, so every time I run this,
it's going to be a different color.
Now I think I want to like guarantee,
I want it to have some amount of brightness.
So I could do like a hue saturation brightness thing,
but I'm just going to limit the bottom range to 10.
And then, every time it hits one of the edges,
I'm actually going to put this in a separate function
called function pickColor.
And I'm going to say pickColor, I'm going to call that function.
So this is me making up a new function,
and then calling that function
because I want to reuse that code,
so in all of these cases, and really...
("Refactor" by Espen Sande Larsen)
♪ I will refactor this later ya know. ♪
There's got to be a nicer way to write this.
♪ I will refactor this later ♪
And here we go.
So now, we're done, all done!
(bell dinging)
And thank you for watching this coding challenge.
(whistle blowing)
I'm sorry this turned into something of a mess.
I hope that you will take this
and make your own variation on it,
play with it, use different imagery,
different way of moving, different way
of checking the corning.
Maybe you'll make some kind of beautiful particle effect
when it hits the corner,
or maybe you'll think of a new idea
and who cares about the corner.
How about the middle, what if it crosses the perfect middle?
I don't know, the world of the bouncing DVD logo
is now yours to play with.
I don't know, hope you learned something,
had a little bit of fun.
If you want to learn more about programming
I basically do this exact same thing
in my foundations of JavaScript with p5.js
tutorial series, but kind of step through
all these concepts quite a bit more slowly.
I don't know whether that's going to be helpful
or interesting to you, but you're welcome to watch it.
Thanks, and see you in a future coding challenge.
(whistle blowing)
(upbeat music)