我正在使用Monogame将游戏从XNA转换为iOS
在下面的代码段中,smallDeform
是Texture2D
,我称之为GetData
方法。
smallDeform = Game.Content.Load<Texture2D>("Terrain/...");
smallDeform.GetData(smallDeformData, 0, smallDeform.Width * smallDeform.Height);
我在使用Monogame时遇到了一些问题,因为iOS中的功能尚未实现,因为它会返回此异常。
#if IOS
throw new NotImplementedException();
#elif ANDROID
我尝试从Windows中序列化XML文件中的数据,以从iOS加载整个文件。序列化文件每个重量超过100MB,这是解析时无法接受的。
基本上,我正在寻找一种解决方法,以便在不使用uint[]
方法的情况下从纹理中获取数据(例如Color[]
或GetData
)。
PS:我在Mac上,所以我不能使用Monogame SharpDX库。
提前致谢。
答案 0 :(得分:1)
序列化数据实际上是一个非常聪明的解决方法,但XML对于这项工作来说非常重要。我要做的是使用自定义但简单的二进制格式,以便您可以控制输出的大小。
以下是我提出的一些应该有效的方法,但请注意我专门回答了这个问题并且没有经过测试。
保存数据..
private void SaveTextureData(Texture2D texture, string filename)
{
int width = texture.Width;
int height = texture.Height;
Color[] data = new Color[width * height];
texture.GetData<Color>(data, 0, data.Length);
using (BinaryWriter writer = new BinaryWriter(File.Open(filename, FileMode.Create)))
{
writer.Write(width);
writer.Write(height);
writer.Write(data.Length);
for (int i = 0; i < data.Length; i++)
{
writer.Write(data[i].R);
writer.Write(data[i].G);
writer.Write(data[i].B);
writer.Write(data[i].A);
}
}
}
并加载数据..
private Texture2D LoadTextureData(string filename)
{
using (BinaryReader reader = new BinaryReader(File.Open(filename, FileMode.Open)))
{
var width = reader.ReadInt32();
var height = reader.ReadInt32();
var length = reader.ReadInt32();
var data = new Color[length];
for (int i = 0; i < data.Length; i++)
{
var r = reader.ReadByte();
var g = reader.ReadByte();
var b = reader.ReadByte();
var a = reader.ReadByte();
data[i] = new Color(r, g, b, a);
}
var texture = new Texture2D(GraphicsDevice, width, height);
texture.SetData<Color>(data, 0, data.Length);
return texture;
}
}
二进制数据远小于XML数据。它与你没有压缩的情况一样小。请注意,二进制格式在变更方面非常严格。如果您需要更改格式,在大多数情况下写出新文件会更容易。
如果您需要对方法进行更改,请注意保持其同步。每个Write应该以完全相同的顺序和数据类型与相同的Read匹配。
我很想知道文件变小了多少。让我知道它是怎么回事?
答案 1 :(得分:1)
我回答我自己的问题,如果有人会遇到同样的问题。
按照 craftworkgame 的建议,我使用字节流保存了数据,但是由于缺少File
类,我不得不使用WinRT函数:
private async void SaveColorArray(string filename, Color[] array)
{
StorageFile sampleFile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(filename + ".dat", CreationCollisionOption.ReplaceExisting);
IRandomAccessStream writeStream = await sampleFile.OpenAsync(FileAccessMode.ReadWrite);
IOutputStream outputSteam = writeStream.GetOutputStreamAt(0);
DataWriter dataWriter = new DataWriter(outputSteam);
for (int i = 0; i < array.Length; i++)
{
dataWriter.WriteByte(array[i].R);
dataWriter.WriteByte(array[i].G);
dataWriter.WriteByte(array[i].B);
dataWriter.WriteByte(array[i].A);
}
await dataWriter.StoreAsync();
await outputSteam.FlushAsync();
}
protected async Task<Color[]> LoadColorArray(string filename)
{
StorageFile sampleFile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(filename + ".dat", CreationCollisionOption.OpenIfExists);
IRandomAccessStream readStream = await sampleFile.OpenAsync(FileAccessMode.Read);
IInputStream inputSteam = readStream.GetInputStreamAt(0);
DataReader dataReader = new DataReader(inputSteam);
await dataReader.LoadAsync((uint)readStream.Size);
Color[] levelArray = new Color[dataReader.UnconsumedBufferLength / 4];
int i = 0;
while (dataReader.UnconsumedBufferLength > 0)
{
byte[] colorArray = new byte[4];
dataReader.ReadBytes(colorArray);
levelArray[i++] = new Color(colorArray[0], colorArray[1], colorArray[2], colorArray[3]);
}
return levelArray;
}
答案 2 :(得分:1)
如果您愿意构建自己的MonoGame版本,可以在iOS上使用Texture2D.GetData。请参阅此处的修复:https://github.com/scottlerch/MonoGame/commit/24c1c3d5398f4ed9dbd9b60c0bbdbc096311632c)。
这是来自同一问题的讨论:https://monogame.codeplex.com/discussions/442667
此修复程序已确认适用于iPad1 v5.1.1 +和iPhone4 v6.1 +。