XNA SpriteBatch 绘制扩展方法抛出 ArrayTypeMismatchException
我正在为 XNA 制作动画课程。我决定尝试使用 SpriteBatch 的扩展方法来添加可以绘制 AnimatedSprite 的 Draw 方法。
AnimatedSprite包含一个Sprite对象的列表,一个Sprite对象有一个Texture2D图像。 我创建了一个静态扩展类,其中包含 Draw 方法的不同重载。
这是一种这样的方法(我假设所有函数的问题都是相似的):
public static void Draw(this SpriteBatch b, AnimatedSprite sprite, Vector2 position, Color color)
{
b.Draw(sprite.CurrentSprite.Image, position, color);
}
当我运行我的项目时,我得到一个 ArrayTypeMismatchException 。我不确定是什么原因造成的,因为 sprite.CurrentSprite.Image
是一个Texture2D。
希望有人能够帮助我了解导致此问题的原因以及潜在的解决方案。
谢谢!
更新:AnimatedSprite 类
public class AnimatedSprite
{
List<Sprite> frames;
double elapsedSeconds;
int currentIndex;
/// <summary>
/// CurrentSprite is the current frame the animation is on
/// Use CurrentSprite.Image to get the underlying Texture2D
/// </summary>
public Sprite CurrentSprite { set; get; }
/// <summary>
/// FrameRate is the frame rate of the animation, measured
/// in frames per second
/// </summary>
public int FrameRate { set; get; }
bool shouldAnimate;
/// <summary>
/// Constructor for AnimatedSprite
/// </summary>
/// <param name="sprites">A list of sprites, cannot be left null</param>
/// <param name="frameRate">The framerate in frames per second</param>
/// <exception cref="ArgumentException">Thrown if sprites is null</Sprite></exception>
public AnimatedSprite(List<Sprite> sprites, int frameRate)
{
if (sprites == null) throw new ArgumentException("Please provide a non-null List<Sprite>");
this.frames = sprites;
this.currentIndex = 0;
if(this.frames.Count != 0) this.CurrentSprite = frames[currentIndex];
this.FrameRate = frameRate;
this.elapsedSeconds = 0;
}
/// <summary>
/// Add a frame to the animation. It will be added to the end.
/// </summary>
/// <param name="frame">The Sprite you would like to add</param>
public void AddFrame(Sprite frame)
{
frames.Add(frame);
if (frames.Count == 1) this.CurrentSprite = frames[0];
}
/// <summary>
/// Call this function in any Update method to continue the animation
/// </summary>
/// <param name="gameTime">The gameTime object keeping track of time</param>
public void Update(GameTime gameTime)
{
elapsedSeconds += gameTime.ElapsedGameTime.TotalSeconds;
if (elapsedSeconds > (1.0 / FrameRate) && shouldAnimate)
{
NextFrame();
elapsedSeconds = 0;
}
}
#region Animation Controls
/// <summary>
/// Starts the animation. This MUST be called to start the animation
/// </summary>
public void Start()
{
shouldAnimate = true;
}
/// <summary>
/// Stops the animation. Call Start() to start again
/// </summary>
public void Stop()
{
shouldAnimate = false;
}
/// <summary>
/// Advances the animation to the next cell
/// </summary>
public void NextFrame()
{
if (frames.Count == 0) return;
currentIndex++;
if (currentIndex >= frames.Count) currentIndex = 0;
this.CurrentSprite = frames[currentIndex];
}
/// <summary>
/// Advances the animation to the previous cell
/// </summary>
public void PreviousFrame()
{
if (frames.Count == 0) return;
currentIndex--;
if (currentIndex < 0) currentIndex = frames.Count - 1;
this.CurrentSprite = frames[currentIndex];
}
#endregion Animation Controls
I am working on an Animation class for XNA. I decided to try using extension methods for SpriteBatch to add Draw methods that can draw an AnimatedSprite.
AnimatedSprite contains a list of Sprite objects, and a Sprite object has a Texture2D image.
I created a static Extensions class that contains different overloads of the Draw method.
Here's one such method (I assume the problem is similar for all the functions):
public static void Draw(this SpriteBatch b, AnimatedSprite sprite, Vector2 position, Color color)
{
b.Draw(sprite.CurrentSprite.Image, position, color);
}
I get a ArrayTypeMismatchException
when I run my project. I am not sure what is causing it because sprite.CurrentSprite.Image
is a Texture2D.
Hopefully someone will be able to help me understand what is causing this problem and a potential fix.
Thanks!
Update: AnimatedSprite Class
public class AnimatedSprite
{
List<Sprite> frames;
double elapsedSeconds;
int currentIndex;
/// <summary>
/// CurrentSprite is the current frame the animation is on
/// Use CurrentSprite.Image to get the underlying Texture2D
/// </summary>
public Sprite CurrentSprite { set; get; }
/// <summary>
/// FrameRate is the frame rate of the animation, measured
/// in frames per second
/// </summary>
public int FrameRate { set; get; }
bool shouldAnimate;
/// <summary>
/// Constructor for AnimatedSprite
/// </summary>
/// <param name="sprites">A list of sprites, cannot be left null</param>
/// <param name="frameRate">The framerate in frames per second</param>
/// <exception cref="ArgumentException">Thrown if sprites is null</Sprite></exception>
public AnimatedSprite(List<Sprite> sprites, int frameRate)
{
if (sprites == null) throw new ArgumentException("Please provide a non-null List<Sprite>");
this.frames = sprites;
this.currentIndex = 0;
if(this.frames.Count != 0) this.CurrentSprite = frames[currentIndex];
this.FrameRate = frameRate;
this.elapsedSeconds = 0;
}
/// <summary>
/// Add a frame to the animation. It will be added to the end.
/// </summary>
/// <param name="frame">The Sprite you would like to add</param>
public void AddFrame(Sprite frame)
{
frames.Add(frame);
if (frames.Count == 1) this.CurrentSprite = frames[0];
}
/// <summary>
/// Call this function in any Update method to continue the animation
/// </summary>
/// <param name="gameTime">The gameTime object keeping track of time</param>
public void Update(GameTime gameTime)
{
elapsedSeconds += gameTime.ElapsedGameTime.TotalSeconds;
if (elapsedSeconds > (1.0 / FrameRate) && shouldAnimate)
{
NextFrame();
elapsedSeconds = 0;
}
}
#region Animation Controls
/// <summary>
/// Starts the animation. This MUST be called to start the animation
/// </summary>
public void Start()
{
shouldAnimate = true;
}
/// <summary>
/// Stops the animation. Call Start() to start again
/// </summary>
public void Stop()
{
shouldAnimate = false;
}
/// <summary>
/// Advances the animation to the next cell
/// </summary>
public void NextFrame()
{
if (frames.Count == 0) return;
currentIndex++;
if (currentIndex >= frames.Count) currentIndex = 0;
this.CurrentSprite = frames[currentIndex];
}
/// <summary>
/// Advances the animation to the previous cell
/// </summary>
public void PreviousFrame()
{
if (frames.Count == 0) return;
currentIndex--;
if (currentIndex < 0) currentIndex = frames.Count - 1;
this.CurrentSprite = frames[currentIndex];
}
#endregion Animation Controls
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
唯一使用的数组是 sprite.CurrentSprite。这(我假设)使用您存储在动画精灵类中的内部索引来返回精灵数组中该索引处的精灵。由于这是您使用数组的唯一地方,因此这就是您的问题。由于您尚未发布 AnimatedSprite 类代码,我只能建议您查看 AnimatedSprite 类中的属性 CurrentImage 并查看它是否访问 Sprite[]。请发布 AnimatedSprite 类,以便我可以为您提供更多帮助。
另外,在我个人看来,您不应该在 AnimatedSprite 中存储 sprite 类的实例,您应该只存储纹理数组。存储精灵数组意味着每个精灵都是独立的实体,但事实并非如此;它们是同一个动画精灵的一部分。
The only array used is sprite.CurrentSprite. This (i assume) uses the internal index you store in your animated sprite class to return the sprite at that index in the sprite array. Since this is the only place you use an array, this is your problem. As you haven't posted your AnimatedSprite class code, I can only suggest that you look at the property CurrentImage in your AnimatedSprite class and see if it accesses a Sprite[]. Please post the AnimatedSprite class so I can help you more.
Also, in my personal opinion, you should not be storing instances of the sprite class in AnimatedSprite, you should just store an array of textures. Storing an array of Sprite's implies that each of those sprites are separate entities, which they aren't; they are part of the same animated sprite.