C#XNA - 用于tilemap

时间:2017-01-13 04:25:07

标签: c# xna monogame tiles

首先,为了让任何不太感兴趣阅读整本小说的人,在这个问题中没有任何代码纯粹是理论上的。 我正在打电话,这是一个关于哪种选择最适合和最容易处理的问题。

所以对于这个问题,我正在研究我认为应该是一个基本的Tilemap引擎*并且我对我的方法有疑问。我已经多次重写了它。并不是说花了太长时间,至少可以说这个项目仍在尿布中。

基本上,我有一个带有这个构造函数的Sprite类:string name,int Id,texture2d texture。

然后我的Tile类派生自Sprite类,并将这些类添加到构造函数中: Int X,int Y,bool walkable。

在我第一次尝试时,我使用了一个2D整数数组,并将所需图块的ID值分配给数组上的位置。 然后,当绘制tilemap时,我会对整个数组进行双循环,并找到具有相同ID的tile,该tile具有Tile函数的循环中当前所在的数组位置,这将返回一个新的Tile,然后我将继续用循环当前的X和Y绘制(乘以纹理大小,原因很明显)。因为在这一点上,我的Tile类没有X和Y值。这似乎是一个非常多的投掷和回来,并且由于某种原因我觉得这是一种原始的方法。

然后我采用另一种方法,我制作了一个2D Tile数组,而不是必须为每个数组分配一个ID值,然后匹配它,制作一个新的实例,然后绘制它我可以只需循环数组并使数组在构造函数中使用当前的X和Y定位所需tile的新实例,然后使用Tile.X和Tile.Y绘制它。似乎更合适。

在我运行代码之前至少大约一秒钟,它确实如此。 看,现在我需要在尝试绘制之前用tile完全填充整个数组,否则它会返回一个null对象引用(当然),因为之前我有一个ID为0的tile,它只是如果没有分配任何其他内容,则绘制为默认值。 在我以前遇到的所有混乱的某个地方,我也有一个简单的小小的"如果"只是告诉它不要画如果ID是0,但后来我添加了。 我现在意识到我可以对Tile数组做同样的事情,而不是检查是否为0,然后检查是否为null我猜。但是,我不在乎检查是否为null。 同样,这对我来说在某种程度上似乎是原始的,因为如果代码没有经过充分考虑并做一些它不应该做的事情。 另外,如果我试图将一个简单的xml文件解析为tilemap,我现在会变成一个泡菜,因为我不知道如何将xml与tile相匹配,我以前只能使用它身份证。 顺便说一句,我之前从未使用过xml,所以我只能猜测这是不是问题。

*虽然如果有人会明确说明"项目"的确切时间或原因。可以被认为是一个引擎,无论它可能是什么基础,那么它也很酷。因为我不认为我完全明白这一点。

**我意识到在这种情况下使用foreach更合适,但这只适用于Tile数组,afaik。

TL; DR 所以结束我的问题.. 什么是最合适的? tile [,]或Tile [,]是否为tilemap?而且,我是否应该使用2个不相关的X和Y ints在Tile类中使用vector2进行定位?

注意 - 我是一名计算机科学专业的学生,​​我们只有基本的" hello world"到目前为止,我所学到的其余部分来自个人兴趣。另外,如果有任何瑕疵或使用错误的条款,请纠正我。我在这里问,因为我需要帮助,而且我会提供任何帮助,无论是在主题上还是在主题之外。但是,如果以适当和建设性的方式给予我,我将不胜感激。

编辑:圣洁,我甚至没有意识到我已经写了那么多。 无论谁读到这一切,你都是真正的MVP!

3 个答案:

答案 0 :(得分:1)

您游戏中的某些区域可能只有一个区块,它们可能会有多个区块在彼此之上。

例如,一张桌子站在地板上,这样你就可以看到地砖和半透明的桌子砖。这意味着在这种情况下,简单的2d瓷砖阵列就不够了 也许是一个瓷砖实例列表,每个实例都有它的绘制坐标?然后你只需遍历列表并在屏幕上以任何顺序绘制图块。

答案 1 :(得分:0)

我不知道它是否仍然相关但无论如何。根据我的经验,绝对使用Tile [,]而不仅仅是int [,],考虑未来(尤其是当你构建引擎时,必须非常通用),也许有人会希望瓷砖动画或输入一些瓦片的逻辑。

你可以做的是使用int [,]构建tilemap,但使用XML会更好。提示:您可以将它们存储在字典(这是HashMap的c#实现)中,而不是在TileID上循环或使用长开关大小写(或许多ifs ofc),然后您将获得复杂的O( 1)而不是O(n)(这可能是至关重要的,可能不是,取决于你得到了多少瓷砖)。您可以在字典中存储委托创建函数的左右。

不使用Tile [,]或int [,]的主要问题是碰撞检测。您将不得不循环遍历整个磁贴集合,而不是仅计算正确的索引(或索引范围)。计算应该看起来像j = x / tilewidth;(再次O(1)而不是O(n),这里非常重要)。

如果你想在你的tilmap上有多个图层(对于桌子,椅子,植物等等)你可以创建Layer类(应该包含Tile [,])或者使用Tile [,,,]其中第一个索引是图层。我认为第一个更好,因为最后一个更复杂,更不通用。

答案 2 :(得分:0)

我建议使用整数。如果您的其他磁贴少于65.000,建议您使用ushorts。

假设您要使用8000x2000的图块。那等于16.000.000。

如果您选择存储引用(64位),那么您将占用16.000.000 * 64 = 1024000000位(〜1000 MB RAM)

如果您选择存储整数(32位),那么您将占用16.000.000 * 32 = 512000000位(〜500 MB RAM)

如果您选择存储uShorts(16bit),则将占用16.000.000 * 16 = 256000000位(〜250 MB RAM)

在我看来,值得花费额外的CPU时间在Tile数组中进行查找,但这取决于您的情况。