Как можно предоставить моему классу некоторую информацию о его среде? - PullRequest
0 голосов
/ 28 мая 2020

Вот пример кода, который я написал с учетом инкапсуляции и композиции:

class Bullet {
 private:
  Vector2 position;
  Vector2 speed;

 public:
  void move(float time_delta) {
    position += speed * time_delta;
  }
};

По сути, это просто снаряд, движущийся в никуда. Однако на самом деле пуля может, например, отрикошетить от стены, в результате чего ее speed значительно изменится. Есть ли хороший способ рассмотреть такие взаимодействия? Я не хочу, чтобы мой Bullet знал о классах «более высокого ранга» (которые должны сами его использовать) и не писал одноразового решения вроде этого:

template<typename F> void move(float time_delta, F collision_checker);

UPDATE: стоит прочитать, если вы хотите сузить этот вопрос. Вот упрощенный пример желаемых logi c для перемещения Bullet s (я не имею в виду функцию-член Bullet::move()!) И их взаимодействия с другими сущностями:

Vector2 destination = bullet.position + bullet.speed * time_delta;
if (std::optional<Creature> target = get_first_creature(bullet.position, destination)) {
  // decrease Bullet::speed depending on the target (and calculate the damage)
} else if (std::optional<Wall> obstacle = get_first_wall(bullet.position, destination)) {
  // calculate the ricochet changing Bullet::position and Bullet::speed
}

Все части кода, представленного комментариями, предполагается использовать некоторые свойства Creature и Wall class es.

1 Ответ

1 голос
/ 29 мая 2020

С точки зрения дизайна, вероятно, лучше всего, если ваша пуля не умеет определять, когда она ... проходит через препятствие (scnr). Так что, возможно, было бы лучше превратить ваш Bullet класс в struct, т.е. заставить его вести себя как вещь, на которую воздействуют, а не как вещь, которая действует.

Вы все равно можете добавить свою функцию удобства но пусть он не мутирует:

struct Bullet {
  Vector2 position;
  Vector2 speed;
  Vector2 move(float time_delta) const {
    return position + speed * time_delta;
  }
};

Таким образом вы можете вычислить коллизии из вызывающей области:

auto dest = bullet.move(dt);
while (std::optional<Collision> const col = detectCollision(bullet.position,dest)) {
  bullet.position = col->intersectPoint;
  bullet.speed = col->reflectedSpeed;
  dest = col->reflectDest;
}
bullet.position = dest;

Здесь detectCollision проверяет, соответствует ли строка из текущей пули position в новое положение dest пересекает любое препятствие и вычисляет параметры отражения. По сути, вы совершаете зигзагообразный путь к пункту назначения, который возникнет в результате всех последовательных ударов пули с потенциальными препятствиями.

...