【问题标题】:Using Static Texture2D's in Classes in XNA在 XNA 的类中使用静态 Texture2D
【发布时间】:2012-03-31 23:51:11
【问题描述】:

在 XNA 中,加载内容是在 init 之后调用的,这很公平,但是它给我带来了一些加载纹理的问题。

在 Init 中,我将 sprite 的 spriteTexture 设置为 Static Texture2D。

然后在 LoadContent 中设置静态 Texture2D 的值。这成功了。

然而,当涉及到 Draw() 方法时 spriteTexture 值仍然为空,导致它失败。我该如何克服这个问题?

感觉它与传递值而不是引用有关。有什么帮助吗?

谢谢, 丹尼

代码: http://pastebin.com/C92ADY7s

【问题讨论】:

    标签: c# xna pass-by-reference


    【解决方案1】:

    必须在调用构造函数之前调用LoadContent 方法。否则不加载纹理,并将 spriteBatch 分配为 null (spriteBatch=null;),因此不分配引用,以后纹理加载无效。

    【讨论】:

      【解决方案2】:

      构造函数将在LoadContent 之前调用。届时,switch 语句中的行都会将null 分配给 spriteTexture。

      最简单的解决方法是保存requestedMenuButtonType 的值并将switch 语句(或对包含switch 语句的方法的调用)放入LoadContent(在图标加载后的某个时间点) .例如:

      private static MenuButtonType savedMenuButtonType;
      
      public MenuButton(int requestedX, int requestedY, int requestedWidth, int requestedHeight, MenuButtonType requestedMenuButtonType)
         : base(requestedX, requestedY, requestedWidth, requestedHeight)
         {
            ...
            savedMenuButtonType = requestedMenuButtonType;
            ...
         }
      
      public static void LoadContent(ContentManager Content)
      {
         ...
         //Main Menu Icons
         ...
         //About Menu Icons
         ...
         spriteTexture = GetRequestedSpriteTexture();
      }
      
      private static Texture2D GetRequestedSpriteTexture()
      {
         switch (savedMenuButtonType)
         {
            case MenuButtonType.play:
               return playButtonIcon;
               break;
      
            ...
      }
      

      更好的解决方案可能是将Texture2Ds 包装在一些Icon 类中,该类有自己的LoadContent 方法(它调用LoadContent 为其特定的Texture2D)。然后当调用 LoadContent 时,它会加载 Texture2Ds 而不会丢弃 Icon 引用。

      public class Icon
      {
         private string mTextureName;
         private Texture2D mTexture;
      
         public Icon(string pTextureName)
         {
            mTextureName = pTextureName;
         }
         ...
         public void LoadContent(ContentManager Content)
         {
            mTexture = Content.Load<Texture2D>(mTextureName);
         }
         ...
      }
      
      public class MenuButton : SpriteObject
      {
         private Icon spriteIcon;
      
         //Different Icons, static for loading
         private static Icon playButtonIcon = new Icon("Menu Items/Menu Buttons/PlayButtonIcon");
         ...
      
         public MenuButton(int requestedX, int requestedY, int requestedWidth, int requestedHeight, MenuButtonType requestedMenuButtonType)
            : base(requestedX, requestedY, requestedWidth, requestedHeight)
         {
            ...
            spriteIcon = playButtonIcon;
            ...
         }
      
         public void LoadContent(ContentManager Content)
         {
            ...
            playButtonIcon.LoadContent(Content);
            ...
         }        
      }
      

      【讨论】:

        【解决方案3】:

        如果您只是加载小/少数纹理(不耗时),您可以在 MenuButton 构造函数中调用加载内容。

        【讨论】:

        • -1 这是个坏主意。永远不要在类实例构造函数中调用加载内容。
        【解决方案4】:

        这是因为引用在 C# 中的工作方式。这是一个使用字符串而不是纹理的简单示例:

        String foo = null; // A null reference is assigned to the foo variable...
        
        String bar = foo; // The null reference is *copied* to the bar variable. We now have 2 distinct references..
        
        foo = "foo"; // The foo variable is *overwritten* with a new reference to the string...
        
        bar != "foo"; // The bar variable is not affected at all, its own reference still points at null.
        

        现在,如果您想在加载之前引用纹理,则需要为实际的 Texture2D 成员提供一定程度的间接性,从而避免复制空引用以开始...

        static public Icon
        {
            public Texture2D Texture; // starts with null...
        
            static public Icon PlayButton = new Icon(); // Not a null reference, even though the texture hasn't been loaded yet...
        }
        
        
        public class MenuButton
        {
            public MenuButton()
            {
                this.Icon = Icon.PlayButton; // Again, not a null reference...
            }
        
            public Icon Icon { get; set; }
        
            public void Draw()
            {
                SpriteBatch.Draw(this.Icon.Texture); // etc...
            }
        }
        

        现在只要我们调用加载内容 (Icon.MenuButton.Texture = Content.Load("blah.png");),我们的 draw 方法就可以工作* :)

        现在,当 Icon.Texture 属性被更改/覆盖/无论如何时,MenuButton 类不会受到影响,因为它只包含对 Icon 类实例的引用,它不会改变。

        * 我实际上很想在 Icon 类中添加一个 draw 方法。甚至是 SpriteBatch 的扩展方法来直接绘制 Icon 引用...这将更符合 'tell don't ask' 原则:)

        【讨论】:

          猜你喜欢
          • 2012-12-21
          • 2010-10-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-22
          • 1970-01-01
          相关资源
          最近更新 更多