3D舞台,正如其名稱所指,是一個在三維空間中放置可視組件的概念。 Ren’Py在3D舞台中渲染可視組件時將計算合適的透視效果,並啟用Z軸維度、燈光和深度效果。
要理解3D舞台的話,可能最重要的點是Ren’Py使用的3D坐標系。 這是在2D坐標系中放置可視組件的方式:
在2D坐標系中,整個矩形就是界面的尺寸。可見區域的寬和高通過 gui.init()
項進行配置(通常在新建遊戲項目時配置)。
3D舞台從原有的坐標系中擴展出了一個新軸——Z軸,其方向正對觀察者視線。 圖像坐標在Z軸方向的值大於0時,該物體距離觀察者近(圖像比原尺寸大); 圖像坐標在Z軸方向的值小於0時,該物體距離觀察者遠(圖像比原尺寸小)。
最後,當圖像在3D坐標系中旋轉時,各個軸的變化情況如下:
這些坐標系的要點解釋,是為了使Ren’Py開發者更容易從2D舞台轉入3D舞台。 當導入3D模型後,還需要根據模型坐標進行坐標變換,使模型能正確顯示。
攝影機的初始位置由參數 gui.init 控制。
Ren'Py會根據 `width()
和 fov 計算出默認的 z 軸坐標。在 fov 預設值為75的情況下:
實際的z軸坐標與這裡給的數值有一個小於1的誤差。
預設的z軸坐標可以通過樣式特性 perspective
或配置項 config.perspective
進行修改。
Ren’Py會自動給攝影機坐標設置一個坐標偏移量(width / 2, height / 2, z)。 攝影機觀看方向為Z軸的負無窮方向。
這個初始的 z 軸距離也是攝影機到某個特殊平面的距離。 在此特殊平面上的圖像,正好能顯示原來的尺寸(忽略整個應用窗口的縮放效果)。 增大攝影機的z軸坐標可以讓所有顯示內容變小,相反則會讓顯示內容變大。
最後一點, perspective
和 config.perspective
設置了攝影機可視範圍,預設的最近和最遠距離分別是100和10000.
當圖像與攝影機的z軸距離小於100或大於10000時,圖像將不會顯示。
使用3D舞台時,首先需要使用 camera
語句指定圖層。常用方法是:
camera:
perspective True
創作者可能還會想要設置一個預設的攝影機位置。詳見下面的內容。
顯示圖像(背景和sprite)則與2D坐標系中相同:
scene bg washington
show lucy mad at right
show eileen happy
所有可視組件都可以在3D空間內移動:
scene bg washington:
xalign 0.5 yalign 1.0 zpos -1000
show lucy mad:
xalign 1.0 yalign 1.0 zpos 100
show eileen happy:
xalign 0.5 yalign 1.0 zpos 200
指定一個ATL變換後,不再使用預設的變換,因此有必要顯式聲明 xalign
和 yalign
的值,分別對應可視組件在x和y軸的坐標。
當然,變換也可以像下面這樣使用:
transform zbg:
zpos -100
transform z100:
zpos 100
transform z200:
zpos 200
scene bg washington at center, zbg
show lucy mad at right, z100
show eileen happy at center, z200
如果嘗試過3D舞台,你會發現背景圖片周圍有一些空白空間。
這是因為背景向後移動後,顯示的尺寸變小了,不能填充整個螢幕。
Ren’Py提供了一個簡單方式修復這個問題—— zzoom
。
將 zzoom
特性設置為True後,無論圖像在z軸負方向的值是多少,都會放大圖像填充整個螢幕。
這對背景圖像很有效:
transform zbg:
zpos -100 zzoom False
使用ATL也可以調整zpos的值,如同調整xpos和ypos一樣:
show eileen happy at center:
zpos 0
linear 4.0 zpos 200
需要注意,zpos與幾個特殊位置(比如 left
和 right
)以及位置相關特性(比如 xalign
和 yalign
)一起使用時,
可能出導致奇怪的問題。因為Ren’Py會將圖像放在一個三維的有體積的矩形中(就像一個方塊,但各邊長度不一致),並對圖像應用透視效果,
最終導致部分圖像移出螢幕範圍。
攝影機也可以移動,使用 camera
語句。例如:
camera:
perspective True
xpos 0
linear 3.0 xpos 500
需要移動攝影機時,最好使用比整個窗口還要大的背景圖片。
如果在某個sprite上應用了zpos值但沒有任何效果,原因可能是在 camera
語句後面忘記添加 perspective
從句了。
默認情況下,Ren’Py根據聲明順序顯示圖像,最後聲明的圖像覆蓋在其他所有圖像之上。 這個機制會導致一些小問題,比如距離攝影機更近的圖像(使用透視效果)被遠處的圖像遮擋住。
如果不想要在遊戲中的圖像顯示層級出現類似問題,可以讓GPU根據深度排列圖像順序,使用
If your game shows images out of order like this, you can tell the GPU gl_depth
:
camera:
perspective True
gl_depth True
名義上處於相同深度的圖像可能會相互覆蓋和顯示錯誤。將這些圖像壓制(flatten)為單一圖像並同時顯示就能解決該問題。
Ren’Py中可以使用 matrixtransform
變化特性,將某個矩陣應用到可視組件上,實現三維空間中圖像的伸縮、位移和旋轉。
matrixtransform
特性可以使用一個 Matrix()
實例或transformmatrix(定義在下一節),並應用到顯示圖像的4個角的頂點上。
Ren’Py使用 matrixanchor
變換特性使矩陣應用更方便。
matrixanchor
的預設值是(0.5, 0.5),並使用通用Ren’Py錨點規則轉換為圖像內部的像素偏移值。
(如果是正數,視為像質數;否則視為整個像素尺寸的比例值。)
Ren’Py將矩陣變換應用到圖像上時,首先將圖像錨點設置(0, 0, 0)。應用矩陣變換後,再將錨點回復為原值。 默認情況下,變換矩陣會應用到圖像中心位置。
例如:
show eileen happy at center:
matrixtransform RotateMatrix(45, 0, 0)
會將圖像沿著其水平中軸做旋轉。圖像頂部向z軸負方向移動,圖像底部向z軸正方向移動。
多個矩陣可以使用乘法連接,依次從右到左實現變換效果。 例如:
show eileen happy at center:
matrixtransform RotateMatrix(45, 0, 0) * OffsetMatrix(0, -300, 0)
圖像將向上平移300像素,然後沿X軸旋轉45度。
Matrix對象只適合靜態變換,對動畫變換沒什麼用。 還有一種可以將普通矩陣參數化的方法。
TransformMatrix是由同一個基類擴展得到的一些使用矩陣創建的類。 Ren’Py調用TransformMatrix類的實例,並得到返回矩陣結果。 TransformMatrix已很好集成在ATL中,可以使用matrixtransform實現動畫。
transform xrotate:
matrixtransform RotateMatrix(0.0, 0.0, 0.0)
linear 4.0 matrixtransform RotateMatrix(360.0, 0.0, 0.0)
repeat
TransformMatrix的子類必須要實現 __call__
方法。該方法需要兩個參數:
下面的列表是Ren’Py內建的TransformMaxtrix子類:
OffsetMatrix
(x, y, z) linkTransformMatrix子類,將頂點移動固定數值後,返回一個矩陣。
RotateMatrix
(x, y, z) linkTransformMatrix子類,將可視組件繞原點旋轉後,返回一個矩陣。
旋轉按如下順序實行:
ScaleMatrix
(x, y, z) linkTransformMatrix子類,縮放可視組件後,返回一個矩陣。
下列變換特性可以在3D舞台中使用。
matrixanchor
linkType: | (position, position) |
---|---|
Default: | (0.5, 0.5) |
該特性指定圖像關聯的錨點位置矩陣。 如果變數是浮點數,是與子組件尺寸相關的比例值;否則,表示像質數。
該特性會將matrixtransform應用的變換對象的值設置為原點(0, 0, 0)的位置。
matrixtransform
linkType: | None or Matrix or TransformMatrix |
---|---|
Default: | None |
若非空,該特性指定的矩陣用於變換子組件的頂點變換。 該變換對象用作子組件變換位置與螢幕坐標間的轉換。
perspective
linkType: | True or False or Float or (Float, Float, Float) |
---|---|
Default: | False |
該特性應用到某個變換時,啟用透視渲染效果。
特性值應該是個3元元組,分別表示最近平面、1:1平面z軸距離和最遠平面。
如果值是一個浮點數,最近和最遠平面從配置項 config.perspective
獲取。
如果值是True,所有3個數值都從配置項 config.perspective
獲取。
當perspective特性不是False時, xpos
、 ypos
和 zpos
的值是反轉的,
表示相對攝影機的位置,而不是某個子組件自身的坐標。
zpos
linkType: | float |
---|---|
Default: | 0 |
改特性表示子組件在z軸方向的偏移。 當perspective特性值是False時,可以直接使用該特性值,否則需要乘以-1後再使用。
如果設置該特性後子組件消失,可能的原因是作為父組件的可視組件本身的zpos是False。
zzoom
linkType: | bool |
---|---|
Default: | False |
若該特性值為True,1:1平面(zone)的z軸距離將於該可視組件的zpos值保持一致。 子組件則根據 (zone - zpos) / zone 在x和y軸縮放。
改特性用作背景的可視組件,在 zpos 為負值的情況下,不會出現顯示過小無法覆蓋整個螢幕的情況。 該項設置為True後,背景圖像始終將以1:1的比例顯示。