Nhược điểm của việc sử dụng DrawableGameComponent cho mọi phiên bản của một đối tượng trò chơi là gì?


25

Tôi đã đọc ở nhiều nơi rằng DrawableGameComponents nên được lưu cho những thứ như "cấp độ" hoặc một số loại người quản lý thay vì sử dụng chúng, ví dụ, cho các ký tự hoặc gạch (Giống như anh chàng này nói ở đây ). Nhưng tôi không hiểu tại sao lại như vậy. Tôi đọc bài đăng này và nó rất có ý nghĩa với tôi, nhưng đây là thiểu số.

Tôi thường không chú ý quá nhiều đến những thứ như thế này, nhưng trong trường hợp này tôi muốn biết tại sao đa số rõ ràng tin rằng đây không phải là con đường để đi. Có lẽ tôi đang thiếu một cái gì đó.


Tôi tò mò tại sao, hai năm sau, bạn đã xóa dấu "được chấp nhận" khỏi câu trả lời của tôi ? Thông thường tôi sẽ không thực sự quan tâm - nhưng trong trường hợp này, điều đó gây ra sự xuyên tạc bực bội của VeraShackle về câu trả lời của tôi để bong bóng lên đầu :(
Andrew Russell

@AndrewRussell Tôi đã đọc chủ đề này cách đây không lâu (do một số phản hồi và phiếu bầu) và nghĩ rằng tôi không đủ điều kiện để đưa ra ý kiến ​​về việc câu trả lời của bạn có đúng hay không. Tuy nhiên, như bạn nói, tôi không nghĩ câu trả lời của VeraShackle phải là câu trả lời nhiều nhất, vì vậy tôi đánh dấu câu trả lời của bạn là chính xác một lần nữa.
Kenji Kina

1
Tôi có thể cô đọng câu trả lời của mình ở đây như sau: " Sử dụng DrawableGameComponentkhóa bạn vào một tập hợp các chữ ký phương thức và một mô hình dữ liệu được giữ lại cụ thể. Đây thường là những lựa chọn sai lầm ban đầu và việc khóa trong đó cản trở đáng kể sự phát triển của mã trong tương lai. "Nhưng hãy để tôi nói cho bạn biết những gì đang xảy ra ở đây ...
Andrew Russell

1
DrawableGameComponentlà một phần của API XNA cốt lõi (một lần nữa: chủ yếu là vì lý do lịch sử). Các lập trình viên Novice sử dụng nó bởi vì nó "ở đó" và nó "hoạt động" và họ không biết gì hơn. Họ thấy câu trả lời của tôi nói với họ rằng họ " sai " và - do bản chất của tâm lý con người - từ chối điều đó và chọn "bên" khác. Điều xảy ra là câu trả lời không trả lời của VeraShackle; điều đó đã xảy ra để lấy đà vì tôi đã không gọi nó ngay lập tức (xem những bình luận đó). Tôi cảm thấy rằng sự phản bác cuối cùng của tôi vẫn còn đủ.
Andrew Russell

1
Nếu bất cứ ai quan tâm đến việc đặt câu hỏi về tính hợp pháp của câu trả lời của tôi trên cơ sở upvotes: trong khi nó là sự thật rằng (GDSE là aflush với người mới nói trên) câu trả lời VeraShackle đã quản lý để có được một cặp vợ chồng hơn upvotes hơn tôi trong những năm gần đây, đừng quên rằng tôi có thêm hàng ngàn lượt nâng cấp trên toàn mạng, chủ yếu là trên XNA. Tôi đã triển khai API XNA trên nhiều nền tảng. Và tôi là một nhà phát triển trò chơi chuyên nghiệp sử dụng XNA. Phả hệ của câu trả lời của tôi là hoàn hảo.
Andrew Russell

Câu trả lời:


22

"Các thành phần trò chơi" là một phần rất sớm của thiết kế XNA 1.0. Chúng được cho là hoạt động giống như các điều khiển cho WinForms. Ý tưởng là bạn sẽ có thể kéo và thả chúng vào trò chơi của mình bằng GUI (giống như bit để thêm các điều khiển không trực quan, như bộ hẹn giờ, v.v.) và đặt thuộc tính cho chúng.

Vì vậy, bạn có thể có các thành phần như có thể là Máy ảnh hoặc ... bộ đếm FPS? ... hoặc ...?

Bạn thấy không? Thật không may, ý tưởng này không thực sự hiệu quả với các trò chơi trong thế giới thực. Loại thành phần bạn muốn cho trò chơi không thực sự có thể tái sử dụng. Bạn có thể có thành phần "người chơi", nhưng nó sẽ rất khác với thành phần "người chơi" của mọi trò chơi khác.

Tôi tưởng tượng rằng đó là vì lý do này và vì thiếu thời gian đơn giản, GUI đã được kéo trước XNA 1.0.

Nhưng API vẫn có thể sử dụng được ... Đây là lý do tại sao bạn không nên sử dụng nó:

Về cơ bản, nó thuộc về những gì dễ nhất để viết, đọc và gỡ lỗi và duy trì như một nhà phát triển trò chơi. Làm một cái gì đó như thế này trong mã tải của bạn:

player.DrawOrder = 100;
enemy.DrawOrder = 200;

Rõ ràng hơn nhiều so với chỉ đơn giản là làm điều này:

virtual void Draw(GameTime gameTime)
{
    player.Draw();
    enemy.Draw();
}

Đặc biệt là khi, trong một trò chơi trong thế giới thực, bạn có thể kết thúc với một thứ như thế này:

GraphicsDevice.Viewport = cameraOne.Viewport;
player.Draw(cameraOne, spriteBatch);
enemy.Draw(cameraOne, spriteBatch);

GraphicsDevice.Viewport = cameraTwo.Viewport;
player.Draw(cameraTwo, spriteBatch);
enemy.Draw(cameraTwo, spriteBatch);

(Phải thừa nhận rằng bạn có thể chia sẻ máy ảnh và spriteBatch bằng Serviceskiến trúc tương tự . Nhưng đó cũng là một ý tưởng tồi vì nhiều lý do tương tự.)

Kiến trúc này - hoặc thiếu nó - có trọng lượng nhẹ và linh hoạt hơn rất nhiều!

Tôi có thể dễ dàng thay đổi thứ tự vẽ hoặc thêm nhiều chế độ xem hoặc thêm hiệu ứng đích hiển thị, chỉ bằng cách thay đổi một vài dòng. Để làm điều đó trong hệ thống khác đòi hỏi tôi phải suy nghĩ về những gì tất cả các thành phần đó - trải rộng trên nhiều tệp - đang làm và theo thứ tự nào.

Nó giống như sự khác biệt giữa lập trình khai báo và lập trình mệnh lệnh. Nó chỉ ra rằng, để phát triển trò chơi, lập trình mệnh lệnh được ưa thích hơn nhiều.


2
Tôi có ấn tượng rằng họ dành cho lập trình dựa trên Thành phần , dường như được sử dụng rộng rãi cho lập trình trò chơi.
BlueRaja - Daniel Pflughoeft

3
Các lớp thành phần trò chơi XNA không thực sự áp dụng trực tiếp cho mẫu đó. Mô hình đó là tất cả về việc kết hợp các đối tượng trong nhiều thành phần. Các lớp XNA được hướng đến một thành phần trên mỗi đối tượng. Nếu chúng phù hợp hoàn hảo trong thiết kế của bạn, thì bằng mọi cách hãy sử dụng chúng. Nhưng bạn không nên xây dựng thiết kế của bạn xung quanh họ! Xem thêm câu trả lời của tôi ở đây - xem ra nơi tôi đề cập DrawableGameComponent.
Andrew Russell

1
Tôi đồng ý rằng kiến ​​trúc GameComponent / Service không hữu ích và nghe có vẻ giống như các khái niệm ứng dụng web hoặc ứng dụng web bị ép buộc vào khung trò chơi. Nhưng tôi rất thích sử dụng player.DrawOrder = 100;phương pháp trên mệnh lệnh bắt buộc để rút thăm. Tôi đang hoàn thành một trò chơi Flixel ngay bây giờ, nó vẽ các đối tượng theo thứ tự mà bạn thêm chúng vào cảnh. Hệ thống Flxgroup giảm bớt một số điều này, nhưng có một số loại sắp xếp chỉ mục Z được tích hợp sẽ rất tốt.
michael.bartnett

@ michael.bartnett Lưu ý rằng Flixel là API chế độ giữ lại, trong khi XNA (ngoại trừ, rõ ràng, hệ thống thành phần trò chơi) là API chế độ tức thời. Nếu bạn sử dụng API chế độ giữ lại hoặc tự triển khai , khả năng thay đổi thứ tự bốc thăm là rất quan trọng. Trong thực tế, sự cần thiết phải thay đổi thứ tự bốc thăm là một lý do chính đáng để làm cho một cái gì đó giữ lại chế độ (ví dụ về một hệ thống cửa sổ xuất hiện trong tâm trí). Nhưng nếu bạn có thể viết một cái gì đó ở chế độ tức thời, nếu API nền tảng (như XNA) được xây dựng theo cách đó, thì IMO bạn nên làm.
Andrew Russell


26

Hừm. Tôi đã thách thức điều này vì một chút cân bằng ở đây tôi sợ.

Dường như có 5 khoản phí trong câu trả lời của Andrew, vì vậy tôi sẽ thử và giải quyết lần lượt từng khoản phí:

1) Các thành phần là một thiết kế lỗi thời và bị bỏ rơi.

