말풍선

Ren'Py는 화면에서 위치를 직접 조절할 수 있는 말풍선에 대사를 표시할 수 있습니다. ADV 방식의 텍스트 상자나 NVL 모드의 전체 화면 대사 대신 사용할 수 있습니다.

게임에서 말풍선을 사용하려면 이미지 태그와 bubble kind를 가진 Character를 정의해야 합니다. 예를 들어:

define e = Character(None, image="eileen", kind=bubble) # Eileen
define l = Character(None, image="lucy", kind=bubble)   # Lucy

이름도 지원하지만 일반적으로 말풍선 꼬리로 화자를 알 수 있으므로 생략해도 됩니다.

그런 다음 이 캐릭터들로 평소처럼 대사를 작성하면 됩니다.

말풍선 위치를 정하려면 shift+B로 말풍선 편집기를 엽니다. 말풍선이 있는 각 캐릭터마다 버튼 두 개가 나타납니다.

영역 버튼을 누르면 말풍선 영역 편집기가 열립니다. 격자 위를 드래그하여 말풍선을 배치할 영역을 선택할 수 있습니다. 드래그를 마치면 말풍선의 위치가 바뀝니다.

속성 버튼을 누르면 말풍선에 연결된 속성 묶음을 전환합니다. 기본 말풍선에서는 속성에 따라 꼬리 위치가 바뀝니다.

캐릭터 또는 같은 이미지 태그를 가진 캐릭터 그룹의 영역이나 속성을 바꾸면, 다시 바꾸거나 다음 scene 문을 실행할 때까지 유지됩니다.

현재 대사에서 영역이나 속성을 설정하면 해당 항목이 밝게 표시됩니다. 이전 대사나 기본값에서 물려받은 값이면 버튼이 흐리게 표시됩니다. 버튼을 오른쪽 클릭하면 현재 대사에서 값을 설정하지 않도록 합니다.

말풍선 유지

Ren'Py는 대사 사이에 말풍선을 유지하여 하나씩 나타나게 하고, 지울 때까지 화면에 남기는 모드를 지원합니다. 말풍선 캐릭터의 retain을 True로 설정하면 켜집니다.

define e = Character(None, image="eileen", kind=bubble, retain=True)

이후 말풍선이 계속 추가됩니다. 겹치지 않도록 각각 위치를 정해야 합니다. 말풍선 편집기의 "(clear retained bubbles)" 버튼을 누르면 가장 최근 것을 제외한 모든 말풍선이 화면에서 제거됩니다.

팁

말풍선은 번역 시스템과 같은 식별자를 사용합니다. 자세한 내용은 번역 팁을 참조하세요. 다음 경우 식별자가 바뀔 수 있습니다.

  • 대사의 텍스트를 바꾼 경우.

  • 같은 레이블 안에서 같은 텍스트의 다른 대사를 추가하거나 제거한 경우.

  • 대사 앞에 레이블을 추가하거나 제거한 경우. 단, hide 절이 있는 레이블은 추가하거나 제거해도 번역 식별자가 바뀌지 않습니다.

장면을 편집했다면 다시 플레이하여 말풍선 배치에 영향이 없는지 확인하는 것을 권장합니다.

말풍선 스크린을 편집하여 말풍선에 트랜스폼을 적용할 수 있습니다.

CTC 표시기를 말풍선 스크린의 일부로 넣으려면 Character의 ctc_position 인수에 "screen-variable"을 지정해 보세요. 다음 코드가 없다면:

showif ctc:
    add ctc

말풍선 스크린 끝에 추가해야 할 수도 있습니다. 그런 다음 캐릭터를 다음과 같이 정의합니다.

