들어가며

기본적으로 렌파이 갤러리 화면은 Gallery 설정을 따라간다.
렌파이의 갤러리 특화형 클래스를 사용해 구성하며, 사실상 UI가 이미 제공된 셈이지만 어째선지 한국말로 검색할 때 자료가 많이 없길래 기록용으로나마 렌파이 갤러리 화면 구현 방법을 적어두기로 했다.
ㅤㅤ

Gallery

렌파이 위키를 보면 갤러리 화면에 대한 설명이 잘 나와 있다.
https://www.renpy.org/doc/html/rooms.html

중요 요소

image()

image(displayables, properties)
이미지가 하나 이상의 displayable로 구성된 현재 버튼에 새 이미지를 추가한다.

show_ 로 시작하는 요소들에서 해당 접두사가 제거되고,
추가 인수로써 gallery.image_screen 화면에 전달된다.

make_button()

make_button(name, unlocked, locked=None, hover_border=None, idle_border=None, style=None, properties)
주어진 버튼 이름과 관련 이미지를 표시하는 버튼이 생성된다.

name
생성될 버튼의 이름.

unlocked
버튼이 잠금 해제되었을 때 표시되는 displayable.

locked
이 버튼이 잠겨 있을 때 표시되는 displayable.
None이면 갤러리 객체의 locked_button 필드가 대신 사용된다.

hover_border
버튼이 잠금 해제되고 포커스가 있을 때 버튼을 오버레이하는 데에 사용되는 displayable.
None이면 갤러리 객체의 hover_border 필드가 사용된다.

idle_border
이 버튼이 잠금 해제되었지만 포커스가 없을 때 오버레이하는 데에 사용되는 displayable.
None이면 갤러리 개체의 idle_border 필드가 사용된다.

style
버튼이 상속받는 스타일.
None이면 테두리 등을 상속하지 않도록 기본적으로 "빈" 스타일이 된다.

추가 인수는 생성된 버튼 개체의 스타일 속성이 된다.

기타 요소

  • transition
    이미지를 바꿀 때 사용되는 효과.

  • navigation
    true인 경우, 이미지 위에 탐색 및 슬라이드쇼 버튼을 표시한다.
    탐색 모양을 사용자 지정하려면 gallery_navigation 화면을 재정의해야 한다.
    기본 화면은 renpy/common/00gallery.rpy에 정의되어 있다.

  • span_buttons
    True인 경우 갤러리가 버튼 사이로 이동한다.

  • slideshow_delay
    갤러리가 슬라이드쇼 모드에서 이미지 사이를 이동하는 데 걸리는 시간.

  • image_screen = "_gallery"
    개별 이미지를 표시하는 데 사용되는 화면.

    locked
    True인 경우 이미지가 잠겨 있다.

    displayables
    사용자에게 표시되어야 하는 변환된 디스플레이어블 목록.

    index
    표시되는 이미지의 1-based 인덱스.

    count
    현재 버튼에 첨부된 이미지의 수.

    gallery
    이미지 갤러리 개체.
    show_를 접두사로 추가 인수를 설정할 수 있다 . (Gallery.image 및 Gallery.unlock 이미지에 대한 call.) 기본 화면은 renpy/common/00gallery.rpy 하단에 정의되어 있다.

  • Action(name)
    주어진 이름의 버튼과 관련된 이미지를 표시한다.

  • Next(unlocked=False)
    갤러리의 다음 이미지로 이동한다.

    unlocked
    true인 경우 잠금 해제된 이미지만 고려한다.

  • Previous(unlocked=False)
    갤러리의 이전 이미지로 이동한다.

    unlocked
    true인 경우 잠금 해제된 이미지만 고려한다.

  • Return(self)
    갤러리 이미지 표시를 중지한다.

  • ToggleSlideshow(self)
    슬라이드쇼 모드로 전환한다.

  • allprior(self)
    현재 버튼과 연결된 모든 이전 이미지가 잠금 해제된 경우 참이 되는 조건이다.

  • button(name)
    이름이 name인 새 버튼을 만든다.

    name
    생성되는 버튼의 이름이다.

  • condition(expression)
    표현식이 true로 평가될 때 충족되는 조건이다.

    expression
    Python 표현식을 제공하는 문자열.

  • get_fraction(name, format=u'{seen}/{total}')
    이름이 name인 버튼에 연결된, 잠금 해제된 이미지의 수와 총 이미지 수를 텍스트 문자열로 반환한다.

    format
    숫자 형식을 지정하는 데 사용되는 Python 형식 문자열. 여기에는 다음과 같이 대체할 수 있는 세 가지 값이 있다.
    1) {seen}: 본 이미지의 수.
    2) {total}: 버튼에 연결된 총 이미지 수.
    3) {locked}: 아직 잠긴 이미지의 수.

  • transform(transforms)
    등록된 마지막 이미지에 transform을 적용한다. 이미지가 가진 displayables 수와 같은 개수의 transform으로 호출해야 한다. 해당 displayables에 transform이 적용된다.
    설정된 transform이 없으면 default transform이 사용됩니다.

  • unlock(images)
    하나 이상의 이미지 이름을 인수로 사용하고, 해당 이름이 지정된 모든 이미지를 플레이어가 보았을 때 충족되는 조건이다. 이미지 이름은 문자열로 지정해야 한다.

  • unlock_image(images, properties)
    포함된 매개변수들로 이미지 호출과 잠금 해제의 효과를 한 번에 주는, 편리한 method. (show_로 시작하는 키워드 인수는 이미지로만 상속된다.) 이렇게 하면 플레이어가 이전에 보았던 이미지가 표시된다. 이미지는 이미지 이름을 제공하는 문자열로 지정해야 한다.

