I want to use centerX and centerY in my 2d scene so that the camera centers on a moving rectangle (you wouldn’t see the rectangle move then, but it leaves a trail, so you see the trail and the view centers around the head of the trail)
Yep camera() is for P3D renderer only and expects either 0 (zero) or 9 parameters. You could do the 2D game in P3D and make sure the scene elements have z+0 then you could use Camera() but that would be overkill. As suggested you could simulate a 2D camera using translate()
I tried something with code I found on internet. In the example it worked, but applied to my application it doesn’t.
The problem with translate for me is that I want the latest rectangle to be drawn in center, but the previous drawn rectangles should be visible as a trail. The locations of the rectangles are based on GPS coordinates.
import processing.serial.*;
String val; // Data received from the serial port
Serial serialConnectionObject;
int serialChannelIndexInt;
float lat;
float lng;
int rectSizeX = 40 ;
int rectSizeY = 40;
float latcoord = 0;
float longcoord = 0;
boolean newData = false;
float xCoord;
float yCoord;
float oldxCoord;
float oldyCoord;
Camera worldCamera;
void setup()
{
background(0);
size(400,400, P3D);
InitSerialConnectionVoid(0);
String portName = Serial.list()[serialChannelIndexInt]; //change the 0 to a 1 or 2 etc. to match your port
println(portName);
serialConnectionObject.bufferUntil('\n');
worldCamera = new Camera();
}
void draw()
{
translate(-worldCamera.pos.x, -worldCamera.pos.y);
worldCamera.draw();
if(newData) {
fill(#FFFFFF, 10);
noStroke();
rectMode(CENTER);
scale(2);
rect(xCoord, yCoord, rectSizeX, rectSizeY);
}
}
class Camera {
PVector pos; //Camera's position
//The Camera should sit in the top left of the window
Camera() {
pos = new PVector(0, 0);
//You should play with the program and code to see how the staring position can be changed
}
void draw() {
float px = xCoord - oldxCoord;
float py = yCoord-oldyCoord;
//I used the mouse to move the camera
//The mouse's position is always relative to the screen and not the camera's position
//E.g. if the mouse is at 1000,1000 then the mouse's position does not add 1000,1000 to keep up with the camera
//if (mouseX < 100) pos.x-=5;
//else if (mouseX > width - 100) pos.x+=5;
// if (mouseY < 100) pos.y-=5;
//else if (mouseY > height - 100) pos.y+=5;
//I noticed on the web the program struggles to find the mouse so I made it key pressed
if (keyPressed) {
if (key == 'w') pos.y -= py;
if (key == 's') pos.y += py;
if (key == 'a') pos.x -= px;
if (key == 'd') pos.x += px;
}
}
}
void serialEvent(Serial p) {
oldxCoord = xCoord;
oldyCoord = yCoord;
try {
println("test");
val = p.readString();
println(val);
JSONObject json = parseJSONObject(val);
if (json == null) {
newData = false;
} else {
println(json.toString());
lat = json.getFloat("lat");
lng = json.getFloat("lng");
println(lat);
LatLngtoXY(lat,lng);
println(xCoord, yCoord);
newData=true;
}
//latcoord = map(lat, lat-0.00045000045, lat+0.00045000045, 0, width);
//longcoord = map(lng, lng-0.00045000063, lng+0.00045000063, 0, height);
}
catch(RuntimeException e) {
e.printStackTrace();
}
}
void LatLngtoXY(float lat, float lon) {
float mapWidth = width;
float mapHeight = height;
// get x value
xCoord = (lon+180)*(mapWidth/360);
// convert from degrees to radians
float latRad = lat*PI/180;
// get y value
float mercN = log(tan((PI/4)+(latRad/2)));
yCoord = (mapHeight/2)-(mapWidth*mercN/(2*PI));
}
void InitSerialConnectionVoid(int _serialChannelIndexInt){
serialChannelIndexInt = _serialChannelIndexInt;
if(serialChannelIndexInt == Serial.list().length){ return; }
try{
serialConnectionObject = new Serial(this, Serial.list()[serialChannelIndexInt], 115200);
serialConnectionObject.bufferUntil('\n');
}
catch (RuntimeException e){
serialConnectionObject = null;
println(e);
println("SERIAL CONNECTION FAILED");
InitSerialConnectionVoid(serialChannelIndexInt + 1);
}
}
You are confusing the camera() method provided by Processing to change how a 3D scene is viewed and Camera() which is s constructor for a class called Camera which is in the code you posted.
You appear to be unfamiliar with the concept of Classes and Objects so I suggest you have a look at this tutorial
yes, it resets anything
what you might have done to pos vector
so i see no movement
see also a modified start position!
/*
import processing.serial.*;
String val; // Data received from the serial port
Serial serialConnectionObject;
int serialChannelIndexInt;
float lat;
float lng;
float latcoord = 0;
float longcoord = 0;
boolean newData = false;
*/
float xCoord=1;
float yCoord=1;
float oldxCoord;
float oldyCoord;
int rectSizeX = 40 ;
int rectSizeY = 40;
int posxstart = 20; // kll
int posystart = 20; // kll
Camera worldCamera;
void setup()
{
background(200, 200, 0);
size(400, 400, P3D);
/*
InitSerialConnectionVoid(0);
String portName = Serial.list()[serialChannelIndexInt]; //change the 0 to a 1 or 2 etc. to match your port
println(portName);
serialConnectionObject.bufferUntil('\n');
*/
worldCamera = new Camera();
stroke(200, 0, 0); // kll
noFill(); // kll
}
void draw() {
// translate(-worldCamera.pos.x, -worldCamera.pos.y); // play here, when enabled it not moves
worldCamera.draw();
/*
if (newData) {
fill(#FFFFFF, 10);
noStroke();
rectMode(CENTER);
scale(2);
rect(xCoord, yCoord, rectSizeX, rectSizeY);
}
*/
}
class Camera {
PVector pos; //Camera's position //The Camera should sit in the top left of the window
Camera() {
pos = new PVector(posxstart, posystart); // kll global preset start position
}
void draw() {
float px = xCoord - oldxCoord;
float py = yCoord - oldyCoord;
//I used the mouse to move the camera
//The mouse's position is always relative to the screen and not the camera's position
//E.g. if the mouse is at 1000,1000 then the mouse's position does not add 1000,1000 to keep up with the camera
//if (mouseX < 100) pos.x-=5;
//else if (mouseX > width - 100) pos.x+=5;
// if (mouseY < 100) pos.y-=5;
//else if (mouseY > height - 100) pos.y+=5;
//I noticed on the web the program struggles to find the mouse so I made it key pressed
if (keyPressed) {
if (key == 'w') pos.y -= py;
if (key == 's') pos.y += py;
if (key == 'a') pos.x -= px;
if (key == 'd') pos.x += px;
}
rect(pos.x, pos.y, rectSizeX, rectSizeY); // kll sorry, needed to see something
}
}
/*
void serialEvent(Serial p) {
oldxCoord = xCoord;
oldyCoord = yCoord;
try {
println("test");
val = p.readString();
println(val);
JSONObject json = parseJSONObject(val);
if (json == null) {
newData = false;
} else {
println(json.toString());
lat = json.getFloat("lat");
lng = json.getFloat("lng");
println(lat);
LatLngtoXY(lat, lng);
println(xCoord, yCoord);
newData=true;
}
//latcoord = map(lat, lat-0.00045000045, lat+0.00045000045, 0, width);
//longcoord = map(lng, lng-0.00045000063, lng+0.00045000063, 0, height);
}
catch(RuntimeException e) {
e.printStackTrace();
}
}
void LatLngtoXY(float lat, float lon) {
float mapWidth = width;
float mapHeight = height;
// get x value
xCoord = (lon+180)*(mapWidth/360);
// convert from degrees to radians
float latRad = lat*PI/180;
// get y value
float mercN = log(tan((PI/4)+(latRad/2)));
yCoord = (mapHeight/2)-(mapWidth*mercN/(2*PI));
}
void InitSerialConnectionVoid(int _serialChannelIndexInt) {
serialChannelIndexInt = _serialChannelIndexInt;
if (serialChannelIndexInt == Serial.list().length) {
return;
}
try {
serialConnectionObject = new Serial(this, Serial.list()[serialChannelIndexInt], 115200);
serialConnectionObject.bufferUntil('\n');
}
catch (RuntimeException e) {
serialConnectionObject = null;
println(e);
println("SERIAL CONNECTION FAILED");
InitSerialConnectionVoid(serialChannelIndexInt + 1);
}
}
*/
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):
Considering the complexity, I now consider making the code so that it recursively draws the rectangles and the first in the middle of the screen. If I can manage to get this working, this solves my problems with the moving camera since no camera is needed.