2011-11-05 63 views
0

好的,我正在製作一個遊戲,用戶在遊戲中的角色後面移動一個圖像(在我的代碼中稱爲「地圖」),這樣看起來好像角色正在移動。Java:我如何更快地繪製這些圖像?

程序運行時,性能下降適中,背景圖像(「地圖」)滯後,並且不總是重新繪製。

這裏是我的主類調用來繪製圖片類:

public graphics(int z,int s, int f) 
{ 
    x = z; 
    y = s; 
    d = f; 
    try { 
    map = ImageIO.read(new File("background.png")); 
    //br = ImageIO.read(new File("blackrectangle.jpg")); 
    s0 = ImageIO.read(new File("spriteshoot0.png")); 
    s10 = ImageIO.read(new File("spriteshoot10.png")); 
    s20 = ImageIO.read(new File("spriteshoot20.png")); 
    s30 = ImageIO.read(new File("spriteshoot30.png")); 
    s40 = ImageIO.read(new File("spriteshoot40.png")); 
    s50 = ImageIO.read(new File("spriteshoot50.png")); 
    s60 = ImageIO.read(new File("spriteshoot60.png")); 
    s70 = ImageIO.read(new File("spriteshoot70.png")); 
    s80 = ImageIO.read(new File("spriteshoot80.png")); 
    s90 = ImageIO.read(new File("spriteshoot90.png")); 
    s100 = ImageIO.read(new File("spriteshoot100.png")); 
    s110 = ImageIO.read(new File("spriteshoot110.png")); 
    s120 = ImageIO.read(new File("spriteshoot120.png")); 
    s130 = ImageIO.read(new File("spriteshoot130.png")); 
} catch (IOException e) {} 
} 
public void moveZ(int a,int b) 
{ 
    xz+=a; 
    yz+=b; 
} 

public void move(int a,int b) 
{ 
    x+=a; 
    y+=b; 
} 

public void angle(int t) 
{ 
    q=t; 

} 



public void paintComponent(Graphics g) { 

     g.drawImage(map,x,y,this); 

     if (q==1) 
     g.drawImage(s0,599,340,null); 

     if (q==2) 
     g.drawImage(s10,599,340,null); 

     if (q==3) 
     g.drawImage(s20,599,340,null); 

     if (q==4) 
     g.drawImage(s30,599,340,null); 

     if (q==5) 
     g.drawImage(s40,599,340,null); 

     if (q==6) 
     g.drawImage(s50,599,340,null); 

     if (q==7) 
     g.drawImage(s60,599,340,null); 

     if (q==8) 
     g.drawImage(s70,599,340,null); 

     if (q==9) 
     g.drawImage(s80,599,340,null); 

     if (q==10) 
     g.drawImage(s90,599,340,null); 

     if (q==11) 
     g.drawImage(s100,599,340,null); 

     if (q==12) 
     g.drawImage(s110,599,340,null); 

     if (q==13) 
     g.drawImage(s120,599,340,null); 

     if (q==14) 
     g.drawImage(s130,599,340,null); 
    }} 

所以我想知道怎樣才能顯示圖像「地圖」更快或找到解決這個性能問題的替代路線。

注* *此代碼是作爲我的主類中的一個對象創建的,並且每次執行時都不會從文件中讀取BufferedImages(據我所知)。此外,repaint();方法在我的程序中每16毫秒調用一次(是的,我試圖增加那個時間,問題仍然存在)。下面是用於重新繪製幀定時器的一個片段:)

