RMXP

습작님의 Scene_Item_Select 관련질문 (픽쳐, 커스텀윈도우, 스위치, 정렬)

by 하진 posted Sep 03, 2012
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 댓글로 가기 인쇄
Extra Form
엊그제 습작님께서 알려주신 '아이템선택창'을 써보다가, 몇 가지 벽에 부딪쳐서 관련 질문을 드리려고 합니다.
좀 여러 개라서 보다가 질리실지도... 모르겠지만...... 가능한 한 해결방안을 찾고 싶어서, 들고 왔습니다.

짜주신 스크립트를 커스텀하다가 부딪친 소소한 문제가 3가지, 그 외의 것이 1가지입니다.


우선... 그 외의 것부터 말씀드릴게요.

제가 이 '아이템선택창'을... 픽쳐로 덮인 화면 위에 표시하려고 하거든요.
이 Scene_Item_Select를, 모든 픽쳐보다 상위에 표시되도록 할 수 있을까요?

(특수한 메뉴화면 중에서, 스크립트로 구현하기 너무 까다로워질 부분을 그냥 픽쳐+이벤트로 픽쳐메뉴를 만들어뒀거든요.
그 픽쳐메뉴에서의 선택에 따라, 이어지게 할 것이 이 Scene_Item_Select입니다.
근데 지금 픽쳐메뉴에서 이 Scene을 호출하면, 픽쳐들에 덮여서 아이템선택창이 안 보이게 됩니다.)
픽쳐들을 캐릭터셋 밑으로 깔리게 하는 스크립트는 본 적이 있는데, 그런 식으로 윈도우들 밑에 깔리도록 할 수도 있을까요..?




그리고, 이하는... 커스텀하다 부딪친 소소한 3가지입니다.

일단 제가 수정하느라 추가한 모든 부분을 회색글씨,(좌표 등 수치는 제외)
그 중 문제1) 관련부분을 분홍색글씨, 행끝에 #1
          문제2) 관련부분을 하늘색글씨, 행끝에 #2
          문제3) 관련부분을 보라색글씨, 행끝에 #3 을 붙여보겠습니다.
(회색글씨는 문제가 없었던 부분)


(이하 추가로 붙인 스크립트)
class Window_Guide < Window_Base
  #--------------------------------------------------------------------------
  # ● 오브젝트 초기화
  #--------------------------------------------------------------------------
  def initialize
    super(180, 72, 280, 58)
    self.contents = Bitmap.new(width - 32, height - 32)
    self.back_opacity = 200
    self.contents.font.color = normal_color
    self.contents.font.size = 21
    refresh
  end
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    if $game_switches[27]
     self.contents.draw_text(0, 0, 280, 32, "먹이로 줄 것을 선택하세요.", 1)   #2
    end
    if $game_switches[51]
     self.contents.draw_text(0, 0, 280, 32, "올려둘 물건을 선택하세요.", 1)   #2
    end
  end
end
(이상 추가로 붙인 스크립트)


