制作一个基本的奔跑精灵效果
本文关键字:奔跑 精灵 一个 | 更新日期: 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。这样可以很容易地得到要绘制的帧号。