글 작성자: Doublsb

오늘부터 RPG Maker VX ACE 스크립트를 해부하며 공부하고, 다른 사람에게도 도움을 주기 위해 글을 작성하려 한다. 

작성 순서는 우리가 게임에서 만날 수 있는 순서로 진행할 예정이다.


먼저, 게임을 실행하기만 하면 만날 수 있는 타이틀의 스크립트부터 해부해보려 한다.

기초인 씬과 클래스는 이 글에서 설명하려면 너무 길어지므로 큰 부분만 다룰 것이다.


보통 타이틀 씬을 건드린다고 하면, 이유는 타이틀 커맨드 선택지를 더 추가하고 싶거나, 타이틀 씬을 아예 없애고 싶거나, 변수에 따라 타이틀 배경을 바꾸고 싶어서일 것이다. 이런 응용은 다음 게시글에서 다루기로 하고, 본 글에선 스크립트가 어떻게 구성되어 있는지만 해부하기로 한다.


메소드를 호출한다는 건 def 이후에 있는 내용을 불러온다는 의미이다.

만약, create_background를 호출한다면 def create_foreground 이하의 내용이 end를 만날 때까지 실행된다.




스크립트 전문


#==============================================================================

# ** Scene_Title

#------------------------------------------------------------------------------

#  This class performs the title screen processing.

#==============================================================================


class Scene_Title < Scene_Base

  #--------------------------------------------------------------------------

  # * Start Processing

  #--------------------------------------------------------------------------

  def start

    super

    SceneManager.clear

    Graphics.freeze

    create_background

    create_foreground

    create_command_window

    play_title_music

  end

  #--------------------------------------------------------------------------

  # * Get Transition Speed

  #--------------------------------------------------------------------------

  def transition_speed

    return 20

  end

  #--------------------------------------------------------------------------

  # * Termination Processing

  #--------------------------------------------------------------------------

  def terminate

    super

    SceneManager.snapshot_for_background

    dispose_background

    dispose_foreground

  end

  #--------------------------------------------------------------------------

  # * Create Background

  #--------------------------------------------------------------------------

  def create_background

    @sprite1 = Sprite.new

    @sprite1.bitmap = Cache.title1($data_system.title1_name)

    @sprite2 = Sprite.new

    @sprite2.bitmap = Cache.title2($data_system.title2_name)

    center_sprite(@sprite1)

    center_sprite(@sprite2)

  end

  #--------------------------------------------------------------------------

  # * Create Foreground

  #--------------------------------------------------------------------------

  def create_foreground

    @foreground_sprite = Sprite.new

    @foreground_sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height)

    @foreground_sprite.z = 100

    draw_game_title if $data_system.opt_draw_title

  end

  #--------------------------------------------------------------------------

  # * Draw Game Title

  #--------------------------------------------------------------------------

  def draw_game_title

    @foreground_sprite.bitmap.font.size = 48

    rect = Rect.new(0, 0, Graphics.width, Graphics.height / 2)

    @foreground_sprite.bitmap.draw_text(rect, $data_system.game_title, 1)

  end

  #--------------------------------------------------------------------------

  # * Free Background

  #--------------------------------------------------------------------------

  def dispose_background

    @sprite1.bitmap.dispose

    @sprite1.dispose

    @sprite2.bitmap.dispose

    @sprite2.dispose

  end

  #--------------------------------------------------------------------------

  # * Free Foreground

  #--------------------------------------------------------------------------

  def dispose_foreground

    @foreground_sprite.bitmap.dispose

    @foreground_sprite.dispose

  end

  #--------------------------------------------------------------------------

  # * Move Sprite to Screen Center

  #--------------------------------------------------------------------------

  def center_sprite(sprite)

    sprite.ox = sprite.bitmap.width / 2

    sprite.oy = sprite.bitmap.height / 2

    sprite.x = Graphics.width / 2

    sprite.y = Graphics.height / 2

  end

  #--------------------------------------------------------------------------

  # * Create Command Window

  #--------------------------------------------------------------------------

  def create_command_window

    @command_window = Window_TitleCommand.new

    @command_window.set_handler(:new_game, method(:command_new_game))

    @command_window.set_handler(:continue, method(:command_continue))

    @command_window.set_handler(:shutdown, method(:command_shutdown))

  end

  #--------------------------------------------------------------------------

  # * Close Command Window

  #--------------------------------------------------------------------------

  def close_command_window

    @command_window.close

    update until @command_window.close?

  end

  #--------------------------------------------------------------------------

  # * [New Game] Command

  #--------------------------------------------------------------------------

  def command_new_game

    DataManager.setup_new_game

    close_command_window

    fadeout_all

    $game_map.autoplay

    SceneManager.goto(Scene_Map)

  end

  #--------------------------------------------------------------------------

  # * [Continue] Command

  #--------------------------------------------------------------------------

  def command_continue

    close_command_window

    SceneManager.call(Scene_Load)

  end

  #--------------------------------------------------------------------------

  # * [Shut Down] Command

  #--------------------------------------------------------------------------

  def command_shutdown

    close_command_window

    fadeout_all

    SceneManager.exit

  end

  #--------------------------------------------------------------------------

  # * Play Title Screen Music

  #--------------------------------------------------------------------------

  def play_title_music

    $data_system.title_bgm.play

    RPG::BGS.stop

    RPG::ME.stop

  end

