レイヤー画像 link

スプライトの組がある程度の複雑さになると、すべての可能な組み合わせを定義するのがやりにくくなります。例えば4つの服装と4つの髪型、6つの表情のスプライトの組み合わせはすでに 96 組あります。すべての組み合わせの静止画像作成には多くのディスクスペースとプログラマーの時間を消費します。

このような状況に対処するため、Ren'Py には複数レイヤーで構成される画像を定義する方法があります(ここでのレイヤーは Photoshop やGIMP のようなペイントソフトでのレイヤーで、Ren'Py の他の場所で語られるレイヤーではありません)。レイヤーは無条件で表示されたり、画像に提供された属性やランタイムで評価された条件によって選択されたりできます。

レイヤー画像の定義をより簡単に定義するため、 Ren'Py には layerdimage ステートメントがあり、それはレイヤー画像の定義に使用される固有の言語を導入します。画像ではありませんが、 image ステートメントで画像のように使用出来る LayerdImage() オブジェクトもあります。

レイヤー画像の定義 link

レイヤー画像用の言語はほんの少数のステートメントで構成され、その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 ステートメントは属性をとれます。 alwaysif ステートメントには displayable が提供されなければなりませんが、 attribute ステートメントには任意で提供されます。すべてのステートメントにはプロパティーが提供出来ます。

always ステートメントはスプライトの背景のような常に表示されるレイヤーを宣言します。

group ステートメントは一度にその属性のうちの1つだけが表示される属性グループを導入します。これにより、このレイヤー画像は1つの服と目、眉、口それぞれの位置で1つずつしか出力されません。グループへのプロパティーは属性に渡され、グループでは自動的に属性を宣言できます。

attribute ステートメントは画像にある属性が提供されると表示されるレイヤーを導入します。例では "dress" 属性が提供されるときのみ "augustina_outfit_dress" が表示されます。 default キーワードが属性に与えられると、矛盾する属性が与えられなければ、その属性が表示されます。この例では "wink" 属性がなければ "augustina_eyes_open" が表示されます。

最後に、 if ステートメントは Python ステートメントを使用して displayable を選択するレイヤーを追加します。これは毎回評価され、最初に True と評価される条件が表示されます。

プロパティーはプロパティー名と単純式で構成され、各レイヤーに提供されます。ステートメントの機能を変更するプロパティーもあります。ひとつ以上の 変換プロパティー があたえられると、 Transform() が作成されて displayable をラップします。 at プロパティーには displayable をラップする変換または変換リストも与えられます。例えば、ここで pos プロパティーは各口の画像の左上端を移動する変換を作成しています。

最終的な画像は全てのレイヤーの短形領域の最大サイズとなるため、画像からはみ出すレイヤーがない十分な大きさのレイヤーが1つあるとよいでしょう。最初のレイヤーは画像の背景に、最後のは前になります。この例では、眼鏡が他のレイヤーの上となります。

group と attribute は表示される属性をもつ全てのレイヤーとともに layeredimage に一回以上表れるでしょう。

レイヤー画像の使用 link

この例でのレイヤー画像を使用するには evil 変数に値を与えなければ成りません。 例

default evil = True

これでレイヤー画像は他の画像のように表示出来ます。ほぼ確実に outfit のどれかは与えられるでしょうが、 Ren'Py はこれを強制しないので、この画像はどれかを必要とします。

show augustina jeans

スプライトが表示されている間、衝突しなければ追加の属性を既に表示しているスプライトに加えられます(これは表示されている画像が既に定義されている画像に一致しないときの場合で、レイヤー画像では起こりません)。そのため、

show augustina wink

これは wink 属性と関連付けされたレイヤーをアクティベートします。開いた目はウィンクと衝突するので次のようにしてウィンクを止められます。

show augustina open

もしくは単に wink 属性を以下のようにして除去できます。

show augustina -wink

これはデフォルトの open 属性で画像を表示します。

レイヤー画像は scene ステートメントでも使用できます。

自動属性 link

最初の例では属性を定義する属性名と 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つの行で記述されます。

alwaysif ステートメントでは、 displayable を省略できないため、(もう少し適切な名前の画像がありますが)これが一番簡略です。これによって数千数万のレイヤーの組み合わせさえ定義できます。

Statement link

そのレイヤー画像が最初に定義される初期化時に if ステートメントの条件であるすべての式が評価されることに注意してください。

Layeredimage link

