All pastes #1488106 Raw Edit

Miscellany

public ruby v1 · immutable
#1488106 ·published 2009-07-08 12:24 UTC
rendered paste body
=beginひきも記 ( http://hikimoki.hp.infoseek.co.jp/ ) さんの RGSS2_RTS新ver をマウスで操作できるようにしてみました。RGSS2_RTS新ver を導入した後で、セクション「(ここに追加)」以降においてください。ポインタがウィンドウの外にあるか、Mouse.enable = false としたとき無効化されます。操作方法:・一般:左ボタン:決定キーと同様 右ボタン:キャンセルキーと同様・マップシーン: 左ボタン押しっぱなし:ポインタ方向へ移動・部隊編成シーン: アクティブな選択ウィンドウ上でのポインタ移動:カーソル移動 部隊編成ウィンドウ上:  - 左ボタン:人数増加  - 右ボタン:人数減少 スキル選択ウィンドウ上:  - 左ボタン:スキルの ON/OFF・RTS シーン: 下部ウィンドウ上:  - 左右ボタン:選択キャラクターの変更=end# ------------------------- ここから マウスのコア部分 -------------------------#==============================================================================# ■ Mouse#------------------------------------------------------------------------------#  マウスの入力情報およびポインタの移動・表示操作を扱うモジュール。#==============================================================================module Mouse  #--------------------------------------------------------------------------  # ● Win32API 定数定義  #--------------------------------------------------------------------------  GetActiveWindow = Win32API.new("user32", "GetActiveWindow", "", "i")  GetCursorPos = Win32API.new("user32", "GetCursorPos", "p", "i")  SetCursorPos = Win32API.new("user32", "SetCursorPos", "ii", "i")  ScreenToClient = Win32API.new("user32", "ScreenToClient", "ip", "i")  ClientToScreen = Win32API.new("user32", "ClientToScreen", "ip", "i")  GetAsyncKeyState = Win32API.new("user32", "GetAsyncKeyState", "i", "i")  ShowCursor = Win32API.new("user32", "ShowCursor", "i", "i")    # マウスボタンの入れ替え対応  if Win32API.new('user32', 'GetSystemMetrics', 'i', 'i').call(23) == 0    LBUTTON = 1    RBUTTON = 2  else    LBUTTON = 2    RBUTTON = 1  end    # マウスの状態を保存するインスタンス変数の初期設定  # 注:RGSSプレーヤは非アクティブ時に停止するので、GetActiveWindow で問題ないはず  @hwnd = GetActiveWindow.call # ウィンドウハンドル  @point = [0, 0].pack("ii")   # マウス座標、Win32API とのインタフェース用  @button = Hash.new(0)        # ボタンの押下状態(押され続けたフレーム数を記録)    #==============================================================================  # ■ Mouse の特異クラス定義  #     この部分に記載されたメソッドは、Mouse.method の形で呼び出される  #==============================================================================  class <<self    #--------------------------------------------------------------------------    # ● 公開インスタンス変数    #--------------------------------------------------------------------------    attr_accessor :enable # マウス使用の可否    #--------------------------------------------------------------------------    # ● 更新    #--------------------------------------------------------------------------    def update      # マウスポインタのウィンドウ座標取得      GetCursorPos.call(@point)      ScreenToClient.call(@hwnd, @point)      @old_cx, @old_cy = @cx, @cy      @cx, @cy = @point.unpack("ii")      # 描画範囲外(タイトルバー上など)にポインタがある場合      if @cx < 0 || @cy < 0        # ボタン無効        @button.clear      # 描画範囲内にポインタがある場合      else        # ボタンの押されたフレーム数を記録        [LBUTTON, RBUTTON].each do |button|          state = GetAsyncKeyState.call(button)          if state & (1<<15) != 0            @button[button] += 1          elsif @button[button] > 0            @button[button] *= -1          else            @button[button] = 0          end        end      end    end    #--------------------------------------------------------------------------    # ● ボタンが押されているかの判定    #     button : ボタンの種類    #     frame  : 押されたと判定する最低フレーム数    #--------------------------------------------------------------------------    def press?(button, frame = 1)      @button[button] > frame    end    #--------------------------------------------------------------------------    # ● ボタンが新しく押されたかの判定    #     button : ボタンの種類    #--------------------------------------------------------------------------    def trigger?(button)      @button[button] == 1    end    #--------------------------------------------------------------------------    # ● ボタンが新しく押されたかの判定(リピート考慮)    #     button : ボタンの種類    #--------------------------------------------------------------------------    def repeat?(button)      @button[button] == 1 || (@button[button] > 21 && @button[button] % 6 == 1)    end    #--------------------------------------------------------------------------    # ● ボタンが新しく離されたかの判定    #     button : ボタンの種類    #--------------------------------------------------------------------------    def release?(button)      @button[button] < 0    end    #--------------------------------------------------------------------------    # ● ボタンがクリックされたかの判定    #     button : ボタンの種類    #     frame  : フレーム数の許容範囲    #--------------------------------------------------------------------------    def click?(button, frame = 10)      @button[button] < 0 && @button[button] >= -frame    end    #--------------------------------------------------------------------------    # ● マウスポインタが移動したかの判定    #--------------------------------------------------------------------------    def move?      return @old_cx != @cx || @old_cy != @cy    end    #--------------------------------------------------------------------------    # ● マウスポインタの座標    #--------------------------------------------------------------------------    def pos      return @cx, @cy    end    #--------------------------------------------------------------------------    # ● マウスポインタの移動量    #--------------------------------------------------------------------------    def move      return @cx - @old_cx, @cy - @old_cy    end    #--------------------------------------------------------------------------    # ● マウスカーソルの可視状態の変更    #     visible : 新しい可視状態    #--------------------------------------------------------------------------    def visible=(visible)      ShowCursor.call(if visible then 1 else 0 end)    end    #--------------------------------------------------------------------------    # ● マウスポインタの移動    #     x : X 座標    #     y : Y 座標    #--------------------------------------------------------------------------    def set_pos(x, y)      return if @pos_fix      @point = [x, y].pack("ii")      ClientToScreen.call(@hwnd, @point)      @cx, @cy = @point.unpack("ii")      SetCursorPos.call(@cx, @cy)    end    #--------------------------------------------------------------------------    # ● マウスポインタの移動命令 (set_pos メソッド) を制限    #     与えられたブロック内でのマウスポインタの移動命令を無視する    #--------------------------------------------------------------------------    def fix_pos      @pos_fix = true      yield      @pos_fix = false    end    #--------------------------------------------------------------------------    # ● マウスポインタが範囲内にあるかどうかの判定    #     area : 範囲を示すオブジェクト、Window, Rectなど    #     opt  : 範囲オブジェクト別のオプション    #--------------------------------------------------------------------------    def is_on?(area, opt = nil)      x1 = x2 = y1 = y2 = nil      case area      when Window        case opt        when nil          x1 = area.x          y1 = area.y          x2 = area.x + area.width          y2 = area.y + area.height        when :contents          x1 = area.x + 16          y1 = area.y + 16          x2 = area.x + [area.contents.width , area.width ].min - 16          y2 = area.y + [area.contents.height, area.height].min - 16        else          raise TypeError.new("invalid option : #{opt}")        end      when Rect        x1 = area.x        y1 = area.y        x2 = area.x + area.width        y2 = area.y + area.height      when :screen        x1 = 0        y1 = 0        x2 = Graphics.width        y2 = Graphics.height      else        raise TypeError.new("not a area : #{area}")      end      return (x1..x2) === @cx && (y1..y2) === @cy    end  endend# マウスを有効にするMouse.enable = true# ----------------------- ここから RPG 一般に対する変更 -----------------------#==============================================================================# ■ Input#------------------------------------------------------------------------------#  ゲームパッドやキーボードからの入力情報を扱うモジュール。#==============================================================================module Input  unless respond_to?(:update_key) # 多重 alias 防止    class <<self      alias update_key update      def update        update_key        Mouse.update if Mouse.enable      end      # 同じような内容なので trigger?, press?, repeat? の定義をまとめて行う      ["trigger", "press", "repeat"].each do |name|        eval(<<-EOS.gsub(/input_type/, name))        alias input_type_key? input_type?        def input_type?(key)          result = false          if Mouse.enable            button = {C => Mouse::LBUTTON, B => Mouse::RBUTTON}[key]            result = Mouse.input_type?(button) if button          end          return result || input_type_key?(key)        end        EOS      end    end  endend#==============================================================================# ■ Game_Player#------------------------------------------------------------------------------#  プレイヤーを扱うクラスです。イベントの起動判定や、マップのスクロールなどの# 機能を持っています。このクラスのインスタンスは $game_player で参照されます。#==============================================================================class Game_Player  #--------------------------------------------------------------------------  # ● 方向ボタン入力またはマウス操作による移動処理  #--------------------------------------------------------------------------  def move_by_input    return unless movable?    return if $game_map.interpreter.running?    # マウスがウィンドウ上で左ボタンが押されているとき    if Mouse.enable && Mouse.press?(Mouse::LBUTTON, 0) && Mouse.is_on?(:screen)      # マウスポインタ方向に移動      cx, cy = Mouse.pos      if cx < screen_x - 16        move_left      elsif cx > screen_x + 16        move_right      elsif cy < screen_y - 32        move_up      elsif cy > screen_y        move_down      end    end    case Input.dir4    when 2;  move_down    when 4;  move_left    when 6;  move_right    when 8;  move_up    end  endend#==============================================================================# ■ Window_Selectable#------------------------------------------------------------------------------#  カーソルの移動やスクロールの機能を持つウィンドウクラスです。#==============================================================================class Window_Selectable  #--------------------------------------------------------------------------  # ● 画面上のカーソルの X 座標  #--------------------------------------------------------------------------  def cursor_screen_x    x + 16 + cursor_rect.x  end  #--------------------------------------------------------------------------  # ● 画面上のカーソルの Y 座標  #--------------------------------------------------------------------------  def cursor_screen_y    y + 16 + cursor_rect.y  end  #--------------------------------------------------------------------------  # ● フレーム更新  #--------------------------------------------------------------------------  def update    super    if cursor_movable?      last_index = @index      # マウス処理      if Mouse.enable        # マウスポインタがウィンドウ上にあるとき        if Mouse.is_on?(self)          # マウスポインタ方向にカーソル移動          cx, cy = Mouse.pos          if cx < cursor_screen_x            cursor_left(false)          elsif cx > cursor_screen_x + cursor_rect.width            cursor_right(false)          end          if cy < cursor_screen_y            cursor_up(false)          elsif cy > cursor_screen_y + cursor_rect.height            cursor_down(false)          end        end      end      if Input.repeat?(Input::DOWN)        cursor_down(Input.trigger?(Input::DOWN))      end      if Input.repeat?(Input::UP)        cursor_up(Input.trigger?(Input::UP))      end      if Input.repeat?(Input::RIGHT)        cursor_right(Input.trigger?(Input::RIGHT))      end      if Input.repeat?(Input::LEFT)        cursor_left(Input.trigger?(Input::LEFT))      end      if Input.repeat?(Input::R)        cursor_pagedown      end      if Input.repeat?(Input::L)        cursor_pageup      end      if @index != last_index        Sound.play_cursor      end    end    update_cursor    call_update_help  endend#==============================================================================# ■ Scene_File#------------------------------------------------------------------------------#  ファイル画面の処理を行うクラスです。#==============================================================================class Scene_File < Scene_Base  #--------------------------------------------------------------------------  # ● セーブファイル選択の更新  #--------------------------------------------------------------------------  def update_savefile_selection    if Input.trigger?(Input::C)      determine_savefile    elsif Input.trigger?(Input::B)      Sound.play_cancel      return_scene    else      last_index = @index      if Mouse.enable        index = nil        @savefile_windows.each_with_index do |window, i|          if Mouse.is_on?(window)            @index = i            break          end        end      end      if Input.repeat?(Input::DOWN)        cursor_down(Input.trigger?(Input::DOWN))      end      if Input.repeat?(Input::UP)        cursor_up(Input.trigger?(Input::UP))      end      if @index != last_index        Sound.play_cursor        @savefile_windows[last_index].selected = false        @savefile_windows[@index].selected = true      end    end  endend# -------------------------- ここから RTS 固有の変更 --------------------------#==============================================================================# ■ TRts_Cursor#------------------------------------------------------------------------------#  RTSのカーソルクラス#==============================================================================class TRts_Cursor < Sprite  #--------------------------------------------------------------------------  # ● 公開インスタンス変数  #--------------------------------------------------------------------------  attr_reader :area # マウスポインタがある領域  #--------------------------------------------------------------------------  # ● 更新  #--------------------------------------------------------------------------  def update    # 次の行を有効にすると、カーソルアイコンが表示されずマウスポインタのみ表示される    #self.visible = !Mouse.enable    if Mouse.enable && Mouse.move?      self.x, self.y = Mouse.pos      rect = $game_temp.trts_rect      # マウスポインタの位置を記録(下部ウィンドウ、配置可能領域、それ以外)      if y >= 352        @area = :win      elsif Mouse.is_on?(rect)        @area = :in      else        @area = :out      end    end    if Input.press?(Input::LEFT)      self.x -= 4    elsif Input.press?(Input::RIGHT)      self.x += 4    end    if Input.press?(Input::UP)      self.y -= 4    elsif Input.press?(Input::DOWN)      self.y += 4    end    if self.x < $game_temp.trts_rect.x      self.x = $game_temp.trts_rect.x     elsif self.x >= $game_temp.trts_rect.x + $game_temp.trts_rect.width      self.x = $game_temp.trts_rect.x + $game_temp.trts_rect.width    end    if self.y < $game_temp.trts_rect.y      self.y = $game_temp.trts_rect.y    elsif self.y >= $game_temp.trts_rect.y + $game_temp.trts_rect.height      self.y = $game_temp.trts_rect.y + $game_temp.trts_rect.height    end  endend#==============================================================================# ■ TRts_Scene#------------------------------------------------------------------------------#  RTSのシーンクラス#==============================================================================class TRts_Scene < Scene_Base  #--------------------------------------------------------------------------  # ● 入力処理の更新  #--------------------------------------------------------------------------  def update_input    if Mouse.enable      no_action = false      if @cursor.area == :win        if Mouse.trigger?(Mouse::LBUTTON)          Sound.play_cursor          @player_window.index = @player_window.get_index_next(@player_window.index)          @player_window.refresh        elsif Mouse.trigger?(Mouse::RBUTTON)          Sound.play_cursor          @player_window.index = @player_window.get_index_prev(@player_window.index)          @player_window.refresh        else          no_action = true        end      elsif Mouse.trigger?(Mouse::LBUTTON)   # キャラクターを配置        if ($game_temp.trts_member[@player_window.index][0] > 0 &&          @actor_num < $game_variables[TRTS::Options::BATTLE_ACTOR_MAX] &&          @cursor.area == :in)          $game_temp.trts_member[@player_window.index][0] -= 1          add_character(@cursor.x, @cursor.y, @player_window.index + 1)        else          Sound.play_buzzer   # 配置不可ならブザーを鳴らす        end      elsif Mouse.trigger?(Mouse::RBUTTON)   # 配置領域の表示切替        @area.visible = !@area.visible      elsif Input.trigger?(Input::F5) # ギブアップ        set_gameover(49)      else        no_action = true      end      return unless no_action    end    if Input.trigger?(Input::C)   # キャラクターを配置      if ($game_temp.trts_member[@player_window.index][0] > 0 &&      @actor_num < $game_variables[TRTS::Options::BATTLE_ACTOR_MAX])        $game_temp.trts_member[@player_window.index][0] -= 1        add_character(@cursor.x, @cursor.y, @player_window.index + 1)      else        Sound.play_buzzer   # 配置不可ならブザーを鳴らす      end    elsif Input.trigger?(Input::B)  # 配置領域の表示切替      @area.visible = !@area.visible    elsif Input.trigger?(Input::F5) # ギブアップ      set_gameover(49)    elsif Input.trigger?(Input::R)  # キャラクター選択(Rボタン)      Sound.play_cursor      @player_window.index = @player_window.get_index_next(@player_window.index)      @player_window.refresh    elsif Input.trigger?(Input::L)  # キャラクター選択(Lボタン)      Sound.play_cursor      @player_window.index = @player_window.get_index_prev(@player_window.index)      @player_window.refresh    end  endend#==============================================================================# ■ TRts_Edit_Scene#------------------------------------------------------------------------------#  部隊編成のシーンクラスです。#==============================================================================class TRts_Edit_Scene < Scene_Base  #--------------------------------------------------------------------------  # ● 部隊人数の変更  #     delta : 増減の方向 (1 または -1)  #--------------------------------------------------------------------------  def character_num_change(delta)    i = @character_window.item    # 増減可能な場合    if @character_window.enable?(i) &&       ((delta > 0 && @point + TRTS::Options::JOB_STATE[i + 1][4] <= $game_variables[TRTS::Options::MEMBER_POINT]) ||        (delta < 0 && $game_temp.trts_member[i][0] > 0))      $game_temp.trts_member[i][0] += delta      @point += TRTS::Options::JOB_STATE[i + 1][4] * delta      @character_window.refresh      @status_window.refresh      Sound.play_cursor    # 増減できなかった場合    else      Sound.play_buzzer    end  end  #--------------------------------------------------------------------------  # ● 部隊ウィンドウの更新  #--------------------------------------------------------------------------  def update_character_selection    @character_window.update    # マウスポインタがウィンドウ上にある場合    if Mouse.enable && Mouse.is_on?(@character_window)      if Mouse.repeat?(Mouse::LBUTTON)        character_num_change(1)        return      elsif Mouse.repeat?(Mouse::RBUTTON)        character_num_change(-1)        return      end    end    if Input.trigger?(Input::B)      Sound.play_cancel      @command_window.active = true      @character_window.active = false      @character_window.visible = false      return    elsif Input.trigger?(Input::C)      Sound.play_decision      @command_window.active = true      @character_window.active = false      @character_window.visible = false      return    elsif Input.repeat?(Input::RIGHT)      character_num_change(1)    elsif Input.repeat?(Input::LEFT)      character_num_change(-1)    end  end  #--------------------------------------------------------------------------  # ● スキルウィンドウの更新  #--------------------------------------------------------------------------  def update_skill_selection    @skill_window.update    i = @skill_window.item    # マウスポインタがウィンドウ上にある場合    if Mouse.enable && Mouse.is_on?(@skill_window)      if Mouse.trigger?(Mouse::LBUTTON) && i != nil        if @skill[i] == 1          @skill[i] = 0          @skill_point -= TRTS::Options::SKILL_STATE[i + 1][1]          @skill_window.refresh          @status_window.refresh          Sound.play_cursor        elsif @skill_point + TRTS::Options::SKILL_STATE[i + 1][1] <= $game_variables[TRTS::Options::SKILL_POINT]          @skill[i] = 1          @skill_point += TRTS::Options::SKILL_STATE[i + 1][1]          @skill_window.refresh          @status_window.refresh          Sound.play_cursor        else          Sound.play_buzzer        end        return      end    end    if Input.trigger?(Input::B)      Sound.play_cancel      @command_window.active = true      @skill_window.active = false      @skill_window.visible = false      return    elsif Input.trigger?(Input::C)      Sound.play_decision      @command_window.active = true      @skill_window.active = false      @skill_window.visible = false      return    end    return if i == nil    # 選択中のスキルが空なら終了    if Input.trigger?(Input::RIGHT)      if @skill[i] == 0 and      @skill_point + TRTS::Options::SKILL_STATE[i + 1][1] <= $game_variables[TRTS::Options::SKILL_POINT]        @skill[i] = 1        @skill_point += TRTS::Options::SKILL_STATE[i + 1][1]        @skill_window.refresh        @status_window.refresh        Sound.play_cursor      else        Sound.play_buzzer      end    elsif Input.trigger?(Input::LEFT)      if @skill[i] == 1        @skill[i] = 0        @skill_point -= TRTS::Options::SKILL_STATE[i + 1][1]        @skill_window.refresh        @status_window.refresh        Sound.play_cursor      else        Sound.play_buzzer      end    end  endend