end



타이틀 스크립트의 메소드는 15개이다. 화면 전환 속도, 배경화면 그리기, 타이틀 선택지 그리기, 타이틀 커맨드 윈도우 띄우기로 되어 있다. 다른 씬보다는 적은 양의 스크립트를 보여주고 있다.


class Scene_Title < Scene_Base 라는 문구에서, 타이틀 씬이 씬 베이스의 하위 클래스임을 확인할 수 있다.

씬 베이스를 기반으로 타이틀 씬이 이루어져 있음을 알 수 있다.





Start Processing


함수 목적 : 타이틀 씬(Scene_Title)을 불러 왔을 때, 제일 먼저 시작되는 메소드.


함수 내용

def start   

    super   

    SceneManager.clear    

    Graphics.freeze   

    create_background   

    create_foreground   

    create_command_window   

    play_title_music  

  end  


설명

(1) super

먼저 Scene_Title을 실행하게 되면, super를 통해 Scene_Base의 start 메소드를 불러오게 된다. 이는 뷰포트를 변경하는 역할을 한다. 뷰포트의 의미는 생략하겠다.


(2) SceneManager.clear

씬 매니저의 내용을 초기화한다. 씬 매니저는 이름답게 현재 사용중인 씬과 다른 씬으로의 이동을 관리하는 역할을 한다.


(3) Graphics.freeze

현재 표시중인 그래픽을 멈춘다. 만약 맵에서 타이틀로 이동할 경우, 맵에서 실행중인 그래픽이 계속 움직이면 안 되기 때문에 움직임을 얼리게 된다.


(4) create_background

create_background 메소드를 실행한다.

제작자가 데이터베이스에서 지정한 배경을 출력한다.


(5) create_foreground

create_foreground 메소드를 실행한다.

제작자가 데이터베이스에서 지정한 전경을 출력한다. 보통 Draw Game Title에 체크했을 때 게임 제목을 화면에 출력하는 역할을 한다. 없으면 게임 타이틀 이름이 따로 뜨지 않을 것이다.


(6) create_command_window

커맨드 윈도우를 만든다. 만약 이 부분이 없다면 배경화면과 타이틀 음악만 재생되고 게임을 제대로 플레이 할 수 없게 된다.


(7) play_title_music

제작자가 데이터베이스에서 지정한 타이틀 배경음을 실행한다.





Get Transition Speed


함수 목적 : 화면 전환 속도를 관리하는 메소드. 


함수 내용

def transition_speed  

    return 20 

  end


설명

만약 return값을 0으로 변경한다면 화면은 눈깜짝할 새에 타이틀 그래픽을 표시한다. 반대로 20보다 늘리게 되면 한없이 기다리게 될 것이다. 한번 바꿔서 플레이어의 인내심을 시험해볼 수도 있을 것이다. 보통 그럴 리는 없겠지만 말이다.





Termination Processing


함수 목적 : 화면이 타이틀로 변경될 때의 과정을 관리하는 메소드. 보통은 제작자가 건드리지 않는다.


함수 내용

 def terminate

    super 

    SceneManager.snapshot_for_background  

    dispose_background   

    dispose_foreground  

  end


설명

(1) super

super를 통해 Scene_Base에 있는 terminate 메소드를 실행한다. 그래픽을 멈추고 윈도우를 다 닫은 뒤, 뷰포트를 해제하는 내용이다.


(2) SceneManager.snapshot_for_background

