Camera() doesn't expect parameters

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)

According to https://processing.org/reference/camera_.html I could use center parameters for camera, but when I do this, Processing says ‘camera() doesn’t expect any parameters’.

How can I achieve this?

1 Like

Hey There!

Preety sure camera is for 3D sketches only. You could create a camera of sorts do your own by using translate.

This could also be useful.

2 Likes

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()

2 Likes

Thanks for your replies!

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

3 Likes

and to the question about

translate

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);
 }
 }
 */

1 Like

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):

1 Like

Thanks for your replies!

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.