【问题标题】:XNA Sprite ClassXNA 精灵类
【发布时间】:2013-11-26 10:15:27
【问题描述】:

我正在使用 XNA 3.0 并尝试制作一个精灵类,但不确定如何处理它。我是否在精灵类中执行动画?我的代码也不断收到错误

Game1.cs

protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin();
        Sprite.Draw(spriteBatch);
        base.Draw(gameTime);
    }

Sprite.cs

private static Texture2D rings;

    Point rings_frameSize = new Point(75, 75);
    Point rings_currentFrame = new Point(0, 0);
    Point rings_sheetSize = new Point(6, 8);

    int ms_elapsedRings = 0;

    public static void setup_sprites(ContentManager Content)
    {
        rings = Content.Load<Texture2D>("Images/threerings");
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(rings,
                         new Vector2(0,0),
                         new Rectangle(rings_currentFrame.X * rings_frameSize.X, //X component of where to begin
                                       rings_currentFrame.Y * rings_frameSize.Y, //Y component of where to begin
                                       rings_frameSize.X,  //cell width
                                       rings_frameSize.Y), //cell height
                         Color.White,
                         0,
                         Vector2.Zero,
                         1,
                         SpriteEffects.None,
                         0);
    }

返回

错误 1 ​​非静态字段、方法或属性 'WindowsGame1.Sprite.Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch)' C:\Users\XXXXXX\Documents\Visual Studio 需要对象引用2008\Projects\WindowsGame1\WindowsGame1\Game1.cs 107 13 WindowsGame1

【问题讨论】:

标签: c# animation xna sprite xna-3.0


【解决方案1】:

首先,您的第二个错误:非静态字段、方法或属性需要对象引用”。

在面向对象的编程中,程序通过类和继承等概念具有结构的好处,这与历史上的命令式编程相反,其中“程序”由一系列基本指令组成,一个接一个。在面向对象编程中,一个类代表一些抽象实体。这样的实体可以是动物、汽车、电视。在这种情况下,您可以编写一个class Car 并“创建”许多Car 对象的“实例”,其中一个可能称为本田、另一辆宝马和另一辆劳斯莱斯。但有时,创建一个类的实例是没有意义的。如果你的课不是汽车怎么办——如果是“数学”怎么办。拥有“数学”课程是完全有效的 - in fact, the .NET framework has a Math class。但在这种情况下,拥有 Math 的“实例”是没有意义的。数学就是数学。这是一项研究——而且只有一项。

因此,非静态方法的访问方式如下:

Car honda = new Car();
honda.Drive();

说 Car.Drive() 没有意义,因为您指的是哪辆车? Car,作为一个类,只是一个通用的蓝图——你想调用 new Car() 以从该类蓝图中制作一些具体的对象。

另一方面,静态方法被访问,如下所示:

Math.Add();

Math myMath = new Math(); 没有意义,这就是为什么 Math 是它自己的静态类。

现在,您已经创建了您的方法setup_sprites()static。您可能会认为此设置方法应该是静态的,因为无论创建了多少个精灵,每个创建的精灵在设置期间都将访问相同的纹理。如果你想以这种方式创建你的 sprite 类,那很好 - 但是你必须让你的整个 sprite 类成为静态的,因为静态方法和变量不能访问非静态方法和变量

一般来说,Sprite 类不是静态的。您可以在此处阅读有关静态与非静态的更多信息:http://msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.80%29.aspx

现在,您的第一个问题。如何将动画集成到代码中完全取决于您。看起来您正在将动画代码嵌入到 Draw() 方法中。这没有错,但可能有更好的解决方案。

面向对象编程有一些原则可以使复杂性保持优雅简单,其中之一是Single Responsibility Principle,简单来说,它建议程序员只给一个类一个职责。你的 Sprite 类应该简单地加载它的资源,绘制它自己,然后卸载它的资源。这就是精灵应该做的。

但是动画呢?这就是面向对象编程的用武之地——分工;您不必将所有内容都粘贴到 Sprite 类中。您有两个选择:您可以以继承自Sprite 类的AnimatedSprite 类的形式扩展您的Sprite 功能,或者您可以以Animatable 接口的形式扩展您的Sprite 功能.这里的设计问题是:类扩展还是接口扩展?

您可以在此处阅读有关辩论的更多信息:http://www.codeproject.com/Articles/11155/Abstract-Class-versus-Interface

在那篇文章中我真正喜欢的是以下定义:抽象类定义核心功能,而接口描述外围属性。

你的精灵不仅可以动画,还可以移动。这些听起来更像是属性而不是核心功能。它有动画的能力。它有移动的能力。有些人认为接口具有“has-a”关系,而类被认为具有“is-a”关系。你的类本质上不是动画——它首先是一个精灵。它然后有动画的能力。

所以我认为你应该通过添加一个Animatable 接口来扩展你的Sprite 类。您实际上想将其称为 IAnimatable,以保留命名标准。

所以你最终可能会得到这样的东西(伪代码):

public class Sprite : IAnimatable
{
    private Texture2D rings;

    public void LoadContent(ContentManager Content)
    {
        // Call this method from Game.LoadContent()
        rings = Content.Load<Texture2D>("Images/threerings");
    }

public void Draw(SpriteBatch spriteBatch)
    {
        if (IsAnimating)
        {
            // Incorporate IAnimatable variables here to draw your animation
        }
    }

}

public interface IAnimatable
{
    public bool IsAnimating {get; set;}
    public int CurrentFrameIndex {get; set;}
    public Point FrameSize {get; set;}
}

在未来,你甚至可能拥有:

public interface IMovable
{
    public bool IsMoving {get; set;}
    public Point CurrentLocation {get; set;}
    public Point DestinationLocation {get; set;}
}

并将所有这些整合到:

public class NpcSprite : Sprite, IMovable, IAnimatable
{
}

确实,即使使用接口,您最终仍会在 Sprite 类中编写接口代码,但至少您已经在精灵、动画精灵和可移动精灵之间建立了明确的约定。以后编辑和扩展会容易得多。

【讨论】:

    猜你喜欢
    • 2011-11-13
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多