【问题标题】:Snake Game - KeyListener does not work贪吃蛇游戏 - KeyListener 不起作用
【发布时间】:2018-05-13 07:45:17
【问题描述】:

大家好,我的代码有问题。请忽略其他没有意义的事情,我还有很多工作要做......

正如您在下面看到的,我所做的是更改名为 checkDirection 的变量,然后检查相同的变量。

Check Direction 是一个私有变量...idk 如果这改变了任何东西

    @Override
    public void paint(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.RED);
        g.fillRect(appleXPosition, appleYPosition, 10, 10);
        g.setColor(Color.GREEN);
        g.fillRect(snakeXPosition, snakeYPosition, 10, 10);


        if (checkDirection == 0) {
            snakeXPosition = right(snakeXPosition);
        } else if(checkDirection == 1) {
            snakeXPosition = left(snakeXPosition);
        } else if (checkDirection == 2) {
            snakeYPosition = up(snakeYPosition);
        } else {
            snakeYPosition = down(snakeYPosition);
        }
    }

  @Override
    public void keyPressed(KeyEvent ke) {
        int code = ke.getKeyCode();
        switch (code) {
            case KeyEvent.VK_RIGHT:
                checkDirection = 0;
                break;
            case KeyEvent.VK_LEFT:
                checkDirection = 1;
                break;
            case KeyEvent.VK_UP:
                checkDirection = 2;
                break;
            case KeyEvent.VK_DOWN:
                checkDirection = 3;
                break;
            default:
                break;
        }
    }

【问题讨论】:

  • “请忽略任何其他没有意义的事情”请努力删除没有意义的内容并发布minimal reproducible example。还要添加您为调试问题所做的工作。
  • public void paint(Graphics g) { super.paintComponent(g); ... } 是一个真正的问题
  • 你不应该在渲染阶段做出逻辑选择,这些应该在“更新”阶段处理,渲染应该渲染当前状态,没有别的 - 为什么?因为这也是它的职责所在,所以在 Swing 中,油漆传球可能因多种原因而被触发,其中许多原因是您无法直接控制的。您的代码应该有一个“主循环”,它的职责是更新游戏模型的状态并安排渲染通道,然后在更新之间等待规定的时间 - 我建议使用 Swing Timer 作为简单的起点
  • 我也鼓励使用KeyListenerkey bindings API,它将解决它的不可靠性问题
  • 谢谢@MadProgrammer!我真的不明白......所以我把所有打算更新的代码放在不同的方法中。但是我又叫油漆了吗?还是我只调用重绘?

标签: java swing keylistener


【解决方案1】:

你在这个方法中更新了变量checkDirection

public void keyPressed(KeyEvent ke) {

但是您的paint() 没有安排在之后执行,因此它不知道新的checkDirection 更改。

要在设置checkDirection() 后安排重绘,请致电repain();

 case KeyEvent.VK_RIGHT:
            checkDirection = 0;
            repaint(); // Add this
            break; 

【讨论】:

  • 虽然这可能是解决方案,但不可能知道,因为 OP 可能有一个“主循环”正在调度重绘
【解决方案2】:

让我们开始吧……

@Override
public void paint(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.RED);
    g.fillRect(appleXPosition, appleYPosition, 10, 10);
    g.setColor(Color.GREEN);
    g.fillRect(snakeXPosition, snakeYPosition, 10, 10);


    if (checkDirection == 0) {
        snakeXPosition = right(snakeXPosition);
    } else if(checkDirection == 1) {
        snakeXPosition = left(snakeXPosition);
    } else if (checkDirection == 2) {
        snakeYPosition = up(snakeYPosition);
    } else {
        snakeYPosition = down(snakeYPosition);
    }
}

您正在覆盖paint,但调用super.paintComponentpaint 本身做了很多重要的工作,调用paintComponent 只是其中之一。

相反,您应该直接覆盖 paintComponent(并将其称为 super

请参阅Performing Custom PaintingPainting in AWT and Swing 了解更多详情

绘画不应该是做出逻辑决策,而应该只是绘画模型的当前状态。相反,这些决定应该作为“主循环”的一部分执行的“更新”传递的一部分做出

“主循环”将检查输入的状态,决定如何更新状态并安排渲染过程。

一个简单的起点可能是使用Swing Timer

我还建议使用key bindings API 而不是KeyListener,它将解决与KeyListener 相关的不可靠性问题

【讨论】:

    【解决方案3】:

    我修好了伙计们!只需要向 JPanel 请求焦点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多