1

Can someone explain why I'm getting this error and how to solve it? Also try to keep it simple. I'm new to coding. (Also i know the answer to the question exists, but i don't know how to implement it to my code)

It gives NullPointerException error when rows are deleted. Also when the blocks move down, the blocks are still counted as 0 so new blocks go through them. (i guess its only the top row, other rows are working as intended) But the actual error is more important: (but i'd be happy if you help to solve this too)

package application;

import java.util.*;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.input.*;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Tetris extends Application {
  public static final int MOVE_AMOUNT = 25;
  public static final int SIZE = 25;
  public static int XLIMIT = SIZE * 10;
  public static int YLIMIT = SIZE * 24;
  public static int[][] GRID = new int[XLIMIT/SIZE][YLIMIT/SIZE];
  private static Pane group = new Pane();
  private static Shape object;
  private static Scene scene = new Scene(group, XLIMIT, YLIMIT);

  public static void main(String[] args) { launch(args); }
  @Override public void start(Stage stage) throws Exception {
    for(int[] a: GRID){
        Arrays.fill(a, 0);
    }
    for(int i = 0; i <= XLIMIT; i+= SIZE){
        Line a = new Line(i, 0, i, YLIMIT);
        group.getChildren().add(a);
    }
    for(int i = 0; i <= YLIMIT; i+= SIZE){
        Line a = new Line(0, i, XLIMIT, i);
        group.getChildren().add(a);
    }
    for(int i = 0; i <= YLIMIT; i+= SIZE){
        Text a = new Text("" + i);
        a.setY(i);
        group.getChildren().add(a);
    }
    for(int i = SIZE; i < XLIMIT; i+= SIZE){
        Text a = new Text("" + i);
        a.setY(10);
        a.setX(i);
        group.getChildren().add(a);
    }
    Shape a = TetrisHolder.createRect();
    group.getChildren().addAll(a.a, a.b, a.c, a.d);
    moveOnKeyPress(scene, a.a, a.b, a.c, a.d);
    object = a;
    stage.setScene(scene);
    stage.show();
    Timer myTimer=new Timer();
    TimerTask task =new TimerTask() {
      @Override
      public void run() {
          Platform.runLater(new Runnable(){
              public void run(){
                  CheckDown(object);
              }
          });
        }
      };
      myTimer.schedule(task,0,300);

    }

  private void moveOnKeyPress(Scene scene, Rectangle rect, Rectangle rect2, Rectangle rect3, Rectangle rect4) {
    scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
      @Override public void handle(KeyEvent event) {
        Shape shape = new Shape(rect, rect2, rect3, rect4);
        switch (event.getCode()) {
          case RIGHT: 
              TetrisHolder.CheckRight(shape);
              break;
          case DOWN:  
              CheckDown(shape);
              break;
          case LEFT:  
              TetrisHolder.CheckLeft(shape);
              break;
          case UP:
              //TetrisHolder.CheckTurn(shape);
              break;
        }
      }
    });
  }

  private void CheckTurn(Shape shape){

  }

  private void DeleteRows(Pane pane){
      ArrayList<Node> rects = new ArrayList<Node>();
      ArrayList<Integer> lines = new ArrayList<Integer>();
      int full = 0;
      for(int i = 0; i < GRID[0].length; i++){
          for(int j = 0; j < GRID.length; j++){
              if(GRID[j][i] == 1)
                  full++;
          }
          if(full == GRID.length)
              lines.add(i/*+lines.size()*/);
          full = 0;
      }
      for(Node node: pane.getChildren()) {
           if(node instanceof Rectangle) {
                rects.add(node);
            }
        }
      if(lines.size() > 0)
          do{
              for(Node node: rects){
                  Rectangle a = (Rectangle)node;
                  if(a.getY() == lines.get(0)*SIZE){
                      GRID[(int)a.getX()/SIZE][(int)a.getY()/SIZE] = 0;
                      pane.getChildren().remove(node);
                  }
                  if(a.getY() < lines.get(0)*SIZE){
                      GRID[(int)a.getX()/SIZE][(int)a.getY()/SIZE] = 0;
                      a.setY(a.getY() + SIZE);
                      GRID[(int)a.getX()/SIZE][(int)a.getY()/SIZE] = 1;
                  }
              }
              lines.remove(0);
              rects.clear();
              for(Node node: pane.getChildren()) {
                   if(node instanceof Rectangle) {
                        rects.add(node);
                    }
                }
          } while(lines.size() > 0);
  }

  private void CheckDown(Shape shape){
      if((shape.c.getY() == YLIMIT - SIZE) || checkA(shape) || checkB(shape) || checkC(shape) || checkD(shape)){
          GRID[(int)shape.a.getX()/SIZE][(int)shape.a.getY()/SIZE] = 1;
          GRID[(int)shape.b.getX()/SIZE][(int)shape.b.getY()/SIZE] = 1;
          GRID[(int)shape.c.getX()/SIZE][(int)shape.c.getY()/SIZE] = 1;
          GRID[(int)shape.d.getX()/SIZE][(int)shape.d.getY()/SIZE] = 1;
          DeleteRows(group);
          Shape a = TetrisHolder.createRect();
          object = a;
          group.getChildren().addAll(a.a, a.b, a.c, a.d);
          moveOnKeyPress(shape.a.getScene(), a.a, a.b, a.c, a.d);
          }
      if(shape.c.getY() + MOVE_AMOUNT < YLIMIT){
          int checka = GRID[(int)shape.a.getX()/SIZE][((int)shape.a.getY()/SIZE) + 1];
          int checkb = GRID[(int)shape.b.getX()/SIZE][((int)shape.b.getY()/SIZE) + 1];
          int checkc = GRID[(int)shape.c.getX()/SIZE][((int)shape.c.getY()/SIZE) + 1];
          int checkd = GRID[(int)shape.d.getX()/SIZE][((int)shape.d.getY()/SIZE) + 1];
          if(checka == 0 && checka == checkb && checkb == checkc && checkc == checkd){
              shape.a.setY(shape.a.getY() + MOVE_AMOUNT);
              shape.b.setY(shape.b.getY() + MOVE_AMOUNT);
              shape.c.setY(shape.c.getY() + MOVE_AMOUNT);
              shape.d.setY(shape.d.getY() + MOVE_AMOUNT);
              }
          }
      }

  private boolean checkA(Shape shape){
      return (GRID[(int)shape.a.getX()/SIZE][((int)shape.a.getY()/SIZE) + 1] == 1);
  }
  private boolean checkB(Shape shape){
      return (GRID[(int)shape.b.getX()/SIZE][((int)shape.b.getY()/SIZE) + 1] == 1);
  }
  private boolean checkC(Shape shape){
      return (GRID[(int)shape.c.getX()/SIZE][((int)shape.c.getY()/SIZE) + 1] == 1);
  }
  private boolean checkD(Shape shape){
      return (GRID[(int)shape.d.getX()/SIZE][((int)shape.d.getY()/SIZE) + 1] == 1);
  }
}

