디스플레이어블

디스플레이어블은 사용자에게 표시할 수 있는 객체입니다. Ren'Py 디스플레이어블은 다양한 방식으로 사용할 수 있습니다.

  • image 문으로 이미지 이름에 할당합니다.

  • 스크린 언어의 add 문으로 스크린에 추가합니다.

  • 특정 config 변수에 할당합니다.

  • 특정 스타일 속성에 할당합니다.

Ren'Py 함수나 변수가 디스플레이어블을 요구할 때 다음과 같은 값을 전달할 수 있습니다.

  • 아래 함수 중 하나를 호출하여 만든 Displayable 유형의 객체.

  • 콜론 :이 들어 있는 문자열. 드문 경우이지만 아래의 디스플레이어블 접두사 절을 참조하세요.

  • 마침표 .가 들어 있는 문자열. Image()가 파일명으로 해석합니다.

  • 색상. "#rgb", "#rgba", "#rrggbb", "#rrggbbaa" 형식의 16진수 색상 문자열, Color 또는 (r, g, b, a) 튜플로 지정할 수 있습니다. 튜플의 각 요소는 0에서 255 사이의 정수입니다. 색상은 Solid()에 전달됩니다.

  • 이미지 이름. 그 밖의 문자열은 image 문으로 정의하거나 images 디렉터리에서 자동 정의한 이미지에 대한 참조로 해석합니다.

  • 리스트. 리스트를 전달하면 각 항목을 아래에서 설명하는 방식으로 확장한 뒤 파일명이나 이미지 이름과 일치하는지 확인합니다. 일치하면 확장을 멈추고 해당 항목을 위 규칙에 따라 처리합니다.

문자열에는 "eileen [mood]"나 "eileen_[outfit]_[mood].png"처럼 대괄호를 사용하는 치환 구문이 하나 이상 들어 있을 수 있습니다. 이런 문자열을 지정하면 동적 이미지가 생성됩니다. 동적 이미지는 say 문이나 메뉴 같은 각 상호작용의 시작 시 텍스트 보간을 수행합니다. 결과 문자열은 위 규칙에 따라 처리합니다.

문자열에 "[prefix_]"가 있으면 현재 디스플레이어블에 연결된 각 스타일 접두사로 치환합니다.

이미지

가장 자주 사용하는 디스플레이어블은 디스크에서 파일을 읽어 표시하는 Image입니다. 사용 빈도가 높으므로 디스플레이어블이 필요한 곳에 파일명을 나타내는 문자열을 지정하면 Image가 자동으로 생성됩니다. Image를 직접 사용해야 하는 경우는 스타일 속성을 가진 이미지를 만들 때뿐입니다.

Image(filename, *, optimize_bounds=True, oversample=1, dpi=96, mipmap=None, **properties)

파일에서 이미지를 읽습니다. filename은 파일명을 나타내는 문자열입니다.

filename

확장자를 포함한 이미지 파일명이어야 합니다.

optimize_bounds

참이면 불투명 픽셀의 경계 상자에 들어가는 이미지 영역만 GPU 메모리에 로드합니다. 이미지를 셰이더의 입력으로 사용하는 경우에만 False로 설정할 필요가 있습니다.

oversample

1보다 크면 논리적 크기보다 많은 픽셀을 가진 오버샘플링 이미지로 취급합니다. 예를 들어 이미지 파일이 2048x2048이고 oversample이 2이면 배치할 때 1024x1024 이미지로 취급합니다.

dpi

SVG 이미지의 DPI입니다. 기본값은 96이며 값을 늘리면 SVG를 더 크게, 줄이면 더 작게 렌더링합니다.

mipmap

"auto"이면 게임을 기본 크기의 75% 미만으로 축소할 때만 밉맵을 생성합니다. True이면 항상 생성하고, False이면 생성하지 않습니다. None이면 config.mipmap에서 기본값을 가져옵니다.

# These two lines are equivalent.
image logo = "logo.png"
image logo = Image("logo.png")

# Using Image allows us to specify a default position as part of
# an image.
image logo right = Image("logo.png", xalign=1.0)

다음 네 이미지 파일 형식을 권장합니다.

  • AVIF

  • WEBP

  • PNG

  • JPG

벡터 이미지 파일 형식은 다음을 권장합니다.

  • SVG

