Я пытаюсь создать редактор карт. Я предполагаю, что карта представляет собой гексагональную сетку, где каждый шестиугольник является плитой карты. Плитка будет графическим изображением этой области (море, луг, пустыня, гора и т. Д.). Карта предназначена для любого размера. Давайте сейчас заморозим требования :)Hex grid map с PyQt4
Я хочу использовать PyQt4 (возьмите его как требование к дизайну). Поскольку я только начинаю с Qt/PyQt, я столкнулся с проблемой огромности: такая большая вещь Qt, которую я не могу понять. И вот я, прошу вас о вашем доброжелательном и приятном опыте.
После небольшого поиска в Google, я решил использовать подход QGraphicalView/Scene. Фактически, я думал о создании собственного класса hexgrid, наследующего от QGraphicalView, и создания моего класса RegularPolygon, наследующего от QGraphicalPolygonItem.
Теперь у них возникают сомнения и проблемы.
Мое главное сомнение заключается в том, что мой подход правильный? Подумайте о потребностях, которые я объяснил в начале сообщения: гексагональная карта, где каждый шестиугольник будет плитой определенного типа (море, пустыня, луга, горы и т. Д.). Меня беспокоит производительность после того, как редактор работает (прокрутка будет приятной и что-то подобное).
И до сих пор проблема в точности. Я рисую гексдрид, создавая и рисуя все его шестиугольники (это даже звучит плохо для меня ... думая о производительности). Я использовал некоторые формулы для вычисления вершин каждого шестиугольника и создания там многоугольника. Я ожидаю, что стороны двух последовательных шестиугольников совпадут точно в одном и том же месте, но округление, похоже, немного походит на мои желания, так как иногда стороны шестиугольника идеально совпадают в одном и том же месте (хорошо), и иногда они не совпадают что кажется 1 пиксельной разницей (плохой). Это дает плохое визуальное представление о сетке. Может быть, я не объяснил себя очень хорошо ... это лучше, если я дам вам код и запустить его сами
Так суммирующих:
- Как вы думаете, что мой подход даст в будущем проблемы с производительностью?
- Почему гексагоны не расположены точно так, что они разделяют стороны? Как избежать этой проблемы?
Код:
#!/usr/bin/python
"""
Editor of the map.
"""
__meta__ = \
{
(0,0,1): (
[ "Creation" ],
[ ("Victor Garcia","[email protected]") ]
)
}
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()
и последнее, но не в последнюю очередь, извините за длинный пост :)
Благодаря Виктор
Я нашел http://www.pygame.org/ с примерами гексрид, но они не используют PyQt. Я посмотрю на это, определенно, но мой вопрос по-прежнему действителен, так как я хочу знать, как правильно сделать hexmap, используя qt. – victor
Я попробую другой подход. Рисование всех шестиугольников означает, что несколько вершин будут нарисованы два раза (те, которые разделены двумя шестиугольниками). Это звучит глупо: зачем делать ту же работу дважды? Я попробую рисовать первый шестиугольник (вверху слева? Может быть, начинается тот, что находится в центре сцены?). Чтобы управлять вторым, мне просто нужно нарисовать вершины, ожидающие рисования, и так далее. Это гарантирует, что общие вершины находятся в одном и том же пикселе, решая мою проблему точности. К счастью, это также позволит избежать проблем с будущей производительностью ... мне потребуется некоторое время, чтобы сделать это. – victor
Просто подсказка для идентификации области щелчка, используйте 2 прямоугольника для грубого анализа (внешние границы, внутренние границы) и при необходимости (щелкните в области перекрытия внешних границ) подсчитайте, какой гексагон активирован (если он не решен с помощью сцен-мышей). –