Bây giờ tôi đã làm việc với một game nhập vai 2d và tôi nhận ra rằng tôi đã đưa ra một số quyết định thiết kế tồi. Có một vài điều đặc biệt gây ra vấn đề cho tôi, vì vậy tôi đã tự hỏi những loại thiết kế mà người khác sử dụng để khắc phục chúng, hoặc sẽ sử dụng.
Để có một nền tảng nhỏ, tôi bắt đầu làm việc với nó trong thời gian rảnh vào mùa hè năm ngoái. Ban đầu tôi làm game ở C #, nhưng khoảng 3 tháng trước, đã quyết định chuyển sang C ++. Tôi muốn có một xử lý tốt về C ++ vì đã được một lúc kể từ khi tôi sử dụng nó rất nhiều, và nghĩ rằng một dự án thú vị như thế này sẽ là một động lực tốt. Tôi đã sử dụng rộng rãi thư viện boost và đã sử dụng SFML cho đồ họa và FMOD cho âm thanh.
Tôi có một chút mã được viết, nhưng đang xem xét loại bỏ nó và bắt đầu lại.
Đây là những lĩnh vực quan tâm chính mà tôi có và muốn có một số ý kiến về cách thức phù hợp mà người khác đã giải quyết chúng hoặc sẽ giải quyết chúng.
1. Phụ thuộc theo chu kỳ Khi tôi đang chơi trò chơi trong C #, tôi không thực sự phải lo lắng về điều này vì nó không phải là vấn đề ở đó. Chuyển sang C ++, điều này đã trở thành một vấn đề khá lớn và khiến tôi nghĩ rằng tôi có thể đã thiết kế mọi thứ không chính xác. Tôi thực sự không thể tưởng tượng làm thế nào để tách lớp của tôi và vẫn để họ làm những gì tôi muốn. Dưới đây là một vài ví dụ về chuỗi phụ thuộc:
Tôi có một lớp hiệu ứng trạng thái. Lớp này có một số phương thức (Áp dụng / Không thích hợp, Đánh dấu, v.v.) để áp dụng các hiệu ứng của nó đối với một ký tự. Ví dụ,
virtual void TickCharacter(Character::BaseCharacter* character, Battles::BattleField *field, int ticks = 1);
Các chức năng này sẽ được gọi mỗi khi nhân vật gây ra hiệu ứng trạng thái thay phiên nhau. Nó sẽ được sử dụng để thực hiện các hiệu ứng như Regen, Poison, v.v. Tuy nhiên, nó cũng giới thiệu các phụ thuộc vào lớp BaseCharacter và lớp BattleField. Đương nhiên, lớp BaseCharacter cần theo dõi những hiệu ứng trạng thái nào hiện đang hoạt động trên chúng để đó là một sự phụ thuộc theo chu kỳ. Battlefield cần theo dõi các bên chiến đấu và lớp nhóm có một danh sách BaseChar character giới thiệu một sự phụ thuộc theo chu kỳ khác.
2 - Sự kiện
Trong C #, tôi đã sử dụng rộng rãi các đại biểu để tham gia vào các sự kiện trên các nhân vật, chiến trường, v.v. (ví dụ, có một đại biểu khi thay đổi sức khỏe của nhân vật, khi thay đổi chỉ số, khi thêm / xóa hiệu ứng trạng thái, v.v. .) và các thành phần đồ họa / chiến trường sẽ kết nối với các đại biểu đó để thực thi các hiệu ứng của họ. Trong C ++, tôi đã làm một cái gì đó tương tự. Rõ ràng là không có tương đương trực tiếp với các đại biểu C #, vì vậy thay vào đó tôi đã tạo ra một cái gì đó như thế này:
typedef boost::function<void(BaseCharacter*, int oldvalue, int newvalue)> StatChangeFunction;
và trong lớp nhân vật của tôi
std::map<std::string, StatChangeFunction> StatChangeEventHandlers;
Bất cứ khi nào chỉ số của nhân vật thay đổi, tôi sẽ lặp lại và gọi mọi StatChangeFunction trên bản đồ. Trong khi nó hoạt động, tôi lo lắng đây là một cách tiếp cận tồi để làm việc.
3 - Đồ họa
Đây là điều lớn. Nó không liên quan đến thư viện đồ họa mà tôi đang sử dụng, nhưng là một thứ mang tính khái niệm. Trong C #, tôi đã kết hợp đồ họa với rất nhiều lớp mà tôi biết là một ý tưởng tồi tệ. Muốn làm điều đó tách rời lần này tôi đã thử một cách tiếp cận khác.
Để thực hiện đồ họa của mình, tôi đã tưởng tượng mọi thứ đồ họa liên quan trong trò chơi là một loạt các màn hình. Tức là có màn hình tiêu đề, màn hình trạng thái nhân vật, màn hình bản đồ, màn hình kho đồ, màn hình chiến đấu, màn hình GUI chiến đấu và về cơ bản tôi có thể xếp các màn hình này lên nhau khi cần thiết để tạo đồ họa trò chơi. Bất kể màn hình hoạt động là sở hữu đầu vào trò chơi.
Tôi đã thiết kế một trình quản lý màn hình sẽ đẩy và bật màn hình dựa trên đầu vào của người dùng.
Chẳng hạn, nếu bạn đang ở trên màn hình bản đồ (trình xử lý / trình hiển thị đầu vào cho Bản đồ Ngói) và nhấn nút bắt đầu, nó sẽ đưa ra lệnh gọi đến trình quản lý màn hình để đẩy màn hình Menu chính qua màn hình bản đồ và đánh dấu bản đồ màn hình để không được vẽ / cập nhật. Người chơi sẽ điều hướng xung quanh menu, sẽ đưa ra nhiều lệnh hơn cho trình quản lý màn hình khi thích hợp để đẩy màn hình mới lên ngăn xếp màn hình, sau đó bật chúng khi người dùng thay đổi màn hình / hủy bỏ. Cuối cùng, khi người chơi thoát khỏi menu chính, tôi sẽ tắt nó và quay lại màn hình bản đồ, nhận xét nó sẽ được vẽ / cập nhật và đi từ đó.
Màn hình chiến đấu sẽ phức tạp hơn. Tôi có một màn hình để làm nền, một màn hình để trực quan hóa từng bên trong trận chiến và một màn hình để trực quan hóa giao diện người dùng cho trận chiến. Giao diện người dùng sẽ nối vào các sự kiện nhân vật và sử dụng chúng để xác định khi nào cần cập nhật / vẽ lại các thành phần UI. Cuối cùng, mọi cuộc tấn công có tập lệnh hoạt hình có sẵn sẽ gọi một lớp bổ sung để tự tạo hiệu ứng trước khi bật ra khỏi ngăn xếp màn hình. Trong trường hợp này, mọi lớp đều được đánh dấu là có thể vẽ và cập nhật được và tôi có được một chồng màn hình xử lý đồ họa chiến đấu của mình.
Mặc dù tôi chưa thể khiến trình quản lý màn hình hoạt động hoàn hảo nhưng tôi nghĩ tôi có thể làm được một lúc. Câu hỏi của tôi về nó là, đây có phải là một cách tiếp cận đáng giá không? Nếu đó là một thiết kế tồi tôi muốn biết bây giờ trước khi tôi đầu tư quá nhiều thời gian để làm tất cả các màn hình tôi sẽ cần. Làm thế nào để bạn xây dựng đồ họa cho trò chơi của bạn?