如何确保只按下一个键

时间:2021-07-25 20:05:02

SO I'm making a game where the user moves on a horizontal, vertical tiled map. However I dont want the user to be able to press 2 keys and make the player move diagonal. ony left,right,up and down.

所以我正在制作一个用户在水平,垂直平铺地图上移动的游戏。但是我不希望用户能够按下2个键并让玩家移动对角线。左,右,上,下。

I currently have a code that does it but if the user presses another key and then lifts it, the player stops moving due to how I have coded it

我目前有一个代码可以执行此操作,但如果用户按下另一个键然后将其抬起,则由于我对其进行编码,播放器会停止移动

@Override
public boolean keyDown(int keycode) {
    if (keyNotDown) {
        switch (keycode) {
        case Keys.RIGHT:
            playScreen.setXD(2);
            break;
        case Keys.LEFT:
            playScreen.setXD(-2);
            break;
        case Keys.DOWN:
            playScreen.setYD(-2);
            break;
        case Keys.UP:
            playScreen.setYD(2);
            break;
        }
        keyNotDown = false;
    }
    return false;
}


@Override
public boolean keyUp(int keycode) {
    player.stopMove();
    keyNotDown = true;
    return false;
}

As you can see if a person presses a key while another one is pressed, it will not work but when they lift that said key, then it'll stop moving

正如你可以看到一个人在按下另一个按键时按下一个按键,它将无法工作,但是当他们抬起那个按键时,它就会停止移动

EDIT

When the user presses down a key it sends the xd,yD values to the render method and because render keeps being called, it keeps on moving the player with the xD,yD values. The stop move method resets those values to 0 so it stops moving when the key is not being pressed.

当用户按下某个键时,它会将xd,yD值发送到render方法,并且因为render继续被调用,所以它会继续使用xD,yD值移动播放器。停止移动方法将这些值重置为0,以便在未按下该键时停止移动。

2 个解决方案

#1


1  

Well normally I don't post a full solution but its fairly simple what you want to do. The solution offers you a different way to implement your design. Since your speed is constant I figure out don't need to set the delta but only change the direction.

通常情况下,我不发布完整的解决方案,但它很简单,你想做什么。该解决方案为您提供了一种实现设计的不同方式。由于你的速度是恒定的,我认为不需要设置三角洲,只需改变方向。

You can keep track of the key presses and based on what is pressed you can determine the direction to move your character. So for instance, when you press the up arrow, it sets the direction to up, but when you press left I track it but ignore the button. If you release the up arrow, then your character will move left and at no point will it move in more than 1 direction.

您可以跟踪按键,根据按下的内容,您可以确定移动角色的方向。因此,例如,当您按向上箭头时,它会将方向设置为向上,但是当您按向左键时我会跟踪它但忽略按钮。如果你释放向上箭头,那么你的角色将向左移动,在任何时候它都不会向多个方向移动。

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;

public class Move implements ApplicationListener {
    private static final Map<Integer, Direction> MOVE_KEYS = new HashMap<Integer, Direction>(){{
        this.put(Keys.RIGHT, Direction.RIGHT);
        this.put(Keys.LEFT, Direction.LEFT);
        this.put(Keys.UP, Direction.UP);
        this.put(Keys.DOWN, Direction.DOWN);
    }};

    private static enum Direction {
        RIGHT, LEFT, UP, DOWN;
    }

    private static class Player {
        public float x;
        public float y;
        public float speed;
        public Queue<Direction> dirStack = new LinkedList<Direction>();

        public Player(float x, float y, float speed) {
            this.x = x;
            this.y = y;
            this.speed = speed;
        }

        public void update(float delta) {
            if (!dirStack.isEmpty()) {
                switch(dirStack.peek()) {
                case DOWN: 
                    y -= speed;
                    break;
                case LEFT:
                    x -= speed;
                    break;
                case RIGHT:
                    x += speed;
                    break;
                case UP:
                    y += speed;
                    break;
                }
            }
        }

        public void render(ShapeRenderer render) {
            render.begin(ShapeType.FilledRectangle);
            render.setColor(1, 0, 0, 1);
            render.filledRect(x, y, 20, 20);
            render.end();
        }
    }

    private static class MoveController extends InputAdapter {
        private final Player player;

        public MoveController(Player player) {
            this.player = player;
        }

        @Override public boolean keyDown(int keycode) {
            if (MOVE_KEYS.containsKey(keycode)) {
                final Direction dir = MOVE_KEYS.get(keycode);
                Gdx.app.log("D", dir.toString());
                return player.dirStack.add(dir);
            }
            return false;
        }

