スプライトの組み合わせがある程度複雑になると、すべての可能な組み合わせの定義は難しくなります。例えば4つの服装と4つの髪型、6つの表情のスプライトの組み合わせはすでに 96 組あります。すべての可能な組み合わせの静止画像作成は多くのディスクスペースとプログラマーの時間を消費します。
このような状況に対処するため、Ren'Py には複数レイヤーで構成される画像を定義する方法があります(ここで言うレイヤーは Photoshop やGIMP のようなペイントソフトでのレイヤーであり、Ren'Py の他の場所で語られているようなレイヤーではありません)。レイヤーは無条件で表示される他、画像に提供された属性や実行時に評価される条件によって選択されたりもできます。
レイヤー画像の定義をより簡単に定義するため、 Ren'Py には layerdimage
ステートメントがあります。これはレイヤー画像の定義に使用される固有の言語を導入します。画像ではありませんが、 image ステートメントに代入して画像のように使用出来る LayerdImage()
オブジェクトもあります。
レイヤー画像用の言語はほんの少数のステートメントで構成され、その1つは画像を導入するステートメントで、続いてレイヤーやレイヤーのグループを導入するためのステートメントが続きます。
この言語の紹介のため、ここで利用可能な機能を使用したレイヤー画像を示します。
layeredimage augustina:
always:
"augustina_base"
group outfit:
attribute dress:
"augustina_outfit_dress"
attribute jeans:
"augustina_outfit_jeans"
group eyes:
attribute open default:
"augustina_eyes_open"
default True
attribute wink:
"augustina_eyes_wink"
group eyebrows:
attribute normal default:
"augustina_eyebrows_normal"
attribute oneup:
"augustina_eyebrows_oneup"
group mouth:
pos (100, 100)
attribute smile default:
"augustina_mouth_smile"
attribute happy:
"augustina_mouth_happy"
if evil:
"augustina_glasses_evil"
else:
"augustina_glasses"
長いスクリプトですが、かなり定型的なものです。以下でどのように簡略化しているかを述べます。
最初に layerdimage
ステートメントでそのスプライトの名前とともにレイヤー画像を導入します。このステートメントは Ren'Py スクリプト言語の一部で初期化時に実行されます。
レイヤー画像のブロックには always と group, if ステートメントを含められます。 group
ステートメントは属性を受け取れます。 always
と if
ステートメントには displayable が提供されなければなりませんが、 attribute
ステートメントへの提供は任意です。すべてのステートメントにはプロパティーが提供出来ます。
always
ステートメントはスプライトの背景のような常に表示されるレイヤーを宣言します。
group
ステートメントは一度にその属性のうちの1つだけが表示される属性グループを導入します。これにより、このレイヤー画像は目、眉、口それぞれの位置で1つずつ、服で1つしか出力されません。グループへのプロパティーはその属性に渡され、グループでは自動的に属性を宣言できます。
attribute
ステートメントは画像にある属性が提供されると表示されるレイヤーを導入します。例では "dress" 属性が提供されるときのみ "augustina_outfit_dress" が表示されます。 default
キーワードが属性に与えられると、矛盾する属性が与えられなければ、その属性が表示されます。この例では "wink" 属性がなければ "augustina_eyes_open" が表示されます。
最後に、 if
ステートメントは Python ステートメントを使用して displayable を選択するレイヤーを追加します。これは毎回評価され、最初に True と評価される条件が表示されます。
プロパティーはプロパティー名と単純式で構成され、各レイヤーに提供されます。ステートメントの機能を変更するプロパティーもあります。ひとつ以上の transform プロパティー があたえられると、 Transform()
が作成されて displayable をラップします。 at プロパティーには displayable をラップする transform または transform リストも与えられます。例えば、ここで pos プロパティーは各口の画像の左上端を移動する transform を作成しています。
最終的な画像は全てのレイヤーの矩形領域の最大サイズとなるため、画像からはみ出すレイヤーがない十分な大きさのレイヤーが1つあるとよいでしょう。最初のレイヤーは画像の後ろに、最後のは前になります。この例では、眼鏡が他のレイヤーの上となります。画像サイズが不明なとき正常に動作しないので xcenter
や xalign
のような含む画像のサイズを仮定するプロパティーは避けましょう。
group と attribute は表示される属性をもつ全てのレイヤーとともに layeredimage に一回以上表れるでしょう。
if` ステートメントの condition を除いて Python 式は初期化時にすべて評価されます。
この例でのレイヤー画像を使用するには evil 変数に値を与えなければなりません。 例
default evil = True
これでレイヤー画像は他の画像のように表示出来ます。ほぼ確実に outfit のどれかは与えられるでしょうが、 Ren'Py はこれを強制しないので、この画像はどれかを必要とします。
show augustina jeans
スプライトが表示されている間、衝突しなければ追加の属性は既に表示されているスプライトに加えられます(これは表示されている画像が既に定義されている画像に一致しないときにRen'Pyのどこででも起こりますが、レイヤー画像では起こりません)。そのため、次のコードでは
show augustina wink
wink 属性と関連付けされたレイヤーをアクティベートします。開いた目はウィンクと衝突するので次のようにしてウィンクを止められます。
show augustina open
もしくは単に wink 属性を次のようにして除去できます。
show augustina -wink
これはデフォルトの open 属性で画像を表示します。
レイヤー画像は scene ステートメントでも使用できます。
最初の例では属性を定義する属性名と displayable で多くの繰り返しがあります。冗長なタイピングを避けるため、 Ren'Py では画像名、グループ名、属性名から自動的に displayable の名前を定義できます。これは名前とアンダースコアを組み合わせて行います。
これには属性のもう一つの機能、プロパティーを最初の行に追加してブロックを完全に省略できることを利用できます。
ここにこれを実行する例を示します。
layeredimage augustina:
always:
"augustina_base"
group outfit:
attribute dress
attribute jeans
group eyes:
attribute open default
attribute wink
group eyebrows:
attribute normal default
attribute oneup
group mouth:
pos (100, 100)
attribute smile default
attribute happy
if evil:
"augustina_glasses_evil"
else:
"augustina_glasses"
(displayable に最初の例と同じ名前を与えているため)この例は最初の例と同じことをしています。例えば、 outfit グループの dress 属性は displayable に "augustina_outfit_dress" を使用し、 displayable はその名前で画像を参照します。
自動的にグループの属性を定義して、さらに簡略化が可能です。これはグループに、パターンにマッチする定義した画像を検索させ、衝突しなければその属性を定義する auto キーワードを与えて実行されます。
attribute
のように、プロパティーをグループの最初の行に配置してブロックを省略できます。 always ステートメントの displayable と プロパティーも同様に最初の行に配置できます。
最後の形式の例です。
layeredimage augustina:
always "augustina_base"
group outfit auto
group eyes auto:
attribute open default
group eyebrows auto:
attribute normal default
group mouth auto:
pos (100, 100)
attribute smile default
if evil:
"augustina_glasses_evil"
else:
"augustina_glasses"
これは画像を定義するのと同じぐらい簡単です。グループ毎により多くの属性があれば、自動定義での節約はより増加します。デフォルト属性がいらなければ、更に行も節約できます。その場合、全てのグループが1つの行で記述されます。
always
や if
ステートメントでは、 displayable を省略できないため、(もう少し適切な名前の画像がありますが)これが一番簡略です。これによって数千数万のレイヤーの組み合わせさえ定義できます。
そのレイヤー画像が最初に定義される初期化時に if
ステートメントの条件式以外のすべての式が評価されることに注意してください。
layerdimage
ステートメントはレイヤー画像を導入する Ren'Py スクリプト言語のステートメントです。これは画像名で始まり、 attribute, group, if ステートメントなどを含むブロックを含みます。
layerdimage は次のプロパティーを受け取ります。 :
文字列で画像が与えられており、かつこのプロパティーが与えられていると、image_format にその画像名が補完され、画像ファイルになります。例えば、 "sprites/eileen/{image}.png" ならsptritesのサブディレクトリーからその画像を探します ( これは画像ファイルではなく画像を探す自動グループでは使用されません )。
layeredimage.format_function の代わりに使用して画像の情報を displayable 形式にする関数です。
与えられると、 displayable に適用される Transform()
を構築するのに使われます。
レイヤー画像へ適用される transform または transform のリストです。
これが True ならそのレイヤー画像はゲームの画面全体と一致する領域が与えられたかのようにその子を配置し、可変サイズの子のサイズを合わせます。 False なら、利用可能な領域を考慮しながらこれらの動作が行われ、例えば他の要素を含む hbox では小さくなり、レイヤー画像の表示は表示されるたびに一貫しなくなります。
None の場合、デフォルトの config.layeredimage_offer_screen
に戻ります。これはデフォルトでは True です。
attribute
ステートメントは特定の属性を使用して画像を表示するときに表示されるレイヤーを追加します。同じ属性が複数のレイヤーに使用出来、その属性に対応する全てのレイヤーが表示されます( if_all, if_any, if_not プロパティーでこれを変更出来ます)。
attribute は属性名を受け取り、さらに 2 つのキーワードも受け取れます。 default
キーワードはそのグループの属性と衝突しなければデフォルトで与えられる属性を示します。 null
キーワードは Ren'Py が自動的にこの属性に対応する displayable を検索しないようにするので、 if_all や if_any, if_not と組み合わせての使用をのみ意図した属性を持つのに便利です。
displayable が与えられなければ、そのレイヤーやグループ、グループバリエーション、属性の名前から、すべてのスペースをアンダースコアで置き換え、さらにアンダースコアで全てを結合して推測します。つまり画像名 "augustina" , グループ "eyes", 属性 "closed" があれば、 "augustina_eyes_closed" が使用されます( レイヤー画像のフォーマット関数がこれに使用され、デフォルトは layeredimage.format_function()
です)。
属性にグループがなければ、同じ名前のグループに配置されますが、そのグループは displayable 名の推測に使用されません(つまり "image_attribute_attribute" ではなく "image_attribute" を探します)。
attribute ステートメントは次のプロパティーを受け取ります :
属性名の文字列または文字列リストです。これがあれば、このレイヤーはそのすべての属性名が与えられなければ表示されません。
属性名の文字列または文字列リストです。これがあれば、このレイヤーはその属性名のどれかが与えられなければ表示されません。
属性名の文字列または文字列リストです。これがあれば、このレイヤーはその属性名がすべて与えられなければ表示されます。
与えられれば、レイヤーに適用される transform を構築するのに使用されます。
レイヤーに適用される transform または transform のリストです。
group
ステートメントはレイヤーをグループ化します。ある属性がグループ内にあり、そのグループが multiple
でないならば、そのグループの他の属性を含むのはエラーになります(同じグループ内であっても、いくつかの属性が同じ名前を持つことは良いです)。
group
ステートメントは名前を受け取ります。名前はあまり使用されませんが、グループ内の属性のデフォルト名を生成するのに使われます。しかし、 multiple
group ではその名前は使用されず影響もありません。
auto
キーワードが名前に続くかもしれません。与えられればそのグループのその後のどの属性も宣言され、 Ren'Py はその画像のリストをスキャンしてグループパターン(下記参照)にマッチするものを探します。見つかった画像で、宣言された属性に対応しないものは attribute ステートメントで宣言されたかのようにそのグループに追加されます。
multiple
キーワードも続けられます。与えられれば、グループのひとつ以上のメンバーが同時に選択できます。これは排他的ではない複数の属性を自動定義するグループや同じプロパティーを一度に属性のセットに適用するのに便利です。これは属性の1つに default
キーワードが与えられていると衝突します。
プロパティーはグループの最初の行で宣言でき、プロパティーや属性を含むブロックをとられます。
グループに指定される 2 つのプロパティーがあります。
指定されるならこれは文字列であり、自動生成の画像名の一部と auto
グループで属性を自動定義するときの画像の検索パターンの一部になります。
指定されるなら、手動または自動定義の属性名とアンダースコアで連結される接頭辞です。つまり prefix が"leftarm" で、属性名が "hip" なら、属性 "leftarm_hip" が代わりに定義されます。
group ステートメントは attribute
と同じプロパティーを受け取ります。グループに提供されたプロパティーは、属性自身の同じプロパティーを上書きしない限りそのグループ内の属性に渡されます。
同じレイヤー画像で定義されている同じ名前の group
ブロックは1つのグループの異なるパーツとして考慮されます。例
layeredimage eileen sitting:
attribute base default
group arms variant "behind":
attribute on_hips
attribute on_knees
attribute mixed
attribute table default
group arms variant "infront":
attribute on_table default
attribute holding_margarita
attribute mixed
例では、 eileen_sitting_arms_behind_mixed.png
にはテーブルの後ろの左手があり、 eileen_sitting_arms_infront_mixed.png
にはテーブルの上の右手があります。 show eileen sitting mixed
を呼び出すと、その二つの画像がそれぞれテーブルの後ろと前に同時に表示されます。
Pattern. 使用される画像パターンは次で構成されます。 :
スペースがアンダースコアで置換された画像の名前
そのグループが multiple
でなければグループ名
あればバリエーションの名前
属性の名前
すべてはアンダースコアで結合されます。例えば、レイヤー画像 "augustina work" とグループ "eyes" があれば、これは augustina_work_eyes_attribute にマッチします。 variant が bule なら、 augustina_work_eyes_blue_attribute にマッチします。
always
ステートメントは常に表示されるレイヤーを宣言します。 displayable が与えられなければならず、プロパティーも受け取れます。両方を同じ行にもブロック内にも配置できます。
always ステートメントは次のプロパティーを受け取ります。 :
属性名の文字列または文字列リストです。これがあれば、このレイヤーはそのすべての属性名が与えられなければ表示されません。
属性名の文字列または文字列リストです。これがあれば、このレイヤーはその属性名のどれかが与えられなければ表示されません。
属性名の文字列または文字列リストです。これがあれば、このレイヤーはその属性名がすべて与えられなければ表示されます。
与えられれば、レイヤーに適用される transform を構築するのに使用されます。
レイヤーに適用される transform または transform のリストです。
if
ステートメント (または if-elif-else ステートメント) には実行時に評価される 1 つ以上の条件を渡せられます。各条件はレイヤーに関連付けられ、最初に True となる条件のものが表示されます。 True となる条件がなく、 else
レイヤーがあれば、それが表示されます。
if
ステートメントのより完全な例は次のようになります。
if glasses == "evil":
"augustina_glasses_evil"
elif glasses == "normal":
"augustina_glasses"
else:
"augustina_nose_mark"
各レイヤーには displayable が与えられなければならず、次のプロパティーも与えられます。 :
属性名の文字列または文字列のリストです。これがあれば、この条件はそのすべての属性名が与えられなければ考慮されません。
属性名の文字列または文字列のリストです。これがあれば、この条件はその属性名のどれかが与えられなければ考慮されません。
属性名の文字列または文字列のリストです。これがあれば、この条件はその属性名がすべて与えられなければ考慮されます。
与えられれば、レイヤーに適用される transform を構築するのに使用されます。
レイヤーに適用される transform または transform のリストです。
if
ステートメントは layerdimage
ステートメント実行時に ConditionSwitch()
に変換されます。
predict_all
が True でなければ、レイヤー画像が表示されている、またはまさに表示されるときは if
ステートメントの条件の変更は避け、予測不能な画像の読み込みを避けるべきです。これはめったに変更されない character のカスタマイズオプションでの使用を意図しています。
全て、または少なくとも興味がある全てが異なる複数のポーズのスプライトがあるキャラクターを持てます。例えばキャラクターに立ちポーズと座りポーズがあれば、全ての画像のパーツは異なる場所にあるでしょう。
その場合、同じ画像タグの複数のレイヤー画像の定義が役立ちます。 layerdimage
ステートメントでは画像名の一部として属性を含められるので、これが可能になります。
layeredimage augustina sitting:
...
layeredimage augustina standing:
...
これは特にレイヤー画像を使用してサイドイメージを構成するのに便利です。別々のキャラクターのサイドイメージは互いに影響しません。
layeredimage side eileen:
...
layeredimage side lucy:
...
画像名でのアンダースコアの使用 デフォルトでは、 Ren'Py のレイヤー画像はアンダースコアで画像名をパーツに分割します。パーツ間にスペースがある画像の使用は魅力的かもしれませんが、後述の問題に発展しかねません。
Ren'Py には既に表示されているものと正確に同じ名前の画像を表示するときは置き換えて表示するルールがあります。これにより定義したレイヤー画像ではなく、直接レイヤーを表示できます。しかし、これはなにもない空間に目が浮かぶような妙な問題に繋がる可能性があります。
各レイヤーがメインの画像と異なるタグを持てばこれは問題ではなくなります。
レイヤーの切り取りは不要です Ren'Py は画像を RAM に読み込む前に、不透明なピクセルの矩形領域に切り取って画像を最適化します。つまり画像が適切に予測されれば、自分で画像を切り取ってもパフォーマンスや画像サイズは一般的にあまり改善しません。
レイヤー画像では起動時に変化するデータを使用してはいけません if ステートメントの condition を除いて、レイヤー画像のすべての式は初期化時に実行され、ゲーム開始後に起きた変数の変化を反映しません(ただし ATL transform の式は他の ATL transform と同様に画像の表示ごとに実行されます)。
もちろん layerdimage
ステートメントには相当する Python がありますが、 group ステートメントは attribute
に与えられるためありません。自動機能は renpy.list_image()
を使用して実装できます。
Attribute
(group, attribute, image=None, default=False, group_args={}, **kwargs) linkこれを使用して属性に制御される LayerdImage のレイヤーを表します。1つの属性で複数のレイヤーを制御でき、この場合、その属性に対応する全てのレイヤーが表示されます。
属性が加わるグループの文字列です。 None である場合、属性と同じ名前のグループが作成されます。
属性の名前の文字列です。
これは None または、この属性が表示される displayable です。
True かつそのグループの他の属性が選択されていなければ、この属性となります。
次のキーワード引数もあります。 :
画像に適用される transform または transform のリストです。
属性または属性のリストです。 displayable はこれらの全てがあるときだけ表示されます。
属性または属性のリストです。 displayable はこれらのどれかがあるときだけ表示されます。
属性または属性のリストです。 displayable はこれらの全てがないときだけ表示されます。
他のキーワード引数は transform プロパティーとして解釈されます。与えられると、画像をラップする transform が作成されます(例えば、 pos=(100, 200) を使用して、画像を 100 ピクセル横に、 200 ピクセル縦にオフセットできます)。
image パラメーターが省略されるか None であり、LayerdImage に image_format パラメーターが与えられると、 image_format を使用して画像ファイル名を生成します。
Condition
(condition, image, **kwargs) linkこれにより条件で制御される LayerdImage のレイヤーを表します。条件が True ならレイヤーが表示され、そうでなければ表示されません。
レイヤーが表示されるかどうかを決定する Python の条件の文字列です。
これは None または条件が True なら表示される displayable です。
属性または属性のリストです。これらのすべてがあるときのみ条件は評価されます。
属性または属性のリストです。これらのどれかがあるときのみ条件は評価されます。
属性または属性のリストです。これらのすべてがないときのみ条件は評価されます。
画像に適用される transform または transform のリストです。
他のキーワード引数は transform プロパティーとして解釈されます。与えられると、画像をラップする transform が作成されます(例えば、 pos=(100, 200) を使用して、画像を 100 ピクセル横に、 200 ピクセル縦にオフセットできます)。
LayeredImage
(attributes, at=[], name=None, image_format=None, format_function=None, attribute_function=None, offer_screen=None, **kwargs) linkこれは画像のようなオブジェクトで、適切な属性の組み合わせで表示されると、それらの属性と関連付けられた displayable を合成して作成した displayable を表示します。
これは Attribute オブジェクトのリストです。各 Attribute オブジェクトはその画像の一部として表示され、またはされない displayable を反映します。このリストの要素は後ろから前の順となり、プレイヤーから見て最初の要素は遠くに、最後のものは近くになります。
合成後に displayable に適用される transform または transform のリストです。
レイヤー画像の名前で、画像要素の名前の一部として使用されます。
文字列で画像が与えられており、かつこのプロパティーが与えられていると、image_format にその画像名が補完され、画像ファイルになります。例えば、 "sprites/eileen/{image}.png" ならsptritesのサブディレクトリーからその画像を探します ( これは画像ファイルではなく画像を探す自動グループでは使用されません )。
layeredimage.format_function の代わりに使用して画像の情報を displayable 形式にする関数です。
None を指定するか、画像に渡される属性の set で呼び出され、レイヤーの選択に使用される属性の set を返す関数です。
子の配置と (可変サイズである場合) サイズ合わせで利用可能な領域を考慮するかどうか設定します。 False であれば利用可能な領域を考慮し、True であれば考慮しません。 None の場合、デフォルトは config.layeredimage_offer_screen
です。
追加のキーワード引数には transofrm プロパティーが含められます。与えられれば Transorm が作成され結果の画像をラップします。残りのキーワード引数はレイヤーを貼り付けるために作成された Fixed に渡されます。明示的な上書きがなければ、 xfit と yfit は Fixed で True に設定され、表示している全てのレイヤー画像にフィットする最小サイズに縮みます。
LayerdImage は displayable ではなく、 displayable が使用可能な全ての場所では使用出来ません。これは (一般的に画像属性を含む) 画像名 の提供が必要なためです。そういうわけで、 LayerdImage は scene や show ステートメントか、 displayable として使用される画像名の文字列から表示されるべきです。
layeredimage.format_function()
は属性と displayable を画像ファイルにフォーマットするための関数です。自身の format_function で置き換えたいなら、これがどう記述されるかやどう引数をとるかを参照しましょう。
layeredimage.
format_function
(what, name, group, variant, attribute, image, image_format, **kwargs) linkこれを呼び出して属性や条件を displayable の情報にフォーマットします。制作者によって置き換えられますが、新しい関数は未知のキーワード引数を無視するはずです。
フォーマットされるものを記述する文字列で、よりよいエラーメッセージを作成するために使用されます。
レイヤー画像の文字列です。
属性のグループで、 提供されないか条件内での使用なら None になります。
グループへのバリエーション引数で、提供されなければ None です。
属性です。
displayable または文字列です。
LayerdImage の image_format 引数です。
image が None なら、 name と (あれば) group,(あれば) variant, attribute がアンダースコアで結合され、 image の文字列になります。
images が文字列で、 image_format が None でなければ、 image は最終的な displayable を所得する文字列にフォーマットされます。
つまり name が "eileen", group が "expression", attribute が "happy" なら、 image は "eileen_expression_happy" に設定されます。 image_format が "images/{image}.png" なら、Ren'Py が見つける最終的な画像は "images/eileen_expression_happy.png" です。ただしフォーマット引数なしでも同じ画像を見るので注意してください。
レイヤー画像を代用して同じレイヤー画像を複数の場所で使用しなければならないときがあります。これは例えば、複数のサイズの同じスプライトを作ったり、サイドイメージとしてもう一つを使用するためです。
LayeredImageProxy()
オブジェクトでこれを行います。レイヤー画像を1つ受け取って複製します。
例
image dupe = LayeredImageProxy("augustina")
独立して表示出来る画像の複製を作成します。これはこのように transform を引数に受け取り、サイドイメージを配置するのに便利です。
image side augustina = LayeredImageProxy("augustina", Transform(crop=(0, 0, 362, 362), xoffset=-80))
LayeredImageProxy
(name, transform=None) linkこれは画像のようなオブジェクトです。渡される属性を他のレイヤー画像に中継します。
中継するレイヤー画像の名前の文字列です。
与えるなら、中継先の画像に適用される transform または transform のリストです。
指定された show
命令の後に何が表示されるかにはいくつかの要素が影響します。どのような順番で何が起こるかをより明確にするために、このセクションでは show 命令から画面上の表示まで、一連の属性の一生を紹介します。
show
ステートメントは画像タグに続いて最初の属性のセットを提供します。
config.adjust_attributes
関数があり、その画像タグに一致すれば呼び出されて属性のセットを返します。これは変更された可能性があります。もしそうであれば以前のセットは置き換えられ、忘れられます。
config.default_attribute_callbacks
関数があって、その実行条件が満たされていれば、呼び出されてそのセットに属性が追加される可能性があります。
前の2つの段階はレイヤー画像に限定されません。この後の段階で Ren'Py はどの画像またはレイヤー画像を呼び出して表示するか決定します。そのために、与えられた属性のセットは、 show statement section で説明されている動作で、1つの、そして唯一の定義された画像 ( または layeredimage, Live2D...) につながる必要があります。
次に、提供された属性はレイヤー画像に定義された属性と結合され、先に表示されていた属性のいくつかは破棄され、他の属性は保存されます。認識されない属性はここで検出され、エラーが発生します。そのようなエラーが発生しなければ、新しい属性と捨てられなかった属性が renpyによってその画像タグに関連する属性のセットとして認識されます。この計算では非互換性の制約のいくつかを考慮に入れていますが、すべてではありません。例えば、属性が同じ非 multiple グループにあることによる非互換性はこの時点で発生しますが、if_any/if_all/if_not 節ではエラーは発生しません。そのため、このような節で否定された属性も renpy ではアクティブとみなされ、例えば、 if_x 節の条件が満たされなくなった時点で再度呼び出されなくとも表示されるようになるのです。
attribute_function がレイヤー画像に提供されている場合、残りの属性のセットで呼び出されます。これは潜在的に異なる可能性のある属性のセットを返します。
このセットは、もう一度レイヤーイメージの非互換性の制約に直面します。これが最終段階であり、残っている属性が表示されます。