Ren'Py は様々な技術でスクリーン言語の速度を最適化しています。 Ren'Py でシミュレーションゲームのような複雑なインターフェースを作成するなら、スクリーン言語の動作の理解は最大のパフォーマンスを得る役に立つでしょう。
このガイドは Ren'Py 6.18 から追加されたスクリーン言語の第二実装に当てはまります。 Ren'Py 6.17 以前で作成されたゲームでは、ランチャーから "Force Recompile" を選んでスクリーンを最新バージョンに更新する必要があります。
このガイドはプログラミングの練習には向きません。スクリーンがネストされたループを使用して非生産敵な作業をしているなら、スクリーンがそのような作業をしている場合と比べて遅くなるでしょう。このガイドのテクニックを理解することは重要ですが、 Ren'Py にあなたの仕事を最適化させるよりもそのような動作の回避の方が常に適切です。
最適な処理のために、すべてのスクリーンにはパラメーターリストが定義されるべきです。スクリーンがパラメーターを受け取らないなら空のパラメーターリストで定義すべきです。
screen test():
vbox:
for i in range(10):
text "[i]"
上のスクリーンは下のスクリーンより高速です。
screen test:
vbox:
for i in range(10):
text "[i]"
スクリーンがパラメーターリストなしで定義されると、そのスクリーン内で使用されたどの名前もスクリーン表示時に再定義される可能性があります。このためそのスクリーンを Ren'Py が分析するときにより保守的であることが要求され、そのパフォーマンス最適化が制限されるかもしれません。
スクリーンは前もって予測されるとパフォーマンスが向上します。これはスクリーン予測中にそのスクリーンを実行し、そのスクリーンで使用された画像をロードするためです。
スクリーンを自動的に予測する 2 つの方法が Ren'Py にはあります。 :
show screen
と call screen
ステートメントで表示されるスクリーンを Ren'Py は予測します。
Show()
と ShowMenu()
アクションで表示されるスクリーンを Ren'Py は予測します。
スクリーンが Pythonから表示されるなら、それが表示される前にそのスクリーンを予測するとよいです。スクリーンの予測を開始するには renpy.start_predict_screen()
関数を使用します。予測を停止するには renpy.stop_predict_screen()
関数を使用します。
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) を適切に使用し、すべてのフィールドを比較しているか確認してください。
Ren'Py は const 変数と pure 関数を活用して、スクリーンの評価を高速化し、スクリーンの一部の評価を完全に省略出来ます。
式が 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 だと保証することには 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 であることに注意してください。
$ 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]"'
renpy.
const
(name) linkstore の変数を const と宣言します。
変数はその値や、それを索引するかまたはそのアトリビュートにアクセスして得られる値が変更不可能ならば constant です。変数は define, init, translate python ブロック以外では変更してはいけません。
const と宣言する変数の名前の文字列です。
renpy.
not_const
(name) linkstore の変数を非 const と宣言します。
renpy.const()
と renpy.pure()
呼び出しの影響を戻します。
非 const と宣言する変数の名前です。
renpy.
pure
(fn) linkpure として宣言する関数です。define, init, translate python ブロックを除いて、 pure 関数は同じ引数で呼び出されたときは常に同じ値を返すべきです。
pure として宣言する関数の名前です。これは関数名の文字列か、関数自身です。文字列を渡しかつその関数がモジュール内にあれば、この文字列はモジュール名をドット区切りで含むべきです。
fn を返し、この関数はデコレーターとして使用出来ます。
Ren'Py は renpy.profile_screen
関数を使用してスクリーンプロファイリングの実行をサポートしています。
renpy.
profile_screen
(name, predict=False, show=False, update=False, request=False, time=False, debug=False, const=False) linkname を名前とするスクリーンに対してスクリーンプロファイリングをリクエストします。
name 以外のすべての引数はキーワード引数として与えられます。この関数は 3 グループの引数を受け取ります。
引数の最初のグループは何時プロファイリングするかを決定します。
True なら、スクリーンが予測されるとプロファイリングを実行します。
True なら、スクリーンが最初に表示されるとプロファイリングを実行します。
True なら、スクリーンが更新されるとプロファイリングを実行します。
True なら、 F8 でリクエストされるとプロファイリングを実行します。
引数の第二グループは何をプロファイリングで出力するかを制御します。
True なら、スクリーンを制御するのにかかった時間を記録します。
True なら、以下のどの項目についてどのようにスクリーンが評価されたかを記録します。 :
どの displayable を Ren'Py は constant と評価したか。
あるならばどの引数が評価を必要としたか。
どの displayable が再利用されたか。
このデバッグ情報の生成と保存には時間がかかるため、debug が設定されているなら time の情報はあてになりません。
引数の最後のグループは Ren'Py の実行ごとになにを出力するか制御します。
const と non-const とマークされたそのスクリーンの変数を表示します。
すべてのプロファイリング結果はゲームディレクトリーの profile_screen.txt に保存されます。
以下の名前はデフォルトで pure かつ const です。
AddToSet()
AlphaBlend()
AlphaDissolve()
AlphaMask()
AnimatedValue()
At()
AudioPositionValue()
Call()
CaptureFocus()
Character()
ClearFocus()
Color
ComposeTransition()
ConditionSwitch()
Confirm()
CropMove()
DictInputValue()
DictValue()
DisableAllInputValues()
Dissolve()
Drag
DynamicDisplayable()
EndReplay()
Fade()
FieldInputValue()
FieldValue()
FileDelete()
FilePage()
FilePageNameInputValue()
FileTakeScreenshot()
Fixed()
Flatten()
FontGroup()
Frame()
Function()
Grid()
HBox()
Help()
Hide()
HideInterface()
If()
Image()
ImageDissolve()
InputValue
InvertSelected()
Jump()
Language()
MainMenu()
MixerValue()
MouseMove()
MoveTransition()
Movie()
MultipleTransition()
Notify()
Null()
NullAction()
OpenDirectory()
OpenURL()
ParameterizedText()
Pause()
PauseAudio()
Pixellate()
PlayCharacterVoice()
Preference()
PushMove()
Queue()
QueueEvent()
QuickLoad()
QuickSave()
Quit()
RemoveFromSet()
Replay()
RestartStatement()
RollForward()
Rollback()
ScreenVariableValue()
Screenshot()
Scroll()
SelectedIf()
SensitiveIf()
SetCharacterVolume()
SetDict()
SetField()
SetMixer()
SetMute()
SetScreenVariable()
SetVariable()
SetVoiceMute()
Show()
ShowMenu()
ShowTransient()
ShowingSwitch()
Skip()
SnowBlossom()
Solid()
Start()
StaticValue()
StylePreference()
Swing()
Text()
ToggleDict()
ToggleField()
ToggleMute()
ToggleScreen()
ToggleScreenVariable()
ToggleSetMembership()
ToggleVariable()
ToggleVoiceMute()
Transform
VBox()
VariableInputValue()
VariableValue()
VoiceReplay()
_()
_p()
blinds
dissolve
fade
実数値
gui.SetPreference()
gui.TogglePreference()
gui.preference()
hpunch
irisin
pixellate
pushright
renpy.check_text_tags()
renpy.exists()
renpy.filter_text_tags()
renpy.fsdecode()
renpy.fsencode()
renpy.get_all_labels()
renpy.has_label()
renpy.known_languages()
renpy.license
renpy.list_files()
renpy.loadable()
renpy.variant()
renpy.version()
renpy.version_name
renpy.version_only
renpy.version_string
renpy.version_tuple
slideawayleft
slideleft
squares
updater.Update()
vpunch
wipeleft
zoomin
zoominout
zoomout