不通过Content直接创建XNB文件

摘要:
我很久没有关注Xna了。我刚刚去了Xna游戏世界,了解到AppHub发布了一个新的示例,包括XNB文件结构解析的示例。所以我第一次浏览了它:CompiledContentFormat。如果你感兴趣,你可以下载一个例子来学习。此外,还有一个关于XNB文件结构的文档。参考文档,我用C#(4.0)编写了一个生成纹理XNB文件的简单工具。编译后的文件放在游戏的Content目录中,然后Content Load<Texture2D>可以加载到Texture2D变量中进行绘制。37列出字节;38stringxnbFile=路径组合;39文件流=新文件流;40bytes=newList<byte>();41字节。AddRange;//文件头标识符“XNB”42字节。AddRange//平台ID:w-Window43bytes。添加//5-Xna4.044///写入当前xnb文件所需的TypeReader。45字节。添加;//标志位:0x01—是否为HiDef模式;0x80-是否压缩。

好久没关注Xna了,刚刚上了Xna游戏世界得知AppHub发布了新示例,其中有关于XNB文件结构解析的示例,于是第一时间去浏览了下:Compiled (XNB) Content Format。有兴趣的朋友可以下载示例研究一下(是C++代码),另外里面有份关于XNB文件结构的文档比较好。

参照文档,我用C#(4.0)写了个简单的纹理XNB文件的生成工具。其实就是个命令行工具,把一堆文件拖上去,会自动将图像文件编译到相同目录下。编译后的文件放到游戏的Content目录中,然后Content.Load<Texture2D>就能加载到Texture2D变量中用于绘制。

 1 static void Main(string[] args)
 2         {
 3             foreach (string fileName in args)
 4             {
 5                 if (File.Exists(fileName))
 6                     ImageToXnb(fileName);
 7             }
 8             Console.ReadLine();
 9         }
