![]() |
Jupyter at Bryn Mawr College |
|
|
Public notebooks: /services/public/dblank / CS110 Intro to Computing / 2015-Spring / Lectures |
In this exploration, we examine the idea of an object, and begin writing our first object-oriented programming study.
This code is from the discussion on Bouncing Balls. We need to keep track of the ball's velocities in the x
and y
direction, keep track of where it is (x
, y
), and the global time.
float g = 9.8;
float vx;
float vy;
int x;
int y;
float dt;
float t;
void setup() {
size(200, 500);
x = width/2;
y = 50;
dt = 0.1;
t = 0;
vx = 50.0;
vy = 0.0;
}
void drawBall(int x, int y, int w, int h) {
fill(255, 0, 0);
ellipse(x, y, w, h);
}
void draw() {
// gravity
vy = vy + g * dt;
dx = vx * dt;
if (((x + dx) > width) || ((x + dx) < 0)) {
vx = vx * -0.8;
} else {
x = x + dx;
}
dy = vy * dt;
if (((y + dy) > height) || ((y + dy) < 0)) {
vy = vy * -0.8;
} else {
y = y + dy;
}
drawBall(x, y, 10, 10);
t = t + dt;
}
What if we wanted to add more balls? We would need to add variables for vx, vy, x, y... for each ball!
A better way is to let each ball keep track of its own properties. We do this by making a class definition, and storing each set of variables inside the Ball object.
Here we will move all of the ball-specific variables "into the Ball class" and leave the others. We create an array of Balls, and bounce each one.
// Globals:
float g = 9.8; // gravity
float dt = 0.1; // change in time
float t = 0; // current time
Ball [] balls; // the balls
class Ball {
int x;
int y;
int w;
int h;
float vx;
float vy;
// Jargon: the "constructor"
Ball(int x, int y, int w, int h, float vx, float vy) {
// Idea: "this" refers to the current ball
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.vx = vx;
this.vy = vy;
}
// Jargon: an object's function is called a "method"
void moveYourself() {
this.vy = this.vy + g * dt;
dx = this.vx * dt;
if (((this.x + dx) > width) || ((this.x + dx) < 0)) {
this.vx = this.vx * -0.8;
} else {
this.x = this.x + dx;
}
dy = this.vy * dt;
if (((this.y + dy) > height) || ((this.y + dy) < 0)) {
this.vy = this.vy * -0.8;
} else {
this.y = this.y + dy;
}
}
void drawYourself() {
fill(255, 0, 0);
ellipse(this.x, this.y, this.w, this.h);
}
}
void setup() {
size(200, 500);
balls = new Ball[1];
// Jargon: we create an "instance" of the Ball class:
balls[0] = new Ball(width/2, 50, 10, 10, 50.0, 0.0);
t = 0;
}
void draw() {
balls[0].moveYourself();
balls[0].drawYourself();
t = t + dt;
}
Cut and paste the above code and try some variations:
// Globals:
float g = 9.8; // gravity
float dt = 0.1; // change in time
float t = 0; // current time
Ball [] balls; // the balls
class Ball {
int x;
int y;
int w;
int h;
float vx;
float vy;
color c;
// Jargon: the "constructor"
Ball(int x, int y, int w, int h, float vx, float vy) {
// Idea: "this" refers to the current ball
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.vx = vx;
this.vy = vy;
this.c = color(random(255), random(255), random(255));
}
// Jargon: an object's function is called a "method"
void moveYourself() {
this.vy = this.vy + g * dt;
dx = this.vx * dt;
if (((this.x + dx) > width) || ((this.x + dx) < 0)) {
this.vx = this.vx * -0.8;
} else {
this.x = this.x + dx;
}
dy = this.vy * dt;
if (((this.y + dy) > height) || ((this.y + dy) < 0)) {
this.vy = this.vy * -0.8;
} else {
this.y = this.y + dy;
}
}
void drawYourself() {
fill(this.c);
ellipse(this.x, this.y, this.w, this.h);
}
}
void setup() {
size(200, 500);
balls = new Ball[1000];
// Jargon: we create an "instance" of the Ball class:
for (int i = 0; i < balls.length; i++) {
balls[i] = new Ball(width * random(), height * random(), 10, 10, random(50) - 25, 0.0);
}
t = 0;
}
void draw() {
background();
for (int i = 0; i < balls.length; i++) {
balls[i].moveYourself();
balls[i].drawYourself();
}
t = t + dt;
}
It would be cool if the balls could detect when they run into each other, just like it detects when it hits a wall. To do that, we go through the other balls, and identify when they "overlap".
Then, we simply swap their velocities.
// Globals:
float g = 9.8; // gravity
float dt = 0.1; // change in time
float t = 0; // current time
Ball [] balls; // the balls
float distance(float x1, float y1, float x2, float y2) {
return sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)))
}
class Ball {
color c;
int x;
int y;
int w;
int h;
float vx;
float vy;
Ball(color c, int x, int y, int w, int h, int vx, int vy) {
this.c = c;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.vx = vx;
this.vy = vy;
}
void move() {
this.vy = this.vy + g * dt;
for (int i = 0; i < balls.length; i++) {
if (balls[i] != this) {
if (distance(this.x, this.y, balls[i].x, balls[i].y) < (this.w/2 + balls[i].w/2)) {
temp = this.vx;
this.vx = balls[i].vx;
balls[i].vx = temp;
temp = this.vy;
this.vy = balls[i].vy;
balls[i].vy = temp;
break;
}
}
}
dx = this.vx * dt;
dy = this.vy * dt;
if (((this.x + dx) > width) || ((this.x + dx) < 0)) {
this.vx = this.vx * -0.8;
} else {
this.x = this.x + dx;
}
if (((this.y + dy) > height) || ((this.y + dy) < 0)) {
this.vy = this.vy * -0.8;
} else {
this.y = this.y + dy;
}
}
void draw() {
fill(this.c);
ellipse(this.x, this.y, this.w, this.h);
}
}
void setup() {
size(200, 500);
balls = new Ball[3];
balls[0] = new Ball(color(255, 0, 0), width/2, 40, 10, 10, 50.0, 0.0);
balls[1] = new Ball(color(0, 255, 0), width/2, 50, 10, 10, -40.0, 0.0);
balls[2] = new Ball(color(0, 0, 255), width/2, 60, 10, 10, 0.0, 0.0);
t = 0;
}
void draw() {
balls[0].move();
balls[0].draw();
balls[1].move();
balls[1].draw();
balls[2].move();
balls[2].draw();
t = t + dt;
}
Variations:
// Globals:
float g = 9.8; // gravity
float dt = 0.1; // change in time
float t = 0; // current time
Ball [] balls; // the balls
float distance(float x1, float y1, float x2, float y2) {
return sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)))
}
class Ball {
color c;
int x;
int y;
int w;
int h;
float vx;
float vy;
Ball(color c, int x, int y, int w, int h, int vx, int vy) {
this.c = c;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.vx = vx;
this.vy = vy;
}
void move() {
this.vy = this.vy + g * dt;
for (int i = 0; i < balls.length; i++) {
if (balls[i] != this) {
if (distance(this.x, this.y, balls[i].x, balls[i].y) < (this.w/2 + balls[i].w/2)) {
temp = this.vx;
this.vx = balls[i].vx;
balls[i].vx = temp;
temp = this.vy;
this.vy = balls[i].vy;
balls[i].vy = temp;
break;
}
}
}
dx = this.vx * dt;
dy = this.vy * dt;
if (((this.x + dx) > width) || ((this.x + dx) < 0)) {
this.vx = this.vx * -0.8;
} else {
this.x = this.x + dx;
}
if (((this.y + dy) > height) || ((this.y + dy) < 0)) {
this.vy = this.vy * -0.8;
} else {
this.y = this.y + dy;
}
}
void draw() {
fill(this.c);
ellipse(this.x, this.y, this.w, this.h);
}
}
void setup() {
background();
size(200, 500);
balls = new Ball[100];
for (int i = 0; i < balls.length; i++ ) {
balls[i] = new Ball(color(random(255), random(255), random(255)),
width * random(), height * random(), 10, 10,
random(50.0) - 25, 0.0);
}
t = 0;
}
void draw() {
for (int i = 0; i < balls.length; i++ ) {
balls[i].move();
balls[i].draw();
}
t = t + dt;
}
// Globals:
float g = 9.8; // gravity
float dt = 0.1; // change in time
float t = 0; // current time
Ball [] balls; // the balls
float distance(float x1, float y1, float x2, float y2) {
return sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)))
}
class Ball {
color c;
int x;
int y;
int w;
int h;
float vx;
float vy;
Ball(color c, int x, int y, int w, int h, int vx, int vy) {
this.c = c;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.vx = vx;
this.vy = vy;
}
void move() {
this.vy = this.vy + g * dt;
for (int i = 0; i < COUNT; i++) {
if (balls[i] != this) {
if (distance(this.x, this.y, balls[i].x, balls[i].y) < (this.w/2 + balls[i].w/2)) {
temp = this.vx;
this.vx = balls[i].vx;
balls[i].vx = temp;
temp = this.vy;
this.vy = balls[i].vy;
balls[i].vy = temp;
break;
}
}
}
dx = this.vx * dt;
dy = this.vy * dt;
if (((this.x + dx) > width) || ((this.x + dx) < 0)) {
this.vx = this.vx * -0.8;
} else {
this.x = this.x + dx;
}
if (((this.y + dy) > height) || ((this.y + dy) < 0)) {
this.vy = this.vy * -0.8;
} else {
this.y = this.y + dy;
}
}
void draw() {
fill(this.c);
ellipse(this.x, this.y, this.w, this.h);
}
}
void setup() {
size(200, 500);
balls = new Ball[100];
COUNT = 0;
t = 0;
}
COUNT = 0;
void mousePressed() {
balls[COUNT] = new Ball(color(random(255), random(255), random(255)),
mouseX, mouseY, 10, 10, random(50) - 25, 0);
COUNT++;
}
void draw() {
for (int i = 0; i < COUNT; i++) {
balls[i].move();
balls[i].draw();
}
t = t + dt;
}