如果用户足够快,Java Snake非法移动

时间:2016-01-05 03:06:47

标签: java

在Snake中向上移动意味着你只能向左和向右转。如果你向左移动,你只能向上和向下翻转等。目前我有一个问题,如果我当前正在向左移动(例如),然后我按下向上或向下,然后非常快速按下右键,蛇将保持在同一水平并自行撞击(虽然我还没有添加碰撞检测)。我觉得我需要一些缓冲区(比如,如果我按下UP它就不会接受任何输入,直到运动完成,然后我可以按下RIGHT等等。)我几乎是一个新手所以我感谢任何帮助并为我的愚蠢道歉: - )

发生了{p> This

My Snake是SnakeParts的一个ArrayList(具有变量x,y和size的对象),并且通过在前面添加一个新的SnakePart然后在后面删除一个来完成移动。

以下是相关代码(我不认为我应该调用Thread.sleep(),但当时我还不知道其他任何方式):

Board.java:

public void keyPressed(KeyEvent e) {
    int keyPressed = e.getKeyCode();
    switch (keyPressed) {
        case KeyEvent.VK_UP:
            controller.setDirection(1); // UP
            break;
        case KeyEvent.VK_DOWN:
            controller.setDirection(2); // DOWN
            break;
        case KeyEvent.VK_LEFT:
            controller.setDirection(3); // LEFT
            break;
        case KeyEvent.VK_RIGHT:
            controller.setDirection(4); // RIGHT
            break;
    }
}

Controller.java:

public void gameLoop() {
    while (!isWon) {
        moveSnake();
        checkCollision();
        try {
            Thread.sleep(100);
        } catch (InterruptedException ie) {
        }
        board.repaint();
    }
}

public void setDirection(int direction) {
    switch (direction) {
        case 1: // UP
            if (this.direction != 2) // If not going DOWN.
                this.direction = direction;
            break;
        case 2: // DOWN
            if (this.direction != 1) // If not going UP.
                this.direction = direction;
            break;
        case 3: // LEFT
            if (this.direction != 4) // If not going RIGHT.
                this.direction = direction;
            break;
        case 4: // RIGHT
            if (this.direction != 3) // If not going LEFT.
                this.direction = direction;
            break;
    }
}

private void moveSnake() {
    switch (direction) { // Add new part in front.
        case 1:
            snake.add(0, new SnakePart(snake.get(0).getX(), snake.get(0).getY() - (Board.SNAKE_SIZE + 1), Board.SNAKE_SIZE));
            break;
        case 2:
            snake.add(0, new SnakePart(snake.get(0).getX(), snake.get(0).getY() + (Board.SNAKE_SIZE + 1), Board.SNAKE_SIZE));
            break;
        case 3:
            snake.add(0, new SnakePart(snake.get(0).getX() - (Board.SNAKE_SIZE + 1), snake.get(0).getY(), Board.SNAKE_SIZE));
            break;
        case 4:
            snake.add(0, new SnakePart(snake.get(0).getX() + (Board.SNAKE_SIZE + 1), snake.get(0).getY(), Board.SNAKE_SIZE));
            break;
    }
    snake.remove(snake.size() - 1); // Remove last part.
}

SnakePart.java:

public SnakePart(int x, int y, int size) {
    this.x = x;
    this.y = y;
    this.size = size;
}

4 个答案:

答案 0 :(得分:4)

向控制器添加一个名为oldDirection的变量。并将其设置为0。

在moveSnake()中添加一行

 this.oldDirction = this.direction
在setDirection()中

将您的检查更改为

  if (this.oldDirection != 3) // If not going LEFT.

也尽量不使用幻数,而是使用枚举

public enum Direction {
    Up, Down, Left, Right
}

答案 1 :(得分:1)

您需要一个消息队列。标志不起作用,因为这意味着将忽略新的按键。这是代码:

                public Queue<Integer> directions;

                public void gameLoop() {
                    directions=new LinkedList<Integer>();
                    while (!isWon) {
                           updateInput();
                        moveSnake();
                        checkCollision();
                        try {

                            Thread.sleep(100);
                        } catch (InterruptedException ie) {
                        }
                        board.repaint();
                    }
                }

                public void setDirection(int dir) {
                    directions.add(dir);
                }

                public void updateInput() {
                    if(directions.isEmpty())
                       return;
                    switch (directions.remove()) {
                        case 1: // UP
                            if (this.direction != 2) // If not going DOWN.
                                this.direction = direction;
                            break;
                        case 2: // DOWN
                            if (this.direction != 1) // If not going UP.
                                this.direction = direction;
                            break;
                        case 3: // LEFT
                            if (this.direction != 4) // If not going RIGHT.
                                this.direction = direction;
                            break;
                        case 4: // RIGHT
                            if (this.direction != 3) // If not going LEFT.
                                this.direction = direction;
                            break;
                    }
                }

                private void moveSnake() {
                    switch (direction) { // Add new part in front.
                        case 1:
                            snake.add(0, new SnakePart(snake.get(0).getX(), snake.get(0).getY() - (Board.SNAKE_SIZE + 1), Board.SNAKE_SIZE));
                            break;
                        case 2:
                            snake.add(0, new SnakePart(snake.get(0).getX(), snake.get(0).getY() + (Board.SNAKE_SIZE + 1), Board.SNAKE_SIZE));
                            break;
                        case 3:
                            snake.add(0, new SnakePart(snake.get(0).getX() - (Board.SNAKE_SIZE + 1), snake.get(0).getY(), Board.SNAKE_SIZE));
                            break;
                        case 4:
                            snake.add(0, new SnakePart(snake.get(0).getX() + (Board.SNAKE_SIZE + 1), snake.get(0).getY(), Board.SNAKE_SIZE));
                            break;
                    }
                    snake.remove(snake.size() - 1); // Remove last part.
                }

答案 2 :(得分:0)

创建一个整数:

public int keyDelay = 0;

每按一次键,将该整数设置为大于零的值:

keyDelay = 8;

你必须尝试一下才能找到合适的价值,如果它太低,这个修补程序就无法工作,如果它太高你就不能在你改变方向后的一段时间内再次改变方向。

如果值超过零,则每个tick(游戏循环周期)都会递减值:

if (keyDelay > 0)
    keyDelay--;

现在进行最后一步,确保只有在keyDelay为零时才能更改方向。一种简单的方法是将整个setDirection方法包装在if语句中:

if (keyDelay == 0) {
    // Set direction
}

答案 3 :(得分:0)

有一个标记bool willMoveSoon = false;

setDirection()包含willMoveSoon = true;

keyPressed()中将您的整个功能包裹在if (!willMoveSoon) { ... }中 - 这会在您等待移动蛇时忽略按键

moveSnake()包含willMoveSoon = false;