Как переместить весло понг с java .Swing? - PullRequest
1 голос
/ 01 марта 2020

Я пытаюсь сделать понг с Java и Swing. Однако у меня есть две проблемы: первая - прямоугольник на экране вообще не перемещается, и вторая - возникает исключение NullPointerException, хотя код все еще выполняется. Вот мои два файла:


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Pong extends JFrame implements KeyListener {

    private static final long serialVersionUID = -5782301423436L;

    JPanel panel;

    Paddle paddle1;

    public Pong() {
        super("Pong");

        panel = new JPanel();
        this.add(panel);

        super.setPreferredSize(new Dimension(800, 600));
        super.setVisible(true);
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        super.pack();
        addKeyListener(this);

        paddle1 = new Paddle(100, 300);
    }

    public static void main(String[] args) {
        @SuppressWarnings("unused")
        Pong game = new Pong();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 800, 600);

        g.setColor(Color.BLACK);
        this.paddle1.draw(g);
    }

    public void keyTyped(KeyEvent e) {}

    public void keyReleased(KeyEvent e) {}

    // I've tested this part and the w and s key presses
    // are still detected, but nothing happens. Why not?
    public void keyPressed(KeyEvent keyEvent) {
        int key = keyEvent.getKeyCode();
        if (key == KeyEvent.VK_ESCAPE) {
            this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
        } else if (key == KeyEvent.VK_W) {
            this.paddle1.up();
        } else if (key == KeyEvent.VK_S) {
            this.paddle1.down();
        }
    }

}

import java.awt.Graphics;

public class Paddle {

    // Position of the paddle's center
    int x;
    int y;

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

    public void draw(Graphics g) {
        g.fillRect(this.x - 10, this.y - 40, 20, 80);
    }

    // Up is negative because Java coordinates

    public void up() {
        this.y -= 30;
    }

    public void down() {
        this.y += 30;
    }

}

Я протестировал метод keyPressed в файле Pong, и когда нажимаются клавиши w и s, он фактически обнаруживает их (это выведет строку на консоль). Я очень новичок в графике в Java, и это первое, что я попробовал создать, не скопировав его из учебника на YouTube. Я искал свой код около часа и не могу найти, где ошибка может быть. Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 02 марта 2020

Я проверил код и могу помочь вам устранить ошибки.

Во-первых, здесь вы показали, что Paddle использует метод paint () JFrame Pong . Вы обнаруживаете клавиши 'W' и 'S' и в соответствии с ключом, который вы написали код, чтобы обновить координату y в классе Paddle.

Но проблема в том, что вы Вы просто обновляете координату y. Вы больше не рисуете весло с новыми координатами. Итак, после установки нового значения y, вы должны снова нарисовать весло. Итак, в методе keyPressed () после

this.paddle1.up();

и

this.paddle1.down();

вы должны снова вызвать метод draw () класса Paddle, который будет рисовать Paddle в измененном location.

В этом методе draw () вы передаете объект Graphics, который является графической конфигурацией текущего JFrame Pong. Таким образом, это можно получить с помощью метода getGraphics () JFrame.

Итак, строка, которую нужно добавить после up () или down (), будет

this.paddle1.draw(getGraphics());

Поскольку мы имеем дело с графикой это также правильно перекрасить JFrame, как только вы измените что-то в его графике. Если вы добавили только вышеприведенную строку после метода up () и down () в методе keyPressed (), вы увидите, что манипулятор не движется. Его предыдущий рисунок будет таким, какой он есть, и, согласно нажатой клавише, новый Paddle будет нарисован вверх или вниз. Таким образом, вместо подвижного весла вы увидите вертикальную черту. Это происходит потому, что мы модифицируем графику, но не рисуем JFrame снова. Таким образом, он просто добавит новый прямоугольник в JFrame, сохранив прежний. Итак, чтобы избавиться от этого, вы должны использовать метод repaint () JFrame, чтобы он вызывал aws только самый последний экран.

Итак, полный метод keyPressed () будет выглядеть так:

@Override
public void keyPressed(KeyEvent keyEvent) {
    int key = keyEvent.getKeyCode();
    if (key == KeyEvent.VK_ESCAPE) {
        this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
    } else if (key == KeyEvent.VK_W) {
        this.paddle1.up();
        this.paddle1.draw(getGraphics());
        repaint();
    } else if (key == KeyEvent.VK_S) {
        this.paddle1.down();
        this.paddle1.draw(getGraphics());
        repaint();
    }
}

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

Теперь об исключении NullPointerException. Я пытался запустить этот код, но я не смог воспроизвести такое исключение. Итак, после попытки предложенного кода, если вы столкнулись с NPE, вы можете обновить трассировку стека, чтобы решить ее.

Я прочитал комментарии, и они очень полезны. Проверьте ссылку, которая объясняет лучший способ прослушивания ключевых событий.

Спасибо.

...