10 
11         static void ImageToXnb(string fileName)
12         {
13             try
14             {
15                 Bitmap image = Bitmap.FromFile(fileName) as Bitmap;
16                 if (image != null)
17                 {
18                     //  获取图像的数组。
19                     int w = image.Width;
20                     int h = image.Height;
21                     int s = 4 * w * h;
22                     BitmapData bmpData = image.LockBits(new Rectangle(00, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
23                     byte[] bmpBytes = new byte[s];
24                     unsafe
25                     {
26                         byte* data = (byte*)(bmpData.Scan0.ToPointer());
27                         for (int i = 0; i < w * h; i++)
28                         {
29                             bmpBytes[4 * i] = data[4 * i + 2];
30                             bmpBytes[4 * i + 1= data[4 * i + 1];
31                             bmpBytes[4 * i + 2= data[4 * i];
32                             bmpBytes[4 * i + 3= data[4 * i + 3];
33                         }
34                     }
35                     image.UnlockBits(bmpData);
36                     //  开始写入xnb数据。
37                     List<byte> bytes;
38                     string xnbFile = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".xnb");
39                     FileStream stream = new FileStream(xnbFile, FileMode.Create, FileAccess.Write);
40                     bytes = new List<byte>();
41                     bytes.AddRange(Encoding.Default.GetBytes("XNB"));   // 文件头标识"XNB"
42                     bytes.AddRange(Encoding.Default.GetBytes("w"));     // 平台标识:w - Window
43                     bytes.Add((byte)5);     // 5 - Xna4.0
44                     //  写入当前xnb文件需要的Type Reader。Texture2D对应的是Texture2DReader。
45                     bytes.Add((byte)1);     // 标记位:0x01 - 是否HiDef模式;0x80 - 是否压缩。
46                     bytes.Add((byte)1);     // Type Reader的数量。
47                     //  写入Type Reader的全称。
48                     string reader = "Microsoft.Xna.Framework.Content.Texture2DReader, Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553";
49                     bytes.Add((byte)reader.Length);
50                     bytes.Add((byte)1);
51                     bytes.AddRange(Encoding.Default.GetBytes(reader));
52                     bytes.Add((byte)0);
53                     bytes.AddRange(BitConverter.GetBytes(0));   // Type Reader 的版本。
54                     //  写入xnb文件的内容。
55                     bytes.Add((byte)1);     // 内容的数量。
56                     //  写入内容,此处为Texture2D。
57                     bytes.AddRange(BitConverter.GetBytes(0));   // Surface format-此处为Color。
58                     bytes.AddRange(BitConverter.GetBytes((uint)w));     // 宽和高。
59                     bytes.AddRange(BitConverter.GetBytes((uint)h));
60                     bytes.AddRange(BitConverter.GetBytes((uint)1));     // Mip 数量。
61                     bytes.AddRange(BitConverter.GetBytes((uint)(s)));   // 数据大小。
62                     bytes.AddRange(bmpBytes);
63                     //  计算文件大小,插入指定位置。实际上在那个标志位后面紧跟着就是 uint 类型的文件大小。
64                     int size = bytes.Count + 4;
65                     bytes.InsertRange(6, BitConverter.GetBytes(size));
66                     //  写入文件。
67                     stream.Write(bytes.ToArray(), 0, bytes.Count);
68                     stream.Close();
69                     Console.WriteLine("文件 {0} 成功编译成 xnb 文件!", fileName);
70                 }
71             }
72             catch
73             {
74                 Console.WriteLine("文件 {0} 不是有效的图像文件,编译失败!", fileName);
75             }
76         }

这里有几点说明下:

1、代码用到不安全代码,要在项目属性中把“允许不安全代码”勾上。

2、Texture2DReader类型的全称是从已生成的XNB文件中复制过来的,我在对象浏览器中都没找到这个类,有人能告诉我为什么吗?

3、因为文件中第7个Byte开始的Uint类型的数表示文件大小,所以我先把整个文件写到List<byte>中,然后将数组长度加上4作为文件大小插入到该位置,然后在将整个List一起保存。(事实上开始的时候我把文件大小都设为0,游戏一样可以正常加载)

4、如果标记位指定文件为压缩的,那么文件大小后面还需指定解压后的文件大小,因为对压缩不甚了解,所以直接跳过了。

5、这里设置纹理的Surface format为Color,这种格式最占空间了,拿一张约900kb的jpg图像编译后达3M多。所以要将本程序实用化,可以研究下其他的格式。

结束,睡觉zzzzz~不通过Content直接创建XNB文件第1张

免责声明:文章转载自《不通过Content直接创建XNB文件》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C# 连接sql数据库对 access,excel导入导出操作 一、SQL SERVER 和ACCESS的数据导入导出OneNote无法打开链接出现错误:你的组织策略阻止我们为你完成此操作下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Python requests关于爬虫下载下来的数据乱码问题

1.html下载后乱码 直接用浏览器检查原网页的编码,然后把你下载下来的网页数据设置为网页上显示的编码,result.encoding=“网页上的编码” 2.直接获取api的json数据乱码 最近几年网页传输出现了新的br压缩方式,在请求的时候如果你的headers里面Accept-Encoding是“gzip, deflate, br”, headers...

GoEasy接口测试Websocket

GoEasy接口测试Websocket1.  登陆GoEasy官网:https://hangzhou.goeasy.io/cn/home 2.  注册账号  登陆GoEasy官网   4.进入我的应用,查看goeasy接口信息           ru 附源代码: <!DOCTYPE html> <html lang="en">...

httprunner学习-hook 机制实现setup和teardown

前言 unittest框架里面有个非常好的概念:前置( setUp )和后置( tearDown )处理器,真正会用的人不多。HttpRunner 实际上也是从用的unittest框架,里面也有前置 setup_hooks 和后置 teardown_hooks 的概念。 setup_hooks: 在整个用例开始执行前触发 hook 函数,主要用于准备工作...

zabbix实现自定义监控

实现自定义监控项实例 1.创建主机组 2.创建主机 3.创建监控项 1.到需要监控的主机的agent中添加自定义的监控项目 cd /etc/zabbix/zabbix_agentd.d vi userparameter_mysql.conf UserParameter=监控项目名称,shell命名 UserParam...

Android(java)学习笔记191:ContentProvider使用之利用ContentProvider备份和还原手机短信(掌握)

1. 通过阅读系统源码我们知道: 短信的内容提供者: content://sms/            系统短信的内容提供者的路径 2. 利用ContentProvider备份和还原手机短信: (1)新建一个Android工程,命名为"短信备份助手",如下: (2)我们先实现UI布局,activity_main.xml,如下: 1 <Linea...

vue 文件上传

  学习参考地址: http://www.cnblogs.com/zhengweijie/p/6922808.html#3920491 依赖js文件: http://files.cnblogs.com/files/zhengweijie/jquery.form.rar HTML 文本内容: <template>   <div id="ac...