스크린샷을 찍어 현재 그래픽을 임시로 배경화면으로 사용한다. 자연스러운 화면전환을 위해 사용한다.


(3) dispose_background

그 전의 씬에서 사용했던 배경을 없앤다.


(4) dispose_foreground

그 전의 씬에서 사용했던 전경을 없앤다.




Create Background


함수 목적 : 타이틀 배경 화면을 생성하는 메소드. 


함수 내용

def create_background

    @sprite1 = Sprite.new    

    @sprite1.bitmap = Cache.title1($data_system.title1_name)  

    @sprite2 = Sprite.new   

    @sprite2.bitmap = Cache.title2($data_system.title2_name)  

    center_sprite(@sprite1)   

    center_sprite(@sprite2)   

  end


설명

제작자가 데이터베이스에서 지정한 타이틀 배경 그림을 화면에 출력하는 메소드다. 없으면 타이틀 배경 화면이 뜨지 않고 검은색 화면에 선택지들만 표시될 것이다.


(1) @sprite1 = Sprite.new

sprite1이라는 이름을 가진 새로운 스프라이트를 생성한다. 만약 @ohyessprite = Sprite.new라고 했으면 ohyessprite라는 스프라이트가 생성되었을 것이다. 뭘 만들던간에 역시 항상 이름을 잘 붙여줘야 한다.


(2) @sprite1.bitmap = Cache.title1($data_system.title1_name)

우리가 데이터베이스에서 지정한 파일을 sprite1에 불러온다.

우리가 타이틀 배경 파일을 Graphics 폴더의 Titles1에 저장하는 건 이 구문이 있기 때문이다. Cache는 각 리소스의 폴더 위치를 기억하고 있다. 데이터베이스에서 우리가 타이틀 그림의 이름을 알려 주면, Cache는 자신이 기억하고 있는 위치에 그런 이름의 파일이 있는지 조사한다. 있으면 출력될 테고, 없으면 Titles1 폴더에 그러한 이름의 파일이 없다고 오류가 뜨게 된다.


(3) @sprite2 = Sprite.new

sprite2라는 이름을 가진 새로운 스프라이트를 생성한다.


(4) @sprite2.bitmap = Cache.title2($data_system.title2_name)

데이터베이스에서 지정한 title2 파일을 sprite2에 불러온다.


(5) center_sprite(@sprite1)

sprite1로 center_sprite 메소드를 실행한다. sprite1을 중앙에 표시하는 내용이다.


(6) center_sprite(@sprite2)

sprite2로 center_sprite 메소드를 실행한다. sprite2를 중앙에 표시하는 내용이다.





Create Foreground


함수 목적 : 타이틀 전경 화면을 생성하는 메소드.


함수 내용

def create_foreground

    @foreground_sprite = Sprite.new 

    @foreground_sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height)

    @foreground_sprite.z = 100 

    draw_game_title if $data_system.opt_draw_title

  end


설명

(1) @foreground_sprite = Sprite.new    

foreground_sprite라는 이름의 스프라이트를 생성한다.


(2) @foreground_sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height)

Graphics.width는 게임 화면의 가로 크기를 의미한다. Graphics.height는 게임 화면의 세로 크기를 의미한다.

따라서 이 구문은 게임 화면 크기만큼의 투명 판을 위에 새로 깐다고 생각하면 된다.


(3) @foreground_sprite.z = 100

z는 새로 깐 투명 판이 어떤 위치에 있는지를 정한다. 만약 투명 판이 배경화면 그림의 아래에 깔린다면 소용이 없을 것이다.

100으로 정한 건 투명 판을 배경 화면의 위에 깔기 위함이다.


(4) draw_game_title if $data_system.opt_draw_title

데이터베이스에서 게임 이름을 타이틀 그림 위에 표시할 것인지 체크하는 기능을 봤을 것이다. 이 구문은 그 기능을 수행한다.

만약 체크가 되어있다면 draw_game_title 메소드를 실행한다.





Draw Game Title


함수 목적 : 타이틀 이름을 표시하는 메소드.


함수 내용

  def draw_game_title

    @foreground_sprite.bitmap.font.size = 48

    rect = Rect.new(0, 0, Graphics.width, Graphics.height / 2)

    @foreground_sprite.bitmap.draw_text(rect, $data_system.game_title, 1)

  end


설명

create_foreground에서 투명 판을 만들었던 것을 기억하는가? 이 메소드는 그 투명 판 위에 글씨를 쓰는 역할을 한다.