애니메이션이 없는 GIF와 BMP 파일도 지원하지만 현대적인 게임에서는 사용하지 않는 것이 좋습니다.

디스크 파일에서 이미지를 읽고 화면에 그릴 수 있도록 디코딩하는 데는 상당한 시간이 걸립니다. 10분의 1초나 100분의 1초 단위이지만 적절한 프레임률을 방해하고 사용자가 불편함을 느끼기에 충분한 시간입니다.

Image는 크기가 고정되어 있고 입력, 게임 상태, 사용할 수 있는 영역의 크기에 따라 바뀌지 않으므로 필요해지기 전에 미리 읽어 이미지 캐시라는 메모리 영역에 저장할 수 있습니다. 디코딩되어 캐시에 들어간 Image는 화면에 빠르게 그릴 수 있습니다.

Ren'Py는 이후 사용할 이미지를 예측하여 사용 전에 이미지 캐시에 로드하려고 합니다. 다른 이미지를 넣을 캐시 공간이 필요하면 더 이상 사용하지 않는 이미지를 제거합니다.

Ren'Py는 기본적으로 화면 8개 분량까지 이미지 데이터를 예측 캐싱합니다. 화면이 800x600이면 화면 한 개 분량은 800x600 이미지 하나, 400x600 이미지 두 개 등에 해당합니다. config.image_cache_size 설정 변수로 바꿀 수 있습니다.

정확한 사용량은 구현 세부 사항에 따라 다르고 상당한 오버헤드도 있지만, 대략적으로 이미지 캐시의 픽셀 하나당 주 메모리 4바이트와 비디오 메모리 4바이트를 사용합니다.

SVG 이미지

Ren'Py는 NanoSVG 라이브러리로 많은 SVG 1.0 이미지를 지원합니다. 지원하지 않는 기능은 다음과 같습니다.

  • 텍스트 요소는 무시합니다. 텍스트를 경로로 변환하면 렌더링됩니다.

  • 포함된 비트맵은 무시합니다.

  • 스크립트는 무시합니다.

  • 애니메이션은 무시합니다.

NanoSVG가 지원하는 기능 목록은 여기에서 볼 수 있습니다.

SVG 이미지에서 제대로 렌더링되지 않는 요소는 모두 경로로 변환하는 것을 권장합니다.

Ren'Py는 가상 화면이 96dpi인 것으로 간주하여 SVG 이미지를 렌더링합니다. 창을 확대하거나 축소하면 SVG 이미지도 그에 맞게 확대하거나 축소하며, 오버샘플링으로 올바른 가상 크기에 렌더링합니다.

이를 통해 별도로 크기를 조절하지 않으면 SVG를 선명하게 렌더링합니다.

이미지형 디스플레이어블

이 디스플레이어블들은 화면의 사각형 영역을 차지하고 입력에 반응하지 않으므로 이미지형이라고 부릅니다. 영역을 채우도록 크기가 변하거나(Frame, Tile, Solid), 사용자가 크기를 지정할 수 있다는 점(Composite, Crop, Null)에서 일반 이미지와 다릅니다. 이미지 조작기는 아닙니다.

이미지형 디스플레이어블은 위치 스타일 속성을 받습니다.

class AlphaMask(child, mask, invert=False, **properties)

이 디스플레이어블은 child의 색상을 사용하고, 알파 채널은 child와 mask의 알파 채널을 곱하여 얻습니다. 따라서 결과는 child와 색상이 같으며, child나 mask 중 하나라도 투명한 부분은 투명합니다. child와 mask가 모두 불투명한 부분은 불투명합니다.

child와 mask에는 어떤 디스플레이어블이든 지정할 수 있습니다. AlphaMask의 크기는 child와 같습니다. invert 매개변수로 마스크의 알파 채널을 반전할 수 있습니다.

마스크의 빨강 채널을 사용하는 im.AlphaMask()와는 받는 인수가 다르다는 점에 유의하세요.

class Borders(left, top, right, bottom, pad_left=0, pad_top=0, pad_right=0, pad_bottom=0)

이 객체는 Frame()에 테두리 크기와 타일링 정보를 제공합니다. window나 frame의 padding 스타일 속성에 전달할 안쪽 여백 정보도 제공할 수 있습니다.

left, top, right, bottom

