2013-06-28 124 views
3

我是新来的。希望你能帮上忙。Java游戏开发:图形

问题: 在JFrame上显示动画的问题。似乎我想念/不够了解Java的图形如何工作。

全球想法: 可以说我想做一个游戏/电影/剪辑。为此,我需要这个(而不是)简单的动画起作用。

对于这个问题的一个例子: 我有类屏幕,该屏幕具有JFrame的屏幕stuff-宣言,设置它的配置(大小,关闭操作等),然后创建类框的对象,将被显示在框架上。请检查类的这种图像/图(希望我写的正确方法):ClassesDiagram

现在,类箱扩展JPanel。我从JPanel继承Paint()方法并覆盖它,绘制框。

在屏幕类,我创建了两个箱子后,我。新增它们()到JFrame。接下来,while(true)开始一个循环,并且通过使线程睡眠该数量来每隔200毫秒更新框的位置。 (在这种情况下,只是简单的X ++或y ++取决于哪个箱,盒1或BOX2)。

主要问题1):程序运行,并且示出了的JFrame,但在它的JFrame显示最后添加的对象/组分 - 框。它不显示另一个。为什么?

我发现一个话题,How to add multiple components to a JFrame?,并尝试了投票最多的提示,由jjnguy 11月15 '10在17:02。 对于一些奇怪的原因,不是第一次,也不是第二尖为我工作。

主要问题2):据我所知,我需要布局管理器。为什么我需要它,如果我只想在框架上的特定X,Y处绘制()?

找到其他职位(不能再次找到它)+ Oracle的约布局的指导方针,建议我需要考虑使用的setLayout(NULL);我试图这样做,但之后再次出现问题。

主要问题3): JFrame中显示出来,它只显示1盒(绿色的不会显示出来,不管你会做不知道为什么),并且当它MOVE-它会从删除另一边。 Here:Box Movement

在此先感谢您的帮助,提示和解释!希望这篇文章清晰,有条理,看起来不错。


public class Screen { 

public static void main(String[] args) { 
    new Screen(); 
} 

private JFrame window; 

public Screen() { 
    window = new JFrame("Multiply components panel"); 
    //window.setLayout(null); 
    window.setSize(200, 200); 

    window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 

    Box b1 = new Box(10,10, "box1"); 
    //b1.setBounds(10, 10, 50, 50); 

    Box b2 = new Box(100,100, "box2"); 
    //b2.setBounds(100, 100, 50, 50); 


    window.add(b1); 
    //window.add(b2); 


    window.setVisible(true); 

    while (true){ 

     b1.update(); 
     b2.update(); 

     try { 
      Thread.sleep(200); 
     } catch (Exception e) { 
      // TODO: handle exception 
     } 
    } 

} 
} 

public class Box extends JPanel{ 

int x, y, w, h; 
private String name; 

public Box(int x, int y, String name) { 
    this.x = x; 
    this.y = y; 
    this.w = 100; 
    this.h = 100; 
    this.name=name; 
} 


public void paint(Graphics g){ 
    System.out.println(this.name.equalsIgnoreCase("box1")); 
    if(this.name.equalsIgnoreCase("box1")){ 
     g.setColor(Color.BLACK); 
     g.fillRect(x, y, w, h); 
    }else{ 
     g.setColor(Color.GREEN); 
     g.fillRect(x, y, w, h); 
    } 


} 


public void update() { 
    if(this.name.equalsIgnoreCase("box1")) 
     x++; 
    else 
     y++; 
    //this.setBounds(x, y, w, h); 
    System.out.println("Current "+name+": X: "+x+", Y: "+y+", W: "+w+", H: "+h); 
    repaint(); 
} 

} 
+2

有1岁孩子可以喂,但是,看看[并发中的Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/),然后搜索只是因为摇摆和动画 – MadProgrammer

+0

@DavidKroukamp感谢您的有用链接。我会检查一下,看看你是如何在那里做的。不过,我想明白我缺少的东西。仅制作2个对象的动画不应该太复杂。我想了解它背后的想法。 – Daniel

+0

@MadProgrammer你将不得不忍受它,爸爸。感谢您的链接,将检查出来。不知道它将通过多少有用。似乎它深深的线程工作,我不知道我需要。至少现在。 – Daniel

回答

3

主要问题1):该程序运行,并且示出了的JFrame,但在 JFrame中它仅示出最后添加的对象/组分 - 框。它不 显示另一个。为什么?

你做 window.add(b1); window.add(b2);, 默认JFrameBorderLayout因此要更换,最后添加的盒子,当你做add(..)

主要问题2):据我所知,我需要布局管理器。为什么 我需要它,如果我只想在框架上的特定X,Y处绘制()?

如果您正在使用JPanel S作为游戏中的物体比,这是使用setLayout(null),因为我们希望在JPanel小号拼劲全力控制的唯一时间。

