我不太擅长编程,这是我第一个使用 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 的值以避免此异常并显示我的船的动画?
谢谢您的帮助。抱歉,如果有类似的问题,但我是编程初学者,我不知道我需要做什么。