マップエディタを作成しようとしています。マップは、各六角形がマップのタイルである六角形のグリッドになる予定です。タイルは、その領域 (海、牧草地、砂漠、山など) をグラフィカルに表現したものになります。マップは任意のサイズを想定しています。今のところ、ここで要件を凍結しましょう:)
PyQt4 を使用したい (設計要件として使用)。Qt/PyQt を使い始めたばかりなので、広大さの問題に直面しています。この Qt は大きすぎて、すべてを把握することはできません。そして、ここで私はあなたの親切で最も歓迎される経験を求めています.
少しグーグルで調べた後、QGraphicalView/Scene アプローチを使用することにしました。実際、QGraphicalView から継承する独自の hexgrid クラスを作成し、QGraphicalPolygonItem から継承する RegularPolygon クラスを作成することを考えていました。
今、彼らは疑問と問題を抱えています。
私の主な疑問は、「私のアプローチは正しいものですか?」ということです。投稿の冒頭で説明した必要性について考えてみてください: 各六角形が特定のタイプ (海、砂漠、牧草地、山など) のタイルになる六角形マップ。エディタが動くとパフォーマンスが気になる(スクロールが気持ちいい?とか)。
これまでのところ、問題は精度に関するものです。すべての六角形を作成して描画することで、六角形グリッドを描画しています(これは私には悪いように聞こえます...パフォーマンスについて考えています)。いくつかの式を使用して各六角形の頂点を計算し、そこから多角形を作成しました。2 つの連続する六角形の側面が同じ位置で正確に一致することを期待していますが、六角形の側面が同じ位置で完全に一致する (良い) 場合もあれば、一致しない場合もあるため、丸めは私の欲求に少し合っているようです。 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()
最後になりましたが、長い投稿で申し訳ありません:)
ありがとうビクター