Khi nào tôi nên biểu diễn các điểm và kích thước dưới dạng cấu trúc?


9

Là một phần của khung phát triển trò chơi Ruby 2D đơn giản của tôi, các đối tượng trò chơi của tôi có vị trí (giá trị x và y) và kích thước (chiều rộng và chiều cao).

class MyGameObject
  attr_accessor :x
  attr_accessor :y
  attr_accessor :width
  attr_accessor :height
  ...

Một cách tiếp cận khác mà tôi đã thấy là coi vị trí là một Pointcấu trúc và kích thước như một Sizecấu trúc:

Point = Struct.new(:x, :y)
Size = Struct.new(:width,:height)

class MyGameObject
  attr_accessor :position   # Point instance
  attr_accessor :size       # Size instance
  ...

Một số khung sử dụng trước đây (tôi nghĩ GDX, Gosu ...). Những người khác sử dụng cái sau (cocos2d-iphone). Vấn đề là, tôi không hoàn toàn rõ ràng về những lợi thế và bất lợi của cả hai hành vi (trong phát triển trò chơi) - Tôi không biết tại sao một số khung công tác lại chọn cái này mà không phải cái kia.

Có sự khác biệt đáng kể tôi nên xem xét?

Câu trả lời:


8

Một số thậm chí sử dụng Rectanglelớp:

class Rectangle
{
    float x, y, w, h;
}
class GameObject
{
    Rectangle dimensions;
}

Đó chỉ là một sự lựa chọn của thiết kế, nó không thực sự quan trọng. Nếu bạn đang thực hiện mã của riêng mình, hãy làm cho những gì bạn cảm thấy dễ hiểu hơn. Nếu bạn đang sử dụng một số API, khung hoặc công cụ hoặc chỉnh sửa / sửa đổi trò chơi, hãy cố gắng nhất quán với phần còn lại của mã và thực hiện giống như trong mã gần đó.

Tôi sẽ nói đi với hai vectơ riêng biệt, như thế này:

class Vector2
{
    float x, y;
    //helper functions like operator overload, dot, length, distance, etc.
}

class GameObject
{
    Vector2 position;
    Vector2 size;
    Vector2 direction;
}

Bằng cách này, bạn có thể xử lý những thứ như góc giữa các đối tượng dễ dàng hơn, như vậy:

GameObject foe;
GameObject player;
Vector2 dist = player.position - foe.position;
dist.normalize();
float angleBetween = acos(dist.dot(foe.direction));

thay vì phải trích xuất các vectơ từ hình chữ nhật, hoặc tạo chúng từ phao trơn.


2

Nói chung, luôn luôn sử dụng một cấu trúc dữ liệu riêng biệt. Nó làm cho mã của bạn dễ sử dụng, đọc và bảo trì hơn đáng kể. Tần suất bạn cần xtách biệt yso với tần suất bạn cần tính toán bù vector, chiều dài, chấm sản phẩm, v.v.? Nhằm mục đích cho trường hợp phổ biến; làm cho mã bạn viết lặp đi lặp lại dễ dàng hơn để làm việc với, đối với các điểm và vectơ, thường sẽ là các hoạt động trên toàn bộ "đối tượng" thay vì hoạt động trên các thành phần riêng lẻ.

Ngoại lệ duy nhất tôi sẽ làm là, sau khi định hình đúng , bạn thấy cấu trúc riêng biệt quá chậm. Các ngôn ngữ như Ruby không thể tạo ra "giá trị" đơn giản do người dùng xác định và theo kinh nghiệm của tôi, việc có các điểm và vectơ là loại "tham chiếu" đôi khi là một nỗi đau và có thể là một sự chậm chạp lớn mà không chú ý cẩn thận đến thời gian . Chẳng hạn, có thể có hai mảng int, một cho xvà một cho y, sau đó có một mảng các Pointđối tượng; Mặc dù vậy, thật khó để làm việc với nó, vì vậy chỉ nên chia nhỏ nếu bạn có số liệu hiệu suất hợp lệ để cho biết nó đáng giá!


+1, nhưng tôi muốn đề cập rằng tiền sinh sản là gốc rễ của mọi tội lỗi.
Gustavo Maciel

3
@GustavoMaciel: thực sự. Sự thật: Cruella de Vil chỉ cố gắng tối ưu hóa tủ quần áo của mình trước khi dọn dẹp tính cách của cô ấy, và xem nơi nào có được cô ấy.
Sean Middleditch
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.