2011-11-30 52 views
1

我正在用XNA构建我的第一场比赛,我试图让我的精灵运行。 一切工作正常,为第一个精灵。 例如:如果我向右转(D)我的精灵看起来是正确的,如果我离开(A)我的精灵向左看,如果我没有碰到任何东西,我的精灵是默认的。 现在我想要做的是如果精灵去右,我想要或者改变精灵(左腿,右腿,左腿等)。x当前是当前精灵绘制xRunRight是第一次运行的精灵和xRunRight1是在运行时必须与xRunRight进行交换。 这是我现在有:做一个基本的运行精灵效果

protected override void Update(GameTime gameTime) 
    { 
     float timer = 0f; 
     float interval = 50f; 
     bool frame1 = false ; 
     bool frame2 = false; 
     bool running = false; 

     KeyboardState FaKeyboard = Keyboard.GetState(); 
     // Allows the game to exit 
     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
      this.Exit(); 


      if ((FaKeyboard.IsKeyUp(Keys.A)) || (FaKeyboard.IsKeyUp(Keys.D))) 
      { 
       xCurrent = xDefault; 
      } 

      if (FaKeyboard.IsKeyDown(Keys.D)) 
      { 

       timer += (float)gameTime.ElapsedGameTime.TotalMilliseconds; 
       if (timer > interval) 
       { 
        if (frame1) 
        { 
         xCurrent = xRunRight; 
         frame1 = false; 
        } 
        else 
        { 
         xCurrent = xRunRight1; 
         frame1 = true; 

        } 
       } 

       xPosition += xDeplacement; 


      } 

任何想法...?我一直坚持这一段时间.. 在此先感谢,让我知道如果你需要从代码中的任何其他部分。

+0

我知道帧1,帧2和(定时器>间隔)逻辑不起作用,但它是我意识到它不起作用之前所处的位置。 – phadaphunk

回答

2

您忘了重置计时器,您可以在遇到timer interval条件时执行此操作。另外,50ms似乎有点太小了一段时间,也许你可以做到400ms?

除此之外,看起来不错,它会做你想做的。

或者,您可以考虑制作动画精灵步行。你所做的就是制作一个相同大小的步行动画精灵图像。你只画出这个图像的一部分(一个精灵),然后根据时间移动它们。

这里是什么可能是动画纹理的快速代码:

class AnimatedTexture2D : Texture2D 
{ 
    int _numberOfImages; 
    int _currentImage = 0; 

    int _timeInterval; 
    int _spriteWidth; 

    public Rectangle DrawFromRectangle 
    { 
     get 
     { 
      return new Rectangle(_currentImage * _spriteWidth, 0, _spriteWidth, this.Height); 
     } 
    } 

    public AnimatedTexture2D(Texture2D entireImage, int spriteWidth, int numberOfImages, int timeInterval) 
     : base(entireImage.GraphicsDevice, entireImage.Width, entireImage.Height) 
    { 
     _numberOfImages = numberOfImages; 
     _timeInterval = timeInterval; 
     _spriteWidth = spriteWidth; 

     Color[] data = new Color[entireImage.Width * entireImage.Height]; 
     entireImage.GetData<Color>(0, new Rectangle(0, 0, entireImage.Width, entireImage.Height), data, 0, entireImage.Width * entireImage.Height); 

     this.SetData<Color>(data); 
    } 

    public void Animate(GameTime gameTime) 
    { 
     int totalImageTime = _timeInterval * _numberOfImages; 
     int currentPoint = (int)gameTime.TotalGameTime.TotalMilliseconds % totalImageTime; 

     _currentImage = currentPoint/_timeInterval; 
    } 
} 

用法相当简单:

1)某处声明它:

AnimatedTexture2D animatedTexture; 

2)启动它与你的纹理(我有一个2560×64序列的40 64 * 64图像),其中个别图像水平放置在彼此相邻:

animatedTexture = new AnimatedTexture2D(Content.Load<Texture2D>(@"Textures\Loading"), 64, 40, 20); 

3)在您的Update()方法,调用:

animatedTexture.Animate(gameTime); 

4)在draw()方法,调用:

SpriteBatch.Draw(animatedTexture, new Rectangle(20, 20, 64, 64), animatedTexture.DrawFromRectangle, Color.White); 

不要忘了DrawFromRectangle部分4 ! (注意目标矩形使用声明的单独部分宽度,而不是整个纹理宽度,这是我测试的2560像素)

现在,在您的代码中,您可以忘记间隔部分和游戏时间部分,并且可以只是用这个而不是默认的!另外,如果你不喜欢我的计时代码(它的超级简单但缺乏重置动画的方法),请改变它,让你有一个经过时间的变量,并像你在自己的代码中那样添加它,并用它来改变_currentImage。您甚至可以将该变量设置为公开,以便您可以使用它重置动画(或将其设置为指定点)。

当然,你也可以使默认的一个动画纹理只有一帧,所以你可以在任何地方使用相同的代码。希望这可以帮助!

1

您需要保持最后一次更新(..)被调用,并且间隔应该是...很好..间隔,即ElapsedGameTime和上次调用ElapsedGameTime之间的差值。 使用类的新成员(LastElapsedGameTimeUpdateCalled)或您的子静态成员执行此操作。

1

如果您知道每个动画将具有相同数量的帧,您可以为每个精灵保留3个变量(封装在类中以获得最佳效果)。 BaseFrame是一个整数,用于保存全局动画编号。 子框架是保存您当前所在框架的动画的偏移量。 FrameAccumulator保存定时信息。

每次更新被调用时,将自上次更新以来的ms数加到累加器中。一旦累加器高于动画定时,增加SubFrame并重置累加器。检查subFrame是否大于每个动画的帧数,如果是,则将其设置为0.您可以通过添加BaseFrame + Subframe来从中获取真实帧索引。当您需要显示不同的动画时,只需更改BaseFrame。

可以说每个动画都有3个帧,并且您有2个动画。你将有6个总帧。 RunLeft将是BaseFrame 0,RunRight将是BaseFrame 3.这应该很容易给你绘制的帧号。

相关问题