制作一个基本的运行精灵效果

时间:2011-11-30 23:37:18

标签: c# xna sprite

我正在使用 XNA构建我的第一个游戏并且我正在尝试让我的精灵运行。 第一个精灵的一切都很好。 例如:如果我向右走(D)我的精灵看起来是正确的,如果我向左走(A)我的精灵向左看,如果我没有触摸任何东西,我的精灵是默认的精灵。 现在我要做的是如果精灵变为右,我想要改变精灵(左腿,右腿,左腿等......) xCurrent 是当前精灵绘制的 xRunRight < / em>是第一个正在运行的Sprite,而 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;


            }

任何想法......?我已经坚持了一段时间.. 提前致谢,如果您需要代码中的任何其他部分,请告知我们。

3 个答案:

答案 0 :(得分: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)用你的纹理启动它(我有一个2560x64的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);

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

现在,在您的代码中,您可以忘记间隔部分和游戏时间部分,您可以使用它而不是默认部分!

另外,如果您不喜欢我的计时代码(它非常简单但缺乏重置动画的方法),请更改它以便您有一个已用时间变量,并像在您自己的代码中一样添加它,并且用它来改变_currentImage。您甚至可以将该变量公开,以便您可以使用它来重置动画(或将其设置为指定点)。

当然,您也可以将默认值设为仅包含一个帧的动画纹理,这样您就可以在任何地方使用相同的代码。希望这有帮助!

答案 1 :(得分:1)

你需要保持最后一次调用Update(..),间隔应该是...... well ..一个间隔,即ElapsedGameTime和最后一次调用更新ElapsedGameTime之间的差异。 使用您班级的新成员(LastElapsedGameTimeUpdateCalled)或您的潜水员的静态成员。

答案 2 :(得分:1)

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

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

让我们说每个动画有3帧,你有2个动画。你总共有6个帧。 RunLeft将是BaseFrame 0,RunRight将是BaseFrame 3.这应该很容易给你绘制的帧号。