VX 스크립트

입력 기능 확장 스크립트 추가. [전체키 스크립트]
게임제작에 도움을 주는 스크립트라고 생각되어 추가 하게되었습니다.

사용예
# Input.trigger?(Input::F2)          # F2를 누르거나 (F2 ~ F11)
# Input.trigger?(Input::NUM[0])      # 0을 누르거나 (0 ~ 9)
# Input.trigger?(Input::A_Z["A"])    # A를 누르거나 (A ~ Z)

조건 분기에서 아래와 같이 사용가능
사용자 삽입 이미지






















위와 같이 사용할경우 F2번 키를 눌렀을대를 검사하여 조건분기를 실행할수 있다.



#================================================= =============================
# ★ 입력 기능 확장 var 1.0 (07.11.12) by shun
#------------------------------------------------- -----------------------------
# 주로 Input 모듈을 확장합니다. (확장의 내용은 하단의 사이트 참조)
# 이렇게하면 사용 키를 늘려 마우스 통한 입력 수있습니다.
#================================================= =============================
# 사용 예
# Input.trigger?(Input::F2)          # F2를 누르거나 (F2 ~ F11)
# Input.trigger?(Input::NUM[0])      # 0을 누르거나 (0 ~ 9)
# Input.trigger?(Input::A_Z["A"])    # A를 누르거나 (A ~ Z)
#================================================= =============================
# ■ API
#------------------------------------------------- -----------------------------
# Win32API 대한 모듈입니다.
#================================================= =============================

module API
  #--------------------------------------------------------------------------
  # ● 定数
  #--------------------------------------------------------------------------
  INI_FILE = '.Game.ini'   # 使用する ini ファイルのパス
  #--------------------------------------------------------------------------
  # ● モジュール変数
  #--------------------------------------------------------------------------
  # Win32API の関数を取得
  @@screen_to_client =
    Win32API.new('user32', 'ScreenToClient', ['l', 'p'], 'i')
  #--------------------------------------------------------------------------
  # 以降、モジュール関数として定義
  #--------------------------------------------------------------------------
  module_function
  #--------------------------------------------------------------------------
  # ● ini ファイルの情報を取得
  #     sec     : セクション名
  #     key     : キーワード名
  #     default : 取得に失敗した際に返す文字列
  #     size    : 情報バッファのサイズ (取得する文字数の上限)
  #--------------------------------------------------------------------------
  def read_ini(sec, key, default = "", size = 0xfff)
    # GetPrivateProfileStringA を取得していないなら取得
    unless defined?(@@get_private_profile_string)
      ary = ['p', 'p', 'p', 'p', 'l', 'p']
      @@get_private_profile_string =
        Win32API.new('kernel32', 'GetPrivateProfileStringA', ary, 'l')
    end
    # 情報バッファにヌル文字 (文字コード 0) を設定
    buffer = 0.chr
    # GetPrivateProfileStringA をコール
    @@get_private_profile_string.call(sec, key, default, buffer, size, INI_FILE)
    return buffer
  end
  #--------------------------------------------------------------------------
  # ● ゲームのタイトルを取得
  #--------------------------------------------------------------------------
  def get_title
    # 既に取得されている場合
    return @@title if defined?(@@title) and not @@title == ""
    # ini ファイルを読み込む
    @@title = read_ini("Game", "Title")
    return @@title
  end
  #--------------------------------------------------------------------------
  # ● ウィンドウハンドルを取得
  #--------------------------------------------------------------------------
  def get_hwnd
    # 既に取得されている場合
    return @@hwnd if defined?(@@hwnd) and not @@hwnd == 0
    # FindWindowA を取得・コール
    find_window = Win32API.new('user32', 'FindWindowA', ['p', 'p'], 'l')
    @@hwnd = find_window.call('RGSS Player', get_title)
    return @@hwnd
  end
  #--------------------------------------------------------------------------
  # ● スクリーン座標をクライアント座標に変換
  #     pos : スクリーン座標が格納 (パック) されている POINT 構造体
  #--------------------------------------------------------------------------
  def to_client(pos)
    # 処理に時間がかかると強制終了してしまうので、
    # 別のスレッドで ScreenToClient をコールして結果を取得する
    @result = 0
    Thread.new(9) {@result = @@screen_to_client.call(get_hwnd, pos)}.join
    # エラーの場合
    if @result == 0
      return nil, nil
    else
      # 変換されたクライアント座標をアンパック
      return pos.unpack('ll')
    end
  end
  #--------------------------------------------------------------------------
  # ● クライアント座標をスクリーン座標に変換
  #     pos : クライアント座標が格納 (パック) されている POINT 構造体
  #--------------------------------------------------------------------------
  def to_screen(pos)
    # ClientToScreenA を取得していないなら取得
    unless defined?(@@client_to_screen)
      @@client_to_screen =
        Win32API.new('user32', 'ClientToScreenA', ['l', 'p'], 'i')
    end
    # エラーの場合
    if @@client_to_screen.call(get_hwnd, pos) == 0
      return nil, nil
    else
      # 変換されたスクリーン座標をアンパック
      return pos.unpack('ll')
    end
  end
