0

I'm currently working on a game in Processing where there are 3 equally spaced platforms on the left and right sides of the screen and 2 platforms on the bottom of the screen. The player in the game is a ball which spawns on one of the platforms. When the ball is on any platform, the player can choose to jump to any of the 4 platforms on the opposite half of the screen. The platforms are numbered in order from 1-8 starting with the platform at the top left corner of the screen to the last one at the top right corner.

For example, if the ball is on platforms 1-4, it can jump to platforms 5-8 and vice versa. Each platform is a class which has attributes for its x and y position (stored in a PVector()). To represent the decision space the player has when at each platform, I tried made an 8 x 8 matrix which stores each of the 4 triggers(platforms) that the player can jump to (and null triggers in the positions that it can't jump to). Here is the matrix:

Trigger[][]  decisionGraph = {{tNull,tNull,tNull,tNull,t5,t6,t7,t8},
                              {tNull,tNull,tNull,tNull,t5,t6,t7,t8},
                              {tNull,tNull,tNull,tNull,t5,t6,t7,t8},
                              {tNull,tNull,tNull,tNull,t5,t6,t7,t8},
                              {t1,t2,t3,t4,tNull,tNull,tNull,tNull},
                              {t1,t2,t3,t4,tNull,tNull,tNull,tNull},
                              {t1,t2,t3,t4,tNull,tNull,tNull,tNull},
                              {t1,t2,t3,t4,tNull,tNull,tNull,tNull}};

I was trying to emulate an adjacency list using a 2D array since processing doesn't have a linked list class. When I take the user's input, I check to see which half of the screen the player is on and then I essentially am (attempting to) using the map() function to linearly interpolate between the ball's current position and the target platform. Here is one case:

 if (keyPressed) {
    if(b.currentPlatform < 5){
    if (b.grounded()) {
      if (key == 'q') {
        choice1 = true;
        
        triggerSpike = true;
        //interpolate ball from its current position to the position of the target platform
        b.pos.x = map(b.velo.x, 40,width-40 ,b.pos.x,decisionGraph[b.currentPlatform-1][4].pos.x);
        
        b.pos.y = map(b.velo.y,0,695,b.pos.y,decisionGraph[b.currentPlatform-1][4].pos.y);
        b.currentPlatform = 5;
      } 

For some reason, accessing the graph in the map() function call with decisionGraph[b.currentPlatform-1][4].pos.x

returns a null pointer exception.

What could be causing the problem? If there is a better way to implement this functionality, how should it be done?

EDIT:

Trigger initialization

Trigger t1;
Trigger t2;
Trigger t3;
Trigger t4;
Trigger t5;
Trigger t6;
Trigger t7;
Trigger t8;
Trigger t[];
//Null trigger
Trigger tNull;

Trigger Class definition and creation of platforms

class Trigger { //platforms to jump between
  PVector pos;
  PVector dim;
  Boolean isNull;

  Trigger(float x, float y, float w, float h) {
    pos = new PVector(x, y);
    dim = new PVector(w, h);
    isNull = false;
  }

  void draw() {
    pushMatrix();
    noStroke();
    fill(#00F9FF);
    rect(pos.x, pos.y, dim.x, dim.y);
    popMatrix();
  }
}

void triggers() {//hard coded platfomrs
  t1 = new Trigger(width/2 - 120, 695, 50, 10);
  t2 = new Trigger(width/2 + 120, 695, 50, 10);
  t3 = new Trigger(40, space*2.5 + 120, 10, 50);
  t4 = new Trigger(600, space*2.5 + 120, 10, 50);
  t5 = new Trigger(40, space*2.1, 10, 50);
  t6 = new Trigger(600, space*2.1, 10, 50);
  t7 = new Trigger(40, space, 10, 50);
  t8 = new Trigger(600, space, 10, 50);
  tNull = new Trigger(0,0,0,0);
  tNull.isNull = true;

Adding the following line of code alone causes the exception

println("Decision Graph position: " + decisionGraph[b.currentPlatform-1][4].pos.x);
Community
  • 1
  • 1
loremIpsum1771
  • 2,497
  • 5
  • 40
  • 87
  • What is the value of `tNull`? Can you please post a [mcve] instead of a disconnected snippet? – Kevin Workman Mar 30 '16 at 01:51
  • @KevinWorkman Just edited the post – loremIpsum1771 Mar 30 '16 at 03:07
  • What does map() do? Show the stack trace, so we can tell whether it actually entered map() or if the error occurred while it was attempting to gather parameters. If it occurred on parametesr, and since the stack trace may not indicate whether it failed on the .pos.x or .pos.y, or on the actual array access, I suggest assigning the Trigger at the array elements to a variable, and doing the same with pos, then accessing .x, to show whether it is complaining about a null array, a null Trigger object in the array, or a null PVector within the Trigger object. – Matt Jordan Mar 30 '16 at 03:25
  • @MattJordan I just updated the post again. The error seems to be coming directly from accessing the a position in the graph. Should I restructure the graph itself? – loremIpsum1771 Mar 30 '16 at 03:42

1 Answers1

1

The reason for this error is because all of your Trigger variables are initialized to null at the time when decisionGraph is initialized to an array, so it is an array of null pointers. This is because you assign decisionGraph a value in its declaration, which occurs before triggers() can be called.

Then, some part of your code calls triggers(), which assigns new values to the trigger variables, but since decisionGraph holds a copy of the original null pointers rather than references to your variables, it doesn't get updated.

To fix this, declare decisionGraph without an initializer, and build decisionGraph in triggers() after you set up the Trigger variables so it has valid non-null objects to access.

Matt Jordan
  • 2,133
  • 9
  • 10
  • Yeah, the problem was that the person who wrote the triggers() method conditionally called it in the main file when a certain button was pressed, so the triggers were all null initially.... – loremIpsum1771 Mar 30 '16 at 04:05