메뉴

[VX Ace] 다이얼 링 메뉴 스크립트

by RaonHank posted Apr 16, 2012
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 댓글로 가기 인쇄
제가 만드는 SRPG의 케릭터 선택 시 표시할 커맨드용 스크립트입니다.
아 물론 어렵지도 않은 간단한 겁니다만 (. . ; 귀찮으신 분들을 위해
물론 SRPG 스크립트도 직접 짜고 있습니다만. 완성할 가능성은 제로에 가까우므로
공개는 패스하고 생긴건

screenshot.jpg
요런 느낌...

크게 3가지로 나뉩니다.

Raon_WindowSelectable  
- Window_Selectable 의 불필요한 부분을 삭제하고 제꺼에 맞게 추가적인 함수와 구현이 있습니다.( 별로 안바뀌었음 )

Raon_WindowRingCmd
- Window_Command 를 참고해 만들었어요. 이부분은 링메뉴 핵심으로 위치 선정 및 동작이 구현되었습니다.
참고로 그냥은 쓸 수 없습니다. 1차 상속에 의한 오버라이드가 필요한 함수가 있습니다.

Raon_SrpgWindowPlayerCmd
- 이부분이 실제 Raon_WindowRingCmd 상속을 통해 구현을 한 스크립트 입니다.
오버라이드할 함수는 
item_width, item_height, make_command_list, 세가지고
setup은 편의상 구현되어있는 함수로 있어도 그만 없으면 귀찮은 함수 입니다.
(VX Ace의 스크립트가 이런식으로 구현합니다, 범용적으로 바꾸기 귀찮아서 Ace 기존구현 룰을 따랐습니다. )


#==============================================================================
# ■ Raon_WindowSelectable
#------------------------------------------------------------------------------
# 기존 Window_Selectable 복제 - 불필요 부분 삭제 및 필요 부분 추가
#==============================================================================

class Raon_WindowSelectable < Window_Base
  #--------------------------------------------------------------------------
  # ● 공개 인스턴스 변수
  #--------------------------------------------------------------------------
  attr_reader   :index                    # 커서 위치
  attr_reader   :help_window              # 도움말 창
  attr_accessor :cursor_fix               # 커서 고정 플래그
  attr_accessor :cursor_all               # 커서 전체 선택 플래그
  #--------------------------------------------------------------------------
  # ● 오브젝트 초기화
  #-------------------------------------------------------------------------
  def initialize(x, y, width, height)
    super
    @index = -1
    @handler = {}
    @cursor_fix = false
    @cursor_all = false
    deactivate
  end
  #--------------------------------------------------------------------------
  # ● 항목수
  #--------------------------------------------------------------------------
  def item_max
    return 0
  end
  #--------------------------------------------------------------------------
  # ● 항목의 너비
  #--------------------------------------------------------------------------
  def item_width
    return 0
  end
  #--------------------------------------------------------------------------
  # ● 항목 높이
  #--------------------------------------------------------------------------
  def item_height
    return 0
  end
  #--------------------------------------------------------------------------
  # ● 활성 상태 변경
  #--------------------------------------------------------------------------
  def active=(active)
    super
    update_cursor
    call_update_help
  end
  #--------------------------------------------------------------------------
  # ● 커서 위치 설정
  #--------------------------------------------------------------------------
  def index=(index)
    @index = index
    update_cursor
    call_update_help
  end
  #--------------------------------------------------------------------------
  # ● 항목 선택
  #--------------------------------------------------------------------------
  def select(index)
    self.index = index if index
  end
  #--------------------------------------------------------------------------
  # ● 항목의 선택 해제
  #--------------------------------------------------------------------------
  def unselect
    self.index = -1
  end
  #--------------------------------------------------------------------------
  # ● 항목을 그릴 사각형
  #--------------------------------------------------------------------------
  def item_rect(index)
    rect = Rect.new
    rect.width = item_width
    rect.height = item_height
    rect.x = 0
    rect.y = index * item_height
    rect
  end
  #--------------------------------------------------------------------------
  # ● 항목을 그릴 사각형(텍스트)
  #--------------------------------------------------------------------------
  def item_rect_for_text(index)
    rect = item_rect(index)
    rect.x += 4
    rect.width -= 8
    rect
  end
  #--------------------------------------------------------------------------
  # ● 도움말 창의 설정
  #--------------------------------------------------------------------------
  def help_window=(help_window)
    @help_window = help_window
    call_update_help
  end
  #--------------------------------------------------------------------------
  # ● 동작에 대한 처리기 설정
  #     method : 처리기로 설정하는 메소드 (Method 개체)
  #--------------------------------------------------------------------------
  def set_handler(symbol, method)
    @handler[symbol] = method
  end
  #--------------------------------------------------------------------------
  # ● 처리기의 존재 확인
  #--------------------------------------------------------------------------
  def handle?(symbol)
    @handler.include?(symbol)
  end
  #--------------------------------------------------------------------------
  # ● 처리기 호출
  #--------------------------------------------------------------------------
  def call_handler(symbol)
    @handler[symbol].call if handle?(symbol)
  end
  #--------------------------------------------------------------------------
  # ● 커서의 이동 가능 판정
  #--------------------------------------------------------------------------
  def cursor_movable?
    active && open? && !@cursor_fix && !@cursor_all && item_max > 0
  end
  #--------------------------------------------------------------------------
  # ● 커서를 위로 이동
  #--------------------------------------------------------------------------
  def cursor_up(wrap = false)
  end
  #--------------------------------------------------------------------------
  # ● 커서를 아래로 이동
  #--------------------------------------------------------------------------
  def cursor_down(wrap = false)
  end
  #--------------------------------------------------------------------------
  # ● 커서를 왼쪽으로 이동
  #--------------------------------------------------------------------------
  def cursor_left(wrap = false)
  end
  #--------------------------------------------------------------------------
  # ● 커서를 오른쪽으로 이동
  #--------------------------------------------------------------------------
  def cursor_right(wrap = false)
  end
  #--------------------------------------------------------------------------
  # ● 프레임 갱신
  #--------------------------------------------------------------------------
  def update
    super
    process_cursor_move
    process_handling
  end
  #--------------------------------------------------------------------------
  # ● 커서 이동 작업
  #--------------------------------------------------------------------------
  def process_cursor_move
    return unless cursor_movable?
    last_index = @index
    cursor_down (Input.trigger?(:DOWN))  if Input.repeat?(:DOWN)
    cursor_up   (Input.trigger?(:UP))    if Input.repeat?(:UP)
    cursor_right(Input.trigger?(:RIGHT)) if Input.repeat?(:RIGHT)
    cursor_left (Input.trigger?(:LEFT))  if Input.repeat?(:LEFT)
    Sound.play_cursor if @index != last_index
  end
  #--------------------------------------------------------------------------
  # ● 결정 나 취소 등을 핸들링 처리
  #--------------------------------------------------------------------------
  def process_handling
    return unless open? && active
    return process_ok       if ok_enabled?        && Input.trigger?(:C)
    return process_cancel   if cancel_enabled?    && Input.trigger?(:B)
  end
  #--------------------------------------------------------------------------
  # ● 결정 처리 유효 상태를 취득
  #--------------------------------------------------------------------------
  def ok_enabled?
    handle?(:ok)
  end
  #--------------------------------------------------------------------------
  # ● 취소 후 유효 상태를 취득
  #--------------------------------------------------------------------------
  def cancel_enabled?
    handle?(:cancel)
  end
  #--------------------------------------------------------------------------
  # ● 결정 버튼을 눌렀을 때의 처리
  #--------------------------------------------------------------------------
  def process_ok
    if current_item_enabled?
      Sound.play_ok
      Input.update
      deactivate
      call_ok_handler
    else
      Sound.play_buzzer
    end
  end
  #--------------------------------------------------------------------------
  # ● 결정 처리기 호출
  #--------------------------------------------------------------------------
  def call_ok_handler
    call_handler(:ok)
  end
  #--------------------------------------------------------------------------
  # ● 취소 버튼을 눌렀을 때의 처리
  #--------------------------------------------------------------------------
  def process_cancel
    Sound.play_cancel
    Input.update
    deactivate
    call_cancel_handler
  end
  #--------------------------------------------------------------------------
  # ● 취소 처리기 호출
  #--------------------------------------------------------------------------
  def call_cancel_handler
    call_handler(:cancel)
  end
  #--------------------------------------------------------------------------
  # ● 커서 업데이트
  #--------------------------------------------------------------------------
  def update_cursor
    if @cursor_all
      cursor_rect.set(0, 0, contents.width, contents.height)
    elsif @index < 0
      cursor_rect.empty
    else
      cursor_rect.set(item_rect(@index))
    end
  end
  #--------------------------------------------------------------------------
  # ● 도움말 윈도우 업데이트 메서드 호출
  #--------------------------------------------------------------------------
  def call_update_help
    update_help if active && @help_window
  end
  #--------------------------------------------------------------------------
  # ● 도움말 창 업데이트
  #--------------------------------------------------------------------------
  def update_help
    @help_window.clear
  end
  #--------------------------------------------------------------------------
  # ● 선택의 유효 상태를 취득
  #--------------------------------------------------------------------------
  def current_item_enabled?
    return true
  end
  #--------------------------------------------------------------------------
  # ● 모든 항목 그리기
  #--------------------------------------------------------------------------
  def draw_all_items
    item_max.times {|i| draw_item(i) }
  end
  #--------------------------------------------------------------------------
  # ● 항목 그리기
  #--------------------------------------------------------------------------
  def draw_item(index)
  end
  #--------------------------------------------------------------------------
  # ● 항목 제거
  #--------------------------------------------------------------------------
  def clear_item(index)
    contents.clear_rect(item_rect(index))
  end
  #--------------------------------------------------------------------------
  # ● 항목을 다시 그리기
  #--------------------------------------------------------------------------
  def redraw_item(index)
    clear_item(index) if index >= 0
    draw_item(index)  if index >= 0
  end
  #--------------------------------------------------------------------------
  # ● 선택 항목을 다시 그리기
  #--------------------------------------------------------------------------
  def redraw_current_item
    redraw_item(@index)
  end
  #--------------------------------------------------------------------------
  # ● 백그라운드 그리기( 링메뉴 뒤에 그릴 무언가를 위해 )
  #--------------------------------------------------------------------------
  def draw_background
  end
  #--------------------------------------------------------------------------
  # ● 재생
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    draw_background
    draw_all_items
  end
end

그리고 구현은

#==============================================================================
# ■ Raon_WindowRingCmd
#------------------------------------------------------------------------------
# 이건 링 메뉴요.
#==============================================================================

class Raon_WindowRingCmd < Raon_WindowSelectable
  #--------------------------------------------------------------------------
  # ● 객체 초기화
  #--------------------------------------------------------------------------
  def initialize(x, y, radius)
    clear_command_list
    make_command_list
    @radius = radius
    super(draw_x(x), draw_y(y), win_width, win_height)
    refresh
    select(0)
    activate
  end
  #--------------------------------------------------------------------------
  # ● 위치 재설정 ( 이건 중점임, 절대 윈도우의 표시 x,y, 좌표 아님. )
  #--------------------------------------------------------------------------
  def location(x, y)
    move(draw_x(x), draw_y(y), win_width, win_height)
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 실제 x좌표( 이건 그리기 시작하는 X 좌표, 기본적으로 화면 못넘어가게 막아놨음 )
  #--------------------------------------------------------------------------
  def draw_x(new_x)
    return [[new_x - half_width, Graphics.width - half_width].min, 0].max
  end
  #--------------------------------------------------------------------------
  # ● 실제 y좌표
  #--------------------------------------------------------------------------
  def draw_y(new_y)
    return [[new_y - half_height, Graphics.height - half_height].min, 0].max
  end
  #--------------------------------------------------------------------------
  # ● 링메뉴 x 좌표 ( 이건 링메뉴 표시 원점, 이점을 기준으로 회전함 )
  #--------------------------------------------------------------------------
  def ring_center_x
    return radius + (item_width / 2)
  end
  #--------------------------------------------------------------------------
  # ● 링메뉴 y 좌표
  #--------------------------------------------------------------------------
  def ring_center_y
    return radius + (item_height / 2)
  end
  #--------------------------------------------------------------------------
  # ● 반지름
  #--------------------------------------------------------------------------
  def radius
    return @radius
  end
  #--------------------------------------------------------------------------
  # ● 창 반토막 너비
  #--------------------------------------------------------------------------
  def half_width(peg_ring = true)
    return ring_center_x + standard_padding if peg_ring
    return win_width / 2
  end
  #--------------------------------------------------------------------------
  # ● 창 반토막 높이
  #--------------------------------------------------------------------------
  def half_height(peg_ring = true)
    return ring_center_y + standard_padding if peg_ring
    return win_height / 2
  end
  #--------------------------------------------------------------------------
  # ● 창 너비( ( 반지름 + 윈도우 패팅 ) * 2 + 아이템 너비 + 확장 너비 ) 높이도 마찬가지임
  #--------------------------------------------------------------------------
  def win_width
    return (radius + standard_padding) * 2 + item_width + addon_width
  end
  #--------------------------------------------------------------------------
  # ● 창 높이
  #--------------------------------------------------------------------------
  def win_height
    return (radius + standard_padding) * 2 + item_height + addon_height
  end
  #--------------------------------------------------------------------------
  # ● 아이템 너비
  #--------------------------------------------------------------------------
  def item_width
    0
  end
  #--------------------------------------------------------------------------
  # ● 아이템 높이
  #--------------------------------------------------------------------------
  def item_height
    0
  end
  #--------------------------------------------------------------------------
  # ● 확장 너비
  #--------------------------------------------------------------------------
  def addon_width
    5
  end
  #--------------------------------------------------------------------------
  # ● 확장 높이
  #--------------------------------------------------------------------------
  def addon_height
    5
  end
  #--------------------------------------------------------------------------
  # ● 항 목 수
  #--------------------------------------------------------------------------
  def item_max
    @list.size
  end
  #--------------------------------------------------------------------------
  # ● 명령 목록 지우기
  #--------------------------------------------------------------------------
  def clear_command_list
    @list = []
  end
  #--------------------------------------------------------------------------
  # ● 명령 목록 만들기
  #--------------------------------------------------------------------------
  def make_command_list
  end
  #--------------------------------------------------------------------------
  # ● 명령 추가
  #     name    : 이름
  #     symbol  : 심볼
  #     icon    : 아이콘
  #     enabled : 활성
  #--------------------------------------------------------------------------
  def add_command(name, symbol, icon = 0, enabled = true)
    @list.push({:name=>name, :symbol=>symbol, :icon=>icon, :enabled=>enabled})
  end
  #--------------------------------------------------------------------------
  # ● 명령 이름
  #--------------------------------------------------------------------------
  def command_name(index)
    @list[index][:name]
  end
  #--------------------------------------------------------------------------
  # ● 명령 심볼
  #--------------------------------------------------------------------------
  def command_symbol(index)
    @list[index][:symbol]
  end
  #--------------------------------------------------------------------------
  # ● 명령 활성?
  #--------------------------------------------------------------------------
  def command_enabled?(index)
    @list[index][:enabled]
  end
  #--------------------------------------------------------------------------
  # ● 명령 데이타
  #--------------------------------------------------------------------------
  def command_icon(index)
    @list[index][:icon]
  end
  #--------------------------------------------------------------------------
  # ● 선택 명령
  #--------------------------------------------------------------------------
  def current_data
    index >= 0 ? @list[index] : nil
  end
  #--------------------------------------------------------------------------
  # ● 선택 명령 활성?
  #--------------------------------------------------------------------------
  def current_item_enabled?
    current_data ? current_data[:enabled] : false
  end
  #--------------------------------------------------------------------------
  # ● 선택 명령 심볼
  #--------------------------------------------------------------------------
  def current_symbol
    current_data ? current_data[:symbol] : nil
  end
  #--------------------------------------------------------------------------
  # ● 선택 명령 데이타
  #--------------------------------------------------------------------------
  def current_icon
    current_data ? current_data[:icon] : 0
  end
  #--------------------------------------------------------------------------
  # ● 심볼로 명령 선택
  #--------------------------------------------------------------------------
  def select_symbol(symbol)
    @list.each_index {|i| select(i) if @list[i][:symbol] == symbol }
  end
  #--------------------------------------------------------------------------
  # ● 항목을 그릴 사각형 가져오기 ( 여기가 핵심 )
  #--------------------------------------------------------------------------
  def item_rect(index)
    rect = Rect.new
    rect.width = item_width
    rect.height = item_height
    deg = Math::PI * 1.5 / item_max
    start_deg = -(deg * @index) + deg * index
    new_x = Math.cos(start_deg) * radius
    new_y = Math.sin(start_deg) * radius
    rect.x = ring_center_x + new_x - (item_width / 2)
    rect.y = ring_center_y + new_y - (item_height / 2)
    rect
  end
  #--------------------------------------------------------------------------
  # ● 항목을 그릴 사각형 가져오기 (텍스트)
  #--------------------------------------------------------------------------
  def item_rect_for_text(index)
    rect = item_rect(index)
    rect.x -= radius
    rect.width = radius
    rect
  end
  #--------------------------------------------------------------------------
  # ● 아이템 그리기( 기본적으로 텍스트는 우측 중앙 선택 영역의 좌측으로 표시됨 )
  #--------------------------------------------------------------------------
  def draw_item(index)
    change_color(normal_color, command_enabled?(index))
    rect = item_rect(index)
    draw_icon(command_icon(index), rect.x, rect.y)
    if @index == index
      draw_text(item_rect_for_text(index), command_name(index), alignment)
    end
  end
  #--------------------------------------------------------------------------
  # ● 커서를 위로 이동
  #--------------------------------------------------------------------------
  def cursor_up(wrap = false)
    if index <= 0
      return if !wrap
      select(item_max - 1)
    else
      select(index - 1)
    end
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 커서를 아래로 이동
  #--------------------------------------------------------------------------
  def cursor_down(wrap = false)
    if index >= item_max - 1
      return if !wrap
      select(0)
    else
      select(index + 1)
    end
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 커서를 왼쪽으로 이동( 좌 우 커서 쓰려면 이거랑 밑에꺼 구현하셈 )
  #--------------------------------------------------------------------------
  def cursor_left(wrap = false)
  end
  #--------------------------------------------------------------------------
  # ● 커서를 오른쪽으로 이동
  #--------------------------------------------------------------------------
  def cursor_right(wrap = false)
  end
  #--------------------------------------------------------------------------
  # ● 정렬
  #--------------------------------------------------------------------------
  def alignment
    return 0
  end
  #--------------------------------------------------------------------------
  # ● 결정 활성화
  #--------------------------------------------------------------------------
  def ok_enabled?
    return true
  end
  #--------------------------------------------------------------------------
  # ● 결정 호출
  #--------------------------------------------------------------------------
  def call_ok_handler
    if handle?(current_symbol)
      call_handler(current_symbol)
    elsif handle?(:ok)
      super
    else
      activate
    end
  end
  #--------------------------------------------------------------------------
  # ● 프레임 갱신
  #--------------------------------------------------------------------------
  def refresh
    clear_command_list
    make_command_list
    create_contents
    super
  end
end

그리고 실제 사용은 상속해서 ( VX Ace 기본 룰에 맞춰 짜서 귀찮음 )

#==============================================================================
# ■ Raon_SrpgWindowPlayerCmd
#------------------------------------------------------------------------------
# 플레이어 커맨드 구현
#==============================================================================

class Raon_SrpgWindowPlayerCmd < Raon_WindowRingCmd
  #--------------------------------------------------------------------------
  # ● 객체 초기화
  #--------------------------------------------------------------------------
  def initialize(radius)
    super(0, 0, radius)
    self.opacity = 0
    self.openness = 0
  end
  #--------------------------------------------------------------------------
  # ● 아이템 너비
  #--------------------------------------------------------------------------
  def item_width
    24
  end
  #--------------------------------------------------------------------------
  # ● 아이템 높이 
  #--------------------------------------------------------------------------
  def item_height
    24
  end
  #--------------------------------------------------------------------------
  # ● 명령 목록( 이거 중요 : 1번은 커맨드 이름, 2번은 키워드(핸들러 작성시 넣는거, 3번은 아이콘 인덱스, 4번은 활성이냐?)
  #--------------------------------------------------------------------------
  def make_command_list
    add_command( 커맨드 이름, 키워드,  아이콘 인덱스, 활성이냐)
  end
  #--------------------------------------------------------------------------
  # ● 정렬(이거 글자 정렬 기준임 0 왼쪽 1중앙 2왼쪽)
  #--------------------------------------------------------------------------
  def alignment
    return 1
  end
  #--------------------------------------------------------------------------
  # ● 초기화
  #--------------------------------------------------------------------------
  def setup
    self.openness = 0
    clear_command_list
    make_command_list
    select(0)
    refresh
    activate
    open
  end
  #--------------------------------------------------------------------------
  # ● 백그라운드 그리기(Raon_WindowSelectable에 함수 원형있음 오버라이드 해서 필요한거 그리면됨
  #--------------------------------------------------------------------------
  def draw_background
각자 구현( 위 스샷에 우측 네모 박스를 여기서 그렸음 )
  end
end

이제 실제 사용은

    @player_cmd = Raon_SrpgWindowPlayerCmd.new( 반지름 )
----------------------------------------------------------
핸들러 연결 하시고...( @player_cmd.set_handler(:move,    method(:player_move)) << 요로코롬 생겨 먹은거
----------------------------------------------------------
    @player_cmd.location( 센터 위치 X 좌표,  센터 위치 Y 좌표 )
    @player_cmd.setup
    @player_cmd.open

불펌, 막펌 그런거 없음 다 가져가도됩니다만 자기꺼라고 우기지 맙시다.
써니 소프트 선투척 후 투척...

PS : 쯔끄루 관련 커뮤니티는 몽창 다운됬네요? 이제 죽어가는 컨텐츤가 봐요 아쉽.