注册会员 登录
Project1 返回首页

QQEat https://rpg.blue/?326184 [收藏] [复制] [分享] [RSS] 这个人很懒,什么也没留下。

日志

【RM】Input输入模块增强v1.1

已有 224 次阅读2019-1-26 11:53 |个人分类:脚本

#encoding:utf-8
#==============================================================================
# ■ 输入模块增强v1.1 By_QQEat
#
#   说明:处理按键输入操作等
#
#
#   [先调用初始化, v1.1及以后的版本底部自动调用了, 无需手动在调用]
#
#     Input.init
#
#   [方法]
#     
#     Input.bind(key, action)
#     Input.unbind(key)
#     Input.unbindAll
#
#     Input.pressed(tag)
#     Input.released(tag)
#     Input.down(tag, interval=0, delay=0)
#     Input.sequence(*args)
#
#   [范例]
#
#     # 将 A 键绑定到一个执行方法
#     Input.bind('A', proc { p '按下了 A 键' })
#
#     # 将 S 键绑定到标签 'tag'
#     Input.bind('S', 'tag')
#
#     # 判断key是否有绑定执行方法
#     Input.has_proc?(key)
#
#     # 返回一个数组, 获取当前key绑定的所有标签
#     Input.get_tags(key)
#
#     # 判断 'tag' 标签绑定的键位是否被按下时(被按下时激活一次, 注意是pressed而不是press)
#     Input.pressed('tag')
#
#     # 判断 'tag' 标签绑定的键位是否被松开时(被松开时激活一次, 注意是released而不是release)
#     Input.released('tag')
#
#     # 处理 'tag' 标签绑定的键位按下后的操作
#     # 按下后返回一次真,持续按住 60 帧后,每 30 帧返回一次真
#     Input.down('tag', 30, 60)
#
#     # 处理 'tag' 标签绑定的键位在规定帧数内连续按下后的操作
#     # 按下tag,按下后20帧内按下tag2,按下后30帧内按下tag3,返回真
#     Input.sequence('tag', 20, 'tag2', 30, 'tag3')
#
#     # 删除 A 键绑定的所有标签和执行方法
#     Input.unbind('a')
#
#     # 删除所有绑定
#     Input.unbindAll
#
#  [v1.1更新内容_2019.08.22]
#     1)、修复错误:
#           RuntimeError: can't add a new key into hash during iteration
#     2)、脚本底部自动调用 Input.init
#     3)、新增方法:
#           Input.has_proc?(key) # 判断key是否有绑定执行方法
#           Input.get_tags(key) # 返回一个数组, 获取当前key绑定的所有标签
#
#==============================================================================

