This site requires JavaScript, please enable it in your browser!
Greenfoot back
DarkGhost
DarkGhost wrote ...

2015/3/12

NullPointerException

DarkGhost DarkGhost

2015/3/12

#
Hey guys, I get a NullPointerException when my enemy's bullet hits the player. The bullet is supposed to subtract 5 from the value of the HealthDisplay class when the bullet hits the player. The NullPointerException happens on line 38 of the Bullet2 Class Any help would be greatly appreciated :) Thanks :) the Error: java.lang.NullPointerException at Bullet2.hitPlayer1(Bullet2.java:38) at Bullet2.act(Bullet2.java:31) Bullet2 Class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Bullet2 here.
 * 
 * @author Owain Jones
 * @version 1.1
 */

public class Bullet2 extends Cymeriadau
{
    private int direction, speed;
    private HealthDisplay health;
    
    public Bullet2(int dir)
    {
        direction = dir;
        speed = -15;
    }

    public void act()
    {
        setRotation(direction);
        move(speed);

        if( atWorldEdge() ) {
            getWorld().removeObject(this);
        }

        if (getWorld() != null) {
            hitPlayer1();
        }
    }

    public void hitPlayer1() {
        Player1 enemy = (Player1) getOneObjectAtOffset(0, 0, Player1.class);
        if (enemy != null) {
            health.setValue(-5);
            getWorld().removeObject(this);
        }

    }
}
HealthDisplay Class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;

/**
 * A simple counter with graphical representation as an actor on screen.
 * 
 * @author mik
 * @version 1.0
 */
public class HealthDisplay extends Actor
{
    private static final Color transparent = new Color(0,0,0,0);
    private GreenfootImage background;
    public static int value = 100;
    public static int target = 100;

    /**
     * Create a new counter, initialised to 0.
     */
    public HealthDisplay()
    {
        background = getImage();  // get image from class
        updateImage();
    }
    
    /**
     * Animate the display to count up (or down) to the current target value.
     */
    public void act() 
    {
        if (value < target) {
            value++;
            updateImage();
        }
        else if (value > target) {
            value--;
            updateImage();
        }
    }

    /**
     * Add a new score to the current counter value.
     */
    public void add(int score)
    {
        target += score;
    }

    /**
     * Return the current counter value.
     */
    public int getValue()
    {
        return value;
    }

    /**
     * Set a new counter value.
     */
    public void setValue(int newValue)
    {
        target = newValue;
        value = newValue;
        updateImage();
    }

    /**
     * Update the image on screen to show the current value.
     */
    private void updateImage()
    {
        GreenfootImage image = new GreenfootImage(background);
        GreenfootImage text = new GreenfootImage("Health:" + value, 22, Color.BLACK, transparent);
        image.drawImage(text, (image.getWidth()-text.getWidth())/2, 
                        (image.getHeight()-text.getHeight())/2);
        setImage(image);
    }
}
Super_Hippo Super_Hippo

2015/3/12

#
You only have 'private HealthDisplay health;' which initialize 'health' to 'null'. You never set it to an object, so it stays 'null' (and you can't call 'setValue' on 'null').
DarkGhost DarkGhost

2015/3/12

#
Ok I see, how could I fix this?
Super_Hippo Super_Hippo

2015/3/12

#
You could add this method to the Bullet2 class if there is always one HealthDisplay object in the world:
protected void addedToWorld(World w)
{
    health = (HealthDisplay) (w.getObjects(HealthDisplay.class).get(0));
}
Or simply remove the 'health' field and use the following instead of 'health.setValue(-5);':
((HealthDisplay)(getWorld().getObjects(HealthDisplay.class).get(0))).setValue(-5);
Here again, this will cause an Exception too, if there isn't a HealthDisplay object in the world. But I guess there will always be one.
davmac davmac

2015/3/12

#
Super_Hippo wrote...
You could add this method to the Bullet2 class if there is always one HealthDisplay object in the world:
You could, but that is a brittle solution (it requires that there's only one HealthDisplay in the world , and it must be added to the world before the Bullet2). Also it's not particularly efficient (the 'getObjects' call is not very fast, and it needs to be called each time you add a Bullet2 into the world). It looks to me like the Bullet2/HealthDisplay classes should not really be coupled. Instead you should set the health of the player (the Player1 instance) and it should in turn update its own HealthDisplay. I.e. add a method to Player1 to set health (and have it update the HealthDisplay as appropriate), and call that method when the bullet hits the Player1 instance.
DarkGhost DarkGhost

2015/3/14

#
Awesome thank you so much that works! :D Thanks!
You need to login to post a reply.