(이하 수정한 스크립트)
#==============================================================================
# ★ 아이템 선택 시스템 ★ 2009.1.29
#==============================================================================
# 제작자 : lepin@naver.com 
#==============================================================================
# 수 정 : etude87@gmail.com
#==============================================================================
#
# 호출 : $scene = Scene_Item_Select.new("속성의 이름", 변수번호[, 소비여부])
#
# 예> $scene = Scene_Item_Select.new("화염", 1, true)
#
# 소비여부는 생략 가능(생략시 false)
#
#==============================================================================
#
# 아이템일 경우 : 변수 값 = 아이템의 ID
# 무기일 경우 : 변수 값 = 무기의 ID + 1000 
# 방어구일 경우 : 변수 값 = 방어구의 ID + 2000
# 선택하지 않을 경우 : 변수 값 = 0
#
#==============================================================================
class Window_Item_Select < Window_Selectable
  #--------------------------------------------------------------------------
  def initialize(elements)
    back = Spriteset_Map.new   #1
    @elements = elements
    super(120, 120, 400, 264)
    self.back_opacity = 200
    @column_max = 2
    refresh
    self.index = 0
  end
  #--------------------------------------------------------------------------
  def item
    return @data[self.index]
  end
  #--------------------------------------------------------------------------
  def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    @data = []
    for i in 1...$data_items.size
      if $game_party.item_number(i) > 0
        if $data_items[i].element_set.include?($data_system.elements.index(@elements))
          @data.push($data_items[i])
        end
      end
    end
    for i in 1...$data_weapons.size
      if $game_party.weapon_number(i) > 0
        if $data_weapons[i].element_set.include?($data_system.elements.index(@elements))
          @data.push($data_weapons[i])
        end
      end
    end
    for i in 1...$data_armors.size
      if $game_party.armor_number(i) > 0
        if $data_armors[i].guard_element_set.include?($data_system.elements.index(@elements))
          @data.push($data_armors[i])
        end
      end
    end
    @item_max = @data.size
    if @item_max > 0
      self.contents = Bitmap.new(width - 32, row_max * 32)
      for i in 0...@item_max
        draw_item(i)
      end
    end
  end
  #--------------------------------------------------------------------------
  def draw_item(index)
    item = @data[index]
    case item
    when RPG::Item
      number = $game_party.item_number(item.id)
    when RPG::Weapon
      number = $game_party.weapon_number(item.id)
    when RPG::Armor
      number = $game_party.armor_number(item.id)
    end
    self.contents.font.color = normal_color
    x = 4 + index % 2 * (160 + 40)
    y = index / 2 * 32
    rect = Rect.new(x, y, self.width / @column_max - 32, 32)
    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
    bitmap = RPG::Cache.icon(item.icon_name)
    opacity = self.contents.font.color == normal_color ? 255 : 128
    self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
    self.contents.draw_text(x + 32, y, 212, 32, item.name, 0)
    self.contents.draw_text(x + 120, y, 16, 32, ":", 1)
    self.contents.draw_text(x + 120+16, y, 16, 32, number.to_s, 2)
  end
end
#==============================================================================
#==============================================================================
class Scene_Item_Select
  #--------------------------------------------------------------------------
  def initialize(elements, item_variable, item_lose = false)
    @elements = elements
    @item_variable = item_variable
    @item_lose = item_lose
  end
  #--------------------------------------------------------------------------
  def main
    @item_window = Window_Item_Select.new(@elements)
    if $game_switches[27]
     s1 = "먹이로 준다"
     s2 = "그만둔다"
    else
    if $game_switches[51]
     s1 = "올려놓는다"
     s2 = "그만둔다"
    else
     s1 = "선택한다"
     s2 = "그만둔다"     
    end 
   end
    @command_window = Window_Command.new(160, [s1, s2], 1)
    @command_window.y = 240 - @command_window.height / 2
    @command_window.x = 320 - @command_window.width / 2
    @command_window.y = 360
    @command_window.visible = false
    @command_window.active = false
    @guide_window = Window_Guide.new ###
    @guide_window.visible = true ###
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      if $scene != self
        break
      end
    end
    Graphics.freeze
    @item_window.dispose
    @command_window.dispose
    @guide_window.dispose ###
  end
  #--------------------------------------------------------------------------
  def update
    @item_window.update
    @command_window.update
    @guide_window.update ###
    if @item_window.active
      update_item
      return
    end
    if @command_window.active
      update_command
      return
    end
  end
  #--------------------------------------------------------------------------
  def update_item  # 취소하고 맵 귀환시
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      $game_variables[@item_variable] = 0
      @guide_window.visible = false ###
      $game_switches[27] = false  # [관리화면_Food]OFF   #3
      $game_switches[51] = false  # [책상위_Stuff]OFF   #3
      $scene = Scene_Map.new
      return
    end
    if Input.trigger?(Input::C)
      @item = @item_window.item
      unless @item.is_a?(RPG::Item) or @item.is_a?(RPG::Weapon) or @item.is_a?(RPG::Armor)
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      $game_system.se_play($data_system.decision_se)
      @item_window.active = false
      @command_window.index = 0
      @command_window.visible = true
      @command_window.active = true
      @guide_window.visible = true ###
      return
    end
  end
  #--------------------------------------------------------------------------
  def update_command
    @command_window.update
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      @item_window.active = true
      @command_window.visible = false
      @command_window.active = false
      @guide_window.visible = true ###
      return
    end
    if Input.trigger?(Input::C)  # 선택하고 맵 귀환시
      case @command_window.index
      when 0
        $game_system.se_play($data_system.decision_se)
        case @item
        when RPG::Item
          value = 0
          if @item_lose == true
          $game_party.lose_item(@item.id, 1)
          end
        when RPG::Weapon          
          value = 1000
          if @item_lose == true
          $game_party.lose_weapon(@item.id, 1)
          end
        when RPG::Armor
          value = 2000
          if @item_lose == true
          $game_party.lose_armor(@item.id, 1)
          end
        end
        $game_variables[@item_variable] = @item.id + value
        $game_switches[27] = false  # [관리화면_Food]OFF   #3
        $game_switches[51] = false  # [책상위_Stuff]OFF   #3
        $scene = Scene_Map.new
      when 1
        $game_system.se_play($data_system.decision_se)
        @item_window.active = true
        @command_window.visible = false
        @command_window.active = false
        @guide_window.visible = true ###
      end
      return
    end
    if Input.trigger?(Input::UP) or Input.trigger?(Input::L)
      @command_window.index = 0
    end
    if Input.trigger?(Input::DOWN) or Input.trigger?(Input::R)
      @command_window.index = 1
    end
  end
