It's me, back for another video about objects and classes
and stuff using JavaScript and p5.js.
So one of the things that I get asked all the time, I think.
I wander around the street and people are like, hey,
you there.
If I made a bunch of bubble objects in a canvas
in the browser-- can you imagine if this actually happened to me
on the street--
and I want to interact with them with a mouse individually,
how would I know if the mouse is hovering
over one versus the other?
How would I deal with that?
Well, just a little bit of this aside before.
So this is what I want to implement in this video.
How can you have the user interact
with individual objects?
How do I set the code to make that happen?
How does this work?
So here's the thing.
Eventually, if you're watching all
of these videos in the order that they are,
there is going to be a time in the future.
I actually recorded these videos in the past,
but for you it will be the future where I will add things
below the canvas.
Like, there will be a button here,
or like a box with text in it.
And the canvas is actually one of those things too.
On this page is a canvas.
I could put other things on this page.
Everything on a web page can register events.
It can register this event like a click-on--
that's not really an event-- or a mouse over,
and there's all sorts of fancy ways
in JavaScript and in p5.js.
to handle all these different types of events
to know how users are interacting with things.
But this thing here, this thing here is one thing, the canvas.
The only thing that p5.js.
Knows is if you're clicking on the canvas or not.
And actually to be honest, if you click off the canvas,
it's going to make one kind of like in its mind
off the canvas that might wonder on, which you just saw happen.
Because I'm using this global mouse pressed event.
I have an event, it's just press the mouse anywhere.
But what if I want to have an event
that's like only when I click on this circle.
So the circles are my own invention,
they are pixels that I've drawn in their space.
It's up to me as the programmer, the person
who designed this sketch to figure out how to handle that.
And so that's what I'm going to do in this video.
So let me think about, what would make sense?
I think what I'm going to do is I'm going to rewrite
this sketch a little bit.
I'm going to get rid of this mouse pressed function.
I mean, I'm going to come back to it.
But in Setup I'm going to say, let x equal random with.
Let y equal random height.
Let r equal random 10 comma 50.
And then I'm going to say, I'm just
going to make this new bubble.
I'm going to take this exact code from the bottom.
You're over there.
I'm like, I never know where to look.
One of these days I'll figure it out.
Take this exact code from the bottom,
and I'm going to make a new bubble, all right.
So actually, let's do this first.
Let's peel away from the array for a second.
And let's simplify our lives.
And I'm just going to make a single bubble object,
and that's going to be it, and forget about this array just
for a little bit.
And so I'll come back to the array eventually.
Now notice, I'm not changing this bubble class at all.
It's still the same thing.
All right, where is it?
Ah, but I do need to say that individual bubble move
bubble.show.
So what I want to do is I want to have something to happen
when I click on that bubble.
So your first instinct might be, aha.
Well, there's this mouse pressed function
that I can write out here.
Oh, ah, look at this.
I wrote this nice mouse pressed function right out here, yay.
So why not, why not.
There's this bubble class that I've
been learning all about it.
I know, let's just do this.
Console log clicked on bubble, right?
Won't that work?
That will work.
Oh, I'm so excited.
Oh, this is going to work.
Click, click, click, I hear click on the bubble.
Oh, nothing's happening.
Nothing's happening.
So I've sent you in the completely wrong direction.
Although the instinct is kind of right, yeah.
This is like a function that's just out in the wild.
It's global so it's for any mouse pressed.
This is a function that's inside of the bubble, so it's fine.
But here's the thing.
This function mouse pressed is a special function
that p5 recognizes.
Just like set up and draw are special functions
that p5 recognizes.
p5 is not going to go inside of these new classes
that you write and somehow recognize
that you have a mouse pressed function,
know where the object is, figure out,
this is not part of its capability.
I don't even know how it could even be capable of that.
But there isn't any reason why I couldn't write a function.
And you know, it's a little bit problematic for me
to call it mouse pressed.
So maybe, let's just call it clicked for right now.
There's no reason why I couldn't inside of the mouse pressed
function say, hey, whenever the user clicks the mouse,
I know that globally.
Why don't I just call another function inside any my objects
that need to handle that click.
So I would say bubble.clicked.
So now, look at this.
It's going to work.
Oh.
Let's get a bigger one.
It's going to work.
OK, I'm going to click on it.
Click on it.
Ah, look, I clicked on the bubble.
Look at me do it again.
Oh, I clicked on the bubble three times.
I'm going to click on it over here now, 6 times, 7 times, 8.
So here's the thing.
Remember, this is a global mouse pressed.
So I can call my function on this bubble object.
But it's just going to do this every single time.
It's up to me to write some code to figure out,
wherever I click the mouse, I know where the bubble is.
And I know how big it is.
This dot, if you know the x the y and the r,
we could write some code.
So I could say something like--
so here's a little bit of a moment here.
Let's say, one of the things I need to figure out
and I've probably done this in other videos,
but this seems like a nice time to talk it through.
If I had a circle, how do I know if a point is inside the circle
or is outside the circle?
Because what I'm trying to do is figure out, is the mouse--
that's the mouse arrow--
did it click outside or inside the circle?
I could ask the same question for a square.
I could ask that question for a triangle.
I could ask that question for some arbitrary strangely shaped
polygon.
And all of these are going to get progressively more complex.
A rectangle and a circle are pretty easy to do.
This is much harder, but all of this is possible.
The point is, I need to write some code to figure that out.
That code needs to go here.
Wherever that mouse is, is it actually related to where
this.x, this.y, this.r are?
So how do I do that?
So one of the nice things on p5 and both processing--
if you were using that instead--
have is a function called dist which stands for distance.
And I can give that function 2 points, arbitrarily x1, y1, x2,
y2.
So if I make one of those points the center of the circle,
maybe I'll call that cx, cy.
And then the other point over here for example
is the mouse where the mouse clicked.
We'll call that mx, my.
I could pass these values into that distance function
and get the length of this line.
Call that d.
Something that I happen to know from my code--
whoops, wrong button-- is r, the radius of the circle.
Now I'm actually using it as a radius, I am.
Because remember, the ellipse function itself
wants wants the diameter.
So r really means the radius which is half of the diameter.
What do I mean by that?
So I happen to know, this.r is this distance.
Or another way of looking at it is this distance right here.
So guess what, this is probably popping into your head
just about now.
If the distance between the center and the mouse
is greater than the radius, then that point
is outside the circle.
If it's less than the radius, then that point
is inside the circle.
OK, so now we can come over here,
and I can start to add that code.
I can say, let me find the distance between mouse
x, mouse y, and this dot x, and this dot y.
And I can now say--
now, this is not this.d because this is a local variable
that I'm using just to calculate.
At this moment, the distance is less than this.r.
Then the console log clicked on bubble.
Now we're really getting somewhere.
[DRUM ROLL]
OK, so this is a moment of success.
And that was really loud.
I don't know if that's going to ruin this video.
So what I've now successfully done
is I'm able to determine and only print out this statement.
So what's the full story here?
This is where I know that the mouse has
been pressed anywhere.
So it's up to me now to say, well,
if the mouse is pressed anywhere,
let's check if the mouse is pressed for this bubble.
And guess what?
Let's go back to the array now.
Let's put this array back.
Let's make this a single bubble.
Let's put that into the array.
And now this loop here, just like in Draw
when I want to move and show everything,
there's no reason why I couldn't when I click the mouse use
that same exact loop and just call
clicked on all the bubbles that are in that array.
So let's see if this works.
Whoops, OK, I have some error.
Bubble is not defined a draw.
So I forgot that I still have this old individual bubble
that I don't need anymore.
So I can click on it.
It worked.
I can click outside.
I don't see anything.
Let's actually add now.
Let's do this five times in Setup.
So I'm going to add 5 bubbles.
And now in theory, we're getting that message
if I click on any of them.
But here's the thing.
I really want something to happen.
So I could change its color.
Here's the thing.
What if I were to just hover over these bubbles, AND I
wanted to change their color if I
were to hover over the bubbles?
And then have something when I--
Well, actually, you know what?
Hold on.
There's another important point that I want to make.
There's something about this function
that I don't really like.
And yes, I'm going to do this from time to time.
And you will too, and it's OK.
But right there, I don't love the fact
that I'm using mouse x and mouse y.
Those are global variables.
In theory, I want my bubble class
to only know about itself.
It doesn't really need to know about the outside world.
It doesn't have to know it's on a canvas that there's a mouse.
And in theory, what I want to be able do
is write a generic bubble class that I could say,
hey, is the mouse clicking on you?
Or is this other object at the same location as you?
Or, I switch it to using like a connect to track my hand.
Is my hand location near this bubble?
So really what would make more sense
is for me to actually put arguments
into the click function.
And again, I'm doing this sort of awful thing
where I'm giving them the same name as properties
of the class itself.
I'm giving these parameters x and y
the same name as this.x, this.y.
But JavaScript is very good at distinguishing
because this x and y are the ones that are coming in
through the parameters.
And these here are the properties,
this dot of the object itself.
But maybe if I wanted to be a little less confusing about it,
I might say px, py for like pixel x or pixel y or something
like that.
And so now, what makes more sense
and what I really want to do is pass in mouse x, mouse y.
Because what I want to do when the mouse is pressed is ask,
does this point?
And really, I might do something like contains or inside
or it includes.
I could name that function some other way
because really what I'm asking is
that point inside that object.
So interestingly enough, what I could do
is let's give the bubbles a color.
I going to give it like a brightness and make it a 0.
And I'm going to say, fill this.brightness.
And I'll give it some alpha.
And then, what I am going to do is when I've clicked on them,
I am going to say this.brightness equals 255.
So the idea here is that now bubbles each
have a new property, a color.
It starts at 0.
And anytime I click on one of them,
I turn that one a different color.
So what's really nice about this is,
I have one function, one function
that's part of the class.
And I could use that function in any way that I want.
All that function does is test at any generic point
is inside a given object.
And if it is inside that shape, the geometry of that object,
if it is, I change its color.
And the way I happen to be using it is by saying, hey, whenever
the user clicks the mouse anywhere,
let's go check all the objects in our array
and see if the mouse is inside them.
So all right, I think this ends this particular video.
I need to do something.
One thing I would really actually like to do,
you should do an exercise here.
So if you're watching this, try to make
it do something different if you hover over the bubble,
change the bubble to a rectangle,
see if you can make the same thing work with a rectangle.
Allow yourself to click on it twice.
Turn it on and off.
That's something you could try.
And have a different behavior for when
you click on it versus when you just mouse
over it, those types of things.
But something that I want to do, and maybe I'll
do it in the next video is when I click on each one of these,
I remove them from the world.
So I can add bubbles and delete them sometimes.
We have to look at how to delete things from an array, OK?
See you in the next video, perhaps, maybe.
OK, goodbye.
[MUSIC PLAYING]