frame에서 사용할 안쪽 경계의 크기이며 각 방향의 안쪽 여백에 더합니다. 0 또는 양의 정수여야 합니다.

pad_left, pad_top, pad_right, pad_bottom

각 방향의 안쪽 여백에 더하는 값이며 양수나 음수일 수 있습니다. 예를 들어 left가 5이고 pad_left가 -3이면 최종 여백은 2입니다.

안쪽 여백 정보는 다음 필드로 제공합니다.

padding

네 방향의 안쪽 여백을 담은 요소 네 개의 튜플입니다.

Composite(size, *args, **properties)

다른 디스플레이어블들을 합성하여 size 크기의 새 디스플레이어블을 만듭니다. size는 (width, height) 튜플입니다.

나머지 위치 인수는 Composite 안에 이미지를 배치하는 데 사용합니다. 두 개씩 짝지어 지정해야 하며 첫 번째는 (x, y) 튜플, 두 번째는 해당 위치에 합성할 디스플레이어블입니다.

디스플레이어블은 뒤에서 앞으로 합성합니다.

image eileen composite = Composite(
    (300, 600),
    (0, 0), "body.png",
    (0, 0), "clothes.png",
    (50, 50), "expression.png")
Crop(rect, child, **properties)

child를 rect 영역으로 잘라 디스플레이어블을 만듭니다. rect는 (x, y, width, height) 튜플입니다.

image eileen cropped = Crop((0, 0, 300, 300), "eileen happy")
class DynamicImage(name)

DynamicImage는 텍스트 보간으로 새 디스플레이어블을 나타내는 문자열을 얻는 디스플레이어블입니다. 각 상호작용이 시작될 때 보간합니다.

class Flatten(child, drawable_resolution=True, **properties)

여러 텍스처로 구성될 수 있는 child를 하나의 텍스처로 합칩니다.

alpha 트랜스폼 속성 같은 일부 연산은 디스플레이어블을 구성하는 모든 텍스처에 각각 적용되므로 화면에서 텍스처가 겹치면 결과가 올바르지 않을 수 있습니다. Flatten은 여러 텍스처를 하나로 만들어 이 문제를 방지합니다.

Flatten은 상대적으로 비용이 큰 연산이므로 꼭 필요할 때만 사용해야 합니다.

drawable_resolution

기본값은 참이며 대개 적절한 선택입니다. 다만 결과 텍스처의 크기를 조절할 때 원래 텍스처들과 다른 렌더링 오류가 생길 수 있습니다. False로 설정하면 오류의 양상이 바뀌며 경우에 따라 더 보기 좋은 결과를 얻을 수 있습니다.

class Frame(image, left=0, top=0, right=None, bottom=None, *, tile=False, **properties)

테두리의 너비와 높이를 유지하면서 이미지를 사용 가능한 영역에 맞게 늘리는 디스플레이어블입니다. window나 button의 배경으로 자주 사용합니다.

_images/frame_example.png

frame으로 이미지 크기를 두 배로 늘리는 예제.

image

이 frame으로 크기를 조절할 이미지 조작기입니다.

left

왼쪽 테두리의 크기입니다. Borders() 객체를 지정할 수도 있으며, 이 경우 다른 매개변수 대신 해당 객체를 사용합니다.

top

위쪽 테두리의 크기입니다.

right

오른쪽 테두리의 크기입니다. None이면 left가 기본값입니다.

bottom

아래쪽 테두리의 크기입니다. None이면 top이 기본값입니다.

tile

True이면 이미지의 각 부분을 늘리는 대신 타일링하여 크기를 조절합니다. 문자열 "integer"이면 각 방향으로 가장 가까운 정수 개수의 타일을 사용합니다. 그런 다음 완전한 타일들로 이루어진 전체를 늘리거나 줄여 필요한 영역에 맞춥니다.

# Resize the background of the text window if it's too small.
init python:
    style.window.background = Frame("frame.png", 10, 10)
class Null(width=0, height=0, **properties)

화면에 빈 상자를 만드는 디스플레이어블입니다. 상자 크기는 width와 height로 제어합니다. 자식이 필수지만 적합한 자식이 없는 경우나 상자 안에 간격을 넣을 때 사용할 수 있습니다.

image logo spaced = HBox("logo.png", Null(width=100), "logo.png")
class Solid(color, **properties)

