数据结构建议:"hull" 中的框
Advice for data structure: boxes inside a "hull"
我正在制作一个 (2D) space飞船游戏,但我还没有找到一种有效的方法来保存 space飞船数据。
我有一个 "hull"(边界),所有 systems/rooms 都在其中。房间是连续的,一些系统也是如此。我想有效地保存船体和房间数据,以便于操作它们(adding/subtracting space 在房间之间,扩展 and/or 损坏船体等)并轻松地将它们保存在 (最好)human-readable格式。
目前我看到的是两个选项:
- 将所有内容 "by-pixel" 保存在 objects 的二维数组中,其中包含 "pixel" 房间的这一部分(繁琐且容易导致错误,但最容易实现),或
- 通过 tree-like 数据结构保存,表示为 XML(满足我的大部分要求,但我不知道如何很好地实现它 - "box model"这种方法不会让我进入非矩形的房间太远。
如果有任何不同,我正在使用(将使用)C# 和 Blend/WPF。如果有一个组件可以神奇地允许操纵 children 并将其序列化,那么我认为这也是可以接受的。
这是我在这个网站上的第一个问题,如果我做错了什么请指出。谢谢你的时间。 :)
考虑到您可能有许多因素会使房间系统更加复杂:
- 您的 rooms/systems 可能有属性、房间名称、房间类型、添加属性时的子类型,例如ComputerRoom 可能将 NumberOfCPUCores 作为 属性,而这不适用于普通房间。伤害百分比,伤害位置等
- 重叠规则可能更复杂,例如您稍后可能会添加一些可以重叠或跨越多个房间的东西。
简单 size/shape 和位置可以使用位图样式存储模型来表示,但是如果没有附带数据,它不会轻易允许更复杂的结构。
我会考虑使用 Data Contract serialization,这样可以使用多种方法来存储和发送您的数据,包括但不限于存储为 XML、二进制(更高效,但不是人类可读),使用 WCF 等通过网络发送。它允许扩展到几乎无限复杂的模型。
下面是一个简单模型和 XML 序列化的示例。 (这里的一切都是矩形的)。
船体、房间等定义:
[DataContract]
class Hull
{
public int Width { get; set; }
public int Height { get; set; }
[DataMember]
public List<Component> Components { get; set; }
//read only properties will be ignored
public int SurfaceArea { get { return Width*Height; }}
//some properties can be excluded from serialization:
[IgnoreDataMember]
public int NotStoredInXml { get; set; }
public Hull()
{
this.Components = new List<Component>();
}
}
[DataContract]
[KnownType(typeof(Room))]
[KnownType(typeof(ComputerRoom))]
[KnownType(typeof(System))]
abstract class Component
{
[DataMember]
int Width { get; set; }
[DataMember]
int Height { get; set; }
[DataMember]
int X { get; set; }
[DataMember]
int Y { get; set; }
}
[DataContract] class Room : Component { }
[DataContract] class System : Component { }
[DataContract] class ComputerRoom : Room
{
[DataMember]
public int NumberOfCPUCores { get; set; }
}
保存和加载数据:
var hull = new Hull();
hull.Components.Add(new ComputerRoom { NumberOfCPUCores = 3 });
hull.Components.Add(new System());
hull.Components.Add(new Room());
var serializer = new DataContractSerializer(typeof (Hull));
using (var stream = File.Open("test.xml", FileMode.Create))
{
serializer.WriteObject(stream, hull);
}
Hull newHull;
using (var stream = File.OpenRead("test.xml"))
{
newHull = serializer.ReadObject(stream) as Hull;
}
Console.WriteLine(newHull.Components.Count); //3
结果XML:
<Hull xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication22"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Components>
<Component i:type="ComputerRoom">
<Height>0</Height>
<Width>0</Width>
<X>0</X>
<Y>0</Y>
<NumberOfCPUCores>3</NumberOfCPUCores>
</Component>
<Component i:type="System">
<Height>0</Height>
<Width>0</Width>
<X>0</X>
<Y>0</Y>
</Component>
<Component i:type="Room">
<Height>0</Height>
<Width>0</Width>
<X>0</X>
<Y>0</Y>
</Component>
</Components>
</Hull>
更新
如果想支持任意形状,可以看看WPF中的Path
语法
和 Geometry Class
我正在制作一个 (2D) space飞船游戏,但我还没有找到一种有效的方法来保存 space飞船数据。
我有一个 "hull"(边界),所有 systems/rooms 都在其中。房间是连续的,一些系统也是如此。我想有效地保存船体和房间数据,以便于操作它们(adding/subtracting space 在房间之间,扩展 and/or 损坏船体等)并轻松地将它们保存在 (最好)human-readable格式。
目前我看到的是两个选项:
- 将所有内容 "by-pixel" 保存在 objects 的二维数组中,其中包含 "pixel" 房间的这一部分(繁琐且容易导致错误,但最容易实现),或
- 通过 tree-like 数据结构保存,表示为 XML(满足我的大部分要求,但我不知道如何很好地实现它 - "box model"这种方法不会让我进入非矩形的房间太远。
如果有任何不同,我正在使用(将使用)C# 和 Blend/WPF。如果有一个组件可以神奇地允许操纵 children 并将其序列化,那么我认为这也是可以接受的。
这是我在这个网站上的第一个问题,如果我做错了什么请指出。谢谢你的时间。 :)
考虑到您可能有许多因素会使房间系统更加复杂:
- 您的 rooms/systems 可能有属性、房间名称、房间类型、添加属性时的子类型,例如ComputerRoom 可能将 NumberOfCPUCores 作为 属性,而这不适用于普通房间。伤害百分比,伤害位置等
- 重叠规则可能更复杂,例如您稍后可能会添加一些可以重叠或跨越多个房间的东西。
简单 size/shape 和位置可以使用位图样式存储模型来表示,但是如果没有附带数据,它不会轻易允许更复杂的结构。
我会考虑使用 Data Contract serialization,这样可以使用多种方法来存储和发送您的数据,包括但不限于存储为 XML、二进制(更高效,但不是人类可读),使用 WCF 等通过网络发送。它允许扩展到几乎无限复杂的模型。
下面是一个简单模型和 XML 序列化的示例。 (这里的一切都是矩形的)。
船体、房间等定义:
[DataContract]
class Hull
{
public int Width { get; set; }
public int Height { get; set; }
[DataMember]
public List<Component> Components { get; set; }
//read only properties will be ignored
public int SurfaceArea { get { return Width*Height; }}
//some properties can be excluded from serialization:
[IgnoreDataMember]
public int NotStoredInXml { get; set; }
public Hull()
{
this.Components = new List<Component>();
}
}
[DataContract]
[KnownType(typeof(Room))]
[KnownType(typeof(ComputerRoom))]
[KnownType(typeof(System))]
abstract class Component
{
[DataMember]
int Width { get; set; }
[DataMember]
int Height { get; set; }
[DataMember]
int X { get; set; }
[DataMember]
int Y { get; set; }
}
[DataContract] class Room : Component { }
[DataContract] class System : Component { }
[DataContract] class ComputerRoom : Room
{
[DataMember]
public int NumberOfCPUCores { get; set; }
}
保存和加载数据:
var hull = new Hull();
hull.Components.Add(new ComputerRoom { NumberOfCPUCores = 3 });
hull.Components.Add(new System());
hull.Components.Add(new Room());
var serializer = new DataContractSerializer(typeof (Hull));
using (var stream = File.Open("test.xml", FileMode.Create))
{
serializer.WriteObject(stream, hull);
}
Hull newHull;
using (var stream = File.OpenRead("test.xml"))
{
newHull = serializer.ReadObject(stream) as Hull;
}
Console.WriteLine(newHull.Components.Count); //3
结果XML:
<Hull xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication22"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Components>
<Component i:type="ComputerRoom">
<Height>0</Height>
<Width>0</Width>
<X>0</X>
<Y>0</Y>
<NumberOfCPUCores>3</NumberOfCPUCores>
</Component>
<Component i:type="System">
<Height>0</Height>
<Width>0</Width>
<X>0</X>
<Y>0</Y>
</Component>
<Component i:type="Room">
<Height>0</Height>
<Width>0</Width>
<X>0</X>
<Y>0</Y>
</Component>
</Components>
</Hull>
更新
如果想支持任意形状,可以看看WPF中的Path
语法
和 Geometry Class