我正在尝试创建一个地图编辑器。我希望地图是一个六边形网格,其中每个六边形都是地图的一个图块。瓦片将是该区域(海洋、草地、沙漠、山脉等)的图形表示。该地图旨在为任何大小。让我们暂时冻结这里的要求:)
我想使用 PyQt4(把它作为设计要求)。当我刚开始使用 Qt/PyQt 时,我面临着巨大的问题:这个 Qt 东西太大了,我无法掌握它。我在这里,请求您的亲切和最受欢迎的体验。
经过一番谷歌搜索,我决定使用 QGraphicalView/Scene 方法。事实上,我正在考虑创建我自己的继承自 QGraphicalView 的 hexgrid 类并创建我的继承自 QGraphicalPolygonItem 的 RegularPolygon 类。
现在他们来了疑惑和问题。
我的主要疑问是“我的方法正确吗?” 想想我在文章开头解释的需求:六边形地图,其中每个六边形将是给定类型(海洋、沙漠、草地、山脉等)的瓷砖。一旦编辑器工作,我会担心性能(滚动会感觉很好吗?和这种事情)。
到目前为止,问题在于精度。我通过创建和绘制所有六边形来绘制六边形网格(这对我来说甚至听起来很糟糕......考虑性能)。我使用了一些公式来计算每个六边形的顶点并从那里创建多边形。我希望两个连续六边形的边在同一位置完全重合,但舍入似乎有点符合我的愿望,因为有时六边形边在同一位置完美匹配(好),有时它们不匹配似乎有 1 个像素的差异(不好)。这给网格的视觉印象很差。也许我没有很好地解释自己......如果我给你代码然后你自己运行它会更好
所以总结一下:
- 你认为我的方法会带来未来的性能问题吗?
- 为什么不将六边形精确放置以便它们共享边?如何避免这个问题?
编码:
#!/usr/bin/python
"""
Editor of the map.
"""
__meta__ = \
{
(0,0,1): (
[ "Creation" ],
[ ("Victor Garcia","vichor@xxxxxxx.xxx") ]
)
}
import sys, math
from PyQt4 import QtCore, QtGui
# ==============================================================================
class HexGrid(QtGui.QGraphicsView):
"""
Graphics view for an hex grid.
"""
# --------------------------------------------------------------------------
def __init__(self, rect=None, parent=None):
"""
Initializes an hex grid. This object will be a GraphicsView and it will
also handle its corresponding GraphicsScene.
rect -- rectangle for the graphics scene.
parent -- parent widget
"""
super(HexGrid,self).__init__(parent)
self.scene = QtGui.QGraphicsScene(self)
if rect != None:
if isinstance(rect, QtCore.QRectF): self.scene.setSceneRect(rect)
else: raise StandardError ('Parameter rect should be QtCore.QRectF')
self.setScene(self.scene)
# ==============================================================================
class QRegularPolygon(QtGui.QGraphicsPolygonItem):
"""
Regular polygon of N sides
"""
def __init__(self, sides, radius, center, angle = None, parent=None):
"""
Initializes an hexagon of the given radius.
sides -- sides of the regular polygon
radius -- radius of the external circle
center -- QPointF containing the center
angle -- offset angle in radians for the vertices
"""
super(QRegularPolygon,self).__init__(parent)
if sides < 3:
raise StandardError ('A regular polygon at least has 3 sides.')
self._sides = sides
self._radius = radius
if angle != None: self._angle = angle
else: self._angle = 0.0
self._center = center
points = list()
for s in range(self._sides):
angle = self._angle + (2*math.pi * s/self._sides)
x = center.x() + (radius * math.cos(angle))
y = center.y() + (radius * math.sin(angle))
points.append(QtCore.QPointF(x,y))
self.setPolygon( QtGui.QPolygonF(points) )
# ==============================================================================
def main():
"""
That's it: the main function
"""
app = QtGui.QApplication(sys.argv)
grid = HexGrid(QtCore.QRectF(0.0, 0.0, 500.0, 500.0))
radius = 50
sides = 6
apothem = radius * math.cos(math.pi/sides)
side = 2 * apothem * math.tan(math.pi/sides)
xinit = 50
yinit = 50
angle = math.pi/2
polygons = list()
for x in range(xinit,xinit+20):
timesx = x - xinit
xcenter = x + (2*apothem)*timesx
for y in range(yinit, yinit+20):
timesy = y - yinit
ycenter = y + ((2*radius)+side)*timesy
center1 = QtCore.QPointF(xcenter,ycenter)
center2 = QtCore.QPointF(xcenter+apothem,ycenter+radius+(side/2))
h1 = QRegularPolygon(sides, radius, center1, angle)
h2 = QRegularPolygon(sides, radius, center2, angle)
# adding polygons to a list to avoid losing them when outside the
# scope (loop?). Anyway, just in case
polygons.append(h1)
polygons.append(h2)
grid.scene.addItem(h1)
grid.scene.addItem(h2)
grid.show()
app.exec_()
# ==============================================================================
if __name__ == '__main__':
main()
最后但并非最不重要的是,很抱歉这篇长文:)
谢谢维克多