0

Everybody! I'm here to annoy you once more)

So, I was trying to make a game, I described some classes: GameObject - just an object which has X,Y,Sizes,Name and may be drawn and moved:

package pkg3dgraphics;

import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;


public class GameObject {
    protected String name;
    protected int xCoord,yCoord,mySizeX = 25,mySizeY = 25;
    public GameObject(){

    }
    public GameObject(String newName, int startXCoord, int startYCoord){
        setName(newName);
        setX(startXCoord);
        setY(startYCoord);
    }
    public void SetSize(int X, int Y){
        mySizeX = X;
        mySizeY = Y;
    }
    public int getXsize(){
        return mySizeX;
    }
    public int getYsize(){
           return mySizeY;
    }
    public String getName(){
        return name;
    }
    public void setName(String newName){
        name = newName;
    }
    public int getX(){
        return xCoord;
    }
     public int getY(){
        return yCoord;
    }
    public void setX(int newXCoord){
        xCoord  = newXCoord;
    }

    public void setY(int newYCoord){
        yCoord  = newYCoord;
    }
    public void moveTo(int X,int Y){
     xCoord  = X;
     yCoord  = Y;
    }
    public void moveBy(int X,int Y){
     xCoord +=X;
     yCoord +=Y;
    }
   public  void Draw(GraphicsContext currentContext){
         currentContext.setFill(Color.GREEN);
         currentContext.setStroke(Color.BLUE);
         currentContext.fillOval(xCoord,yCoord, mySizeX,mySizeY );

    }
}

And I have Shooter extending previous class and here he goes:

    package pkg3dgraphics;


    public class Shooter extends GameObject {
        public Shooter(){

        }
        public Shooter(String newName, int startXCoord, int startYCoord){
            setName(newName);
            setX(startXCoord);
            setY(startYCoord);
        }
        public Bullet shoot(String direction){
            Bullet newBullet = new Bullet(direction);
            return newBullet;
        }

    }

Also I've got Bullets which are , you know, bullets:

    package pkg3dgraphics;

    import javafx.scene.paint.Color;
    import javafx.scene.canvas.GraphicsContext;

    public class Bullet extends GameObject{
        String myDirection;
        protected int mySpeed = 5,mySizeX  = 5,mySizeY = 5;
        boolean  goNorth,goSouth,goWest,goEast;
        protected boolean active = false;
        public void setSpeed(int newSpeed){
            mySpeed = newSpeed;
        }
        public void setDirection(String newDirection){
            myDirection = newDirection;
            active = true;
            if ( myDirection == "North" )
                goNorth = true;
            if ( myDirection == "South" )
                goSouth = true;
            if ( myDirection == "West" )
                goWest = true;
            if ( myDirection == "East" )
                goEast = true;
        }
        Bullet(String direction ){
            myDirection = direction;
            active = true;
            if ( myDirection == "North" )
                goNorth = true;
            if ( myDirection == "South" )
                goSouth = true;
            if ( myDirection == "West" )
                goWest = true;
            if ( myDirection == "East" )
                goEast = true;      
        }

        public void advance(int W,int H,GraphicsContext gc){
           if (xCoord <= W && xCoord >= 0 && yCoord <= H && yCoord >= 0 ) {
                    if (goNorth) moveBy(0,mySpeed);
                    if (goSouth) moveBy(0,mySpeed);
                    if (goWest) moveBy(mySpeed,0);
                    if (goEast) moveBy(mySpeed,0);
           }else{
               active = false;
               Vanish(gc);
               goNorth = false;
               goSouth = false;
               goWest  = false;
               goEast  = false;
           }
        }
        public void Vanish(GraphicsContext gc){
            gc.setFill(Color.WHITE);
        }
    }

The purpose was to have this guy shooting in a next way: When I catch pressed button I use precreated inactive bullet and direct it to go in a several direction. When this bullet crosses a window's border it becomes inactive and stops. For this I have an array of Bullets. When user presses shoot key I seek in the array for an inactive Bullet and if there is none I create additional one which follows the path user wanted. Well, this way to Implement bullets probably is not the best, but I didn't come up with another.

So I compiled my Main Class:

package pkg3dgraphics;

import java.util.Vector;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import static javafx.scene.input.KeyCode.DOWN;
import static javafx.scene.input.KeyCode.LEFT;
import static javafx.scene.input.KeyCode.RIGHT;
import static javafx.scene.input.KeyCode.SHIFT;
import static javafx.scene.input.KeyCode.UP;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;






