Игра змея - не могу управлять змея - PullRequest
0 голосов
/ 15 ноября 2018

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

Я пишу простую игру «Змейка», и я заставил змею двигаться автоматически. Он автоматически перемещается вправо от окна при выполнении кода, как и предполагалось. Однако я не могу управлять своей змеей так, как хочу, она совершенно не меняет своего направления.


Чтобы избежать путаницы, player является экземпляром класса Snake.


Чтобы объяснить движение змеи:

Объект Snake имеет свойство coordinates, которое представляет собой ArrayList, содержащий объекты SnakePart. Каждый объект SnakePart имеет свойство x и y. Используя этот ArrayList, змея движется, рисуя маленькие прямоугольники на холсте, используя свойства x и y на оси Y и X холста.

Объект Snake также имеет свойство dx и dy, которое добавляется (или вычитается - в зависимости от направления змеи) к свойству x и y SnakePart объект для перемещения змеи в направлении.


Чтобы обновить ArrayList в Snake.java:

public void move() {
  SnakePart head = new SnakePart(this.coordinates.get(0).x + this.dx, this.coordinates.get(0).y + this.dy);

  this.coordinates.add(0, head);
  this.coordinates.remove(this.coordinates.size() - 1);
}

Чтобы нарисовать змею на холсте в Board.java (частично, остальная часть метода пока не нужна):

@Override
public void paintComponent(Graphics g) {
  this.player.coordinates.forEach(snakePart -> {
    g.setColor(Color.BLUE);
    g.fillRect(snakePart.x, snakePart.y, 10, 10);
  });
}

Чтобы управлять змеей, я хочу использовать клавиши со стрелками. В зависимости от того, какая клавиша со стрелкой нажата, координаты / свойства змеи x и y изменяются (Board.java):

@Override
public void keyPressed(KeyEvent event) {
  int keyCode = event.getKeyCode();

  if (keyCode == 37) {
    this.player.dx = -10;
    this.player.dy = 0;
  } else if (keyCode == 38) {
    this.player.dx = 0;
    this.player.dy = -10;
  } else if (keyCode == 39) {
    this.player.dx = 10;
    this.player.dy = 0;
  } else if (keyCode == 40) {
    this.player.dx = 0;
    this.player.dy = 10;
  }
}

Весь код:

Snake.java

package com.codef0x.snake;
import java.util.ArrayList;

public class Snake {
  ArrayList < SnakePart > coordinates;
  int dx = 10;
  int dy = 0;

  public Snake(ArrayList < SnakePart > coords) {
    this.coordinates = coords;
  }

  public void move() {
    SnakePart head = new SnakePart(this.coordinates.get(0).x + this.dx, this.coordinates.get(0).y + this.dy);

    this.coordinates.add(0, head);
    this.coordinates.remove(this.coordinates.size() - 1);
  }

  public void grow() {
    SnakePart newPart = new SnakePart(0, 0);
    newPart.x = this.coordinates.get(this.coordinates.size() - 1).x - 10;
    newPart.y = this.coordinates.get(this.coordinates.size() - 1).y;

    this.coordinates.add(this.coordinates.size() - 1, newPart);
  }
}

Board.java (показаны только соответствующие части, в противном случае было бы слишком много кода)

package com.codef0x.snake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;


public class Board extends JPanel implements KeyListener {
  Snake player;
  ArrayList<SnakePart> snakeCoordinates;

  public Board() {

    this.snakeCoordinates = new ArrayList<>();

    snakeCoordinates.add(new SnakePart(150, 150));
    snakeCoordinates.add(new SnakePart(140, 150));
    snakeCoordinates.add(new SnakePart(130, 150));
    snakeCoordinates.add(new SnakePart(120, 150));

    this.player = new Snake(snakeCoordinates);

    this.food = new Food();
  }

  @Override
  public void paintComponent(Graphics g) {
    clear(g);

    this.player.coordinates.forEach(snakePart - > {
      g.setColor(Color.BLUE);
      g.fillRect(snakePart.x, snakePart.y, 10, 10);
    });
  }

  public void clear(Graphics g) {
    g.clearRect(0, 0, getHeight(), getWidth());
  }

  @Override
  public void update(Graphics g) {
    paintComponent(g);
  }

  @Override
  public void keyPressed(KeyEvent event) {
    int keyCode = event.getKeyCode();

    if (keyCode == 37) {
      this.player.dx = -10;
      this.player.dy = 0;
    } else if (keyCode == 38) {
      this.player.dx = 0;
      this.player.dy = -10;
    } else if (keyCode == 39) {
      this.player.dx = 10;
      this.player.dy = 0;
    } else if (keyCode == 40) {
      this.player.dx = 0;
      this.player.dy = 10;
    }
  }

  @Override
  public void keyTyped(KeyEvent event) {
    return;
  }

  @Override
  public void keyReleased(KeyEvent event) {
    return;
  }

  public void run(Board board) {
    Timer game = new Timer();
    game.schedule(new TimerTask() {
      boolean initiallySpawned = false;
      @Override
      public void run() {
        Graphics g = board.getGraphics();

        if (hitSomething()) { // removed method hitSomething, not relevant
          game.cancel();
          return;
        }

        player.move();
        update(g);
      }
    }, 0, 500);
  }
}

SnakePart.java

package com.codef0x.snake;

public class SnakePart {
  int x;
  int y;

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

Что я делаю не так и что мне нужно изменить, чтобы правильно управлять змеей?


Если вы все еще хотите / хотите увидеть все файлы целиком, вы можете посмотреть их здесь:

Snake.java
Board.java
SnakePart.java
Food.java <- Не связано, но может предотвратить путаницу с <code>Food объектом

1 Ответ

0 голосов
/ 15 ноября 2018

Проблема в основном.Вы создаете board до хоста своего игрового статуса и создаете другой статус для прослушивания клавиатуры.

public static void main(String[] args) {

    JFrame frame = new JFrame("Snake");
    frame.setDefaultCloseOperation(3);

    Board board = new Board();
    frame.add(board);
    frame.setSize(500, 500);
    frame.addKeyListener(new Board());
    frame.setVisible(true);

    board.run(board);
}

оно должно быть:

public static void main(String[] args) {

    JFrame frame = new JFrame("Snake");
    frame.setDefaultCloseOperation(3);

    Board board = new Board();
    frame.add(board);
    frame.setSize(500, 500);
    frame.addKeyListener(board);
    frame.setVisible(true);


    board.run(board);
}

Также board.run(board) не имеет большого смысла, в рамках метода run плату можно поменять на this (и так опущено) ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...