The error:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at application.Tetris.moveOnKeyPress(Tetris.java:70)
at application.Tetris.CheckDown(Tetris.java:147)
at application.Tetris.access$1(Tetris.java:137)
at application.Tetris$1$1.run(Tetris.java:60)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
Karl Sburg
  • 13
  • 6

2 Answers2

1

Why are you getting the scene from a shape if you still have a reference to a static scene at the top?

I'd say try switching the following out at line 70:

scene.setOnKeyPressed(new EventHandler<KeyEvent>() {

to this:

this.scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
Ellisan
  • 563
  • 8
  • 22
0

You are trying to access a shape which is null.

In your case, if you look at line 70, you are trying to perform scene.setOnKeyPressed, but scene is null.

You are calling in 2 places the moveOnKeyPress method. Where your problem is calling this method at line 147, where you do shape.a.getScene(). That call to getScene() is null.

Furthermore, if you look where you call CheckDown, you have them in 2 places, but your problematic call is at line 60.

Not sure what you do at line 48 (Shape a = TetrisHolder.createRect();), but I suspect there might be something wrong with setting up the scene

What I did here is translate your stacktrace:

at application.Tetris.moveOnKeyPress(Tetris.java:70)
at application.Tetris.CheckDown(Tetris.java:147)
at application.Tetris.access$1(Tetris.java:137)
at application.Tetris$1$1.run(Tetris.java:60)
Andrei Sfat
  • 8,440
  • 5
  • 49
  • 69
  • @Ellisan he does, but he never uses it on the object that he wants to pass. If you look at `Shape a = TetrisHolder.createRect();`, he then passes the reference to `object` and sets the scene created above to `stage`, not to the `Shape`, and then he does a call to `shape.a.getScene()`. Honestly, the code is pretty confusing, I dragged the code in my IDE to understand what is he trying to achieve. I might be wrong, so let me know – Andrei Sfat Nov 03 '17 at 08:49
  • Yes you are correct, i saw that later aswell. Im also slightly confused what he is trying to do soince he still has a static reference to `scene` up top – Ellisan Nov 03 '17 at 08:49
  • That makes sense. Also after deleting, the rows goes so wrong. (the grid) Do you guys know how to solve that? – Karl Sburg Nov 03 '17 at 09:07