Các lựa chọn thay thế linh hoạt cho nhiều lớp đa hình nhỏ (để sử dụng làm thuộc tính hoặc thông điệp hoặc sự kiện) C ++


9

Có hai lớp trong trò chơi của tôi thực sự hữu ích, nhưng dần dần trở thành một nỗi đau. Tin nhắn và tài sản (tài sản về cơ bản là một thành phần).

Cả hai đều xuất phát từ một lớp cơ sở và chứa một id tĩnh để các hệ thống chỉ có thể chú ý đến những cái mà chúng muốn. Nó hoạt động rất tốt ... ngoại trừ ...

Tôi liên tục tạo các loại tin nhắn và loại tài sản mới khi tôi mở rộng trò chơi của mình. Mỗi lần tôi cần phải viết 2 tệp (hpp và cpp) và một tấn mẫu soạn sẵn để có được một classID và một hoặc hai loại dữ liệu tiêu chuẩn hoặc một con trỏ.

Nó bắt đầu biến việc chơi xung quanh và thử nghiệm những ý tưởng mới thành một việc vặt thực sự. Tôi ước khi tôi muốn tạo một tin nhắn hoặc loại thuộc tính mới, tôi muốn có thể chỉ cần gõ một cái gì đó như

ShootableProperty:  int gunType, float shotspeed;

ItemCollectedMessage:  int itemType;

thay vì tạo một tệp tiêu đề và cpp, hãy viết một hàm tạo, bao gồm cả lớp cha, v.v.

Đó là khoảng 20 - 40 dòng (bao gồm cả lính canh và tất cả mọi thứ) chỉ để làm những gì hợp lý là 1 hoặc 2 dòng trong tâm trí của tôi.

Có một số mô hình lập trình để có được xung quanh này?

Thế còn với kịch bản (mà tôi không biết gì) ... có cách nào để xác định một nhóm các lớp gần giống nhau không?


Đây là chính xác một lớp trông như thế nào:

// Velocity.h

#ifndef VELOCITY_H_
#define VELOCITY_H_

#include "Properties.h"

#include <SFML/System/Vector2.hpp>

namespace LaB
{
namespace P
{

class Velocity: public LaB::Property
{
public:
    static const PropertyID id;

    Velocity(float vx = 0.0, float vy = 0.0)
    : velocity(vx,vy) {}
    Velocity(sf::Vector2f v) : velocity(v) {};

    sf::Vector2f velocity;
};

} /* namespace P */
} /* namespace LaB */
#endif /* LaB::P_VELOCITY_H_ */



// Velocity.cpp

#include "Properties/Velocity.h"

namespace LaB
{
namespace P
{

const PropertyID Velocity::id = Property::registerID();

} /* namespace P */
} /* namespace LaB */

Tất cả điều đó chỉ dành cho một Vector 2D và một ID nói rằng sẽ mong đợi một vector 2D. (Cấp, một số thuộc tính có các yếu tố phức tạp hơn, nhưng đó là cùng một ý tưởng)


3
Hãy nhìn vào điều này, nó có thể giúp bạn. gameprogrammingpotypes.com/type-object.html

1
Tất cả điều này trông giống như các mẫu có thể giúp đỡ, nhưng không phải với khởi tạo tĩnh. Nó chắc chắn có thể trở nên dễ dàng hơn rất nhiều trong trường hợp này, nhưng thật khó để nói mà không có thêm thông tin về những gì bạn muốn làm với những ID đó và tại sao bạn lại sử dụng quyền thừa kế. Sử dụng thừa kế công khai nhưng không có chức năng ảo chắc chắn là mùi mã ... Đây không phải là đa hình!
ltjax

Bạn đã tìm thấy thư viện bên thứ 3 thực hiện nó?
Boris

Câu trả lời:


1

C ++ rất mạnh, nhưng nó dài dòng . Nếu những gì bạn muốn là rất nhiều lớp đa hình nhỏ khác nhau, thì có, nó sẽ mất rất nhiều mã nguồn để khai báo và định nghĩa. Không có gì để làm về nó, thực sự.

Bây giờ, như ltjax đã nói, những gì bạn đang làm ở đây không chính xác là đa hình , ít nhất là đối với mã bạn đã cung cấp. Tôi không thể thấy một giao diện chung sẽ ẩn việc triển khai cụ thể của các lớp con. Ngoại trừ có thể cho ID lớp, nhưng điều này thực sự dư thừa với ID lớp thực: tên của nó. Đây dường như chỉ là một nhóm các lớp chứa một số dữ liệu, không có gì thực sự phức tạp.

