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

2013/9/18

Can't add a new object to the world from another class.

oldmonk7 oldmonk7

2013/9/18

#
I am creating a Gumball machine scenario in which I have a class Inspector that picks an alien and that alien adds an object to my GumballWorld. The code is very simple as of now but I am getting a null pointer exception. Please help! From the console I can see that I am not able to get the world using getWorld() method. When I directly invoke method pickRandom() from an object of RandomPicker class, it works. But I use the object of Inspector to invoke pickAlien() method, it gives me a null pointer exception! INSPECTOR
public class Inspector extends Alien
{
    /**
     * Act - do whatever the Inspector wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        // Add your action code here.
        //pickAlien();
    }    
    
    public void pickAlien()
    {
       int choice=Greenfoot.getRandomNumber(1);
       if (choice == 0)
       {
           RandomPicker RP =new RandomPicker();
           RP.pickRandom(); 
       }
       else
       {
           GreenPicker GP =new GreenPicker();
           GP.pickGreen(); 
    
       }
    }

}
RANDOMPICKER

public class RandomPicker extends Picker
{
    /**
     * Act - do whatever the RandomPicker wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
       
    }  
    
    public void test()
    {
    
    System.out.println("in test");
    }
    public void pickRandom()
    {
      
     int choice = Greenfoot.getRandomNumber(1);
     switch(choice)
     {
         case 0:
         BlueGumball bg = new BlueGumball();
         getWorld().addObject(bg, 366, 392);
         break;
         case 1:
         System.out.println("getworld()"+new RandomPicker().getWorld());
         //this.getWorld().addObject(new RedGumball(), 366, 392);
         break;   
         case 2:
         System.out.println("getworld()"+new RandomPicker().getWorld());
         //this.getWorld().addObject(new GreenGumball(), 366, 392);
         break;      
        
     }
    }
}
BLUEGUMBALL
 */
public class BlueGumball extends Gumball
{
    /**
     * Act - do whatever the BlueGumball wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        // Add your action code here.
    }    
    
    public BlueGumball()
    {
    GreenfootImage image = getImage() ;
        image.scale( 50, 50 ) ; 
    }
}

danpost danpost

2013/9/19

#
Let me start by informing you that lines 28 and 32 of the RandomPicker class (if they every do get executed) will always print "getWorld()null" to the terminal. Now I will explain why. When you create a new object (as with 'new RandomPicker()', you are creating an object whose returned value of 'getWorld()' is null; it is not added to the world automatically when you create the object. The 'addObject' method from the World class is what will change the returned value from null to the world the object was added to. Often, you will see both actions coded in the same statement, like 'addObject(new RandomPicker)'; however, you do not immediately get a reference to it when coded like that. Coding the two actions separately will give you that reference, like this:
RandomPicker rp = new RandomPicker();
addObject(rp, 0, 0);
Still, from an actor class you need a world to add the object to, and unless that actor is placed in the world, you do not have an immediate reference to the world in which to place the object. Your inspector is in the world. But it creates new objects on lines 18 and 23 and calls a method on them on lines 19 and 24 (without adding the picker objects into the world). Then when the RP object tries to execute line 25, it finds you are trying to add an object to a null world; hence the error. The easiest fix does not involve adding the RP object into the world, however. Better would be to have the pickRandom method return the object back to the calling method:
public Gumball pickRandom()
{
    int choice = Greenfoot.getRandomNumber(3);
    switch(choice)
    {
         case 0: return new BlueGumball();
         case 1: return new RedGumball();
         case 2: return new GreenGumball();
    }
    return null;
}
Then your 'pickAlien' method in the Inspector class should be:
public void pickAlien()
{
    Gumball GB;
    int choice=Greenfoot.getRandomNumber(2);
    if (choice == 0)
    {
        RandomPicker RP =new RandomPicker();
        Gumball GB = RP.pickRandom();
    }
    else
    {
        GreenPicker GP =new GreenPicker(); // same change in GreenPicker
        Gumball GB = GP.pickGreen();
    }
    getWorld().addObject(GB, 366, 392);
}
Now, you do not want to create a gumball on every act method; so, line 10 in the Inspector class should not be there. The world, or another actor, will probably have the inspector create a gumball when the conditions are right.
oldmonk7 oldmonk7

2013/9/19

#
Thanks Danpost. I got your point and thanks for the elegant solution, I was thinking can it get better than this, will get back if I find one.
span span

2013/9/20

#
But dan, if we call the inspector method pickAlien() by creating an object from another actor (class) doesn't the line 15 which does addObject return a null exception?? I tried and am getting one.
danpost danpost

2013/9/20

#
@span, If you are getting a null exception error there, it is probably because your inspector object was not added to the world. Where is the 'pickAlien' method in the Inspector class being called from?
span span

2013/9/20

#
It is added in the world .. from an another actor
public class GMachine extends Actor
{
public void act()
    { 
        if(Greenfoot.mouseClicked(this))
        {
          Inspector inspect = new Inspector();
          inspect.pickAlien();
          }
     }
}
span span

2013/9/20

#
ok i got it.. thanks dan
danpost danpost

2013/9/20

#
No. It is not added to the world. It is created in line 7 and the method is called on it in line 8; but you did not add the 'inspect' object to the world. Alright, let us do the same with 'pickAlien' as we did with 'pickRandom'. Change it to the following:
public Gumball pickAlien()
{
    Gumball GB;
    int choice=Greenfoot.getRandomNumber(2);
    if (choice == 0)
    {
        RandomPicker RP =new RandomPicker();
        Gumball GB = RP.pickRandom();
    }
    else
    {
        GreenPicker GP =new GreenPicker(); // same change in GreenPicker
        Gumball GB = GP.pickGreen();
    }
    return GB;
}
Now that the gumball object is being returned to the GMachine object, we can modify the 'act' there to this:
public void act()
{
    if (Greenfoot.mouseClicked(this))
    {
        Inspector inspect = new Inspector();
        Gumball gball = inspect.pickAlien();
        getWorld().addObject(gball, 366, 392);
    }
}
randeepsingh85 randeepsingh85

2013/9/20

#
HI, If you and me working on the same assignment and Inspector object is already in the world, which I know it is; see if this works for you: List<Inspector> inspectorList = getWorld().getObjects(Inspector.class); if(!inspectorList.isEmpty()) { Inspector inspector = (Inspector)inspectorList.get(0); //use inspector object to call methods. }
span span

2013/9/20

#
danpost wrote...
No. It is not added to the world. It is created in line 7 and the method is called on it in line 8; but you did not add the 'inspect' object to the world. Alright, let us do the same with 'pickAlien' as we did with 'pickRandom'. Change it to the following:
public Gumball pickAlien()
{
    Gumball GB;
    int choice=Greenfoot.getRandomNumber(2);
    if (choice == 0)
    {
        RandomPicker RP =new RandomPicker();
        Gumball GB = RP.pickRandom();
    }
    else
    {
        GreenPicker GP =new GreenPicker(); // same change in GreenPicker
        Gumball GB = GP.pickGreen();
    }
    return GB;
}
Now that the gumball object is being returned to the GMachine object, we can modify the 'act' there to this:
public void act()
{
    if (Greenfoot.mouseClicked(this))
    {
        Inspector inspect = new Inspector();
        Gumball gball = inspect.pickAlien();
        getWorld().addObject(gball, 366, 392);
    }
}
Yup this has strike me immediately , so was my repost .. thanks for clearing again :)
You need to login to post a reply.