Ví dụ về thiết kế hướng dữ liệu


8

Tôi dường như không thể tìm thấy một lời giải thích hay về Thiết kế hướng dữ liệu cho một trò chơi zombie chung chung (đó chỉ là một ví dụ, ví dụ khá phổ biến).

Bạn có thể làm một ví dụ về Thiết kế hướng dữ liệu về việc tạo một lớp zombie chung không? Sau đây là tốt?

Lớp danh sách zombie:

class ZombieList {
    GLuint vbo; // generic zombie vertex model
    std::vector<color>;    // object default color
    std::vector<texture>;  // objects textures
    std::vector<vector3D>; // objects positions
public:
    unsigned int create(); // return object id
    void move(unsigned int objId, vector3D offset);
    void rotate(unsigned int objId, float angle);
    void setColor(unsigned int objId, color c);
    void setPosition(unsigned int objId, color c);
    void setTexture(unsigned int, unsigned int);
    ...
    void update(Player*); // move towards player, attack if near
}

Thí dụ:

Player p;

Zombielist zl;
unsigned int first = zl.create();
zl.setPosition(first, vector3D(50, 50));
zl.setTexture(first, texture("zombie1.png"));
...

while (running) { // main loop
    ...
    zl.update(&p);
    zl.draw(); // draw every zombie
}

Hoặc có thể tạo ra một container thế giới chung có chứa tất cả các hành động từ bite(zombieId, playerId)để moveTo(playerId, vector)đến createPlayer()để shoot(playerId, vector)đến face(radians)/face(vector); và chứa:

std::vector<zombie>
std::vector<player>
...
std::vector<mapchunk>
...
std::vector<vbobufferid> player_run_animation;
...

là một ví dụ tốt?

Cách thích hợp để tổ chức một trò chơi với DOD là gì?

Câu trả lời:


11

Không có thứ gọi là "trò chơi với DOD". Đầu tiên, từ buzz đó hơi mờ, vì mỗi hệ thống được thiết kế hướng dữ liệu. Mỗi chương trình hoạt động trên một tập hợp dữ liệu và thực hiện các biến đổi nhất định cho nó. Không thể làm điều đó mà không định hướng thiết kế về phía dữ liệu. Vì vậy, nó không loại trừ lẫn nhau với thiết kế "bình thường", nhưng thêm các ràng buộc trong cách bố trí bộ nhớ và cách truy cập bộ nhớ tương ứng.

Ý tưởng đằng sau DOD là đóng gói và nhóm dữ liệu thuộc một chức năng gần nhau hơn trong một khối bộ nhớ liên tục, để có ít bộ nhớ cache hơn, loại bỏ các chức năng ảo và vtables, song song dễ dàng hơn, không truy cập bộ nhớ ngẫu nhiên (hoặc tối thiểu) và để viết mã cho các bộ xử lý được tối ưu hóa cao như SPU của Cell trong PS3 với tài nguyên bộ nhớ hạn chế, tối ưu hóa truy cập bộ nhớ và DMA đến và từ bộ nhớ chính của nó.

Điều này không chỉ đơn giản là thay đổi mọi thứ từ "Mảng cấu trúc" (AoS) thành "Cấu trúc của mảng" (SoA) như được hiển thị trong các ví dụ ở đây. Nó cũng có thể có nghĩa là trộn cả hai và xen kẽ và đóng gói dữ liệu thuộc một chức năng gần nhau, ví dụ như "vị trí" và "vận tốc" để tránh nhảy vào bộ nhớ để tích hợp vị trí.

Tuy nhiên, các hệ thống DOD thuần rất khó thực hiện, vì mỗi lần truy cập con trỏ là vi phạm khái niệm thuần túy đó , vì bạn không truy cập vào khối bộ nhớ liên tục nữa, nhưng thực hiện truy cập bộ nhớ ngẫu nhiên bằng cách hủy bỏ một con trỏ. Điều này đặc biệt quan trọng để viết mã cho SPU khi di chuyển, ví dụ hệ thống hạt từ CPU sang SPU, nhưng trong phát triển trò chơi hàng ngày thông thường, điều đó không quan trọng. Đó là một cách để tối ưu hóa chức năng phụ, không phải để viết trò chơi với nó (tuy nhiên, như bài viết của Noels giải thích).