Ý tưởng về mẫu thiết kế các thành phần đã tồn tại từ lâu trước XNA - về bản chất, đó chỉ đơn giản là một quyết định tạo ra các đối tượng, chứ không phải là đối tượng trò chơi quá cong, ngôi nhà của hành vi Cập nhật và Vẽ của chính họ. Đối với các đối tượng trong bộ sưu tập thành phần của nó, trò chơi sẽ tự động gọi các phương thức này (và một vài phương thức khác) vào thời điểm thích hợp - đặc biệt là đối tượng trò chơi không phải tự 'biết' bất kỳ mã nào trong số này. Nếu bạn muốn sử dụng lại các lớp trò chơi của mình trong các trò chơi khác nhau (và do đó là các đối tượng Trò chơi khác nhau), việc hủy ghép các đối tượng này về cơ bản vẫn là một ý tưởng tốt. Một cái nhìn nhanh về các bản demo mới nhất (được sản xuất chuyên nghiệp) của XNA4.0 từ AppHub xác nhận ấn tượng của tôi rằng Microsoft vẫn (hoàn toàn đúng theo quan điểm của tôi) chắc chắn đứng sau bản này.

2) Andrew không thể nghĩ ra hơn 2 lớp trò chơi có thể sử dụng lại.

Tôi có thể. Trong thực tế tôi có thể nghĩ về tải! Tôi vừa kiểm tra lib được chia sẻ hiện tại của tôi và nó bao gồm hơn 80 có thể sử dụng lại thành phần và dịch vụ . Để cung cấp cho bạn một hương vị, bạn có thể có:

  • Nhà quản lý trò chơi / màn hình
  • Hạt
  • Nguyên thủy có thể vẽ
  • Bộ điều khiển AI
  • Bộ điều khiển đầu vào
  • Bộ điều khiển hoạt hình
  • Biển quảng cáo
  • Quản lý Vật lý & Va chạm
  • Máy ảnh

