我目前正在使用Python开发一个基于十六进制的2D棋盘游戏。我没有使用PyGame,我用更难的方法来练习。图形目前是使用PyQt5创建的。使用QPolygonF和QGraphicsPolygonItem创建六边形块,并使用QPixmap和QGraphicsPixmapItem添加来自图像文件的图像。“移动相机”仅仅是通过调整所有位置计算的起始点来完成的。
问题是,我想要一些纹理的瓷砖从现成的图像文件。这样,板子看起来比纯色漂亮多了。我可以绘制准备好的六边形图像文件并放置它们,但这看起来很好,只有当图像已经是六边形,并且图像是仔细地缩放和放置。如果我以后改变主意,例如,我想从六边形变成正方形或透视六边形或其他形状,所有的工作都白费了。因此,将纹理设置为形状会更好--这将是更通用的。
我发现可以使用QBrush ()将纹理设置为setTexture()。起初,这听起来是个完美的解决方案,只是不,它不是。由于某种原因,这种纹理缺乏一个更好的术语,是全球性的。
此外,纹理不会“粘”在瓷砖上,因为“照相机”(实际上是瓷砖)被移动
我首先尝试通过测试像素映射的滚动()做什么来解决这个问题。我不知道在地狱的九圈里发生了什么。此外,它显然是沉重的计算机,帧速率的程序严重中断。
我需要建议,因为我不知道该怎么做,谷歌教授也没有多大帮助。
绝对最好的解决方案是,添加几行代码就可以生成裁剪到QPolygon描述的区域的图像。我也可以使用一个全局纹理,只要我可以移动它与瓷砖,以“粘贴”纹理。由于我进入这个项目的时间还早,如果认为有必要改变库或其他类似的东西,那么它也是一个合理的工作量。
以下是相关代码:
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.Qt import QPixmap
from PyQt5.QtGui import QBrush
import math
def main():
global app
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
class Window(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setCentralWidget(QtWidgets.QWidget())
self.horizontal = QtWidgets.QHBoxLayout()
self.centralWidget().setLayout(self.horizontal)
self.x0 = 30
self.y0 = 30
self.scale = 1.0
self.board = Board(8,8)
self.scene = QtWidgets.QGraphicsScene()
self.initWindow()
self.update()
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.update)
self.timer.start(int(1000 / 60)) # Milliseconds
"Initialize the window"
def initWindow(self):
self.setGeometry(300,200,800,800)
self.show()
self.scene.setSceneRect(0, 0, 700, 700)
self.view = QtWidgets.QGraphicsView(self.scene, self)
self.view.adjustSize()
self.view.show()
self.horizontal.addWidget(self.view)
def update(self):
self.scene.clear() # The window is wiped clean before adding updated graphics
r = self.scale * 50
h = r * math.sin(math.pi/3)
midpointX = 0
midpointY = 0
for x in range(self.board.width):
for y in range(self.board.height):
qt_polygon = QtGui.QPolygonF()
if y % 2 == 0:
midpointX = ( self.x0 + h*2*x )
else:
midpointX = ( self.x0 + h + h*2*x )
midpointY = ( self.y0 + 1.5*r*y )
qt_polygon.append(QtCore.QPointF( midpointX, midpointY - r ))
qt_polygon.append(QtCore.QPointF( midpointX + h, midpointY - 0.5*r ))
qt_polygon.append(QtCore.QPointF( midpointX + h, midpointY + 0.5*r ))
qt_polygon.append(QtCore.QPointF( midpointX, midpointY + r ))
qt_polygon.append(QtCore.QPointF( midpointX - h, midpointY + 0.5*r ))
qt_polygon.append(QtCore.QPointF( midpointX - h, midpointY - 0.5*r ))
polygon = QtWidgets.QGraphicsPolygonItem(qt_polygon)
path = <insert path>
pixmap = QPixmap(path)
brush = QBrush()
brush.setTexture(pixmap)
polygon.setBrush(brush)
self.scene.addItem(polygon)
"Keyboard commands"
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_A:
self.x0 -= 5
if event.key() == QtCore.Qt.Key_D:
self.x0 += 5
if event.key() == QtCore.Qt.Key_W:
self.y0 -= 5
if event.key() == QtCore.Qt.Key_S:
self.y0 += 5
class Tile():
def __init__(self):
""
class Board():
def __init__(self, width, height):
self.height = height
self.width = width
self.tiles = [None] * self.width
for x in range(self.width):
self.tiles[x] = [None] * self.height
for y in range(self.height):
self.tiles[x][y] = Tile()
main()发布于 2022-07-14 19:19:11
笔刷总是相对于图形项的位置。
由于一个新的图形项总是位于(0, 0)坐标,所以您将始终得到相同的画笔,因为您正在创建的多边形的点总是相对于0。
相反,您应该做的是始终创建相同的多边形,然后在适当的坐标下移动它。
def update(self):
self.scene.clear()
r = self.scale * 50
h = r * math.sin(math.pi/3)
hexagon = QtGui.QPolygonF([
QtCore.QPointF(h, 0),
QtCore.QPointF(h * 2, 25),
QtCore.QPointF(h * 2, 75),
QtCore.QPointF(h, 100),
QtCore.QPointF(0, 75),
QtCore.QPointF(0, 25),
])
for x in range(self.board.width):
for y in range(self.board.height):
midpointX = 2 * h * x
if y & 1:
midpointX += h
midpointY = 1.5 * r * y
polygon = QtWidgets.QGraphicsPolygonItem(hexagon)
polygon.setPos(midpointX, midpointY)
path = '/tmp/spacebg.jpg'
pixmap = QPixmap(path)
brush = QBrush()
brush.setTexture(pixmap)
polygon.setBrush(brush)
self.scene.addItem(polygon)一个非常重要的注意事项:虽然图形视图框架非常快,但是持续地清除场景并重新创建它通常并不是非常有效;相反,要找到方法重用现有的项并最终更新它们。
如果您只想在按下键时移动项目,那么不断地重建整个场景是没有意义的,而且完全没有必要,而不是完全浪费资源。相反,创建一个实际移动这些项的函数,然后只在适当的键按下时才调用它。还请注意,如果您实际上只想滚动场景的视图,则应该使用视图的setSceneRect(),或者最终使用滚动条(假设场景足够大)。
最后,请注意,update()是任何QWidget的一个现有函数,它不仅非常重要,而且也是一个插槽,因此,除非您真正知道要做什么,否则不应该覆盖它。
https://stackoverflow.com/questions/72972062
复制相似问题