Mike Acton từ Insomniac Games có rất nhiều tài liệu liên quan đến chủ đề này, bạn có thể tìm thấy một số nội dung của anh ấy ở đây cũng như các bài viết của Noel , cả hai đều rất được khuyến khích.


Một điều tôi muốn thêm vào câu trả lời này: DOD không phải là TẤT CẢ về các hệ thống SoA. Mặc dù các cấu trúc SoA có xu hướng hoạt động tốt nhất cho DOD, nhưng chúng không luôn phù hợp với khái niệm DOD thực tế. Khái niệm đằng sau DOD chỉ đơn giản là ý tưởng rằng bạn đang thiết kế mã xung quanh dữ liệu, chứ không phải theo cách khác, đó là phương pháp thông thường.
Gurgadurgen 17/05/2015

0

Tôi đã tìm kiếm một ví dụ tốt về điều này, nhưng với nguồn lực hạn chế trên mạng và không ai cho tôi biết làm thế nào cho đúng, tôi đã thực hiện với cách thực hiện sau. (nó có thể không phải là tốt nhất, nhưng nó tuân theo ý tưởng cơ bản)

Object
   //Basic data
   Vector3* Position;
   Vector3* Rotation;
   Vector3* Scale;



Car : Object
    float* acceleration;
    Object* GetObjectData();
    //invoke the updateCars, to update all cars.
    void    UpdateCar() { UpdateCars(Postion, Rotation, Scale);

    //Update all your objects in a big loop.
    void    UpdateCars(vector3* Position, vector3* Rotation, Vector3* scale);

Vì vậy, việc thực hiện ít nhiều như thế này: Bạn có một lớp đối tượng cơ sở, chứa tất cả dữ liệu chung. Khi lớp xe của bạn được xây dựng, bạn chỉ định lượng dữ liệu bạn muốn gộp lại và do đó có đủ bộ nhớ cho tất cả các đối tượng.

từ đó bạn có thể thêm các số nhận dạng hoặc những gì cảm thấy không cần thiết cho việc thực hiện của bạn. nhưng tôi đã thử điều này trên một trò chơi đơn giản hơn và nó hoạt động khá gọn gàng.

Nó cũng không quá xa thiết kế của bạn, và thật lòng mà nói tôi không biết cách nào hiệu quả hơn để làm điều này.


Một vài vấn đề của DOD: 1. Mất quy mô, chắc chắn. Các tính toán liên quan đến vị trí và xoay hầu như không bị ảnh hưởng bởi tỷ lệ, do đó, nó sẽ không bao giờ được sử dụng và chỉ chiếm không gian bộ nhớ cache. 2. Tôi cũng sẽ mất vòng quay và thay thế nó bằng vận tốc. Một chiếc xe dự định di chuyển thẳng, nhưng vận tốc của nó cuối cùng sẽ quyết định hướng của nó. Người lái nhấn cánh hoa ga, nhưng vật lý di chuyển chiếc xe. 3. Không kế thừa từ các lớp cho dữ liệu nếu bạn không có kế hoạch sử dụng nó trong hầu hết các tính toán cùng nhau. 4. Ngay cả trong OOP, xe hơi không cập nhật lẫn nhau. Sử dụng các chức năng miễn phí.
Gurgadurgen

Đây là nhiều hơn một ví dụ, không phải là một hướng dẫn cuối cùng. bạn tất nhiên phải chọn fitt tốt nhất để thực hiện của riêng bạn. (như đã nêu)
Tordin

Ví dụ của bạn là một ví dụ về sự trừu tượng hóa OOP tiêu chuẩn và mất ít hoặc không tận dụng các chiến lược DoD. DoD là về dữ liệu, không phải về mô hình. Việc bạn thậm chí có một đối tượng "xe hơi" là một sự cho đi đã chết rằng đây không phải là một ví dụ về DoD. Một chiếc xe khá đặc biệt và DoD có xu hướng thực hiện thành phần đối tượng và đa hình dựa trên sự tồn tại, thay vì dựa trên sự kế thừa. Vì vậy, ví dụ, bạn có thể có một đối tượng chứa thông tin cần thiết cho một biến đổi cụ thể và tạo một mảng các đối tượng đó, thay vì một đối tượng có thông tin cho nhiều biến đổi.
Gurgadurgen
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.