        @Override public boolean keyUp(int keycode) {
            if (MOVE_KEYS.containsKey(keycode)) {
                final Direction dir = MOVE_KEYS.get(keycode);
                Gdx.app.log("U", dir.toString());
                return player.dirStack.remove(dir);
            }
            return false;
        }
    }

    private Camera cam;
    private ShapeRenderer render;
    private Player player;

    @Override public void create() {
        Gdx.app.log("CREATE", "App Opening");

        this.player = new Player(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, 5);
        Gdx.input.setInputProcessor(new MoveController(player));

        this.cam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        this.render = new ShapeRenderer();

        cam.apply(Gdx.gl10);

        Gdx.gl10.glClearColor(0f, 0f, 0f, 1);
    }

    @Override public void render() {
        Gdx.gl10.glClear(GL20.GL_COLOR_BUFFER_BIT);

        player.update(Gdx.graphics.getDeltaTime());
        player.render(render);
    }

    @Override public void dispose() {
        Gdx.app.log("DISPOSE", "App Closing");
    }

    @Override public void resize(final int width, final int height) {
        Gdx.app.log("RESIZE", width + "x" + height);
        Gdx.gl10.glViewport(0, 0, width, height);
    }

    @Override public void pause() {}

    @Override public void resume() {}
}

#2


2  

Try this following code and let me know, because I haven't test it.

尝试以下代码并告诉我,因为我没有测试它。

private KEY_PRESSE keyPressed = KEY_PRESSE.NONE;

    @Override
    public boolean keyDown(int keycode) {
        switch (keycode) {
        case Keys.RIGHT:
            if (keyPressed.equals(KEY_PRESSE.RIGHT) || keyPressed.equals(KEY_PRESSE.NONE)) {
                playScreen.setXD(2);
                keyPressed = KEY_PRESSE.RIGHT;
                break;
            }
        case Keys.LEFT:
            if (keyPressed.equals(KEY_PRESSE.LEFT) || keyPressed.equals(KEY_PRESSE.NONE)) {
                playScreen.setXD(-2);
                keyPressed = KEY_PRESSE.LEFT;
                break;
            }

        case Keys.DOWN:
            if (keyPressed.equals(KEY_PRESSE.DOWN) || keyPressed.equals(KEY_PRESSE.NONE)) {
                playScreen.setYD(-2);
                keyPressed = KEY_PRESSE.DOWN;
                break;
            }
        case Keys.UP:
            if (keyPressed.equals(KEY_PRESSE.UP) || keyPressed.equals(KEY_PRESSE.NONE)) {
                playScreen.setYD(2);
                keyPressed = KEY_PRESSE.UP;
                break;
            }
        }
        return false;
    }

    @Override
    public boolean keyUp(int keycode) {
        player.stopMove();// I don't know exactly but can you remove this ligne, I
                            // think its useless , when no key is pressed
                            // the player will stop no?
        keyPressed = KEY_PRESSE.NONE;
        return false;
    }

    enum KEY_PRESSE {
        RIGHT, LEFT, DOWN, UP, NONE
    }

#1


1  

Well normally I don't post a full solution but its fairly simple what you want to do. The solution offers you a different way to implement your design. Since your speed is constant I figure out don't need to set the delta but only change the direction.

通常情况下,我不发布完整的解决方案,但它很简单,你想做什么。该解决方案为您提供了一种实现设计的不同方式。由于你的速度是恒定的,我认为不需要设置三角洲,只需改变方向。

You can keep track of the key presses and based on what is pressed you can determine the direction to move your character. So for instance, when you press the up arrow, it sets the direction to up, but when you press left I track it but ignore the button. If you release the up arrow, then your character will move left and at no point will it move in more than 1 direction.

您可以跟踪按键,根据按下的内容,您可以确定移动角色的方向。因此,例如,当您按向上箭头时,它会将方向设置为向上,但是当您按向左键时我会跟踪它但忽略按钮。如果你释放向上箭头,那么你的角色将向左移动,在任何时候它都不会向多个方向移动。

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;

public class Move implements ApplicationListener {
    private static final Map<Integer, Direction> MOVE_KEYS = new HashMap<Integer, Direction>(){{
        this.put(Keys.RIGHT, Direction.RIGHT);
        this.put(Keys.LEFT, Direction.LEFT);
        this.put(Keys.UP, Direction.UP);
        this.put(Keys.DOWN, Direction.DOWN);
    }};