할당받은 영역을 color로 채우는 디스플레이어블입니다.

image white = Solid("#fff")
class Tile(child, style='tile', **properties)

할당받은 영역을 채울 때까지 child를 반복 배치합니다.

image bg tile = Tile("bg.png")

텍스트 디스플레이어블

텍스트 디스플레이어블을 참조하세요.

동적 디스플레이어블

동적 디스플레이어블은 게임 상태에 따라 자식 디스플레이어블을 표시합니다.

동적 디스플레이어블은 항상 현재 상태를 표시합니다. 따라서 화면 전환에 참여하지 않습니다. 더 정확히는 화면 전환의 이전 상태와 새 상태 양쪽에서 같은 내용을 표시합니다.

동적 디스플레이어블은 캐릭터 꾸미기 시스템처럼 드물게 바뀌며 해당 이미지가 화면 밖에 있을 때 바뀌는 대상에 사용하도록 설계되었습니다. 캐릭터의 감정처럼 자주 바뀌는 대상에는 적합하지 않습니다.

ConditionSwitch(*args, predict_all=None, **properties)

Python 조건에 따라 표시 내용을 바꾸는 디스플레이어블입니다. 위치 인수는 두 개씩 짝지어 지정하며, 각 쌍은 다음으로 구성됩니다.

  • Python 조건을 담은 문자열.

  • 조건이 참이면 사용할 디스플레이어블.

처음으로 참이 되는 조건의 디스플레이어블을 표시합니다. 항상 하나 이상의 조건이 참이어야 합니다.

여기서 사용하는 조건에는 외부에서 관찰할 수 있는 부수 효과가 없어야 합니다.

predict_all

True이면 디스플레이어블을 표시할 때 가능한 모든 디스플레이어블을 예측 로딩합니다. False이면 현재 조건만 예측합니다. None이면 config.conditionswitch_predict_all을 사용합니다.

image jill = ConditionSwitch(
    "jill_beers > 4", "jill_drunk.png",
    "True", "jill_sober.png")
class DynamicDisplayable(function, *args, **kwargs)

상호작용 도중 Python 함수에 따라 자식을 바꿀 수 있는 디스플레이어블입니다. 반환하는 자식 디스플레이어블의 속성이 배치를 제어하므로 자체 속성은 받지 않습니다.

function

다음 인수로 호출하는 함수입니다.

  • 이 디스플레이어블이 표시된 시간.

  • 같은 태그의 디스플레이어블이 표시된 시간.

  • DynamicDisplayable에 전달한 모든 위치 인수와 키워드 인수.

함수는 다음 내용의 (d, redraw) 튜플을 반환해야 합니다.

  • d는 표시할 디스플레이어블입니다.

  • redraw는 함수를 다시 호출할 때까지 기다릴 수 있는 최대 시간입니다. None이면 다음 상호작용이 시작되기 전에는 다시 호출할 필요가 없습니다.

function은 모든 상호작용이 시작될 때 호출합니다.

특별한 경우로 function에 디스플레이어블로 평가되는 Python 문자열을 사용할 수도 있습니다. 이 경우 상호작용마다 한 번 실행합니다.

# Shows a countdown from 5 to 0, updating it every tenth of
# a second until the time expires.
init python:

    def show_countdown(st, at):
        if st > 5.0:
            return Text("0.0"), None
        else:
            d = Text("{:.1f}".format(5.0 - st))
            return d, 0.1

image countdown = DynamicDisplayable(show_countdown)
ShowingSwitch(*args, predict_all=None, **properties)

화면에 표시 중인 이미지에 따라 표시 내용을 바꾸는 디스플레이어블입니다. 위치 인수는 두 개씩 짝지어 지정하며 각 쌍은 다음으로 구성됩니다.

  • 이미지 이름을 나타내는 문자열 또는 기본값을 뜻하는 None.

  • 조건이 참이면 사용할 디스플레이어블.

기본 이미지를 지정해야 합니다.

predict_all

True이면 디스플레이어블을 표시할 때 가능한 모든 디스플레이어블을 예측 로딩합니다. False이면 현재 조건만 예측합니다. None이면 config.conditionswitch_predict_all을 사용합니다.

ShowingSwitch로 캐릭터의 현재 감정에 따라 이미지를 바꿀 수 있습니다. 예를 들면 다음과 같습니다.

