Các câu hỏi liên quan đến kiến ​​trúc trò chơi với XNA


12

Vì vậy, cuối cùng tôi cũng đã chơi xung quanh với XNA và đã chơi đùa với việc tạo ra một trò chơi 2D (Tôi có một loạt tài sản nghệ thuật từ một người bạn đã phát triển nó trên iOS)

Rất nhiều thứ có vẻ dễ thực hiện và được đưa ra khỏi hộp tuy nhiên tôi bị vấp ngã vì một đống thứ vì hầu hết các tài liệu (ví dụ như những cuốn sách tôi đã mua) không quá chú ý đến 2D.

Tôi thực sự đánh giá cao bất kỳ sự làm rõ hoặc được chỉ ra thêm thông tin về các nhiệm vụ sau:

  1. Điểm của một dịch vụ trò chơi là gì? Tôi hiểu toàn bộ thành ngữ của việc đăng ký một đối tượng là một dịch vụ để bất kỳ GameComponent nào khác có thể lấy nó, tuy nhiên làm thế nào để đánh bại nó chỉ đơn giản là làm cho nó có thể công khai hoặc tĩnh? Chẳng hạn, cuốn sách của tôi khuyên bạn nên đăng ký đối tượng SpriteBatch trong lớp Game.cs. Tôi không chắc làm thế nào điều này có thể thích hợp hơn khi chỉ đơn giản là đặt nó ở chế độ công khai / tĩnh vì chỉ nên có một phiên bản của Game anyways (singleton)?

  2. Tôi bối rối khi tôi nên kế thừa từ GameComponent hoặc RenderableGameComponent. Tôi đang cố gắng tuân theo thiết kế Trình quản lý / Trình điều khiển, sao cho tất cả các thực thể được tạo / sở hữu bởi một người quản lý duy nhất và tương tự cho những thứ khác. Hiện tại tôi có mỗi Trình quản lý / Trình điều khiển kế thừa từ GameComponent, tuy nhiên làm thế nào để đánh bại đối tượng Game sở hữu tất cả các Người quản lý và gọi cập nhật thủ công cho họ và rút ra?

  3. Tôi nhận thấy rằng Khởi tạo được gọi trước ContentLoad (), tôi thấy điều này gây phiền nhiễu vì trong Khởi tạo của tôi là nơi tôi muốn tạo một số thực thể của mình (ví dụ: Sprite, Player, v.v.), tuy nhiên tôi không thể cung cấp cho chúng tải SpriteSheets hoặc Textures kể từ khi cuộc gọi tải chúng chưa xảy ra. Có lẽ tôi đang khởi tạo không chính xác hoặc mọi người chỉ gán kết cấu xuống trong ContentLoad?

Chúng dường như là " WTF " lớn nhất của tôi không thực sự hiểu

Câu trả lời:


11

Câu trả lời cho câu hỏi của bạn chỉ đơn giản là: Làm bất cứ việc gì. Lý tưởng nhất là làm những gì đơn giản và làm việc. Thường thì việc sử dụng kiến ​​trúc tích hợp không đơn giản bởi vì, khi bạn đang tìm kiếm, bạn phải nhảy qua các vòng để cấu trúc trò chơi theo cách bạn muốn.

Để trả lời câu hỏi một, tôi sẽ giới thiệu cho bạn câu trả lời của tôi cho câu hỏi "Tại sao nên sử dụng dịch vụ?" . Câu trả lời ngắn gọn là các dịch vụ là một cách tốt để tránh các vấn đề ghép nối (phiên bản, phụ thuộc, mở rộng) mà bạn sẽ không bao giờ gặp phải trong một trò chơi khép kín . Hầu hết thời gian chỉ đơn giản là làm thành viên public(và thậm chí static, nếu bạn đang vội) và lo lắng về các vấn đề thú vị hơn.

Để trả lời câu hỏi thứ hai của bạn, tôi sẽ giới thiệu cho bạn câu trả lời của tôi cho câu hỏi "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ì?" cũng như suy nghĩ của tôi về kiến ​​trúc trò chơi . Câu trả lời ngắn gọn là: không có lợi ích gì khi sử dụng GameComponenthơn chỉ đơn giản là tạo các lớp và phương thức gọi của riêng bạn như DrawUpdatechính bạn. Nếu GameComponentchính xác phù hợp với kiến ​​trúc mong muốn của bạn, bằng mọi cách, hãy sử dụng nó - nhưng hầu như luôn luôn là không.

Sử dụng các dịch vụ và thành phần chỉ thực sự trở nên thú vị nếu bạn xây dựng thư viện cho tiêu dùng của bên thứ ba. XNA tự làm điều này - nó có IGraphicsDeviceServiceGamerServicesComponent, ví dụ. Những điều này đáp ứng các yêu cầu tách riêng cụ thể mà bạn thường không gặp phải khi phát triển trò chơi.

