Objects - Object Communication

Resources:

Shiffman - 7.6: Object Communication Part 1 - p5.js
Shiffman - 7.7: Object Communication Part 2 - p5.js

Objects Want to Communicate!

One big advantage of object-oriented programming is that we can abstract object communication -- we can make objects talk to each other directly so that we don't need to mediate their "conversation" in a centralized way. In this simple example, we'll ask our Spot objects to check if they're overlapping (intersecting) with other Spot objects, and have them change colors (or other properties) if they are. This is a fundamental component of a lot of the generative art we've looked at, where simple rules between vast numbers of objects give rise to emergent properties.

The following code creates an array of 2 spots. Let's add a function called overlaps() and call it from the draw() function to see if spots[0] overlaps with spots[1] -- if so, let's change the color of spots[0].

Solution:

That's a great start on object communication! However, we'll ultimately want to make this functionality more reusable, so that objects can be checking themselves for overlaps (as opposed to us checking manually for overlaps between specific objects). We'll get to that in a bit -- first, a couple useful shortcuts:

Optional Default Arguments

Sometimes we want to provide default parameters to our class constructors (or other functions) in case we forget to pass the correct number of arguments, or if we just want default values in general. For the previous code example, we could have written the constructor in this way instead:

This gives us the option of specifying diameter when we construct the object. If we give it a 3rd parameter, it will use that as the diameter. If not, no worries, it'll stick with the default value of 30.

Returning True or False

Remember that conditional statements like (d < 5) must resolve to either true or false. That means we don't actually have to write out a full if/else expression. for the overlaps() method in the above code example, we can instead use the following shorthand and get the same result:

Autonomous Object Communication

We want to make our Spot objects more autonomous, in the sense that they should be responsible for determining their own overlaps. This makes a lot more sense if we consider having more than 2 objects. What if we had 100? We'd want to create a some kind of for() loop to iterate over each Spot and check for overlaps.

Let's create a for() loop to check for an overlap between the first object in the array and every other, changing the color of objects that overlap with spots[0]. Let's also increase the number of objects in the array:

Solution below. The obvious next thing we'd want to be able to do is to not just check for overlaps with spots[0], but rather check for overlaps among all the spots. So if a single loop could identify all overlaps between spots[0] and spots[i], we can use a nested loop to identify all overlaps between spots[i] and spots[j], where both i and j and incremented once for each spot in the array.

Solution:

for (... of ...) Syntax

We're used to using syntax like this: for (let i = 0; i < numSpots; i++){ to define a for() loop. However, since iterating over an entire array is such a common thing, there's a special syntax for that: for(let sp of spots){ is a shortcut for the same thing. The old way is still useful for iterating over parts of an array, or only over even numbers, etc. Try modifying the above code to use for(...of...) loops.

Solution: