【问题标题】:How to manage "speed" in a simple racing game?如何在简单的赛车游戏中管理“速度”?
【发布时间】:2010-10-19 12:49:42
【问题描述】:

我正在尝试用 C# sdl.net 开发一个简单的赛车 2d 游戏(自上而下查看)。 现在,我正在尝试管理我的汽车的速度、加速度和刹车。 我的问题是算法。 我有循环(Events_Tick)每秒执行 50 次,其中我的汽车位置处理如下:

private void Events_Tick(object sender, TickEventArgs e)
{
    car.ProcessPosition();
}

ProcessPosition 类似于:

if (throttle)
{
    speed += 1;
    x += 1;                        
}

最后,我在新的 X 上绘制我的精灵。

问题是太快了!

所以我问你如何保持 50 FPS(每秒帧数)并且每秒只移动我的精灵(汽车)N 个像素(基于它的速度)。

提前感谢您!问候!

【问题讨论】:

    标签: c# algorithm


    【解决方案1】:

    首先,因为你有 2d 而不是 1d 游戏,所以你需要你的速度是

    class Vector
    {
         double x;
         double y;
    }
    

    有了这个类,你应该保持位置和速度。

    由于您是 2d 自上而下的,因此您必须在速度向量上实现一些 .RotateLeft().RotateRight()

    旋转的实现方式如下:

    x' = cos(a) * x - sin(a) * y
    y' = sin(a) * x + cos(a) * y
    

    您必须按如下方式实现您的.Move() 方法:

    void Move(Vector v)
    {
        x+=v.x;
        y+=v.y;
    }
    

    编辑:请询问是否需要澄清,或者进行更深入的讨论。

    另外,您可以在这里使用计时器,但尝试计算从上次计时器事件花费的时间,然后在添加到当前位置时将速度乘以该值,这样您将获得更准确的位置。

    sin()cos() 中的a 将以弧度为单位,您可能需要这里的度数。

    这里是something,可以帮助您了解度数和弧度。

    【讨论】:

    • 嗨,丹尼尔,谢谢。我想问你关于轮换的问题:你能给我一些额外的信息吗?我数学不好,所以我问你:关于 sin(a) .. 什么是 a ?角度?
    • 是的,a 是角度,单位是弧度。您可能需要以度为单位,因此您可以一次将汽车旋转 15 度。无论如何,什么时候可以展示的时候给我看游戏:)
    【解决方案2】:

    对速度和x使用双精度值,然后你可以使用Math.Round(x)进行绘图。

      if (throttle == true) {
            speed+=0.05;                    
      }
      x+=speed; //move car even without acceleration
    

    遵循 Henk 的建议,让您的程序更加灵活,并能够向用户显示 50mph 而不是每 0.02 秒 0.05px 的速度:

    double speedInMph = 50;
    double screenSizeInMiles = .1;
    double screenSizeInPx = 500;
    
    if(throttle)
    {
        speedInMph += 1;
    }
    double speedInMpms = 50/(60*60*1000);//Miles per millisecond
    double xInMiles = speedInMpms * 50;
    double pxPerMile = screenSizeInPx/screenSizeInMiles;
    x+= xInMiles * pxPerMile;
    

    【讨论】:

      【解决方案3】:

      加速度将保持不变,具体取决于用户输入(简单来说,汽车要么加速、减速或保持速度)。

      速度将根据该加速度改变每一帧。每一帧,根据加速度和帧覆盖的一秒的比例(即在您的情况下为 1/50 秒)更新汽车的速度。

      因此,如果您的汽车以每秒 10 个单位距离的速度加速,在您的示例中,速度将增加每帧单位距离的 1/5。

      只是认为值得对其他答案进行一些详细说明,而不是仅仅发布更多代码:-)

      【讨论】:

        【解决方案4】:

        您应该根据当前加速度添加速度并使用控件处理加速度,使用上限限制速度并根据两个游戏循环迭代之间经过的时间增加速度。

        float accel = 10.0f; // units per squared second
        float maxSpeed = 50.0f // units per second
        float curSpeed = 0.0f;
        
        //game init
        
        while (1) {
          long timeBefore = time();
          // game loop
          long timeElapsed = time() - timeBefore;
        
          if (throttle) {
            curSpeed += accel*(timeElapsed / 1000.0);
            if (curSpeed > maxSpeed)
              curSpeed = maxSpeed;
          }
        }
        

        通过这种方式,您会考虑到这样一个事实,即较长的车架比较快的矿石更能提高您的车速,并使其与时间保持一致。

        此模型意味着恒定加速度,而您可能假设需要一个动态模型,在这种情况下,您只需将更新移动到加速度(考虑到帧持续时间作为速度)并将其限制为不超过固定阈值.

        【讨论】:

          【解决方案5】:

          亨克是对的。你会想要创建一个

          Thread
          

          并调用它的

          Sleep(Int32)
          

          循环中每次减慢动画的方法,其中 int 参数是以毫秒为单位的暂停时间。

          在您的情况下,您将希望每次循环移动汽车 N/50 像素,并且每次使线程休眠 20 毫秒。

          【讨论】:

          • 我假设他当前使用的是 Timer WinForms 控件(或者可能是 System.Timers.Timer),所以这可能不会成为问题。
          猜你喜欢
          • 2012-10-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-19
          相关资源
          最近更新 更多