목차

이전 항목

모드

다음 항목

제작자 정의 명령문

링크


원문 보러 가기
오역 신고하기
Created using Sphinx.

제작자 정의 디스플레이어블

렌파이의 동작 방식을 바꾸는 방법 중 가장 강력하면서도 복잡한 방법으로 제작자 정의 디스플레이어블을 꼽을 수 있습니다. 제작자 정의 디스플레이어블을 이용하면 파이게임 이벤트를 받아 사용할 수 있습니다. 또한 다른 디스플레이어블을 렌더링해서 화면에 마음대로 배치할 수도 있습니다. 이것으로 렌파이에서 지원하는 기능으로는 만들 수 없는 2D 미니 게임 제작에 알맞은 기능입니다(참고로 이와 비슷한 기능을 하면서 보다 편리한 스프라이트 도 있으니 한번 살펴보시기 바랍니다).

제작자 정의 디스플레이어블은 전부 파이썬에서 프로그래밍해야 하므로 객체 지향적인 파이썬 프로그래밍 능력을 어느 정도 익힐 것을 추천합니다.

예제

다음은 제작자 정의 디스플레이어블의 예제입니다. 이 코드를 사용하면 하위 디스플레이어블의 중심부로부터 마우스 포인터까지의 거리를 계산해 하위 디스플레이어블의 알파값을 바꾸는 디스플레이어블을 만들 수 있습니다:

init python:

    import math

    class Appearing(renpy.Displayable):

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

            # 추가 속성은 renpy.Displayable 생성자에
            # 전달한다.
            super(Appearing, self).__init__(**kwargs)

            # 하위 위젯.
            self.child = renpy.displayable(child)

            # 하위 위젯이 불투명상태가 되는 거리와
            # 투명상태가 되는 거리. 불투명상태가 되는 거리가
            # 투명 상태일 때보다 값이 작아야 한다.
            self.opaque_distance = opaque_distance
            self.transparent_distance = transparent_distance

            # 하위 위젯의 알파 채널.
            self.alpha = 0.0

            # 하위 위젯의 너비와 높이.
            self.width = 0
            self.height = 0

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

            # 하위 위젯의 알파채널값을 조정하는 트랜스폼을
            # 만든다.
            t = Transform(child=self.child, alpha=self.alpha)

            # 하위 위젯에서 렌더를 만든다.
            child_render = renpy.render(t, width, height, st, at)

            # 하위 위젯의 크기를 알아낸다.
            self.width, self.height = child_render.get_size()

            # 반환할 렌더를 만든다.
            render = renpy.Render(self.width, self.height)

            # 하위 위젯의 렌더를 디스플레이어블 렌더에 그린다.
            render.blit(child_render, (0, 0))

            # 렌더를 반환한다.
            return render

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

            # 디스플레이어블의 중심부와 마우스 포인터간의
            # 거리를 계산한다. 마우스 포인터의 위치는 디스플레이어블의
            # 좌측 상단 모서리 지점을 원점으로 삼아 x, y 값을 받는다.
            distance = math.hypot(x - (self.width / 2), y - (self.height / 2))

            # 거리에 따라 알파값을 계산한다.
            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)

            # 알파값이 바뀌면 redraw 이벤트를 작동시킨다.
            if alpha != self.alpha:
                self.alpha = alpha
                renpy.redraw(self, 0)

            # 하위 위젯에 이벤트를 전달한다.
            return self.child.event(ev, x, y, st)

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

제작자 정의 디스플레이어블의 객체를 만든 다음, 그 객체를 화면에 추가하면 디스플레이어블을 사용할 수 있습니다.:

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

label start:
    show screen alpha_magic

    "로고가 어디에 있게?"

    return

renpy.Displayable

제작자 정의 디스플레이어블은 renpy.Displayable 클래스를 상속하는 자식클래스를 이용하여 만듭니다. 제작자 정의 디스플레이어블은 render 메소드는 꼭 재작성해야 되고, 필요하다면 다른 메소드도 재작성해야 합니다.

