Một đối tượng trong trò chơi 2D có nên tự hiển thị không?


16

Tôi đang tạo ra một trò chơi giống như máy bay chiến đấu đường phố 2D không dựa trên gạch. Thông thường mọi người khuyên rằng các thực thể được trao cho trình kết xuất hiển thị chúng, không phải chúng tự hiển thị, nhưng có vẻ như nghịch đảo là tốt hơn,

Tại sao cái này tốt hơn cái kia?

Cảm ơn


Tại sao bạn nghĩ ngược lại là tốt hơn?

1
@Martin vì đối tượng sẽ gợi ý bitmap nào sẽ sử dụng anyways, vậy tại sao không chỉ làm object-> render ();
jmasterx

Câu trả lời:


11

Một vài cân nhắc:

  • như bạn đã đề cập, mỗi sprite sẽ phải "gợi ý" về việc sử dụng bitmap nào, nhưng nếu thực thể phải tự kết xuất. 'Gợi ý' đó sẽ là gì? Nếu nó là một tham chiếu đến một bitmap khác, bảng sprite, v.v ... cho mỗi sprite, thì bạn có thể sẽ sử dụng nhiều bộ nhớ hơn mức cần thiết hoặc gặp khó khăn khi quản lý bộ nhớ đó. Một lợi thế của trình kết xuất riêng là bạn chỉ có một lớp chịu trách nhiệm quản lý tài sản. Điều đó nói rằng, trong một trò chơi chiến đấu giống như SF2, bạn có thể chỉ có hai họa tiết;)

  • như đã đề cập ở nơi khác, bất cứ khi nào bạn muốn thay đổi API đồ họa của mình, bạn phải thay đổi mã cho tất cả các họa tiết của bạn.

  • kết xuất hiếm khi được thực hiện mà không tham chiếu đến một số bối cảnh đồ họa. Vì vậy, có một biến toàn cục đại diện cho khái niệm này hoặc mỗi sprite có một giao diện với kết xuất (GraphicalContext ctx). Điều này trộn lẫn API đồ họa và logic của trò chơi của bạn (mà một số người sẽ thấy không phù hợp) và có thể gây ra sự cố biên dịch.

  • Tôi cá nhân thấy rằng tách biệt kết xuất khỏi các thực thể riêng lẻ là bước đầu tiên thú vị theo hướng xem trò chơi của bạn như một hệ thống hoàn toàn không cần đồ họa. Ý tôi là khi bạn đưa ra kết xuất, bạn sẽ nhận ra rất nhiều trò chơi xảy ra trong một "thế giới phi đồ họa" trong đó tọa độ của các thực thể, trạng thái bên trong của chúng, v.v ... mới là vấn đề. Điều này mở ra cánh cửa để thử nghiệm tự động, hệ thống tách rời hơn, v.v ...

Nói chung, tôi có xu hướng thích các hệ thống trong đó việc kết xuất được thực hiện bởi một lớp riêng biệt. Điều đó không có nghĩa là các họa tiết của bạn không thể có một số thuộc tính "liên quan đến đồ họa" (tên hoạt hình, khung hình động, chiều cao x chiều rộng, id sprite, v.v.), nếu điều đó làm cho trình kết xuất dễ viết hơn hoặc hiệu quả hơn.

Và tôi không biết điều đó có áp dụng cho 3D hay không (trong đó khái niệm về các mắt lưới và biến tọa độ bạn sẽ sử dụng có thể được gắn với API 3D của bạn; trong khi x, y, h, w khá độc lập với bất kỳ 2D nào API).

Hy vọng điều này sẽ giúp.


11

Bạn muốn hệ thống kết xuất kiểm soát những gì được vẽ khi nào. Nếu thay vào đó, các họa tiết nằm trong tầm kiểm soát của kết xuất, bạn sẽ mất rất nhiều hiệu quả và tính linh hoạt. Tôi cho rằng việc kiểm soát hệ thống render sẽ dẫn đến mã sạch hơn.

Một số lợi thế của kết xuất tập trung:

  • z-order:
    Nếu chính các đối tượng trò chơi chịu trách nhiệm hiển thị, bạn phải đảm bảo rằng bạn gọi chúng theo đúng thứ tự. Mặt khác, các đối tượng nền có thể được vẽ trên các đối tượng nền trước.
    Với hệ thống kết xuất được kiểm soát, nó có thể chọn sắp xếp tất cả các đối tượng kết xuất, phát hiện các lớp phủ trong thời gian kết xuất và chỉ hiển thị các đối tượng đó hoặc chỉ từ bỏ thứ tự tất cả cùng nhau. Vấn đề là quyết định có thể được đưa ra dễ dàng ngay bây giờ.
  • tạo khối:
    Ưu điểm rõ ràng khác của việc cho phép hệ thống kết xuất được kiểm soát là tạo khối. Ở đây một lần nữa, hệ thống kết xuất phải tùy chọn để sprite hàng loạt kết xuất chia sẻ một kết cấu. Nó có thể sử dụng tam giác cắt để kết xuất mọi thứ với một cuộc gọi. Nó có thể lưu trữ một số tính toán kết xuất. Hoặc nó chỉ có thể hiển thị lần lượt từng sprite mà không có thứ gì lạ mắt đó. (Lưu ý: có thể có lô khi mỗi đối tượng tự hiển thị, nhưng vấn đề kém hiệu quả và phức tạp hơn).

Cách tôi thực hiện điều này trong các trò chơi của mình để các đối tượng trò chơi đăng ký các họa tiết mà chúng muốn vẽ bằng hệ thống kết xuất. Khi đối tượng không còn muốn đối tượng được vẽ, nó hủy đăng ký sprite hoặc đánh dấu nó không hoạt động.