Bất kỳ ý tưởng trò chơi cụ thể nào cũng sẽ cần ít nhất 5-10 thứ từ bộ này - được đảm bảo - và chúng có thể có đầy đủ chức năng trong một trò chơi hoàn toàn mới với một dòng mã.

3) Kiểm soát thứ tự vẽ theo thứ tự các lệnh gọi rõ ràng có thể sử dụng thuộc tính DrawOrder của thành phần.

Vâng, về cơ bản, tôi đồng ý với Andrew về điều này. NHƯNG, nếu bạn để tất cả các thuộc tính DrawOrder của thành phần làm mặc định, bạn vẫn có thể kiểm soát rõ ràng thứ tự vẽ của chúng theo thứ tự bạn thêm chúng vào bộ sưu tập. Điều này thực sự giống hệt nhau về các thuật ngữ 'khả năng hiển thị' để sắp xếp rõ ràng các cuộc gọi vẽ thủ công của họ.

4) Tự gọi một tải các phương thức Vẽ của đối tượng là 'nhẹ' hơn so với việc gọi chúng bằng phương thức khung hiện có.

Tại sao? Thêm vào đó, trong tất cả các dự án tầm thường nhất, logic Cập nhật và mã Draw của bạn sẽ hoàn toàn làm lu mờ phương thức gọi phương thức của bạn về mặt hiệu suất đạt được trong mọi trường hợp.

