【问题标题】:XNA pass SpriteBatch and Content as referenceXNA 通过 SpriteBatch 和 Content 作为参考
【发布时间】:2012-06-15 10:17:49
【问题描述】:

最近我开始将 XNA 与 MonoMac 一起使用。 我上课有问题。 我想创建一个里面有纹理和位置信息的类。我也想做绘图功能。

我的想法是传递 spriteBatch 和 Content arround,这样我就可以加载纹理并在之后绘制它们。然而,我传递给这个对象的内容对象不加载任何纹理,当我在类之外尝试内容时,它加载的纹理很好,所以纹理必须在那里。

    public class TPlayer {
        public Texture2D[] textures;
        public ContentManager Content;
        public SpriteBatch spriteBatch;
        public int currentFrame;
        public Rectangle position;
        public TPlayer(ContentManager ccontent, SpriteBatch cspritebatch){
            this.Content = ccontent;
            this.spriteBatch = cspritebatch;
            this.Content.RootDirectory = "Content";
            this.currentFrame = 0;
            this.position = new Rectangle(250,20,100,150);
            this.LoadContent();
        }

        protected void LoadContent(){
            this.textures[0] = this.Content.Load<Texture2D>("Textures/ToughStanding");
            this.textures[1] = this.Content.Load<Texture2D>("Textures/ToughWalking1");
            this.textures[2] = this.Content.Load<Texture2D>("Textures/ToughWalking2");
        }

        public void Draw(){
            spriteBatch.Begin (SpriteSortMode.Deferred, BlendState.AlphaBlend);
            this.spriteBatch.Draw (textures[0], this.position, Color.White);
            this.spriteBatch.End ();
        }

这就是我创建实例的方式:

Player = new TPlayer(this.Content,this.spriteBatch);

也许我试图使用错误的模型。也许我不应该在类中使用 spritebatch 和 Content,但是我可以让 spritebatch 和 content 全局化吗?

感谢您的帮助

【问题讨论】:

  • Content.RootDirectory 在进入你的 TPlayer 构造函数之前的值是多少?在构造函数中设置值,确定需要这样做吗?
  • 另外作为提示(与您的问题无关)我猜您有一个吸引玩家的循环,调用 spritebatch.begin 并结束该循环的任一侧,而不是在每个绘制方法中,你会加快速度。
  • 不,我认为我不需要这样做。之前设置为“内容”。我只是想猜测可能是哪里出了问题,所以我也试过了。感谢您对 spritebatch 的建议...从现在开始我只会调用 Begin 和 End 一次。
  • 我通过只将纹理传递给对象而不是将 spritebatch 传递给绘图函数来解决问题,因为它在这里完成:create.msdn.com/en-US/education/tutorial/2dgame/… 抱歉给您带来麻烦

标签: c# xna xna-4.0 spritebatch


【解决方案1】:

既然你已经解决了你自己的问题(干得好!)我将使用这个空间来建议一种资源密集度稍低的方法来绘制你的精灵帧,这也将解决你遇到的问题,而不是使用单独的纹理您可以将每一帧动画组合成一个纹理。交换纹理实际上是一个相对较慢的操作。

所以代替站立、行走1、行走2的3个纹理并使用当前帧属性在它们之间切换,您可以创建一个大纹理来容纳所有3个,这可以通过简单地创建一个空白在油漆或任何绘图包中完成对所有 3 帧的大小进行成像并将它们复制/粘贴到位(记下每个帧的开始/结束位置)

您可以创建一个矩形数组来保存表单中每个精灵的位置。

spriteSheetRegions = new Rectangle[]
{
    new Rectangle (0,0, 50,50),     // standing.
    new Rectangle (50,0, 100, 50),  // tough walking 1
    new Rectangle (100,0, 150, 50), // tough walking 2
};

然后要为精灵设置动画,您只需跟踪哪个矩形是当前帧。

我在下面附上了一个快速游戏类,它展示了整个操作如何与精灵和玩家类一起工作,精灵类可以成为所有精灵的基础,而不仅仅是玩家。

#region Using Directives.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
#endregion

namespace sprites
{
    public class Sprite
    {
        // Texture instances.
        public Texture2D spriteSheet;
        protected Rectangle[] spriteSheetRegions;
        protected Rectangle currentSpriteSheetRegion;

        // player instances.
        public Rectangle location;

        // call this to change the image that's drawn for the sprite.
        public void SetSpriteSheetIndex(int index)
        {
            currentSpriteSheetRegion = spriteSheetRegions[index];
        }
    }

    public class TPlayer : Sprite
    {
        public TPlayer()
        {
            // Since your sprite sheets for the player are fixed we can set them up here.
            spriteSheetRegions = new Rectangle[]
            {
                new Rectangle (0,0, 50,50),     // standing.
                new Rectangle (50,0, 100, 50),  // tough walking 1
                new Rectangle (100,0, 150, 50), // tough walking 2
            };
            currentSpriteSheetRegion = spriteSheetRegions[0];
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(spriteSheet, location, currentSpriteSheetRegion, Color.White);
        }
    }

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        List<TPlayer> players;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            // Create the players and add 3 of them.
            players = new List<TPlayer>();
            players.Add(new TPlayer() { location = new Rectangle(10, 10, 100, 100) });
            players.Add(new TPlayer() { location = new Rectangle(110, 10, 100, 100) });
            players.Add(new TPlayer() { location = new Rectangle(220, 10, 100, 100) });

            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // Load up the players content.
            Texture2D playerSpriteSheet = Content.Load<Texture2D>("PlayerSpriteSheet");

            // each player gets a reference to the same texture so there is no duplication.
            for (int i = 0; i < players.Count; i++)
                players[i].spriteSheet = playerSpriteSheet;
        }

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

            // draw the players.
            spriteBatch.Begin();
            for (int i = 0; i < players.Count; i++)
                players[i].Draw(spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

当你想改变播放器的当前帧时,你调用 SetSpriteSheetIndex。

如果您想将玩家 0 的图片设置为艰难的步行 1 帧,您会调用。

players[0].SetSpriteSheetIndex(1);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多