Lập trình trò chơi Java 2D: Các cách tiếp cận khác nhau để tạo một vòng lặp trò chơi


10

Tôi chưa quen với lập trình trò chơi Java, nhưng càng đọc tôi càng bối rối, vì tôi đã thấy một số cách tiếp cận khác nhau để tạo một vòng lặp trò chơi: 1. Cách tiếp cận tiêu chuẩn, sử dụng lớp Timer (dường như ít hơn tóm lược). 2. Cách tiếp cận chính xác hơn sử dụng System.nanoTime. 3. Một cách tiếp cận đơn giản sử dụng calendarAtFixedRate.

Cái nào thường được ưu tiên và đâu là ưu điểm / nhược điểm của từng phương pháp? Cảm ơn trước cho bất kỳ thông tin.

Câu trả lời:


7

Đối với vòng lặp trò chơi cơ bản, bạn sẽ chạy vòng lặp while, trong đó bạn sẽ có thời gian sử dụng nanoTime (), xác định thời gian đã trôi qua kể từ khung hình cuối cùng, sau đó cập nhật trò chơi và kết xuất của bạn.

Sử dụng http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#nanoTime%28%29 , bạn có thể thăm dò trong thời gian đã trôi qua. Về cơ bản...

public static void main(String [ ] args)
{
    long current_frame_time = system.nanoTime();
    long last_frame_time = current_frame_time;

    while(gameIsRunning)
    {
        last_frame_time = current_frame_time;
        current_frame_time = system.nanoTime();

        long timeTaken = current_frame_time - last_frame_time;

        //update and render game here
    }
}

Phương pháp cơ bản này có thể được cải thiện dựa trên, ví dụ: http://www.koonsolo.com/news/dewitters-gameloop/http://gafferongames.com/game-physics/fix-your-timestep/ .

Ngoài ra, bạn có thể tạo bộ hẹn giờ và đặt bộ hẹn giờ này để chạy cập nhật và hiển thị mỗi X mili giây. Nhưng, có một số nhược điểm khi xây dựng một trò chơi như thế.

Theo http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html : " Tương ứng với mỗi đối tượng Timer là một luồng nền duy nhất được sử dụng để thực hiện tất cả các bộ đếm thời gian Các tác vụ, tuần tự. Các tác vụ hẹn giờ sẽ hoàn thành nhanh chóng. Nếu một tác vụ hẹn giờ mất quá nhiều thời gian để hoàn thành, nó sẽ "ăn cắp" luồng thực thi tác vụ của bộ đếm thời gian. Điều này có thể, đến lượt nó, trì hoãn việc thực hiện các tác vụ tiếp theo, có thể "bó lại" và thực hiện liên tiếp nhanh chóng khi (và nếu) nhiệm vụ vi phạm cuối cùng đã hoàn thành. "

Theo http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html#scheduleAtFixedRate%28java.util.TimerTask,%20java.util.Date,%20long%29 : " Trong thực thi tốc độ cố định, mỗi lần thực hiện được lên lịch liên quan đến thời gian thực hiện theo lịch trình của lần thực hiện ban đầu. Nếu việc thực thi bị trì hoãn vì bất kỳ lý do nào (chẳng hạn như thu gom rác hoặc hoạt động nền khác), hai hoặc nhiều lần thực hiện sẽ xảy ra liên tiếp để "bắt kịp". Về lâu dài, tần suất thực hiện sẽ chính xác là đối ứng của khoảng thời gian được chỉ định (giả sử đồng hồ hệ thống nằm dưới Object.wait (dài) là chính xác). "

Vì bạn thường không biết trước vòng lặp trò chơi mất bao lâu, nên việc đặt bộ hẹn giờ để thực hiện giao diện của bạn sau mỗi X mili giây (tùy thuộc vào tốc độ khung hình đích) có thể dẫn đến một vài khung hình bị bó lại, sẽ thực hiện bất cứ khi nào một khung hình kết thúc thay vì khi một khung được lên lịch. Khi điều đó xảy ra ... tại sao lại sử dụng đồng hồ bấm giờ ở nơi đầu tiên?

Bây giờ, đừng hiểu sai ý tôi, bộ đếm thời gian không phải là một lớp xấu, nhưng nó thường phù hợp hơn với các nhiệm vụ nhỏ cần được thực hiện định kỳ hoặc tại một thời điểm nhất định, ví dụ: một ứng dụng thư có thể muốn kiểm tra thư mới cứ sau 5 phút hoặc một bộ đếm có thể bị giảm dần mỗi giây để hiển thị đếm ngược trước khi bắt đầu cuộc đua.


Câu hỏi là về các vòng lặp trò chơi để thông tin awt / swing bị lạc đề. Tuy nhiên có vẻ như thông tin đó có liên quan vì một dòng không liên quan và khó hiểu trong câu hỏi, vì vậy tôi đã loại bỏ nó.
jhocking

Tôi điều chỉnh câu trả lời của mình để phản ánh những thay đổi được thực hiện cho câu hỏi.
Exilyth

7

Tôi sẽ không đặt vòng lặp chính trong một bộ đếm thời gian. Thay vào đó, tôi sẽ tạo một vòng lặp 'while' xử lý mọi khung hình và sau đó sử dụng một số loại chức năng chấm công (nghe có vẻ như trong Java sẽ là System.nanoTime) để tính thời gian đã trôi qua kể từ lần lặp cuối cùng / lần lặp cuối cùng của vòng.

Một số ngôn ngữ là ngoại lệ ở đây (ví dụ: JavaScript, ActionScript) vì các ngôn ngữ đó hoạt động trong một môi trường có vòng lặp chính ẩn để kết nối (ví dụ: trình duyệt, Flash Player) nhưng ngoại lệ đó không áp dụng cho Java.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.