Obstacle game in 3d (with 2d obstacles), unable to add more than 1 obstacle

I am trying to make an obstacle game where you are supposedly driving and there are trees you need to avoid (for now those are just rectangles). Since I am pretty new to processing, I tried some stuff out, and it all seemed to work (kinda), but when I added more that one obstacle (obst1), the translation I do at the beginning of the setup gets changed to a value that is lower that what I want (the translation should be -2000 on the z axis, but when I add obst2, it suddenly is only 1000). I really can’t find the problem.

If you have any other tips on how I should actually handle the overall game, in terms of how it functions, I would really appreciate that.

Code:

boolean moving = false;
boolean restart = false;
int amount = 4;
int numberWaves = 10;
int wave = 0;
int size = 100;

//Obstacle obst[][] = new Obstacle[numberWaves][amount];
Obstacle obst1, obst2, obst3;

void setup() {
  size(1000, 1000, P3D);
  background(200);
  rectMode(CENTER);

  //for (int w = 0; w < numberWaves; w++) {
  //  for (int i = 0; i < amount; i++) {
  //    //obst[w][i] = new Obstacle(size, ((int) random((width*5) / size)) * (2 * size));
  //    obst[w][i] = new Obstacle(size, -width + (i * (5*size)));
  //  }
  //}
  
  obst1 = new Obstacle(size, 100);
  obst2 = new Obstacle(size, 900);
  obst3 = new Obstacle(size, 1300);

  //translate(0, 0, -2000);
  pushMatrix();
}


void draw() {
  background(200);
  
  popMatrix();

  //for (int i = 0; i < amount; i++) {
  //  obst[wave][i].moveCar(8);
  //  obst[wave][i].obstacleInteract();
  //  obst[wave][i].nextWave();
  //}
  
  obst1.moveCar(8);
  obst1.obstacleInteract();
  obst1.nextWave();
  
  obst2.moveCar(8);
  obst2.obstacleInteract();
  obst2.nextWave();
  
  obst3.moveCar(8);
  obst3.obstacleInteract();
  obst3.nextWave();


  pushMatrix();

  //println(obst[0].xCar , obst[1].xCar, obst[2].xCar, obst[3].xCar, obst[4].xCar);
}


class Obstacle {

  float size, speed, xCar;
  float distance = 0;
  float z = 0;
  boolean wavePassed = false;



  Obstacle(float s, float x) {
    size = s;
    xCar = x;
  }

  void moveCar(float speed) {

    if (mousePressed && mousePressed == (mouseButton == LEFT) && restart == false) {      //Let's you drive when you hold a mousebutton
      moving = true;
    } else {
      moving = false;
    }



    if (moving == true && restart == false) {      //This part gives you the ability to move left and right while driving
      if (keyPressed && keyPressed == (keyCode == LEFT)) {
        xCar += speed;
      }
      if (keyPressed && keyPressed == (keyCode == RIGHT)) {
        xCar -= speed;
      }
    }

    if (moving == true && restart == false) {      //Moves the objects towards you with translate, as if you are driving towards them
      translate(0, 0, z);
      z += 0.1;
    } else {
      z = 0;
    }
  }

  void obstacleInteract() {
    //for (int i = 0; i < amount; i++) {
      distance += z;

      translate(0, 0, -2000);
      rect(xCar, -500, size, height*3);      //draws the obstacles

      if (distance > 2000 && moving == true) {      //checks if the obstacle is hit (when it is still in screen) and gives a notification that you died or survived
        if (dist(width/2, 0, xCar, 0) < 500) {
          moving = false;
          restart = true;
          println("you are dead, not big suprise");
        } else {
          wavePassed = true;
          translate(0,0,-distance);
        //}
      }
    }
  }

  void nextWave() {
    if (wavePassed == true && wave < numberWaves -1) {
      wave += 1;
      wavePassed = false;
      distance = 0;
    }
  
  
    println("distance = ", distance );
    println("z = ", z );
  }

}
1 Like

This function also has translate in it

Please write pushMatrix and popMatrix at the beginning and at the end of the function too

1 Like

Thanks for the help, but unfortunately this change didn’t affect the program at all. The translation is still affected by the number of obstacles that I want to spawn in.

Also in draw() :

PushMatrix(); must come first, popMatrix(); last?

https://processing.org/reference/pushMatrix_.html

1 Like

I found a way to implement a 3d camera, so luckily I don’t need to use translate anymore. Thanks anyway.

Well, normally yes, but when you want to execute a translation just once (that doesn’t change back to its origin afterwards) , I had read that you would have to do:

setup() {
pushMatrix();
}

draw() {
popMatrix();
(some code)
pushMatrix();
}