Nhưng điều này không giải quyết được vấn đề của bạn: bạn muốn tạo nhiều thông điệp và thuộc tính với số lượng mã ít nhất. Ít mã hơn có nghĩa là ít lỗi hơn nên đây là một quyết định sáng suốt. Thật không may cho bạn không có giải pháp duy nhất. Thật khó để nói những gì sẽ phù hợp với nhu cầu của bạn nhất mà không biết chính xác những gì bạn định làm với những thông điệp và tính chất đó . Vì vậy, hãy để tôi chỉ đưa ra các lựa chọn của bạn:

  1. Sử dụng các mẫu C ++ . Mẫu là một cách tuyệt vời để cho trình biên dịch "viết mã" cho bạn. Nó trở nên ngày càng nổi bật hơn trong thế giới C ++, vì ngôn ngữ phát triển để hỗ trợ chúng tốt hơn (ví dụ: bây giờ bạn có thể sử dụng một số lượng tham số mẫu khác nhau ). Có toàn bộ kỷ luật dành riêng cho việc tạo mã tự động thông qua các mẫu: siêu lập trình mẫu . Vấn đề là: nó khó khăn. Đừng mong đợi những người không lập trình có thể tự thêm các thuộc tính mới nếu bạn định sử dụng một kỹ thuật như vậy.

  2. Sử dụng các macro C đơn giản . Đó là trường học cũ, dễ lạm dụng và dễ bị lỗi. Họ cũng rất đơn giản để tạo ra. Macro chỉ là các bản sao chép được tôn vinh được thực hiện bởi bộ tiền xử lý, vì vậy chúng thực sự khá phù hợp để tạo ra vô số thứ gần giống nhau với ít biến thể. Nhưng đừng hy vọng các lập trình viên khác yêu bạn vì đã sử dụng chúng, vì các macro thường được sử dụng để che giấu các lỗ hổng trong thiết kế chương trình tổng thể. Đôi khi, mặc dù, chúng hữu ích.

  3. Một tùy chọn khác là sử dụng một công cụ bên ngoài để tạo mã cho bạn. Nó đã được đề cập trong một câu trả lời trước đó vì vậy tôi sẽ không mở rộng về điều đó.

  4. Có những ngôn ngữ khác ít dài dòng hơn và sẽ cho phép bạn tạo các lớp dễ dàng hơn. Vì vậy, nếu bạn đã có các ràng buộc tập lệnh (hoặc bạn dự định có chúng), việc xác định các lớp đó trong tập lệnh có thể là một tùy chọn. Việc truy cập chúng từ C ++ sẽ khá phức tạp và bạn sẽ mất phần lớn lợi ích của việc tạo các lớp đơn giản hóa. Vì vậy, điều này có lẽ chỉ khả thi khi bạn có kế hoạch thực hiện hầu hết logic trò chơi của mình bằng ngôn ngữ khác.

  5. Cuối cùng nhưng không kém phần quan trọng, bạn nên cân nhắc sử dụng thiết kế dựa trên dữ liệu . Bạn có thể định nghĩa các "lớp" đó trong các tệp văn bản đơn giản bằng cách sử dụng bố cục tương tự như bố cục bạn đề xuất. Bạn sẽ phải tạo một định dạng và trình phân tích cú pháp tùy chỉnh cho nó hoặc sử dụng một trong một số tùy chọn đã có sẵn (.ini, XML, JSON và whatnot). Sau đó, về phía C ++, bạn sẽ cần tạo một hệ thống hỗ trợ bộ sưu tập các loại đối tượng khác nhau đó. Điều này gần như tương đương với cách tiếp cận kịch bản (và có thể đòi hỏi nhiều công việc hơn), ngoại trừ bạn sẽ có thể điều chỉnh nó chính xác hơn theo nhu cầu của bạn. Và nếu bạn làm cho nó đủ đơn giản, những người không lập trình có thể tự tạo ra những thứ mới.


0

Làm thế nào về một công cụ tạo mã để giúp bạn ra ngoài?

ví dụ, bạn có thể xác định loại thông báo và các thành viên của mình trong một tệp văn bản nhỏ và có công cụ gen mã phân tích nó và viết tất cả các tệp C ++ soạn sẵn dưới dạng bước xây dựng trước.

Có các giải pháp hiện có như ANTLR hoặc LEX / YACC, và sẽ không khó để tự mình thực hiện tùy thuộc vào độ phức tạp của các thuộc tính và tin nhắn của bạn.


Chỉ là một thay thế cho aproach LEX / YACC, khi tôi phải tạo các tệp rất giống nhau chỉ với sửa đổi nhỏ, tôi sử dụng tập lệnh python đơn giản và nhỏ và tệp mẫu mã C ++ chứa thẻ. Tập lệnh python tìm kiếm các thẻ này trong mẫu thay thế chúng bằng mã thông báo đại diện của phần tử được tạo.
người chiến thắng

0

Tôi khuyên bạn nên nghiên cứu về Bộ đệm giao thức của Google ( http://code.google.com.vn/p/protobuf/ ). Họ là một cách rất thông minh để xử lý các thông điệp chung chung. Bạn chỉ cần xác định các thuộc tính trong mẫu struct-llike và trình tạo mã thực hiện tất cả công việc tạo các lớp cho bạn (Java, C ++ hoặc C #). Tất cả các lớp được tạo đều có trình phân tích cú pháp văn bản và nhị phân, điều này làm cho chúng tốt cho cả khởi tạo và tuần tự hóa tin nhắn dựa trên văn bản.


Trung tâm nhắn tin của tôi là cốt lõi chương trình của tôi - bạn có biết bộ đệm giao thức có phải chịu bất kỳ chi phí lớn nào không?
Bryan

Tôi không nghĩ rằng họ phải chịu chi phí lớn, vì API chỉ là một lớp Builder cho mỗi tin nhắn và lớp cho chính tin nhắn. Google sử dụng chúng cho cốt lõi của cơ sở hạ tầng của họ. Ví dụ: Các thực thể Máy ứng dụng của Google đều được chuyển đổi thành bộ đệm giao thức trước khi tồn tại. Nếu bạn nghi ngờ, tôi khuyên bạn nên thực hiện kiểm tra so sánh giữa bộ đệm giao thức và triển khai hiện tại của bạn. Nếu bạn nghĩ rằng chi phí chấp nhận được, hãy sử dụng chúng.
DSilva.vinicius
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.