image emotion_indicator = ShowingSwitch(
   "eileen concerned", "emotion_indicator concerned",
   "eileen vhappy", "emotion_indicator vhappy",
   None, "emotion_indicator happy")

레이어 디스플레이어블

레이어 디스플레이어블은 게임 상태에 따라 레이어 내용을 표시합니다. config.detached_layers와 함께 사용하도록 설계되었습니다.

동적 디스플레이어블과 마찬가지로 내부의 레이어는 항상 현재 상태를 표시합니다. 따라서 화면 전환이 표시 중인 레이어를 대상으로 하는 경우를 제외하면 레이어 디스플레이어블의 내용은 화면 전환에 참여하지 않습니다.

class Layer(layer, *, clipping=True, **properties)

레이어를 다른 레이어 위에 디스플레이어블로 표시할 수 있게 합니다. 분리된 레이어에 사용하도록 설계되었습니다.

레이어를 자기 자신 위에 표시하는 것은 지원하지 않습니다.

layer

표시할 레이어입니다.

clipping

False이면 레이어의 내용이 경계를 벗어날 수 있습니다. 그 밖의 경우 경계를 벗어난 부분은 잘립니다.

config.layer_clipping에 항목이 있으면 이 옵션을 무시하고 해당 설정대로 잘라냅니다.

# A new detached layer to hold the contents of a broadcast.
define config.detached_layers += [ "broadcast" ]

# A layer displayable to represent a TV and watch the broadcast layer.
image tv = Window(Layer("broadcast"), background='#000', padding=(10, 10), style="default")

image living_room = Placeholder('bg', text='거실')
image studio = Solid('7c7')
image eileen = Placeholder('girl')

label example:
    pause

    # Set up the broadcast scene.
    scene studio onlayer broadcast
    with None

    # Begin a new scene in the living room.
    scene living_room

    # Show the TV in the lower right corner of ths screen.
    show tv:
      align (.75, .75) zoom .3

    # Show Eileen in the broadcast.
    show eileen onlayer broadcast

    # Dissolve into the living room, as Eileen enters the TV from the right.
    with {'master': dissolve, 'broadcast': moveinright}
    pause

레이아웃 상자와 격자

레이아웃 상자는 자식을 화면에 배치하는 디스플레이어블입니다. 가로나 세로 방향으로 배치하거나 표준 위치 결정 알고리즘으로 배치할 수 있습니다.

상자 디스플레이어블은 원하는 수만큼 위치 인수와 키워드 인수를 받습니다. 위치 인수는 자식으로 추가할 디스플레이어블이며, 키워드 인수는 상자에 적용할 스타일 속성입니다.

상자는 위치 스타일 속성과 상자 스타일 속성을 받습니다.

Fixed(*args, **properties)

화면을 채우는 상자입니다. 자식들을 뒤에서 앞으로 배치하며, 각 자식의 위치 속성이 위치를 결정합니다.

HBox(*args, **properties)

자식들을 왼쪽에서 오른쪽으로 배치하는 상자입니다.

VBox(*args, **properties)

자식들을 위에서 아래로 배치하는 레이아웃입니다.

# Display two logos, to the left and right of each other.
image logo hbox = HBox("logo.png", "logo.png")

# Display two logos, one on top of the other.
image logo vbox = VBox("logo.png", "logo.png")

# Display two logos. Since both default to the upper-left
# corner of the screen, we need to use Image to place
# those logos on the screen.
image logo fixed = Fixed(
    Image("logo.png", xalign=0.0, yalign=0.0),
    Image("logo.png", xalign=1.0, yalign=1.0))

Grid 레이아웃은 화면에 자식을 격자로 표시합니다. 위치 스타일 속성과 spacing 스타일 속성을 받습니다.

Grid(cols, rows, *args, **properties)

디스플레이어블들을 격자로 배치합니다. 처음 두 위치 인수는 격자의 열 수와 행 수입니다. 그 뒤에는 격자를 채울 디스플레이어블을 columns * rows개의 위치 인수로 지정해야 합니다.

효과

특정 시각 효과를 만드는 디스플레이어블입니다.

AlphaBlend(control, old, new, alpha=False)

