Ren’Py含有一些拖放組件,這些組件允許使用滑鼠在界面上任意移動。關於拖拽功能的使用有以下要點:
拖放組件提供不僅限於自身的拖放功能。這裡主要涉及兩個類。Drag類提供讓一些東西能夠在界面上拖動的功能,讓其他可拖動組件掉落在自己上面的功能,或者兩者兼有。DragGroup類提供了Drag的群組功能——當拖放發生時,作為同一個DragGroup內的一部分,組內所有Drag對象都需要做出響應。
拖放系統可以通過 Screen Language 使用,或者直接用作可視組件。當你創建Drag對象後不再需要引用這些對象,最好使用界面語言。典型的情況是,可拖拽組件顯示了一個用於放置在界面裡的窗口。如果你在創建Drag對象後還需要引用,通常更好的做法是直接創建Darg對象並把它們添加到一個DragGroup對象中。
Drag
(d=None, drag_name=None, draggable=True, droppable=True, drag_raise=True, dragged=None, dropped=None, drag_handle=(0.0, 0.0, 1.0, 1.0), drag_joined=..., clicked=None, hovered=None, unhovered=None, mouse_drop=False, **properties) link一個可視組件,提供了一個對象,可以在其有效區域內使用滑鼠拖拽。一個Drag對象還有供其他Drag對象可以掉落在上面的區域。
一個Drag對象可以在父對象(parent)內部隨意移動。通常,Drag的父對象是一個 Fixed()
或 DragGroup
。
一個Drag對象有一個子組件。子組件的狀態反映出拖放操作的狀態:
selected_hover
- 當其被拖拽時。selected_idle
- 當其被放下時。hover
- 滑鼠已點擊而拖拽未發生時。idle
- 其他情況。拖拽句柄(handle)是一個子組件內的矩形。當滑鼠進到拖拽句柄裡的非透明像素上方時,就允許發生拖拽或點擊。
一個新創建的可拖拽組件會被添加到預設的DragGroup中。一個可拖拽組件只能在一個DragGroup裡。一旦被添加到另一個組中,就會自動被上一個組移除。
當某個Drag對象首次渲染時,如果從其所在的DragGroup中無法獲得坐標,就使用標準布局算法計算出它的左上角坐標。
一個回調函數(或回調函數列表),當Drag對象落下時被調用。調用時使用兩個入參。第一個參數表示掉落在哪個Drag對象上。第二個參數是一個被拖拽的Drag對象列表。如果回調函數返回一個非None,這個值也會作為此次交互行為的返回結果。
當dragged和dropped回調函數被同一個事件消息觸發,那麼僅在dragged回調函數返回None的情況dropped回調函數才會被調用。
除了 d ,所有的參數都在Drag對象的欄位(field)中。除此之外,在Drag對象被渲染後,下列域裡的值也變成可用狀態:
bottom
(self) link降低該可視組件的高度,降到其所在drag_group的底層。
set_child
(d) link將該Drag對象的子組件設為d。
snap
(x, y, delay=0) link修改Drag對象的坐標。如果Drag對象沒有顯示,坐標的改變瞬時完成。否則,坐標的改變會耗時 dalay 秒,生成線性移動的動畫。
top
(self) link升高該可視組件的高度,升到其所在drag_group的頂層。
DragGroup
(*children, **properties) link表示一個Drag對象組。某個Drag對象受限於整個DragGroup。掉落只在同一個組內的Drag對象間發生。組內的Drag對象可以會被抬升高度。
DragGroup的布局類似 Fixed()
。
DragGroup構造函數的所有固定位置參數都是需要添加到DragGroup的Drag對象。
add
(child) link添加Drag對象作為DragGroup的子組件(child)。
get_child_by_name
(name) link返回該DragGroup中名為 name 的第一個子組件。
remove
(child) link移除該DragGroup中的子組件child。
這個樣例中,在say界面允許用戶拖拽窗口並選擇放在界面的任意位置。
screen say:
drag:
drag_name "say"
yalign 1.0
drag_handle (0, 0, 1.0, 30)
xalign 0.5
window id "window":
# 確保窗口尺寸小於整個界面。
xmaximum 600
has vbox
if who:
text who id "who"
text what id "what"
這是一個稍微複雜的樣例,展示了如何拖拽功能如何用在遊戲流程中,還有如何使用拖拽功能將一個角色移動到某個位置:
init python:
def detective_dragged(drags, drop):
if not drop:
return
store.detective = drags[0].drag_name
store.city = drop.drag_name
return True
screen send_detective_screen:
# 作為背景的地圖。
add "europe.jpg"
# DragGroup確保每個偵探可以拖拽到每個城市。
draggroup:
# 偵探們
drag:
drag_name "Ivy"
child "ivy.png"
droppable False
dragged detective_dragged
xpos 100 ypos 100
drag:
drag_name "Zack"
child "zack.png"
droppable False
dragged detective_dragged
xpos 150 ypos 100
# 可選的城市。
drag:
drag_name "London"
child "london.png"
draggable False
xpos 450 ypos 140
drag:
drag_name "Paris"
draggable False
child "paris.png"
xpos 500 ypos 280
label send_detective:
"我們需要調查!應該派誰去哪裡?"
call screen send_detective_screen
"好的,我們派 [detective] 去 [city]。"
更複雜的系統需要使用更重要的程式技巧才能搞定。 Ren’Py cardgame framework 是一個在複雜系統如何使用拖放功能和製作卡牌遊戲兩方面都很有用的例子。
使用 as
分句可以將一個拖拽組件綁定到變數,這樣就可以直接調用組件的各類方法。
screen snap():
drag:
as carmen
draggable True
xpos 100 ypos 100
frame:
style "empty"
background "carmen.png"
xysize (100, 100)
vbox:
textbutton "London" action Function(carmen.snap, 450, 140, 1.0)
textbutton "Paris" action Function(carmen.snap, 500, 280, 1.0)