ユーザー定義 Displayable link

Ren'Py の動作をカスタマイズする最も複雑だが最もパワフルな方法はユーザー定義 displayable の使用です。ユーザー定義 displayable は任意の pygame イベントを受け取れ、他の displayable をレンダリングして画面の任意の位置にそれらを配置できます。 このため Ren'Py が提供するツールでは表現できない 2D ゲームを作成するのに最適です。( sprites の章も見てください。大量の同一displayableを扱う高度な方法が述べられています。 )

ユーザー定義 displayable はすべて Python でプログラムされるため、この作成を始める前にある程度のオブジェクト指向 Python プログラミングスキル獲得を勧めます。

link

これはユーザー定義 displayable の例です。この displayable は、その中心とマウスポインターとの距離から alpha 値を決めて、その子のレンダリングを変更します。

init python:

    import math

    class Appearing(renpy.Displayable):

        def __init__(self, child, opaque_distance, transparent_distance, **kwargs):

            # Pass additional properties on to the renpy.Displayable
            # constructor.
            super(Appearing, self).__init__(**kwargs)

            # The child.
            self.child = renpy.displayable(child)

            # The distance at which the child will become fully opaque, and
            # where it will become fully transparent. The former must be less
            # than the latter.
            self.opaque_distance = opaque_distance
            self.transparent_distance = transparent_distance

            # The alpha channel of the child.
            self.alpha = 0.0

            # The width and height of us, and our child.
            self.width = 0
            self.height = 0

        def render(self, width, height, st, at):

            # Create a transform, that can adjust the alpha channel of the
            # child.
            t = Transform(child=self.child, alpha=self.alpha)

            # Create a render from the child.
            child_render = renpy.render(t, width, height, st, at)

            # Get the size of the child.
            self.width, self.height = child_render.get_size()

            # Create the render we will return.
            render = renpy.Render(self.width, self.height)

            # Blit (draw) the child's render to our render.
            render.blit(child_render, (0, 0))

            # Return the render.
            return render

        def event(self, ev, x, y, st):

            # Compute the distance between the center of this displayable and
            # the mouse pointer. The mouse pointer is supplied in x and y,
            # relative to the upper-left corner of the displayable.
            distance = math.hypot(x - (self.width / 2), y - (self.height / 2))

            # Base on the distance, figure out an alpha.
            if distance <= self.opaque_distance:
                alpha = 1.0
            elif distance >= self.transparent_distance:
                alpha = 0.0
            else:
                alpha = 1.0 - 1.0 * (distance - self.opaque_distance) / (self.transparent_distance - self.opaque_distance)

            # If the alpha has changed, trigger a redraw event.
            if alpha != self.alpha:
                self.alpha = alpha
                renpy.redraw(self, 0)

            # Pass the event to our child.
            return self.child.event(ev, x, y, st)

        def visit(self):
            return [ self.child ]

ユーザー定義 displayable を使用するためにそのインスタンスを作成し、それをスクリーンに追加できます。

screen alpha_magic:
    add Appearing("logo.png", 100, 200):
        xalign 0.5
        yalign 0.5

label start:
    show screen alpha_magic

    "Can you find the logo?"

    return

renpy.Displayable link

ユーザー定義 displayable は renpy.Displayable のサブクラスとして作成されます。ユーザー定義 displayable では render メソッドと、おそらくその他のメソッドも同様に上書きしなければなりません。

displayable オブジェクトは pickle 可能でなければなりません。つまり pickle できないオブジェクトへの参照を含んではいけません。 特に Render オブジェクトはユーザー定義 displayable に保存できません。

displayable クラスのメソッド上書きをして欲しいので、 self パラメーターつきで記載します。

class renpy.Displayable link

ユーザー定義 displayable の基本クラスです。

__init__(**properties) link

サブクラスはコンストラクターを上書きし、新しいパラメーターを追加するかもしれません。その場合、以下のようなコードを使用して、すべての未知のキーワード引数をrenpy.Displayable のコンストラクターに渡すべきです。

