这是我的油漆代码。我知道我应该使用缓冲区,但我不明白如何在我的代码上使用它以及它做了什么,所以请你帮忙解释一下它是什么以及它做了什么和/或编辑我的代码以便它可以停止闪烁谢谢。
public void paint(Graphics g ) {
g.fillRect(BulletX, BulletY,0,0);
g.setColor(Color.yellow);
try{
FileInputStream saveFile = new FileInputStream("Wins1.sav");
ObjectInputStream save = new ObjectInputStream(saveFile);
wins1 = (int) save.readObject();
save.close();
}
catch(Exception exc){
exc.printStackTrace();
}
Image image;
URL resource = getClass().getClassLoader().getResource("moon1.jpg");
URL resource1 = getClass().getClassLoader().getResource("Tank.jpg");
URL resource2 = getClass().getClassLoader().getResource("Tank2.jpg");
ImageIcon i2 = new ImageIcon(resource);
ImageIcon i1 = new ImageIcon(resource1);
ImageIcon i3 = new ImageIcon(resource2);
image = i2.getImage();
g.drawImage(image, 0,0,null);
if (SHOW.equals("ON")){
g.setFont(new Font("TimesRoman", Font.BOLD, 30));
g.drawString("Player 1's health ="+Integer.toString(Player1H), 50, 25);}
if (wins == 1){
g.setColor(Color.BLACK);
g.fillOval(20, 10, 30, 30);
g.setColor(Color.YELLOW);
}
if (wins == 2){
g.setColor(Color.BLACK);
g.fillOval(20, 10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval( 60,10, 30, 30);
g.setColor(Color.YELLOW);
}
if (wins == 3){
g.setColor(Color.BLACK);
g.fillOval(20, 10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval( 60,10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval( 100,10, 30, 30);
g.setColor(Color.YELLOW);
}
if (wins == 4){
g.setColor(Color.BLACK);
g.fillOval(20, 10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval( 60,10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval( 100,10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval(140,10, 30, 30);
g.setColor(Color.YELLOW);
}
if (wins1 == 1){
g.setColor(Color.BLACK);
g.fillOval( 360,10, 30, 30);
g.setColor(Color.YELLOW);
}
if (wins1 == 2){
g.setColor(Color.BLACK);
g.fillOval( 360,10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval( 400,10, 30, 30);
g.setColor(Color.YELLOW);
}
if (wins1 == 3){
g.setColor(Color.BLACK);
g.fillOval( 360,10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval( 400,10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval( 480,10, 30, 30);
g.setColor(Color.YELLOW);
}
if (wins1 == 4){
g.setColor(Color.BLACK);
g.fillOval( 360,10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval( 400,10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval( 480,10, 30, 30);
g.setColor(Color.BLACK);
g.fillOval( 520,10, 30, 30);
g.setColor(Color.YELLOW);
}
image = i1.getImage();
g.drawImage(image,myX, myY,null);
image = i3.getImage();
g.setColor(Color.blue);
if (Boss == 1){
g.setColor(Color.RED);
g.fillOval(myX1, myY1, 50, 50);
try {
Thread.sleep(800);
} catch (InterruptedException ex) {
Logger.getLogger(onePlayer1.class.getName()).log(Level.SEVERE, null, ex);
}
Boss = 2;
win();
}
g.drawImage(image,myX1, myY1,null);
if (hit2 ==1){
g.setColor(Color.red);
hit2 =0;
g.fillOval(myX1, myY1, 20, 20);
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(onePlayer1.class.getName()).log(Level.SEVERE, null, ex);
}
repaint();
}
if (hit1 ==1){
g.setColor(Color.red);
hit1 =0;
g.fillOval(myX, myY, 20, 20);
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(onePlayer1.class.getName()).log(Level.SEVERE, null, ex);
}
repaint();
}
if (Explode == true){
g.setColor(Color.RED);
g.fillOval(myX11,myY11,40,40);
number = 0;
Explode = false;
myX11 = -10;
myY11 = -10;
Player3H = 0;
try {
Thread.sleep(800);
} catch (InterruptedException ex) {
Logger.getLogger(onePlayer1.class.getName()).log(Level.SEVERE, null, ex);
}
repaint();
}
if (number ==11){
URL resource3 = getClass().getClassLoader().getResource("Dynamite.jpg");
ImageIcon i4 = new ImageIcon(resource3);
image = i4.getImage();
g.setColor(Color.GREEN);
g.drawImage(image,myX11, myY11,null);
}
if (number == 1){
g.setColor(Color.GREEN);
myX11 = myX1+10;
myY11 = myY1+10;
g.drawImage(image,myX11, myY11,null);
number =11;
Player3H = 10;
repaint();
}
g.setColor(Color.BLACK);
if (fire1.equals("Yes")){
if (aim1.equals("right")){
BulletY1 = myY1;
BulletX1 = myX1;
g.fillRect(BulletX1, BulletY1, 1000, 5);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(HandlingEvents.class.getName()).log(Level.SEVERE, null, ex);
}
fire1="no";
repaint();}
if (aim1.equals("down")){
BulletY1 = myY1;
BulletX1 = myX1;
g.fillRect(BulletX1, BulletY1, 5, 1000);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(HandlingEvents.class.getName()).log(Level.SEVERE, null, ex);
}
fire1="no";
repaint();}
if (aim1.equals("left")){
BulletY1 = myY1;
BulletX1 = myX1-1000;
g.fillRect(BulletX1, BulletY1, 1000,5);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(HandlingEvents.class.getName()).log(Level.SEVERE, null, ex);
}
fire1="no";
repaint();}
if (aim1.equals("up")){
BulletY1 = myY1-1000;
BulletX1 = myX1;
g.fillRect(BulletX1, BulletY1, 5, 1000);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(HandlingEvents.class.getName()).log(Level.SEVERE, null, ex);
}
fire1="no";
repaint();}}
if (fire.equals("Yes")){
if (aim.equals("right")){
BulletY = myY;
BulletX = myX;
BulletXX = myX+10;
BulletYY = myY+10;
g.fillRect(BulletXX, BulletYY, 1000, 5);
g.fillRect(BulletX, BulletY, 1000, 5);
fire="no";
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(onePlayer1.class.getName()).log(Level.SEVERE, null, ex);
}
repaint();}
if (aim.equals("down")){
BulletY = myY;
BulletX = myX;
BulletXX = myX+10;
BulletYY = myY+10;
g.fillRect(BulletXX, BulletYY, 5, 1000);
g.fillRect(BulletX, BulletY, 5, 1000);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(HandlingEvents.class.getName()).log(Level.SEVERE, null, ex);
}
fire="no";
repaint();}
if (aim.equals("left")){
BulletY = myY;
BulletX = myX-1000;
BulletXX = myX-990;
BulletYY = myY+10;
g.fillRect(BulletXX, BulletYY, 1000, 5);
g.fillRect(BulletX, BulletY, 1000,5);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(HandlingEvents.class.getName()).log(Level.SEVERE, null, ex);
}
fire="no";
repaint();}
if (aim.equals("up")){
BulletY = myY-1000;
BulletX = myX;
BulletXX = myX+10;
BulletYY = myY-990;
g.fillRect(BulletXX, BulletYY, 5, 1000);
g.fillRect(BulletX, BulletY, 5, 1000);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(HandlingEvents.class.getName()).log(Level.SEVERE, null, ex);
}
g.fillRect(BulletX, BulletY, 0, 0);
fire="no";
repaint();}}}
答案 0 :(得分:6)
你的代码太长了,没有人想调试它,但我发现你在快速检查中发现它有一些错误:
public void paint(Graphics g ) {
您应该从不覆盖paint(...)
方法,但paintComponent(...)
覆盖Swing components are double-buffered(正如@Radiodef在其回答中所解释的那样) ):
Swing确保将适当类型的Graphics对象(用于双缓冲的屏幕外图像Graphics,否则为常规Graphics)传递给组件的paint回调,因此所有组件需要做的就是用它绘制
我猜你使用这种方法的唯一原因是因为你正在扩展JFrame
,你应该扩展JPanel
并基于它们构建你的GUI,如JFrame
是一个严格的容器,请点击此处阅读:Extends JFrame vs. creating it inside the program
您不是在调用super.paint(g);
(或者如果遵循上面的建议super.paintComponent(g);
作为方法中的第一行......那可能会破坏画颜链
读取绘制方法中的文件可能是程序闪烁的原因,因为它增加了处理时间和延迟,这些行:
FileInputStream saveFile = new FileInputStream("Wins1.sav");
ObjectInputStream save = new ObjectInputStream(saveFile);
...
//until this line
image = i2.getImage();
会更好地放置在构造函数级别,绘制方法应该绘制,只有那样,因为绘制方法被多次调用(每次将鼠标移到GUI上都会重新绘制,因此每次都会加载资源)
< / LI> Thread.sleep(...);
您阻止Event Dispatch Thread,这可能是您的程序闪烁的另一个原因,您应该使用Swing Timer执行peridic任务
Boss = 2;
,Explode == true
您没有关注Java naming conventions:
FirstWordUpperCaseClass
firstWordLowerCaseVariable
firstWordLowerCaseMethod()
ALL_WORDS_UPPER_CASE_CONSTANT
您在repaint();
方法中多次调用paint(...)
!这是另一个原因,因为每次都是递归电话......
if (Explode == true)
,可以写成if (explode)
,这样可以防止像这样的拼写错误if (explode = true)
您的代码未正确缩进,因此很难阅读
如果您遵循上述所有建议并仍然遇到问题,请考虑发布一个有效的Minimal, Complete and Verifiable Example来证明问题,它应该很短但仍然完整且可编辑
答案 1 :(得分:6)
Swing components are already double-buffered by default.你重写了paint
,颠覆了这种机制。如果你改写paintComponent
而不是(正如我们在Swing中绘画时那样),那么绘画将自动进行双缓冲。
然而:
您正在阅读paint
中的文件,您不应该这样做。这使得您的绘画效率非常低,以至于低帧速率可能会明显变得明显。相反,您应该在程序首次启动时加载文件一次,并将资源放在您可以从程序中轻松引用的位置。
您正在Thread.sleep
中调用冻结GUI的paint
。 Swing程序应使用Timer
代替。
您以递归方式调用repaint()
,这会使事件队列充满油漆事件,并启动一个您无法控制的无限循环。使用Timer
远远好得多。
如果你想学习如何使用Swing编写简单的游戏,你可以看一下我的这两个答案:https://stackoverflow.com/a/44371593/2891664,https://stackoverflow.com/a/30175751/2891664。