Loading...
Logo
Processing Forum
Hello I'm starting with oriented object programming and i'm getting a nullpointerexeption when I try to compile the code.

It's supposed to create a ball at the position where I'm clicking and the balls are moving around and bump on the sides.

here is the code :

Copy code

  1. class balle{
     
      float x;
      float y;
      float deplx;
      float deply;

    balle(){
      x= mouseX;
      y= mouseY;
      deplx = random(0,3);
      deply = random(0,3);

    }

    void show() {
     ellipse(x,y,20,20);
     
    }

    void rebond() {
      x += deplx;
      y += deply;
     
      if ( y > 395) {
       deply = -deply ;
      }
      if (y < 5) {
       deply = -deply ;
      }
      if ( x > 395) {
       deplx = -deplx ;
      }
      if (x < 5) {
       deplx = -deplx ;
      }
      
    }

    }
    ArrayList balles;
    balle ball;


    void setup() {

      size(400,400);
    ball = new balle();
    }

    void mouseClicked() {
    balles.add(new balle());
    }
     


    void nettoyer() {
     size(400,400);
    background(0) ;
    }

    void draw() {
     nettoyer();
      for (int i = 0; i < balles.size()-1; i++ ) {  // here is when it's highlighted
        balle balle = (balle) balles.get(i);
     ball.rebond();
     ball.show();
      }


    }


Replies(18)

When you launch your program, you have not clicked the mouse yet.
That means that you have not added a new balle() to the arrayList.
So, the arrayList size is 0. In addition to that, you subtract 1 in your for loop.
Which means that:
1) The arrayList contains nothing at all.
2) The for loop cannot iterate, as you int i = 0, whereas balles.size = -1.
That's is why your program throws the exception.
Try adding an object before the program gets to the for loop.

- MC.

P.S. Null, if you don't know already, is an empty space, variable, or array.
If the program tries to receive something that's not there at all, it will throw the NullPointerException.
Remember that the next time you get the exception/error.
In a more technical side, a "NullPointException" means that:
An Object type variable has not been assigned a memory address or reference pointer yet.
It's still = null. Thus, it has to be initialized, generally w/ keyword new, before being used!

In your code, you've got into a big confusion! You've declared 2 Object variables:
  • ArrayList balles;
  • balle ball;
Variable balles is of type ArrayList and ball is of type balle.

None of them got initialized w/ a reference pointer yet!
Moreover, why have 1 instance of balle, if you intend to have a Collection of instances of it using an ArrayList?
So, variable ball is useless and should be axed out!

Just a lil' tip before continuing:
There is a standard convension in Java, that a class name should start w/ a capital letter for each of its words!
Thus, class balle should be class Balle instead!  From now on, I'm gonna refer balle as Balle, OK?  

Now we just have variable balles. And in order to have a List of instances of class Balle, we have to initialize it:
final static List<Balle> balles = new ArrayList();

The keyword new allocates a memory block big enough to store a reference to an ArrayList.
And this reference pointer is assigned to variable balles which is of type List< Balle>.
Now we have a variable balles w/ a valid pointer memory address and ready to use!  


Here's your code refactored! Click to create an instance of Balle, or middle-click to remove the oldest Balle's:
Copy code
    //import java.util.List;
    
    final static List
                   
                    <Balle> balles = 
                    new 
                    ArrayList();
    
                    final 
                    static 
                    color BG = 0;
    
    
                    void 
                    setup() {
      
                    size(600, 400, 
                    P2D);
      
                    frameRate(50);
      
                    ellipseMode(
                    CENTER);
    
      
                    fill(Balle.COLOUR);
    }
    
    
                    void 
                    draw() {
      
                    background(BG);
    
      
                    for (Balle b: balles) {
        b.rebound();
        b.show();
      }
    }
    
    
                    void 
                    mousePressed() {
      
                    if (
                    mouseButton != 
                    CENTER)    balles.
                    add( 
                    new Balle() );
      
                    else 
                    if (balles.
                    size() > 0)   balles.remove(0);
    }
    
    
                    final 
                    class Balle {
      
                    float x, y;
      
                    float spX, spY;
    
      
                    final 
                    static 
                    byte  DIM = 20, HALF_DIM = DIM >> 1;
      
                    final 
                    static 
                    byte  MAX_SPD = 5;
      
                    final 
                    static 
                    color COLOUR = #FFFF00;
    
      Balle() {
        x = 
                    mouseX;
        y = 
                    mouseY;
    
        spX = 
                    random(1, MAX_SPD) * (
                    random(1) < .5 ? -1:1);
        spY = 
                    random(1, MAX_SPD) * (
                    random(1) < .5 ? -1:1);
      }
    
      
                    void show() {
        
                    ellipse(x, y, DIM, DIM);
      }
    
      
                    void rebound() {
        x += spX *= x < HALF_DIM | x > 
                    width  - HALF_DIM ? -1:1;
        y += spY *= y < HALF_DIM | y > 
                    height - HALF_DIM ? -1:1;
      }
    }
    
                   