end


#==============================================================================
# ■ Graphics (追加定義)
#------------------------------------------------------------------------------
#  グラフィック全体にかかわる処理を行うモジュールです。
#==============================================================================

module Graphics
  #--------------------------------------------------------------------------
  # ○ マウスカーソルの表示設定
  #     visible : カーソルの可視状態 (真のとき可視)
  #--------------------------------------------------------------------------
  def self.cursor_visible=(visible)
    # ShowCursor を取得していないなら取得
    unless defined?(@@show_cursor)
      @@show_cursor = Win32API.new('user32', 'ShowCursor', 'l', 'l')
    end
    # ShowCursor をコールして、表示カウントを設定
    count = (visible ? 1 : 0)
    @@show_cursor.call(count)
  end
end


#==============================================================================
# ■ Input (追加定義)
#------------------------------------------------------------------------------
#  ゲームパッドやキーボードからの入力情報を扱うモジュールです。
#==============================================================================

#------------------------------------------------------------------------------
# ○ Input モジュール関数のエイリアス
#------------------------------------------------------------------------------
# F12 による再起動対策
#  (ゲーム停止のための例外が発生させられ、その位置の情報が $@ に代入される)
unless $@
  class << Input
    # キー入力判定メソッド (既存のキーの場合、呼び戻す)
    alias :__orig_press? :press?
    alias :__orig_trigger? :trigger?
    alias :__orig_repeat? :repeat?
    # フレーム更新を拡張する
    alias :__orig_update :update
  end
end

