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

2020/10/11

Help with Greenfoot.getKey()

DatHeroAndy DatHeroAndy

2020/10/11

#
So, I want 2 Objects to be moved by getKey(). After I saw that it is not possible to have 2 getKeys at the time, I tried to use
String key = Greenfoot.getKey();
to use the 2 getKeys. Here's my code:
import lang.stride.*;
import java.util.*;
import greenfoot.*;

/**
 * 
 */
public class PlayerOne extends Actor
{
    private String key = Greenfoot.getKey();

    /**
     * Act - do whatever the Am wants to do. This method is called whenever the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        if (key != null && "space".equals(key)) {
            this.move(3);
        }
        if (this.isAtEdge()) {
            getWorld().showText("Player1 wins!", this.getWorld().getWidth() / 2, this.getWorld().getHeight() / 2);
            getWorld().showText("Press the reset button if you want to play again.", this.getWorld().getWidth() / 2, 220);
            Greenfoot.stop();
        }
    }
}
The code for the 2. Player is pretty much the same, the only thing different is that I want the CTRL key for the 2. Player and not the space bar. And I don't want to use isKeyDown(), because then you can just hold the space bar/ctrl key to move forward. I want the players to repeatedly tab on the space bar / ctrl key to get along. Hope that someone can help me with this issue.
RcCookie RcCookie

2020/10/11

#
You need to update the string every frame. For one player this will work just fine, however, the second player will get the reset value of Greenfoot.getKey(): null. The solution is to call this method only once per frame. There may be many possibilities how to do this, but one easy is to use the world as there will always be exactly one world.
//in your world class
private String key;

public void act() {
    key = Greenfoot.getKey();
    //other act stuff
}

public void getKey() {
    return key;
}
For the players as a sidenode, it’s way easier especially if you want to modify their code, to just use one class and define in the constructor their input key.
//Combines PlayerOne and PlayerTwo
public class Player {
    private final String myKey;

    public Player(String myKey) {
        this.myKey = myKey;
        //Other constructor stuff
    }


    public void act() {
        //Assuming that your world class is called MyWorld
        String input = ((MyWorld)getWorld()).getKey();
        if(myKey.equals(input)) {
            ...
        }
        ...
    }
}
RcCookie RcCookie

2020/10/11

#
If you want your players to have different images or other things differently, you may not want to input a string but a number to give it a type:
//Inside of player class

//The keys for the different players
static final String keys = {"space", "ctrl"};

//First player is 0, second is 1...
//(For each player there has to be a key defined in keys, or there will be an error!
private final int type;

public Player(int type) {
    this.type = type;
    //Example for setting an image:
    setImage("images/player" + type + ".png");
    //...
}

public void act() {
    //...
    if(keys[type].equals(input)) {
        //...
    }

    //For printing out the winner:
    String text = "Player " + (type+1) + "won!";
}
DatHeroAndy DatHeroAndy

2020/10/11

#
Worked perfectly! Thanks!
DatHeroAndy DatHeroAndy

2020/10/11

#
RcCookie wrote...
You need to update the string every frame. For one player this will work just fine, however, the second player will get the reset value of Greenfoot.getKey(): null. The solution is to call this method only once per frame. There may be many possibilities how to do this, but one easy is to use the world as there will always be exactly one world.
//in your world class
private String key;

public void act() {
    key = Greenfoot.getKey();
    //other act stuff
}

public void getKey() {
    return key;
}
For the players as a sidenode, it’s way easier especially if you want to modify their code, to just use one class and define in the constructor their input key.
//Combines PlayerOne and PlayerTwo
public class Player {
    private final String myKey;

    public Player(String myKey) {
        this.myKey = myKey;
        //Other constructor stuff
    }


    public void act() {
        //Assuming that your world class is called MyWorld
        String input = ((MyWorld)getWorld()).getKey();
        if(myKey.equals(input)) {
            ...
        }
        ...
    }
}
Only found one mistake. The "public void getKey()" method would give me an error, but replacing the void with String would fix this error.
RcCookie RcCookie

2020/10/11

#
Sorry mate, didn’t test run it. Good that you figured out how to fix it
You need to login to post a reply.