游戏定位的OO设计

4
我正在开始一个游戏项目,这是我的第一个项目,它将类似于文明克隆,并且重点放在战争上。我一直使用C#开发业务应用程序(主要是Web应用程序),因此我对如何构建地图定位系统的设计有疑问。
我希望每个单位都知道自己的位置,并且地图知道每个点上的所有单位,这是双向关系,但我不知道最好的建模方式!如果您能提供一些想法和伪代码,我会很感激!
谢谢。

祝你好运。我自己很喜欢文明游戏,但更多的是享受创建大量军事单位并消灭我的邻居。我认为这样的东西有市场。 - MusiGenesis
6个回答

2
将您的地图制作成一个二维数组,在每个位置上放置所有对象的数组。此外,向每个对象添加位置属性。
是的,这将重复信息!因此,在每次移动时,您都需要更改对象并更新地图。
然而,对于这种类型的游戏来说,快速读取和快速查找对象非常重要。此外,该解决方案避免了任何搜索例程(例如,通过地图查找特定对象),这通常是一个好主意:用索引替换所有大型数据集上的搜索例程。可以将地图视为某种索引,用于对象的位置属性。

我应该告诉某个单位移动并让它更新地图吗? - Alaor
当然可以!这样一来,更新的代码就干净地放在一个地方。 - vog
1
这是一个回合制游戏,速度并不是一个因素。除非他有成千上万的游戏对象,但他不会有 - 将单位分成每个玩家一个数组就足够了。 - Sneakyness
值得一提的是,无论您选择哪种方法,更新代码都应该干净、整洁,并且放在一个地方。 - Sneakyness

2
地图应该拥有所有对象的知识。此外,只有地图上的每个对象应该知道自己的位置。这样,地图可以询问所有对象它们在哪里,并将它们放置在正确的位置。您永远不应该存储两次定位信息。

“你不应该需要两次存储定位信息”... 这是一种极端的观点,我不推荐这么做。它既不简化代码也不使其更快。 - vog
3
这种方式大大简化了代码。不得不重复跟踪某些事情是很荒谬的,特别是如果你忘记在两个地方更新它。在这里使用观察者模式,让映射关系观察其对象,比数据变量的重复更加可取。 - AlbertoPL
2
我认为要绘制场景,地图必须知道哪些单位在某个区域内,这样会使绘制屏幕变得容易,而要移动单位,它们必须知道自己的位置和目的地,因此我认为需要将其存储两次,我知道这很容易出错,但这会使开发变得更轻松,我需要一种优雅的模式或示例代码来完成这个问题。 - Alaor
必须要两次跟踪同一件事情是非常荒谬的,这太极端了。执行搜索操作也是额外的工作,并且通常比简单更新索引更费力。如果直接在对象的“changePosition()”或“move()”方法中进行更新索引,则不容易出错。换句话说:只需要在一个地方更新索引即可。 - vog
1
DRY的意思是:在代码中不要重复自己。是的,索引更新代码应该放在一个地方。DRY并没有涉及数据方面。事实上,多次存储数据是任何快速数据访问方法的关键。每个数据库都这样做。 - vog
显示剩余2条评论

1
这里有一种方法可以避免重复:
创建一个类,它包含地图上所有对象,并在其中包含不同类型对象的集合。
public class MapObjects
{
   private Collection<GamePiece> gamePieces;
}

每个集合中的项目都将保存它们(当前)的地图坐标。
public class GamePiece
{
   private MapCoordinate mapCoordinate;
   // Other items relevant to a GamePiece.. Health, ItemType, etc
}

找到地图上特定选定项的位置应该很容易,您有一个持有其坐标的GamePiece的引用。要查找特定坐标中有哪些项,您需要一个帮助方法,可能在MapObjects类中:
public class MapObjects
{
   public Collection<GamePiece> GamePiecesAtLocation(MapCoordinate mapCoordinate)
   {
      // Iterate through gamePieces collection and build a result 
      // collection of items at specified coordinates.
   }
}

祝你好运,听起来是一个充满挑战的有趣项目。


这真的比每次 GamePiece.move() 后更新地图更好吗?MapObjects 变量似乎更慢,需要更多的代码。 - vog
谢谢,那很有帮助。我考虑过这种方法,但我有一个问题:如果比例发生变化,有很多单位的地图改变存储位置信息的责任会节省一些时间吗?但现在我想我错过了重点,没有办法将那么多单位放到一个地图上,即使在繁忙的游戏中,让单位知道它们在哪里会更好。 - Alaor

0

好的设计等于简单的设计。

将地图制作成对象列表。

Object
    int X { get; set; }
    int Y { get; set; }

