Когда я должен представлять точки и размеры как структуры?

9

Как часть моей простой среды разработки игр на Ruby 2D, мои игровые объекты имеют положение (значения x и y) и размер (ширина и высота).

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

Другой подход, который я видел, рассматривал позицию как Pointструктуру, а размер как Sizeструктуру:

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

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

Некоторые фреймворки используют первые (я думаю, GDX, Gosu ...). Другие используют последний (cocos2d-iphone). Проблема в том, что мне не совсем понятны преимущества и недостатки обоих видов поведения (в разработке игр) - я не знаю, почему некоторые фреймворки выбрали один, а не другой.

Есть ли существенные различия, которые я должен рассмотреть?

оксид
источник

Ответы:

8

Некоторые даже используют Rectangleкласс:

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

Это просто выбор дизайна, это не имеет значения. Если вы делаете свой собственный код, сделайте то, что вам удобнее. Если вы используете какой-то API, фреймворк или движок или редактируете / модифицируете игру, постарайтесь быть согласованными с остальным кодом и делайте то же самое, что и в соседнем коде.

Я бы сказал, чтобы пойти с двумя отдельными векторами, как это:

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

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

Таким образом, вы можете легче обрабатывать такие вещи, как угол между объектами, например

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

вместо того, чтобы извлекать векторы из прямоугольников или создавать их из простых чисел.

Густаво Масиэль
источник
2

В общем, всегда используйте отдельную структуру данных. Это значительно упрощает использование, чтение и обслуживание вашего кода. Как часто вам нужно xотделяться отy vs, как часто вам нужно вычислять векторное смещение, длину, точечное произведение и т. Д.? Стремиться к общему делу; сделать код, который вы пишете многократно, проще для работы, что для точек и векторов обычно будет операциями над всем «объектом», а не операциями над отдельными компонентами.

Единственное исключение, которое я сделал бы, - после правильного профилирования вы обнаружите, что отдельная структура слишком медленная. Такие языки, как Ruby, не делают возможным простое определяемое пользователем «по значению», и, по моему опыту, наличие точек и векторов в качестве «по ссылкам» типов иногда является болью и может привести к значительному замедлению без внимательного отношения к временным специалистам. , Например, может быть выгодно иметь два массива целых, один для xи один для y, а затем иметь один массив Pointобъектов; работать с ним гораздо труднее, хотя делайте это только в том случае, если у вас есть действительные показатели производительности, которые указывают на его ценность!

Шон Миддледич
источник
+1, но я хотел бы отметить, что предоптимизация является корнем всего зла.
Густаво Масиэль
3
@GustavoMaciel: действительно. Факт: Круэлла де Виль просто пыталась оптимизировать свой гардероб, прежде чем навести порядок в своей личности, и посмотреть, откуда она ее взяла.
Шон Мидлдич