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