Drawing a second instance of a ball class in a game

Hello everyone!
Pretty new into processing and into programming as well! So first of all, I´d like to apologize if the format is wrong or if my doubt has been solved before (I´ve been trying to find a solution for two days, no clue how to solve it).

So I am making my first game, which is a…surprise! floppy pong!
Thing is I´ve created a Ball class and used a for loop to create some of them. Now, I want to set a condition (if score> x, pop a second ball, which will be ball[1]) but I don´t have a clue how to do that. I´ve tried several ways like just duplicating the ball[0].draw, ball[0].bounce and so on to ball[1].draw etc, but does not work. Here is my code:

//Variables generales 
PFont arcade; //Fuente1
PFont arcade2;//Fuente 2
PFont arcade3;
boolean textoVisible=true;//Booleano para hacer el texto parpadear

Bola[] miBola;//array de tipo Bola
Pala miPala;//instancia de tipo Pala
Score miScore;//instancia de tipo Score
int pantalla;//variable para cambiar la pantalla



void setup() {
  size(800, 800);
  //Inizializamos variables
  arcade=createFont("ARCADE_N.TTF", 60);
  arcade2=createFont("ARCADE_I.TTF", 15);
  arcade3=createFont("ARCADE_N.TTF", 10);
  miBola=new Bola[100];
  for (int i=0; i<miBola.length; i++) {
    miBola[i]= new Bola(); //CREO ARRAY DE 10 BOLAS.
  }
  miPala=new Pala();
  miScore=new Score();
  pantalla=0;
}


void draw() {

  //DEFINO EN QUE PANTALLA/INSTANCIA ESTAMOS//0=INICIO, 1=JUEGO 2=GameOver
  if (pantalla==0) {
    pantallaInicio();
  } else if (pantalla==1) {
    pantallaJuego();
  } else if (pantalla==2) {
    pantallaGameOver();
  }
  
  
}

  //DEFINIMOS CONDICIÓN DE GAME START y de GAME OVER A INICIO AL PRESIONAR EL MOUSE
  void mousePressed() {
    if (pantalla==0) {
      pantallaJuego();
    } else if (pantalla==2) {
      restart();
    }
  }
  
  
  //---PANTALLA INICIO----//