An alternative class Balle using fields w/ types short & byte rather than float.
5 bytes are saved for each instance created!  

Just 2/3 from the top of the class Balle had to be tweaked.
That is, both non- static fields & its constructor. And methods kept unchanged: 
Copy code
    final class Balle {
      short x, y;
      byte  spX, spY;
    
      final static byte  DIM = 20, HALF_DIM = DIM >> 1;
      final static byte  MAX_SPD = 5;
      final static color COLOUR = #FFFF00;
    
      Balle() {
        x = (short) mouseX;
        y = (short) mouseY;
    
        spX = (byte) ( random(1, MAX_SPD) * (random(2) < 1 ? -1:1) );
        spY = (byte) ( random(1, MAX_SPD) * (random(2) < 1 ? -1:1) );
      }  // ...
    

Thank you very much ! :)
Sorry to disturb you again but I don't get some parts :

I plan to make a lot of balls in the future so I need to do it this way with an arraylist to hold them.

That's my idea. But if I do

balles.add(new Balle()); I get a npe at this location. Why ? Isn't it supposed to fill the arraylist ?

How can I initialize a pointer for both ?
So sorry! Forum here has some bug on posting code between angle braces <>:
instead of -> final static List <Balle> balles = new ArrayList <Balle>();
it's posted -> final static List balles = new ArrayList();

W/o using generics within angle braces,
there's an annoying need to use ( cast) before extracting an element from a Collection!

It's fixed now I hope! 
balles.add(new Balle()); I get a NPE at this location.
Why? Isn't it supposed to fill the ArrayList?
Only after a Collection is initialized, you can start putting anything into them!

And you initialize a collection with

    final static List<Balle> balles = new ArrayList <Balle>();  ?

With this processing tells me that he can't find a class or type named "list"
B/c you're using 1 of the beta versions. They've taken away much of the auto library import!  
Just remove the slashes (uncomment) the top line w/ import keyword!
Or just use class ArrayList rather than interface List as the access type for field variable balles

P.S.: Since you're using the newest beta, remove P2D parameter from function size():
size(600, 400);
So it uses default JAVA2D engine instead of OPENGL! Just test which one is fastest though! 

Both P2D & P3D graphic engines got axed out as well! 
And Processing 2.x.x actually ends up using OPENGL when they are specified!

It's working ! :) thank you very much !

I'm always using JAVA2D, I'll try the rest out :)

Opengl is used with P3D which is used for 3d renders so it's less powerfull with 2d renders right ?

I don't get some part of your code ( I'm sorry to disturb you like that but I want to fully understand :p)
 
"final static" I guess static mean a constant variable but final I don't get it.

I've commented all the lines with what I understand and what I don't If I understanded something wrong tell me as well please :)

Copy code
  1.   
       import java.util.List; // Import of an ext lib
        final static List<Balle> balles = new ArrayList(); // Creation of the arraylist with the object Balle ?
        final static color BG = 0; // Color of the background is set to 0

        void setup() {
          size(600, 400, P2D); // size + render with P2D
          frameRate(50); // 50 frame per seconds
          ellipseMode(CENTER); // Ellipse mode set to center

          fill(Balle.COLOUR); // Fill in yellow
        }

        void draw() {
          background(BG); // Background 0

          for (Balle b: balles) { // ?
            b.rebound(); // bump
            b.show(); // show
          }
        }

        void mousePressed() { // Easy
          if (mouseButton != CENTER)    balles.add( new Balle() ); // if middle button is pressed add a ball to prevent from npe
          else if (balles.size() > 0)   balles.remove(0); // If there is more than one remove it is .remove a fonction available on everything ?
        }

        final class Balle { // class Balle
          float x, y;
          float spX, spY;

          final static byte  DIM = 20, HALF_DIM = DIM >> 1; // I don't get the , HALF_DIM = DIM >> 1;
          final static byte  MAX_SPD = 5;// the max speed is 5, used for the random later
          final static color COLOUR = #FFFF00;// color yellow

          Balle() {
            x = mouseX; // if created use the pos of the mouse
            y = mouseY;

            spX = random(1, MAX_SPD) * (random(1) < .5 ? -1:1); // speed = random(1,5)*random(??)
            spY = random(1, MAX_SPD) * (random(1) < .5 ? -1:1); // same I don't get the * (random(1) < .5 ? -1:1);
          }

          void show() {
            ellipse(x, y, DIM, DIM); // show the ellipse at the pos x y with the size dim dim
          }

          void rebound() {
            x += spX *= x < HALF_DIM | x > width  - HALF_DIM ? -1:1; // if it get too close of a side reverse the movement + movement
            y += spY *= y < HALF_DIM | y > height - HALF_DIM ? -1:1;// but I don't get y > height - HALF_DIM ? -1:1;
          }
        }