디스플레이어블 객체는 반드시 피클할 수 있어야 합니다. 즉, 피클할 수 없는 객체 참조는 담지 말아야 합니다. 특히 Render 객체는 제작자 정의 디스플레이어블에 저장해서는 안 됩니다.

디스플레이어블 클래스의 메소드는 재작성해야 하므로 self 매개변수도 함께 적어두었습니다.

class renpy.Displayable

제작자 정의 디스플레이어블의 부모 클래스.

__init__(**properties):

자식 클래스는 생성자를 재작성하거나 새 매개변수를 더할 수도 있다. 그렇다면 아래 코드를 사용하여 알 수 없는 키워드 인수는 전부 renpy.Displayable 생성자에 전달해야 한다.:

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

자식 클래스는 반드시 이 메소드를 재작성해서 renpy.Render 객체를 반환해야 한다. render 객체는 어떤 것이 화면에 나타나야 하는지를 결정하는 객체이다.

width, height
이 디스플레이어블에 배정할 공간. 픽셀 단위.
st
표시시간축. 초 단위 부동소수점. 표시 시간축은 디스플레이어블을 화면에 그렸을 때부터 시간 계산을 시작한다.
at
동작시간축. 초 단위 부동소수점. 동작 시간축은 동일한 태그가 지정된 이미지가 화면에 나타났을 때부터 시간 계산을 시작한다. (태그가 없는 디스플레이어블이 화면에 나타나있으면 이 값은 표시시간축과 같게 된다.)

render 메소드는 디스플레이어블에 화면에 처음 나타났을 때 호출된다. renpy.redraw() 를 이 객체에 호출하면 render 메소드가 다시 호출 될 수 있다.

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

파이게임 이벤트를 제작자 정의 디스플레이어블에 넘겨줄 때 호출되는 메소드이다. 이벤트 메소드가 None 이 아닌 값을 반환하면 값은 인터렉션의 결과값으로써 반환된다.

이벤트 메소드는 다른 디스플레이어블에서 제작자 정의 디스플레이어블에 이벤트를 넘겨줄 수도 있다.

ev
이벤트 객체
x, y
이벤트의 x, y 좌표값. x, y 값은 디스플레이어블의 좌측 상단 모서리를 원점으로 삼아 계산한다. 좌표값은 파이게임 이벤트 객체에서 찾을 수 있는 위치 정보 보다 우선해서 사용된다.
st
표시시간축. 초 단위 부동 소수점.

이벤트는 각 인터렉션이 시작할 때 만들어지지만, renpy.timeout() 를 사용하면 다른 이벤트를 발생하게 할 수도 있다.

per_interact(self)

각 인터렉션이 시작할 때 호출되는 메소드. redraw 함수를 작동시키거나, 롤백에 영향을 받는 객체에 redraw 함수를 작동시킬 때 사용할 수 있다.

visit(self)

디스플레이어블에 하위 디스플레이어블이 있으면 이 메소드는 하위 디스플레이어블의 리스트를 반환하도록 재작성해야 한다. 이는 하위 디스플레이어블이 per_interact 메소드를 호출해서 하위 디스플레이어블이 사용하는 이미지를 예측하기 위함이다.

renpy.Render

제작자 정의 디스플레이어블은 renpy.Render 객체를 통해 작동합니다. 디스플레이어블에 renpy.render() 함수를 호출하면 Render 객체가 반환됩니다. 제작자 정의 디스플레이어블에서는 renpy.Render 클래스를 호출하여 렌더 클래스의 메소드에서 렌더 객체를 만들어야 합니다.

render 객체는 자식 클래스를 만들 수 있도록 만들어진 객체가 아니라서 self 매개변수는 적지 않았습니다.

class renpy.Render(width, height)

새 Render 객체를 만든다.

width, height
렌더 객체의 너비와 높이. 픽셀 단위.
blit(source, pos)

이 렌더 객체에 또다른 렌더 객체를 그린다.