layerdimage ステートメントはレイヤー画像を導入する Ren'Py スクリプト言語のステートメントです。これは画像名で始まり、 attribute, group, if ステートメントなどを含むブロックをとります。

layerdimage は以下のプロパティーをとります。 :

image_format

与えられた画像が文字列でこれが与えられると、画像名は image_format に補間され、画像ファイルになります。例えば、 "sprites/eileen/{image}.png" ならスプライトのサブディレクトリーからその画像を探します ( これは画像ではなく画像ファイルを探す自動グループでは使用されません )。

format_function

layeredimage.format_function の代わりに使用して画像の情報を displayable 形式にする関数です。

変換プロパティー

与えられると、 displayable に適用される Transform() を構築するのに使われます。

at

レイヤー画像へ適用される変換または変換のリストです。

Attribute link

attribute ステートメントは特定の属性を使用して画像を表示するときに表示されるレイヤーを追加します。同じ属性が複数のレイヤーに使用出来、その属性に対応する全てのレイヤーが表示されます( if_all, if_any, if_not プロパティーでこれを変更出来ます)。

attribute は属性名をとり、さらに 2 つのキーワードもとれます。 default キーワードはそのグループの属性と衝突しなければデフォルトで与えられる属性を示します。 null キーワードは Ren'Py が自動的にこの属性に対応する displayable を検索しないようにするので、 if_allif_any, if_not と組み合わせての使用をのみ意図した属性を持つのに便利です。

displayable が与えられなければ、そのレイヤーやグループ、グループバリエーション、属性の名前から、すべてのスペースをアンダースコアで置き換え、さらにアンダースコアで全てを結合して推測します。つまり画像名 "augustina" , グループ "eyes", 属性 "closed" があれば、 "augustina_eyes_closed" が使用されます( レイヤー画像のフォーマット関数がこれに使用され、デフォルトは layeredimage.format_function() です)。

属性にグループがなければ、同じ名前のグループに配置されますが、そのグループは displayable 名の推測に使用されません(つまり "image_attribute_attribute" ではなく "image_attribute" を探します)。

attribute ステートメントは以下のプロパティーをとります :

if_all

属性名の文字列または文字列リストです。これがあれば、このレイヤーはすべての属性名が与えられなければ表示されません。

if_any

属性名の文字列または文字列リストです。これがあれば、このレイヤーは属性名のどれかが与えられなければ表示されません。

if_not

属性名の文字列または文字列リストです。これがあれば、このレイヤーは属性名がすべて与えられなければ表示されます。

変換プロパティー

与えられれば、レイヤーに適用される変換を構築するのに使用されます。

at

レイヤーに適用される変換または変換のリストです。

Group link

group ステートメントはレイヤーをグループ化します。属性がグループ内にあるときに、そのグループの他の属性を含むのはエラーになります(同じ属性を 2 回含むのは良いです。 multiple キーワードはこの制限をなくします)。

group ステートメントは名前をとります。名前はあまり使用されませんが、グループ内の属性のデフォルト名を生成するのに使われます。

auto キーワードが名前に続くかもしれません。与えられればそのグループのその後のどの属性も宣言され、 Ren'Py はその画像のリストをスキャンしてグループパターン(下記参照)にマッチするものを探します。見つかった画像で、宣言された属性に対応しないものは attribute ステートメントで宣言されたかのようにそのグループに追加されます。

multiple キーワードも続けられます。与えられれば、グループのひとつ以上のメンバーが同時に選択できます。これは排他的ではない複数の属性を自動定義するグループに便利です。これは属性の1つに default キーワードが与えられていると衝突します。

プロパティーはグループの最初の行で宣言でき、プロパティーや属性を含むブロックをとられます。

グループに指定される 2 つのプロパティーがあります。

variant

指定されるならこれは文字列で、バリエーション要素として自動生成の画像名の一部や自動定義の属性の検索パターンになります。

prefix

指定されるなら、手動または自動定義の属性名とアンダースコアで連結される接頭辞です。つまり prefix が"leftarm" で、属性名が "hip" なら、属性 "leftarm_hip" が代わりに定義されます。

group ステートメントは attribute と同じプロパティーをとります。グループに提供されたプロパティーは、属性の同じプロパティーを上書きしない限りそのグループ内の属性に渡されます。

Pattern. 使用される画像パターンは以下で構成されます。 :

  • 画像の名前で、スペースはアンダースコアで置換されます。

  • グループの名前です。

  • バリエーションの名前です。

  • 属性の名前です。