define e = Character(

None, image="eileen", kind=bubble, ctc_position="screen-variable", ctc=Transform("ctc_image.png", align=(0.5, 1.0))

설정 변수

말풍선 시스템은 bubble 네임스페이스의 변수와 bubble 스크린 및 관련 스타일로 제어합니다.

bubble 네임스페이스에는 다음 변수가 있습니다.

bubble.area_property = "window_area"

말풍선 영역을 담는 속성의 이름입니다. Character()에 전달하는 것처럼 같은 접두사 규칙을 사용합니다. 기본값 "window_area"는 영역을 window 디스플레이어블의 속성으로 전달합니다. 또 다른 유용한 값인 "show_area"는 말풍선 스크린의 area 인수로 전달합니다.

bubble.clear_retain_statements = [ "call screen", "menu",  "say", "say-centered", "say-nvl", "scene", ]

유지된 말풍선을 자동으로 지우게 하는 문들의 리스트입니다.

bubble.cols = 24

말풍선 위치와 크기 조절에 사용하는 격자의 가로 단위 크기입니다.

bubble.db_filename = "bubble.json"

말풍선 정보를 담는 데이터베이스 파일이며 game 디렉터리에 저장합니다.

bubble.default_area = (15, 1, 8, 5)

다른 영역을 지정하지 않았을 때 사용할 기본 영역입니다. (x, y, w, h) 튜플이며 각 값은 격자 칸 수입니다.

bubble.expand_area = { ... }

속성 묶음의 이름을 (left, top, right, bottom) 튜플에 매핑합니다. 여기에 항목이 있으면 지정한 픽셀 수만큼 말풍선 영역을 확장합니다.

따라서 말풍선이 제작자가 드래그한 영역보다 커집니다. 꼬리를 신경 쓰지 않고 본체 영역만 드래그할 수 있게 하며, 속성 묶음을 바꾸어 꼬리가 이동해도 텍스트 자체의 위치는 유지하려는 목적입니다.

기본값은 다음과 같습니다.

define bubble.expand_area = {
    "bottom_left" : (0, 0, 0, 22),
    "bottom_right" : (0, 0, 0, 22),
    "top_left" : (0, 22, 0, 0),
    "top_right" : (0, 22, 0, 0),
}
bubble.layer = "screens"

유지하지 않는 말풍선을 배치할 레이어입니다.

bubble.properties = { ... }

영역 이외에 말풍선을 꾸미는 데 사용할 속성들입니다. 속성 묶음의 이름을 속성과 값의 딕셔너리에 매핑합니다. 이 속성들이 캐릭터에 지정한 속성보다 우선하며 bubble 스크린에 전달됩니다.

Character()와 같은 접두사 규칙을 사용합니다. window_ 속성은 접두사를 제거하여 말풍선 스크린에서 id가 "window"인 말풍선 자체에 전달합니다. what_ 속성은 접두사를 제거하여 id가 "what"인 말풍선 텍스트에 전달합니다. who_ 속성도 같은 방식으로 캐릭터 이름에 전달합니다. show_ 속성은 말풍선 스크린 자체의 인수로 전달합니다.

새 게임의 screens.rpy에는 다음이 포함됩니다.

define bubble.frame = Frame("gui/bubble.png", 55, 55, 55, 95)

define bubble.properties = {
    "bottom_left" : {
        "window_background" : Transform(bubble.frame, xzoom=1, yzoom=1),
        "window_bottom_padding" : 27,
    },

    "bottom_right" : {
        "window_background" : Transform(bubble.frame, xzoom=-1, yzoom=1),
        "window_bottom_padding" : 27,
    },

    "top_left" : {
        "window_background" : Transform(bubble.frame, xzoom=1, yzoom=-1),
        "window_top_padding" : 27,
    },

    "top_right" : {
        "window_background" : Transform(bubble.frame, xzoom=-1, yzoom=-1),
        "window_top_padding" : 27,
    },
}

bubble.frame 변수는 bubble.properties를 쉽게 정의하기 위해서만 사용합니다. 네 가지 말풍선 스타일 각각에서 꼬리가 올바른 위치에 오도록 말풍선을 뒤집고, 꼬리 공간을 남기도록 안쪽 여백을 조정합니다.

bubble.properties_order = [ ]

말풍선 편집기에서 전환할 속성 묶음의 이름을 순서대로 나열한 리스트입니다. 이름을 지정하지 않으면 사전순으로 전환합니다.

bubble.properties_callback = None

None이 아니면 이미지 태그를 받아 그 태그에 사용할 속성 묶음 이름의 리스트나 튜플을 전환 순서대로 반환하는 함수여야 합니다. bubble.properties_order보다 우선하며 캐릭터별로 말풍선 속성 목록을 다르게 설정할 수 있습니다.

bubble.retain_layer = "screens"

유지되는 말풍선을 배치할 레이어입니다.

bubble.rows = 24

말풍선 위치와 크기 조절에 사용하는 격자의 세로 단위 크기입니다.

말풍선 스크린

기본 bubble 스크린은 screens.rpy에 있으며 기본 say 스크린과 비슷합니다.

screen bubble(who, what):
    style_prefix "bubble"

    window:
        id "window"

        if who is not None:

            window:
                id "namebox"
                style "bubble_namebox"

                text who:
                    id "who"

        text what:
            id "what"

bubble_window, bubble_what, bubble_namebox, bubble_who 등의 자체 스타일을 사용하므로 say 스크린과 분리되어 있습니다. 스타일을 직접 바꾸면 bubble.properties의 모든 묶음에 같은 속성을 지정할 필요가 없습니다.

말풍선에 효과를 적용하려면 show 및 hide 트랜스폼 이벤트를 받는 트랜스폼을 말풍선 스크린에 추가합니다. 예를 들면 다음과 같습니다.

screen bubble(who, what):
    style_prefix "bubble"

    window:
        id "window"

        at transform:
            on show:
                alpha 0.0
                linear .5 alpha 1.0

            on hide:
                linear .5 alpha 0.0

        if who is not None:

            window:
                id "namebox"
                style "bubble_namebox"

                text who:
                    id "who"

        text what:
            id "what"

게임에 말풍선 지원 추가

Ren'Py 8.1 출시 전에 만든 게임에는 말풍선 시스템에 필요한 기본 스크린과 설정이 없습니다. 두 가지 작업이 필요합니다. 먼저 다음을 다운로드합니다.

파일을 게임의 game/gui 디렉터리에 넣습니다. 그런 다음 screens.rpy 끝에 다음을 추가합니다.

## Bubble screen ###############################################################
##
## The bubble screen is used to display dialogue to the player when using
## speech bubbles. The bubble screen takes the same parameters as the say
## screen, must create a displayable with the id of "what", and can create
## displayables with the "namebox", "who", and "window" ids.
##
## https://www.renpy.org/doc/html/bubble.html#bubble-screen

screen bubble(who, what):
    style_prefix "bubble"

    window:
        id "window"

        if who is not None:

            window:
                id "namebox"
                style "bubble_namebox"

                text who:
                    id "who"

        text what:
            id "what"

style bubble_window is empty
style bubble_namebox is empty
style bubble_who is default
style bubble_what is default

style bubble_window:
    xpadding 30
    top_padding 5
    bottom_padding 5

style bubble_namebox:
    xalign 0.5

style bubble_who:
    xalign 0.5
    textalign 0.5
    color "#000"

style bubble_what:
    align (0.5, 0.5)
    text_align 0.5
    layout "subtitle"
    color "#000"

define bubble.frame = Frame("gui/bubble.png", 55, 55, 55, 95)
define bubble.thoughtframe = Frame("gui/thoughtbubble.png", 55, 55, 55, 55)

define bubble.properties = {
    "bottom_left" : {
        "window_background" : Transform(bubble.frame, xzoom=1, yzoom=1),
        "window_bottom_padding" : 27,
    },

    "bottom_right" : {
        "window_background" : Transform(bubble.frame, xzoom=-1, yzoom=1),
        "window_bottom_padding" : 27,
    },

    "top_left" : {
        "window_background" : Transform(bubble.frame, xzoom=1, yzoom=-1),
        "window_top_padding" : 27,
    },

    "top_right" : {
        "window_background" : Transform(bubble.frame, xzoom=-1, yzoom=-1),
        "window_top_padding" : 27,
    },

    "thought" : {
        "window_background" : bubble.thoughtframe,
    }
}

define bubble.expand_area = {
    "bottom_left" : (0, 0, 0, 22),
    "bottom_right" : (0, 0, 0, 22),
    "top_left" : (0, 22, 0, 0),
    "top_right" : (0, 22, 0, 0),
    "thought" : (0, 0, 0, 0),
}