이 화면 전환은 control 디스플레이어블로 두 디스플레이어블 사이를 전환합니다. control은 거의 항상 애니메이션이 적용된 트랜스폼입니다. 트랜스폼을 평가한 뒤 불투명한 곳에는 new 디스플레이어블을, 투명한 곳에는 old 디스플레이어블을 사용합니다.

alpha

참이면 이미지를 뒤의 내용과 합성합니다. 기본값인 거짓이면 이미지는 불투명하며 뒤의 내용을 덮어씁니다.

이미지 조작기

이미지 조작기는 이미지나 다른 이미지 조작기에만 변형이나 연산을 적용하는 이전 방식의 디스플레이어블입니다. 다른 종류의 디스플레이어블에는 적용할 수 없습니다.

이미지 조작기는 디스플레이어블을 받는 모든 곳에서 사용할 수 있지만 반대는 성립하지 않습니다. Image()는 이미지 조작기의 일종이므로 이미지 조작기가 필요한 곳에서 사용할 수 있습니다.

이미지 조작기는 오래된 방식입니다. 과거에 문서화된 여러 이미지 조작기에는 구조적인 문제가 있어 더 이상 사용하지 않아야 합니다. 일반적으로 im.Data()를 제외하면 Transform() 디스플레이어블이 같은 기능을 제공하면서 문제도 해결합니다.

이미지 조작기 목록은 이미지 조작기 문서를 참조하세요.

임시 이미지

Placeholder 디스플레이어블은 상황에 맞는 배경이나 캐릭터 이미지를 표시합니다. 개발자 모드에서 정의되지 않은 이미지를 사용하면 자동으로 임시 이미지를 사용합니다. 기본값이 적합하지 않으면 Placeholder 디스플레이어블을 직접 사용할 수도 있습니다.

# By default, the girl placeholder will be used.
image sue = Placeholder("boy")

label start:
    show sue angry
    "수" "안녕? 이제 넌 죽었어!"
class Placeholder(base=None, full=False, flip=None, text=None, **properties)

임시 캐릭터나 배경을 표시할 수 있는 디스플레이어블입니다.

base

표시할 이미지의 종류입니다. 다음 중 하나여야 합니다.

'bg'

임시 배경을 표시합니다. 현재는 화면을 밝은 회색으로 채우고 화면 위쪽에 이미지 이름을 표시합니다.

'boy'

가슴에 이미지 이름을 표시한 남성 형태의 임시 캐릭터를 표시합니다.

'girl'

가슴에 이미지 이름을 표시한 여성 형태의 임시 캐릭터를 표시합니다.

None

사용할 이미지 종류를 자동으로 정하려고 합니다. 이미지 이름이 "bg", "cg", "event"로 시작하면 'bg'를 사용합니다.

그 밖의 경우 'girl' 임시 이미지를 사용합니다.

full

참이면 전신 스프라이트를 사용합니다. 그렇지 않으면 3/4 길이 스프라이트를 사용합니다.

flip

참이면 스프라이트를 좌우로 뒤집습니다.

text

지정하면 임시 이미지에는 이 텍스트만 표시합니다. 지정하지 않으면 표시할 때 사용한 show 명령을 텍스트에 반영합니다.

디스플레이어블 접두사

디스플레이어블 접두사를 사용하면 제작자가 자신만의 디스플레이어블을 정의하고 Ren'Py에서 디스플레이어블을 받는 모든 곳에서 참조할 수 있습니다. 접두사가 있는 디스플레이어블은 콜론이 포함된 문자열입니다. 콜론 왼쪽은 접두사이고 오른쪽 전체는 인수입니다. config.displayable_prefix 변수는 접두사를 함수에 매핑합니다. 함수는 인수를 받아 디스플레이어블이나 None을 반환합니다.

예를 들어 다음 코드는 big 접두사가 원본보다 두 배 큰 이미지를 반환하도록 합니다.

init -10 python:
    def embiggen(s):
        return Transform(s, zoom=2)

    config.displayable_prefix["big"] = embiggen

init -10은 이 접두사를 사용하는 이미지보다 먼저 접두사를 정의하도록 합니다. 이후 접두사로 이미지를 정의할 수 있습니다.

image eileen big = "big:eileen happy"

또는 디스플레이어블이 필요한 다른 모든 곳에서 사용할 수 있습니다.

관련 항목

이미지 표시: 이 디스플레이어블들을 화면에 표시하는 기본 방법입니다.