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

2017/1/10

getKey() doesn't work für the second instance

Thom Thom

2017/1/10

#
I use two instances of an actor. The instructor of every instance gets 4 different keynames. The goal is to control each Actor-instance with his own keyset. But only the first instance reacts to his keyset, the second doesn't! Why??? Here is the code (only the important snippet):
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
public class Player extends Actor
{
    private Point destination;
    private final String rechts, unten, oben, links; // keynames for the directions
    private String name; // playername
     
    // Constructor:
    public Player(String rechts, String unten, String links, String oben, Point destination, String name,
                    String filename) {    
        this.rechts = rechts;
        this.unten = unten;
        this.links = links;
        this.oben = oben;
        this.destination = destination;
        this.name = name;
        this.setImage(filename);
    }   
     
    public void act()
    {      
        String key = Greenfoot.getKey();
        if (key != null) {
            if (key.equals(rechts)) {
                setRotation(0);
                move(1);
            }
            else if (key.equals(unten)) {
                setRotation(90);
                move(1);
            }
            else if (key.equals(links)) {
                setRotation(180);
                move(1);
            }
            else if (key.equals(oben)) {
                setRotation(270);
                move(1);
            }
        }
    }
}
Thanks for explanation
davmac davmac

2017/1/10

#
A keypress is "consumed" by the call to getKey(). If it wasn't, then once you had pressed a key, getKey() would forever after return that same key. If you want to check if a key is being held down, use isKeyDown(...) instead of getKey().
1
2
3
4
5
if (Greenfoot.isKeyDown(rechts)) {
    setRotation(0);
    move(1);
}
else // ... etc
Super_Hippo Super_Hippo

2017/1/10

#
You can only use 'getKey' one each act-cycle. I think of it like the 'getKey' is like a variable which is set at the beginning of an act-cycle. If you call the method from different classes in the same act-cycle, it can't have a different value. (As I said, that's how I think how it could be, doesn't mean it actually is like that). Try to use the 'Greenfoot.isKeyDown' method.
Thom Thom

2017/1/11

#
The solution with the Greenfoot.isKeiyDown() works without problems! Thank you. #davmac and #Super_Hippo: In spite of your explanations I can't apprehend the reason for the fail of Greenfoot.getKey(). The two Actor-Instances are be created in the contructor of a World-Subclass. Here the code-snippet:
1
2
3
4
5
6
7
// Add Player to the World:
        leftPlayer = new Player("d", "s", "a", "w", new Point(mWidthIC, mHeightIC), "Player links",
                                 "man_from_top_red_50x50.png");
        this.addObject(leftPlayer, 1, 1);
        rightPlayer = new Player("right", "down", "left", "up", new Point(1, 1), "Player rechts",
                                 "man_from_top_green_50x50.png");
        this.addObject(rightPlayer, mWidthIC, mHeightIC);
If I only struck (for example) the "left"-key with the duration of 1 second and no other key I think the getKey()-method had to return this key. In the first act-cycle it returns probably "left", in the second act-cycle (for the second instance) it should return also "left". But it doesn't obviously. If the keypress is consumed by the call to getKey(), the method should also return "left" because I struck the key so long (1 second) that the getKey()-method should read and return "left" again. But in the praxis it doesn't works so.
danpost danpost

2017/1/11

#
The 'getKey' method only registers keys that are being, or have been, released. When a key is released, that is the instance that a keystroke is placed into a keyboard buffer. When a key is 'fetched' from the buffer (using 'getKey'), the buffer pointer is automatically advanced to the location where the next keystroke is/will be stored. If no keys are in the buffer, 'getKey' will return a 'null' value. The 'isKeyDown' method registers keys that are being held down (in the 'pressed' state).
Super_Hippo Super_Hippo

2017/1/11

#
Before posting this, I thought the getKey-method would only work once for a keystroke right after it was pressed (not released as described by danpost). However, if you put the following in the world's act method, you will see that it starts printing right when you press and it does not stop. It doesn't print every act cycle (unless the speed of the scenario is reduced), but it doesn't only print it out once.
1
2
3
4
5
6
7
private int timer = 0;
 
public void act()
{
    timer++;
    if ("space".equals(Greenfoot.getKey())) System.out.println(timer);
}
danpost danpost

2017/1/11

#
Super_Hippo wrote...
Before posting this, I thought the getKey-method would only work once for a keystroke right after it was pressed (not released as described by danpost). However, if you put the following in the world's act method, you will see that it starts printing right when you press and it does not stop. It doesn't print every act cycle (unless the speed of the scenario is reduced), but it doesn't only print it out once.
Tested and confirmed. Thanks for the correction, Super_Hippo.
davmac davmac

2017/1/11

#
In fact, getKey() will return a key whenever it is typed according to the system. Normally that means once when the key is pressed, but because of "autorepeat" functionality you can hold down a key and have it reported continuously at some particular rate (after an initial delay). This "autorepeat" is not part of Greenfoot, but of your operating system.
danpost danpost

2017/1/11

#
I distinctly remember early scenarios I wrote where actors would not move until the key was released when using 'getKey'. It ruined the 'feel' of the game. I think they were in gridded worlds where a keystroke would move you one cell in some direction. Maybe that was a glitch in a version of Windows that was updated and fixed. I do not know.
danpost danpost

2017/1/11

#
Update: I have found that the cursor control keys (up, down, left and right) do not react the same as other keys. They register only when released..
Thom Thom

2017/1/12

#
Okay: Greenfoot.getKey() reacts when a key is pressed down except for the 4 cursor control keys, which react when released. But even if I press a key down several times, the getKey()-method registers it only in the first Actor-Instance ("leftPlayer"). The getKey()-method in the second Actor-Instance ("rightPlayer") doesn't react. I think it should react regardless of whether it is triggered by pressing or releasing a key because I typed the key several times. I have exchanged the cursor control keys (up, down, left and right) with normal letter-keys but this didn't solved the problem. You helped me with your tip to use isKeyDown(...) instead of getKey(). But I still can't comprehend: Why reacts getKey() only in the first Actor-Instance.
danpost danpost

2017/1/12

#
It would be misleading if the 'getKey' method continued to return the same key each time it was called. You would not be able to tell how many times that key was actually pressed -- once? twice? ten times? The method, therefore will return an entered key once, and only once. Only the first actor, in your case, to call 'getKey' will actually get the key; all others will get a 'null' value return until the next act cycle begins. Suffice it to say that 'getKey' is more suited for text input and 'isKeyDown' is more suited for game play controls.
Thom Thom

2017/1/12

#
Thank you for your explanations. Now I think I understand the reason. 'getKey' checks the keys only once in every act cycle. An act cycle runs the act-methods of the both actor-instances. Hence the first instance gets the entered key. After the 'getKey' returns its value the return storage delets its content by replacing it with null. So if the second instance act-method calls 'getKey' it will return null.
danpost danpost

2017/1/12

#
To show in code, with a 'lastKeyTyped' field that is assigned the last key detected as pressed:
1
2
3
String r = lastKeyTyped; // fetches the key (or null) from the field
lastKeyTyped = null; // nullifies the field
return r; // returns the fetched value
These lines (without the comments) were taken directly from the 'getKey' method of the KeyboardManager class of the greenfoot source files.
Thom Thom

2017/1/12

#
The code-snippet of the KeyboardManager class is helpfully to understand the details. Thank you danpost.
You need to login to post a reply.