public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
    }



    public int WINDOWWIDTH = 600;
    public int WINDOWHEIGHT = 400;
    boolean goNorth,goSouth,goWest,goEast,running,ShootNorth,ShootSouth,ShootWest,ShootEast;
    Shooter player = new Shooter("Player",WINDOWWIDTH/2,WINDOWHEIGHT/2);
    Bullet bullets[]  = new Bullet[500];
    int bulletsSize = 0;
     Canvas mainCanvas = new Canvas(WINDOWWIDTH,WINDOWHEIGHT);
     GraphicsContext mainContext =  mainCanvas.getGraphicsContext2D();
    @Override 
    public void start(Stage primaryStage) {
        Group root = new Group();
        Canvas mainCanvas = new Canvas(WINDOWWIDTH,WINDOWHEIGHT);
        GraphicsContext mainContext =  mainCanvas.getGraphicsContext2D();
        root.getChildren().add(mainCanvas);

        Scene scene  = new Scene(root,WINDOWWIDTH,WINDOWHEIGHT);
        scene.setOnKeyPressed(new EventHandler<KeyEvent> (){
            @Override
            public void handle(KeyEvent event){
                        switch(event.getCode()){
                            case UP:        ShootNorth = true; break;
                            case DOWN:      ShootSouth = true; break;
                            case LEFT:      ShootWest  = true; break;
                            case RIGHT:     ShootEast  = true; break;
                            case W:         goNorth = true; break;
                            case S:         goSouth = true; break;
                            case A:         goWest  = true; break;
                            case D:         goEast  = true; break;
                        } 
            }
        });
       scene.setOnKeyReleased(new EventHandler <KeyEvent>(){
           @Override
           public void handle(KeyEvent event){
               switch(event.getCode()){
                   case UP:         ShootNorth = false; break;
                   case DOWN:       ShootSouth = false; break;
                   case LEFT:       ShootWest  = false; break;
                   case RIGHT:      ShootEast  = false; break;
                   case W:          goNorth = false; break;
                   case S:          goSouth = false; break;
                   case A:          goWest  = false; break;
                   case D:          goEast  = false; break;

               }
           }
       }); 
        primaryStage.setScene(scene);
        primaryStage.show();
       AnimationTimer Timer = new AnimationTimer(){
           @Override
           public void handle (long now){
               int dx = 0, dy = 0;
               if (goNorth) dy = -1;
               if (goSouth) dy = 1;
               if (goWest)  dx = -1;
               if (goEast)  dx = 1;
               if (running) { dx *= 3; dy *= 3;}
               mainContext.clearRect(0,0,WINDOWWIDTH,WINDOWHEIGHT);
               player.moveBy(dx, dy);
               CheckShoot();
               player.Draw(mainContext);

           }


       };
       Timer.start();


    }

    public void CheckShoot(){
        String direction = null;
        int count = 0;
        if (ShootNorth)
            {
                direction = "North";
            }
        if (ShootSouth)
            {
                direction = "South";
            }
        if (ShootWest)
            {
                direction = "West";
            }
        if (ShootEast)
            {
                direction = "East";
            }
        for (int i = 0; i < bulletsSize; i ++ )
        {
            if (bullets[i].active = false ){
                bullets[i].setDirection(direction);
                bullets[i].moveTo(player.getX(),player.getY());
                break;
            }else count ++;
        }
        if ( count == bulletsSize ) {
           bulletsSize++;
           bullets[bulletsSize] = player.shoot(direction);
        }

    }

     public void advanceAll(){
        for (int i = 0; i < bulletsSize; i ++ )
        {
            bullets[i].advance(WINDOWWIDTH,WINDOWHEIGHT,mainContext);
        }
    }

}

Application runs but then I get this problem looped untill I close the application:

   Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
        at pkg3dgraphics.Main.CheckShoot(Main.java:126)
        at pkg3dgraphics.Main$3.handle(Main.java:91)
        at javafx.animation.AnimationTimer$AnimationTimerReceiver.lambda$handle$483(AnimationTimer.java:57)
        at java.security.AccessController.doPrivileged(Native Method)
        at javafx.animation.AnimationTimer$AnimationTimerReceiver.handle(AnimationTimer.java:56)
        at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:357)
        at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
        at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:506)
        at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
        at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$403(QuantumToolkit.java:319)
        at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
        at java.lang.Thread.run(Thread.java:748)

So, that is all I wanted to complain about. If someone has any idea why these all occure I would be glad and grateful if you shared the secret with me.(And all others)

HarvyD
  • 203
  • 1
  • 2
  • 5
  • There is no need for secret or magic. The error is self-explanatory. It is of type *NullPointerException* and on line *126* of your *CheckShoot* method. You need to do a null-check or make sure that those fields are never null. – Raf Feb 19 '18 at 03:58

1 Answers1

0

You seem to have created the array, without creating each members

Bullet bullets[]  = new Bullet[500];

Then you iterate through them, while they are nulls

    for (int i = 0; i < bulletsSize; i ++ )
    {
        if (bullets[i].active = false ){
            bullets[i].setDirection(direction);
            bullets[i].moveTo(player.getX(),player.getY());
            break;
        }else count ++;
    }

bullets[i] = null, and you try to invoke .active on it.

Solution:

Try to check nulls

        if (bullets[i] == null) { bullets[i] = new Bullet(); }
        if (bullets[i].active = false ){
            bullets[i].setDirection(direction);
            bullets[i].moveTo(player.getX(),player.getY());
            break;
        }else count ++;

Read What is NullPointerException

user9335240
  • 1,739
  • 1
  • 7
  • 14