super(MyDisplayable, self).__init__(**properties)
render(self, width, height, st, at) link

サブクラスはこれを上書きして renpy.Render オブジェクトを返さなければなりません。 render オブジェクトは画面に何が表示されるかを決定します。

width, height

この displayable が利用できるピクセル数での空間です。

st

秒数での出現時間軸の浮動小数です。出現時間軸はこの displayable が最初に画面に表示されると開始します。

at

秒数でのアニメーション時間軸の浮動小数です。アニメーション時間軸は同じタグを持つ画像が hide されていない状態で表示されると開始します。 ( displayable がタグなしで表示されるとこれは出現時間軸と同じです。 )

render メソッドはこの displayable が最初に表示されるときに呼び出されます。これはこのオブジェクトの renpy.redraw() が呼び出されると、もう一度呼び出されます。

event(self, ev, x, y, st) link

イベントメソッドを呼び出して pygame イベントをユーザー定義 Displayable に渡せます。イベントメソッドが None ではなく値を返すならその値はそのインタラクションの結果として返されます。イベントメソッドが None を返すと、そのイベントは他の Displayable に渡されます。

None を返す以外でイベントを無視するには renpy.IgnoreEvent を投げます。

event メソッドは他の displayable にも存在し、ユーザー定義 displayable がそのイベントを渡せるようにします。

ev

event オブジェクト

x, y

displayable の左上に対するイベントの x,y 座標です。これらは pygame イベントオブジェクトで見つけられる位置情報より優先して使用されるはずです。

st

出現する時間軸の秒数

event は各インタラクションの開始で生成され、 renpy.timeout() はもう一つのイベントを発生させるために使用できます。

per_interact(self) link

このメソッドは各インタラクションの開始で呼び出されます。再描画を起こすために使用でき、また、オブジェクトがロールバックに参加するなら、再描画に使用するべきです。

visit(self) link

displayable が子の displayable を持っていたら、このメソッドを上書きしてそれらの displayable のリストを返すべきです。これはそれらの displayable の per_interact メソッドが呼び出されることを保証し、それらの displayable に使用される画像が予測されるようにもします。

place(self, dest, x, y, width, height, surf, main=True) link

レンダー(この Displayable のレンダーでなければなりません)をバウンディング領域内に配置し、 その Displayable が配置された場所を与える (x, y) タプルを返します。

dest

None でなければ算出された座標で surfdest に貼り付けられます。

x, y, width, height

バウンディング領域

surf

配置される Render オブジェクト

main

これは Render.blit() に渡されます。

renpy.Render link

ユーザー定義 displayable は renpy.Render オブジェクトとともに働きます。 Render オブジェクトはdisplayableの renpy.render() 関数を呼び出すと返されます。ユーザー定義 displayable はその render メソッドから renpy.Render を呼び出して Render オブジェクトを作成するべきです。

render オブジェクトはサブクラスにすることが意図されていないので、 self パラメーターを省略して記載しています。

class renpy.Render(width, height) link

新しい Render オブジェクトを作成します。

width, height

ピクセル数での Render オブジェクトの幅と高さです。

blit(source, pos, main=True) link

この Render オブジェクトにもう一つの Render オブジェクトを描写します。

source

描画する Render オブジェクト

pos

描画する座標。これは対象の Render の左上端に対するピクセル数の座標 (x,y) のタプルです。

main

キーワード専用パラメーターです。 True なら source がスタイルインスペクターに表示されます。

place(d, x=0, y=0, width=None, height=None, st=None, at=None, render=None, main=True) link

Displayable d をレンダリングし、 x, y, width, height で定義された矩形に Ren'Py 標準の配置方法で配置します。その Displayabe が配置された場所を与える (x, y) タプルを返します。場所は Displayable.place メソッドを呼び出して算出されます。

x, y, width, height

配置する長方形です。 widthheight が None でなければ、それぞれこの render の幅と高さになります。

st, at

render に渡される時間です。 None なら、このメソッドを呼び出している render メソッドに渡される時間になります。