It worked, but it was very limited, so luckily I found an alternative.

In this scenario pushMatrix and popMatrix don’t do anything

At the start of draw() the Matrix is resetted anyway

sorry, I actually meant:

setup() {
pushMatrix();
translation();
}

draw() {
popMatrix();
(some code)
translation();
pushMatrix();
}

Not that this is a good thing to use though

This doesn’t make sense in setup ()

The matrix gets resetted at start of draw

1 Like

pushMatrix and popMatrix should be used in pairs in that order - it is bad programming practice to split them across two functions as you have done in your code. It makes it confusing if you need other drawing functions to use them in the same sketch.

2 Likes

Remark 1

I understand that you made big progress here because you use a 3D camera now that gives you the view from the car. Well done.

When you click the mouse or w (as in wasd) you should move the camera.

The obstacles should be in fixed position. So they don’t move but the camera moves.

Remark 2

Don’t make car stuff part of the class Obstacle. This is confusing. Keep your class clean.

Either make a new class Car or Camera and treat it separately.

Remark 3

It’s good that you have a class of obstacles.

But better put the obstacles obst1,obst2,obst3 in an array (1D array, not 2D) and for loop over it.

So you can shorten these lines:

  obst1.moveCar(8);
  obst1.obstacleInteract();
  obst1.nextWave();

  obst2.moveCar(8);
  obst2.obstacleInteract();
  obst2.nextWave();

  obst3.moveCar(8);
  obst3.obstacleInteract();
  obst3.nextWave();

But I might say, you achieved a lot already. Well done!

Regards, Chrisir

Here is an example with wasd keys:


final int GENERAL_Y_HEIGHT = 300; 

Obstacle obstacles[] = new Obstacle[22];
Car car = new Car(); 

void setup() {
  size(1000, 1000, P3D);
  background(200);

  for (int i=0; i<obstacles.length; i++) {
    obstacles[i] = new Obstacle(random(30, 211), random(-1500, 1555)); // size, x-pos
  }
}

void draw() {
  background(200);

  lights();

  // Car 
  car.carCamera();  

  for (Obstacle obst : obstacles) {
    obst.obstacleDisplay();
  }

  // floor
  floor1() ;

  keyPressedThroughout();

  camera(); 
  fill(255); 
  text("Use wasd", 13, 13);
}

// --------------------------------------------------------------------
// Inputs 

void keyPressedThroughout() {
  switch (key) {

    // these letters we pass to car
  case 'w':
  case 's':
  case 'a':
  case 'd':
    car.keyPressedThroughoutCar();
    break;
    //
  }//switch
}//func 

// --------------------------------------------------------------------
// Tools 

void floor1() {
  // decoration: the floor  
  float extensionHalf=7500;

  PVector[] pvList = {
    new PVector (-extensionHalf, GENERAL_Y_HEIGHT, -extensionHalf), // upper left corner 
    new PVector (-extensionHalf, GENERAL_Y_HEIGHT, extensionHalf), // go down |
    new PVector (extensionHalf, GENERAL_Y_HEIGHT, extensionHalf), // go right ->
    new PVector (extensionHalf, GENERAL_Y_HEIGHT, -extensionHalf)  // go up | (to upper right corner) 
  }; 
  fill(255, 0, 0);//RED
  beginShape();
  for (PVector pv : pvList) {
    vertex(pv.x, pv.y, pv.z);
  }
  endShape();
}

// ===========================================================================================================
// class 1

class Car {
  float carX = 0, 
    carY = GENERAL_Y_HEIGHT-88, 
    carZ = 1330;

  void carCamera() {
    camera(carX, carY, carZ, 
      carX, carY, carZ-300, 
      0, 1, 0);
  }

  void keyPressedThroughoutCar() {
    switch (key) {

    case 'w':
      carZ-=12;
      break;

    case 's':
      carZ+=12;
      break;

      //

    case 'a':
      carX-=12;
      break;

    case 'd':
      carX+=12;
      break;
      //
    }//switch
  }//func
}// class

// ===========================================================================================================
// class 1
class Obstacle {

  float x, y, z;  // pos - see constr 
  float sizeObst; // size - see constr
  color colObst = color (random(255), random(255), random(255) );

  // constr 
  Obstacle(float s_, float x_) {  // mark parameters by _ sign 

    sizeObst=s_;

    x = x_;    
    y=GENERAL_Y_HEIGHT-sizeObst/2;
    z=random(-3300, -55);
  }

  void obstacleDisplay() {

    pushMatrix(); 
    fill(colObst); 
    translate(x, y, z);
    box(sizeObst);      //draws the obstacle
    popMatrix();
  }
  //
}// class
//