0

这是我在考虑封装和组合的情况下编写的代码示例:

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);

更新:如果你想缩小这个问题,值得一读。这是移动 s 的期望逻辑的简化示例Bullet(我并不是指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 classes的一些属性。

4

1 回答 1

2

从设计的角度来看,如果您的子弹不知道如何检测它何时...通过障碍物 (scnr),这可能是最好的。所以最好把你的Bullet类变成 a 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检查从子弹当前位置到新位置的线是否dest与任何障碍物相交并计算反射参数。实际上,您曲折前往目的地,这将是子弹的所有连续乒乓球与潜在障碍的结果。

于 2020-05-28T21:37:03.800 回答