render

None でなければこれが d の代わりに使用されます。

main

.blit() と同様です。

canvas() link

canvas オブジェクトを返します。 canvas オブジェクトは pygame.draw の関数に対応し、最初のパラメーター ( surface ) を省略したメソッドを持ちます。

Ren'Py では arc 関数と ellipse 関数は実装されていません。

Canvas オブジェクトはその canvas 下にある pygame Surface を返す get_surface() メソッドも持ちます。

get_size() link

この Render のサイズを与える (width, height) のタプルを返します。

subsurface(rect) link

この Render を長方形に切り取って構成される Render を返します。

rect

(x, y, width, height) のタプル

zoom(xzoom, yzoom) link

この displayable の子の水平、垂直方向のズームレベルを設定します。 displayable の子のみが拡大され、幅、高さ、 blit 座標は拡大されません。

以下の属性とメソッドはモデルベースのレンダリング有効時のみ使用可能です。

mesh link

このフィールドはこのレンダーに対してモデルベースのレンダリングを有効にします。 :

True なら :

  • この Displayable のすべての子がテクスチャにレンダリングされます。

  • mesh はこの Displayable の最初の子のサイズです。

  • モデルはこのレンダーの mesh, shader, uniform, properties で作成されます。

モデル1つのオペレーションで描画されます。

add_shader(shader) link

これにより、 shader は shader を分離してこのレンダーやその子が描画されるときに使用されるようにします。文字列またはshaderで描画されないようにする "-" で始まる文字列です。

add_uniform(name, value) link

このレンダーやその子が描画されるときに uniform namevalue にします。

add_property(name, value) link

このレンダーまたはその子の1つが描画されるときに GL プロパティー namevalue にします。

ユーソリティー関数とクラス link

renpy.displayable(d, scope=None) link

これは displayable オブジェクトか文字列の d を受け取ります。文字列なら通常のルールに基づきその文字列を displayable に変換します。

renpy.end_interaction(value) link

value が None でなければ、即座に現在のインタラクションが終了し、インタラクションは value を返します。 value が None の場合は何もしません。

これは Render 内部とユーザー定義 displayable の event メソッドから呼び出され得ます。

renpy.is_pixel_opaque(d, width, height, st, at, x, y) link

この Displayable が renpy.render(d, width, height, st, at) によりレンダリングされたときに (x, y) でのピクセルが不透明かどうかを返します。

renpy.load_image(im) link

画像キャッシュを使用して画像マニピュレータ im をロードし、 render を返します。

renpy.load_rgba(data, size) link

size で指定したサイズのテクスチャーに画像データ bytes をロードし、 render を返します。

data

RGBA8888 順の画像データを含むバイトオブジェクトであるべきです。

renpy.load_surface(im) link

画像キャッシュを使用して画像マニピュレータ im をロードし、 pygame Surface を返します。

renpy.map_event(ev, keysym) link

pygame のイベント evkeysym にマッチするなら True を返します。

keysym

以下のうちの 1 つです :

renpy.render(d, width, height, /, st, at) link

displayable がレンダリングされ、 renpy.Render オブジェクトが返されます。

d

レンダリングする displayable

width, height

displayable がレンダリング可能な幅と高さです。

st, at

出現時刻とアニメーション時間軸です。

このオブジェクトから返された Render はキャッシュされるので、一度取り出された Render は修正すべきではありません。

renpy.timeout(seconds) link

event が seconds 秒が経過後に生成されます。これは ユーザー定義 displayable の event メソッドが呼び出されることを保証します。

renpy.redraw(d, when) link

when 秒が経過後、 Displayable d を(renderメソッドを呼び出して)再描画します。 Displayable がその時間前に再描画される可能性もあります(例えば子の再描画)。その場合、保留中の再描画は破棄されます。

exception renpy.IgnoreEvent link

これは発生すると Ren'Py にそのイベントを無視させる例外です。イベントのメソッド内でこれを発生させるには次のように記述します。

raise renpy.IgnoreEvent()