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

2017/4/8

Moving an actor one space at a time

vermox vermox

2017/4/8

#
I'm having difficulty using the keyboard to move an actor one square at a time. At the moment it responds to the keyboard input fine but jumps several cells in the process. My code for this actor is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void act()
 {
 
     if(Greenfoot.isKeyDown("up")){
         setLocation(getX(), getY() - 2);
     }
     if(Greenfoot.isKeyDown("down")){
         setLocation(getX(), getY() + 2);
     }
     if(Greenfoot.isKeyDown("left")){
         setLocation(getX() - 2, getY());
     }
     if(Greenfoot.isKeyDown("right")){
         setLocation(getX() + 2, getY());
 
     }
 }
How can I fix it so that it only moves one cell at a time? Thanks!
danpost danpost

2017/4/8

#
vermox wrote...
How can I fix it so that it only moves one cell at a time?
If you want that one space is moved every time a key is pressed and released, then you can use the getKey method instead of the isKeyDown one.. If you just want a delay between the moves, so if the key is held, the actor moves with delays between each step, you can use an int timer field (this would give the user time to release the key, so the actor can be controlled better).
davmac davmac

2017/4/8

#
And if you want to be able to move a minimum of one cell rather than two, change the 2's in your code to 1's.
vermox vermox

2017/4/8

#
Thank you for your replies. I changed it to get key with these two possibilities
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
String key = Greenfoot.getKey();
if (getOneIntersectingObject(Wall.class) != null){
 
    if(key.equals("up")){
        setLocation(x, y - 1);
    }
    if(key.equals("down")){
        setLocation(x, y + 1);
    }
    if(key.equals("left")){
        setLocation(x - 1, y);
    }
    if(key.equals("right")){
        setLocation(x + 1, y);
 
    }
 
}
and
1
2
3
4
5
6
7
8
9
10
11
12
13
if(Greenfoot.getKey().equals("up")){
     setLocation(getX(), getY() - 1);
 }
 if(Greenfoot.getKey().equals("down")){
     setLocation(getX(), getY() + 1);
 }
 if(Greenfoot.getKey().equals("left")){
     setLocation(getX() - 1, getY());
 }
 if(Greenfoot.getKey().equals("right")){
     setLocation(getX() + 1, getY());
 
 }
Now I don't have any movement as well as a null pointer exception!
Super_Hippo Super_Hippo

2017/4/8

#
If you want to use 'getKey', you either need to make sure it is not null or you have to change the order:
1
if ("up".equals(key))
vermox vermox

2017/4/8

#
Again, thank you very much. The issue I have no is that the actor only moves diagonally two spaces at a time. At least it's moving now though! I need to make is so that it can't walk through walls so I assume I need to use something like
1
if (getOneIntersectingObject(Wall.class) != null)
for this.
danpost danpost

2017/4/8

#
You cannot call 'getKey' but once per act cycle. The first call will return any keystoke that has occurred and any subsequent calls will not return the same value. Usually, it will return 'null' on subsequent calls; however, it is possible under special conditions that it will return another, but distinctly different, keystroke instance. Therefore the moving and collision checking would be best placed together in the same method:
1
2
3
4
5
6
7
8
9
10
11
String key = Greenfoot.getKey();
int dx = 0, dy = 0;
if ("right".equals(key)) dx++;
if ("left".equals(key)) dx--;
if ("down".equals(key)) dy++;
if ("up".equals(key)) dy--;
setLocation(getX()+dx, getY()+dy);
if (getOneIntersectingObject(Wall.class) != null)
{
    setLocation(getX()-dx, getY()-dy);
}
vermox vermox

2017/4/9

#
Thank you so much! It almost works perfectly. I have a scenario which is a house with rooms. The actor can walk into some rooms but not others. Any ideas why this might be the case? Here are the rooms draw:
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
// Outer walls
        for(int i = 0; i < 25; i++){
            Wall wall = new Wall();
            addObject(wall, 0, i);
        }
        for(int i = 0; i < 35; i++){
            Wall wall = new Wall();
            addObject(wall, i, 0);
        }
        for(int i = 25; i >= 0; i--){
            Wall wall = new Wall();
            addObject(wall, 35, i);
        }
        for(int i = 35; i >= 0; i--){
            // Front door
            if( i == 9)
                continue;
            Wall wall = new Wall();
            addObject(wall, i, 30);
        }
        // Master bedroom, library, study, right wall
        for(int i = 0; i < 25; i++){
            //Master ensuite door
            if(i == 2)
                continue;
            // Master bedroom door           
            if(i == 6)
                continue;
            // Study door
            if(i == 14)
                continue;
            // Library door
            if(i == 18)
                continue;
            Wall wall = new Wall();
            addObject(wall, 7, i);
        }
 
.... etc for the rest of the rooms
And I am using the code above for the actor which is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void act()
    {
        String key = Greenfoot.getKey();
        int dx = 0, dy = 0;
        if ("right".equals(key)) dx++;
        if ("left".equals(key)) dx--;
        if ("down".equals(key)) dy++;
        if ("up".equals(key)) dy--;
        setLocation(getX()+dx, getY()+dy);
        if (getOneIntersectingObject(Wall.class) != null)
        {
            setLocation(getX()-dx, getY()-dy);
        }
 
    }
I'm very new to Greenfoot and finding it a bit confusing coming straight from regular Java.
danpost danpost

2017/4/9

#
vermox wrote...
I'm very new to Greenfoot and finding it a bit confusing coming straight from regular Java.
Greenfoot is an IDE that uses regular Java. It just provides its package of classes that can help you create your simulations and games (as well as providing an entry point into your project without the use of a 'static void main(String args)' method and the cycle of frame executions). Make sure that the width and height of the image of your actor are both less than the size of the cells in your world. As an alternative, you could try this for lines 9 through 13 of the act method of the actor:
1
2
3
4
if (getWorld().getObjectsAt(getX()+dx, getY()+dy, Wall.class).isEmpty())
{
    setLocation(getX()+dx, getY()+dy);
}
vermox vermox

2017/4/9

#
It's fixed! Thank you so much! It's just the package classes that I'm not used to I think.
danpost danpost

2017/4/9

#
vermox wrote...
IIt's just the package classes that I'm not used to I think.
Well, its the same learning process as any other package you might import. You look at the documentation to see what the individual classes are for (in general description of class) and what they can do (fields, constructors and methods).
You need to login to post a reply.