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

2017/2/14

I Receive an Error Message Whenever I Remove an Actor

Cirion Cirion

2017/2/14

#
I have a game that's supposed to remove an actor whenever it eats it, and it does, but it also gives an error message and pauses the program. How can I stop this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
/**
 * Write a description of class nonPlayerCharacters here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class nonPlayerCharacters extends insects
{
    int x;
    int y; boolean food;
 
    /**
     * Act - do whatever the nonPlayerCharacters wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
     
    public boolean atWorldEdge()
    {
        if (getX() <= 5 || getX() >= getWorld() . getWidth() -5 || getY() <= 5 || getY() >= getWorld() . getHeight() -5)
        {   
            return true;
        }
        else
        {
            return false;
        }
    }
     
    public int movement(int x)
    {
        int q = 0;
        while (q<30)
        {
            move(x); delay(1); q++; kill ();
        }
        return (x);
    }
     
        public int delay (int z)
    {
        Greenfoot.delay(z);
        return(z);
    }
     
    public void borderTurn ()
    {
        if (atWorldEdge())
        {
            turnTowards(500,300);
                atWorldEdge();
                movement(1); delay(1);
        }
    }
     
    public int playerDetection(int a)
    {
        Actor playerCharacter;
        playerCharacter = getWorld().getObjects(playerCharacter.class).get(0);
         
        turnTowards(playerCharacter.getX()*a, playerCharacter.getY()*a);
             
        return(a);
    }
     
        public void kill ()
    {
                 
        if (isTouching(playerCharacter.class)&&food)
        {
            World world;
            world = getWorld();
            Actor superfood;
            superfood = this.getOneObjectAtOffset(0, 0, superfood.class);
            if (getWorld() != null){getWorld().removeObject(this);}
            counter.addScore(); counter.addScore();
        }
         
        if (isTouching(playerCharacter.class)&&!food)
        {
            World world;
            world = getWorld();
            Actor food;
            food = this.getOneObjectAtOffset(0, 0, food.class);
            getWorld().getObjects(food.class);
            if (getWorld() != null){getWorld().removeObject(this);}
            counter.addScore();
        }
         
    }
     
    public void act()
    {
         
    }   
}
danpost danpost

2017/2/14

#
Cirion wrote...
I have a game that's supposed to remove an actor whenever it eats it, and it does, but it also gives an error message and pauses the program. How can I stop this? < Code Omitted >
Use 'else if' at line 80 so that collision checking (isTouching) is not attempted if the actor was removed by the first 'if' block.
danpost danpost

2017/2/14

#
You are not using 'world' (lines 72, 73, 82 and 83), 'food' (84 and 85) or 'superfood' (74 and 75) in the blocks they are declared in and 'getWorld' cannot be null until removal of the actor from the world and line 86 is just a hanging List object (getObjects is returning a List; but, it is not going anywhere or being used for anything). So, after removing all the nonsense and simplifying, you have this:
1
2
3
4
5
6
7
8
9
public void kill()
{
    if (isTouching(playerCharacter.class))
    {
        getWorld().removeObject(this);
        counter.addScore();
        if (food) counter.addScore();
    }
}
Cirion Cirion

2017/2/15

#
Thanks danpost! Here's my modified my kill() method:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void kill ()
{
             
    if (isTouching(playerCharacter.class)&&food)
    {
        getWorld().removeObject(this);
        counter.addScore();
        if (food) counter.addScore();
    }
     
    else if (isTouching(playerCharacter.class)&&!food)
    {
        getWorld().removeObject(this);
        counter.addScore();
        if (food) counter.addScore();
    }
     
}
However, I am still getting an error message when I remove the actor. Am I misunderstanding your suggestions?
Cirion Cirion

2017/2/15

#
This is the error message
1
2
3
4
5
6
7
8
9
10
java.lang.IllegalStateException: Actor not in world. An attempt was made to use the actor's location while it is not in the world. Either it has not yet been inserted, or it has been removed.
    at greenfoot.Actor.failIfNotInWorld(Actor.java:711)
    at greenfoot.Actor.isTouching(Actor.java:972)
    at nonPlayerCharacters.kill(nonPlayerCharacters.java:70)
    at nonPlayerCharacters.movement(nonPlayerCharacters.java:36)
    at superfood.act(superfood.java:15)
    at greenfoot.core.Simulation.actActor(Simulation.java:604)
    at greenfoot.core.Simulation.runOneLoop(Simulation.java:562)
    at greenfoot.core.Simulation.runContent(Simulation.java:221)
    at greenfoot.core.Simulation.run(Simulation.java:211)
danpost danpost

2017/2/15

#
Apparently, the change I gave was not enough because you are calling the 'kill' method from within a 'while' loop. Change the 'kill' method to what I gave above (I gave what the entire method should look like). Then, in the 'movement' method, change line 34 to the following:
1
while (q < 30 && getWorld() != null)
Not sure why you have the 'movement' and 'delay' methods returning back the same value that were sent them. Seems a bit pointless.
Cirion Cirion

2017/2/16

#
danpost wrote...
Not sure why you have the 'movement' and 'delay' methods returning back the same value that were sent them. Seems a bit pointless.
Could you explain to me what return really means? I have it there because that's how I've seen others do it.
Cirion Cirion

2017/2/16

#
I'm still receiving the error message and I've also added this getWorld() check to all methods that are called. Here's the modified class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
/**
 * Write a description of class nonPlayerCharacters here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class nonPlayerCharacters extends insects
{
    int x;
    int y; boolean food;
 
    /**
     * Act - do whatever the nonPlayerCharacters wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
     
    public boolean atWorldEdge()
    {
        if (getX() <= 5 || getX() >= getWorld() . getWidth() -5 || getY() <= 5 || getY() >= getWorld() . getHeight() -5 && getWorld() != null)
        {   
            return true;
        }
        else
        {
            return false;
        }
    }
     
    public int movement(int x)
    {
        int q = 0;
        while (q<30 && getWorld() != null)
        {
            move(x); delay(1); q++; kill ();
        }
        return (x);
    }
     
        public int delay (int z)
    {
        Greenfoot.delay(z);
        return(z);
    }
     
    public void borderTurn ()
    {
        if (atWorldEdge() && getWorld() != null)
        {
            turnTowards(500,300);
                atWorldEdge();
                movement(1); delay(1);
        }
    }
     
    public int playerDetection(int a)
    {
        if (getWorld() != null)
        {
            Actor playerCharacter;
            playerCharacter = getWorld().getObjects(playerCharacter.class).get(0);
         
            turnTowards(playerCharacter.getX()*a, playerCharacter.getY()*a);
        }   
        return(a);
   }
     
        public void kill ()
    {  
            if (isTouching(playerCharacter.class))
            {
                getWorld().removeObject(this);
                counter.addScore();
                if (food) counter.addScore();
            }
    }
     
    public void act()
    {
         
    }   
}
danpost danpost

2017/2/16

#
Cirion wrote...
Could you explain to me what return really means? I have it there because that's how I've seen others do it.
Usually, a 'return' statement is used to accomplish one of two things (or both at the same time). One is to make an early exit from the method (so the rest of the method is skipped from being executed). The other is to pass a value back to the calling statement. Returning a value is most often used in what are called 'getter' methods, where that is the only thing the method does (returns a particular value or object reference). Sometimes, a calculation is performed and the result is returned; sometimes some action is performed only if a condition is true and that result of that condition is returned to inform the calling statement whether the action was actually performed or not. For a full explanation, go to this page of the java tutorials.
davmac davmac

2017/2/16

#
Just for a little extra to what danpost says above: "return" is actually short for "return to caller" ("return to the calling method"). It means that the current method stops executing, and the execution resumes in the calling method.
danpost danpost

2017/2/16

#
Cirion wrote...
I'm still receiving the error message and I've also added this getWorld() check to all methods that are called.
If you are going to add this 'getWorld()' check to all methods, make sure that it is the first condition checked (particularly referring to line 49).
Cirion Cirion

2017/2/21

#
Thanks for your continued support. I've taken your advice and even added a check to the actors, but I still receive an error message upon removing an actor. Why is this happening?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
/**
 * Write a description of class nonPlayerCharacters here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class nonPlayerCharacters extends insects
{
    int x;
    int y; boolean food;
 
    /**
     * Act - do whatever the nonPlayerCharacters wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
     
    public boolean atWorldEdge()
    {
        if (getWorld() != null && getX() <= 5 || getX() >= getWorld() . getWidth() -5 || getY() <= 5 || getY() >= getWorld() . getHeight() -5)
        {   
            return true;
        }
        else
        {
            return false;
        }
    }
     
    public int movement(int x)
    {
        if (getWorld() != null)
    {
            int q = 0;
        while (getWorld() != null && q<30)
        {
            if (x == 3)
            {
                GreenfootImage myImage = new GreenfootImage("enemy1.png");
                setImage(myImage);
            }
            move(x); delay(1); q++; kill ();
            if (x == 3)
            {
                GreenfootImage myImage = new GreenfootImage("enemy2.png");
                setImage(myImage);
            }
        }
    }
        return (x);
    }
     
        public int delay (int z)
    {
        if (getWorld() != null)
        {
            Greenfoot.delay(z);
        }
        return(z);
    }
     
    public void borderTurn ()
    {
        if (getWorld() != null && atWorldEdge())
        {
            turnTowards(500,300);
                atWorldEdge();
                movement(1); delay(1);
        }
    }
     
    public int playerDetection(int a)
    {
        if (getWorld() != null)
        {
            Actor playerCharacter;
            playerCharacter = getWorld().getObjects(playerCharacter.class).get(0);
         
            turnTowards(playerCharacter.getX()*a, playerCharacter.getY()*a);
        }   
        return(a);
   }
     
        public void kill ()
    {  
            if (getWorld() != null && isTouching(playerCharacter.class))
            {
                getWorld().removeObject(this);
                counter.addScore();
                if (food) counter.addScore();
            }
    }
     
    public void act()
    {
         
    }   
}
1
2
3
4
5
6
7
8
9
public class superfood extends nonPlayerCharacters
{
         
    public void act()
    {
        if (getWorld() != null)
        {food = true; movement(6); playerDetection(-1); borderTurn(); atWorldEdge();}
    }   
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class food extends nonPlayerCharacters
{
    /**
     * Act - do whatever the food wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
     
     
     
    public void act()
    {
            if (getWorld() != null)  {food = false; movement(4); playerDetection(-1); borderTurn(); atWorldEdge();}
    }   
}
Error Message wrote...
java.lang.IllegalStateException: Actor not in world. An attempt was made to use the actor's location while it is not in the world. Either it has not yet been inserted, or it has been removed. at greenfoot.Actor.failIfNotInWorld(Actor.java:711) at greenfoot.Actor.getX(Actor.java:164) at nonPlayerCharacters.atWorldEdge(nonPlayerCharacters.java:21) at food.act(food.java:20) at greenfoot.core.Simulation.actActor(Simulation.java:604) at greenfoot.core.Simulation.runOneLoop(Simulation.java:562) at greenfoot.core.Simulation.runContent(Simulation.java:221) at greenfoot.core.Simulation.run(Simulation.java:211) java.lang.IllegalStateException: Actor not in world. An attempt was made to use the actor's location while it is not in the world. Either it has not yet been inserted, or it has been removed. at greenfoot.Actor.failIfNotInWorld(Actor.java:711) at greenfoot.Actor.getX(Actor.java:164) at nonPlayerCharacters.atWorldEdge(nonPlayerCharacters.java:21) at superfood.act(superfood.java:15) at greenfoot.core.Simulation.actActor(Simulation.java:604) at greenfoot.core.Simulation.runOneLoop(Simulation.java:562) at greenfoot.core.Simulation.runContent(Simulation.java:221) at greenfoot.core.Simulation.run(Simulation.java:211)
danpost danpost

2017/2/21

#
In your atWorldEdge method, you are only checking to see if the actor is in the world for the first part of the conditions. Because you are ORing the conditionals, you would need to check before each one. Something like this:
1
if (getWorld() != null && getX() <= 5 || getWorld() != null && getX() >= getWorld() . getWidth() -5 || getWorld() != null && getY() <= 5 || getWorld() != null && getY() >= getWorld() . getHeight() -5)
More simply, you can modify the method like so:
1
2
3
4
5
6
7
8
9
10
11
12
public boolean atWorldEdge()
{
    if (getWorld() == null) return false;
    if (getX() <= 5 || getX() >= getWorld().getWidth()-5 || getY() <= 5 || getY() >= getWorld().getHeight()-5)
    {
        return true;
    }
    else
    {
        return false;
    }
}
Or even more simply:
1
2
3
4
public boolean atWorldEdge()
{
    return getWorld() != null && (getX() <= 5 || getX() >= getWorld().getWidth()-5 || getY() <= 5 || getY() >= getWorld().getHeight()-5);
}
You need to login to post a reply.