2013-08-16 81 views
11

Tôi đang viết một vòng lặp trò chơi, tôi đã tìm thấy mã trong ví dụ bên dưới here. Tôi cũng đã xem xét các cách khác để thực hiện một vòng lặp trò chơi, chẳng hạn như từ this article. Tôi không thể nhận được bất kỳ của những người làm việc mặc dù. Vì vậy, tôi giữ với một từ liên kết đầu tiên.Vòng lặp trò chơi chính Java

Những gì tôi muốn biết:

  • có phải là cách tôi đã viết vòng lặp trò chơi của tôi một cách tốt để làm điều này?
    • Bất kỳ đề xuất nào?
  • Tôi có nên sử dụng Thread.sleep(); trong vòng lặp trò chơi của mình không?

Đây là mã hiện tại của tôi:

public void run(){ 
    long lastLoopTime = System.nanoTime(); 
    final int TARGET_FPS = 60; 
    final long OPTIMAL_TIME = 1000000000/TARGET_FPS; 
    long lastFpsTime = 0; 
    while(true){ 
     long now = System.nanoTime(); 
     long updateLength = now - lastLoopTime; 
     lastLoopTime = now; 
     double delta = updateLength/((double)OPTIMAL_TIME); 

     lastFpsTime += updateLength; 
     if(lastFpsTime >= 1000000000){ 
      lastFpsTime = 0; 
     } 

     this.updateGame(delta); 

     this.repaint(); 

     try{ 
      Room.gameTime = (lastLoopTime - System.nanoTime() + OPTIMAL_TIME)/1000000; 
      System.out.println(Room.gameTime); 
      Thread.sleep(Room.gameTime); 
     }catch(Exception e){ 
     } 
    } 
+1

Tôi có một bài về vòng trò chơi và giữ nó ổn định [ở đây] (http://stackoverflow.com/question/17847930/custom-vsync-algorithm/18070011 # 18070011). –

Trả lời

11

Cuối cùng bạn sẽ muốn chuyển đến một cái gì đó giống như LWJGL, nhưng hãy để tôi căng thẳng, tiếp tục làm những gì bạn đang làm gì ở đây vào lúc này. Nó sẽ dạy cho bạn các nguyên tắc cơ bản.

Làm tốt công việc của bạn. Có vẻ đẹp, hãy để tôi cung cấp một vài gợi ý:

  • Dấu vết sẽ không hiển thị màn hình ngay lập tức. Nó cho biết RepaintManager để hiển thị khi sẵn sàng. Sử dụng vô hiệu hóa paintImmediately để thay thế. paintImmediately sẽ chặn thực thi cho đến khi thành phần đã được vẽ lại để bạn có thể đo thời gian hiển thị.

  • Thread.sleep thường có một vài phần nghìn giây trôi dạt. Bạn nên sử dụng nó để giữ cho vòng lặp của bạn từ việc sử dụng quá nhiều CPU, nhưng chắc chắn rằng bạn hiểu được nếu bạn ngủ 10 mili giây bạn có thể ngủ 5 mili giây hoặc bạn có thể ngủ 20.

  • Cuối cùng:

    double delta = updateLength/((double)OPTIMAL_TIME); 
    

    Nếu updateLength nhỏ hơn OPTIMAL_TIME, đừng gọi cập nhật. Nói cách khác, nếu delta nhỏ hơn một, không cập nhật. This tutorial giải thích lý do tại sao tốt hơn tôi có thể.

+0

Cảm ơn! Nếu tôi sử dụng vô hiệu hóa một mình, không có gì xảy ra. Điều đó có xảy ra không? –

+0

Rất tiếc, tôi không bị lỗi. Tôi làm việc với C# và Java hàng ngày. Đã trộn lẫn lên. Đã chỉnh sửa. Hãy thử paintImmediately thay vì –

+0

Tôi đã phải di chuyển 'paintImmediately' sau khi' try-catch' nếu không nó làm một số rendering lạ ... tôi nên làm điều đó? –

4

Nhìn chung, đó là một vòng lặp tốt, nhưng có một vài khía cạnh thiếu đối với những gì tôi đã thấy là trải nghiệm tốt nhất.

Cuối cùng bạn sẽ muốn di chuyển đến LWJGL hoặc một số API trò chơi java khác, nhưng hiện tại, hãy tìm hiểu kiến ​​thức cơ bản về cách vòng trò chơi hoạt động và điều gì phù hợp nhất với nhu cầu của bạn.

  • Thứ nhất, để trả lời một trong các điểm của bạn, không. Bạn sẽ làm tốt hơn tránh xa

    Thread.sleep()

    này có thể lạc vào số tiền thực sự của thời gian bạn đặt nó vào giấc ngủ.
    ví dụ: nếu bạn đặt nó ngủ trong 10 mili giây, nó có thể ngủ chương trình trong 5 đến 20 mili giây.

  • Vấn đề thứ hai mà tôi cam ngay lập tức thấy là bạn không có cách nào để dừng vòng lặp trò chơi cho phương thức stop() tùy chỉnh. Hãy thử

    boolean running = true;
    while (chạy) {
    // Code của bạn đây //
    }

  • Thứ ba, bạn có thể muốn xem xét thay đổi cách bạn sử dụng biến đồng bằng của bạn. Cách thức trong mã bên dưới có thể là cách sử dụng và xây dựng tốt hơn cho bạn.

    Đây là một ví dụ của tôi trò chơi vòng mà tôi sử dụng trong các chương trình của tôi:

    @Override 
    public void run() { 
    
    long initialTime = System.nanoTime(); 
    final double timeU = 1000000000/UPS; 
    final double timeF = 1000000000/FPS; 
    double deltaU = 0, deltaF = 0; 
    int frames = 0, ticks = 0; 
    long timer = System.currentTimeMillis(); 
    
        while (running) { 
    
         long currentTime = System.nanoTime(); 
         deltaU += (currentTime - initialTime)/timeU; 
         deltaF += (currentTime - initialTime)/timeF; 
         initialTime = currentTime; 
    
         if (deltaU >= 1) { 
          getInput(); 
          update(); 
          ticks++; 
          deltaU--; 
         } 
    
         if (deltaF >= 1) { 
          render(); 
          frames++; 
          deltaF--; 
         } 
    
         if (System.currentTimeMillis() - timer > 1000) { 
          if (RENDER_TIME) { 
           System.out.println(String.format("UPS: %s, FPS: %s", ticks, frames)); 
          } 
          frames = 0; 
          ticks = 0; 
          timer += 1000; 
         } 
        } 
    } 
    
+0

Xin chào Tôi biết đó là một bài đăng/câu hỏi cũ, nhưng phương thức getInput() nào thực hiện? Và tại sao bạn đang sử dụng một chuỗi thay vì một Timer? sử dụng Thread có tốt hơn không? – navy1978

+0

1. Chức năng 'getInput()' chỉ tách chế độ xử lý đầu vào của người dùng khỏi logic trò chơi chính (tức là nhấn phải, đăng ký trò chơi ngay trong 'getInput()', đối tượng di chuyển ngay trong 'update()'). 2. Tôi sử dụng một Thread thay vì Timer bởi vì nó tách toàn bộ logic game khỏi các tiến trình nền nên nó sẽ chạy trên một lõi cpu khác. Hãy xem điều này để biết thêm thông tin về các chủ đề: http://www.tomshardware.co.uk/forum/306079-28-what-core-thread – TheCrazyPhoenix

+0

Cảm ơn câu trả lời của bạn Tôi đã thực hiện rất nhiều bài kiểm tra và sử dụng Thread thay vì Timer (thực hiện trên 60FPS) làm cho ứng dụng của tôi sử dụng nhiều CPU hơn trên MacBook Pro của tôi (3 GHz Intel Core i7 với 16GB ram). Rất lạ tôi sẽ cố gắng thực hiện các cuộc điều tra khác, nhưng hiện tại tôi sẽ sử dụng Timer. Mặt khác, bạn đã cho tôi một ý tưởng tốt với phương thức getInput của bạn. ;) – navy1978

Các vấn đề liên quan