すべてはアンダースコアで結合されます。例えば、レイヤー画像 "augustina work" とグループ "eyes" があれば、これは augustina_work_eyes_attribute にマッチします。 variantbule なら、 augustina_work_eyes_blue_attribute にマッチします。

Always link

always ステートメントは常に表示されるレイヤーを宣言します。 displayable が与えられなければならず、プロパティーもとれます。両方を同じ行にもブロック内にも配置できます。

always ステートメントは以下のプロパティーをとります。 :

if_all

属性名の文字列または文字列リストです。これがあれば、このレイヤーはすべての属性名が与えられなければ表示されません。

if_any

属性名の文字列または文字列リストです。これがあれば、このレイヤーは属性名のどれかが与えられなければ表示されません。

if_not

属性名の文字列または文字列リストです。これがあれば、このレイヤーは属性名がすべて与えられなければ表示されます。

変換プロパティー

与えられれば、レイヤーに適用される変換を構築するのに使用されます。

at

レイヤーに適用される変換または変換のリストです。

If link

if ステートメントにはランタイムで評価される 1 つ以上の条件を渡せられます。各条件はレイヤーに関連付けられ、最初に True となる条件のものが表示されます。 True となる条件がなく、 else レイヤーがあれば、それが表示されます。

if ステートメントのより完全な例は以下のようになります。

if glasses == "evil":
    "augustina_glasses_evil"
elif glasses == "normal":
    "augustina_glasses"
else:
    "augustina_nose_mark"

各レイヤーには displayable が与えられなければならず、以下のプロパティーも与えられます。 :

if_all

属性名の文字列または文字列のリストです。これがあれば、この条件はすべての属性名が与えられなければ考慮されません。

if_any

属性名の文字列または文字列のリストです。これがあれば、この条件は属性名のどれかが与えられなければ考慮されません。

if_not

属性名の文字列または文字列のリストです。これがあれば、この条件は属性名がすべて与えられなければ考慮されます。

変換プロパティー

与えられれば、レイヤーに適用される変換を構築するのに使用されます。

at

レイヤーに適用される変換または変換のリストです。

if ステートメントは layerdimage ステートメント実行時に ConditionSwitch() に変換されます。

predict_all が True でなければ、レイヤー画像が表示されている、またはまさに表示されるときは if ステートメントの条件の変更は避け、予測不能な画像の読み込みを避けるべきです。これはめったに変更されない character のカスタマイズオプションでの使用を意図しています。

Poses link

全て、または少なくとも興味がある全てが異なる複数のポーズのスプライトがあるキャラクターを持つことが可能です。例えばキャラクターに立ちポーズと座りポーズがあれば、全ての画像のパーツは異なる場所にあるでしょう。

その場合、同じ画像タグの複数のレイヤー画像の定義が役立ちます。 layerdimage ステートメントでは画像名の一部として属性を含められるので、これが可能になります。

layeredimage augustina sitting:
    ...

layeredimage augustina standing:
    ...

これは特にレイヤー画像を使用してサイドイメージを構成するのに便利です。別々のキャラクターのサイドイメージは互いに影響がありません。

layeredimage side eileen:
    ...

layeredimage side lucy:
    ...

Advice link

画像名でのアンダースコアの使用 デフォルトでは、 Ren'Py のレイヤー画像はアンダースコアで画像名をパーツに分割します。パーツ間にスペースがある画像の使用は魅力的かもしれませんが、後述の問題に発展しかねません。

Ren'Py には表示されているものと同じ名前の画像を表示するときは置き換えて表示されるルールがあります。これにより定義したレイヤー画像を越えて、直接レイヤーを表示できます。これはなにもない空間に目が浮かぶような妙な問題に繋がる可能性があります。

各レイヤーがメインの画像と異なるタグを持てばこれは問題ではなくなります。

レイヤーの切り取りは不要です Ren'Py は画像を RAM に読み込む前に、不透明なピクセルの短形領域に切り取って画像を最適化します。つまり画像が適切に予測されれば、自分で画像を切り取ってもパフォーマンスや画像サイズは一般的にあまり改善しません。

Python link

もちろん layerdimage ステートメントには等価な Python がありますが、 group ステートメントは attribute に与えられるためありません。自動機能は renpy.list_image() を使用して実装できます。

