Objects and Images

Resources:

Shiffman - 7.8: Objects and Images - p5.js

Exercise 5.0

We've already looked at how to load images using loadimage() and display images using image(). Let's start Exercise 5.0 together by opening a blank sketch.js file in your assignments directory (or just copy a previous sub-folder, whatever you're used to doing by now). Inside the sketch.js file, let's create a Box class that will contain our bouncing images. Let's also make an 'assets' folder, and place some png files inside. Here are some pngs of Marge, Homer, and Bart if you don't already have images you'd like to use.

For this Exercise, create an object-oriented screen saver that loads at least 3 unique images and assigns them randomly to an array of objects. When a user clicks on an object, its image should randomly change. Once completed, please make sure to upload your Exercise in order to get credit.

Rectangles vs. Ellipses

Before loading images, let's use rect() as a placeholder. The dimensions on the rectangle are determined by width and height, and not a single diameter. So instead of a this.diameter, we'll need to store a this.w and this.h. Accordingly, we'll need to write a different bounce() function and overlap() function. Also, by default rect() draws from the top left corner point of the rectangle, not from the center. We can change that using rectMode(CENTER), but let's not do that for now.

Add Images

If we name our images something sequential like 0.png, 1.png, 2.png, it's easy to automate loading them. Instead of writing loadImage('assets/bart.png'); then loadImage('assets/homer.png'); and so on and so on, we can simply make a for() loop to count from 0 to however many images you have, and store those images in an array, like this:

This uses what's called string concatenation. In JavaScript, adding 5 + 4 = 9, but adding "five" + "four" = "fivefour". In other words, when you try to add strings, JavaScript merges them into a single string. We can use this feature to create a series like 'assets/0.png', 'assets/1.png', 'assets/2.png', etc.

Next, we'll need to add an associated image to each object. Let's create a new constructor argument, so the constructor expects an image as well as an x and y coordinate. We still construct each object from the setup() function. However, this time we'll pass the extra argument for the associated image. We can even randomly select an element from our array by simply writing random(images). Finally, within the constructor, store the image to the object using something like: this.img = _img;

Finally, add a mouseClicked() function that each time the mouse is clicked loops through each spot and calls a spot.clicked() method to see if that spot contains the mouseX, mouseY at the time of the click. In that clicked() method, pick a new random image if clicked. Optionally, you could also try changing images whenever they bounce. Make sure to upload your exercise!

Transformations

p5 has a novel way of dealing with transformations. It makes it seem a little difficult to do things like simple rotation at first, but its usefulness becomes apparent when you're trying to do nested systems for example, like a solar system. The main syntax we'll use for transformations is translate(), rotate(), scale(), push(), and pop().

The translate() function moves our origin point to somewhere else on the canvas. This becomes the new (0,0), and becomes the pivot point to use for rotations. The code below first moves the origin, then draws a rect() at the origin. It's the same as simply writing rect(50, 50, 100, 50);

Why would we want to do this? Because transformations are cumulative. In other words, this method makes it easy to make geometry relative to other geometry. Try making another rectangle without changing the translation. What happens if you replace the translate(50, 50) with translate(mouseX, mouseY)? Transformations do get reset to (0,0) on each pass of the draw() loop.

Rotate()

The other main reason to do use transformations is for rotation. We need to specify a pivot point, because otherwise the rotate() function will assume the canvas (0,0) point (top left corner) to be the pivot point.

By default, p5 wants to calculate angles using radians as opposed to degrees. We can change that by declaring angleMode(DEGREES); in the setup() function.