(1) @foreground_sprite.bitmap.font.size = 48

타이틀 이름을 48의 글씨 크기로 쓸 것임을 알린다. 숫자가 더 적어진다면 작게 쓰일 것이고, 더 늘어난다면 크게 쓰일 것이다.


(2) rect = Rect.new(0, 0, Graphics.width, Graphics.height / 2)

rect라는 투명 라벨을 붙일 사각형 공간을 만든다. 투명 판에 수성 펜으로 아무리 글씨를 쓰려 해도 쓰지 못했던 경험이 한번쯤은 있을 것이다. 하지만 그 위에 라벨 스티커를 붙이고 글씨를 쓰면 누구라도 쓸 수 있다. rect는 이런 라벨 스티커의 역할을 한다.

이 스티커는 투명 판의 (0,0) 위치에 붙인다. 그리고 스티커의 크기는 가로가 Graphics.width, 세로가 Graphics.height의 반 만큼이다.

만약 다음에 투명 라벨을 만들고 싶다면, rect = Rect.new(가로 위치, 세로 위치, 가로 크기, 세로 크기)를 사용하면 된다.


(3) @foreground_sprite.bitmap.draw_text(rect, $data_system.game_title, 1)

투명 판과 rect라는 투명 라벨 위에, 우리가 데이터베이스에서 게임 이름으로 정했던 이름으로 글씨를 쓴다.

1은 가운데 정렬을 의미한다. 만약 값이 0이라서 게임 이름이 왼쪽부터 쓰여 있다면 그렇게 보기 좋지는 않을 것이다.





Free Background


함수 목적 : 배경 화면을 없앤다.


함수 내용

def dispose_background

    @sprite1.bitmap.dispose 

    @sprite1.dispose

    @sprite2.bitmap.dispose

    @sprite2.dispose

  end


설명

타이틀 씬을 끄고 다른 씬으로 이동하려면 배경 화면이나 커맨드를 없애야 한다. 이 메소드는 배경 화면을 없애는 역할을 한다.


(1) @sprite1.bitmap.dispose

sprite1의 그림을 지운다.


(2) @sprite1.dispose

sprite1을 없앤다.


둘의 차이는 투명 판 위에 올려진 그림을 없애느냐, 아니면 투명 판 자체를 없애느냐로 설명이 가능하다.

@sprite2.bitmap.dispose와 @sprite2.dispose도 이름은 다르지만 같은 내용이니 설명하지 않겠다.





Free Foreground


함수 목적 : 전경 화면을 없앤다. 배경 화면에 그려진 타이틀 이름이 지워지게 된다.


함수 내용

def dispose_foreground

    @foreground_sprite.bitmap.dispose

    @foreground_sprite.dispose

  end


설명

타이틀 씬을 끄고 다른 씬으로 이동하려면 배경 화면이나 커맨드를 없애야 한다. 이 메소드는 전경 화면을 없애는 역할을 한다.


(1) @foreground_sprite.bitmap.dispose

foreground_sprite의 그림을 지운다.


(2) @foreground_sprite.dispose

foreground_sprite를 없앤다.


둘의 차이는 투명 판 위에 올려진 그림을 없애느냐, 아니면 투명 판 자체를 없애느냐로 설명이 가능하다.





Move Sprite to Screen Center


함수 목적 : 스프라이트를 가운데에 표시한다.


함수 내용

def center_sprite(sprite)

    sprite.ox = sprite.bitmap.width / 2

    sprite.oy = sprite.bitmap.height / 2

    sprite.x = Graphics.width / 2

    sprite.y = Graphics.height / 2

  end


설명

그림을 가운데에 놓는 역할을 하는 메소드이다. 큰 내용은 없으니 자세히 설명하지 않는다.





Create Command Window


함수 목적 : 타이틀 선택지를 만든다.


함수 내용

def create_command_window

    @command_window = Window_TitleCommand.new

    @command_window.set_handler(:new_game, method(:command_new_game))

    @command_window.set_handler(:continue, method(:command_continue))

    @command_window.set_handler(:shutdown, method(:command_shutdown))

  end


설명

가장 많이 변경하고 응용할 내용이리라 생각한다. 새 게임, 이어하기, 종료하기 선택지를 표시하는 메소드이다.


(1) @command_window = Window_TitleCommand.new

