0

I'm working on a game in Java using the Slick2D library. I've just started building a new mechanic which will involve a laser that I will implement the ability to redirect later. But for now I'm having trouble rendering a basic laser in the first place.

Below is the code for the class that handles the laser shooting object. The "updateLaser" method is used in the update loop of the basicGame extension, and the "render" method in the render loop.

package assets;

import java.util.ArrayList;

import levelTEST.BoxesTest;
import levelTEST.WallsTest;
import org.newdawn.slick.Color;
import org.newdawn.slick.ShapeFill;
import org.newdawn.slick.fills.GradientFill;
import org.newdawn.slick.geom.Point;
import org.newdawn.slick.geom.Polygon;
import org.newdawn.slick.geom.Shape;
import org.newdawn.slick.geom.ShapeRenderer;

public class LaserFire {

    Polygon hitbox;
    ArrayList<Point> laser = new ArrayList<Point>();
    String directL;
    float xL;
    float yL;
    boolean isOn;
    WallsTest wT;
    float startX;
    float startY;
    boolean laserNew;
    float pointX;
    float pointY;
    BoxesTest bT;

    // the wallstest and boxestest variables are just for colision, just ignore
    // them
    public LaserFire(float x, float y, WallsTest wt, BoxesTest bt, String direct) {
        hitbox = new Polygon();
        directL = direct;
        xL = x;
        yL = y;
        // this part of the code creates the hitbox of the laser shooter and
        // determines where the laser will start
        if (direct.equals("top")) {
            hitbox.addPoint(x, y + 50);
            hitbox.addPoint(x + 50, y + 50);
            hitbox.addPoint(x + 25, y);
            startX = xL + 25;
            startY = yL;
        } else if (direct.equals("bottom")) {
            hitbox.addPoint(x, y);
            hitbox.addPoint(x + 50, y);
            hitbox.addPoint(x + 25, y + 50);
            startX = xL + 25;
            startY = yL + 50;
        } else if (direct.equals("left")) {
            hitbox.addPoint(x + 50, y + 50);
            hitbox.addPoint(x + 50, y);
            hitbox.addPoint(x, y + 25);
            startX = xL;
            startY = yL + 25;
        } else if (direct.equals("right")) {
            hitbox.addPoint(x, y);
            hitbox.addPoint(x, y + 50);
            hitbox.addPoint(x + 50, y + 25);
            startX = xL + 50;
            startY = yL + 25;
        }
        isOn = true;
        wT = wt;
        laserNew = true;
        pointX = 0;
        pointY = 0;
        bT = bt;
    }

    public void updateLaser(int delta) {
        // first I wanted the laser to not be instant in how fast it went, so I
        // limit the amount of time it takes before a new point in the laser can
        // be added
        int time = 0;
        int timeToBlock = 2;
        // second I made sure to start the laser in the correct spot and to have
        // a point to start the laser (so there is a point to render at first)
        if (laserNew == true) {
            laser.add(new Point(startX, startY));
            pointX = startX;
            pointY = startY;
            laserNew = false;
        }
        // if the laser is on...
        if (isOn) {
            // this is part of the time limiter
            if (time > 0 && time < timeToBlock) {
                time += delta;
            } else if (time >= timeToBlock) {
                time = 0;
            }
            // here's where each new point of the laser is added, it first
            // checks if it would colide with the wall, if so, no new points are
            // added
            if (bT.allColide(new Point(pointX, pointY)) != true
                    && wT.checkColi(new Point(pointX, pointY)) != true
                    && time == 0) {
                // then it adds a point if there is space for it
                laser.add(new Point(pointX, pointY));
                // then it checks what direction the laser is going, and plans
                // where the next point will be
                if (directL.equals("top")) {
                    pointY -= 1;
                } else if (directL.equals("bottom")) {
                    pointY++;
                } else if (directL.equals("left")) {
                    pointX -= 1;
                } else if (directL.equals("right")) {
                    pointX++;
                }
                // this part sets of the timer
                time += delta;
            }
        } else if (isOn != true) {
            // this resets the laser if it is off
            laser.clear();
            laserNew = true;
        }
    }

    public void render() {
        // first I need the colors for the laser and the ShapeFill to fill it in
        Color c = new Color(10, 210, 210);
        Color c2 = new Color(10, 210, 210);
        Color cL = new Color(255, 10, 10);
        ShapeFill fillbox;
        // if the laser is on it fills one color for the shooter, if not,
        // another
        if (isOn) {
            fillbox = new GradientFill(0, 0, c, 960, 540, c);
        } else {
            fillbox = new GradientFill(0, 0, c2, 960, 540, c2);
        }
        // this renders the shooter
        ShapeFill fillLaser = new GradientFill(0, 0, cL, 960, 540, cL);
        ShapeRenderer.fill(hitbox, fillbox);
        // if the laser is on, this renders each part of the laser beam
        if (isOn) {
            for (int i = 0; i < laser.size(); i++) {
                ShapeRenderer.fill(laser.get(i), fillLaser);
            }
        }
    }