主要问题3):JFrame中显示出来,它只显示1盒(绿色 一个不会显示出来,不管你会做不知道为什么),并且当 DOES MOVE-它得到从对方擦去。在这里:箱中移动

,因为你说,你这g.fillRect(x,y,w,h),它应该是g.fillRect(0,0,w,h)

其他问题:

1)我认为你有一个主要的问题是在这里:

public class Box extends JPanel{ 

    ... 

    public void paint(Graphics g){ 

     ... 
    } 

} 

您应该覆盖的JPanel,并记得拨打super.paintComponent(g)作为第一次调用的重写方法。

3)你应该重写的JPanelgetPreferredSize和返回的JPanel

4图像或内容匹配其正确的尺寸)不叫setSizeJFrame使用正确Layoutmanager和/或覆盖必要的容器的getPreferredSize不是简单地调用在将其设置为可见之前,在JFrame上的pack()。 5)如@MadProgrammer所述,读取Concurrency in Swing,但基本上所有Swing组件都应通过SwingUtilities.inokeXXX块在EDT上创建/操作。

6)这样做是不好的definetly:

while (true){ 

    b1.update(); 
    b2.update(); 

    try { 
     Thread.sleep(200); 
    } catch (Exception e) { 
     // TODO: handle exception 
    } 
} 

因为你不仅是创建一个连续的循环,而且在其创建您的GUI线程中调用Thread.sleep,因而会显得冻结。看看How to use Swing Timers,也看到this类似question.answer就上面的话题。

这里是代码上面的修复实施:

enter image description here

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import javax.swing.AbstractAction; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 

public class Screen { 

    private JFrame window; 

    public static void main(String[] args) { 

     //creat UI on EDT 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Screen(); 
      } 
     }); 
    } 

    public Screen() { 
     window = new JFrame("Multiply components panel") { 
      @Override 
      public Dimension getPreferredSize() { 
       return new Dimension(600, 400); 
      } 
     }; 

     window.setLayout(null);//only reason this is warrented is because its a gmae using JPanels as game objects thus we need full control over its placing 
     window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//changed from DISPOSE to EXIT so Timers will be exited too 

     final Box b1 = new Box(10, 10, 50, 50, "box1"); 

     final Box b2 = new Box(100, 100, 50, 50, "box2"); 

     window.add(b1); 
     window.add(b2); 

     window.pack(); 
     window.setVisible(true); 

     Timer timer = new Timer(200, new AbstractAction() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       b1.update(); 
       b2.update(); 
      } 
     }); 
     timer.setInitialDelay(0); 
     timer.start(); 

    } 
} 

class Box extends JPanel { 

    int x, y, w, h; 
    private String name; 

    public Box(int x, int y, int w, int h, String name) { 
     this.x = x; 
     this.y = y; 
     this.w = w; 
     this.h = h; 
     this.name = name; 
     setBounds(x, y, w, h);//let the Box class handle setting the bounds more elegant OOP 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     System.out.println(this.name.equalsIgnoreCase("box1")); 
     if (this.name.equalsIgnoreCase("box1")) { 
      g.setColor(Color.BLACK); 
      g.fillRect(0, 0, w, h); 
     } else { 
      g.setColor(Color.GREEN); 
      g.fillRect(0, 0, w, h); 
     } 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(w, h); 
    } 

    public void update() { 
     if (this.name.equalsIgnoreCase("box1")) { 
      x++; 
     } else { 
      y++; 
     } 
     this.setBounds(x, y, w, h);//set the new bounds so box may be updated 
     System.out.println("Current " + name + ": X: " + x + ", Y: " + y + ", W: " + w + ", H: " + h); 
     revalidate(); 
     repaint(); 
    } 
} 

最后看看我的教程/代码片断Game Development Loop, Logic and Collision detection Java Swing 2D。它具有启动一个简单的2D游戏所需的一切,比如游戏循环,逻辑,像素碰撞检测,动画(即在多个精灵之间交换以创建精灵集合的动画)等等,但其根本区别在于它使用对象作为游戏实体,即一个类将保存所有需要绘制对象的信息,这就是游戏应该如何完成,事情可能会变得很激烈,并且有很多JPanels想知道屏幕肯定会丢失整体FPS

+0

谢谢你的回答。我会仔细检查,并尝试学习和理解它。如果我有任何问题,我会写。有一件事 - 我试图添加另一个Box,它在第一个消失时出现。 :\ – Daniel

+1

@DanielBenshtein请看我更新的帖子我尽力回答你所有的问题,并且让你的盒子出现,而不仅仅是1 –

+0

非常感谢你的耐心,以及良好和完整的答案!现在剩下的是查看代码并学习,以及您和其他人提供的链接(但现在是我的工作;)谢谢! – Daniel