source
그리려는 렌더 객체.
pos
그리려는 위치. (x, y) 튜플. 튜플은 대상 렌더의 좌측 상단 모서리를 원점으로 삼는 픽셀 단위의 좌표이다.
main
키워드 전용 매개변수. 참값이면 source 가 스타일 조사기에 나타난다.
place(d, x=0, y=0, width=None, height=None, st=None, at=None, render=None, main=True)

d 를 렌더하고 렌파이 표준 배치 알고리즘을 사용하여 x, y, width, height 로 정의된 사각형 안에 배치한다.

x, y, width, height
d 를 배치시킬 사각형. width 혹은 `height`가 None 이면, 각각의 값은 이 렌더의 가로와 세로값으로 설정된다.
st, at
Render가 전달 받을 시간값. None이라면 이 메소드를 호출하는 렌더 메소드에 전달되는 시간을 기본값으로 한다.
render
None이 아닌 경우에는 d 를 렌더링하는 대신에 사용된다.
main
.blit()에 관한 매개변수.
canvas()

캔버스 객체를 반환한다. 캔버스 객체에는 pygame.draw 함수에서 surface 매개변수를 제한 나머지 메소드를 똑같은 방식으로 사용한다.

캔버스 객체는 get_surface() 메소드를 가진다. 이 메소드는 캔버스 밑에 깔린 pygame Surface 를 반환한다.

get_size()
렌더의 크기를 (너비, 높이) 튜플 형태로 반환한다.
subsurface(rect)

이 렌더에서 잘라낸 사각형의 렌더를 반환한다.

rect
(x, y, 너비, 높이) 튜플
zoom(xzoom, yzoom)

이 디스플레이어블의 하위 디스플레이어블의 가로 방향 및 세로 방향 축의 확대 정도를 설정한다. 디스플레이어블의 하위 디스플레이어블만 확대된다. 가로 길이, 세로 길이, blit 좌표는 확대되지 않는다.

유용한 함수

다음 함수는 렌더링 프로세스를 관리하는 함수입니다.

renpy.displayable(d, scope=None)

디스플레이어블 객체나 문자열로 나타낸 d 를 받는다. 문자열일 때는 일반 규칙에 따라 문자열을 디스플레이어블로 바꾼다.

renpy.end_interaction(value)

`value`가 None이 아니라면 현재 인터렉션을 즉시 종료하고 인터렉션이 `value`를 반환하도록 한다. `value`가 None이라면 동작하지 않는다.

이 함수는 제작자 정의 디스플레이어블의 render 와 event 메소드 내부에서 호출될 수 있다.

renpy.load_image(im)

이미지 캐시를 사용해 이미지 조작기 im 을 불러오고 텍스처를 반환한다.

renpy.load_surface(im)

이미지 캐시를 사용해 이미지 조작기 im 을 불러오고 pygame Surface를 반환한다.

renpy.map_event(ev, keysym)

pygame 이벤트 evkeysym 과 일치하면 참을 반환한다.

keysym

다음 중 하나이어야 한다. :

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

디스플레이어블을 렌더링하고 renpy.Render 객체를 반환한다.

d
렌더링할 디스플레이어블.
width, height
디스플레이어블을 렌더링할 수 있는 영역의 너비와 높이.
st, at
표시시간축과 동작시간축.

이 객체가 반환하는 렌더는 캐싱할 수도 있으므로, 한 번 반환하고 나면 수정해서는 안 된다.

renpy.timeout(seconds)

seconds 초가 지나기 전에 이벤트를 만들어 제작자 정의 디스플레이어블의 이벤트 메소드를 호출한다. 사용자 정의 디스플레이어블의 event 메소드가 확실히 호출되도록 하는 함수.

im.load_image(im)

이미지 캐시를 사용해 이미지 조작기 im 을 불러오고 텍스처를 반환한다.

im.load_surface(im)

이미지 캐시를 사용해 이미지 조작기 im 을 불러오고 pygame Surface를 반환한다.

renpy.redraw(d, when)

디스플레이어블이 when 초가 경과한 후에 d 를 다시 그리도록 한다.