Attribute(group, attribute, image=None, default=False, **kwargs) link

これを使用して属性に制御される LayerdImage のレイヤーを表します。1つの属性で複数のレイヤーを制御でき、この場合、その属性に対応する全てのレイヤーが表示されます。

group

属性が加わるグループの文字列です。 None である場合、属性と同じ名前のグループが作成されます。

attribute

属性の名前の文字列です。

image

これは None または、この属性が表示される displayable です。

default

True かつそのグループの他の属性が選択されていなければ、この属性となります。

以下のキーワード引数もあります。 :

at

画像に適用される変換または変換のリストです。

if_all

属性または属性のリストです。 displayable はこれらの全てがあるときだけ表示されます。

if_any

属性または属性のリストです。 displayable はこれらのどれかがあるときだけ表示されます。

if_not

属性または属性のリストです。 displayable はこれらの全てがないときだけ表示されます。

他のキーワード引数は変換プロパティーとして解釈されます。与えられると、画像をラップする変換が作成されます(例えば、 pos=(100, 200) を使用して、画像を 100 ピクセル横に、 200 ピクセル縦にオフセットできます)。

image 引数が省略されるか None であり、LayerdImage に image_format 引数が与えられると、 image_format を使用して画像ファイル名を生成します。

Condition(condition, image, **kwargs) link

これにより条件で制御される LayerdImage のレイヤーを表します。条件が True ならレイヤーが表示され、そうでなければ表示されません。

condition

レイヤーが表示されるかどうかを決定する Python の条件の文字列です。

image

これは None または条件が True なら表示される displayable です。

if_all

属性または属性のリストです。これらのすべてがあるときのみ条件は評価されます。

if_any

属性または属性のリストです。これらのどれかがあるときのみ条件は評価されます。

if_not

属性または属性のリストです。これらのすべてがないときのみ条件は評価されます。

at

画像に適用される変換または変換のリストです。

他のキーワード引数は変換プロパティーとして解釈されます。与えられると、画像をラップする変換が作成されます(例えば、 pos=(100, 200) を使用して、画像を 100 ピクセル横に、 200 ピクセル縦にオフセットできます)。

LayeredImage(attributes, at=[], name=None, image_format=None, format_function=None, attribute_function=None, **kwargs) link

これは画像のようなオブジェクトで、適切な属性の組み合わせで表示されると、それらの属性と関連付けられた displayable を合成して作成した displayable を表示します。

attributes

これは Attribute オブジェクトのリストです。各 Attribute オブジェクトはその画像の一部として表示され、またはされない displayable を反映します。このリストの要素は後ろから前の順となり、プレイヤーから見て最初の要素は遠くに、最後のものは近くになります。

at

合成後に displayable に適用される変換または変換のリストです。

name

属性画像の名前で、画像要素の名前の一部として使用されます。

image_format

与えられた画像が文字列でこれが与えられると、画像名は image_format に補間され、画像ファイルになります。例えば、 "sprites/eileen/{image}.png" ならスプライトのサブディレクトリーからその画像を探します ( これは画像ではなく画像ファイルを探す自動グループでは使用されません )。

format_function

layeredimage.format_function の代わりに使用して画像の情報を displayable 形式にする関数です。

attribute_function

None を指定するか、画像に渡される属性の set で呼び出され、レイヤーの選択に使用される属性の set を返す関数です。

追加のキーワード引数はレイヤーを貼り付けるために作成された 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 の情報にフォーマットします。制作者によって置き換えられますが、新しい関数は未知のキーワード引数を無視するはずです。

what

フォーマットされるものを記述する文字列で、よりよいエラーメッセージを作成するために使用されます。

name

属性名の文字列です。

group

属性のグループで、 提供されないか条件の一部なら None になります。

variant

グループへのバリエーション引数で、提供されなければ None です。

attribute

属性です。

image

displayable または文字列です。

image_format

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" です。ただしフォーマット引数なしでも同じ画像を見つけたことに注意してください。

Proxying Layered Images link

レイヤー画像を代用して同じレイヤー画像を複数の場所で使用しなければならないときがあります。これは例えば、複数のサイズの同じスプライトを作ったり、サイドイメージとしてもう一つを使用するためです。

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

これは画像のようなオブジェクトで。渡される属性を他のレイヤー画像に中継します。

name

中継するレイヤー画像の名前の文字列です。

transform

与えるなら、中継先の画像に適用される変換または変換のリストです。