Gallery 사용 방법

기본 코드

init python:

   init python:

    # 1단계. 갤러리 오브젝트를 생성한다.
    g = Gallery()

    # 2단계. 갤러리에 버튼과 이미지를 추가한다.

    # 항상 잠금이 해제된 이미지가 있는 버튼.
    g.button("title")
    g.image("title")

    # 자동으로 잠금이 해제되는 이미지가 들어 있는 버튼.
    g.button("dawn")
    g.image("dawn1")
    g.unlock("dawn1")

    # 여러 개의 이미지가 연결된 버튼.
    # unlock_image를 사용하므로 .image와 .unlock을 모두 호출할 필요가 없다.
    # 첫 번째 이미지에도 transition을 적용한다.
    g.button("dark")
    g.unlock_image("bigbeach1")
    g.transform(slowpan)
    g.unlock_image("beach1 mary")
    g.unlock_image("beach2")
    g.unlock_image("beach3")

    # 이 버튼은 게임에서 잠금 해제할 이미지를 선택할 수 있는 조건을 가지고 있다.
    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")

    # 이 버튼의 마지막 이미지에는 관련된 조건이 있으므로
    # 사용자가 양쪽 끝을 모두 얻을 경우에만 잠금이 해제된다.
    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")

    # 마지막 두 버튼에는 여러 개의 사진이 동시에 표시되는 이미지가 포함되어 있다.
    # 배경에 캐릭터 아트를 구성하는 데 사용될 수 있다.
    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

# 3단계. 우리가 사용하는 갤러리 화면.
screen gallery:

    # 기본 메뉴를 대체하고 있는지 확인한다. (메뉴에 표시되는가.)
    tag menu

    # 배경을 설정한다.
    add "beach2"

    # 버튼이 놓이는 그리드.
    grid 3 3:

        xfill True
        yfill True

        # 특정 버튼을 표시하려면 make_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)


        # 이 스크린 요소는 메인 메뉴로 돌아가는 역할을 담당한다.
        # 다른 갤러리 화면으로 이동할 수도 있다.
        textbutton "Return" action Return() xalign 0.5 yalign 0.5

1단계 갤러리 오브젝트 생성

g = Gallery()

갤러리 오브젝트는 렌파이에 내장된 오브젝트인 것 같다.
(1) 이미지 잠금 여부를 처리하고, (2) 하나 이상의 이미지를 표시할 수 있는 action과, (3) 해당 action을 사용하는 버튼을 만드는 method를 제공하여, 이미지 갤러리 만들기를 지원한다는 설명에도 나와 있듯이, 비주얼 노벨에서 일러스트가 나와 그 일러스트를 수집한 후 확인할 수 있는 창에 필요한 기능을 많이 지원한다. 일러스트 습득 시 특정 일러스트가 해금되는 상황, 그리고 일러스트를 누르면 뒷면에 추가로 해금되는 특전 일러스트를 확인할 수 있는 기능이 기본적으로 들어가 있다. image method로 설정할 수 있는데, 조금 아쉬운 점은 특전 일러가 없는 경우 특전 일러 설정을 하지 않으면 이미지 버튼을 눌렀을 때 아무것도 없는 검은 화면이 나온다는 점이다. 특전 일러가 없는 경우는 고려가 안 된 것 같아 개발 방향을 수정해야 했다.

2단계 버튼과 이미지를 추가

중요 버튼

잠금 해제 조건이 있는 이미지 버튼

    g.button("end1")
    g.condition("persistent.unlock_1")
    g.image("ending1")

