【问题标题】:Snake Game -- Can't steer snake蛇游戏——不能驾驭蛇
【发布时间】:2018-11-15 14:50:34
【问题描述】:

帖子底部的实际问题!
首先,我想解释一下我的问题。

我正在编写一个基本的 Snake 游戏,我让蛇自动移动。当您执行代码时,它会自动移动到窗口的右侧,就像预期的那样。但是,我无法按照我想要的方式引导我的蛇,它根本不会改变它的方向。


为避免混淆,player 是类 Snake 的一个实例。


解释蛇的运动:

Snake 对象有一个 coordinates 属性,它是一个包含 SnakePart 对象的 ArrayList。每个SnakePart 对象都具有xy 属性。使用这个 ArrayList,蛇通过在画布的 y 轴和 x 轴上使用 xy 属性在画布上绘制小矩形来移动。

Snake 对象还有一个dx 和一个dy 属性,它们被添加到x 和@987654341 的xy 属性中(取决于蛇的方向) @object 使蛇朝一个方向移动。


更新Snake.java中的ArrayList:

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);
  });
}

要引导蛇,我想使用箭头键。根据按下的箭头键,蛇的xy 坐标/属性会被修改(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 Food 对象

【问题讨论】:

  • 您看到了什么行为?蛇有反应吗?您是否检查过以确保 keyPressed 事件像您认为的那样触发?我会将 System.out.println() 语句放入您的移动代码中,并在您按下按键时验证它是否流经您期望的代码路径。
  • 我会做按键输入或释放而不是按键,但是您是否尝试过仅打印或以其他方式调试增长方法以查看为什么 dx 总是“向右”移动?跨度>
  • @Jazzepi 我使用System.out.println(this.player.dx + " " + this.player.dx) 进行调试,但仅在keyPressed 方法中一切看起来都很好。现在我又做了一次,但这次我还在Snake.java 中的move() 方法中添加了一个System.out.println(this.dx + " " + this.dy)。在keyPressed 中,输出看起来像预期的那样(按下键后dx 从 10 变为 0,dy 从 0 变为 -10)。但在move() dx 仍然是 10 而dy 仍然是 0...
  • @cricket_007 我确定grow() 方法与问题无关,因为dx 应该一直向右移动,直到通过箭头键改变什么不'不行。
  • 不要使用 KeyListener。见Motion Using the Keyboard

标签: java swing awt


【解决方案1】:

问题是主要的。 您创建一个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(所以省略)...

【讨论】:

  • @minus 不错!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-11
  • 1970-01-01
  • 1970-01-01
  • 2015-06-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多