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

2011/9/25

How to create a persistent global object reference?

ez4u2c ez4u2c

2011/9/25

#
I would like to make a persistent reference to my world that my actor's methods can use to access my world's methods & variables without having to re-define the world object each time it's used. What I've tried so far compiles okay but gives a runtime error (null pointer). First I tried making a world variable and assigning it at once:
public class Wombat extends Actor
{
    private WombatWorld MyWorld = (WombatWorld) getWorld();
Next, I tried deferring the assignment until the actor's constructor is called:
public class Wombat extends Actor
{
    private WombatWorld MyWorld ;
    
    public Wombat()  {
        MyWorld = (WombatWorld) getWorld();
    }
Neither of these attempts were successful of course. Can anyone help me avoid having to re-declare my world object in every method that needs to reference one of it's methods?
kiarocks kiarocks

2011/9/25

#
This code should work:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)


public class Wombat extends Actor
{
    private WombatWorld MyWorld = (WombatWorld) getWorld();  
    
    public void act() 
    {
       
    }    
}
ez4u2c ez4u2c

2011/9/25

#
This compiles okay, but when one of Wombat's methods tries to use it (at runtime) it gets a null pointer exception. For example: lets say I have an actor class Spot, instantiated in the constructor of WombatWorld with a private variable name (private to WombatWorld), with a public method to return the spot object, called getSpot(). if Wombat has a method that calls getSpot() using MyWorld, it returns a null pointer at runtime. Here's a couple snippets, one from WombatWorld:
public class WombatWorld extends World
{
    private Spot theSpot;

    public WombatWorld()  {
        super(8, 8, 60);        
        theSpot = new Spot();
        addObject(theSpot, 0, 0);
    }

    public Spot getSpot()  {
        return theSpot;
    }
...and one from Wombat:
public class Wombat extends Actor  
{  
    private WombatWorld MyWorld = (WombatWorld) getWorld();

    private boolean onSpot()  {
        Spot spot = MyWorld.getSpot();
        return ((getX() == spot.getX()) && (getY() == spot.getY()));
    }
The null pointer exception occurs line #6 in Wombat. Why doesn't it work?
davmac davmac

2011/9/25

#
Why doesn't it work?
The "getWorld()" method returns the world that the actor is in - if any. If the actor isn't in the world yet, getWorld() returns null. In your example Wombat class above, getWorld() is being called on line 3, which runs when the Wombat is constructed - i.e. before it is actually put in the world. You can override the addedToWorld method to get a reference to the world when the actor is added to it:
    protected void addedToWorld(World theWorld)
    {
        myWorld = theWorld;
    }
Note I wrote 'myWorld' not 'MyWorld', because in Java the convention is to have variable names start with lower-case letters (and class names start with upper-case letters).
ez4u2c ez4u2c

2011/9/26

#
I just uploaded my scenario as "wombat-spot" with the tag "test", for your perusal. It exhibits the same behaviour (null pointer exception) at runtime, so I must have misunderstood your solution. Maybe I put the addedToWorld method in the wrong place? Thanks much for your help.
davmac davmac

2011/9/26

#
The signature for your addedToWorld method is wrong. You have:
protected void addedToWorld(WombatWorld theWorld)
{
    myWorld = theWorld;
}
Whereas it should be:
protected void addedToWorld(World theWorld)
{
    myWorld = (WombatWorld) world;
}
(I missed the typecast earlier - it is necessary of course because you are assigning a World expression to a WombatWorld variable). Because the method is not defined correctly, it doesn't override the method from the Actor class.
You need to login to post a reply.