module Input
  #--------------------------------------------------------------------------
  # ● 定数
  #--------------------------------------------------------------------------
  F2 = 90   # F2 キーに対応する番号
  F3 = 91   # F3 キーに対応する番号
  F4 = 92   # F4 キーに対応する番号
  F10 = 98  # F11 キーに対応する番号
  F11 = 99  # F11 キーに対応する番号
  # 数字キー (0..9) 対応する番号の配列
  NUM = [100, 101, 102, 103, 104, 105, 106, 107, 108, 109]
  # A キーから Z キーまでに対応する番号のハッシュ
  A_Z = {
    "A" => 110, "B" => 111, "C" => 112, "D" => 113, "E" => 114,
    "F" => 115, "G" => 116, "H" => 117, "I" => 118, "J" => 119,
    "K" => 120, "L" => 121, "M" => 122, "N" => 123, "O" => 124,
    "P" => 125, "Q" => 126, "R" => 127, "S" => 128, "T" => 129,
    "U" => 130, "V" => 131, "W" => 132, "X" => 133, "Y" => 134, "Z" => 135
  }
  # クリックに対応する番号のハッシュ
  CLICK = {"L" => 136, "R" => 137, "M" => 139}
  # 仮想キーコードの配列
  #   [F1キー, 0キー, A キー, 左クリック]
  VK = [0x70, 0x30, 0x41, 0x01]
  #--------------------------------------------------------------------------
  # ○ モジュール変数
  #--------------------------------------------------------------------------
  # Win32API の関数を取得
  @@get_keystate = Win32API.new('user32', 'GetAsyncKeyState', 'i', 'i')
  @@get_cursor_pos = Win32API.new('user32', 'GetCursorPos', 'p', 'i')
  # キーの押下フレーム数のハッシュ (仮想キーコード => フレーム数)
  @@press_count = {}
  #--------------------------------------------------------------------------
  # 以降、モジュール関数として定義
  #--------------------------------------------------------------------------
  module_function
  #--------------------------------------------------------------------------
  # ○ 仮想キーコードを取得
  #     num : キーに対応する番号
  #--------------------------------------------------------------------------
  def vkey(num)
    case num
    when 89..99  # ファンクションキー (F2..F4, F10, F11)
      return VK[0] + num - 89
    when 100..109  # 数字キー
      return VK[1] + num - 100
    when 110..135  # A から Z キー
      return VK[2] + num - 110
    when 136..139  # クリック
      return VK[3] + num - 136
    end
  end
  #--------------------------------------------------------------------------
  # ○ キーの押下状態を取得
  #     vk_code : 仮想キーコード
  #--------------------------------------------------------------------------
  def key_state(vk_code)
    # GetAsyncKeyState をコール
    state = @@get_keystate.call(vk_code)
    # 現在押されているまたは前回の取得以降に押された場合、真を返す
    return (state.abs == 0x8000 or state.abs == 0x8001)
  end
  #--------------------------------------------------------------------------
  # ● 押下判定
  #     num :キーに対応する番号
  #--------------------------------------------------------------------------
  def press?(num)
    # 既存のキーの場合、呼び戻す
    return __orig_press?(num) if num < 85
    vk = vkey(num)
    # 既に押されているか確認できない場合
    if @@press_count[vk].nil?
      # キーの押下状態を取得
      if key_state(vk)
        @@press_count[vk] = 0
        return true
      else
        return false
      end
    # 既に押されている場合、真を返す
    else
      return true
    end
  end
  #--------------------------------------------------------------------------
  # ● 新規押下判定
  #     num :キーに対応する番号
  #--------------------------------------------------------------------------
  def trigger?(num)
    # 既存のキーの場合、呼び戻す
    return __orig_trigger?(num) if num < 85
    # 直前に押されていないかどうかを取得
    count = @@press_count[vkey(num)]
    # 既に新規で押されていることが確認された場合、真を返す
    return true if count == 0
    # それ以外で直前に押されておらず現在押されている場合、真を返す
    return (count.nil? and press?(num))
  end
  #--------------------------------------------------------------------------
  # ● 新規押下判定 (リピートを含む)
  #     num :キーに対応する番号
  #--------------------------------------------------------------------------
  def repeat?(num)
    # 既存のキーの場合、呼び戻す
    return __orig_repeat?(num) if num < 85
    # 新たに押された場合、真を返す
    return true if trigger?(num)
    # 既に押されていることが確認できない場合、偽を返す
    count = @@press_count[vkey(num)]
    return false if count.nil?
    # リピート判定を行う
    return (count >= 15 and (count - 15) % 4 == 0)
  end
  #--------------------------------------------------------------------------
  # ○ マウスカーソルの座標を取得
  #     anywhere : ウィンドウ外でも、座標を返す
  #--------------------------------------------------------------------------
  def cursor_pos(anywhere=true)
    # 格納する POINT 構造体を定義
    pos = [0, 0].pack('ll')
    # エラーの場合
    if @@get_cursor_pos.call(pos) == 0
      return nil, nil
    else
      # ウィンドウ内でない場合
      if not anywhere and
         not ((0..640).include?(pos[0]) and (0..480).include?(pos[1]))
        return nil, nil
      end
      # スクリーン座標をクライアント座標に修正して返す
      return API.to_client(pos)
    end
  end
  #--------------------------------------------------------------------------
  # ○ マウスカーソルの座標を設定
  #     coord : 座標の配列 [X 座標, Y 座標]
  #--------------------------------------------------------------------------
  def cursor_pos=(coord)
    # スクリーン座標に変換
    x, y = API.to_screen(coord.pack('ll'))
    # 座標が無効なら、中断
    return unless x.is_a?(Integer) and y.is_a?(Integer)
    # SetCursorPosA を取得していないなら取得
    unless defined?(@@set_cursor_pos)
      @@set_cursor_pos =
        Win32API.new('user32', 'SetCursorPosA', ['i', 'i'], 'i')
    end
    @@set_cursor_pos.call(x, y)
  end
  #--------------------------------------------------------------------------
  # ● フレーム更新
  #--------------------------------------------------------------------------
  def update
    # 呼び戻す
    __orig_update
    # マウス入力の押下フレーム数を更新
    @@press_count.each {|vk, count|
      next if count.nil?
      @@press_count[vk] = (key_state(vk) ? count + 1 : nil)
    }
  end
end


#==============================================================================
# □ Sprite_MouseCursor
#------------------------------------------------------------------------------
#  マウスカーソル表示用のスプライトです。Input モジュールによりマウスカーソル
# の座標を監視し、スプライトの状態を自動的に変化させます。
#==============================================================================

class Sprite_MouseCursor < Sprite
  #--------------------------------------------------------------------------
  # ● クラス変数
  #--------------------------------------------------------------------------
  # 使用不可能なグラフィックファイル名の配列
  @@unavailable_file = []
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #     filename : カーソルグラフィック (ピクチャ) のファイル名
  #--------------------------------------------------------------------------
  def initialize(filename = "")
    super()
    @cursor_name = [filename, filename + "_cl"]
    self.bitmap = RPG::Cache.picture(filename)
    self.z = 10001
    update
  end
  #--------------------------------------------------------------------------
  # ● 解放
  #--------------------------------------------------------------------------
  def dispose
    self.bitmap.dispose
    super
  end
  #--------------------------------------------------------------------------
  # ● グラフィックを変更
  #     filename : カーソルグラフィック (ピクチャ) のファイル名
  #--------------------------------------------------------------------------
  def cursor_name=(filename)
    # 変更が無い場合
    return if @filename == filename
    @filename = filename
    # ファイルが存在しないなどで、読み込めない場合を考慮
    begin
      return if @@unavailable_file.include?(filename)
      self.bitmap = RPG::Cache.picture(filename)
    rescue
      @@unavailable_file.push(filename)
    end
  end
  #--------------------------------------------------------------------------
  # ● フレーム更新
  #--------------------------------------------------------------------------
  def update
    super
    # 左クリックが押されている場合、画像を変更
    num = (Input.press?(Input::CLICK["L"]) ? 1 : 0)
    self.cursor_name = @cursor_name[num]
    # カーソルの座標を取得
    x, y = Input.cursor_pos(false)
    # 座標が無効でなければ、スプライトの座標を更新
    self.x, self.y = x, y unless x.nil? or y.nil?
  end
