Here is a simple 2D “camera” – it is using translate at exactly the right time. It doesn’t need to store anything, because your object (rectangle, ball, whatever) is the focal point.
Ball p1;
float[] bounds;
void setup() {
size(200, 200);
fill(0);
// create a bounding box with a bouncing ball
bounds = new float[]{1, height*.2, width-1, height*.6};
p1 = new Ball(random(width), height/2, 2, 10, bounds);
}
void draw() {
background(128);
pushMatrix();
noFill();
// update ball location
p1.move();
// set camera view
translate(width/2, height/2); // center screen on 0,0
translate(-p1.pos.x, -p1.pos.y); // recenter screen on player
// draw
rect(bounds[0], bounds[1], bounds[2], bounds[3]);
p1.render();
popMatrix();
}
// simple bouncing ball with a bounding box
class Ball {
float[] box;
PVector pos;
PVector speed;
float rad;
Ball(float x, float y, float speed, float rad, float[] box) {
this.pos = new PVector(x, y);
this.rad = rad;
this.box = box;
this.speed = PVector.random2D().setMag(speed);
}
void move() {
if (pos.x > box[0]+box[2] || pos.x < box[0]) speed.x *= -1;
if (pos.y > box[1]+box[3] || pos.y < box[1]) speed.y *= -1;
pos.add(speed);
}
void render() {
ellipse(pos.x, pos.y, 10, 10);
}
}
Here is a slightly more complex version. It gives you three view options – a static view, a camera fixed on the object, and a chasing camera that tries to follow the object.
/**
* Player Camera 2D
* 2019-08 - Jeremy Douglass - Processing 3.4
* Keep a balls (player) in view.
* Press any key to switch modes.
*
* Switch between modes: FLAT, TRACK.
* 0 FLAT is a normal 2D view.
* 1 ON centers view ball.
* 2 FOLLOW chases view after ball.
*
* Simplified from TwoPlayerCamera2D.
*/
Ball p1;
float[] bounds;
PVector view;
int mode=1; // 0=FLAT, 1=ON, 2=FOLLOW
void setup() {
size(200, 200);
fill(0);
// create a bounding box with a bouncing ball
bounds = new float[]{1, height*.2, width-1, height*.6};
p1 = new Ball(random(width), height/2, 2, 10, bounds);
view = new PVector(0,0);
}
void draw() {
background(128);
pushMatrix();
noFill();
// update ball location
p1.move();
// view x,y is a world-space location chasing the ball
// the value is the % it closes the gap each frame
view.lerp(p1.pos, 0.03);
switch(mode){
case 0: // FLAT
break;
case 1: // ON
translate(width/2, height/2); // center screen on 0,0
translate(-p1.pos.x, -p1.pos.y); // recenter screen on player
break;
case 2: // FOLLOW
translate(width/2, height/2); // center screen on 0,0
translate(-view.x, -view.y); // recenter screen on view
break;
}
// draw
rect(bounds[0], bounds[1], bounds[2], bounds[3]);
p1.render();
ellipse(view.x, view.y, 3, 3);
popMatrix();
// status
String msg = "mode:" + mode + " xy:" + (int)view.x + "," + (int)view.y + "\nPress any key";
text(msg, 5, 15);
}
// simple bouncing ball with a bounding box
class Ball {
float[] box;
PVector pos;
PVector speed;
float rad;
Ball(float x, float y, float speed, float rad, float[] box) {
this.pos = new PVector(x, y);
this.rad = rad;
this.box = box;
this.speed = PVector.random2D().setMag(speed);
}
void move() {
if (pos.x > box[0]+box[2] || pos.x < box[0]) speed.x *= -1;
if (pos.y > box[1]+box[3] || pos.y < box[1]) speed.y *= -1;
pos.add(speed);
}
void render() {
ellipse(pos.x, pos.y, 10, 10);
}
}
// press any key to switch between modes 0 and 1
void keyReleased() {
mode = (mode+1)%3;
}
The above sketches are based on a more complex sketch in which the camera is trying to keep multiple objects within the 2D view at the same time by using scaling (zoom):