编辑:我刚刚删除了整篇文章,并重新提出了更为通用的问题。
我想做一个简单的策略游戏:地图,单位。
地图:一节课。单位:另一类,自画。
简单问题:
多数民众赞成!
答案 0 :(得分:2)
有两种方法。
要么有一个Map类,它是主要的JPanel,要维护单元的集合,但要将Unit类保持为非Swing。调用Map的paint()方法时,通过调用每个可见Unit中的方法,让每个Unit重绘自己。 Unit可以从任何基类继承,例如Rectangle,或者您在程序中使用的其他一些数据结构。在这种情况下,Unit类处理绘画和计算,但Map处理每个单元的点击和事件。如果需要,它可以将消息传递给该单位;但是,如果单位本身不需要了解这些东西,这种方法效果很好。 Unit类轻巧经济。您还可以决定单位是否知道其在地图中的位置。
或者将每个单元作为JComponent,并分别处理自己的事件。缺点是单元的每个实例都会创建一堆数据以便绘制它。因此,如果你有数百个单位,只有几个单位被绘制,这种方式效率不高。优点是每个单元可以处理自己的GUI事件而无需翻译等。这也假设游戏中的实际单位和屏幕上的图形单元的1:1映射。如果一个单位需要知道其他单位是什么,那么在单位中实施某些事件处理程序也比较棘手!
第三种可以说是更好的方法是拥有一个纯粹的数据Unit类,包含有关单元的游戏信息,如(1)所示,但它有一个在需要时创建JComponent的方法。例如,JComponent可以是Unit中的内部类 - 然后它可以访问Unit数据。如果单元可能需要在2个位置显示(例如,在2个屏幕或视图上),这是很好的。
-
这是正确的,在(1)Map(主JPanel)实现鼠标处理程序,并依次询问每个单元是否“命中”。这允许您执行更复杂的操作,例如将2个单元重叠/彼此叠加,并且两者都可以响应单击。
另外,例如,它们可能不是矩形,也可能是使用alpha通道绘制的(如果单位是JComponents,它们默认会在整个矩形上抓取任何鼠标事件给自己)。如果你的单位没有重叠并且在它们自己的矩形中,那么JComponent自己的鼠标处理程序就足够了。
如果使用方法(1),地图可以询问每个单位是否包含点击的点,然后地图可以处理“选择”过程。请记住,一个单位本身将无法确定选择其他单位 - 选择可能涉及取消选择另一个单位。在这种情况下,选择操作实际上是Map操作,而不是Unit操作,尽管它也可能改变Unit的外观或功能。
如果对单位使用单独的JComponents,则可以覆盖contains(Point)以确定鼠标是否命中该项目,但这不会让其他单位也响应该单击。但是每个单元可以“自己选择”(设置绘制时使用的标志)然后通知Map(它需要使用getParent或预设属性来查找它)。
在决定此设计之前,您需要了解的关键事项是: 每场比赛你需要一个以上的“地图”面板吗? 您是否需要比显示更多的Unit对象? 你需要不止一次展示一个单位吗? 如果答案是肯定的,您应该将“数据”类与“视图”类分开,如3中所示。 那么:一个单位需要做什么?为了做到这一点,它需要了解地图和其他单位需要了解什么?例如在这种情况下,移动通常由Map类完成,因为它取决于Map和其他单元;最好由单位完成绘图,因为可能需要绘制许多具有不同数据结构的单位子类型;你所指出的单位选择操作介于两者之间。如果你看到Swing如何实现它(例如ButtonGroup,ListSelectionModel),那么'selection'本身可以作为一个单独的类。
答案 1 :(得分:0)
几年前我制作了一个peg纸牌游戏,它几乎只是一个扩展了MouseListener和MouseMotionListener的JPanel。钉是在绘制方法中绘制的原始圆,但是您可以通过获取光标位置并以数学方式计算它着陆的方格来跟踪它们着陆的位置。这样就排成了一个阵列,在板上每个方块都存储1或0,具体取决于是否存在任何东西。您还可以通过查找当前光标位置来拖动每个部分,然后在实现MouseMotionListener的mouseDragged方法中调用repaint()。
我可能建议以这种方式开始。创建一个任意大小的数组,并使用它来跟踪单位。然后每次进行移动时,只需检查该数组并在paint方法中重绘单位。如果您正在使用鼠标移动,那么您可以在mouseDown上获取该单元的当前位置,然后使用mouseDragged执行我之前提到的操作,然后在mouseUp上获取您的最终位置,并对mouseUp中的合法移动等进行计算。
在paint方法中,你只需遍历定义地图的数组,如果在数组的当前位置有一个单位,那么执行类似g.fillOval(x,y,x_dimension,y_dimension)的操作。该阵列可以将其元素设置为0,当前位置没有单位,或者当前位置的团队1单位为1,团队2等为2等。绘制方法将采用这些数字并相应地绘制棋子(更改颜色)对于每种类型或其他什么)。
我希望这有点道理。