制作一个基本的奔跑精灵效果

本文关键字:奔跑 精灵 一个 | 更新日期: 2023-09-27 18:16:30

我正在用XNA创建我的第一款游戏,我试图让我的精灵运行起来。在第一个精灵中一切都运行良好。例如:如果我向右移动(D),我的精灵就会向右移动,如果我向左移动(A),我的精灵就会向左移动,如果我不触碰任何东西,我的精灵就是默认的。现在我想做的是,如果精灵向右,我想改变精灵(左腿,右腿,左腿等)xCurrent是当前绘制的精灵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;

            }

任何想法……?我被这个问题困扰了一段时间。如果您需要代码中的任何其他部分,请提前感谢我。

制作一个基本的奔跑精灵效果

您忘记重置计时器了,您可以在达到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);
在你的Draw()方法中,调用:
SpriteBatch.Draw(animatedTexture, new Rectangle(20, 20, 64, 64), animatedTexture.DrawFromRectangle, Color.White);

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

现在,在你的代码中,你可以忘记interval部分和gametime部分,你可以用它来代替默认的那个!

同样,如果你不喜欢我的计时代码(它非常简单,但缺乏重置动画的方法),改变它,这样你就有了一个经过的时间变量,并像你在自己的代码中那样添加它,并使用它来改变_currentImage。你甚至可以把这个变量设为public,这样你就可以用它来重置动画(或者把它设为一个指定的点)。

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

您需要保留Update(..)最后一次被调用的时间,并且间隔应该是…嗯. .一个间隔,即ElapsedGameTime和最后一次调用更新ElapsedGameTime之间的差异。使用类的新成员(lastelapsedgametimeupdateccalled)或子的静态成员来完成。

如果你知道每个动画都有相同的帧数,你可以为每个精灵保留3个变量(将其封装在类中以获得最佳效果)。BaseFrame是一个保存全局动画数的整数。子帧是动画的一个偏移量,它保留了你当前所处的帧。FrameAccumulator保存计时信息。

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

假设每个动画有3帧,你总共有2个动画。总共有6帧。RunLeft将是BaseFrame 0,而RunRight将是BaseFrame 3。这样可以很容易地得到要绘制的帧号。