command_window라는 이름의 새로운 타이틀 커맨드를 만든다. 이름을 붙이고 정의하는 내용이다.


(2) @command_window.set_handler(:new_game, method(:command_new_game))

새 게임 선택지를 만든다. 만약 이 선택지를 골랐을 경우 command_new_game이라는 메소드를 실행한다.

set_handler는 선택했을 때 어떤 메소드를 불러올 것인지 연결해주는 역할을 한다. 

:new_game은 Window_TitleCommand에 있는 add_command(Vocab::new_game, :new_game)에서 왔다.

그러므로 만약 제작자가 선택지를 추가하려면, Window_TitleCommand 스크립트도 함께 수정을 해 주어야 한다.

이 내용은 다음에 올라올 응용편에서 이야기한다.


(3) @command_window.set_handler(:continue, method(:command_continue))

(4) @command_window.set_handler(:shutdown, method(:command_shutdown))

이어하기, 종료하기 선택지를 만든다. 선택하면 각각 command_continue와 command_shutdown이라는 메소드를 실행한다.


만약 이 스크립트의 내용을, 

@command_window.set_handler(:continue, method(:command_shutdown))

으로 바꿔버린다면 어떤 일이 일어날까?


계속하기 선택지를 눌렀을 때 command_shutdown 메소드가 호출되어 게임이 꺼져버린다.

이처럼 method 괄호 안의 내용을 다른 메소드로 바꿔버리면 다른 내용이 튀어나온다.


다른 예시로, 

@command_window.set_handler(:shutdown, method(:dispose_background))

으로 바꿔버리면 게임 종료 선택지를 눌렀는데 배경 화면만 없어져버리는 일이 일어난다.





Close Command Window


함수 목적 : 타이틀 선택지를 없앤다.


함수 내용

def close_command_window

    @command_window.close

    update until @command_window.close?

  end


설명

(1) @command_window.close

command_window를 닫는다.


(2) update until @command_window.close?

command_window가 열리고 닫힐 때, 창문이 열리듯이 위로 늘어났다가 아래로 줄어든다.

update는 이러한 자연스러운 애니메이션을 이어주는 기능이다. 그러므로 이 구문은 command_window가 완전히 닫힐 때까지 애니메이션이 나타나도록 업데이트를 해 준다.





Command_new_game


함수 목적 : 새 게임을 시작한다.


함수 내용

  def command_new_game

    DataManager.setup_new_game

    close_command_window

    fadeout_all

    $game_map.autoplay

    SceneManager.goto(Scene_Map)

  end


설명

이 메소드는 새 게임 선택지를 선택했을 때만 실행된다.


(1) DataManager.setup_new_game

새 게임을 위해 데이터를 만든다.


(2) close_command_window

선택지 윈도우를 닫는다. 


(3) fadeout_all

화면 전환을 위해 화면을 깜깜해지게 만든다.


(4) $game_map.autoplay

우리가 시작 맵에 지정해둔 음악을 실행한다.


(5) SceneManager.goto(Scene_Map)

맵 화면으로 전환한다.





Command_continue


함수 목적 : 불러오기 씬을 호출한다.


함수 내용

  def command_continue

    close_command_window

    SceneManager.call(Scene_Load)

  end


설명

이 메소드는 계속하기 선택지를 선택했을 때만 실행된다.


(1) close_command_window

커맨드 윈도우를 닫는다.


(2) SceneManager.call(Scene_Load)

불러오기 씬 스크립트를 호출한다.





Command_shutdown


함수 목적 : 게임을 종료한다.


함수 내용

  def command_shutdown

    close_command_window

    fadeout_all

    SceneManager.exit

  end


설명

이 메소드는 종료하기 선택지를 선택했을 때만 실행된다.


(1) close_command_window

커맨드 윈도우를 닫는다.


(2) fadeout_all

자연스러운 종료를 위해 화면을 검게 만든다. 없으면 누르자마자 바로 종료된다.


(3) SceneManager.exit

게임 창을 종료한다.





Play Title Screen Music


함수 목적 : 타이틀 음악을 실행한다.


함수 내용

def play_title_music

    $data_system.title_bgm.play

    RPG::BGS.stop

    RPG::ME.stop

  end


설명

(1) $data_system.title_bgm.play

데이터베이스에서 지정해둔 타이틀 음악을 재생한다.


(2) RPG::BGS.stop

BGS는 끈다.


(3) RPG::ME.stop

ME도 끈다.

반응형