2017-10-05 96 views
0

我正在尋找一種有效的方法來實現2D遊戲渲染。如何正確高效地在2D遊戲中渲染Java圖形

這裏是我的遊戲此刻使用什麼樣的渲染系統的例子。 (我要麼不知道如何使用它,要麼它不夠靈活。)

我使用Canvas及其BufferStrategies,但我不確定它們的效率如何。 任何幫助表示讚賞。

//MY RENDERING SYSTEM EXPLAINED IN JAVA AND WITH ONLY ONE CLASS. 
//DOES NOT INCLUDE TICKING JUST RENDERING, TICKING IS A DIFFERENT THREAD. 
//(so they can run on different frames per second) 
//main() method is at the very bottom. 

/* 
* @Author 
* CodyOrr4 
*/ 

import javax.swing.*; 
import java.awt.*; 
import java.awt.image.*; 


public class Main implements Runnable { 

    public static Cache cache; 
    public static JFrame frame; 
    public static JPanel panel; 
    public static JViewport camera; 
    public static Canvas canvas; 
    public static BufferStrategy bufferStrategy; 
    public static Graphics graphics; 
    public static boolean rendering = false; 
    public static Thread renderingThread; 

    //turns this runnable into an object. 
    public Main() { 
     frame = new JFrame("Rendering System Example"); 
     frame.setSize(new Dimension(800, 600)); 
     frame.setDefaultCloseOperation(1); 
     frame.setVisible(true); 

     panel = new JPanel(); 
     panel.setBackground(Color.DARK_GRAY); 

     canvas = new Canvas(); 
     canvas.setBackground(Color.BLACK); 
     canvas.setPreferredSize(new Dimension(800, 600)); 
     canvas.setMinimumSize(new Dimension(800, 600)); 
     canvas.setMaximumSize(new Dimension(2000, 2000)); 

     cache = new Cache(); 

     panel.add(canvas); 
     frame.getContentPane().add(panel); 
    } 

    //used to run things that are not meant to be run in a loop; 
    private void init() { 
     cache.initCache(); //can now grab sprites (including names/ids) and other types within cache. 
    } 

    //renders everything (this method is used in a while() loop based on a boolean, within the run() method); 
    private void render(Graphics g) { 

     g.drawImage(cache.getSprite(0), 400, 300, 25, 25, null); 

    } 

    //runs the runnable 
    public void run() { 
     init(); 
     while(rendering) { 
      setFps(16);//simply set fps now - iJustin *codys note on the setFps(fps); method* = not sure if its the same thing lol, 
                 //but since ticking and rendering are separate threads in the main source (and contain separate init() methods) it seems like it would be good. 

      if(bufferStrategy == null) { 
       canvas.createBufferStrategy(3);//should only need a max of 3. 
       bufferStrategy = canvas.getBufferStrategy(); 
       graphics = bufferStrategy.getDrawGraphics(); 
       System.out.println("creating canvas components..."); 
      } 

      //drawing with methods 
      render(graphics); 

      //drawing without methods 
      graphics.drawImage(cache.getSprite(0), 0, 0, 50, 50, null); 



      bufferStrategy.show(); 
      graphics.dispose(); 
     } 
    } 

    //starts the run method and creates a thread for this 
    public synchronized void start() { 
     renderingThread = new Thread(this); 
     renderingThread.setName("Game Rendering Thread"); 
     renderingThread.start(); 
     rendering = true; 
    } 

    //stops the while loop by setting the boolean to false and the thread is now null 
    public synchronized void stop() { 
     renderingThread = null; 
     rendering = false; 
    } 

    //@Author iJustin - sets fps of the rendering loop (while() loop within run() method) 
    @SuppressWarnings("static-access") 
    public void setFps(long fps) { 
     try { 
      renderingThread.sleep(fps); 
     } 
     catch(InterruptedException e) { 

     } 
    } 

    //main method obv. 
    public static void main(String[] args) { 
     Main gameExample = new Main(); 
     gameExample.start(); 
    } 
} 
+0

對於fps,因爲渲染圖像不能完全總是在同一時間,你應該等待考慮最後渲染時間 – Tuco

+0

這是一個非常聰明的想法,究竟是多麼準確我會這樣做嗎? –

+0

儘管在渲染循環中使用setFps()方法創建了16毫秒的延遲,該延遲允許每1000毫秒(幾乎)60幀或每秒60幀 –

回答

0

對於FPS,你應該在解釋最後一幀渲染時間 它允許具有恆定的幀速率

對於此期間,你可以針對每一幀:

//a the start of rendering process 
long startRendering=System.nanoTime(); 

... rendering here... 

//duration of the frame rendering in ms : 
long durationMs=TimeUnit.NANOSECONDS.toMillis(System.nanoTime()-startRendering); 

// now waits 
if (durationMs < fps) 
{ 
renderingThread.sleep(fps - durationMs); 
} 

System.nanoTime允許以很高的精度測量時間:如果兩次調用System.nanoTime()之間的差異,您可以在調用之間花費時間(以納秒爲單位)。 我sugest不使用System.currentTimeMillis這是不太準確

+0

哇,很好,非常感謝,我會設置變量'fps'爲60,以每秒60幀的速度渲染? –

+0

不,你的fps變量是以毫秒爲單位的,所以如果你想要每秒60幀:fps = 1000/60 – Tuco

+0

有道理,alrigh t非常感謝你,tuco。 –