    // this part is for character colision, and works fine.
    public boolean colision(Shape X) {
        boolean check = false;
        if (hitbox.intersects(X)) {
            check = true;
        } else if (hitbox.intersects(X) != true) {
            check = false;
        }
        return check;
    }
}

Every time I run the code in Eclipse I get a NullPointerException at the following line (at least according to Eclipse):

&& wT.checkColi(new Point(pointX, pointY)) != true

I've tested the class with the laser off, and it works just fine, but now with me testing the laser on I keep getting this exception.

I assume this has to do with how I'm adding on to the ArrayList "laser" within the if statement, but I don't really know. Just in case it has to do with the collision detection for the wallsTest object, here's the "checkColi" method from that object:

public boolean checkColi(Shape jupiter){
        boolean colide = false;
        if (top.intersects(jupiter)){
            colide = true;
        }if (bottom.intersects(jupiter)){
            colide = true;
        }if (left.intersects(jupiter)){
            colide = true;
        }if (right.intersects(jupiter)){
            colide = true;
        }if (midtop.intersects(jupiter)){
            colide = true;
        }if (midbottom.intersects(jupiter)){
            colide = true;
        }if (spire.intersects(jupiter)){
            colide = true;
        }
        return colide;
    }

Here is the initialization of the "WallsTest" object that is used in the laser class:

This is the wT being passed in the constructor

package levelTEST;

public class levelTest{
    public WallsTest W;
    public void render(){
        W = new WallsTest();
        W.render();
    }
}

This class (levelTEST) is going to be used to manage all the other classes that take care of various objects, so far, though, it only takes care of the walls object.

This class itself is initialized in the following class Level (this class is going to manage all the levels, but again, hasn't gotten that far):

package assets;

import levelTEST.levelTest;

public class Level{
    public levelTest lT = new levelTest();
    public void main(){
        lT.render();
    }
}

And at the very end it is all initialized in the main game class like so:

Level lT = new Level();

Below is how the object wT gets passed on:

LaserTest laT = new LaserTest(lT.lT.W , bT);

lT.lT.W is being passed in the constructor, it is the "wallstest" object within the "leveltest" object within the "level" object.

This line is from the main BasicGame extended class that initializes the LaserTest class (a class that itself initializes the LaserFire class) the "lT.lT.W" leads to the WallsTest "W" that is used in the LaserFire object.

Below is the LaserTest class, it shows how wT is passed into the constructor for the "LaserFire" class:

package levelTEST;

import org.newdawn.slick.geom.Shape;

import assets.LaserFire;

public class LaserTest {

    LaserFire[] lasers;

    public LaserTest(WallsTest wT, BoxesTest bT) {
        //this is how the wT variable is passed into the LaserFire object
        LaserFire L1 = new LaserFire(300, 300, wT, bT, "top");

        lasers = new LaserFire[] { L1 };
    }

    public void render() {
        for (int i = 0; i < lasers.length; i++) {
            lasers[i].render();
        }
    }

    public void update(int delta) {
        for (int i = 0; i < lasers.length; i++) {
            lasers[i].updateLaser(delta);
        }
    }

    public boolean colide(Shape X) {
        boolean coli = false;
        for (int i = 0; i < lasers.length; i++) {
            if (lasers[i].colision(X)) {
                coli = true;
            }
        }
        return coli;
    }

}
Ryuluce
  • 21
  • 6
  • How do you instantiate the object? `wT` is null (if you get an error there) but I want to be sure of that. – Makoto Jul 07 '15 at 03:16
  • @Makoto The object wT is initialized within another class that manages several classes like so: 'W = new WallsTest();' (the constructor relies on no variables) this "W" object is what is input into the wT variable. – Ryuluce Jul 07 '15 at 03:19
  • Where does the constructor where you only pass two things in come from? It doesn't match the constructor you've got declared there. – Makoto Jul 07 '15 at 03:28
  • @Makoto Added the code that initializes the walls object – Ryuluce Jul 07 '15 at 03:28
  • @Makoto That is not the same class, I added the code for the class that that is initializing. – Ryuluce Jul 07 '15 at 03:31
  • Okay. Let me be explicit. What are you passing in for `wT`? – Makoto Jul 07 '15 at 03:33
  • @Makoto I am passing the object "lT.lT.W". I have now added the code to fully explain how the object was created and passed in the constructor. – Ryuluce Jul 07 '15 at 03:43
  • The ultimate result of that field is `null`. You don't initialize it in a constructor of sorts, so its only value could be `null`. – Makoto Jul 07 '15 at 03:56
  • @Makoto I know that the variable wT should not be Null. I use it in other classes without error. – Ryuluce Jul 07 '15 at 03:57
  • Maybe you should just chase back your varaible. I mean print the value in the constructor and then back in the stack call to find where it is null – RPresle Jul 10 '15 at 06:37

0 Answers0