我对这门语言有点陌生,但明年我将攻读学位,其中包括一篇Java论文,所以我正在复习这门语言,这样我明年就不会完全没用了。
我试图模仿'Flappybird‘这个游戏(这是我想到的第一个需要Java图形的东西)。
当我运行我的代码时,内存迅速增加,超过了4gb和15%的CPU使用率。请有人解释一下是什么原因造成了这个内存泄漏/问题。
请随时为我的绘画/图形留下推荐的替代方法。我为目前的代码如此混乱而道歉。
代码:
import java.awt.Component;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class Animation {
private Image imgBackgroundBottom, imgBackgroundTop;
private int intFrameHeight;
private int intFrameWidth;
public static void main(String[] args) throws IOException {
new Animation();
}
public Animation() throws IOException{
System.out.println("Program Iniatiated");
JFrame frameAnimation = new JFrame("Animation");
frameAnimation.setResizable(false);
frameAnimation.setSize(310, 650);
frameAnimation.setVisible(true);
int Level = 10;
frameAnimation.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
for (int i = 0; i < frameAnimation.getWidth() + 1; i++) {
if (i == frameAnimation.getWidth()) {
//Level--;
i = 0;
}
frameAnimation.add(new AnimationPane(i));
try {
Thread.sleep(Level);
} catch (InterruptedException e) {
e.printStackTrace();
}
frameAnimation.revalidate();
}
}
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.concurrent.ThreadLocalRandom;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class AnimationPane extends JPanel {
private BufferedImage imgBackgroundBottom, imgBackgroundTop, imgPipeTop, imgPipeBottom;
private int XPos = 40, YPos = 40;
private int BackgroundTopWidth, BackgroundTopHeight;
private int BackgroundBottomWidth, BackgroundBottomHeight;
private int i = 0;
public static int yPipe1, yPipe2, yPipe3, yPipe4;
public static int xPipe1 = -50, xPipe2 = -50, xPipe3 = -50, xPipe4 = -50;
public static int runAgain = 1, selectPipe = 0;
public AnimationPane(int xValue) {
try {
if (imgBackgroundBottom = null ) {
imgBackgroundBottom = ImageIO.read(new File("resources/BackgroundBottom.png"));
imgBackgroundTop = ImageIO.read(new File("resources/BackgroundTop.png"));
imgPipeTop = ImageIO.read(new File("resources/PipeTop.png"));
imgPipeBottom = ImageIO.read(new File("resources/PipeBottom.png"));
BackgroundTopWidth = imgBackgroundTop.getWidth(null);
BackgroundBottomWidth = imgBackgroundBottom.getWidth(null);
BackgroundTopHeight = imgBackgroundTop.getHeight(null);
BackgroundBottomHeight = imgBackgroundBottom.getHeight(null);
this.setDoubleBuffered(true);
i = xValue;
repaint();
} catch (IOException e) {
e.printStackTrace();
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(imgBackgroundTop, 0, 0, getWidth(), BackgroundTopHeight * 2, this);
//Level Difficult can be adjusted by adjusting thread.sleep count AND adjusting max.variance in randomisation.
if (runAgain % 170 == 0) {
selectPipe++;
if (selectPipe % 4 == 0) {
yPipe4 = ThreadLocalRandom.current().nextInt(50, 312 + 1);
xPipe4 = 310;
} else if (selectPipe % 3 == 0){
yPipe3 = ThreadLocalRandom.current().nextInt(50, 312 + 1);
xPipe3 = 310;
} else if (selectPipe % 2 == 0) {
yPipe2 = ThreadLocalRandom.current().nextInt(50, 312 + 1);
xPipe2 = 310;
} else {
yPipe1 = ThreadLocalRandom.current().nextInt(50, 312 + 1);
xPipe1 = 310;
}
}
xPipe1--;
xPipe2--;
xPipe3--;
xPipe4--;
runAgain++;
if (xPipe1 < 310 && xPipe1 > -50) {
g.drawImage(imgPipeTop, xPipe1, yPipe1 - 400, 50, 400, this);
g.drawImage(imgPipeBottom, xPipe1, yPipe1 + 150, 50, 400, this);
}
if (xPipe2 < 310 && xPipe2 > -50) {
g.drawImage(imgPipeTop, xPipe2, yPipe2 - 400, 50, 400, this);
g.drawImage(imgPipeBottom, xPipe2, yPipe2 + 150, 50, 400, this);
}
if (xPipe3 < 310 && xPipe3 > -50) {
g.drawImage(imgPipeTop, xPipe3, yPipe3 - 400, 50, 400, this);
g.drawImage(imgPipeBottom, xPipe3, yPipe3 + 150, 50, 400, this);
}
if (xPipe4 < 310 && xPipe4 > -50) {
g.drawImage(imgPipeTop, xPipe4, yPipe4 - 400, 50, 400, this);
g.drawImage(imgPipeBottom, xPipe4, yPipe4 + 150, 50, 400, this);
}
g.drawImage(imgBackgroundBottom, -i, BackgroundTopHeight * 2, getWidth() * 2, BackgroundBottomHeight * 2, this);
g.drawImage(imgBackgroundBottom, getWidth() - i, BackgroundTopHeight * 2, getWidth() * 2, BackgroundBottomHeight * 2, this);
}}
我的参考计划:参考图像
发布于 2016-01-11 23:55:46
首先,看看在Swing中并发,可能还有如何使用摆动计时器。
而且,您的paint方法非常危险,绘制是通过将一系列方法调用链接在一起来生成所需的结果来完成的,您不应该修改它,除非您非常、非常、非常肯定您正在做的事情。与其重写paint,不如简单地覆盖paintComponent (并调用它的超级方法)
有关详细信息,请参阅AWT和Swing中的绘画和表演定制绘画
一般经验法则是,您应该有一个“模型”,它表示游戏的当前状态(就像玩家的位置和任何其他需要跟踪的值一样),您将有一个“游戏/主”循环,它将根据输入和其他所需的逻辑定期更新模型的状态,然后安排一次画图更新。
您正在绘制的绘画不应该包含任何逻辑,除了绘制模型当前状态所需的逻辑之外,绘画是用于绘画的
让我们看看密码..。
for (int i = 0; i < frameAnimation.getWidth() + 1; i++) {
if (i == frameAnimation.getWidth()) {
//Level--;
i = 0;
}
frameAnimation.add(new AnimationPane(i));
try {
Thread.sleep(Level);
} catch (InterruptedException e) {
e.printStackTrace();
}
frameAnimation.revalidate();
}这有点奇怪(有点危险)。由于JVM启动时调用main方法的方式是偶然的,所以循环没有在事件分派线程的上下文中运行,但是您不应该做这些假设。您应该使用Swing Timer或另一个Thread在其中运行此循环。
现在,有两个主要问题。
这似乎是你问题的核心根源。
就我个人而言,我会有一个单一的面板,它能够简单地根据游戏的当前状态绘制需要绘制的内容。记住,Swing使用被动渲染引擎,因此可以随时触发绘画事件,这就是我们建议使用Swing计时器的原因。
一种更复杂的方法是使用BufferStrategy和BufferStrategy和BufferCapabilities,这允许您控制绘画过程(AKA活动绘画),这将允许您在控制绘画过程时使用Thread。
您还应该避免在可能的情况下使用static,static是造成更多问题和问题的原因,而不是我们从新开发人员那里看到的其他任何事情,它不是一种跨对象的通信机制。
如果您需要共享数据(比如游戏循环和视图之间的模型),那么应该将它的引用传递给两者。
https://stackoverflow.com/questions/34733102
复制相似问题