首页 > 其他 > 详细

【XNA 4】使用Easy Pak打包XNA游戏资源文件

时间:2014-02-09 16:24:16      阅读:544      评论:0      收藏:0      [点我收藏+]

EASY PAK的源代码(在Code Plex上)

Easy Pak on CodePlex

 

如果要载入很大数量的文件的时候,使用Easy Pak打包成.pak文件可以通过减少查找时间而显著加快读取速度。

但是我发现这个Easy Pak现在有几个bug

在PakContentManager下,有几个去扩展名的方法不对 

string[] GetAssetNames()

bubuko.com,布布扣
        /// <summary>
        /// Gets an array of the asset names of the content inside the pak file.
        /// </summary>
        /// <returns>An array of strings with all the asset names.</returns>
        public string[] GetAssetNames()
        {
            if (pakFile == null)
                throw new NullReferenceException("Attempting to call GetAssetNames() when pak file is released or not yet loaded");

            List<string> filenames = new List<string>();

            foreach (PakEntry entry in pakFile)
            {
                string name = entry.FileName;
                if (name.EndsWith(".xnb"))
                    name = name.Remove(name.Length - 4, 4); // 原来的源代码里是name.Length - 4, 3,其实应该是name.Length - 4, 4,不然名字的最后多一个b
                filenames.Add(name);
            }

            return filenames.ToArray();
        }
bubuko.com,布布扣

 

以及 string[] GetAssetNamesFromDirectory(string)

bubuko.com,布布扣
        /// <summary>
        /// Gets an array of asset names from a specific directory within
        /// the pak file.
        /// </summary>
        /// <param name="directory">The directory to get asset names from</param>
        /// <returns>An array of strings with all the asset names</returns>
        public string[] GetAssetNamesFromDirectory(string directory)
        {
            if (pakFile == null)
                throw new NullReferenceException(string.Format("Attempting to call GetAssetNamesFromDirectory(\"{0}\") when pak file is released or not yet loaded", directory));

            List<string> filenames = new List<string>();

            foreach (PakEntry entry in pakFile)
            {
                string name = entry.FileName;
                if (name.EndsWith(".xnb"))
                    name = name.Remove(name.Length - 4, 4); // 这个也是

                string[] parts = name.Split(\\);
                string dir = "";
                for (int i = 0; i < parts.Length - 1; i++)
                    dir += parts[i] + "/";
                if (dir == directory)
                    filenames.Add(name);
            }

            return filenames.ToArray();
        }
bubuko.com,布布扣

 

修改完毕之后就可以build了

然后在你的XNA项目的.csproj文件中加入

注意AssemblyFile改成你编译的那几个dll的位置。

bubuko.com,布布扣
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets. -->
  <Target Name="BeforeBuild">
  </Target>
  <UsingTask TaskName="EasyPak.PakWriter" AssemblyFile="c:\EasyPak\EasyPakWriter.dll" />
  <Target Name="AfterBuild">
    <PropertyGroup>
      <OutDir>bin\$(Platform)\$(Configuration)\Content\</OutDir>
      <ContentDir>bin\$(Platform)\$(Configuration)\Content\</ContentDir>
      <PakName>content.pak</PakName>
      <IncludeFolders></IncludeFolders>
      <ExcludeFolders></ExcludeFolders>
      <ExcludeExtensions>.xgs;.xwb;.xsb;.pak</ExcludeExtensions>
    </PropertyGroup> 
    <EasyPak.PakWriter OutDir="$(OutDir)" ContentDir="$(ContentDir)" PakName="$(PakName)" IncludeFolders="$(IncludeFolders)" ExcludeFolders="$(ExcludeFolders)" ExcludeExtensions="$(ExcludeExtensions)" />
  </Target>
bubuko.com,布布扣

 

然后你编译你的XNA游戏之后,Easy Pak会在build结束之后打包你的游戏资源。

Easy Pak会检查已经存在的pak,如果不需要重新打包的话他是不会重新打的。

注意VS不知道.pak文件在Content目录下。所以不会自己清理。但是实际上不需要清理,除非你决定不用easy pak了。。。

 

要在游戏里使用Easy Pak加载文件怎么做呢?在游戏的LoadContent方法中

bubuko.com,布布扣
        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            // TODO: use this.Content to load your game content here

            Content = new PakContentManager(this.Services, "Content/content.pak");

            font = Content.Load<SpriteFont>("SpriteFont1");
            font2 = Content.Load<SpriteFont>(@"Fonts\SpriteFont2");

            // 这里加载其他资源...

            // 最后释放pak文件
            (Content as PakContentManager).ReleasePakFile();
        }
bubuko.com,布布扣

 

 

另外最后,Easy Pak打包了你的资源,却留下一大堆空目录。

修改PakWriter 让它自动删除空目录吧

bool Execute()方法最后加入调用一个递归删空目录的方法(从stackoverflow直接拿过来的。。)

注意在return true之前调用 ProcessDirectory(fullContentPath)

bubuko.com,布布扣
private static void ProcessDirectory(string startLocation)
{
    foreach (var directory in Directory.GetDirectories(startLocation))
    {
        ProcessDirectory(directory);
        if (Directory.GetFiles(directory).Length == 0 && 
            Directory.GetDirectories(directory).Length == 0)
        {
            Directory.Delete(directory, false);
        }
    }
}
bubuko.com,布布扣

 

最后总结几点

1. Easy Pak适合打包大数量的文件

2. Easy Pak只打包,不压缩。而且默认.xgs / .xwb / .xsb / .pak 这几个扩展名的文件是不打包的(XACT的音效资源本身就被打包过了)

3. 如果需要压缩文件,在XNA项目里设置属性 “Content Build”里面有一个 Compress content pipeline output files 打勾就可以。压缩的是XNA资源文件,Easy Pak依旧不压缩

4. 如果资源不是很大,可以在游戏一开始就把整个pak载入了。

【XNA 4】使用Easy Pak打包XNA游戏资源文件

原文:http://www.cnblogs.com/thefake/p/3541190.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!