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

2023/3/27

NullPointerException in Grabber Class

KCee KCee

2023/3/27

#
I have a NullPointerException in lines 23 and 18 and im not sure what the error is. Grabber code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Grabber here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public abstract class Grabber extends Vehicle {
    private Villager grabbed;
     
    public Grabber(final VehicleSpawner origin) {
        super(origin);
    }
  
    public void act() {
        drive();
        checkHitPedestrian();
    }
     
    public boolean checkHitPedestrian() {
        final boolean isNewlyGrabbed = tryGrab();
        if (grabbed.getWorld() == null){
            grabbed = null;
        }
        if (grabbed != null && grabbed.getWorld() !=null) {
            actionWithGrabbed(grabbed, isNewlyGrabbed);
        }
        return grabbed != null;
    }
    
    public Villager getGrabbed() 
    {
        return grabbed;
    }
    
    private boolean tryGrab() 
    {
        if (grabbed == null) {
            final VehicleWorld world = (VehicleWorld)getWorld();
            for (final Villager villager : getObjectsAtOffset((int)speed + getImage().getWidth() / 2, 0, Villager.class)) {
                if (!world.isGrabbed(villager)) {
                    grabbed = villager;
                    return true;
                }
            }
        }
        return false;
    }
     
    /**
     * Do whatever has to be done with the grabbed villager.
     * 
     * This method is automatically called after checkHitPedestrian has grabbed onto a villager.
     * 
     * @param grabbed the grabbed villager, must not be null.
     * @param isNewlyGrabbed whether the villager has just been grabbed in this act.
     */
    protected abstract void actionWithGrabbed(final Villager grabbed, final boolean isNewlyGrabbed);
     
    public void releaseGrabbed() {
        grabbed = null;
    }
}
Vehicle Code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * This is the superclass for Vehicles.
 * 
 */
public abstract class Vehicle extends SuperSmoothMover
{
    protected double maxSpeed;
    protected double speed;
    protected int direction; // 1 = right, -1 = left
    protected boolean moving;
    protected int yOffset;
    protected VehicleSpawner origin;
    
    protected abstract boolean checkHitPedestrian ();

    public Vehicle (VehicleSpawner origin) {
        this.origin = origin;
        moving = true;
        
        if (origin.facesRightward()){
            direction = 1;
            
        } else {
            direction = -1;
            getImage().mirrorHorizontally();
        }
    }
    
    public void addedToWorld (World w){
        setLocation (origin.getX() - (direction * 100), origin.getY() - yOffset);
    }

    /**
     * A method used by all Vehicles to check if they are at the edge.
     * 
     * Note that this World is set to unbounded (The World's super class is (int, int, int, FALSE) which means
     * that objects should not be stopped from leaving the World. However, this introduces a challenge as there
     * is the potential for objects to disappear off-screen but still be fully acting and thus wasting resources
     * and affecting the simulation even though they are not visible.
     */
    protected boolean checkEdge() {
        if (direction == 1)
        { // if moving right, check 200 pixels to the right (above max X)
            if (getX() > getWorld().getWidth() + 200){
                return true;
            }
        } 
        else 
        { // if moving left, check 200 pixels to the left (negative values)
            if (getX() < -200){
                return true;
            }
        }
        return false;
    }

    /**
     * Method that deals with movement. Speed can be set by individual subclasses in their constructors
     */
    public void drive() 
    {
        boolean bloodMooning = VehicleWorld.isBloodMooning();
        // Ahead is a generic vehicle - we don't know what type BUT
        // since every Vehicle "promises" to have a getSpeed() method,
        // we can call that on any vehicle to find out it's speed
        Vehicle ahead = (Vehicle) getOneObjectAtOffset (direction * (int)(speed + getImage().getWidth()/2 + 4), 0, Vehicle.class);
        if (ahead == null)
        {
            speed = maxSpeed;

        } else {
            speed = ahead.getSpeed();
        }
        
        if (bloodMooning)
        {
            speed = maxSpeed*2;
            move (speed * direction);
        }
        else
        {
            speed = maxSpeed;
            move (speed * direction);
        }
    }   

    /**
     * An accessor that can be used to get this Vehicle's speed. Used, for example, when a vehicle wants to see
     * if a faster vehicle is ahead in the lane.
     */
    public double getSpeed(){
        return speed;
    }
    
    public void speedUp () {
        speed = maxSpeed*3;
    }
}
Spock47 Spock47

2023/3/27

#
KCee wrote...
        if (grabbed.getWorld() == null){
            grabbed = null;
        }
        if (grabbed != null && grabbed.getWorld() !=null) {
            actionWithGrabbed(grabbed, isNewlyGrabbed);
        }
grabbed can be null there, so replace the quoted lines with this (it moves the relevant line into the part where grabbed is checked to not be null):
    if (grabbed != null) {
        if (grabbed.getWorld() == null) {
            grabbed = null;
        } else {
            actionWithGrabbed(grabbed, isNewlyGrabbed);
        }
    }
You need to login to post a reply.