Tất cả những gì đã nói. Nếu nó dễ dàng hơn để các đối tượng trò chơi của bạn tự hiển thị bằng mọi cách hãy làm theo cách đó. Điều quan trọng hơn nhiều để đạt được tiến bộ và có được một cái gì đó / bất cứ thứ gì được vẽ hơn là để có một kiến ​​trúc hoàn hảo.


Về thứ tự z nếu các đối tượng tự vẽ không thể một hệ thống quyết định về thứ tự gọi phương thức vẽ của chúng? Tôi có nghĩa là tập trung so với không tập trung dường như không có sự khác biệt về thứ tự z.
GorillaApe

3

Tuyên bố miễn trừ trách nhiệm: câu hỏi của bạn không cung cấp nhiều chi tiết vì vậy tôi trả lời theo nguyên tắc chung. Xin thứ lỗi cho tôi nếu tôi hiểu nhầm cách sử dụng của bạn hoặc 'kết xuất'.

Tôi thường sử dụng một đối tượng bên ngoài để hiển thị các diễn viên khác nhau trong một cảnh như một cách gói gọn các thuộc tính và phương thức mức cảnh bên ngoài các 'đối tượng diễn viên' riêng lẻ. Các đối tượng trong cảnh chỉ nên chứa các phương thức và thuộc tính bên trong; họ chỉ nên biết về bản thân họ là gì và họ làm gì. Có lẽ, chúng sẽ bị ảnh hưởng bởi các đối tượng khác trong trò chơi cũng như đầu vào của người dùng. Điều này sẽ ảnh hưởng đến cách / liệu chúng được hiển thị trên màn hình. Ví dụ, một 'đối tượng đạo diễn' có thể dịch phím nhấn 'w' để nhảy, sau đó nói với đối tượng diễn viên .jump (). Logic cấp đạo diễn như vậy cũng có thể yêu cầu các diễn viên nhập hoặc thoát hoàn toàn cảnh.

Chúc mừng, David


Nhưng theo nghĩa đó, đạo diễn không thể chỉ nói acton-> setVisible (false); ?
jmasterx

Ngay cả trong trường hợp setVisible (false), đó là một thực thể bên ngoài thực hiện kết xuất bằng cách kiểm tra biến hiển thị của diễn viên và chỉ hiển thị nó nếu nó đúng.
Nav

Chỉ làm cho một diễn viên vô hình không loại bỏ nó khỏi cảnh. Nó cũng phải ngừng tham gia vào các vụ va chạm, v.v.
Finnw

3

Điều gì sẽ xảy ra nếu một ngày nào đó bạn muốn chuyển trò chơi của mình sang một độ phân giải khác (ví dụ: iPhone và bạn bè). Vì vậy, một thuộc tính toàn cầu về kết xuất thay đổi, làm thế nào để bạn dễ dàng cập nhật mã của mình?


3

Những gì tôi đã sử dụng là một thiết kế dựa trên người quan sát. Khi tôi tạo một thể hiện của một lớp mà tôi muốn kết xuất, thì một con trỏ tới nó được lưu trữ trong lớp Renderer trung tâm. Khi bạn gọi RenderFrame(), thì trình kết xuất đã có tất cả các đối tượng hiện có mà nó cần để kết xuất và truy cập các thuộc tính của chúng để thực hiện. Bản thân các lớp không có ý tưởng rằng chúng sẽ được kết xuất. API này rất hay, sạch sẽ và dễ sử dụng.


1
+1 Thú vị. Tôi đã sử dụng phương pháp này cho âm thanh trong khi sử dụng Mẫu khách truy cập cho đồ họa. Tôi nghĩ rằng điều này có ý nghĩa hơn đối với âm thanh bởi vì trong khi đồ họa và AI đang chạy trên cùng một đồng hồ, bộ trộn âm thanh đang chạy trên một cái khác nên một mô hình sự kiện dễ dàng hơn. Ngoài ra, nó không quan trọng nếu một sự kiện chuyển động (làm cho pan / Reverb của kênh âm thanh thay đổi) đến muộn vài mili giây nhưng rất quan trọng nếu một sprite được vẽ ở trạng thái sai.
vây

2

Nói chung, luôn luôn dễ dàng để duy trì và mở rộng mã của bạn. Ngày mai bạn phát hiện ra rằng bạn không thích API đồ họa hiện đang sử dụng và muốn chuyển đổi. Bây giờ bạn sẽ phải trải qua tất cả các lớp đối tượng của mình và thay đổi mọi thứ, hay bạn vẫn chỉ cần thay đổi mã của mình trong một điểm trung tâm của dự án?

Nó phụ thuộc vào những gì đối tượng của bạn đang thực sự làm khi bạn gọi render (). Miễn là họ chỉ gọi các phương thức gọi xung quanh công cụ đồ họa của bạn, điều đó hoàn toàn tốt, vì logic <-> phân biệt đồ họa sẽ vẫn được đưa ra.

Ví dụ: nếu các phương thức render () của bạn về cơ bản là các phương thức tiện lợi và trông giống như thế này:

void MyClass::render(const Graphics &g)
{
    g.draw(this);
}

hoặc là

void MyClass::render()
{
   mySprite->render();
}

hoặc là

void MyClass::render()
{
    mySprite->UseShader(thatshader);
    mySprite->render();
}

hoặc gần như vậy, tôi không nghĩ đó là vấn đề gì.

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.