Map
    List<Object> objects
    Add(Object)
    Remove(Object)
    GetAt(X, Y)
    GetInBox(X,Y,Width,Height)
    GetInRadius(X,Y,Radius)

这应该是你所需要的全部。如果 Get(..) 查询变得过慢,可以添加缓存或将地图分成区块,并为每个区块保留对象列表,并在它们移动时更新它。如果你有许多静态对象或物体不会太快地从一个区块到另一个区块移动,这将有助于显着提高性能。我猜在回合制游戏中,你根本不需要进行优化。


NSPoint、NSRect 和 NSRange 可以替换你所写的一半内容。没必要重复造轮子。 :) - Sneakyness
我认为首先解释轮子的工作原理是很好的,然后再寻找现有的实现。此外,NSPoint可能不会在每种语言和/或平台上都可用。 - Tomas Andrle

0
我会将地图变成六边形而不是网格,这样你就不会出现奇怪的文明现象,即你可以对角线覆盖更多的地面。除此之外,我只会让每个单位存储自己的位置,当你需要知道哪些单位在特定的六边形中时,只需遍历整个集合即可。很难想象有那么多单位参与,以至于这种方法会成为性能问题。

1
一个六边形网格通常也只是一个二维数组。 :-) ……有一些坐标没有使用。 - vog
MusiGensis!很高兴在这里见到你。我建议为每个玩家都有一个单位数组。请参阅下面关于编写此类内容的意外复杂性的答案。 - Sneakyness
@Sneaky:在美好的星期天下午,我还能在哪里呢?出去享受这个世界吗? - MusiGenesis

0

NSPoint在这种情况下非常有用。每个游戏对象都应该有自己的位置。你可以将这些游戏对象存储在数组中,一个数组为每个玩家,一个数组为整个游戏,这取决于你。

我要警告你,这是一个非常庞大的项目,不仅是代码方面,而且是内容方面,需要大量的反复工作来平衡游戏。在尝试这个项目之前,你应该真正尝试一些较小的游戏。没有什么能阻止你开始,但如果你的第一个游戏是如此庞大的话,你会遇到很多障碍并写出一些严重的混乱代码。我建议从像跳棋这样的东西开始,以掌握回合制的基本概念。

这一切都来自于目前正在编写他的第一个游戏项目——地牢游戏的人。在我的辩护中,它相对简单,但有很多事情我没有预料到,即使是计算视野/战争迷雾考虑到障碍物也使用了复杂的算法。我不后悔选择地牢游戏作为我的第一个游戏,但在看到即使是最基本的概念实现起来也很复杂之后,像回合制策略游戏这样的东西对我来说只是留给专业人士。

如果你目前正在苦恼如何不仅创建单位,而且还要表示地图和存储位置,那么当编写研究、城市、生产、资源收集、随机地图生成器、轨迹计算、命中概率、装甲、机动性、视野范围、随机事件、人工智能等代码时,你该怎么办呢?

我并不是要打击你的梦想,只是提醒你选择的游戏类型比看起来更加复杂。你的大脑会超负荷而爆裂开来。(我可以继续押韵,但我会忍住不说,提醒你应该先尝试一些像跳棋这样的简单游戏。)


1
跳棋?也许他可以先从井字游戏开始。 :) - MusiGenesis
说实话这并不是一个坏主意。但不要只是试图制作游戏。加入你自己的独特元素,改变一些东西。 - Sneakyness
嗨!感谢回复,我完全同意你的观点。我知道这将是一个巨大而艰难的项目,但目前还不是商业化的目标,它是我研究生期间的一个最终项目,我有一个团队与我一起工作,他们会处理其他方面的事情,如图形、音频等。游戏玩法已经计划好了,像城市、生产公式等方面的东西,整体上它是如何运作的,所有这些都在编码之前考虑过了。就像编码是我的责任一样,我开始建模实体,如城市、国家、单位,并制定了一个定位系统,我只想知道我是否走在正确的道路上。 - Alaor
计划实际上是要运用我们在课程中学到的大部分知识,包括人工智能、面向对象等。 - Alaor
我个人在确保基础知识掌握之前,甚至不会碰任何与游戏对象相关的东西。如果你以前从未制作过任何游戏,那么最好先写一些非常简单的东西,比如井字棋或跳棋,以便在那里犯所有简单的错误并了解你将为此项目做什么。特别是如果这是学校的期末项目。先学会走路再跑。 - Sneakyness
我在阅读有关XNA的书籍时做了两个小游戏,但也有一些指导性的项目。当我说这是我的第一个游戏时,是因为这是我自己从零开始做的第一个游戏。我之前通过跟随书本上的例子做过一些游戏,所以我认为我有一些基础可以开始自己独立开发了。 - Alaor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接