Java AWT có phù hợp để kết xuất trò chơi 2d không?


8

[Đăng lại câu hỏi này từ stackoverflow, vì nó đã chỉ ra rằng nó phù hợp hơn ở đây.]

Tôi hiện đang chuyển công cụ trò chơi 2D của mình sang Java. Tôi đã xem xét một số thư viện trò chơi được chỉ ra ở đây trên stackoverflow. Tuy nhiên, những cái tôi nhìn vào khá đơn giản và thậm chí không nói rõ nếu chúng hỗ trợ những thứ như độ trong suốt alpha, vì vậy tôi quyết định chuyển trình kết xuất C ++ của mình mà tôi đã viết ra logic.

Trình kết xuất này là trình kết xuất phần mềm thuần túy sử dụng ốp lát để tránh kết xuất lại không cần thiết. Tôi đã tối ưu hóa hiệu suất cuộn của nó bằng cách tạo ra "bộ đệm ngoài màn hình" lớn hơn một chút so với khung đầu ra của tôi và đưa bộ đệm ngoài màn hình này vào đầu ra của tôi trên mỗi khung hình. Bằng cách này, tôi có thể tránh vẽ lại các ô một cách không cần thiết chỉ vì tôi đã cuộn một pixel trên bản đồ.

Tôi đã sử dụng AWT của Java để triển khai nó, sử dụng BufferedImage lớn cho bộ đệm ngoài màn hình. Việc sử dụng CPU vẫn ổn (khoảng hai lần so với những gì tôi có trong C ++), nhưng có một vấn đề kỳ lạ với việc cuộn liên tục, trong đó mỗi giây hoặc lâu hơn, trình kết xuất sẽ bị trễ trong khoảng 0,2 giây.

Vì không có gì trong mã của riêng tôi sẽ xảy ra trong các giai đoạn này và vì các xung đột biến mất nếu tôi không vẽ bộ đệm ngoài màn hình của mình lên khung nhìn chính, tôi chỉ có thể kết luận rằng Java đang tự tối ưu hóa nội bộ. Tuy nhiên, tôi không chắc nó làm gì, tôi cũng không biết mình sẽ phải loại bỏ tối ưu hóa nào để loại bỏ các gai nhọn. Ngoài ra, có thể java AWT không được tạo ra với tính năng cuộn FPS liên tục, cao và điều đó hoàn toàn không thể sử dụng cho mục đích này.

Có cách nào để tôi thoát khỏi những cái gai này không?


4
Nó có thể là người thu gom rác đánh bạn?
bummzack

@bummzack: Có thể. Trong hồ sơ có vẻ như thế này: i.imgur.com/EMxkA.png Tuy nhiên, tôi không chắc mình sẽ giảm hiệu ứng này như thế nào, đặc biệt là nếu nó gây ra bởi các cuộc gọi của tôi tới Graphics.drawImage
cib

Câu trả lời:


4

Mặc dù tôi không thể chắc chắn nếu không nhìn vào mã của bạn, nhưng có vẻ như vấn đề của bạn là trình thu gom rác. Trong Java, bạn có các bộ sưu tập rác lớn và nhỏ diễn ra mọi lúc mọi nơi. Trẻ vị thành niên sử dụng một số cpu của bạn nhưng sẽ không làm phiền bạn quá nhiều. Các bộ sưu tập chính có thể là một vấn đề thực sự cho các ứng dụng thời gian thực như trò chơi vì chúng thực sự sẽ tạm dừng mọi thứ trong khi chúng đang chạy.

Có hai lựa chọn để giải quyết điều này. Trước tiên, bạn có thể điều chỉnh JVM để đảm bảo các bộ sưu tập chính ít hơn diễn ra. Thứ hai (và được khuyến nghị), bạn có thể đảm bảo rằng bạn không để lại quá nhiều rác. Chỉ cần kiểm tra vị trí trong ứng dụng của bạn, bạn tạo ra rất nhiều đối tượng (trong các trò chơi của tôi thường là các lớp vector3) và đảm bảo bạn sử dụng lại chúng càng nhiều càng tốt (đặc biệt là các vòng lặp bên trong, v.v.).


