A Spinning Box¶
In these notes we’ll create a class for a rectangle that can move and spin. It’s a good example of how to go about creating your own animated sprites.
We will need the Sprite
class:
class Sprite {
float x;
float y;
float dx;
float dy;
void update() {
x += dx;
y += dy;
}
}
Here is the SpinningBox
class, and its variables:
class SpinningBox extends Sprite {
float width;
float height;
float angleInDegrees;
float dAngle; // rate of change of angle
color fillColor;
color strokeColor;
// ...
} // class SpinningBox
Recall that extends Sprite
means that a copy of all the variables and
functions in the Sprite
class will be put in SpinningBox
. So, we don’t
need to add x
, y
, dx
, or dy
because they are inherited from
Sprite
.
The render()
function draws the box, while the update()
function makes
it move:
void render() {
rectMode(CENTER);
pushMatrix();
// move the origin to the center of the box
translate(x, y);
rotate(radians(angleInDegrees));
fill(fillColor);
stroke(strokeColor);
rect(0, 0, w, h);
popMatrix();
}
void update() {
super.update();
angleInDegrees += dAngle;
}
This draws the box centered at, and rotated around, the point (x
, y
).
The statement super.update()
calls that update()
function in the
Sprite
class. The term “super” refers to the fact that Sprite
is the
“super class” of SpinningBox
.
Here’s a program that animates it:
SpinningBox b = new SpinningBox();
void setup() {
size(500, 500);
b.x = 250;
b.y = 250;
b.w = 200;
b.h = 150;
b.angleInDegrees = 0;
b.dAngle = 2;
b.fillColor = color(0, 255, 0);
b.strokeColor = color(255, 0, 0);
}
void draw() {
background(255);
b.render();
b.update();
}
Changing update¶
To change how the box moves, modify update()
. For example:
class SpinningBox extends Sprite {
// ...
void update() {
// super.update();
angleInDegrees += dAngle;
w = map(mouseY, 0, 500, 50, 300);
h = map(mouseX, 0, 500, 50, 300);
x = mouseX;
y = mouseY;
}
} // class SpinningBox
The call to super.update()
has been commented-out but left in as a
reminder that we can call if it we want the default Sprite
update
behaviour.
Multiple Spinning Boxes¶
It’s easy to make as many spinning boxes as you like. For example:
Box b = new Box();
Box c = new Box();
void setup() {
size(500, 500);
b.x = 250;
b.y = 250;
b.w = 200;
b.h = 150;
b.angleInDegrees = 0;
b.dAngle = 2;
b.fillColor = color(0, 255, 0);
b.strokeColor = color(255, 0, 0);
c.x = 25;
c.y = 350;
c.w = 400;
c.h = 15;
c.angleInDegrees = 0;
c.dAngle = -0.5;
c.fillColor = color(23, 255, 44);
c.strokeColor = color(255, 200, 100);
}
void draw() {
background(255);
b.render();
b.update();
c.render();
c.update();
}
The procedure for creating and using sprites is always the same:
Create a class for your animated object that extends
Sprite
.Add a
render()
function that draws the object based on the current values of its variables.Do not put any code that changes variables in
render()
! Put all such code intoupdate()
.Add a customized
update()
function, callingsuper.update()
(theupdate()
function fromSprite
) if necessary. If you are happy with the defaultupdate()
inSprite
, then you don’t need a customupdate()
.Do not put any drawing code in update! All drawing code should be in
render()
.
To use a sprite, follow these steps:
Create an object using
new
and assign it to a variable, e.g.:SpinningBox b = new SpinningBox();
Inside
setup()
, assign initial values to all the variables in the object.Inside
draw()
, call the objectsrender()
function to display it on the screen, and itsupdate()
function to change its variables.
An Image Sprite¶
An image sprite is an animated object that draws an image.
Images behave similarly to rectangles, and so we will use SpinningBox
as a
guide for writing the ImageSprite
class:
class Sprite {
float x;
float y;
float dx;
float dy;
void update() {
x += dx;
y += dy;
}
}
class ImageSprite extends Sprite {
PImage img;
float angleInDegrees;
float dAngle;
void render() {
imageMode(CENTER);
pushMatrix();
// move the origin to the center of the image
translate(x, y);
rotate(radians(angleInDegrees));
image(img, 0, 0);
popMatrix();
}
void update() {
// super.update();
x = mouseX;
y = mouseY;
angleInDegrees += dAngle;
}
}
ImageSprite a = new ImageSprite();
void setup() {
size(500, 500);
a.img = loadImage("cat.jpg");
a.x = 250;
a.y = 250;
a.angleInDegrees = 0;
a.dAngle = 2;
}
void draw() {
background(255);
a.render();
a.update();
}
For this code to work, you must have an image file named cat.jpg
in your
program’s data
folder.
Questions¶
Why are
x
andy
not defined in theSpinningBox
class?What does the statement
super.update()
mean in theupdate()
function ofSpinningBox
? What would happen if that statement were deleted?What is the value of
b
immediately after this statement is executed:SpinningBox b;
Programming Questions¶
- Make a class called
SpinningTriangle
that extendsSprite
and makes a triangle move around the screen, and also rotate around one of its corner points. - Make a class called
BouncingBox
that extendsSprite
and makes a box bounce around the screen. Don’t let any part of the box go off the screen.
Source Code¶
class Sprite {
float x;
float y;
float dx;
float dy;
void update() {
x += dx;
y += dy;
}
}
class Box extends Sprite {
float w;
float h;
float angleInDegrees;
float dAngle; // rate of change of the angle
color fillColor;
color strokeColor;
void render() {
rectMode(CENTER);
pushMatrix();
// move the origin to the center of the box
translate(x, y);
rotate(radians(angleInDegrees));
fill(fillColor);
stroke(strokeColor);
rect(0, 0, w, h);
popMatrix();
}
void update() {
// super.update();
angleInDegrees += dAngle;
w = map(mouseY, 0, 500, 50, 300);
h = map(mouseX, 0, 500, 50, 300);
x = mouseX;
y = mouseY;
}
} // class Box
Box b = new Box();
Box c = new Box();
void setup() {
size(500, 500);
b.x = 250;
b.y = 250;
b.w = 200;
b.h = 150;
b.angleInDegrees = 0;
b.dAngle = 2;
b.fillColor = color(0, 255, 0);
b.strokeColor = color(255, 0, 0);
c.x = 25;
c.y = 350;
c.w = 400;
c.h = 15;
c.angleInDegrees = 0;
c.dAngle = -0.5;
c.fillColor = color(23, 255, 44);
c.strokeColor = color(255, 200, 100);
}
void draw() {
background(255);
b.render();
b.update();
c.render();
c.update();
}