Detecting the Edges of the Screen¶
In these notes you will learn:
- How to test if a point has hit an edge of the screen.
- Some basic uses of if-statements.
- The structure and terminology of basic if-statements.
- How to use variables to control the velocity of a ball.
Introduction¶
In this note we’ll see how to get an object to recognize the edges of the screen by using if-statements.
Detecting the Bottom Edge¶
Lets start with a program that makes a ball move slowly down the screen. When the ball hits the bottom, it disappears:
float x; // (x, y) is the center
float y; // of the ball
void setup() {
size(500, 500);
x = 250; // start near the top middle
y = 50; // of the screen
}
void draw() {
background(255); // draw the background
// draw the ball
noStroke();
fill(255, 0, 0);
ellipse(x, y, 50, 50);
x += 0; // add 0 to x
y += 1; // add 1 to y
}
Now lets modify this so that the ball wraps-around to the top of the screen. The means after it hits the bottom, it jumps back to the top.
To do this, we need to know when the ball has hit the bottom. We can do that
by adding an if-statement after x
and y
are incremented:
void draw() {
// ...
x += 0; // add 0 to x
y += 1; // add 1 to y
if (y > 499) { // if y is greater than 499, then
y = 0; // set y to be 0
}
}
Every time draw()
runs, it now checks to see if y
is bigger than 499,
i.e. if the ball has hit, or passed, the bottom of the screen.
If it has hit the bottom, then y
is set to 0 so that on the next call to
draw()
the ball starts at the top. This gives the appearance of wrapping-
around the screen.
Adding Velocity¶
Now lets make a useful improvement to our program. In addition to a position, all animated objects also have a velocity, which is the speed and direction the object is travelling in.
We will often want to change the velocity of an object, e.g. make it stop or slow down or speed up. To make that possible, the velocity must be represented as variables so that we can, when needed, vary the velocity.
The standard names for the velocity variables are dx
and dy
, where the
d stands for “difference”. For example, dx
is the difference in the
x
values in two consecutive calls to draw()
.
Now lets re-write the above program using dx
and dy
:
float x; // (x, y) is the center
float y; // of the ball
float dx; // left/right velocity
float dy; // up/down velocity
void setup() {
size(500, 500);
x = 250; // start near the top middle
y = 50; // of the screen
dx = 0; // initialize the velocity so
dy = 1; // its moving downwards only
}
void draw() {
background(255); // draw the background
// draw the ball
noStroke();
fill(255, 0, 0);
ellipse(x, y, 50, 50);
x += dx; // add dx to x
y += dy; // add dy to y
if (y > 499) { // if y is greater than 499, then
y = 0; // set y to be 0
}
}
The behaviour should be the same as before, but now we can more easily control the ball’s velocity.
For example, to make the ball stop when it hits the bottom edge, change the if-statement to this:
if (y > 499) { // if y is greater than 499, then
dx = 0; // set stop the ball
dy = 0;
}
Setting both dx
and dy
to 0 immediately stops the ball.
Or, if want to make the ball reverse direction, we would change the if- statement to this:
if (y > 499) { // if y is greater than 499, then
dy = -dy; // reverse the y-direction
}
The statement dy = -dy
means “assign to dy
the negation of dy
”.
This flips the sign of dy
, which has the effect of changing the ball’s
direction.
Note
All the 2-dimensional animated objects we create in this course will
have, at least, these four variables: x
, y
, dx
, and dy
.
Some objects might have (many!) more, but these are the minimum set of
variables we need to do interesting animation.
Changing the Color¶
We can run any code we like when the ball hits the bottom of the screen. Lets make the ball’s color change to a random new color when it hits the bottom.
Since its color now varies, we’ll store its color in a variable called
ballFillColor
to store its color. Here is the modified program:
float x; // (x, y) is the center
float y; // of the ball
float dx; // left/right velocity
float dy; // up/down velocity
color ballFillColor;
void setup() {
size(500, 500);
x = 250; // start near the top middle
y = 50; // of the screen
dx = 0; // initialize the velocity so
dy = 1; // its moving downwards only
ballFillColor = color(255, 0, 0);
}
void draw() {
background(255); // draw the background
// draw the ball
noStroke();
fill(ballFillColor);
ellipse(x, y, 50, 50);
x += dx; // add dx to x
y += dy; // add dy to y
if (y > 499) { // if y is greater than 499, then
dy = -dy; // flip its sign and give it a random color
ballFillColor = color(random(256), random(256), random(256));
}
}
Checking for the Top Edge¶
Currently, our program only checks for the bottom edge of the screen. If we want to check for other edges, then we need to add if-statements that check for each edge:
void draw() {
// ...
// check if hit the bottom edge
if (y > 499) { // if y is greater than 499, then
dy = -dy; // flip its sign and give it a random color
ballFillColor = color(random(256), random(256), random(256));
}
// check if hit the top edge
if (y < 0) { // if y is less than 0, then
dy = -dy; // flip its sign and give it a random color
ballFillColor = color(random(256), random(256), random(256));
}
}
If you run the program now, the ball will bounce up and down forever, changing to a random color after each bounce.
Checking for the Left and Right Edges¶
We’ve set dx
to 0 in our program, which means the ball does not move left
or right at all. But if we set it to some non-zero value, then it will
eventually hit the left or right edge. So lets check for those two edges:
void draw() {
// ...
// check if hit the left edge
if (x < 0) { // if x is less than 0, then
dx = -dx; // flip its sign
ballFillColor = color(0, 0, 255);
}
// check if hit the top edge
if (x > 499) { // if y is greater than 499, then
dx = -dx; // flip its sign
ballFillColor = color(255, 255, 0);
}
}
Notice that we check the value of x
here (instead of y
), and that we
flip the sign of dx
(instead of dy
).
When you test this program, make sure to set both dx
and dy
to non-
zero values.
Bouncing Off Edges of the Ball¶
For simplicity, we’ve been making the ball bounce when its center point hits an edge. The problem with this is that the ball goes half-way off the screen on each edge, e.g:
Instead, suppose we want the ball to stop when its outside edge hits the a screen edge. Since the screen has four edges, we need to keep track of four different points on the ball:
- the top-most point, (
x
,y - 25
) - the bottom-most point, (
x
,y + 25
) - the left-most point, (
x - 25
,y
) - the right-most point, (
x + 25
,y
)
We need to modify the four if-statements to check for these points instead of
(x
, y
):
void draw() {
// ...
// check if hit the bottom edge
if (y + 25 > 499) {
// ...
}
// check if hit the top edge
if (y - 25 < 0) {
// ...
}
// check if hit the left edge
if (x - 25 < 0) {
// ...
}
// check if hit the top edge
if (x + 25 > 499) {
// ...
}
}
Be careful to get all the arithmetic exactly right!
Adjust the Ball’s Position on a Bounce¶
It is useful to add one more small feature to this program. When a fast-moving ball hits an edge, it’s possible that it goes a few pixels past the edge. In other words, the ball can be slightly embedded in the edge. When we reverse the direction of a ball embedded in an edge, it’s possible that the ball could get stuck forever.
We will try to prevent that problem by adjusting the position of the ball after it hits an edge. When we reverse the ball, we will also move it a little so that it is precisely on the edge. That way it will hopefully never get caught in an edge.
To implement this, we will need to modify the if-statements. For example:
// check if hit the bottom edge
if (y + 25 > 499) { // if y is greater than 499, then
dy = -dy; // flip its sign
y = 499 - 50;
ballFillColor = color(255, 0, 0);
}
The statement y = 499 - 50
was added. It makes sure that the ball is
exactly on the edge when it reverses direction.
For the top edge, the if-statement becomes this:
// check if hit the top edge
if (y - 25 < 0) { // if y is less than 0, then
dy = -dy; // flip its sign
y = 25;
ballFillColor = color(0, 255, 0);
}
The statement y = 25
has been added.
The if-statements for the left and right edges are modified in a similar way,
except the variable x
is used instead of y
.
Questions¶
- In brief, clear English, describe the purpose of an if-statement. Show how it works using a simple example.
- Why is the body of an if-statement indented?
- What do the variables
dx
anddy
mean in these programs? - In the program developed in the notes, we checked for edges in this order: bottom, top, left, and right. Would the program still work if we changed the order the edges were checked?
Programming Questions¶
Modify the final program below so that when the ball hits an edge it wraps- around (i.e. immediately jumps) to the opposite edge. Make sure no part of the ball is ever drawn off the screen.
Modify the final program below so that an image bounces around the screen instead of a ball. Make sure that no part of the image ever goes off the screen, i.e. it should bounce off its edges just like the ball.
Modify the final program below so that ball changes to a random color every time it hits an edge. Use this expression create a random color:
color(random(256), random(256), random(256))
Final Program¶
float x; // (x, y) is the center
float y; // of the ball
float dx; // left/right velocity
float dy; // up/down velocity
color ballFillColor;
void setup() {
size(500, 500);
x = 250; // start near the top middle
y = 50; // of the screen
dx = -2; // initialize the velocity so
dy = 1; // its moving downwards only
ballFillColor = color(255, 0, 0);
}
void draw() {
background(255); // draw the background
// draw the ball
noStroke();
fill(ballFillColor);
ellipse(x, y, 50, 50);
x += dx; // add dx to x
y += dy; // add dy to y
// check if hit the bottom edge
if (y + 25 > 499) { // if y is greater than 499, then
dy = -dy; // flip its sign
ballFillColor = color(random(256), random(256), random(256));
}
// check if hit the top edge
if (y - 25 < 0) { // if y is less than 0, then
dy = -dy; // flip its sign
ballFillColor = color(random(256), random(256), random(256));
}
// check if hit the left edge
if (x - 25 < 0) { // if x is less than 0, then
dx = -dx; // flip its sign
ballFillColor = color(random(256), random(256), random(256));
}
// check if hit the top edge
if (x + 25 > 499) { // if y is greater than 499, then
dx = -dx; // flip its sign
ballFillColor = color(random(256), random(256), random(256));
}
}