2011-09-22 30 views
5

Trước tiên, hãy để tôi xin lỗi vì đã đặt câu hỏi có vẻ hơi mơ hồ (hoặc bị chính thức hóa), nhưng tôi thiếu kinh nghiệm để hỏi bất cứ điều gì cụ thể hơn.C# Cấu trúc cho các đối tượng trong trò chơi 2D

Tôi đang xây dựng một công cụ để chơi trò chơi mạo hiểm 2D (loại bạn bấm vào-một-đối tượng-và-điều gì đó xảy ra) trong C# và tôi đang xem xét cấu trúc tốt nhất cho nó. Như bạn có thể hình dung, những thứ khác nhau có thể xảy ra khi bạn tương tác với một vật thể: nếu đó là cánh cửa, bạn sẽ bước vào một căn phòng khác, nếu đó là một người, bạn sẽ bắt đầu nói chuyện với họ, vv Ý tưởng của tôi là đạt được hành vi này với các đại biểu, như thế này:

public abstract class GameObject { 
    public delegate void onAction(); 
    public onAction Click; 
} 

public class Door : GameObject { 
    public Door() { 
     Click = new onAction(ChangeRoom); 
    } 
    private void ChangeRoom() { 
     //code to change room here 
    } 
} 

public class Person : GameObject { 
    public Person() { 
     Click = new onAction(StartTalking); 
    } 
    private void StartTalking() { 
     //code to display dialogue here 
    } 
} 

tôi thấy giải pháp này khá thanh lịch, vì nếu tôi muốn tạo ra một đối tượng đặc biệt với một số hành vi không được bao phủ bởi các lớp học, tôi chỉ có thể làm điều này:

specialObject.Click += new onAction(SpecialMethod); 

Nhưng đây cũng là nơi mọi thứ trở nên phức tạp. Tôi muốn động cơ của mình có khả năng chơi các trò chơi khác nhau chỉ đơn giản bằng cách tải dữ liệu khác nhau, không thay đổi động cơ, vì vậy mã hóa cứng SpecialMethod ở đâu đó bên trong động cơ không phải là tùy chọn, nó phải là một phần của dữ liệu. Đối với đối tượng bình thường, tất cả có thể được thực hiện với (de) serialization, nhưng từ những gì tôi đã đọc, đây là vấn đề với các đại biểu. Bạn có thể đề xuất một cách để làm điều đó?

P.S .: Vì tôi vẫn đang ở cấp khái niệm và mã ở trên chưa được triển khai, bạn được tự do đề xuất bất kỳ giải pháp nào bạn tìm thấy tốt nhất, thậm chí cả giải pháp tránh đại biểu hoàn toàn.

+0

Có vẻ như bạn đang mô tả Công cụ quy tắc http://martinfowler.com/bliki/RulesEngine.html – Jodrell

+1

Tôi nghĩ bạn có thể đăng câu hỏi này tại http://gamedev.stackexchange.com/ – Luca

+0

Cảm ơn bạn @ luca vì liên kết. Chắc chắn sẽ kiểm tra xem nó ra, mặc dù ở cái nhìn đầu tiên, có vẻ như diễn đàn này là một chút chuyên nghiệp hơn tôi. –

Trả lời

1

Đầu tiên của tất cả các công cụ viết khi bạn thiếu kinh nghiệm có thể khó khăn hơn bạn nghĩ. Tôi sẽ đề nghị bạn viết cho bạn trò chơi đầu tiên mà không cần động cơ và hardcode nhiều như bạn muốn và sau đó học hỏi từ kinh nghiệm và viết động cơ của bạn ... Tôi biết đó không phải là những gì bạn muốn: D

Nếu bạn chưa kiểm tra nhưng nhìn vào http://www.adventuregamestudio.co.uk/ chơi với trình soạn thảo và nghĩ về mô hình đối tượng bên dưới. Nó sẽ giúp.

Vì bạn muốn trò chơi của mình là dữ liệu điều khiển, bạn phải có khả năng tải và thực thi mã. "Nó không phải là một ngôn ngữ kịch bản." Đối với bản chất của tôi, tôi khuyên bạn nên thêm ngôn ngữ kịch bản và học nó cùng một lúc khi bạn học cách xây dựng một động cơ. .NET Framework có một hệ thống phản chiếu tuyệt vời cho phép bạn tải mã C# và biên dịch nó khi chạy. Tôi phải chỉ ra rằng đây là loại kịch bản trong C# nhưng có một thiếu định nghĩa thích hợp của ngôn ngữ kịch bản.

Vì bạn không có nhiều kinh nghiệm trong đề xuất này nên sử dụng các tệp XML xác định phòng của bạn và có chuỗi các lệnh cơ bản xác định những gì sẽ xảy ra khi bạn nhấp vào một cái gì đó. Bạn nên thực hiện tất cả các lệnh trong "động cơ" của bạn nhưng bạn sẽ có thể dễ dàng tạo ra các phòng mới do đó trò chơi tương tự. XML cũng sẽ là phương pháp tiếp cận rất mở rộng vì cấu trúc phân cấp của nó sẽ cho phép bạn thêm các điều kiện, vòng lặp, v.v. sẽ mở rộng khả năng "viết kịch bản" của động cơ của bạn.

+0

Sau khi suy nghĩ và khám phá các tùy chọn khác nhau, tôi thấy câu trả lời này hữu ích nhất. Nó nhắc tôi rằng bạn không cần phải làm quá nhiều thứ, và cho tôi một ý tưởng rằng tôi có thể sử dụng như một sự khởi đầu. Cảm ơn! –

1