TimerTask的任務=新的TimerTask({

public void run()  { 

     if (onU) 
      g.move(0,3); 

     if (onL) 
      g.move(3,0); 

     if (onD) 
      g.move(0,-3); 

     if (onR) 
      g.move(-3,0); 
     //System.out.println(ze.getX(650,400,650,0,xZ,yZ)); 
     //System.out.println(ze.getY(650,400,650,0,xZ,yZ)); 
     if(onR||onL||onD||onU) 
     gameSurface.repaint(); 
    }}; 

任何幫助感激,謝謝。

+0

永遠不要處理由paint或paintComponent方法中的JVM傳遞給您的Graphics對象。只處理你自己創建的一個。 –

+0

你試過雙緩衝嗎? – 2011-11-05 02:55:50

+0

不,我以爲自動雙緩衝 – user1030690

回答

1

如果你正在編寫遊戲,你應該使用遊戲引擎。編寫高性能遊戲非常困難,螢幕上的所有內容的蠻力重繪都不會削減它。其他聰明人已經解決了這些問題,你可以利用他們的累積工作而不是試圖重新發明輪子。

我不是遊戲引擎方面的專家,但在「java遊戲引擎」上的第一個搜索引擎是jmonkeyengine.com。也許你應該嘗試一下。

+0

好的謝謝你,我一定會嘗試。 – user1030690

1

考慮限制重新繪製(...)到需要重新繪製的GUI的小區域。另外,不要將JVM在Graphics或PaintComponent方法中傳遞給您的Graphics對象置於其中。只處理你自己創建的一個。

編輯1
如果顯卡性能的關鍵是,你可能會更好離開Swing和移動到爲遊戲,動畫和圖形優化的庫。

+0

好的,我已經刪除了dispose();方法,但背景圖像顯示在整個JPanel中,每次移動時都需要重繪,所以我不能將repaint()方法限制爲某些參數,因爲整個JPanel需要更新。 – user1030690

+0

@ user1030690:看編輯 –

+0

是的,我會嘗試一個高速性能的遊戲庫,謝謝。 – user1030690

1

您可以通過ResourceBundle緩存經常使用的圖像。以下代碼提供對存儲在jar或絕對路徑中的圖像的緩存訪問,如ImageIcons。首次訪問會將圖像存儲到Hashtable中。隨後對相同圖像的調用將作爲查找。這個類必須在「默認」包設置:

import java.util.*; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.net.*; 

import javax.imageio.ImageIO; 
import javax.swing.*; 

/** 
* ImageBundle is a ResourceBundle that retrieves the content of an image from an image file with supported extension. 
*/ 
public class ImageBundle extends ResourceBundle { 
    private static final String RESOURCE = "MyApp"; 
    private String __fileSuffix; 
    /** 
    * @uml.property name="__KEYS" 
    */ 
    private static final Vector<String> __KEYS; 
    private static Hashtable<String, ImageIcon> __TABLE; 

    static { 
     __KEYS = new Vector<String>(); 
     __KEYS.addElement(RESOURCE); 
     __TABLE = new Hashtable<String, ImageIcon>(); 
    } 

    /** 
    * Load image file stored in a JAR classpath 
    * @param imageName the filename of the image 
    * @return the ImageIcon of the image file 
    */ 
    private ImageIcon __loadImageFromJar(String imageName) { 
     String path = ""; //define the file path of the image file in imageName itself 

     String imagePath = path + imageName + __fileSuffix; 
     ImageIcon icon; 
     URL url; 

     icon = (ImageIcon)__TABLE.get(imageName); 

     if(icon != null) 
      return icon; 

     url = ImageBundle.class.getResource(imagePath); 

     icon = new ImageIcon(url); 
     __TABLE.put(imageName, icon); 

     return icon; 
    } 

    /** 
    * Load image file stored in a given path 
    * @param imageName the filename of the image 
    * @return the ImageIcon of the image file 
    */ 
    @SuppressWarnings("unused") 
    private ImageIcon __loadImageFromExternalSource(String imageName) { 
     String path = System.getenv("MY_APP_HOME_PATH"); 

     String imagePath = ((path != null) ? (path + imageName + __fileSuffix) : (imageName + __fileSuffix)); 
     ImageIcon value; 

     value = (ImageIcon)__TABLE.get(imageName); 

     if(value != null){ 
      //Outils.debugMessage("Cached " + imagePath + "> " + imageName + ": " + value); 
      return value; 
     } 
     else { 
      //Outils.debugMessage("New " + imagePath + "> " + imageName + ": " + value); 
     } 

     ImageIcon property = null; 
     BufferedImage image = null; 
     try { 
      image = ImageIO.read(new File(imagePath)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     property = new ImageIcon(image); 

     value = property; 
     __TABLE.put(imageName, value); 

     return value; 
    } 

    protected ImageBundle(String suffix) { 
     __fileSuffix = suffix; 
    } 

    public ImageBundle() { 
     this(""); 
    } 

    /** 
    * @return 
    * @uml.property name="__KEYS" 
    */ 
    public Enumeration<String> getKeys() { 
     return __KEYS.elements(); 
    } 

    protected final Object handleGetObject(String key) { 
     return __loadImageFromJar(key); 
    } 
} 

用法:

ResourceBundle rsc = ResourceBundle.getBundle("ImageBundle"); //call rsc only once 
... 
ImageIcon icon = (ImageIcon) rsc.getObject("picture/plus.png"); 
+0

好吧,我在我的代碼中實現了這一點,但沒有性能改進。這可能是因爲這個想法更快地讀取圖像,而不是更快地繪製/重新繪製圖像,這是最大的性能問題所在。 – user1030690

+0

如何通過安裝自己的重繪管理器來使用javax.swing.RepaintManager? – ecle

0

我有一個性能問題與容器內的交互式移動的JComponent,發現調用重繪()上父母,而不是在移動的組件,給了巨大的速度增加。我不知道爲什麼 - 有人知道嗎?

+0

我試過這個,但是我沒有看到重繪容器和重新繪製框架的性能有任何區別。 – user1030690