精靈(sprite) link
為了滿足同時顯示大量圖像的需求,Ren’Py支持精靈(sprite)系統。這個系統允許用戶創建精靈,每個精靈包含一個可視組件。精靈可以擁有自身的界面坐標和垂直順序改變。
如果不在乎系統性能的話,精靈系統的概念類似於 Fixed()
與 Transform()
的結合。 精靈的運行速度比變換(transform)快,但是擴展性比較低。精靈系統最大的性能提升方法是,每一幀中每個可視組件只渲染一次。精靈的限制是只能修改自身的xoffset和yoffset值,而不像變換(transform)有許多特性(property)可以修改。
使用那個精靈系統之前,需要先創建一個SpriteManager對象,然後調用它的create方法創建新的粒子(particle)。根據需要,更新每個精靈的xoffset、yoffset和zorder域,就能讓精靈在界面內移動。透過把 update 和 event 入參應用於SpriteManager,創作者能根據時間調整精靈,並對用戶輸入做出響應。
Sprite類 link
- class Sprite link
這表示一個被SpriteManager類管理下的精靈(sprite)。其包含的欄位(field)控制精靈在界面的位置。精靈不能直接創建,而是調用
SpriteManager.create()
。Sprite對象的欄位(field)如下:
- x, y
精靈左上角為原點的x和y軸坐標值,與SpriteManager相關。
- zorder
一個整數值,控制SpriteManager中所有精靈疊放順序。這個數值越大,對應精靈距離觀看者(viewer)越近。
- events
若為True,事件消息會傳給子組件。若為False,也是預設值,子組件忽略所有事件消息(並屏蔽事件消息以免浪費時間處理)。
Sprite對象含有如下的方法:
- destroy(self) link
銷毀該精靈,防止其再次顯示,並從SpriteManager中移除。
- set_child(d) link
將可視組件與精靈 d 關聯。
- class SpriteManager(update=None, event=None, predict=None, ignore_time=False, **properties) link
這是個管理一組精靈的可視組件,並盡可能快地把所有精靈顯示出來。
- update
若非None,每次SpriteManager渲染某個精靈都會調用的函數。調用時帶一個入參,值是從SpriteManager第一次顯示後的時間長度,單位為秒。返回值一般是該函數再次被調用以及SpriteManager再次被渲染的時間間隔,單位為秒。
- event
若非None,當某個事件發生時會調用的函數。其使用以下事件消息作為入參:
某個pygame事件對象。
事件的x坐標調整。
事件的y坐標調整。
從SpriteManager第一次顯示開始計算的時間。
如果該函數返回了一個非空值,互動結束時將這個值返回。
- predict
若非None,該函數返回一個可視組件列表。These displayables are predicted when the sprite manager is.
- ignore_time
若為True,渲染可視組件時忽略的時間。當SpriteManager使用了一些數量不大的圖像,並且這些圖像不會變化時,才應該使用這項值。使用這項值的可視組件數量不能多,因為使用後的可視組件在SpriteManager對象的整個生命週期內,會一直保留在記憶體中。
在首次渲染後(在 update 函數調用前),SpriteManager如有下列欄位(field):
- width, height
SpriteManager的寬度和高度,單位為像素。
SpriteManager包含下列方法:
- create(d) link
為可視組件 d 創建一個新的精靈(Sprite),並添加到該SpriteManager中。
- redraw(delay=0) link
在 delay 秒後重繪該SpriteManager。
- SnowBlossom(d, count=10, border=50, xspeed=(20, 50), yspeed=(100, 200), start=0, fast=False, horizontal=False) link
雪花(snowblossom)效果可以讓某個精靈(sprite)的多個實例在界面中上下左右移動。當某個精靈離開界面時,其會返回起始點。
- d
用作精靈的可視組件。
- border
界面邊界(border)的尺寸。精靈會被看作處於界面內,除非它越出了邊界。需要確保精靈不會突然消失。
- xspeed, yspeed
精靈移動速度,分別對應水平和垂直方向。這可以是一個數值或者兩個數值的元組。在後面那種情況,每個粒子(particle)的速度可以聲明為兩個值之間的隨機數。速度可以是整數或負數,只要保證後面的數值比前面的大。
- start
每添加一個粒子(particle),延遲的時間,單位為秒。這項值允許粒子從界面頂部出發,跟“wave”效果不同。
- fast
若為True,粒子從界面中心出發,而不是界面四邊。
- horizontal
若為True,粒子在界面的左右兩邊出現,而不是上下兩邊。
Sprite樣例 link
SnowBlosson類是在界面內放置掉落物體的易用辦法。
image snow = SnowBlossom("snow.png", count=100)
這個樣例展示了如何使用一個SpriteManager創建複雜行為。在這個例子中,總共顯示了400個粒子,並讓粒子避開滑鼠。
init python:
import math
def repulsor_update(st):
# 如果我們不知道滑鼠在哪裡,先放棄獲取滑鼠資訊
if repulsor_pos is None:
return .01
px, py = repulsor_pos
# 使用for循環檢測每一個精靈……
for i in repulsor_sprites:
# 計算從精靈到滑鼠的向量
vx = i.x - px
vy = i.y - py
# 計算向量長度,將向量歸一化。
vl = math.hypot(vx, vy)
if vl >= 150:
continue
# 計算需要移動的距離
distance = 3.0 * (150 - vl) / 150
# 移動
i.x += distance * vx / vl
i.y += distance * vy / vl
# 確保停留在界面上。
if i.x < 2:
i.x = 2
if i.x > repulsor.width - 2:
i.x = repulsor.width - 2
if i.y < 2:
i.y = 2
if i.y > repulsor.height - 2:
i.y = repulsor.height - 2
return .01
# 收到事件消息時,記錄滑鼠的坐標。
def repulsor_event(ev, x, y, st):
store.repulsor_pos = (x, y)
label repulsor_demo:
python:
# 創建一個SpriteManager。
repulsor = SpriteManager(update=repulsor_update, event=repulsor_event)
repulsor_sprites = [ ]
repulsor_pos = None
# 確保只有一個可視組件smile。
smile = Image("smile.png")
# 添加400個精靈。
for i in range(400):
repulsor_sprites.append(repulsor.create(smile))
# 放置這400個精靈。
for i in repulsor_sprites:
i.x = renpy.random.randint(2, 798)
i.y = renpy.random.randint(2, 598)
del smile
del i
# 把repulsor添加到界面。
show expression repulsor as repulsor
"..."
hide repulsor
# 清理。
python:
del repulsor
del repulsor_sprites
del repulsor_pos