Bạn không cần phải mã hóa cứng chức năng SpecialMethod vào công cụ, bạn có thể sử dụng nó từ các trò chơi khác nhau mà sử dụng động cơ của bạn:

var medievalDoor = new Door(); 
medievalDoor.Click += OpenDoorNormally; 

Nhưng trong một trò chơi khác nhau:

var starTrekDoor = new Door(); 
starTrekDoor.Click += SlideDoorUpward; 

Miễn là bạn phơi bày sự kiện Nhấp, bạn không cần phải mã hóa bất cứ thứ gì vào công cụ của mình. Nó có thể được đưa vào trò chơi của bạn mà có thể có động cơ của bạn như là một tài liệu tham khảo DLL.

+0

Nếu 'medievalDoor.Click + = OpenDoorNormally' được định nghĩa ở cấp độ động cơ, mà có vẻ là những gì anh ta đang nguyền rủa, sau đó bạn sẽ cần phải sửa đổi mã động cơ bất cứ khi nào bạn thay đổi dữ liệu trò chơi. – InBetween

0

Tôi không thấy vấn đề nếu 'quyết định' thực hiện một số hành vi đặc biệt hoặc không được để chính đối tượng trò chơi. Nếu bạn muốn động cơ quyết định sau đó bạn có, tôi nghĩ, các thông số kỹ thuật thiết kế không tương thích như bạn sẽ có hiệu quả làm cho động cơ có một quyết định trò chơi xác định đó là chính xác những gì bạn không muốn.

Tạo một trường ISpecialBehaviorProvider trong đối tượng trò chơi của bạn và đặt thành giá trị thích hợp khi cần thiết (thông qua hàm tạo, thuộc tính công khai, bạn có gì).

Động cơ của bạn sẽ luôn thực hiện GameObject.Click bất cứ khi nào người dùng nhấp chuột. Tuy nhiên, nếu specialBehaviorProvider là không, hãy thực hiện mã số GameObject.Click thực hiện mã 'trong lớp', nếu không hãy gọi ISpecialBehaviorProvider.SpecialMethod.

Bằng cách này, động cơ không có phần nào quyết định nên gọi phương thức nào.

+0

Vâng, ý tưởng của tôi là để động cơ kích hoạt 'GameObject.Click' khi thích hợp mà không cần bất kỳ kiểm tra nào. Nhưng tôi vẫn có thể vượt qua hành vi đặc biệt của một số vật thể "từ bên ngoài". Khi các câu trả lời tiếp theo đề xuất, tôi đang trên đường tìm hiểu về cách viết kịch bản. –

0

Điều đầu tiên tôi lưu ý ở đây là vì đây là các lớp, đa hình sẽ khá lý tưởng ở đây - ví dụ như với phương pháp Nhấp chuột ảo.

Các đại biểu thực sự có thể khó khăn cho các bộ nối tiếp, tùy thuộc vào cách tiếp cận tuần tự hóa.BinaryFormatter sẽ làm điều đó, nhưng tôi có xu hướng tránh serializer đó bằng mọi giá trị như một quy tắc chung.

Nếu có thể, tôi khuyên bạn nên chỉ có tùy chỉnh của bạn phân lớp các triển khai chuẩn và sử dụng đa hình. Nếu nó phải được xác định hoàn toàn là thông qua dữ liệu, về cơ bản bạn sẽ triển khai một công cụ tạo tập lệnh. Nhiều cái như vậy có sẵn trong .NET - IronPython có thể hữu ích, mặc dù game lua khá phổ biến (bạn có thể sử dụng Lua.NET khá dễ dàng). Sau đó, bạn chỉ có thể có một kịch bản tùy chọn liên kết với hành động, và gọi kịch bản (được định nghĩa trong dữ liệu).

+0

Tôi muốn nói rằng 90% hành vi của đối tượng có thể được xác định chỉ bằng đa hình. Vấn đề (như thường lệ) nằm trong 10% còn lại. Tôi có thể hỏi tại sao bạn tránh BinaryFormatter? (Tôi cũng khá mới trong khu vực đó.) –

3

Những gì bạn cần là tập lệnh.

Về cơ bản, tập lệnh là tài nguyên bên ngoài (nghĩa là tệp bên ngoài) có chứa mã nguồn mô tả hành động.

C# có tùy chọn khác cho việc này.

Bạn có thể phát ra hội đồng từ các ngôn ngữ .NET. Hoặc bạn có thể tích hợp một ngôn ngữ khác (ví dụ như python) và thực thi kịch bản khi chạy. Về cơ bản, tập lệnh được tải, diễn giải hoặc biên dịch và được thực thi vào đúng thời điểm. Nếu kịch bản có thể sửa đổi trạng thái ứng dụng (các cấu trúc dữ liệu), bạn có thể xác định hành vi đối tượng với dữ liệu ngoài (phát triển theo hướng dữ liệu).

Có rất nhiều tài liệu về vấn đề này, nhưng tôi cảm thấy đề xuất GPU Programming Gems 6 (phần 4). Tuy nhiên, nỗ lực cần thiết để tích hợp một công cụ tạo tập lệnh tuyệt vời là rất nhiều. Bằng cách đó, tôi đã cố gắng tìm ra một logic đơn giản dựa trên các tệp XML (here là câu hỏi của tôi về việc tham gia một số question khác để xác định nội dung XML); thật đáng buồn, tôi thấy rằng hầu như phụ thuộc vào sự linh hoạt bạn cần.

+0

+1 để viết kịch bản. Các IronLanguages ​​là tầm thường để tích hợp vào một ứng dụng .NET và có khả năng tương tác rất tốt với C#: https://github.com/IronLanguages/main – robbrit

Các vấn đề liên quan