Opengl is used with P3D which is used for 3d renders so it's less powerfull with 2d renders right?
There's no P3D nor P2D graphics engine in Processing 2.x.x! When using 1 of them, OPENGL is used instead!

"final static " I guess static mean a constant variable but final I don't get it.
It is final which makes a value assigned to a variable constant, immutable! 

Now static is a completely different "creature"!
It means such field variables can't be instantiated and they are shared among all instances of their class!

Here's the code again re-commented: 
Copy code
    import java.util.List; // actually, it is already imported, but not "activated"!
    
    // constant field variables of the top class, the sketch itself!  ;-)
    
    // an ArrayList which only stores instances of class Balle, and initial size = 128: final static List <Balle> balles = new ArrayList(0200);

    final static color BG = 0;
    final static String ENGINE = P2D; // JAVA2D, P2D, P3D, OPENGL void setup() {
       size(600, 400, ENGINE); // P2D & P3D don't exist in Processing 2.x.x!    frameRate(50);
       ellipseMode( CENTER);

       fill(Balle.COLOUR); // directly access a static field w/o instantiate it 1st! } void draw() {
       background(BG);

       // this is called enhanced or for-each or even for-in loop    // iterates all of the elements stored within variable balles    // since balles only contains instances of class Balle    // iterator b is declared as of type Balle to receive an element from it:    for (Balle b: balles) b.script();

       // changes app window top-bar title:   frame.setTitle(  "# Balls: " + balles. size() );
    }

    void mousePressed() {
       // if it's NOT a middle-click, add a new instance of Balle:    if ( mouseButton != CENTER) balles. add( new Balle() );

       // otherwise, also checks whether it has at least 1 instance stored    // before removing oldest one to avoid an exception:    else if (balles. size() != 0) balles.remove(0);
    }

    final class Balle {
       // fields of inner class Balle (instantiatable):    short x, y;
       byte spX, spY;

       // static constant fields of inner class Balle (non-instantiatable):    final static byte DIM = 20, HALF_DIM = DIM >> 1; // >> 1 is / 2    final static byte MAX_SPD = 5;
       final static color COLOUR = #FFFF00; // yellow   Balle() {  // constructor of inner class Balle     x = ( short) mouseX;
        y = ( short) mouseY;

         // ternary operator ?: which demands 3 operands      // if (random(2) < 1) multiplies by -1, otherwise by 1:     spX = ( byte) ( random(1, MAX_SPD) * ( random(2) < 1 ? -1:1) );
        spY = ( byte) ( random(1, MAX_SPD) * ( random(2) < 1 ? -1:1) );
      }

       void bump() {
         // multiplies spX/spY by -1 in case x/y is (off canvas - size/2 of Balle)      // afterwards, adds current result of spX/spY into x/y:     x += spX *= x < HALF_DIM | x >  width - HALF_DIM ? -1:1;
        y += spY *= y < HALF_DIM | y >  height - HALF_DIM ? -1:1;
      }

       void show() {
         ellipse(x, y, DIM, DIM);
      }

       void script() {
        bump();
        show();
      }
    }

DIM >> 1 = DIM/2

Then why not DIM/2 ? I mean it's even shorter :p
I like >> 1 a lot! 
Either way, HALF_DIM is a good tip that it's half of DIM, right? 
Anywayz, HALF_DIM is the radius of Balle's diameter (DIM).
    // ternary operator ?: which demands 3 operands
    // if (random(2) < 1) multiplies by -1, otherwise by 1:
    spX = (byte) ( random(1, MAX_SPD) * (random(2) < 1 ? -1:1) );
    spY = (byte) ( random(1, MAX_SPD) * (random(2) < 1 ? -1:1) );
  }

but if random 2 gives you 0,5 the speed will go on the other side and the balls would randomly go on an other direction, why not ?
Let's see... random(2) would pick a float number ranging from 0 up to 1.99999999...

Let's say it's picked 0.5. Is 0.5 < 1 ? Yes, it is! So evaluate it as -1. Otherwise, evaluate it as 1.

Pay attention that random(2) is the 1st operand. -1 is 2nd and 1 the 3rd one from ternary operator ?:

Here's its reference:
http://processing.org/reference/conditional.html
I guess I'll do without operand I don't get it well enough to use it x)
On that case, here's the regular way for spX within constructor, w/o using ?: operator:
spX = (byte) random(1, MAX_SPD);
if (random(2) < 1) spX *= -1;

And within bump() too:
if ( (x += spX) < HALF_DIM | x > width  - HALF_DIM )  spX *= -1;

A comparison between the 2 formats:
if ( (x += spX) < HALF_DIM | x > width  - HALF_DIM )  spX *= -1;
y += spY  *= y < HALF_DIM | y > height - HALF_DIM ? -1:1;


Well thanks you very much you were very helpfull :)