5) Đặt mã của bạn vào một tệp là thích hợp hơn, khi gỡ lỗi, hơn là đặt mã trong tệp của đối tượng riêng lẻ.

Chà, trước tiên, khi tôi gỡ lỗi trong Visual Studio, vị trí của một điểm dừng về các tệp trên đĩa gần như vô hình ngày nay - IDE xử lý vị trí mà không có bất kỳ bộ phim truyền hình nào. Nhưng cũng nên cân nhắc một chút rằng bạn có vấn đề với bản vẽ Skybox của mình. Có phải việc sử dụng phương thức Draw của Skybox thực sự gây khó chịu hơn so với việc định vị mã vẽ của skybox trong phương thức vẽ chính (có lẽ rất dài) trong đối tượng Trò chơi? Không, thực sự không - thực tế tôi sẽ lập luận rằng nó hoàn toàn ngược lại.

Vì vậy, tóm lại - xin hãy xem xét kỹ các tranh luận của Andrew ở đây. Tôi không tin rằng họ thực sự đưa ra những căn cứ đáng kể để viết mã trò chơi vướng mắc. Các mặt trái của mẫu thành phần tách rời (được sử dụng một cách thận trọng) là rất lớn.


2
Tôi chỉ nhận thấy bài đăng này, và tôi phải đưa ra phản bác mạnh mẽ: Tôi không có vấn đề gì với các lớp có thể tái sử dụng! (Có thể có các phương thức vẽ và cập nhật, v.v.) Tôi đang gặp vấn đề cụ thể với việc sử dụng ( Drawable) GameComponentđể cung cấp kiến ​​trúc trò chơi của bạn, do mất kiểm soát rõ ràng đối với thứ tự vẽ / cập nhật (mà bạn đồng ý với # 3) về độ cứng giao diện của họ (mà bạn không giải quyết).
Andrew Russell

1
Quan điểm số 4 của bạn sử dụng từ "nhẹ" của tôi để chỉ hiệu suất, trong đó tôi thực sự có nghĩa là linh hoạt về kiến ​​trúc. Các điểm còn lại của bạn # 1, # 2 và đặc biệt là # 5 dường như dựng lên người rơm vô lý mà tôi nghĩ rằng hầu hết / tất cả các mã nên được đưa vào lớp trò chơi chính của bạn! Đọc câu trả lời của tôi ở đây để biết một số suy nghĩ chi tiết hơn của tôi về kiến ​​trúc.
Andrew Russell

5
Cuối cùng: nếu bạn định gửi phản hồi cho câu trả lời của tôi, nói rằng tôi sai, thì cũng nên lịch sự thêm câu trả lời cho câu trả lời của tôi để tôi sẽ thấy một thông báo về nó, thay vì phải vấp ngã nó hai tháng sau
Andrew Russell

Tôi có thể đã hiểu lầm, nhưng làm thế nào điều này trả lời câu hỏi? Tôi có nên sử dụng GameComponent cho các họa tiết của mình hay không?
Tuyệt vời nhất


4

Tôi không đồng ý một chút với Andrew, nhưng tôi cũng nghĩ rằng có một thời gian và địa điểm cho mọi thứ. Tôi sẽ không sử dụng một Drawable(GameComponent)thứ đơn giản như Sprite hay Enemy. Tuy nhiên, tôi sẽ sử dụng nó cho một SpriteManagerhoặc EnemyManager.

Quay trở lại với những gì Andrew nói về vẽ và cập nhật thứ tự, tôi nghĩ Sprite.DrawOrdersẽ rất khó hiểu cho nhiều họa tiết. Hơn nữa, nó tương đối dễ dàng để thiết lập một DrawOrderUpdateOrdercho một lượng nhỏ Người quản lý (hoặc hợp lý) (Drawable)GameComponents.

Tôi nghĩ rằng Microsoft sẽ loại bỏ chúng nếu chúng thực sự cứng nhắc và không ai sử dụng chúng. Nhưng họ đã không làm việc bởi vì họ làm việc hoàn toàn tốt, nếu vai trò là đúng. Bản thân tôi sử dụng chúng để phát triển Game.Servicesđược cập nhật trong nền.


2

Tôi cũng đã suy nghĩ về điều này và nó đã xảy ra với tôi: Chẳng hạn, để lấy cắp ví dụ trong liên kết của bạn, trong một trò chơi RTS, bạn có thể biến mọi đơn vị thành một ví dụ thành phần trò chơi. Đuợc.

Nhưng bạn cũng có thể tạo một thành phần UnitManager, giữ một danh sách các đơn vị, vẽ và cập nhật chúng khi cần thiết. Tôi đoán lý do bạn muốn biến các đơn vị của mình thành các thành phần trò chơi ngay từ đầu là để ngăn chặn mã, vậy giải pháp này có đạt được mục tiêu đó không?


2

Trong các bình luận, tôi đã đăng một phiên bản cô đọng cho câu trả lời cũ của mình:

Sử dụng DrawableGameComponentkhóa bạn vào một tập hợp các chữ ký phương thức và một mô hình dữ liệu được giữ lại cụ thể. Đây thường là sự lựa chọn sai lầm ban đầu và khóa trong gây cản trở đáng kể cho sự phát triển của mã trong tương lai.

Ở đây tôi sẽ cố gắng minh họa tại sao lại như vậy bằng cách đăng một số mã từ dự án hiện tại của tôi.


Đối tượng gốc duy trì trạng thái của thế giới trò chơi có một Updatephương thức giống như sau:

void Update(UpdateContext updateContext, MultiInputState currentInput)

Có một số điểm vào Update, tùy thuộc vào việc trò chơi có chạy trên mạng hay không. Chẳng hạn, có thể cho trạng thái trò chơi được quay ngược về thời điểm trước đó và sau đó được mô phỏng lại.

Ngoài ra còn có một số phương pháp giống như cập nhật bổ sung, như:

void PlayerJoin(int playerIndex, string playerName, UpdateContext updateContext)

Trong trạng thái trò chơi, có một danh sách các diễn viên sẽ được cập nhật. Nhưng điều này không chỉ đơn giảnUpdate cuộc gọi . Có thêm chuyền trước và sau để xử lý vật lý. Ngoài ra còn có một số công cụ ưa thích để trì hoãn sinh sản / tiêu diệt các diễn viên, cũng như chuyển đổi cấp độ.

Bên ngoài trạng thái trò chơi, có một hệ thống UI cần được quản lý độc lập. Nhưng một số màn hình trong UI cũng cần có khả năng chạy trong ngữ cảnh mạng.


Để vẽ, vì bản chất của trò chơi, có một hệ thống sắp xếp và loại bỏ tùy chỉnh lấy đầu vào từ các phương thức sau:

virtual void RegisterToDraw(SortedDrawList sortedDrawList, Definitions definitions)
virtual void RegisterShadow(ShadowCasterList shadowCasterList, Definitions definitions)

Và sau đó, khi nó tìm ra những gì cần vẽ, sẽ tự động gọi:

virtual void Draw(DrawContext drawContext, int tag)

Các tag tham số là cần thiết vì một số diễn viên có thể giữ được các diễn viên khác - và do đó nhu cầu để có thể vẽ cả trên và dưới diễn viên được tổ chức. Hệ thống phân loại đảm bảo rằng điều này xảy ra theo đúng thứ tự.

Ngoài ra còn có hệ thống menu để vẽ. Và một hệ thống phân cấp để vẽ UI, xung quanh HUD, xung quanh trò chơi.


Bây giờ so sánh các yêu cầu đó với những gì DrawableGameComponentcung cấp:

public class DrawableGameComponent
{
    public virtual void Update(GameTime gameTime);
    public virtual void Draw(GameTime gameTime);
    public int UpdateOrder { get; set; }
    public int DrawOrder { get; set; }
}

Không có cách hợp lý để có được từ một hệ thống sử dụng DrawableGameComponentđến hệ thống mà tôi đã mô tả ở trên. (Và đó không phải là những yêu cầu bất thường đối với một trò chơi có độ phức tạp thậm chí khiêm tốn).

Ngoài ra, điều rất quan trọng cần lưu ý là những yêu cầu đó không chỉ đơn giản là khởi động khi bắt đầu dự án. Họ đã phát triển qua nhiều tháng làm việc phát triển.


Những gì mọi người thường làm, nếu họ bắt đầu DrawableGameComponenttuyến đường, là họ bắt đầu xây dựng trên các bản hack:

  • Thay vì thêm các phương thức, họ thực hiện một số phương pháp đúc xấu xí cho loại cơ sở của riêng họ (tại sao không sử dụng trực tiếp?).

  • Thay vì thay thế mã để sắp xếp và gọi Draw/ Update, họ thực hiện một số điều rất chậm để thay đổi số thứ tự đang hoạt động.

  • Và điều tồi tệ nhất: Thay vì thêm các tham số vào các phương thức, chúng bắt đầu "truyền" "tham số" vào các vị trí bộ nhớ không phải là ngăn xếp (việc sử dụng Servicesnày là phổ biến). Điều này là phức tạp, dễ bị lỗi, chậm, dễ vỡ, hiếm khi an toàn luồng và có khả năng trở thành vấn đề nếu bạn thêm mạng, tạo các công cụ bên ngoài, v.v.

    Nó cũng làm cho mã sử dụng lại khó hơn , vì bây giờ các phụ thuộc của bạn được ẩn bên trong "thành phần", thay vì được xuất bản ở ranh giới API.

  • Hoặc, họ gần như thấy tất cả những điều này điên rồ đến mức nào, và bắt đầu làm "người quản lý" DrawableGameComponentđể giải quyết những vấn đề này. Ngoại trừ họ vẫn có những vấn đề này ở ranh giới "người quản lý".

    Luôn luôn có thể dễ dàng thay thế các "người quản lý" này bằng một loạt các lệnh gọi phương thức theo thứ tự mong muốn. Bất cứ điều gì khác là quá phức tạp.

Tất nhiên, một khi bạn bắt đầu sử dụng những bản hack đó, thì sẽ mất công thực sự để hoàn tác những bản hack đó một khi bạn nhận ra mình cần nhiều hơn những gì DrawableGameComponentcung cấp. Bạn trở nên " bị nhốt ". Và sự cám dỗ thường là tiếp tục chồng chất lên các bản hack - điều này trong thực tế sẽ làm bạn chán nản và hạn chế các loại trò chơi bạn có thể làm cho những trò chơi tương đối đơn giản.


Rất nhiều người dường như đạt đến điểm này và có phản ứng nội tạng - có thể vì họ sử dụng DrawableGameComponentvà không muốn chấp nhận là "sai". Vì vậy, họ chấp nhận thực tế rằng ít nhất có thể làm cho nó "hoạt động".

Tất nhiên nó có thể được thực hiện để "làm việc"! Chúng tôi là lập trình viên - làm cho mọi thứ hoạt động dưới sự hạn chế bất thường thực tế là công việc của chúng tôi. Nhưng sự hạn chế này là không cần thiết, hữu ích hoặc hợp lý ...


Có gì đặc biệt flabbergasting về là nó là đáng kinh ngạc tầm thường sang một bên bước toàn bộ vấn đề này. Ở đây, tôi thậm chí sẽ cung cấp cho bạn mã:

public class Actor
{
    public virtual void Update(GameTime gameTime);
    public virtual void Draw(GameTime gameTime);
}

List<Actor> actors = new List<Actor>();

foreach(var actor in actors)
    actor.Update(gameTime);

foreach(var actor in actors)
    actor.Draw(gameTime);

(Thật đơn giản để thêm vào sắp xếp theo DrawOrderUpdateOrder. Một cách đơn giản là duy trì hai danh sách và sử dụng List<T>.Sort(). Nó cũng không quan trọng để xử lý Load/ UnloadContent.)

Nó không quan trọng mã đó thực sự là gì . Điều quan trọng là tôi có thể sửa đổi nó một cách tầm thường .

Khi tôi nhận ra rằng tôi cần một hệ thống thời gian khác gameTimehoặc tôi cần thêm tham số (hoặc toàn bộ UpdateContextđối tượng có khoảng 15 thứ trong đó) hoặc tôi cần một thứ tự hoạt động hoàn toàn khác để vẽ hoặc tôi cần một số phương thức bổ sung Đối với các bản cập nhật khác nhau, tôi có thể tiếp tục và làm điều đó .

Và tôi có thể làm điều đó ngay lập tức. Tôi không cần phải cố gắng chọn DrawableGameComponentra mã của mình. Hoặc tệ hơn: hack nó theo một cách nào đó sẽ khiến nó trở nên khó khăn hơn vào lần tới khi có nhu cầu như vậy xuất hiện.


Thực sự chỉ có một kịch bản mà nó là một lựa chọn tốt để sử dụng DrawableGameComponent: và đó là nếu bạn thực sự tạo và xuất bản phần mềm trung gian kiểu kéo và thả thành phần cho XNA. Đó là mục đích ban đầu của nó. Mà - tôi sẽ thêm - không ai đang làm!

(Tương tự, nó chỉ thực sự có ý nghĩaServices khi sử dụng khi tạo các loại nội dung tùy chỉnh cho ContentManager.)


Mặc dù tôi đồng ý với quan điểm của bạn, tôi cũng không thấy có gì đặc biệt sai khi sử dụng những thứ thừa hưởng từ DrawableGameComponentmột số thành phần nhất định, đặc biệt là đối với những thứ như màn hình menu (menu, nhiều nút, tùy chọn và nội dung) hoặc lớp phủ FPS / gỡ lỗi bạn đã đề cập Trong những trường hợp này, bạn thường không cần kiểm soát chi tiết tốt đối với lệnh rút thăm và bạn kết thúc với ít mã hơn bạn cần phải viết thủ công (đó là một điều tốt, trừ khi bạn cần viết mã đó). Nhưng tôi đoán đó là khá nhiều kịch bản kéo và thả mà bạn đang đề cập.
Groo
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.