2

Đúng.

Đối với các trò chơi dựa trên sprite 2D, AWT có thể được sử dụng để xử lý kết xuất thành hiệu quả tuyệt vời. Nó thậm chí có thể được tăng tốc phần cứng , tùy thuộc vào phần cứng có sẵn.

Không có bất kỳ đoạn mã hoặc đoạn trích chi tiết nào, thật khó để nói vấn đề là gì. Điều tốt nhất tôi có thể làm là cung cấp một số mẹo cơ bản để làm việc với Java và AWT khi xây dựng trò chơi.

Làm việc với Trình thu gom rác

GC trong Java là điều mà chúng ta phải thực sự ghi nhớ khi chúng ta xây dựng các trò chơi của mình. Nó sẽ chạy định kỳ và tìm kiếm các đối tượng không có bất kỳ tham chiếu nào đến chúng và xóa chúng khỏi bộ nhớ. Quá trình loại bỏ này là chậm và có khả năng là nguyên nhân của việc quá giang bạn đang gặp phải.

Đề nghị của tôi là tránh tạo các tham chiếu đối tượng sẽ không được lưu giữ trong suốt thời gian thực hiện (hoặc ít nhất, càng nhiều càng tốt). Mục tiêu lý tưởng là đảm bảo rằng GC không có gì để làm bất cứ khi nào nó chạy.

Trong thực tế, bạn có thể kết thúc với rất nhiều biến tĩnh mà bạn sử dụng lại trong suốt trò chơi. Đây là một ví dụ rất dễ hiểu về cách tôi có xu hướng đối phó với điều đó:

public final class Resources {
    public static Map<int, String> strings;
    public static Map<int, Texture> textures;
    public static Map<int, GameObject> objects;
    public static Map<int, SoundEffect> sounds;
}

Trong quá trình tải màn hình là nơi bạn có thể phát triển hoặc thu nhỏ các Mapthể hiện của mình bằng newtừ khóa. Nhưng trong khi chơi, bạn sẽ muốn tránh điều đó nhiều nhất có thể. Nếu có thứ gì đó bị phá hủy trong khi chơi, hãy đặt cờ lên đối tượng để bạn biết đó không phải là thứ đang hoạt động. Nếu bạn cần sinh ra một đối tượng mới, hãy đi qua Mapcho đến khi bạn tìm thấy một đối tượng không hoạt động, và đặt thuộc tính của nó và đánh dấu nó là hoạt động.

Đây là điều bạn sẽ muốn ghi nhớ khi sử dụng Java cho các ứng dụng nhạy cảm với hiệu suất bất kể bạn đang sử dụng AWT, JavaFX hay OpenGL để thực hiện kết xuất.

Tranh sơn dầu

Đối với AWT nói riêng, tôi đặc biệt khuyên bạn nên sử dụng lớp Canvas để hiển thị mọi thứ trên vì nhiều lý do:

  • Bạn có thể kiểm soát tốt hơn khi mọi thứ kết xuất. Điều này có nghĩa là bạn có thể viết vòng lặp trò chơi của riêng mình và thực hiện những việc như nội suy, ngoại suy, giới hạn tỷ lệ, v.v.
  • Nó dường như để thực hiện tốt hơn. Tôi đã có thể nhận được nhiều thứ hơn trên màn hình cùng một lúc với tốc độ khung hình chấp nhận được, trái ngược với việc cố gắng làm động một loạt các đối tượng Nhãn và Hình ảnh.
  • Nó dễ dàng hơn để nhúng trong các trình soạn thảo. Có thể thiết lập Khung với các điều khiển GUI thông thường và trỏ logic kết xuất trò chơi của bạn vào Canvas có nghĩa là tôi có thể sử dụng lại mã kết xuất của trò chơi trong các công cụ chỉnh sửa.
  • Nó cho phép bạn truy cập dễ dàng vào API Java2D (hay còn gọi là lớp Graphics2D ).
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.