0

我不太擅长编程,这是我第一个使用 Swing 和 AWT 库的程序。我在缓冲我的游戏视图时遇到问题。这是我的 Gra(游戏)类的代码。这个类使用一些属性,如 xPredkoscMax (xMaxVelocity) 或一些坐标(在画布上构建月亮和其他东西),来自 PropertiesGry 类,它正在解析配置文件中的属性。

'''

public class Gra extends Canvas {

private BufferStrategy bufferStrategy = null;
int score = 1000;
boolean hasCrushed;
boolean hasWon;
boolean isPaused = false;
int vy;
int vx;
int x;
int y;
boolean plus300Taken = false;
boolean minus300Taken = false;
public boolean minusShipTaken = false;
public static Timer timerForBonuses;
int time = 10;

Gra(int level) throws IOException {
    PropertiesGry.wczytajPlansze(level);
    x = PropertiesGry.xStartoweStatku[0];
    //bonusesTime();
}


private void shipLocation() {
    y = y + vy;
    if (vy < abs(PropertiesGry.yPredkoscMax)) vy++;
    if (vx > abs(PropertiesGry.yPredkoscMax)) vx = PropertiesGry.yPredkoscMax;
    if (vx < -PropertiesGry.yPredkoscMax) vx = -PropertiesGry.yPredkoscMax;
    x = x + vx;
    if (x > PropertiesGry.SZEROKOSC * 0.97)
        x = (int) (PropertiesGry.SZEROKOSC * 0.97);
    if (y < 0)
        y = 0;
    if (x < 0)
        x = 0;
    if (vx > 1) vx--;
    if (vx < -1) vx++;
}

@Override
public void addNotify() {
    super.addNotify();
    createBufferStrategy(3);
    bufferStrategy = getBufferStrategy();
}


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

    Shape moon = new Polygon(PropertiesGry.xWierzcholkiPlanety, PropertiesGry.yWierzcholkiPlanety, PropertiesGry.xWierzcholkiPlanety.length);
    Shape landing = new Polygon(PropertiesGry.xLadowiska, PropertiesGry.yLadowiska, PropertiesGry.xLadowiska.length);
    Graphics2D graphics2D = (Graphics2D) graphics;
    setBackground(new Color(47, 46, 64));
    graphics.clearRect(0, 0, getWidth(), getHeight());

    AffineTransform scaleTransform = graphics2D.getTransform();
    AffineTransform scaleMatrix = new AffineTransform();
    float xScale = (1f + (getSize().width - PropertiesGry.SZEROKOSC) / (float) PropertiesGry.SZEROKOSC);
    float yScale = (1f + (getSize().height - PropertiesGry.WYSOKOSC) / (float) PropertiesGry.WYSOKOSC);
    scaleMatrix.scale(xScale, yScale);
    graphics2D.setTransform(scaleMatrix);

    Rectangle2D ship = new Rectangle2D.Float(x, y, 25, 25);
    graphics2D.setColor(Color.white);
    graphics2D.fill(ship);

    graphics2D.setColor(Color.green);
    graphics2D.fill(landing);

    graphics2D.setColor(Color.gray);
    graphics2D.fill(moon);

    if (!plus300Taken) {
        Shape bonus = new Polygon(PropertiesGry.xBonusu, PropertiesGry.yBonusu, PropertiesGry.xBonusu.length);
        graphics2D.setColor(Color.yellow);
        graphics2D.fill(bonus);
        plus300(ship, bonus);
    }

    graphics2D.setTransform(scaleTransform);
    isColliding(moon, landing, ship);
}


private void isColliding(Shape moon, Shape landing, Rectangle2D player) {
    if ((moon.intersects(player)) || (landing.intersects(player)) && Math.abs(vy) > PropertiesGry.yPredkoscLadowania) {
        hasCrushed = true;
        hasWon = false;
    }
    if (landing.intersects(player) && Math.abs(vy) <= PropertiesGry.yPredkoscLadowania && Math.abs(vx) <= Math.abs(PropertiesGry.xPredkoscLadowania)) {
        hasWon = true;
        hasCrushed = false;
    }
}


private void minus300(Rectangle2D player, Shape minus) {
    if (minus.intersects(player)) {
        score -= 300;
        minus300Taken = true;
    }
}


private void plus300(Rectangle2D player, Shape bonus) {
    if (bonus.intersects(player)) {
        score += 300;
        //plus300Taken = true;
    }
}

private void deletebonuses() {
    plus300Taken = true;

}


public void isPaused() {
    this.isPaused = true;
}


public void isResumed() {
    this.isPaused = false;
}


public class AnimationTimerTask extends TimerTask {
    int i = 0;

    public void run() {
        if (!isPaused) {
            if (i == 2) {
                shipLocation();
                i = 0;
            }
            i++;
        }
        do {
            do {
                Graphics graphics = bufferStrategy.getDrawGraphics();
                paint(graphics);
                graphics.dispose();
                if (!isPaused) score--;

                //System.out.println(score);
            } while (bufferStrategy.contentsRestored());
                bufferStrategy.show();
            } while (bufferStrategy.contentsLost());
        }
    }
}

'''