void pantallaInicio() {
  pantalla=0;
  background(#80C152);
  textFont(arcade);
  textAlign(CENTER);
  text("Mis Bolitas", height/2, width/2.3);
  textFont(arcade3);
  text("A game by Manuel Martin for DAW", height/2, width/1.5);
  if (textoVisible) { //Condicion Booleano para hacer un texto tiltear
    textFont(arcade2);
    text("Presiona el raton para empezar", height/2, width/2);
  }
  if (frameCount%60==0) { //Si el contador de frames entre 60 es igual a cero, cambia de 60 fps a 1
    if (millis()>0) { //si el contador de milisegundos es mayor que 0
      textoVisible=!textoVisible;//cambia de booleano visible a invisible.
    }
  }
}


//---PANTALLA DE JUEGO------//


void pantallaJuego() {
  pantalla=1;
  miBola[0].dibuja();
  miBola[0].gravedad();
  miBola[0].rebota();
  pinchos();
  miPala.palaDibuja();
  miScore.dibuja();
  miScore.suma();
  if (miBola[0].bolaY-(30/2)>=750) { //CONDICIONES DE GAME OVER
    pantalla=2;
  }
  if (miScore.score>5) { //SI EL SCORE SUPERA 30, DIBUJA UNA SEGUNDA BOLA
    //?????
  }
}
//-----PANTALLA DE GAME OVER------//
void pantallaGameOver() {
  pantalla=2;
  background(#80C152);
  textAlign(CENTER);
  textFont(arcade);
  text("Eres malisimo", height/2, width/2);
  textFont(arcade3);
  text("Tu puntuacion lamentable: "+miScore.score+" .Pulsa raton para hacer el ridiculo otra vez", height/2, width/1.5);
}


Hope you can help me, in your wisdom I trust.
Thanks in advance and sorry for any mistake ^^

Hi,

Welcome to the community! :slight_smile:

It seems that in your problem, you want to dynamically create some ball objects when the score is greater than some value (I suggest that it goes to 0 at some point?).

In your code, you are creating a fixed array of Bola which have a size of 100. At the beginning of the program, you don’t know if the player is going to go over a certain score. That’s why we want to dynamically add a new ball each time the player increase it’s score.

For that we are not going to use raw Arrays but rather ArrayList. An ArrayList is basically an Array of objects but that don’t have a fixed size. This is handy when you don’t know how much elements you are going to create.

This is how you use it :

// Define the class that it's going to hold
// Here Bola
ArrayList<Bola> bolas = new ArrayList<Bola>();

// Add a new ball, simple as that
bolas.add(new Bola());

// Get a ball from the array
bolas.get(0);

Then in your code, you say :

if (miScore.score>5) {
  bolas.add(new Ball());
}

But now you will only draw and update your first ball because you used miBola[0] in the pantallaJuego() function. What we want is to check every ball in the game, update it, apply the forces and draw it (and whatever you want…).

We do this by looping through the balls with a specific syntax :

// It's basically a for but without the index
// It's for every bola of type Bola in Bolas do ...
for (Bola bola : Bolas) {
  bola.dibuja();
  bola.gravedad();
  bola.rebota();
}

Then you should be able to make it work by adding your other functions and implementation specific.

Hope it helps! :wink:

1 Like

Wow, thanks for that fast answer!!
So (because I am pretty pretty new, just 2 months in class) let me get this straight:

I have to declare the class Bola as an ArrayList in global vars of my program, like you said:

ArrayList<Bola> miBola;

So far so good. Then, I initialize the ArrayList in the constructor:

ArrayList<Bola> bolas = new ArrayList<Bola>();

Here I get a message: “The value of local variable “miBola” is not used” and a yellow underline.
Then, I´m not sure where I have to write the miBola.add, miBola.get and the for loop, wether in the main constructor or in the pantallaJuego() function or both…

Very much appreciated for your answer and sorry in advance for my clumsiness :frowning:

This is your old array

Replace it with the arraylist

Nothing changes in the class


This belongs in setup ()

1 Like

Thanks a lot!!!
So I just wrote the ArrayList just like you said:

ArrayList<Bola> miBola;

Pala miPala;//instancia de tipo Pala
Score miScore;//instancia de tipo Score
int pantalla;//variable para cambiar la pantalla



void setup() {
  size(800, 800);
  //Inizializamos variables
  arcade=createFont("ARCADE_N.TTF", 60);
  arcade2=createFont("ARCADE_I.TTF", 15);
  arcade3=createFont("ARCADE_N.TTF", 10);
  miBola=new ArrayList<Bola>();

Still, I have no idea how to implement this in the game (sorry again for my clumsiness, I´m just starting with OOP and it´s still a mess for me).

Here is my gameScreen() function:

void pantallaJuego() {
  pantalla=1;
  for(Bola bola:miBola){
  bola.dibuja();
  bola.gravedad();
  bola.rebota();
  }
  //GUESS HERE GOES THE CODE TO MAKE THE BALLS POP?
  pinchos();
  miPala.palaDibuja();
  miScore.dibuja();
  miScore.suma();
  /*if (miBola.bolaY-(30/2)>=750) { //GAME OVER CONDITIONS (IF BALL TOUCHES A FLOOR OF SPIKES)
    pantalla=2;
  }
  if (miScore.score>5) { //SECOND BALL POPS CONDITION
    //?????
  }*/
}

Not sure what I have to write there to implement balls (one at the beginning, two if scores>5, three if score>30) and so on.

Sorry again and thanks a lot for your dedication :smiley:

1 Like

Do you have the Ball class already? Or not?

It doesn’t change when you use ArrayList instead of array

Does your program run now?

Yes, my Ball object is already created and so is my Racket object. Here is my code for the Ball object:

class Bola {

  //1. Variables de clase

  float bolaX, bolaY;
  float gravedad;
  float bolaVelVer;
  float bolaVelHor;
  float friccionSuelo;
  float friccionAire;

  //2. Constructor

  Bola() {
    this.bolaX=width/2;
    this.bolaY=height/2;
    this.gravedad=1;
    this.bolaVelVer=0;
    this.bolaVelHor=0;
    this.friccionSuelo=0.1;
    this.friccionAire=0.00001;
  }

  //3. Métodos. 




  void gravedad() {
    bolaVelVer=bolaVelVer+gravedad;
    bolaY=bolaY+bolaVelVer;

    bolaX=bolaX+bolaVelHor;
  }
  //REBOTA CON EL SUELO
  void rebota() {
    if (bolaY+(30/2)>height) {
      bolaY=height-(30/2);
      bolaVelVer=-bolaVelVer;
    }//REBOTA CON EL TECHO
    if (bolaY-(30/2)<0) {
      bolaY=0+(30/2); 
      bolaVelVer=-bolaVelVer;
    }
    //REBOTA LADO DERECHO
    if (bolaX+(30/2)>width) {
      bolaX=width-(30/2);
      bolaVelHor=-bolaVelHor;
    }

    //REBOTA LADO IZQUIERDO
    if (bolaX-(30/2)<0) {
      bolaX=0+(30/2);
      bolaVelHor=-bolaVelHor;
    }
 //REBOTE EN PALA
    
      if ((bolaX+(30/2)>mouseX-(miPala.palAncho/2)) && (bolaX-(30/2)<mouseX+(miPala.palAncho/2))) {
      if (dist(bolaX, bolaY, bolaX, mouseY)<=(30/2)) {
        bolaY=mouseY-(30/2);
        bolaVelVer=-bolaVelVer;
        bolaVelHor=(bolaX-mouseX)/10;
        /*if(noteCaigas<0){
        bolaY=bolaY+(noteCaigas/2);
        bolaVelVer=bolaVelVer+(noteCaigas/2);
        }*/
      }
    }
  }
  void dibuja() {
    background(#80C152);
    noStroke();
    fill(255);
    ellipse(bolaX, bolaY, 30, 30);
  }

This is my Racket object code:

class Pala {

  //1.Variables de clase
  float palAncho;
  float palAlto;
  //2. Constructor

  Pala() {

    palAncho=150;
    palAlto=15;
  }
  //3. Métodos
  void palaDibuja() {

    noStroke();
    fill(255);
    rectMode(CENTER);
    rect(mouseX, mouseY, palAncho, palAlto, 5);
  }
}

And this is my gameScreen() function code. As you can see, I´ve changed my normal array with the ArrayList one, but I have not changed anything here yet, because I´m not sure how to do it without breaking everything :frowning:

void pantallaJuego() {
  pantalla=1;
  miBola[0].dibuja();
  miBola[0].gravedad();
  miBola[0].rebota();
  pinchos();
  miPala.palaDibuja();
  miScore.dibuja();
  miScore.suma();
  if (miBola[0].bolaY-(30/2)>=750) { //CONDICIONES DE GAME OVER
    pantalla=2;
  }
  if (miScore.score>5) { //SI EL SCORE SUPERA 30, DIBUJA UNA SEGUNDA BOLA
    //?????
  }
}

And this is where I´m stuck now.

Where are you stuck?

Does it work?

What’s your question?

I think josephh explained everything beautifully

add a ball to the arraylist using the command add()

for-loop over the ArrayList and use get() command to get a ball from the ArrayList

display the balls etc.

see https://www.processing.org/reference/ArrayList.html

No magic involved.

1 Like