Игрок (Снейк) не двигается с постоянством, останавливается - PullRequest
0 голосов
/ 17 апреля 2020

Я работаю над игрой змеи и только что завершил реализацию KeyEvent и метода перемещения для моей змеи, который сначала начинается с одного сегмента. Змея отвечает на первую пару клавиш, но затем перестает отвечать и продолжает двигаться в соответствии с последним вводом ключа (на что она фактически отреагировала). Вот код, относящийся к вопросу:

public class Snake implements Runnable, KeyListener {

private boolean running=false;
private Thread thread;

private BufferStrategy bs;
private Graphics g;

private int interval;

private ArrayList<Point> coords;

private LinkedList<Point> snake;
private boolean moveLeft;
private boolean moveRight;
private boolean moveUp;
private boolean moveDown;
private Point apple;

private void init() {

    display = new Display(title, width, height);
    display.getFrame().addKeyListener(this);

    initInterval(30);
    initPoints();
    initSnake();
    apple();
}

private void update() {

    moveSnake();

}

private void render() {
    bs = display.getCanvas().getBufferStrategy();
    if (bs==null) {
        display.getCanvas().createBufferStrategy(3);
        return;
    }
    g = bs.getDrawGraphics();
    //Clear Screen before drawing
    g.clearRect(0, 0, width, height);
    //Draw here

    //Background
    g.setColor(Color.BLUE);
    g.fillRect(0, 0, width, height);

    drawGrid();

    try {
        thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    drawSnake();
    drawApple();

    //End Drawing
    bs.show();  
    g.dispose();
}

private void initPoints() {

    coords = new ArrayList<Point>();

    for (int y=interval/2; y<=height-interval; y+=interval) {
        for (int x=interval/2; x<=width; x+=interval) {
            coords.add(new Point(x, y));
        }
    }
} 

private void initSnake() {

    snake = new LinkedList<Point>();
    int randPos = (int)( Math.random() * coords.size()-1 );
    snake.add( new Point( (int)coords.get(randPos).getX(), (int)coords.get(randPos).getY() ) );

}

private void drawSnake() {

    g.setColor(Color.YELLOW);

    for (int i = 0; i<snake.size(); i++) {
        fillRect((int)snake.get(i).getX(), (int)snake.get(i).getY(), interval, interval);
    }

}

private void moveSnake() {

    int headX = (int)snake.get(0).getX();
    int headY = (int)snake.get(0).getY();

    if (moveUp) {

        if (snake.size()==1) 
            snake.get(0).move(headX, headY - interval);


        else if (snake.size()>1) {              
            snake.addFirst( new Point(headX, headY - interval) );
        }

    }

    else if (moveLeft) {

        if (snake.size()==1) 
            snake.get(0).move(headX-interval, headY);

        else if (snake.size()>1) {
            snake.addFirst( new Point(headX-interval, headY) );
        }

    }

    else if (moveDown) {

        if (snake.size()==1) 
            snake.get(0).move(headX, headY + interval);

        else if (snake.size()>1) {
            snake.addFirst( new Point(headX, headY+interval) );
        }

    }

    else if (moveRight) {

        if (snake.size()==1) 
            snake.get(0).move(headX+interval, headY);

        else if (snake.size()>1) {
            snake.addFirst( new Point(headX+interval, headY) );
        }

    }

}

    public void keyPressed(KeyEvent e) {

        switch (e.getKeyCode()) {

        case KeyEvent.VK_W :
            moveUp = true;
            break;
        case KeyEvent.VK_UP :
            moveUp = true;
            break;

        case KeyEvent.VK_A :
            moveLeft = true;
            break;
        case KeyEvent.VK_LEFT :
            moveLeft = true;
            break;

        case KeyEvent.VK_S :
            moveDown = true;
            break;
        case KeyEvent.VK_DOWN :
            moveDown = true;
            break;

        case KeyEvent.VK_D :
            moveRight = true;
            break;
        case KeyEvent.VK_RIGHT :
            moveRight = true;
            break;
        default : break;
    }

    }

public void run() {

    init();

    while(running) {

            update();
            render();

    }

    stop();
}

* Был удален ненужный код, включая реализацию KeyListener

Я думаю, что проблема может быть в moveSnake ( ) или keyPressed (), хотя я не уверен.

1 Ответ

1 голос
/ 17 апреля 2020

Способ сохранения направлений змеи позволяет нескольким направлениям иметь истинное значение и позволяет змее указывать в нескольких направлениях одновременно.

Когда программа устанавливает направление в Ключевое событие, оно не устанавливает другие направления в значение false, поэтому после нескольких поворотов змея направляет несколько путей одновременно. Установив для каждого поворота другие направления в false, это можно исправить одним из способов.

В качестве стратегии проектирования представление вашего направления в виде строковой константы может устранить проблемы со змеями, указывающими несколько направлений одновременно, поскольку вы являетесь указателем. всегда будет в точности одно из 4 возможных направлений:

String UP = "up"
String LEFT = "left"
String RIGHT = "right"
String DOWN = "down"

String direction = RIGHT

// for key event processing, set the direction to your constants
case KeyEvent.VK_W :
        direction = UP;
        break;
...

if (direction.equals(UP)) {
     //code for moving up
}

Если вы хотите немного покопаться, возитесь с Java Enums и вы получите более изощренный способ сделать то же самое

...