Lời khuyên này không thực sự cụ thể để kết xuất nhưng sẽ giúp đưa ra một hệ thống giúp mọi thứ tách biệt nhau. Trước hết hãy thử và tách dữ liệu 'GameObject' khỏi thông tin vị trí.
Điều đáng chú ý là thông tin vị trí XYZ đơn giản có thể không đơn giản như vậy. Nếu bạn đang sử dụng công cụ vật lý thì dữ liệu vị trí của bạn có thể được lưu trữ trong công cụ của bên thứ 3. Bạn có thể cần phải đồng bộ hóa giữa chúng (sẽ liên quan đến việc sao chép bộ nhớ vô nghĩa) hoặc truy vấn thông tin trực tiếp từ công cụ. Nhưng không phải tất cả các đối tượng đều cần vật lý, một số sẽ được cố định tại chỗ để một bộ phao đơn giản hoạt động tốt ở đó. Một số thậm chí có thể được gắn vào các đối tượng khác, vì vậy vị trí của chúng thực sự là phần bù của vị trí khác. Trong thiết lập nâng cao, bạn có thể chỉ có vị trí được lưu trữ trên GPU, lần duy nhất bên máy tính cần thiết là để tạo kịch bản, lưu trữ và sao chép mạng. Vì vậy, bạn có thể sẽ có một số lựa chọn có thể cho dữ liệu vị trí của bạn. Ở đây nó có ý nghĩa để sử dụng thừa kế.
Thay vì một đối tượng sở hữu vị trí của nó, thay vào đó, chính đối tượng đó phải được sở hữu bởi một cấu trúc dữ liệu lập chỉ mục. Ví dụ: 'Cấp độ' có thể có Octree hoặc có thể là 'cảnh' của động cơ vật lý. Khi bạn muốn kết xuất (hoặc thiết lập cảnh kết xuất), bạn truy vấn cấu trúc đặc biệt của mình cho các đối tượng hiển thị trước máy ảnh.
Điều này cũng giúp cung cấp cho quản lý bộ nhớ tốt. Bằng cách này, một đối tượng không thực sự ở trong một khu vực thậm chí không có vị trí nào có ý nghĩa hơn là trả lại 0,0 coords hoặc các coords mà nó có khi nó tồn tại trong một khu vực.
Nếu bạn không còn giữ tọa độ trong đối tượng, thay vì object.getX () bạn sẽ có level.getX (object). Vấn đề với việc tìm kiếm đối tượng ở cấp độ có thể sẽ là một hoạt động chậm vì nó sẽ phải xem qua tất cả các đối tượng của nó và khớp với đối tượng mà bạn truy vấn.
Để tránh điều đó có lẽ tôi sẽ tạo một lớp 'liên kết' đặc biệt. Một liên kết giữa một cấp độ và một đối tượng. Tôi gọi nó là "Địa điểm". Điều này sẽ chứa tọa độ xyz cũng như tay cầm ở mức và tay cầm đối tượng. Lớp liên kết này sẽ được lưu trữ trong cấu trúc / cấp độ không gian và đối tượng sẽ có một tham chiếu yếu đến nó (nếu mức / vị trí bị phá hủy, các đối tượng cần phải cập nhật thành null. 'sở hữu' đối tượng, theo cách đó nếu một mức bị xóa, thì cấu trúc chỉ mục đặc biệt, các vị trí mà nó chứa và các Đối tượng của nó cũng vậy.
typedef std::tuple<Level, Object, PositionXYZ> Location;
Bây giờ thông tin vị trí chỉ được lưu trữ ở một nơi. Không trùng lặp giữa Object, cấu trúc lập chỉ mục Spacial, trình kết xuất, v.v.
Các cấu trúc dữ liệu không gian như Octrees thường không cần phải có tọa độ của các đối tượng mà chúng lưu trữ. Có vị trí được lưu trữ ở vị trí tương đối của các nút trong chính cấu trúc (nó có thể được coi là một dạng nén mất mát, hy sinh độ chính xác cho thời gian tra cứu nhanh). Với đối tượng vị trí trong Octree thì tọa độ thực được tìm thấy bên trong nó sau khi truy vấn được thực hiện.
Hoặc nếu bạn đang sử dụng một công cụ vật lý để quản lý các vị trí đối tượng của mình hoặc hỗn hợp giữa hai thứ đó, lớp Location sẽ xử lý một cách trong suốt trong khi giữ tất cả mã của bạn ở một nơi.
Một lợi thế khác bây giờ là vị trí và sự điều chỉnh theo cấp độ được lưu trữ trong cùng một vị trí. Bạn có thể triển khai object.TeleportTo (other_object) và để nó hoạt động ở các cấp. Tương tự như vậy, việc tìm đường AI có thể đi theo một thứ gì đó vào một khu vực khác.
Liên quan đến kết xuất. Kết xuất của bạn có thể có một ràng buộc tương tự với Vị trí. Ngoại trừ nó sẽ có các công cụ cụ thể kết xuất trong đó. Bạn có thể không cần 'Đối tượng' hoặc 'Cấp độ' để được lưu trữ trong cấu trúc này. Đối tượng có thể hữu ích nếu bạn đang cố gắng thực hiện một số thứ như chọn màu hoặc hiển thị một thanh hit nổi phía trên nó, nhưng nếu không thì trình kết xuất chỉ quan tâm đến lưới và như vậy. RenderableStuff sẽ là một Lưới, cũng có thể có các hộp giới hạn, v.v.
typedef std::pair<RenderableStuff, PositionXYZ> RenderThing;
renderer.render(level, camera);
renderer: object = level.getVisibleObjects(camera);
level: physics.getObjectsInArea(physics.getCameraFrustrum(camera));
for(object in objects) {
//This could be depth sorted, meshes could be broken up and sorted by material for batch rendering or whatever
rendering_que.addObjectToRender(object);
}
Bạn có thể không cần phải làm điều này mọi khung hình, bạn có thể đảm bảo bạn có một vùng lớn hơn so với máy ảnh hiện đang hiển thị. Lưu trữ bộ nhớ cache, theo dõi chuyển động của đối tượng để xem có hộp giới hạn nào trong phạm vi, theo dõi chuyển động của camera hay không. Nhưng đừng bắt đầu lộn xộn với những thứ đó cho đến khi bạn đã điểm chuẩn nó.
Bản thân động cơ vật lý của bạn có thể có một sự trừu tượng tương tự, vì nó cũng không cần dữ liệu Object, chỉ cần lưới va chạm và các thuộc tính vật lý.
Tất cả dữ liệu đối tượng cốt lõi của bạn sẽ chứa tên lưới mà đối tượng sử dụng. Sau đó, công cụ trò chơi có thể tiếp tục và tải nó ở bất kỳ định dạng nào mà nó thích mà không làm gánh nặng lớp đối tượng của bạn với một loạt các thứ cụ thể kết xuất (có thể cụ thể cho API kết xuất của bạn, ví dụ DirectX vs OpenGL).
Nó cũng giữ các thành phần khác nhau riêng biệt. Điều này giúp bạn dễ dàng thực hiện những việc như thay thế động cơ vật lý của mình vì những thứ đó chủ yếu được chứa trong một vị trí. Nó cũng làm cho việc bỏ qua dễ dàng hơn nhiều. Bạn có thể kiểm tra những thứ như truy vấn vật lý mà không cần phải có bất kỳ thiết lập đối tượng giả thực tế nào vì tất cả những gì bạn cần là lớp Location. Bạn cũng có thể tối ưu hóa công cụ dễ dàng hơn. Nó làm cho rõ ràng hơn những truy vấn bạn cần thực hiện trên các lớp và vị trí đơn lẻ nào để tối ưu hóa chúng (ví dụ: level.getVisibleObject sẽ là nơi bạn có thể lưu trữ mọi thứ nếu máy ảnh không di chuyển đến nhiều).
m_renderable
thành viên đó . Bằng cách đó, bạn có thể tách logic của bạn tốt hơn. Không thực thi "giao diện" có thể kết xuất trên các đối tượng chung cũng có vật lý, ai và không có gì .. Sau đó, bạn có thể quản lý kết xuất đồ họa một cách riêng biệt. Bạn cần một lớp trừu tượng hóa qua các lệnh gọi hàm OpenGL để tách rời mọi thứ hơn nữa. Vì vậy, đừng mong đợi một công cụ tốt sẽ có bất kỳ lệnh gọi API GL nào bên trong các triển khai có thể kết xuất khác nhau của nó. Đó là nó, trong một tóm tắt vi mô.