【问题标题】:Asteroids Game Movement In C#C# 中的小行星游戏运动
【发布时间】:2010-09-03 19:24:29
【问题描述】:

我正在尝试制作游戏 Asteroids。我现在遇到的问题是,如果您按向上箭头键,它会将“船”向上移动 10 个像素。如果你按下左箭头键,它会将“船”向左转 5 度,当你左转或右转时,我遇到的问题就会发挥作用。然后尝试向上移动。它不会向转向的方向移动。它只会将转动的“船”沿 Y 方向移动 10 度。

我想做的是有一个叫做方向的变量,把这个变量想象成一个 360 度的圆。我想要做的是每次我击中左箭头时,它会从方向中减去 5,它从 0 开始并从 360 向后退,因此将其设置为 355。然后我将 355 除以 10 并得到 35.5。然后我将 10 除以 35.5 得到 0.355。然后我会从 10 中减去 0.355(在 Y 轴上向上移动)。并从 0 中减去它(在 X 中向左移动)。所以我会在 Y 轴上移动 9.645,在 X 轴上向左移动 0.355。

我遇到的问题是小行星中的“船”我有一个 Graphics.FillPie,它需要 Ints 用作起始角和扫角,但是正如你所看到的,我必须使用双打或浮动。我很确定我把它复杂化了,而且我很确定有些东西要简单 100 倍,我在想一些类似于 Bresenham 线算法的东西。如果有人可以通过建议更简单的方法或解决我的问题来提供帮助,将不胜感激。提前致谢。

【问题讨论】:

  • tigonometry 在这里会有所帮助。我不知道你是如何提出你的算法的,即使它适用于某些情况,它也可能会在一般情况下返回奇怪的结果。

标签: c# game-physics angle bresenham


【解决方案1】:

听起来您需要根据船的当前方向(以弧度为单位)计算船的航向矢量。例如:

double xVector = Math.Sin(orientationInRadians);
double yVector = Math.Cos(orientationInRadians);

然后使用左右箭头来控制船的当前方向。一旦你有了这个向量,你就可以计算出船的位置,它沿着航向向量距离其当前位置 10 个单位。首先,您需要将向量缩放为单位(长度为 1)向量。

double magnitude = sqrt(xVector*xVector + yVector*yVector);
double unitVectorX = xVector/magnitude;
double unitVectorY = yVector/magnitude;

现在你有一个 1 个单位长但仍指向飞船当前方向的向量。接下来以 positionX 和 positionY 作为当前坐标移动船。

double distanceToTravel = 10;
double newPositionX = positionX + unitVectorX*distanceToTravel;
double newPositionY = positionY + unitVectorY*distanceToTravel;

即使您最终使用仅允许整数的系统进行渲染,您也需要使用双精度或浮点数来跟踪船的位置和方向。您不应该使用渲染引擎的精度存储当前位置和方向,否则您将在移动和旋转时开始看到奇怪的跳跃和暂停。此外,使用上述方法,您可以使 distanceToTravel 变为非常量(想象在按下键时加速,而不是从按键移动固定距离)。

【讨论】:

  • +1 提到三角法是一种计算方向的方法。
  • 打败我 :) +1 为简单起见,为矢量提供。
  • 是我遗漏了什么还是“幅度”总是为 1? Math.Sin 和 Math.Cos 肯定会返回单位圆上的值,不是吗?
  • @dash-tom-bang - 你是对的,在这种情况下,幅度部分是不必要的。
  • 我一直使用类似newPositionX = positionX + Math.Sin(orientationInRadians)*distanceToTravel; 的东西,其工作方式完全相同。
【解决方案2】:

你想多了。 ;> 只需使用矩阵变换来旋转和移动船。当船指向“西北”并且用户按下向上键时,您将船的平移矩阵在船的 Y 轴上调整 10 个单位。您应用旋转和平移矩阵将船的坐标系转换为屏幕坐标系。操作顺序很关键 - 如果您在旋转之前应用平移,那么飞船将围绕中心点摆动,而不是围绕飞船原点旋转,然后平移到新的“前进”方向。

由于您可以使用相同的矩阵变换进行绘图,因此您可以仅以相对于其局部坐标系的相同固定方向(机头指向“向上”正 Y 轴)绘制船。图像的旋转将由矩阵变换处理。

【讨论】:

  • +1 虽然这个解决方案更复杂,但它会更容易过渡到 3D 游戏。请注意,矩阵将有很多零,并且变换将以一种或另一种方式产生与公认解中列出的完全相同的简单方程。
  • 好吧,这种方法需要/假设您在任何框架或环境中都有一个好的转换引擎可用。如果您必须从头开始实现所有内容,直接计算会更快自己旋转(如其他答案)而不是实现自己的世界变换层。但是,如果您已经有一个很好的转换堆栈(如在 WinGDI、DirectX、OpenGL 中),则相对于自己的坐标处理(移动、绘制)船要容易得多,IMO。一切都与某物有关。 Ender Wiggin 的定位规则:“敌人的大门已经关闭”。
【解决方案3】:

我不想带走你的乐趣,但你总是可以下载别人的代码并查看它以找出如何用你自己的方法来做。你可以在这里得到一个实现:http://www.c-sharpcorner.com/UploadFile/dannaboneheart/Asteroids11292005064500AM/Asteroids.aspx

这里是:http://www.codeproject.com/KB/game/hucsharpasteroids.aspx

【讨论】:

    【解决方案4】:

    在内部使用浮点数并在需要以这种方式使用它们时将它们转换为整数没有问题:

    double angle = ...;
    int angleAsInt = (int)Math.Round(angle);
    

    我建议您考虑使用三角函数,如 sincos 来确定速度和加速度的 X 和 Y 分量。

    【讨论】:

      【解决方案5】:

      你还没有提到的一点是,在 Asteroids(R) 品牌的街机和由此衍生的视频游戏中,玩家的飞船具有惯性。因此,您需要跟踪船舶的速度。您应该在每一帧中执行以下操作:

      if (thrusting)
      {
        XVelocity += (XVelocity - Math.Cos(Heading)*MAX_SPEED) * (1/INERTIA_CONSTANT);
        YVelocity += (YVelocity - Math.Sin(Heading)*MAX_SPEED) * (1/INERTIA_CONSTANT);
      }
      else
      {
        XVelocity -= XVelocity * (1/FRICTION_CONSTANT);
        YVelocity -= YVelocity * (1/FRICTION_CONSTANT);
      }
      
      XPosition += XVelocity; // Do twice--once before and once after speed adjust
      YPosition += YVelocity;
      

      请注意,有些游戏只是将速度添加到余弦/正弦的常数倍。这样做会带来不幸的后果,如果玩家将他的船指向某个方向并开始连续推进,那么船每帧经过的距离可能会增长到荒谬的极限。如图所示的代码将导致加速度随着船的速度渐近接近最大值而减小。

      【讨论】:

        猜你喜欢
        • 2015-07-01
        • 1970-01-01
        • 2014-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-02
        相关资源
        最近更新 更多