ユーザー定義 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):

サブクラスはコンストラクターを上書きし、新しい引数を追加するかもしれません。その場合、以下のようなコードを使用して、すべての未知のキーワード引数を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

event メソッドは pygame イベントをユーザー定義 displayable に渡すために呼び出されます。 event メソッドが None 以外の値を返すとその値はインタラクションの結果として返されます。

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 に使用される画像が予測されるようにもします。

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

d をレンダリングし、 x, y, width, height で定義された長方形に配置します。

x, y, width, height

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

st, at

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

render

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

main

.blit() と同様です。

canvas() link

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

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 座標は拡大されません。

ユーティリティー関数 link

これらの関数はレンダリングプロセスを管理します。

renpy.displayable(d, scope=None) link

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

renpy.end_interaction(value) link

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

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

renpy.load_image(im) link

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

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 メソッドが呼び出されることを保証します。

im.load_image(im) link

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

im.load_surface(im) link

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

renpy.redraw(d, when) link

displayable dwhen 秒経過後に再描画されます。