Gallery 오브젝트에 버튼과 이미지를 추가하고, 만족할 조건을 추가한다.
이때 조건은 지속데이터로 정의된다.

여러 버튼들

상시 잠금 해제된 이미지 버튼

    g.button("title")
    g.image("title")

Gallery 오브젝트에 버튼과 이미지를 특정 변수명으로 추가한다.

자동으로 잠금이 해제되는 이미지가 들어 있는 버튼

    g.button("dawn")
    g.image("dawn1")
    g.unlock("dawn1")

'상시 잠금 해제된 이미지 버튼'에 unlock 요소를 추가한다.
lock이 디폴트 상태이므로 unlock 코딩을 통해 잠금을 자동으로 해제시킨다.

여러 개의 이미지가 연결된 버튼

    g.button("dark")
    g.unlock_image("bigbeach1")
    g.transform(slowpan)
    g.unlock_image("beach1 mary")
    g.unlock_image("beach2")
    g.unlock_image("beach3")

unlock_image를 사용하므로 .image와 .unlock을 모두 호출할 필요가 없다.
첫 번째 이미지에도 transition을 적용한다.

잠금 해제할 이미지를 선택할 수 있는 조건이 있는 버튼

    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")

persistent.unlock_1 or persistent.unlock_2 둘 중 하나가 True면, 엔딩에 따라 얻을 수 있는 이미지 구성이 달라진다.

사용자가 양끝을 모두 얻을 경우에만 잠금이 해제되는 버튼

    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")

각 엔딩 일러스트 해금 조건에 g.condition("persistent.unlock_3 and persistent.unlock_4") 부분이 추가되어, 엔딩을 다 봐야만이 이미지를 얻을 수 있다.

여러 개의 사진이 동시에 표시되는 이미지 버튼

    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

3단계. 갤러리 화면 설정

screen gallery:

    # 기본 메뉴를 대체하고 있는지 확인한다. (메뉴에 표시되는가.)
    tag menu

    # 배경을 설정한다.
    add "beach2"

    # 버튼이 놓이는 그리드.
    grid 3 3:

        xfill True
        yfill True

        # 특정 버튼을 표시하려면 make_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)


        # 이 스크린 요소는 메인 메뉴로 돌아가는 역할을 담당한다.
        # 다른 갤러리 화면으로 이동할 수도 있다.
        textbutton "Return" action Return() xalign 0.5 yalign 0.5
  1. tag menu: 기본 메뉴에 표시가 될 수 있도록 등록하는 절차다.
  2. add "beach2": 배경을 설정한다. (이름은 확장자까지 붙여서 설정하자.)
  3. grid 3 3: 버튼들이 놓이는 그리드. 3*3 행렬이고, 만약 덜 채워지거나 더 채워지면 오류가 나기 때문에 꼭 맞는 수만큼 써야 한다.
  4. add g.make_button("dark", "gal-dark.png", xalign=0.5, yalign=0.5):
    버튼 명을 맨 앞에 설정하고, 그 다음에 버튼을 눌렀을 때 보이는 이미지를 설정한다. 버튼을 누르기 전에 그리드에 나열되는 디폴트 이미지는 g.locked_button = "locked.png"처럼, 따로 설정할 수 있다. 버튼을 눌렀을 때 버튼이 뒤집히며 배경에 큰 일러스트가 뜨는 형태로 뜰 텐데, 결국 갤러리에 버튼 하나를 구성하려면 locked.png를 제외하고, 최소 3개의 이미지가 필요하다는 사실을 알 수 있다. 썸네일 이미지, 버튼 클릭 시 뒤집힌 뒷면 이미지, 버튼 클릭 후 공개되는 특전 일러스트

나오며

렌파이의 갤러리 기능을 어떻게 쓸 수 있는지에 대해 알아보았다.
기본적이 코드는 렌파이 위키에서 제공하는 것을 많이 쓰는 모양이다.
불편한 점은 버튼을 눌렀을 때 뒤집히지 않는 방법은 찾을 수 없었다는 것이다.
transition을 바꾸면 될까? 잘은 모르겠지만 그게 디폴트가 아니라는 점이 불편하다.
아이콘과 일러스트를 따로 구비해야 하는 방법이라 소규모 게임 만들 때에는 갤러리 사용이 힘들다는 단점이 있었다.

참고 레퍼런스

Renpy gallery tutorial
https://dirchansky.com/freetalk/renpy-gallery-tutorial

A Quick and Dirty Guide to In-Game Achievements in Ren’Py
https://birdrobot.tumblr.com/post/139590693177/a-quick-and-dirty-guide-to-in-game-achievements-in

0개의 댓글