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

2014/1/9

Greenfoot Collision Crash

ChuckTenton ChuckTenton

2014/1/9

#
Hello everyone, I am a beginner in Object Oriented Programming and I have been experiencing a rather strange problem. What I have is a soldier with an animated image (it uses a loop in an array to animate and I have made sure the hitbox of the individual images are constantly the same, max height and width wise). All it does now is simply walking and colliding with objects. However, it sometimes collides with an object and crashes my entire Greenfoot program (it won't compile anymore, and won't throw an error). Here is my code :
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
public class Police extends Actor
{
    private char dir = 'R';
    public static int XP;
    public static int YP;
    private static int imageCounter;
    GreenfootImage[] imagesL = new GreenfootImage[7];
    GreenfootImage[] imagesR = new GreenfootImage[7];
    GreenfootImage[] imagesU = new GreenfootImage[7];
    GreenfootImage[] imagesD = new GreenfootImage[7];
    public void act()
    {
        walk();
        animate();
        if (Greenfoot.isKeyDown("left") || Greenfoot.isKeyDown("right") || Greenfoot.isKeyDown("up") || Greenfoot.isKeyDown("down")){
            animation();
        }
        getXPosition();
        getYPosition();
    }   
 
    public void walk(){
        int x = getX();
        int y = getY();
        if (Greenfoot.isKeyDown("up")){
            if (getOneObjectAtOffset(0, -(getImage().getHeight()/2)-4, Obstacle.class) == null){
                setLocation(x, y-4);
            }
            else{
                while (getOneObjectAtOffset(0, -(getImage().getHeight()/2)-1, Obstacle.class) == null){
                    setLocation (x, y-1);
                }
            }
            dir = 'U';
        }
        if (Greenfoot.isKeyDown("down")){
            if (getOneObjectAtOffset(0, (getImage().getHeight()/2)+4, Obstacle.class) == null){
                setLocation(x, y+4);
            }
            else{
                while (getOneObjectAtOffset(0, (getImage().getHeight()/2)+1, Obstacle.class) == null){
                    setLocation(x, y+1);
                }
            }
            dir = 'D';
        }
        if (Greenfoot.isKeyDown("left")){
            if (getOneObjectAtOffset(-(getImage().getWidth()/2)-4, 0, Obstacle.class) == null){
                setLocation(x-4, y);
            }
            else{
                while (getOneObjectAtOffset(-(getImage().getWidth()/2)-1, 0, Obstacle.class) == null){
                    setLocation(x-1, y);
                }
            }
            dir = 'L';
        }
        if (Greenfoot.isKeyDown("right")){
            if (getOneObjectAtOffset((getImage().getWidth()/2)+4, 0, Obstacle.class) == null){
                setLocation(x+4, y);
            }
            else{
                while (getOneObjectAtOffset((getImage().getWidth()/2)+1, 0, Obstacle.class) == null){
                    setLocation(x+1, y);
                }
            }
            dir = 'R';
        }
    }
 
    public void animate(){
        for( int i=0; i<imagesD.length; i++ ) {
            switch (dir){
                case 'D':
                imagesD[i] = new GreenfootImage( "P_D_" + i + ".png" ); 
                setImage( imagesD[imageCounter] );
                break;
                case 'U':
                imagesU[i] = new GreenfootImage( "P_U_" + i + ".png" ); 
                setImage( imagesU[imageCounter] );
                break;
                case 'L':
                imagesL[i] = new GreenfootImage( "P_L_" + i + ".png" ); 
                setImage( imagesL[imageCounter] );
                break;
                case 'R':
                imagesR[i] = new GreenfootImage( "P_R_" + i + ".png" ); 
                setImage( imagesR[imageCounter] );
                break;
            }
        }
    }
 
    public void animation() 
    {
        switch (dir){
            case 'D':
            imageCounter = ( imageCounter + 1 ) % imagesD.length; 
            setImage( imagesD[imageCounter] );
            break;
            case 'U':
            imageCounter = ( imageCounter + 1 ) % imagesU.length; 
            setImage( imagesU[imageCounter] );
            break;
            case 'L':
            imageCounter = ( imageCounter + 1 ) % imagesL.length; 
            setImage( imagesL[imageCounter] );
            break;
            case 'R':
            imageCounter = ( imageCounter + 1 ) % imagesR.length; 
            setImage( imagesR[imageCounter] );
            break;
        }
    }   
    public int getXPosition(){
        XP = getX();
        return XP;
    }
    public int getYPosition(){
        YP = getY();
        return YP;
    }
}
The Obstacle Class does not have any instance variables nor methods other than Act(){}, and it is a superclass of two seperate objects that are equally empty (these are the objects Police.class is supposed to collide against). Any help would be appreciated ;-)
Gevater_Tod4711 Gevater_Tod4711

2014/1/9

#
The problem is that you use while loops in your walk method. E.g.:
1
2
3
while (getOneObjectAtOffset(0, -(getImage().getHeight()/2)-1, Obstacle.class) == null) {
    setLocation (x, y-1); 
}
If there is no obstacle in the actors way he'll move. Then if there again is no obstacle he'll move again. And if there is no obstacle when the actor reaches the end of the world there will never be any obstacles so the while loop will run on and on... This infinite loop makes greenfoot crash because all the other code is not executed anymore and so you can't do anything. If you use an if-clause instead of the while loop it should work better I think.
ChuckTenton ChuckTenton

2014/1/9

#
Well if you look closely there shouldn't be an infinite loop. the while statement checks the current Y position of the Police actor, and see if the next position would collide with another object. if not, increase/decrease Y. I understand how an infinite loop would make Greenfoot crash, but this does not explain the whole "infinite loop thing" actually happening. Or maybe you are seeing things that I'm not...
Gevater_Tod4711 Gevater_Tod4711

2014/1/9

#
Ok I see that there should not be infinite loops but thats the only think I know that could make greenfoot crash. You could try to use a for loop that does the same like your while loop but maximumly executeds 10 times:
1
2
3
for (int i = 0; getOneObjectAtOffset(0, -(getImage().getHeight()/2)-1, Obstacle.class) == null && i < 10; i++) { 
    setLocation (x, y-1);   
}
That would be more save because this loop will never be infinite unless you change the value of i.
danpost danpost

2014/1/9

#
The x and y at lines 24 and 25 are never updated to the new location during the while loop. Therefore, you continually set the actor to the same location which creates the infinite loop.
ChuckTenton ChuckTenton

2014/1/9

#
ohh What Danpost said makes sense. So what I need to do is do this:
1
2
x = getX();
y = getY();
after every while loop? Anyways thank you for the swift responses! Really appreciate it EDIT: Actually I just tried what I said in this post and it seems to be working properly now ;-) Thanks again!
You need to login to post a reply.