end

#================================================= =============================
# ★ 정보
#------------------------------------------------- -----------------------------
# 제작
# shun
# HP : Simp (http://simp.u-abel.net)
#================================================= =============================


Comment '22'
  • profile
    아방스 2008.08.25 12:29

    다른분이 올리신자료도있던데...

    그건 기존에 키입력처리가 가능했던 버튼들...즉 방향키나 결정키 등등 을 조건분기 하는데 문제가 있다더군요.

    이건문제가 없는것 같아서 올립니다.

    기존에 문제가 된 스크립트주소를 아래
    http://avangs.info/zbxe/178901

  • ?
    읽어버린세계 2008.10.18 12:46
    이스크립트는 문제가없다는거네요.
    http://avangs.info/zbxe/178901 여기에는 문제가있고요.
  • profile
    ⌒_⌒ 2008.08.27 18:19

    ...!! 일본어도 있다. ㅎㅎ 아무튼 감사합니다. 아방스님~!

  • ?
    푸른★ 2008.09.02 21:50
    무슨말임????????????????????????????????
  • ?
    ★찜찜 2008.09.17 10:29
    제가 찾고 있던 거임. 감사해요~
  • ?
    야즈아엘 2008.09.27 08:17
    오 감사합니다,,,
  • ?
    읽어버린세계 2008.10.18 12:53
    키보드 방향키는 어떻게해야되나요?
    조건분기로 아래를 눌렀다 이런거 안되던데...
  • ?
    다크아머 2008.10.25 10:50
    VX는 스크립도 조건분기가 가능하구나!
  • ?
    흑기사 2008.11.16 16:49
    안되는데요
    조건분기 스크립트에 # Input.trigger?(Input::A_Z["A"])  써넣고
    그속에 문장의표시 안녕 이라고 넣으면 A를 아무리 눌러도 안녕이라는 문구가 안뜨는데요.
  • ?
    방콕족의생활 2008.12.10 18:55
    안녕하세요. 정말오랫만에 접속하네요.
    몇몇 분들의 혼동이 있을까봐 미리 답글달아드려요.
    맨위의 사용예

    # Input.trigger?(Input::F2)          # F2를 누르거나 (F2 ~ F11)
    # Input.trigger?(Input::NUM[0])      # 0을 누르거나 (0 ~ 9)
    # Input.trigger?(Input::A_Z["A"])    # A를 누르거나 (A ~ Z)
    하고 사진을 첨부해주셨는데요

    사진에 # Input.trigger?(Input::F2)  이렇게 실수하셧더라구요
    입력할 땐 #을 빼고 해야 실행됩니다.; -> Input.trigger?(Input::F2)
    또한 흑기사님이 질문하셧던 것도 #을 빼고 쓰면 정상작동됩니다.

  • profile
    아방스 2009.02.15 01:43
    아....

    #  잊었군
  • ?
    하얀모자 2009.10.22 10:56
    이것처럼하니까 게임시작할때 '이 메모리는"read"될수없습니다 계속하시려면 확인 디버그하시려면 취소를 눌러주세요. '라는 문구가 뜨는데요
  • ?
    Aakerse 2009.01.15 17:47
    잘쓸게요
  • ?
    하얀모자 2009.09.13 17:59

    맵 만들때 마다 넣어야 하나요?

  • ?
    078656577er 2009.10.22 15:43

    잘 되는 군요

  • ?
    알피쥐초보자 2010.01.11 16:23

    와~!이런신의스크립트가있었다니!!아방스님짱!!

  • profile
    ★☆legend game☆★ 2010.01.30 15:21

    짱조은 스크립

  • ?
    미스터Joker 2010.02.12 11:32

    근데 엔터는 못쓰는 건가요????

  • profile
    아방스 2012.07.09 23:58
    스크립트에 너무 의존 하지마세요~
    엔터키는 기본으로 지원하지 않나요? ^___^
  • ?
    질풍처럼 2010.08.24 00:35

    오예!!!!!!!!!!!!!!!

    감사하다풍.

  • ?
    광우병 멧돼지 2011.03.06 10:30

    감사합니다

  • ?
    최닉네임 2011.06.14 21:05

    11