    private static enum Direction {
        RIGHT, LEFT, UP, DOWN;
    }

    private static class Player {
        public float x;
        public float y;
        public float speed;
        public Queue<Direction> dirStack = new LinkedList<Direction>();

        public Player(float x, float y, float speed) {
            this.x = x;
            this.y = y;
            this.speed = speed;
        }

        public void update(float delta) {
            if (!dirStack.isEmpty()) {
                switch(dirStack.peek()) {
                case DOWN: 
                    y -= speed;
                    break;
                case LEFT:
                    x -= speed;
                    break;
                case RIGHT:
                    x += speed;
                    break;
                case UP:
                    y += speed;
                    break;
                }
            }
        }

        public void render(ShapeRenderer render) {
            render.begin(ShapeType.FilledRectangle);
            render.setColor(1, 0, 0, 1);
            render.filledRect(x, y, 20, 20);
            render.end();
        }
    }

    private static class MoveController extends InputAdapter {
        private final Player player;

        public MoveController(Player player) {
            this.player = player;
        }

        @Override public boolean keyDown(int keycode) {
            if (MOVE_KEYS.containsKey(keycode)) {
                final Direction dir = MOVE_KEYS.get(keycode);
                Gdx.app.log("D", dir.toString());
                return player.dirStack.add(dir);
            }
            return false;
        }

        @Override public boolean keyUp(int keycode) {
            if (MOVE_KEYS.containsKey(keycode)) {
                final Direction dir = MOVE_KEYS.get(keycode);
                Gdx.app.log("U", dir.toString());
                return player.dirStack.remove(dir);
            }
            return false;
        }
    }

    private Camera cam;
    private ShapeRenderer render;
    private Player player;

    @Override public void create() {
        Gdx.app.log("CREATE", "App Opening");

        this.player = new Player(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, 5);
        Gdx.input.setInputProcessor(new MoveController(player));

        this.cam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        this.render = new ShapeRenderer();

        cam.apply(Gdx.gl10);

        Gdx.gl10.glClearColor(0f, 0f, 0f, 1);
    }

    @Override public void render() {
        Gdx.gl10.glClear(GL20.GL_COLOR_BUFFER_BIT);

        player.update(Gdx.graphics.getDeltaTime());
        player.render(render);
    }

    @Override public void dispose() {
        Gdx.app.log("DISPOSE", "App Closing");
    }

    @Override public void resize(final int width, final int height) {
        Gdx.app.log("RESIZE", width + "x" + height);
        Gdx.gl10.glViewport(0, 0, width, height);
    }

    @Override public void pause() {}

    @Override public void resume() {}
}

#2


2  

Try this following code and let me know, because I haven't test it.

尝试以下代码并告诉我,因为我没有测试它。

private KEY_PRESSE keyPressed = KEY_PRESSE.NONE;

    @Override
    public boolean keyDown(int keycode) {
        switch (keycode) {
        case Keys.RIGHT:
            if (keyPressed.equals(KEY_PRESSE.RIGHT) || keyPressed.equals(KEY_PRESSE.NONE)) {
                playScreen.setXD(2);
                keyPressed = KEY_PRESSE.RIGHT;
                break;
            }
        case Keys.LEFT:
            if (keyPressed.equals(KEY_PRESSE.LEFT) || keyPressed.equals(KEY_PRESSE.NONE)) {
                playScreen.setXD(-2);
                keyPressed = KEY_PRESSE.LEFT;
                break;
            }

        case Keys.DOWN:
            if (keyPressed.equals(KEY_PRESSE.DOWN) || keyPressed.equals(KEY_PRESSE.NONE)) {
                playScreen.setYD(-2);
                keyPressed = KEY_PRESSE.DOWN;
                break;
            }
        case Keys.UP:
            if (keyPressed.equals(KEY_PRESSE.UP) || keyPressed.equals(KEY_PRESSE.NONE)) {
                playScreen.setYD(2);
                keyPressed = KEY_PRESSE.UP;
                break;
            }
        }
        return false;
    }

    @Override
    public boolean keyUp(int keycode) {
        player.stopMove();// I don't know exactly but can you remove this ligne, I
                            // think its useless , when no key is pressed
                            // the player will stop no?
        keyPressed = KEY_PRESSE.NONE;
        return false;
    }

    enum KEY_PRESSE {
        RIGHT, LEFT, DOWN, UP, NONE
    }