How to add objects to ArrayList one at a time at timed intervals

I’m trying to make a 3D space shooter-type game, where spikes come at the ship and must be avoided. I’m currently coding for adding spikes one at a time at different intervals in the user’s score using an ArrayList. My error is that an infinite amount of spikes are created, not just one. Here’s my relevant code:

ArrayList<Spikes> spikes;
void setup() {
  size(600, 600, P3D);
 spikes = new ArrayList<Spikes>();
}
void draw(){
 if(score > 0 && score < 25){
    spikes.add(new Spikes(width/2,500,50));
    
  }
  for(int i=0; i < spikes.size(); i++){
    spikes.get(i).render();
     spikes.get(i).move();
  }
}
class Spikes{
  float x;
  float y;
  float z;
 
  
  Spikes(float _x, float _y, float _z){
    x = _x;
    y = _y;
    z = _z;
  }
  void render(){
    translate(x,y,z);
    fill(0);
    stroke(255);
   
    beginShape(TRIANGLES);
    
    vertex(100,-300,-100);
    vertex(150,-350,-100);
    vertex(100,-300,200);
    
    vertex(100,-300,-100);
    vertex(50,-350,-100);
    vertex(100,-300,200);
    
    endShape();
   translate(-x,-y,-z);
   
  }
  void move(){
    y+=4;
    if(y>1810){
      x = random(300,1500);
      y = 600;
    }
  }
}

Full code if anyone needs it (pretty messy):



int cols, rows;
int scl = 20;
int w = 2000;
int h = 1600;
Ship ship;
Ground ground;
ArrayList<Spikes> spikes;
color g;
color s;
float flying = 0;
float score = 0;
float[][] terrain;
boolean gameStart;
boolean gameOver;

void setup() {
  size(600, 600, P3D);
  cols = w / scl;
  rows = h/ scl;
  terrain = new float[cols][rows];
  g = color(156,111,81);
  s = color(0);
  ship = new Ship(1000,1100,200);
  ground = new Ground(1000,1100,200);
  spikes = new ArrayList<Spikes>();
  gameStart = true;
  gameOver = false;
}


void draw() {
  if( gameStart == true){
  flying -= 0.1;
  
  
  for (int y = 0; y < rows; y++) {
    for (int x = 0; x < cols; x++) {
       terrain[x][y] = flying;
    }
  } 



  background(0);
  textSize(50);
  fill(255);
  text(score, 50,50);
  stroke(s);
  fill(g);
  score += 0.01;
  translate(width/2, height/2+50);
  rotateX(PI/3);
  translate(-w/2, -h/2);
  ground.render();
  for (int y = 0; y < rows-1; y++) {
    beginShape(TRIANGLE_STRIP);
    for (int x = 0; x < cols; x++) {
      vertex(x*scl, y*scl, terrain[x][y]);
      vertex(x*scl, (y+1)*scl, terrain[x][y+1]);
      
    }
    endShape();
    // Idea for terrain using a triangle sector adapted from The Coding Train by Dan Shiffman
  }
  if(score > 0 && score < 25){
    spikes.add(new Spikes(width/2,500,50));
    
  }
  for(int i=0; i < spikes.size(); i++){
    spikes.get(i).render();
     spikes.get(i).move();
  }
  ship.render();
  ship.move();
  }
}

