スクリーン言語の最適化 link
Ren'Py は様々な技術でスクリーン言語の速度を最適化しています。 Ren'Py でシミュレーションゲームのような複雑なインターフェースを作成するなら、スクリーン言語の動作の理解は最大のパフォーマンスを得る役に立つでしょう。
このガイドは Ren'Py 6.18 から追加されたスクリーン言語の第二実装に当てはまります。 Ren'Py 6.17 以前で作成されたゲームでは、ランチャーから "Force Recompile" を選んでスクリーンを最新バージョンに更新する必要があります。
このガイドはプログラミングの練習には向きません。スクリーンがネストされたループを使用して非生産敵な作業をしているなら、スクリーンがそのような作業をしている場合と比べて遅くなるでしょう。このガイドのテクニックを理解することは重要ですが、 Ren'Py にあなたの仕事を最適化させるよりもそのような動作の回避の方が常に適切です。
引数リスト link
最適な処理のために、すべてのスクリーンにはパラメーターリストが定義されるべきです。スクリーンがパラメーターを受け取らないなら空のパラメーターリストで定義すべきです。
screen test():
vbox:
for i in range(10):
text "[i]"
上のスクリーンは下のスクリーンより高速です。
screen test:
vbox:
for i in range(10):
text "[i]"
スクリーンがパラメーターリストなしで定義されると、そのスクリーン内で使用されたどの名前もスクリーン表示時に再定義される可能性があります。このためそのスクリーンを Ren'Py が分析するときにより保守的であることが要求され、そのパフォーマンス最適化が制限されるかもしれません。
予測 link
スクリーンは前もって予測されるとパフォーマンスが向上します。これはスクリーン予測中にそのスクリーンを実行し、そのスクリーンで使用された画像をロードするためです。
スクリーンを自動的に予測する 2 つの方法が Ren'Py にはあります。 :
show screen
とcall screen
ステートメントで表示されるスクリーンを Ren'Py は予測します。Show()
とShowMenu()
アクションで表示されるスクリーンを Ren'Py は予測します。
スクリーンが Pythonから表示されるなら、それが表示される前にそのスクリーンを予測するとよいです。スクリーンの予測を開始するには renpy.start_predict_screen()
関数を使用します。予測を停止するには renpy.stop_predict_screen()
関数を使用します。
Displayable の再利用 link
displayable を作成するスクリーン言語のステートメントを評価するとき、 Ren'Py はその displayable に指定された位置引数とプロパティーが、最後にそのステートメントが評価されたときに指定された位置引数とプロパティーと等しいか確認します。もしそうなら新しい displayable を作成する代わりに既存の displayable を Ren'Py は使用します。
displayable の再利用はパフォーマンスと多いに関連します。新しい displayable 作成のコスト節約は、多くの内部状態を持つ displayable に対して特に効果的です。さらに重要なことは displayable を再利用する場合、たいていはユーザーに表示前に displayable を再レンダリングする必要がなくなり、さらなる速度向上に繋がります。
位置引数とプロパティーを比較するため、 Ren'Py は python の == 演算子による等式の概念を使用します。 2 つのアクションが互いに見分けられないとき、どちらのアクションが使用されるか、選択または無効状態かが問題ではないときは等しいと判断して、この等式の概念をアクションにまで拡張しました。
Ren'Py から提供されるすべてのアクションはこの定義に従います。自身でアクションを定義するときは、この等式の概念を用意するとよいです。これは適切な __eq__
メソッドを提供して実現出来ます。例えば
class TargetShip(Action):
def __init__(self, ship):
self.ship = ship
def __eq__(self, other):
if not isinstance(other, TargetShip):
return False
return self.ship is other.ship
def __call__(self):
global target
target = self.ship
__eq__
関数は注意深く定義して、 (==) と (is) を適切に使用し、すべてのフィールドを比較しているか確認してください。
const 式と pure 関数 link
Ren'Py は const 変数と pure 関数を活用して、スクリーンの評価を高速化し、スクリーンの一部の評価を完全に省略出来ます。
定義 link
式が const であるとはいつ評価されても常に同じ値を表わすということです。 Ren'Py においては、以下の式の評価が常に同じ一定の値になるなら式は const であり、そうでなければ未定義であるということになります。 :
単項、二項、三項演算子のその式への適用。提供される他の演算対象も const である。
その式でアクセスするフィールド
数字かオブジェクトを使用したその式の索引
Python の数字と文字列は const で、すべての要素が const である list と tuple, set, dict も同様に const です。 Ren'Py は define
ステートメントを使用して const として定義される変数をマークします。 renpy.const()
や renpy.not_const()
関数を使用すれば Ren'Py が何を const として制御するかをさらに制御出来ます。デフォルトの const 名のリストが後述の Const 名 にあります。
決して変更されない変数があるなら、 define
を使用してそれを定義するとよいです。例
define GRID_WIDTH = 20
define GRID_HEIGHT = 10
呼び出し可能な 関数やクラス、アクションは、そのすべての引数が const 値であるとき、常に同じ値を返すなら pure です。 const 式を引数に pure 関数を使用する式も const 式です。
多くのデフォルトの関数やクラス、アクションが pure としてマークされています。これらの関数は後述する Pure 名 でリストされています。
renpy.pure()
関数を使用して、関数は pure と宣言され、それらはデフォルトの store で宣言された関数のデコレータとして使用出来ます。
const 式と pure 関数は以下のイベントでは同じ値を維持する必要はありません。 :
初期化の終了
言語の変更
スタイルの再ビルド
const のスクリーン言語最適化効果 link
スクリーン言語の引数とプロパティーが const だと保証することには 3 つの利点があります。
まず、初期化終了時やスクリーンが準備されるとき、言語変更時、スタイルの再ビルド時に const 引数とプロパティーは評価されます。その後はもう const 引数やプロパティーを評価するために時間を消費する必要はありません。
第 2 に displayable の再利用に const は最適です。その displayable のすべての引数とプロパティーが const であると、その displayable は常に再利用され、 displayable 再利用の利益が得られます。
最後に、すべての引数とプロパティーが const であり、制御に影響を与える式も const であるような displayable のツリーを Ren'Py が発見すると、 Ren'Py は displayable の評価も作成もせずにツリーをまるごと再利用します。これは明らかなパフォーマンス向上に寄与します。
例えば、以下のスクリーンは最初に予測や表示をされてからは、どんなコードの評価も displayable の作成もしません。
screen mood_picker():
hbox:
xalign 1.0
yalign 0.0
textbutton "Happy" action SetVariable("mood", "happy")
textbutton "Sad" action SetVariable("mood", "sad")
textbutton "Angry" action SetVariable("mood", "angry")
const テキスト link
テキストを定義するときは、新スタイルの置換を使用している文字列は const であることに注意してください。
$ t = "Hello, world."
text "[t]"
テキストの変数を直接与えると一般的には非 const になります。
$ t = "Hello, world."
text t
% による置換でも同様です。
$ t = "Hello, world."
text "%s" % t
最後に、 _ テキスト関数は pure であるため、文字列を含むと式全体が const になります。
text _("Your score is: [score]")
変数に置換を含むテキストがあれば、 !i
変換フラグを使用する必要があります。
$ who = "Jane"
$ t = "Hello, [who]!"
text 'Then I told her, "[t!i]"'
Const 関数 link
- renpy.const(name) link
store の変数を const と宣言します。
変数はその値や、それを索引するかまたはそのアトリビュートにアクセスして得られる値が変更不可能ならば constant です。変数は define, init, translate python ブロック以外では変更してはいけません。
- name
const と宣言する変数の名前の文字列です。
- renpy.not_const(name) link
store の変数を非 const と宣言します。
renpy.const()
とrenpy.pure()
呼び出しの影響を戻します。- name
非 const と宣言する変数の名前です。
- renpy.pure(fn) link
pure として宣言する関数です。define, init, translate python ブロックを除いて、 pure 関数は同じ引数で呼び出されたときは常に同じ値を返すべきです。
- fn
pure として宣言する関数の名前です。これは関数名の文字列か、関数自身です。文字列を渡しかつその関数がモジュール内にあれば、この文字列はモジュール名をドット区切りで含むべきです。
fn を返し、この関数はデコレーターとして使用出来ます。
プロファイリング link
Ren'Py は renpy.profile_screen
関数を使用してスクリーンプロファイリングの実行をサポートしています。
- class renpy.profile_screen(name, predict=False, show=False, update=False, request=False, time=False, debug=False, const=False) link
name を名前とするスクリーンに対してスクリーンプロファイリングをリクエストします。
name 以外のすべての引数はキーワード引数として与えられます。この関数は 3 グループの引数を受け取ります。
引数の最初のグループは何時プロファイリングするかを決定します。
- predict
True なら、スクリーンが予測されるとプロファイリングを実行します。
- show
True なら、スクリーンが最初に表示されるとプロファイリングを実行します。
- update
True なら、スクリーンが更新されるとプロファイリングを実行します。
- request
True なら、 F8 でリクエストされるとプロファイリングを実行します。
引数の第二グループは何をプロファイリングで出力するかを制御します。
- time
True なら、スクリーンを制御するのにかかった時間を記録します。
- debug
True なら、以下のどの項目についてどのようにスクリーンが評価されたかを記録します。 :
どの displayable を Ren'Py は constant と評価したか。
あるならばどの引数が評価を必要としたか。
どの displayable が再利用されたか。
このデバッグ情報の生成と保存には時間がかかるため、debug が設定されているなら time の情報はあてになりません。
引数の最後のグループは Ren'Py の実行ごとになにを出力するか制御します。
- const
const と non-const とマークされたそのスクリーンの変数を表示します。
すべてのプロファイリング結果はゲームディレクトリーの profile_screen.txt に保存されます。
const 名 link
以下の名前はデフォルトで const です。
False
None
True
config
pure 名 link
以下の名前はデフォルトで pure かつ const です。
ADVCharacter
ADVSpeaker
Alpha
Animation
DynamicCharacter
FactorZoom
ImageReference
LiveComposite
LiveCrop
LiveTile
Motion
Move
MoveFactory
MoveIn
MoveOut
NVLCharacter
OldMoveTransition
Pan
Particles
Play
Position
Revolve
RevolveInOut
RotoZoom
SizeZoom
Speaker
Stop
SubTransition
Viewport
Window
Zoom
ZoomInOut
_CharacterVolumeValue
_DisplayReset
_InputValueAction
_TouchKeyboardBackspace
_TouchKeyboardReturn
_TouchKeyboardTextInput
__renpy__dict__
__renpy__list__
__renpy__set__
_m1_00gallery__GalleryAction
_m1_00gallery__GalleryToggleSlideshow
_m1_00musicroom__MusicRoomPlay
_m1_00musicroom__MusicRoomRandomPlay
_m1_00musicroom__MusicRoomStop
_m1_00musicroom__MusicRoomTogglePause
_m1_00musicroom__MusicRoomTogglePlay
_m1_00preferences__DisplayAction
_m1_00preferences__ResetPreferences
_movebottom
_moveleft
_moveright
_movetop
_notify_transform
_touch_keyboard
abs
all
any
ascii
bin
bool
bytes
callable
chr
color
complex
dict
dir
dissolve
divmod
enumerate
filter
float
format
frozenset
getattr
hasattr
hash
hex
int
irisout
isinstance
issubclass
len
list
map
max
min
oct
ord
pow
pushdown
pushleft
pushup
range
renpy.Keymap
renpy.ParameterizedText
renpy.curried_call_in_new_context
renpy.curried_invoke_in_new_context
renpy.curry
renpy.easy_displayable
renpy.has_screen
renpy.image_exists
renpy.munged_filename
renpy.partial
renpy.unelide_filename
repr
reversed
round
set
slice
slideawaydown
slideawayright
slideawayup
slidedown
slideright
slideup
sorted
str
sum
tuple
type
ui.callsinnewcontext
ui.gamemenus
ui.invokesinnewcontext
ui.jumps
ui.jumpsoutofcontext
ui.returns
wipedown
wiperight
wipeup
zip