Cuối cùng, câu trả lời cho câu hỏi thứ ba của bạn khá đơn giản: Chỉ cần tạo các thực thể trò chơi của bạn trong LoadContent. Không có gì đặc biệt về Initialize.

Thật đáng để chỉ ra rằng toàn bộ Microsoft.Xna.Framework.Gamelắp ráp là tùy chọn . Nó cung cấp một điểm khởi đầu cực kỳ hữu ích - nhưng không nên coi đó là "cách đúng đắn" để làm mọi việc.


Cách rất thú vị để xem nó. Thực tế hơn nhiều và xuống trái đất hơn câu trả lời của tôi. Rất xứng đáng +1, thưa ông.
Jesse Emond

Tôi có một câu hỏi nữa! Còn về nguồn gốc khi bạn vẽ cho Texture2D. Có phải là phổ biến để đặt nguồn gốc ở giữa dưới cùng của kết cấu? Tôi đang cố gắng làm hoạt hình và tôi thấy việc có nguồn gốc ở (0,0) đang khiến kết cấu thay đổi một chút nếu chiều rộng và chiều cao không giống nhau
Setheron

@Setheron: Bạn thực sự nên tạo một câu hỏi mới - vì điều này khá không liên quan đến câu hỏi ban đầu. Tôi sẽ hoàn nguyên bản chỉnh sửa mà bạn đã thực hiện cho câu hỏi này. Nguồn gốc cho SpriteBatch.Drawđược chỉ định trong tọa độ pixel kết cấu so với góc trên bên trái của kết cấu (hoặc hình chữ nhật nguồn, nếu bạn sử dụng một tọa độ).
Andrew Russell

1
@Andrew: Gần đây tôi đã cấu trúc lại trò chơi của mình để nó hoàn toàn dựa trên các dịch vụ thay vì public/ staticthuộc tính. Tại sao? Khả năng kiểm tra. Gần như không thể chuyển đổi mọi thứ bằng cách tiếp cận thuộc tính, trong khi thật tầm thường nếu mọi thứ được khởi tạo với một IServiceProviderthứ có thể được nhồi bằng bất cứ thứ gì mà lớp cần bằng phương thức thử nghiệm của bạn. Nó cũng tránh sự cần thiết phải khởi tạo Gameđối tượng trong bài kiểm tra của bạn, điều này trở nên lộn xộn rất nhanh.
Matthew Scharley

Bên cạnh, tôi vẫn có nhiều tài sản công khai trên Gameđối tượng. Chúng tình cờ được truy cập thông qua các giao diện được đẩy vào Game.Servicesđó và sau đó được chuyển qua mọi thứ để có được những gì họ cần một lần nữa.
Matthew Scharley

3

Đối với câu hỏi đầu tiên của bạn, tôi phải thừa nhận rằng tôi không thực sự biết câu trả lời thực sự. Tôi đoán nó sẽ có cùng lý do là tại sao singleton nói chung là một mẫu thiết kế tồi. Tôi sẽ giới thiệu cho bạn một trích dẫn từ liên kết này :

Lý do đầu tiên chúng tôi nghĩ đến (và một trong những lý do đằng sau việc giới thiệu dịch vụ) là cung cấp tài liệu tham khảo GraphicsDevice trên một trò chơi. Về cơ bản, chúng tôi đã có Game sở hữu GraphicsDevice và hiển thị thông qua một tài sản như Game.GraphicsDevice. Vấn đề với điều này là điều này đã ràng buộc chặt chẽ GraphicsDevice với Trò chơi, không cho phép người khác sở hữu thiết bị (như trình kết xuất) và ngăn người khác sử dụng GraphicsDevice được cập nhật trong tương lai mà không cung cấp phiên bản Trò chơi mới nào mà không có t tương thích ngược.

Đối với câu hỏi thứ hai của bạn, tôi cho rằng sử dụng các Thành phần như thế này sẽ hữu ích hơn nếu bạn theo một cách tiếp cận dựa trên thành phần thay vào đó, như thể bạn sẽ có một danh sách các Spritethành phần sẽ biết cách vẽ và tự cập nhật thay vì người quản lý biết cách cập nhật và vẽ mọi sprite. Tôi đồng ý, nó có vẻ giống nhau nhưng tôi thích một thiết kế dựa trên thành phần bởi vì tôi thực sự thích cách tiếp cận hướng đối tượng mà nó có.

Đối với câu hỏi thứ ba của bạn, có, bạn nên tải bất kỳ dạng nội dung nào (tài sản, phông chữ, v.v.) trong phương thức LoadContent. Đối với việc khởi tạo, bạn thường sẽ tạo đối tượng Trình phát trong hàm Khởi tạo và sau đó tải nội dung của nó trong LoadContent .. Hoặc bạn có thể thực hiện tất cả trong LoadContent nếu muốn.

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.