대사와 서술
텍스트는 비주얼 노벨의 핵심이며 스토리 중심 게임에서도 대개 매우 중요합니다. 텍스트에는 말하는 캐릭터를 표시하는 대사와 화자가 없는 서술이 있습니다. 편의를 위해 차이가 중요하지 않은 경우에는 둘을 합쳐 대사라고 부르겠습니다. 제작자가 게임에 맞게 대사의 모양을 꾸밀 수 있는 것도 중요합니다.
Ren'Py에서는 대부분의 대사를 say 문으로 작성합니다. Character 객체로 캐릭터마다 대사의 모양을 다르게 설정할 수 있습니다.
say 문
say 문은 대사와 서술에 사용합니다. Ren'Py 스크립트에서 거의 항상 가장 자주 사용하는 문이므로 작성 부담을 최소화하는 구문을 사용합니다. 예제는 다음과 같습니다.
"이것은 서술입니다."
"에일린" "캐릭터 이름을 직접 지정한 대사입니다."
e "캐릭터 객체를 사용한 대사입니다."
"쾅!!" with vpunch
첫 번째 형식은 문자열 하나만으로 구성됩니다. 서술에 사용하는 형식이며 문자열의 내용이 서술이 됩니다.
두 번째 형식은 문자열 두 개로 구성됩니다. 첫 번째는 말하는 캐릭터의 이름이고 두 번째는 대사입니다.
세 번째 형식은 단순 표현식 뒤에 문자열을 작성합니다. 단순 표현식은 캐릭터 이름을 나타내는 문자열이나 Character 객체로 평가되어야 합니다. Character 객체이면 그 객체가 대사 표시 방식을 제어합니다.
마지막 형식은 문자열과 화면 전환을 지정하는 with 절로 구성됩니다. 이 경우 문자열을 표시하면서 동시에 화면을 흔듭니다.
say 문의 정확한 동작은 사용하는 캐릭터 객체가 제어하지만, 일반적으로 화면에 대사를 표시하고 사용자가 클릭하여 닫을 때까지 기다린 뒤 대사를 화면에서 제거합니다.
일부 문자는 Ren'Py에서 특별한 의미가 있어 대사 문자열에 그대로 사용할 수 없습니다. {는 텍스트 태그를 시작하고 [는 치환 구문을 시작합니다. 대사에 이 문자를 넣으려면 두 번 씁니다. 따옴표가 문자열을 끝내지 않도록 앞에 백슬래시를 붙여야 할 수도 있습니다. 예를 들면 다음과 같습니다.
"\"100%% 최선을 다하자!\"라고 적힌 표지판을 지나갔다."
캐릭터 객체 대신 프록시 함수를 사용할 수도 있습니다. 자세한 내용은 이 절을 참조하세요.
Character 객체 정의
Character 객체를 만들어 say 문에 사용하면 대사의 모양과 일부 동작을 바꿀 수 있습니다. define 문으로 Character를 변수에 할당하여 캐릭터를 만듭니다. 예를 들면 다음과 같습니다.
define e = Character("에일린", who_color="#c8ffc8")
이후 say 문에서 이 캐릭터를 사용할 수 있습니다.
e "안녕, 세상아."
Character는 여러 키워드 인수를 받는 Python 함수입니다. 키워드 인수들이 캐릭터의 동작을 제어합니다.
- Character(name=..., kind=adv, **args)
대사와 서술의 모양과 동작을 제어하는 Character 객체를 만들어 반환합니다.
- name
문자열이면 대사에서 사용할 캐릭터 이름입니다. name이 None이면 서술처럼 이름 표시를 생략합니다. 이름을 지정하지 않으면 kind에서 가져오며 그 밖의 경우 기본값은 None입니다.
- kind
이 Character의 기반이 되는 Character입니다. 지정하면 이 Character에 전달하지 않은 모든 인수의 기본값을
kind에 지정된 해당 인수 값에서 가져옵니다. 캐릭터 템플릿을 정의한 뒤 일부를 바꾸어 복사하는 데 사용할 수 있습니다.네임스페이스를 지정할 수도 있으며 이 경우 그 안의 'character' 변수를 kind로 사용합니다.
연결된 이미지. Character에 이미지 태그를 연결할 수 있습니다. 그러면 해당 캐릭터를 사용하는 say 문에서 그 태그의 이미지를 표시할 수 있고, 캐릭터가 말할 때 Ren'Py가 표시할 사이드 이미지를 자동으로 선택할 수도 있습니다.
- image
이 캐릭터에 연결할 이미지 태그를 나타내는 문자열입니다.
음성 태그. Character에 음성 태그를 지정하면 환경설정 스크린에서 연결된 음성 파일을 음소거하거나 재생하도록 설정할 수 있습니다.
- voice_tag
Character에 연결된 음성 파일을 'voice' 채널에서 음소거하거나 재생하도록 설정할 수 있게 하는 문자열입니다.
접두사와 접미사. 캐릭터 이름과 표시할 텍스트 앞뒤에 문자열을 붙입니다. 예를 들어 각 대사의 앞뒤에 따옴표를 추가할 수 있습니다.
- what_prefix
대사를 표시하기 전에 앞에 붙일 문자열입니다.
- what_suffix
대사를 표시하기 전에 뒤에 붙일 문자열입니다.
- who_prefix
캐릭터 이름을 표시하기 전에 앞에 붙일 문자열입니다.
- who_suffix
캐릭터 이름을 표시하기 전에 뒤에 붙일 문자열입니다.
이름 표시 변경. 이름 표시 방식을 제어하는 옵션입니다.
- dynamic
참이면 name은 Python 표현식을 담은 문자열, 함수 또는 호출 가능한 객체여야 합니다. 문자열이면 대사마다 평가한 결과를 캐릭터 이름으로 사용합니다. 그 밖의 경우에는 대사마다 함수나 호출 가능한 객체를 인수 없이 호출하여 반환값을 캐릭터 이름으로 사용합니다.
상호작용 제어. 대사 표시 여부, 상호작용 발생 여부, 표시 시 진입할 모드를 제어하는 옵션입니다.
- condition
지정하면 Python 표현식을 담은 문자열이어야 합니다. 표현식이 거짓이면 say 문을 실행하지 않은 것처럼 대사를 표시하지 않습니다.
- interact
기본값인 참이면 대사를 표시할 때마다 상호작용이 발생합니다. 거짓이면 상호작용이 발생하지 않으며 화면에 다른 요소를 더 추가할 수 있습니다.
- advance
기본값인 참이면 플레이어가 클릭하여 다음으로 진행할 수 있고 건너뛰기나 자동 진행도 동작합니다. 거짓이면 점프 하이퍼링크나 스크린 같은 다른 수단을 제공하지 않는 한 say 문을 지나갈 수 없습니다.
- callback
캐릭터가 말하는 동안 이벤트가 발생하면 호출하는 함수입니다. 자세한 내용은 캐릭터 콜백 절을 참조하세요.
클릭하여 계속. 모든 텍스트가 표시되면 사용자가 다음으로 진행하도록 안내하는 표시기를 보여 줍니다.
- ctc
더 구체적인 표시기가 지정되지 않았을 때 클릭하여 계속 표시기로 사용할 디스플레이어블입니다.
- ctc_pause
{p}나 {w} 텍스트 태그로 텍스트 표시가 멈췄을 때 클릭하여 계속 표시기로 사용할 디스플레이어블입니다.
- ctc_timedpause
{p=}나 {w=} 텍스트 태그로 텍스트 표시가 멈췄을 때 클릭하여 계속 표시기로 사용할 디스플레이어블입니다. None이면 ctc_pause의 값을 기본으로 사용합니다. ctc_pause는 표시하고 ctc_timedpause는 표시하지 않으려면
Null()을 사용합니다.- ctc_position
클릭하여 계속 표시기의 위치를 제어합니다. 다음 값을 사용할 수 있습니다.
- "nestled"
표시 중인 텍스트의 일부로서 마지막 문자 바로 뒤에 표시합니다.
- "nestled-close"
"nestled"와 비슷하지만 텍스트와 CTC 표시기 사이에서 줄을 바꿀 수 없습니다.- "fixed"
"ctc"라는 스크린이 있으면 표시합니다. 없으면 CTC 디스플레이어블을 표시하며 그 디스플레이어블의 위치 스타일 속성으로 표시기를 배치합니다.
- "screen-variable"
CTC 표시기를 표시해야 할 때 "ctc" 변수에 CTC 디스플레이어블을 설정합니다. 다음 스크린 언어와 함께 사용할 수 있습니다.
default ctc = None showif ctc: add ctc
스크린. 대사는 스크린으로 표시합니다. 이 인수들로 사용할 스크린을 선택하고 인수를 전달할 수 있습니다.
- screen
대사를 표시할 스크린의 이름입니다.
- retain
참이 아니면 대사마다 사용하지 않은 태그를 생성하고 스크린을 일시적이지 않은 방식으로 표시합니다.
renpy.clear_retain()으로 유지된 스크린을 모두 제거합니다. 거의 항상 말풍선과 함께 사용합니다.
show_로 시작하는 키워드 인수는 접두사를 제거하여 스크린에 인수로 전달합니다. 예를 들어show_myflag의 값은 스크린의myflag변숫값이 됩니다.myflag변수는 기본적으로 사용하지 않지만 사용자 정의 say 스크린에서 사용할 수 있습니다.과거 구현과의 호환을 위해 show 변수 하나는 Ren'Py 자체에서 처리합니다.
- show_layer
지정하면 say 스크린을 표시할 레이어의 이름을 나타내는 문자열이어야 합니다.
텍스트와 대사창의 스타일.
who_,what_,window_로 시작하는 키워드 인수는 접두사를 제거한 뒤 각각 캐릭터 이름, 대사 텍스트, 둘을 담는 대사창의 스타일을 지정하는 데 사용합니다.예를 들어 캐릭터에
who_color="#c8ffc8"키워드 인수를 지정하면 이름의 색상을 녹색으로 바꿉니다.window_background="frame.png"는 해당 캐릭터의 대사창 배경을 설정합니다.who_style,what_style,window_style인수로 각각 캐릭터 이름, 대사 텍스트, 대사창에 적용할 스타일 자체도 설정할 수 있습니다.config.character_id_prefixes를 설정하면 다른 디스플레이어블의 스타일도 지정할 수 있습니다. 예를 들어 기본 GUI에서는namebox_접두사의 스타일로 말하는 캐릭터의 이름을 꾸밉니다.
이미지 속성을 사용하는 say 문
캐릭터를 정의할 때 이미지 태그를 연결했다면 해당 캐릭터의 say 문에서 캐릭터 이름과 두 번째 문자열 사이에 이미지 속성을 넣을 수 있습니다.
이 형식에서는 해당 태그의 이미지가 표시 중이면 Ren'Py가 캐릭터 태그와 속성을 사용하는 show 명령을 실행합니다. 이미지가 표시 중이 아니면 사이드 이미지에 사용하도록 속성만 저장하고 이미지는 표시하지 않습니다.
예를 들어:
define e = Character("에일린", image="eileen")
label start:
show eileen concerned
e "너한테 조금 화가 났어."
e happy "그래도 금방 풀릴 거야."
다음과 같습니다.
define e = Character("에일린", image="eileen")
label start:
show eileen concerned
e "너한테 조금 화가 났어."
show eileen happy
e "그래도 금방 풀릴 거야."
위 예제에서는 concerned와 happy가 서로 교체됩니다. 하지만 concerned를 지정하지 않고도 happy가 없는 eileen으로 되돌릴 수 있습니다. show 문과 마찬가지로 속성 이름 앞에 빼기 기호(-)를 붙이면 됩니다.
예를 들면 다음과 같습니다.
define e = Character("에일린")
label start:
show eileen
e concerned "너한테 조금 화가 났어."
e happy "그거 재미있네."
e -happy "이젠 어떻게 생각해야 할지 모르겠어."
속성 목록에 @가 있으면 그 뒤의 모든 요소는 임시로만 적용되며 대사가 끝나면 되돌아갑니다.
예를 들어 다음 코드는 앞의 예제와 같습니다.
define e = Character("에일린", image="eileen")
label start:
show eileen concerned
e "너한테 조금 화가 났어."
e @ happy "그거 재미있네."
e "이젠 어떻게 생각해야 할지 모르겠어."
한 줄에서 @ 앞의 영구적인 변경과 뒤의 임시 변경을 함께 사용할 수 있습니다.
e happy @ vhappy "정말! 그럼 얘기가 완전히 달라지지."
@ 뒤에서도 빼기 기호를 사용할 수 있습니다.
e @ right -concerned "화내는 건 잠깐 미뤄 둘게..."
e "하지만!"
이 방식으로 이미지가 바뀔 때마다 화면 전환을 적용하려면 config.say_attribute_transition에 화면 전환을 설정합니다. 더 세밀하게 제어하려면 config.say_attribute_transition_callback을 사용합니다.
캐릭터 예제
다음은 캐릭터 정의 예제입니다.
# A character that has its dialogue enclosed in parenthesis.
define e = Character("에일린", what_prefix='(', what_suffix=')')
# A character that pulls its name from a variable.
define p = Character("player_name", dynamic=True)
특수 캐릭터
몇 가지 캐릭터 이름은 기본적으로 정의되어 특정 상황에서 자동으로 사용됩니다. 의도적으로 재정의하면 Ren'Py의 동작을 바꿀 수 있지만 실수로 사용하면 문제가 생길 수 있습니다.
advCharacter가 기본 kind로 사용하는 캐릭터입니다. 화면에 대사를 한 번에 하나씩 표시하도록 설정합니다.
nvl화면에 여러 줄의 텍스트를 한꺼번에 표시하는 NVL 모드로 대사를 표시하는 Character 종류입니다.
narrator캐릭터 이름이 없는 say 문에서 서술을 표시하는 데 사용하는 캐릭터입니다.
name_only캐릭터 이름을 문자열로 지정한 대사에 사용하는 캐릭터입니다. 지정한 이름의 새 캐릭터로 복사한 뒤 그 캐릭터로 대사를 표시합니다.
centered대사창 밖, 화면 정중앙에 가운데 정렬하여 텍스트를 표시하는 캐릭터입니다.
vcentered대사창 밖, 화면 정중앙에 세로쓰기 텍스트를 가운데 정렬하여 표시하는 캐릭터입니다.
extend마지막으로 말한 캐릭터가 이전 대사에 "{fast}"와 extend에 지정한 대사를 이어 붙여 말하게 하는 캐릭터입니다. 대사가 이어지는 도중 화면을 바꾸는 데 사용할 수 있습니다.
Extend는 NVL 모드를 인식하여 올바르게 처리합니다. 처음 say 문과 extend 사이에서 언어 설정이 바뀌면 제대로 동작하지 않습니다.
예를 들면 다음과 같습니다.
# Show the first line of dialogue, wait for a click, change expression, and show
# the rest.
show eileen concerned
e "가끔 슬퍼질 때가 있어."
show eileen happy
extend " 그래도 대개는 금방 털어 내!"
# Similar, but automatically changes the expression when the first line is finished
# showing. This only makes sense when the user doesn't have text speed set all the
# way up.
show eileen concerned
e "가끔 슬퍼질 때가 있어.{nw}"
show eileen happy
extend " 그래도 대개는 금방 털어 내!"
대사창 관리
Ren'Py는 대사창을 관리하는 여러 문을 제공합니다. 대사 중에는 대사창이 항상 표시되므로 이 문들은 대사 이외의 상호작용에서 대사창 표시 여부를 제어합니다.
window showwindow show 문은 대사창을 표시합니다. 선택적으로 대사창 표시에 사용할 화면 전환을 인수로 받습니다. 생략하면
config.window_show_transition을 사용합니다.window hidewindow hide 문은 대사창을 숨깁니다. 선택적으로 대사창 숨김에 사용할 화면 전환을 인수로 받습니다. 생략하면
config.window_hide_transition을 사용합니다.window auto True대사창 자동 관리를 켭니다.
config.window_auto_show에 나열된 문을 실행하기 전에 대사창을 표시합니다. 기본적으로 say 문입니다.config.window_auto_hide에 나열된 문을 실행하기 전에는 숨깁니다. 기본적으로scene,call screen, 제목이 없는menu문입니다.문만 고려하며 그에 대응하는 함수는 고려하지 않습니다.
window auto False대사창 자동 관리를 끕니다. 대사창을 자동으로 표시하거나 숨기지 않습니다.
window auto 문은 표시할 때 config.window_show_transition, 숨길 때 config.window_hide_transition을 사용합니다. window auto는 window show나 window hide로 해제됩니다.
예를 들면 다음과 같습니다.
window show # shows the window with the default transition, if any.
pause # the window is shown during this pause.
window hide # hides the window.
pause # the window is hidden during this pause.
window show dissolve # shows the window with dissolve.
pause # the window is shown during this pause.
window hide dissolve # hides the window with dissolve.
pause # the window is hidden during this pause.
window auto True
"이 대사가 나오기 전에 대사창이 자동으로 표시됩니다."
pause # the window is shown during this pause.
scene bg washington # the window is hidden before the scene change.
with dissolve
window show # Shows the window before it normally would be shown.
show eileen
with dissolve
"window show를 쓰지 않았다면 이 시점에 대사창이 표시되었을 것입니다."
대사창 관리는 "show empty window" Preference() 설정의 영향을 받습니다. 이 설정이 꺼져 있으면 위 문들은 효과가 없습니다.
인수를 사용하는 say 문
say 문 뒤에 괄호를 붙여 추가 인수를 전달할 수 있습니다. 예를 들어 다음과 같이 작성할 수 있습니다.
e "안녕, 세상아." (what_color="#8c8")
say 문의 인수는 config.say_arguments_callback이 None이 아니면 먼저 그 함수가 처리합니다. 남은 인수는 캐릭터에 전달하며 캐릭터를 정의할 때 지정한 것처럼 취급합니다. 따라서 위 예제는 대사를 녹색으로 표시합니다. _with_none 키워드는 캐릭터의 with_none 속성을 덮어씁니다.
interact 매개변수는 예외입니다. Character를 정의할 때 False로 지정했다면 interact=True를 전달해도 덮어쓰지 않으므로 상호작용이 발생하지 않습니다.
config.say_arguments_callback은 인수가 있을 때만이 아니라 say 문을 실행할 때마다 호출합니다. 캐릭터의 설정을 조건에 따라 덮어쓰는 데 유용할 수 있습니다. 예를 들면 다음과 같습니다.
init python:
def say_arguments_callback(char, *args, **kwargs):
if colorblind_mode:
kwargs["what_color"] = "#000"
return args, kwargs
define config.say_arguments_callback = say_arguments_callback
독백 모드
일부 비주얼 노벨에는 긴 서술이나 같은 캐릭터가 이어서 말하는 여러 대사 블록이 있습니다. 이때마다 캐릭터 이름과 따옴표를 반복해서 작성하는 것은 번거롭습니다.
이를 위해 Ren'Py는 독백 모드를 지원합니다. 대사를 삼중 따옴표 문자열 안에 쓰면 빈 줄을 기준으로 블록을 나누고 각 블록에 대해 별도의 say 문을 만듭니다. 다음은 서술 세 블록 뒤에 대사 세 줄이 이어지는 예제입니다.
"""
이것은 서술의 첫 번째 줄입니다. 나머지 두 줄보다 길어서
자동으로 줄바꿈됩니다.
이것은 서술의 두 번째 줄입니다.
이것은 서술의 세 번째 줄입니다.
"""
e """
이것은 대사의 첫 번째 줄입니다. 나머지 두 줄보다 길어서
자동으로 줄바꿈됩니다.
이것은 대사의 두 번째 줄입니다.
이것은 대사의 세 번째 줄입니다.
"""
인수나 속성 같은 추가 절도 사용할 수 있지만 독백의 각 대사에 모두 전달되므로 유용성이 떨어질 수 있습니다.
블록 사이의 빈 줄을 생략하려면 파일 최상위 수준에서 첫 독백 줄 앞에 rpy monologue single을 작성합니다.
이 기능을 끄고 삼중 따옴표 안의 모든 줄을 줄바꿈을 유지한 하나의 메시지로 표시하려면 rpy monologue none을 사용합니다.
character 스토어
관련 문서: 다른 이름 있는 스토어
say 문은 기본 스토어보다 먼저 character라는 스토어에서 찾습니다. 기본 스토어의 변수와 같은 이름의 캐릭터를 만들려면 다음과 같이 정의할 수 있습니다.
define character.e = Character("에일린")
이후 기본 스토어의 변수와 함께 캐릭터를 사용할 수 있습니다.
default e = 0
label start:
# This is still a terrible variable name.
$ e = 100
e "현재 에너지는 [e]단위입니다."
say 문과 충돌하지 않고 네임스페이스에서 캐릭터에 대한 가변 정보를 관리할 때 특히 유용합니다.
define character.naomi = Character("나오미 나가타", who_color="#8c8")
default naomi = PersonClass(engineering=5, max_g_force=.7) # can be an object...
define character.fred = Character("프레드 존슨", who_color="#72f")
default fred.money = 1000 # ...or a dedicated named store
default fred.rank = "Colonel"
label traded:
fred "여기 있어."
$ fred.money -= 50
$ naomi.money += 50
naomi "고마워! 내 [naomi.engineering]등급 공학 실력의 가치를 알아줄 줄 알았어."
다른 표시 방식
NVL 모드 튜토리얼: 화면 전체에 대사를 표시하는 모드입니다.
말풍선: 위치를 대화식으로 조절할 수 있는 말풍선에 대사를 표시하는 모드입니다.
함께 보기
문에 대응하는 Python 기능: 일부 단점과 제약은 있지만 여기서 설명한 기능 대부분을 Python에서 사용하는 방법입니다.
renpy.last_say(): 마지막 say 문에 대한 정보를 제공합니다.