这是我创建 Gra 对象、计时器 (licznikAnimacji) 等的课程。

'''

public abstract class Logika {
Timer licznikAnimacji;

public void oknoGry(int numerPlanszy) throws IOException {
JFrame ramka = new JFrame("Gra");
ramka.setSize(PropertiesGry.SZEROKOSC,PropertiesGry.WYSOKOSC);
ramka.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
ramka.setLocationRelativeTo(null);
ramka.setLayout(new BorderLayout());

JPanel panel = new JPanel();
panel.setLayout(new GridLayout(5,1));

panel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0,0,0,0),BorderFactory.createMatteBorder(5,5,5,5,new Color(94, 179, 228))));    
JButton bPauza = new JButton("PAUZA");

panel.add(bPauza);

JLabel lStatki = new JLabel("", SwingConstants.CENTER);
panel.add(lStatki);

JLabel lPaliwo = new JLabel("", SwingConstants.CENTER);
panel.add(lPaliwo);

JLabel lPredkoscX = new JLabel("", SwingConstants.CENTER);
panel.add(lPredkoscX);

JLabel lPredkoscY = new JLabel("", SwingConstants.CENTER);
panel.add(lPredkoscY);

ramka.add(panel,BorderLayout.EAST);

licznikAnimacji = new Timer();
Gra gra = new Gra(numerPlanszy);

licznikAnimacji.scheduleAtFixedRate(gra.new AnimationTimerTask(), 100, 25);
//this.setFocusable(false);
ramka.add(gra);

Klawiatura klawiatura = new Klawiatura(gra);
ramka.addKeyListener(klawiatura);

ramka.requestFocus();
//ramka.setVisible(true);

//setBackground(Color.BLACK);

new Thread(() -> {
    while (!gra.hasCrushed && !gra.hasWon) {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        lPredkoscX.setText("PRĘDKOŚĆ X: " + gra.vx);
        if (Math.abs(gra.vx) > PropertiesGry.xPredkoscLadowania)
            lPredkoscX.setForeground(Color.RED);
            lPredkoscY.setText("PRĘDKOŚĆ Y: " + gra.vy);
        if (Math.abs(gra.vy) > PropertiesGry.yPredkoscLadowania)
            lPredkoscY.setForeground(Color.RED);
    }
    try {
        resetujLicznikAnimacji();
        if (gra.czyWyladowano) {

        }
        if (gra.czyRozbitoSie && gra.liczbaStatkow > 1) {

        }
        if (gra.czyRozbitoSie && gra.liczbaStatkow <= 1) {

        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    }).start();
}

public void resetujLicznikAnimacji() {
    licznikAnimacji.cancel();
    licznikAnimacji.purge();
}

}

'''

问题是当我运行这个程序时,会出现这个异常:

Exception in thread "Timer-0" java.lang.NullPointerException
at Gra$AnimationTimerTask.run(Gra.java:601)
at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
at java.base/java.util.TimerThread.run(Timer.java:506)

第 601 行是

 Graphics graphics = bufferStrategy.getDrawGraphics();

我必须做什么?看起来 addNotify 方法没有被调用。我不知道为什么。我应该在哪里传递变量 bufferstrategy 的值以避免此异常并显示我的船的动画?

谢谢您的帮助。抱歉,如果有类似的问题,但我是编程初学者,我不知道我需要做什么。

4

1 回答 1

0

作为方法createBufferStrategygetBufferStrategy在其中定义,Canvas您可以向您的Gra类添加一个方法并从您想要的任何位置(Gra构造函数或任务)调用它:

private BufferStrategy getInitializedBufferStrategy() {
    BufferStrategy strategy = getBufferStrategy();
    if (null == strategy) {
        createBufferStrategy(3);
        strategy = getBufferStrategy();
    }
    return strategy;
}

然后在任务代码中替换对实例的调用:

Graphics graphics = getInitializedBufferStrategy().getDrawGraphics();
于 2020-04-25T22:06:48.863 回答