module Input
  module_function
  #--------------------------------------------------------------------------
  # ● APIS
  #--------------------------------------------------------------------------
  GetKeyState = Win32API.new("user32","GetAsyncKeyState",['I'],'I')
  GetKeyboardState = Win32API.new("user32","GetKeyState",['I'],'I')
  GetSetKeyState = Win32API.new("user32","SetKeyboardState",['I'],'I')
  #--------------------------------------------------------------------------
  # ● ALL_KEYS
  #--------------------------------------------------------------------------
  ALL_KEYS = {
    # 鼠标
    'MOUSE1'    => 0x01,       # 左键
    'MOUSE2'    => 0x02,       # 右键
    'MOUSE3'    => 0x04,       # 中键
    'MOUSE4'    => 0x05,       # 侧键1
    'MOUSE5'    => 0x06,       # 侧键2
    # 键盘
    'BACK'      => 0x08,       # BACKSPACE key
    'TAB'       => 0x09,       # TAB key
    'RETURN'    => 0x0D,       # ENTER key
    'SHIFT'     => 0x10,       # SHIFT key
    'CTLR'      => 0x11,       # CTLR key
    'ALT'       => 0x12,       # ALT key
    'PAUSE'     => 0x13,       # PAUSE key
    'CAPITAL'   => 0x14,       # CAPS LOCK key
    'ESCAPE'    => 0x1B,       # ESC key
    'SPACE'     => 0x20,       # SPACEBAR
    'PRIOR'     => 0x21,       # PAGE UP key
    'NEXT'      => 0x22,       # PAGE DOWN key
    'END'       => 0x23,       # END key
    'HOME'      => 0x24,       # HOME key
    'LEFT'      => 0x25,       # LEFT ARROW key
    'UP'        => 0x26,       # UP ARROW key
    'RIGHT'     => 0x27,       # RIGHT ARROW key
    'DOWN'      => 0x28,       # DOWN ARROW key
    'SELECT'    => 0x29,       # SELECT key
    'PRINT'     => 0x2A,       # PRINT key
    'SNAPSHOT'  => 0x2C,       # PRINT SCREEN key
    'INSERT'    => 0x2D,       # INS key
    'DELETE'    => 0x2E,       # DEL key
    #--------------------------------------------------------------------------
    '0'         => 0x30,       # 0 key
    '1'         => 0x31,       # 1 key
    '2'         => 0x32,       # 2 key
    '3'         => 0x33,       # 3 key
    '4'         => 0x34,       # 4 key
    '5'         => 0x35,       # 5 key
    '6'         => 0x36,       # 6 key
    '7'         => 0x37,       # 7 key
    '8'         => 0x38,       # 8 key
    '9'         => 0x39,       # 9 key
    #--------------------------------------------------------------------------
    'A'         => 0x41,       # A key
    'B'         => 0x42,       # B key
    'C'         => 0x43,       # C key
    'D'         => 0x44,       # D key
    'E'         => 0x45,       # E key
    'F'         => 0x46,       # F key
    'G'         => 0x47,       # G key
    'H'         => 0x48,       # H key
    'I'         => 0x49,       # I key
    'J'         => 0x4A,       # J key
    'K'         => 0x4B,       # K key
    'L'         => 0x4C,       # L key
    'M'         => 0x4D,       # M key
    'N'         => 0x4E,       # N key
    'O'         => 0x4F,       # O key
    'P'         => 0x50,       # P key
    'Q'         => 0x51,       # Q key
    'R'         => 0x52,       # R key
    'S'         => 0x53,       # S key
    'T'         => 0x54,       # T key
    'U'         => 0x55,       # U key
    'V'         => 0x56,       # V key
    'W'         => 0x57,       # W key
    'X'         => 0x58,       # X key
    'Y'         => 0x59,       # Y key
    'Z'         => 0x5A,       # Z key
    #--------------------------------------------------------------------------
    'LWIN'      => 0x5B,       # Left Windows key (Microsoft Natural keyboard) 
    'RWIN'      => 0x5C,       # Right Windows key (Natural keyboard)
    'APPS'      => 0x5D,       # Applications key (Natural keyboard)
    #--------------------------------------------------------------------------
    'NUMPAD0'   => 0x60,       # Numeric keypad 0 key
    'NUMPAD1'   => 0x61,       # Numeric keypad 1 key
    'NUMPAD2'   => 0x62,       # Numeric keypad 2 key
    'NUMPAD3'   => 0x63,       # Numeric keypad 3 key
    'NUMPAD4'   => 0x64,       # Numeric keypad 4 key
    'NUMPAD5'   => 0x65,       # Numeric keypad 5 key
    'NUMPAD6'   => 0x66,       # Numeric keypad 6 key
    'NUMPAD7'   => 0x67,       # Numeric keypad 7 key
    'NUMPAD8'   => 0x68,       # Numeric keypad 8 key
    'NUMPAD9'   => 0x69,       # Numeric keypad 9 key
    'MULTIPLY'  => 0x6A,       # Multiply key (*)
    'ADD'       => 0x6B,       # Add key (+)
    'SEPARATOR' => 0x6C,       # Separator key
    'SUBTRACT'  => 0x6D,       # Subtract key (-)
    'DECIMAL'   => 0x6E,       # Decimal key
    'DIVIDE'    => 0x6F,       # Divide key (/)
    #--------------------------------------------------------------------------
    'F1'        => 0x70,       # F1 key
    'F2'        => 0x71,       # F2 key
    'F3'        => 0x72,       # F3 key
    'F4'        => 0x73,       # F4 key
    'F5'        => 0x74,       # F5 key
    'F6'        => 0x75,       # F6 key
    'F7'        => 0x76,       # F7 key
    'F8'        => 0x77,       # F8 key
    'F9'        => 0x78,       # F9 key
    'F10'       => 0x79,       # F10 key
    'F11'       => 0x7A,       # F11 key
    'F12'       => 0x7B,       # F12 key
    #--------------------------------------------------------------------------
    'NUMLOCK'   => 0x90,       # NUM LOCK key
    'SCROLL'    => 0x91,       # SCROLL LOCK key
    #--------------------------------------------------------------------------
    'LSHIFT'    => 0xA0,       # Left SHIFT key
    'RSHIFT'    => 0xA1,       # Right SHIFT key
    'LCONTROL'  => 0xA2,       # Left CONTROL key
    'RCONTROL'  => 0xA3,       # Right CONTROL key
    'L_ALT'     => 0xA4,       # Left ALT key
    'R_ALT'     => 0xA5,       # Right ALT key
    #--------------------------------------------------------------------------
    'SEP'       => 0xBC,       # , key
    'DASH'      => 0xBD,       # - key
    'DOTT'      => 0xBE,       # . Key
  }
  #--------------------------------------------------------------------------
  # ● init
  #--------------------------------------------------------------------------
  def init
    @binds = Hash.new{|h,k| h[k] = [] }
    @functions = {}
    @prev_state, @state = {}, {}
    @fun_state, @pr_state, @down_state, @repeat_state = {}, {}, {}, {}
    @sequences = {}
  end
  #--------------------------------------------------------------------------
  # ● bind
  #--------------------------------------------------------------------------
  def bind(key, action)
    key = key.upcase  # key convert to upcase
    case action.class.to_s
    when 'String'
      @binds[action] << key unless @binds[action].include?(key)
    when 'Proc','Method'
      @functions[key] = action
    end
  end
  #--------------------------------------------------------------------------
  # ● has_proc?
  #--------------------------------------------------------------------------
  def has_proc?(key)
    key = key.upcase  # key convert to upcase
    return @functions[key]
  end
  #--------------------------------------------------------------------------
  # ● get_tags
  #--------------------------------------------------------------------------
  def get_tags(key)
    key = key.upcase  # key convert to upcase
    arr = []
    @binds.keys.each do |k|
      arr << k if @binds[k].include?(key)
    end
    return arr
  end
  #--------------------------------------------------------------------------
  # ● unbind
  #--------------------------------------------------------------------------
  def unbind(key)
    key = key.upcase
    @binds.values.each{|v| v.delete(key) }
    @functions.delete(key)
  end
  #--------------------------------------------------------------------------
  # ● unbindAll
  #--------------------------------------------------------------------------
  def unbindAll
    [@binds, @functions, @fun_state, @prev_state, @state, 
      @pr_state, @down_state, @repeat_state, @sequences].each(&:clear)
  end
  #--------------------------------------------------------------------------
  # ● pressed
  #--------------------------------------------------------------------------
  def pressed(tag)
    return @binds[tag].find{|k|
      key = "#{tag}_#{k}"
      @pr_state[key] == true and @pr_state.delete(key)
    } != nil
  end
  #--------------------------------------------------------------------------
  # ● released
  #--------------------------------------------------------------------------
  def released(tag)
    return @binds[tag].find{|k|
      key = "#{tag}_#{k}"
      @pr_state[key] == false and @pr_state.delete(key) == false
    } != nil
  end
  #--------------------------------------------------------------------------
  # ● down
  #--------------------------------------------------------------------------
  def down(tag, interval = 0, delay = 0)
    key = ''
    if @binds[tag].find{|k| key = "#{tag}_#{k}"; @down_state.include?(key) } != nil
      if @repeat_state[key]
        if @repeat_state[key][2] >= delay
          if @repeat_state[key][1] >= interval
            @repeat_state[key][1] -= interval
            return true
          else
            @repeat_state[key][1] += 1
            return false
          end
        else
          @repeat_state[key][2] += 1
          return false
        end
      else
        @repeat_state[key] = [true, 0, 0]
        return true
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● sequence
  #--------------------------------------------------------------------------
  def sequence(*args)
    raise '参数传递错误!' if args.size <= 1 or args.size % 2 == 0
    o = @sequences[args] ||= { index: 0, frame: 0, tag: {} }
    if o[:index] == 0
      tag = args[0]
      if @binds[tag].find{|k| o[:tag].delete("#{tag}_#{k}") } != nil
        o[:index], o[:frame] = 1, 0
        return false
      end
    else
      if o[:frame] <= args[o[:index]]
        tag = args[o[:index]+1]
        if @binds[tag].find{|k| o[:tag].delete("#{tag}_#{k}") } != nil
          o[:index] += 2
          o[:frame] = 0
          if o[:index] >= args.size
            @sequences.delete(args)
            return true
          end
        end
        o[:frame] += 1
        return false
      else
        @sequences.delete(args)
        return false
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● update
  #--------------------------------------------------------------------------
  InputUpdate = method :update unless $@
  def update
    InputUpdate.call
    # call binding
    @functions.keys.each do |k|
      a = @functions[k]
      press = GetKeyState.call(ALL_KEYS[k]) != 0
      a.call if !@fun_state[k] and press
      @fun_state[k] = press
    end
    @binds.keys.each do |tag|
      pressState = press_(tag)
      pressState.keys.each do |k|
        s = pressState[k]
        key = "#{tag}_#{k}"
        @prev_state[key] = @state[key]
        @state[key] = s
        # pressed
        if !@prev_state[key] and @state[key]
          @pr_state[key] = true
          @down_state[key] = true
          @sequences.values.each{|s| s[:tag][key] = true }
        end
        # released
        if @prev_state[key] and !@state[key]
          @pr_state[key] = false
          @down_state.delete(key)
          @repeat_state.delete(key)
          @sequences.values.each{|s| s[:tag].delete(key) }
        end
      end
    end
    
  end
  #--------------------------------------------------------------------------
  # ● press_
  #--------------------------------------------------------------------------
  def press_(tag)
    state = {}
    @binds[tag].map{|k| state[k] = GetKeyState.call(ALL_KEYS[k]) != 0 }
    return state
  end
  private :press_
end

Input.init

鸡蛋

鲜花

评论 (0 个评论)

facelist doodle 涂鸦笔

您需要登录后才可以评论 登录 | 注册会员

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-3-29 16:40

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

返回顶部