Python遊戲引擎開發(七):繪製向量圖
阿新 • • 發佈:2019-02-03
今天來完成繪製向量圖形。
沒有讀過前幾章的同學,請先閱讀前幾章:
Graphics類
首先我們建立Graphics
類用於建立向量圖形:
class Graphics(DisplayObject):
def __init__(self):
super(Graphics, self).__init__()
# 儲存所有圖形資料的列表
self.__drawingList = []
# 用於儲存當前圖形資料
self.__currentGraphics = None
由於我們的視窗介面是在不斷清除,然後重繪的,所以加入__drawingList
__currentGraphics
用於儲存當前圖形資料。
在flash
中,我們使用beginFill
方法來下達開始繪製命令。加入該方法:
def beginFill(self, color = "transparent", alpha = 1):
if color == "transparent":
alpha = 0
self.__currentGraphics = {
"path" : QtGui.QPainterPath(),
"lineAlpha" : 255,
"lineWidth" : None,
"lineColor" : None,
"fillColor" : color,
"fillAlpha" : 255 * alpha,
"joins" : None,
"caps" : None,
"miterLimit" : None
}
開始繪製命令需要如下幾個引數:圖形填充色、填充色透明度。
在上面的程式碼中,我們初始化了__currentGraphics
屬性,可以看到,他是一個dict
物件,其中的path
成員是一個QPainterPath
物件,這個物件來自Qt
,通過呼叫這個類中的一些方法,可以建立一些圖形,然後呼叫QPainter
drawPath
方法就可以把這個物件裡建立的所有圖形畫出來。
新增endFill
方法,用於把當前圖形儲存到__drawingList
中,儲存到__drawingList
後,就可以使其顯示出來:
def endFill(self):
if not self.__currentGraphics:
return
self.__currentGraphics["path"].setFillRule(QtCore.Qt.WindingFill)
self.__drawingList.append(self.__currentGraphics)
然後是_show
方法,在前面的章節中介紹過,每個顯示在介面上的物件都有這個方法,用於顯示自身:
def _show(self, c):
for item in self.__drawingList:
if not isinstance(item, dict):
return
path = item["path"]
if not path:
continue
lineWidth = item["lineWidth"]
lineColor = item["lineColor"]
fillColor = item["fillColor"]
joins = item["joins"]
caps = item["caps"]
miterLimit = item["miterLimit"]
fillAlpha = item["fillAlpha"]
lineAlpha = item["lineAlpha"]
brush = None
pen = QtGui.QPen()
c.save()
if lineWidth:
pen.setWidth(lineWidth)
else:
pen.setWidth(0)
if lineColor:
color = getColor(lineColor)
if isinstance(color, QtGui.QColor):
if lineAlpha:
color.setAlpha(lineAlpha)
pen.setColor(color)
else:
pen.setColor(getColor("transparent"))
if joins:
pen.setJoinStyle(joins)
if caps:
pen.setCapStyle(caps)
if miterLimit:
pen.setMiterLimit(miterLimit)
if fillColor:
color = getColor(fillColor)
if fillAlpha and hasattr(color, "setAlpha"):
color.setAlpha(fillAlpha)
brush = QtGui.QBrush(color)
brush.setStyle(QtCore.Qt.SolidPattern)
c.setBrush(brush)
c.setPen(pen)
c.drawPath(path)
c.restore()
其中,我們遍歷了__drawingList
,從中讀取每個圖形資料,然後根據資料進行一些圖形樣式設定,最後drawPath
畫出圖形。
上面的程式碼主要完成了基礎的一些部分,目前我們只有開始繪圖和結束繪圖命令。還差設定樣式以及新增圖形的命令,通過以下程式碼加入:
def lineStyle(self, thickness = 1, color = "black", alpha = 1, joints = None, caps = None, miterLimit = 3):
if not self.__currentGraphics:
return
if color == "transparent":
alpha = 0
if joints == JoinStyle.ROUND:
joints = QtCore.Qt.RoundJoin
elif joints == JoinStyle.MITER:
joints = QtCore.Qt.MiterJoin
elif joints == JoinStyle.BEVEL:
joints = QtCore.Qt.BevelJoin
if caps == CapsStyle.NONE:
caps = QtCore.Qt.FlatCap
elif caps == CapsStyle.SQUARE:
caps = QtCore.Qt.SquareCap
elif caps == CapsStyle.ROUND:
caps = QtCore.Qt.RoundCap
self.__currentGraphics["lineWidth"] = thickness
self.__currentGraphics["lineColor"] = color
self.__currentGraphics["lineAlpha"] = 255 * alpha
self.__currentGraphics["joints"] = joints
self.__currentGraphics["caps"] = caps
self.__currentGraphics["miterLimit"] = miterLimit
def moveTo(self, x, y):
if not self.__currentGraphics:
return
self.__currentGraphics["path"].moveTo(x, y)
def lineTo(self, x, y):
if not self.__currentGraphics:
return
self.__currentGraphics["path"].lineTo(x, y)
def drawRect(self, x, y, width, height):
if not self.__currentGraphics:
return
self.__currentGraphics["path"].addRect(x, y, width, height)
def drawCircle(self, x, y, radius):
self.drawEllipse(x - radius, y - radius, radius * 2, radius * 2)
def drawEllipse(self, x, y, width, height):
if not self.__currentGraphics:
return
self.__currentGraphics["path"].addEllipse(x, y, width, height)
有了這些命令,就可以進行繪圖操作了。
Sprite上使用Graphics
Graphics
主要是在Sprite
上使用,如下程式碼所示:
layer = Sprite()
layer.graphics.beginFill("#FF0000")
layer.graphics.drawRect(0, 0, 200, 200)
layer.graphics.endFill()
addChild(layer)
可見我們需要為Sprite
新增一個graphics
屬性,用於操作向量圖形,所以在Sprite
構造器中加入如下程式碼:
self.graphics = new Graphics()
self.graphics.parent = self
通過上面的這些命令,我們就可以創建出許多不同的向量圖形:
繪製向量圖的功能就搞定了~如有不懂之處,歡迎留言。
至此,引擎基本功能就實現了