2011-02-06 112 views
6

我试图在我的第一个xna 2d游戏中模拟重力。我有以下Xna将重力加到2d精灵上

 //Used for Jumping 
    double elapsedAirTime = 0.0; 
    double maxAirTime = 8.35; 
    //End Jumping 

所以,我想通过一定量的移动精灵了,而elapsedAirTime < maxAirTime 然而,有一些问题,即我的代码似乎只有一次,不能多移动精灵了在这段时间内。这里是我的“player.cs”类中的代码,或者类的更新方法。

if (newState.IsKeyDown(Keys.Space)) 
     { 
      if(oldState.IsKeyUp(Keys.Space)) 
      { 
       //if we are standing or jumping then change the velocity 
       if (playerState == PlayerStates.Standing) 
       { 
        playerState = PlayerStates.Jumping; 
        this.position.Y -= (float)(30.0 + ((1.2)*elapsedAirTime)*elapsedAirTime); 
       } 
      } 
     } 
     //if we are jumping give it some time 
     if (playerState == PlayerStates.Jumping) 
     { 
      if ((elapsedAirTime < maxAirTime) && position.Y < 3) 
      { 
       this.position.Y -= (float)(30.0 + ((1.2) * elapsedAirTime)*elapsedAirTime); 
       elapsedAirTime += gameTime.ElapsedGameTime.TotalSeconds; 
      } 
      //otherwise time to fall 
      else 
      { 
       playerState = PlayerStates.Falling; 
      } 

     } 

     //add gravity to falling objects 
     if (playerState == PlayerStates.Falling || playerState == PlayerStates.Standing) 
     { 
      //if we are above the ground 
      if (this.position.Y < windowBot - 110) 
      { 
       //chnage state to falling 
       playerState = PlayerStates.Falling; 
       this.position.Y += 3.0f + ((float)(gameTime.ElapsedGameTime.TotalSeconds)); 
      } 
      else 
      { 
       playerState = PlayerStates.Standing; 
       elapsedAirTime = 0.0f; 
      } 
     } 

任何帮助,非常感谢,请和谢谢!

回答

11

为了让你的精灵有引力的感觉,你应该为你的精灵类添加速度和加速度。然后,为Sprite创建一个Update方法,并在每次更新时将加速度添加到您的速度中,并将速度添加到每次更新的位置。位置不应该以经过的空气时间为基础。您可以将加速度设置为恒定的重力值,然后在跳跃时添加到Sprite的速度。这将创建一个流畅的抛物线跳跃,看起来不错。如果你想包括时间,你可以将GameTime传递给Sprite的更新方法,并将其用作速度修改器。下面是一个例子更新方法:

 
void Update(GameTime gt) 
{ 
    int updateTime = gt.ElapsedGameTime.TotalMilliseconds - oldgt.ElapsedGameTime.TotalMilliseconds; 
    float timeScalar = updateTime/AVG_FRAME_TIME; 
    this.velocity += this.acceleration * timeScalar; 
    this.position += this.velocity; 
    oldgt = gt; 
} 

如果使用时间,这种方法有点复杂。你必须跟踪更新花费了多少时间,然后将它除以更新或帧应该花费的平均时间量,以获得应该调整速度的量。如果没有时间,方法很简单:

 
void Update() 
{ 
    this.velocity += this.acceleration; 
    this.position += this.velocity; 
} 

我会建议使用简单的方法,直到你明白究竟如何定时工作,以及为什么需要实现它。

+0

为什么要计算timeScalar并存储旧的游戏时间?如果这个更新函数在每个游戏循环中都被调用(它应该是这样),那么gt.ElapsedGameTime已经为你做了所有繁重的工作。 – 2011-02-09 19:49:09

2

看起来这一行有过错:

this.position.Y -= (float)(30.0 + ((1.2) * elapsedAirTime)*elapsedAirTime); 

我想你会发现,这将更新精灵位置速度比你想象的,精灵将移动330个像素在屏幕的10次更新(假设Game.IsFixedTimeStep == true)即十分之一秒实时

很可能这只是更新得如此之快以至于在&& position.Y < 3条件开始并更改playerState之前没有看到它升高。

它看起来像你想说的 - 只要空间被保持,它就以每秒x像素的速度跳跃高达8.5秒。

您需要的是将计算更改为this.position.y -= (float) (30 * gameTime.ElapsedGameTime.TotalSeconds),这将给跳跃动作带来非常直线的移动,但这意味着精灵会以每秒30个像素跳跃。

如果Game.IsFixedTimeStep == true - 这是默认值 - 更新每秒被调用60次,所以gameTime.ElapsedGameTime.TotalSeconds将在每次更新时约为0.1。如果某些事情导致更新跳过(例如渲染问题),则更新将延迟,并且gameTime.ElapsedGameTime.TotalSeconds可能为0.3(跳过2次更新),但公式仍然计算出正确的跳转率。