class Ship{
  float x;
  float y;
  float z;
 
  
  Ship(float _x, float _y, float _z){
    x = _x;
    y = _y;
    z = _z;
  }
  void render(){
    translate(x,y,z);
    fill(160);
    stroke(0);
    
     beginShape(TRIANGLES);
     scale(0.6);
      vertex(-50,0,25);
      vertex(-150,100,25);
      vertex(0,100,25);
      
      vertex(50,0,25);
      vertex(150,100,25);
      vertex(0,100,25);
      
       vertex(-50,0,-25);
      vertex(-150,100,-25);
      vertex(0,100,-25);
      
      vertex(50,0,-25);
      vertex(150,100,-25);
      vertex(0,100,-25);
      
      vertex(-50,0,25);
      vertex(50,0,25);
      vertex(0,-300,25);
      
      vertex(-50,0,25);
      vertex(50,0,25);
      vertex(0,100,25);
      
      vertex(-150,100,25);
      vertex(150,100,25);
      vertex(-150,100,-25);
      
      vertex(150,100,25);
      vertex(-150,100,-25);
      vertex(150,100,-25);
      
       vertex(-150,100,25);
      vertex(150,100,25);
      vertex(150,100,-25);
      
       vertex(50,0,25);
       vertex(50,0,-25);
        vertex(0,-300,-25);
        
        vertex(50,0,25);
       vertex(0,-300,25);
        vertex(0,-300,-25);
        
        vertex(-50,0,25);
       vertex(-50,0,-25);
        vertex(0,-300,-25);
        
        vertex(-50,0,25);
       vertex(0,-300,25);
        vertex(0,-300,-25);
       
        vertex(-50,0,25);
      vertex(-50,0,-25);
      vertex(-150,100,25);
      
        vertex(50,0,25);
      vertex(50,0,-25);
      vertex(150,100,25);
      
endShape(); 
  }
  void move(){
    if(keyPressed && keyCode == LEFT){
      x-=3;
    }
     if(keyPressed && keyCode == RIGHT){
      x+=3;
    }
     if(keyPressed && keyCode == UP){
      y-=3;
    }
     if(keyPressed && keyCode == DOWN){
      y+=3;
    }
  }
}
class Ground{
  float x;
  float y;
  float z;
  Ground(float _x,float _y,float _z){
    x = _x;
    y = _y;
    z = _z;
  }
  void render(){
    fill(g);
    translate(x,y,z);
    beginShape(TRIANGLES);
    
    vertex(100,100,2000);
      vertex(100,2000,-150);
      vertex(100,100,-150);
      translate(-x,-y,-z);
      endShape();
  }
}
class Spikes{
  float x;
  float y;
  float z;
 
  
  Spikes(float _x, float _y, float _z){
    x = _x;
    y = _y;
    z = _z;
  }
  void render(){
    translate(x,y,z);
    fill(0);
    stroke(255);
   
    beginShape(TRIANGLES);
    
    vertex(100,-300,-100);
    vertex(150,-350,-100);
    vertex(100,-300,200);
    
    vertex(100,-300,-100);
    vertex(50,-350,-100);
    vertex(100,-300,200);
    
    endShape();
   translate(-x,-y,-z);
   
  }
  void move(){
    y+=4;
    if(y>1810){
      x = random(300,1500);
      y = 600;
    }
  }
}

Hello,

I just spent a moment on your code…

This should give you some ideas:

  text(frameCount, 50,50);

  if(frameCount%60==0)
    {
    spikes.add(new Spikes(width/2,500,50));
    println(spikes.size());
    }
  
  if(spikes.size()>=10)
    {
    spikes.remove(0);
    println(spikes.size());
    }

You can look up the references to understand the code.
draw() \ Language (API) \ Processing 3+
frameRate() \ Language (API) \ Processing 3+
frameCount \ Language (API) \ Processing 3+

There are other timers that you can use if you desire. Search for these.

I often use frameCount() for quick code and examples where timing is not critical.

:)

1 Like

Thanks. This helps a lot. Two things: One, if I changed the ten to some int and slowly adjusted that int overtime to make it for example start with 3 spikes for the first minute of play, then 5 for the next minute, etc., would that work? And second, I have a loop where the spikes basically come forward (increasing in y) on the terrain, and once they are out of a certain value, they is changed back to the starting value. The spikes. remove(0); seems to remove them in the middle of the terrain. How could I make the remove happen simultaneously with my spike loop.

The limit of ten spikes can be adjusted. But that’s not really what you want. what you want is that spikes don’t just appear to vanish while you can still see them.

What you want to do is have the spikes get removed after they have gone off the screen. The trick to removing things from an ArrayList is to loop over them in reverse. Consider:

for( int i = spikes.size()-1; i >=0; i--){
  spikes.get(i).render();
  spikes.get(i).move();
  if( spikes.get(i).y > height + 100 ){ // It's way off-screen!
    spikes.remove(i);
  }
}