이미지 갤러리, 음악 감상실, 다시 보기 액션
이미지 갤러리
이미지 갤러리는 플레이어가 이미지의 잠금을 해제하고 감상할 수 있는 스크린입니다. 스크린에는 하나 이상의 버튼이 연결되고 각 버튼에는 하나 이상의 이미지가 연결됩니다. 버튼과 이미지에는 잠금 해제 여부를 결정하는 조건도 있습니다.
이미지 갤러리는 Gallery 클래스의 인스턴스로 관리합니다. 하나의 인스턴스를 여러 이미지 갤러리 스크린에서 공유할 수 있습니다.
갤러리에는 하나 이상의 버튼이, 각 버튼에는 하나 이상의 이미지가, 각 이미지에는 하나 이상의 디스플레이어블이 연결됩니다. 버튼과 이미지에는 조건을 지정할 수 있습니다. 버튼에 연결된 모든 조건을 만족하고 그 버튼의 이미지 중 하나 이상이 잠금 해제되면 버튼의 잠금이 해제됩니다. 이미지는 연결된 모든 조건을 만족하면 잠금 해제됩니다.
이미지 갤러리 제작은 다음 네 단계로 이루어집니다.
Gallery 인스턴스를 만듭니다.
갤러리에 버튼과 이미지를 추가하고, 해당 버튼과 이미지의 잠금 해제 여부를 결정할 조건도 추가합니다. 이 과정도 여러 단계로 나뉩니다.
Gallery.button()을 호출하여 새 버튼을 선언합니다.필요하면
Gallery.unlock()또는Gallery.condition()을 호출하여 버튼에 잠금 해제 조건을 하나 이상 추가합니다.하나 이상의 디스플레이어블을 인수로
Gallery.image()를 호출하여 이미지를 선언합니다. 편의 메서드Gallery.unlock_image()를 대신 호출해도 됩니다.필요하면
Gallery.transform()을 호출하여 디스플레이어블에 트랜스폼을 연결합니다.필요하면
Gallery.unlock(),Gallery.condition()또는Gallery.allprior()를 호출하여 이미지에 잠금 해제 조건을 하나 이상 추가합니다.
3~5단계를 반복하면 버튼에 이미지를 더 추가할 수 있고, 다섯 단계 전체를 반복하면 갤러리에 버튼을 더 추가할 수 있습니다.
이미지 갤러리 스크린을 만듭니다. 배경을 표시하고, 다른 이미지 갤러리로 이동하거나 메인 메뉴 또는 추가 콘텐츠 메뉴로 돌아갈 수 있는 탐색 수단을 포함해야 합니다.
메인 메뉴 또는 추가 콘텐츠 메뉴에 이미지 갤러리 스크린을 여는 기능을 추가합니다.
예제는 다음과 같습니다.
init python:
# Step 1. Create the gallery object.
g = Gallery()
# Step 2. Add buttons and images to the gallery.
# A button with an image that is always unlocked.
g.button("title")
g.image("title")
# A button that contains an image that automatically unlocks.
g.button("dawn")
g.image("dawn1")
g.unlock("dawn1")
# This button has multiple images associated with it. We use unlock_image
# so we don't have to call both .image and .unlock. We also apply a
# transform to the first image.
g.button("dark")
g.unlock_image("bigbeach1")
g.transform(slowpan)
g.unlock_image("beach1 mary")
g.unlock_image("beach2")
g.unlock_image("beach3")
# This button has a condition associated with it, allowing the game
# to choose which images unlock.
g.button("end1")
g.condition("persistent.unlock_1")
g.image("transfer")
g.image("moonpic")
g.image("girlpic")
g.image("nogirlpic")
g.image("bad_ending")
g.button("end2")
g.condition("persistent.unlock_2")
g.image("library")
g.image("beach1 nomoon")
g.image("bad_ending")
# The last image in this button has an condition associated with it,
# so it will only unlock if the user gets both endings.
g.button("end3")
g.condition("persistent.unlock_3")
g.image("littlemary2")
g.image("littlemary")
g.image("good_ending")
g.condition("persistent.unlock_3 and persistent.unlock_4")
g.button("end4")
g.condition("persistent.unlock_4")
g.image("hospital1")
g.image("hospital2")
g.image("hospital3")
g.image("heaven")
g.image("white")
g.image("good_ending")
g.condition("persistent.unlock_3 and persistent.unlock_4")
# The final two buttons contain images that show multiple pictures
# at the same time. This can be used to compose character art onto
# a background.
g.button("dawn mary")
g.unlock_image("dawn1", "mary dawn wistful")
g.unlock_image("dawn1", "mary dawn smiling")
g.unlock_image("dawn1", "mary dawn vhappy")
g.button("dark mary")
g.unlock_image("beach2", "mary dark wistful")
g.unlock_image("beach2", "mary dark smiling")
g.unlock_image("beach2", "mary dark vhappy")
# The transition used when switching images.
g.transition = dissolve
# Step 3. The gallery screen we use.
screen gallery:
# Ensure this replaces the main menu.
tag menu
# The background.
add "beach2"
# A grid of buttons.
grid 3 3:
xfill True
yfill True
# Call make_button to show a particular button.
add g.make_button("dark", "gal-dark.png", xalign=0.5, yalign=0.5)
add g.make_button("dawn", "gal-dawn.png", xalign=0.5, yalign=0.5)
add g.make_button("end1", "gal-end1.png", xalign=0.5, yalign=0.5)
add g.make_button("end2", "gal-end2.png", xalign=0.5, yalign=0.5)
add g.make_button("end3", "gal-end3.png", xalign=0.5, yalign=0.5)
add g.make_button("end4", "gal-end4.png", xalign=0.5, yalign=0.5)
add g.make_button("dark mary", "gal-dark_mary.png", xalign=0.5, yalign=0.5)
add g.make_button("dawn mary", "gal-dawn_mary.png", xalign=0.5, yalign=0.5)
add g.make_button("title", "title.png", xalign=0.5, yalign=0.5)
# The screen is responsible for returning to the main menu. It could also
# navigate to other gallery screens.
textbutton "돌아가기" action Return() xalign 0.5 yalign 0.5
4단계의 구현은 게임 구조에 따라 달라지지만, 한 가지 방법은 다음 줄을:
textbutton "갤러리" action ShowMenu("gallery")
메인 메뉴 스크린에 추가하는 것입니다.
- class Gallery
이미지 잠금을 관리하고, 하나 이상의 이미지를 표시하는 액션과 해당 액션을 사용하는 버튼 생성 메서드를 제공하여 이미지 갤러리 제작을 지원하는 클래스입니다.
- enter_transition
갤러리 버튼에 연결된 첫 이미지를 표시할 때 사용하는 화면 전환입니다.
- intra_transition
갤러리 버튼에 연결된 이미지 중 첫 번째 이후의 이미지를 표시할 때 사용하는 화면 전환입니다.
- exit_transition
갤러리 버튼의 마지막 이미지에서 갤러리 스크린으로 돌아갈 때 사용하는 화면 전환입니다.
- transition
enter_transition, intra_transition, exit_transition 중 설정되지 않은 항목이 있으면 대신 사용합니다.
- locked_button
make_button이 잠긴 버튼에 사용하는 기본 디스플레이어블입니다.
- hover_border
make_button이 사용하는 기본 hover 테두리입니다.
- idle_border
make_button이 사용하는 기본 idle 테두리입니다.
- unlocked_advance
true이면 잠금 해제된 이미지만 차례로 표시합니다.
true이면 이미지 위에 탐색 버튼과 슬라이드 쇼 버튼을 표시합니다.
탐색 UI의 외형을 바꾸려면 gallery_navigation 스크린을 재정의하세요. 기본 스크린은 renpy/common/00gallery.rpy에 정의되어 있습니다.
- span_buttons
true이면 버튼 사이를 넘어가며 표시합니다.
- slideshow_delay
슬라이드 쇼 모드에서 다음 이미지로 넘어가기까지의 시간입니다.
- image_screen = "_gallery"
이 갤러리의 개별 이미지를 표시하는 스크린입니다. 다음 키워드 인수를 전달받습니다.
- locked
이미지가 잠겨 있으면 True입니다.
- displayables
사용자에게 표시할 트랜스폼 적용 후 디스플레이어블 목록입니다.
- index
현재 표시하는 이미지의 인덱스이며 1부터 시작합니다.
- count
현재 버튼에 연결된 이미지 수입니다.
- gallery
이미지 갤러리 객체입니다.
Gallery.image와 Gallery.unlock image를 호출할 때 show_ 접두사를 붙여 추가 인수를 제공할 수 있습니다.
기본 스크린은 renpy/common/00gallery.rpy의 맨 아래에 정의되어 있습니다.
- Action(name)
지정한 이름의 버튼에 연결된 이미지를 표시하는 액션입니다.
- Next(unlocked=False)
갤러리의 다음 이미지로 이동합니다.
- unlocked
true이면 잠금 해제된 이미지만 대상으로 합니다.
- Previous(unlocked=False)
갤러리의 이전 이미지로 이동합니다.
- unlocked
true이면 잠금 해제된 이미지만 대상으로 합니다.
- Return()
갤러리 이미지 표시를 종료합니다.
- ToggleSlideshow()
슬라이드 쇼 모드를 전환합니다.
- allprior()
현재 버튼에 연결된 이전 이미지가 모두 잠금 해제되었으면 참인 조건입니다.
- button(name)
name이라는 새 버튼을 만듭니다.
- name
만들 버튼의 이름입니다.
- condition(expression)
표현식의 평가 결과가 참이면 충족되는 조건입니다.
- expression
Python 표현식을 나타내는 문자열입니다.
- get_fraction(name, format='{seen}/{total}')
name 버튼의 잠금 해제된 이미지 수와 전체 이미지 수를 나타내는 텍스트 문자열을 반환합니다. name이 None이면 모든 버튼에 대한 같은 정보를 반환합니다.
- format
숫자 서식을 지정하는 Python 형식 문자열입니다. 다음 세 값을 치환할 수 있습니다.
- {seen}
이미 감상한 이미지 수입니다.
- {total}
버튼의 전체 이미지 수입니다.
- {locked}
아직 잠겨 있는 이미지 수입니다.
- image(*displayables, **properties)
현재 버튼에 새 이미지를 추가합니다. 이미지는 하나 이상의 디스플레이어블로 구성됩니다.
show_로 시작하는 속성은 접두사를 제거한 뒤 gallery.image_screen 스크린에 추가 키워드 인수로 전달합니다.
다음 키워드 인수 하나를 받습니다.
- movie
디스플레이어블 중 소리가 있는 동영상이 있으면 true로 설정해야 합니다. 화면 전환 중 해당 동영상을 숨깁니다.
- make_button(name, unlocked, locked=None, hover_border=None, idle_border=None, style=None, **properties)
지정한 이름의 버튼에 연결된 이미지를 표시하는 버튼을 만듭니다.
- name
만들 버튼의 이름입니다.
- unlocked
버튼의 잠금이 해제되었을 때 표시할 디스플레이어블입니다.
- locked
버튼이 잠겨 있을 때 표시할 디스플레이어블입니다. None이면 갤러리 객체의 locked_button 필드를 대신 사용합니다.
- hover_border
버튼의 잠금이 해제되어 있고 포커스가 있을 때 위에 덧씌울 디스플레이어블입니다. None이면 갤러리 객체의 hover_border 필드를 사용합니다.
- idle_border
버튼의 잠금이 해제되어 있지만 포커스가 없을 때 위에 덧씌울 디스플레이어블입니다. None이면 갤러리 객체의 idle_border 필드를 사용합니다.
- style
버튼이 상속할 스타일입니다. None이면 테두리 등을 상속하지 않도록 "empty" 스타일을 기본값으로 사용합니다.
추가 키워드 인수는 생성한 버튼 객체의 스타일 속성이 됩니다.
- transform(*transforms)
마지막으로 등록한 이미지에 트랜스폼을 적용합니다. 이미지의 디스플레이어블 수와 같은 수의 트랜스폼을 전달해야 합니다. 각 트랜스폼은 대응하는 디스플레이어블에 적용됩니다.
트랜스폼이 None이면 기본 트랜스폼을 사용합니다.
- unlock(*images)
하나 이상의 이미지 이름을 인수로 받으며, 플레이어가 지정된 이미지를 모두 보았으면 충족되는 조건입니다. 이미지 이름은 문자열로 지정해야 합니다.
- unlock_image(*images, **properties)
같은 매개변수로 image와 unlock을 호출하는 것과 같은 편의 메서드입니다. (
show_로 시작하는 키워드 인수는 image에만 전달합니다.) 이미 본 이미지라면 표시합니다.이미지는 이미지 이름을 나타내는 문자열로 지정해야 합니다.
음악실
음악실은 사용자가 게임의 음악 트랙을 선택하여 재생할 수 있는 스크린입니다. 게임을 처음 시작할 때 트랙은 잠겨 있을 수 있으며, 게임을 플레이하면서 해당 음악을 들으면 잠금이 해제됩니다.
음악실은 MusicRoom 클래스의 인스턴스로 관리합니다. 한 게임에 여러 인스턴스를 만들어 음악실을 여러 개 둘 수 있습니다. 음악실 제작은 다음 네 단계로 이루어집니다.
MusicRoom 인스턴스를 만듭니다. 생성자에는 음악을 재생할 채널과 페이드아웃 및 페이드인 시간을 제어하는 매개변수가 있습니다.
인스턴스에 음악 파일을 추가합니다.
MusicRoom 인스턴스로 버튼, 이미지 버튼 또는 핫스폿의 액션을 만드는 스크린을 제작합니다. 이 액션들로 특정 트랙, 다음 트랙 또는 이전 트랙을 선택하거나 음악을 멈추고 시작할 수 있습니다.
사용하는 액션은 MusicRoom 인스턴스의 멤버입니다. 인스턴스 이름이
mr이면 재생 액션은mr.Play("track1.ogg")처럼 사용합니다.메인 메뉴나 추가 콘텐츠 메뉴에 음악실 스크린을 추가합니다.
예제는 다음과 같습니다.
init python:
# Step 1. Create a MusicRoom instance.
mr = MusicRoom(fadeout=1.0)
# Step 2. Add music files.
mr.add("track1.ogg", always_unlocked=True)
mr.add("track2.ogg")
mr.add("track3.ogg")
# Step 3. Create the music room screen.
screen music_room:
tag menu
frame:
has vbox
# The buttons that play each track.
textbutton "트랙 1" action mr.Play("track1.ogg")
textbutton "트랙 2" action mr.Play("track2.ogg")
textbutton "트랙 3" action mr.Play("track3.ogg")
null height 20
# Buttons that let us advance tracks.
textbutton "다음" action mr.Next()
textbutton "이전" action mr.Previous()
null height 20
# The button that lets the user exit the music room.
textbutton "메인 메뉴" action ShowMenu("main_menu")
# Start the music playing on entry to the music room.
on "replace" action mr.Play()
# Restore the main menu music upon leaving.
on "replaced" action Play("music", "track1.ogg")
4단계의 구현은 게임 구조에 따라 달라지지만, 한 가지 방법은 다음 줄을:
textbutton "음악 감상실" action ShowMenu("music_room")
메인 메뉴 스크린에 추가하는 것입니다.
Preferences() 함수, 특히 Preferences("music volume")을 사용하면 음악실 스크린에 볼륨 슬라이더를 넣을 수 있습니다.
- class MusicRoom(channel='music', fadeout=0.0, fadein=0.0, loop=True, single_track=False, shuffle=False, stop_action=None)
사용자가 잠금을 해제할 수 있는 곡 목록과 목록 항목을 순서대로 재생하는 액션을 제공하는 음악실입니다.
- channel
이 음악실에서 사용할 채널입니다.
- fadeout
트랙을 바꿀 때 이전 음악을 페이드아웃하는 시간이며 단위는 초입니다.
- fadein
트랙을 바꿀 때 새 음악을 페이드인하는 시간이며 단위는 초입니다.
- loop
재생 목록 끝에 도달했을 때 반복할지 멈출지 결정합니다.
- single_track
true이면 트랙 하나만 재생합니다. loop가 true이면 그 트랙을 반복하고, 아니면 트랙이 끝날 때 재생을 멈춥니다.
- shuffle
true이면 트랙을 섞어 무작위 순서로 재생합니다. false이면 MusicRoom에 추가한 순서대로 재생합니다.
- stop_action
음악이 멈추면 실행할 액션입니다.
single_track과 shuffle은 서로 충돌하므로 한 번에 하나만 true여야 합니다. (이 속성들을 설정하는 액션은 이 제약을 적용합니다.)
- Next()
재생 목록에서 다음으로 잠금 해제된 파일을 재생하는 액션입니다.
- Play(filename=None)
음악실 재생을 시작하는 액션입니다. filename을 지정하면 해당 파일을 재생합니다. 그렇지 않으면 현재 파일이 잠금 해제되어 있을 경우 처음부터 다시 재생하고, 아니면 첫 파일을 재생합니다.
filename을 지정한 경우, 이 액션을 사용하는 버튼은 filename이 잠겨 있는 동안 비활성화되며 filename을 재생하는 동안 선택 상태가 됩니다.
- Previous()
재생 목록에서 이전의 잠금 해제된 파일을 재생하는 액션입니다.
- RandomPlay()
잠금 해제된 음악 트랙을 무작위로 선택하여 재생을 시작하는 액션입니다.
- SetLoop(value)
loop 속성의 값을 설정하는 액션입니다.
- SetShuffle(value)
shuffle 속성의 값을 설정하는 액션입니다.
- SetSingleTrack(value)
single_track 속성의 값을 설정하는 액션입니다.
- Stop()
음악을 멈추는 액션입니다.
- ToggleLoop()
loop 속성의 값을 전환하는 액션입니다.
- TogglePause()
음악이 재생 중이면 상황에 따라 일시 정지하거나 일시 정지를 해제합니다.
음악이 일시 정지되어 있으면 이 버튼이 선택 상태가 됩니다.
- TogglePlay()
현재 재생 중인 음악이 없으면 첫 번째 잠금 해제된 트랙을 재생합니다. 재생 중이면 현재 음악을 멈춥니다.
어떤 음악이든 재생 중이면 이 버튼이 선택 상태가 됩니다.
- ToggleShuffle()
shuffle 속성의 값을 전환하는 액션입니다.
- ToggleSingleTrack()
single_track 속성의 값을 전환하는 액션입니다.
- add(filename, always_unlocked=False, action=None)
음악 파일 filename을 이 음악실에 추가합니다. 음악실은 잠금 해제된 파일을 추가된 순서대로 재생합니다.
- always_unlocked
true이면 음악 파일은 항상 잠금 해제 상태입니다. 게임에서 아직 재생하지 않은 파일도 음악실에 표시할 수 있습니다.
- action
이 파일을 재생할 때 호출할 액션 또는 액션 목록입니다.
예를 들어 재생 중인 파일에 맞춰 스크린, 배경, 설명을 변경하는 데 사용할 수 있습니다.
- is_unlocked(filename)
파일이 잠금 해제되었거나 항상 잠금 해제 상태이면 true를 반환하고, 아직 잠겨 있으면 false를 반환합니다.
리플레이
Ren'Py는 메인 메뉴나 게임 메뉴에서 특정 장면을 다시 플레이하는 기능도 제공합니다. 플레이어가 중요한 장면을 반복할 수 있는 “장면 갤러리” 또는 회상 갤러리를 만들 때 사용할 수 있습니다. 장면이 끝나면 리플레이를 시작한 곳으로 돌아갑니다.
Start() 액션으로도 장면을 다시 플레이할 수 있습니다. 두 방식의 차이는 다음과 같습니다.
리플레이는 어느 스크린에서나 시작할 수 있지만 Start는 메인 메뉴 또는 메인 메뉴에서 표시한 스크린에서만 사용할 수 있습니다.
리플레이가 끝나면 이를 호출한 지점으로 제어가 돌아갑니다. 예를 들어 메인 메뉴나 게임 메뉴 안일 수 있습니다. 게임 진행 중 리플레이를 호출했다면 게임 상태가 보존됩니다.
리플레이 모드에서는 저장할 수 없습니다. 저장이 필요한 다시 로드 기능도 비활성화됩니다.
리플레이 모드에서
renpy.end_replay()를 호출하면 리플레이를 종료합니다. 일반 모드에서는 end_replay가 아무것도 하지 않습니다.
리플레이 모드를 활용하려면 장면을 레이블로 시작하고 renpy.end_replay() 호출로 끝내야 합니다. 일반 모드와 리플레이 모드에서 레이어나 변수의 상태는 매우 다를 수 있으므로 특정 상태를 가정해서는 안 됩니다. (리플레이 진입 시 scope 매개변수로 설정한 변수는 예외입니다.) 리플레이를 시작하면 검은 화면에서 레이블을 호출합니다.
예를 들면 다음과 같습니다.
"그리고 마침내, 나는 그 마법사를 직접 만났다."
label meaning_of_life:
scene revelation
"마법사" "인생의 의미가 뭐냐고?"
"마법사" "나도 그걸 오래도록 깊이 생각해 봤지. 바로 그 질문을 두고
참으로 오랜 시간을 고민했네."
"마법사" "그래서 내 답은 말이지, 인생 그 자체의 의미는
바로..."
"마법사" "마흔셋이라네."
$ renpy.end_replay()
"마법사" "뭐, 대충 그런 뜻이지."
이렇게 장면을 정의하면 Replay 액션으로 리플레이를 시작할 수 있습니다.
textbutton "인생의 의미" action Replay("meaning_of_life")
리플레이 모드에서 사용하는 스토어 변수는 하나입니다.
- _in_replay
리플레이 모드에서는 리플레이를 시작한 레이블로 설정됩니다. 호출한 쪽의 레이블이 아니라 호출된 레이블입니다. 리플레이 모드가 아니면 None입니다.
또한 리플레이 모드에 들어갈 때는 config.enter_replay_transition을, 나올 때는 config.exit_replay_transition을 사용합니다. config.replay_scope는 리플레이 진입 시 초기화된 스토어에 변수를 추가하며, 기본적으로 _game_menu_screen을 설정하여 리플레이에서 오른쪽 클릭 시 환경설정 스크린을 표시하도록 합니다.
리플레이 모드에서는 다음 변수와 액션을 사용합니다.
- EndReplay(confirm=True)
현재 리플레이를 종료합니다.
- confirm
true이면 리플레이를 끝내기 전에 사용자에게 확인을 요청합니다.
- Replay(label, scope={}, locked=None)
label을 리플레이로 시작하는 액션입니다.
- scope
변수 이름을 값에 대응시키는 딕셔너리입니다. 리플레이 진입 시 이 변수들을 설정합니다.
- locked
true이면 액션이 비활성화되며 실행해도 아무것도 하지 않습니다. false이면 정상적으로 동작합니다. None이면 어느 플레이에서도 해당 레이블을 본 적이 없는 경우 잠깁니다.
- renpy.call_replay(label, scope={})
레이블을 회상으로 호출합니다.
scope 인수는 회상 컨텍스트에서 변수의 초기값을 설정하는 데 사용합니다.
- renpy.end_replay()
리플레이 중이면 즉시 종료합니다. 그렇지 않으면 아무것도 하지 않습니다.