end

(이상 수정한 스크립트)


(이하 문제설명)

문제1) #1
이 아이템선택창이 뜨는 동안에, 뒷배경이 검은색이 되지 않고 여태까지의 맵화면이 남아있게 하기 위해서
  def initialize(elements) 밑에
    back = Spriteset_Map.new
를 넣었거든요. (다른 스크립트에서 복붙했습니다..)

그랬더니 의도대로 배경에 맵화면이 유지됐습니다.
그런데 아이템을 선택하거나 / ESC로 창을 취소한 뒤, 다시 Scene을 호출했더니 게임이 얼어버려요.
ESC를 눌러서 메뉴화면을 보려고 해도 얼어버리고요. F9(디버그) 불러도 마찬가지...

뭔가 더 넣어줘야 하는 것 같은데...... 뭐가 더 필요한 건가요?


문제2) #2
[질문]custom_window_align.png
이 부분은 제가 필요한 대로 만들어 넣어본 윈도우인데요(밝은부분).
아이템선택창에서 help_window(아이템설명 뜨는) 대신에, guide_window를 넣어서 '***를 선택하세요' 문구만 계속 떠있도록 한 겁니다. 뜨고 없어지고는 어떻게 잘 되는 것 같은데...

근데 이...... 글자를 좀, 멀쩡하게 가운데정렬할 수 없을까요?;;

커맨드윈도우에 뜨는 글자의 경우, 가운데정렬을 했습니다. Window_Command쪽에 @=align을 추가해서요.
근데 커맨드윈도우가 아닌 경우는... 어떻게 바꿔야 align이 적용되게 할 수 있을지 모르겠네요.
Window_Base쪽을 만져야 되는 게 아닌가 싶은데, Command쪽하곤 생긴 모양도 다르고... 이렇게저렇게 바꿔봐도 오류만 뜰 뿐이고...... 끝에 1 붙였더니, 저모양으로 뜨고......

이런 커스텀윈도우에서도, 가운데정렬을 하고 싶어요... (메시지창의 경우, 사용중인 메시지스크립트에서 지원해줘서 괜찮지만 이건...)


문제3) #3
      $game_switches[27] = false  # [관리화면_Food]OFF
      $game_switches[51] = false  # [책상위_Stuff]OFF
      $scene = Scene_Map.new
이 부분 말인데요. (아이템선택시 / 창 취소시, 특정스위치 끄는 것)

첫 행의 스위치는 잘 꺼지는데, 둘째 행의 스위치는 안 꺼집니다.;;
원래 이런가요? 스위치는 한 번에 1개밖에 조작 못하나요??? (어찌 그런...)
2개 다 끄려면 뭐라고 써야 할까요.

(저 스위치들은 guide_window / s1,s2에 문구를 달리하기 위해, Scene호출 전 상황별로 ON하는 것들입니다)



질문이 너무 많아 죄송합니다. ㅠㅠ
하지만, 가능한 만큼만이라도 답을 얻어갈 수 있었으면 좋겠습니다.