Войти на сайт

Авторизация, ждите ...
×
Правила раздела:
1 Задавайте конкретные вопросы. Для болтовни есть свободный раздел.
2 По возможности давайте конкретные ответы.
3 Один вопрос=одна тема. Если хотите задать ещё вопрос, то начинайте новую тему.
4 Название темы должно составлять сам вопрос, и быть максимально конкретным. Рекомендуется начинать тему словами "Как", "Что", "Почему". А первый пост повторяет вопрос и даёт расширенные сведения.
5 Рекомендуется указывать версию мейкера (2000, 2003, RMXP, RMVX, ACE, IGM, и.т.д.. Это важно, и всё равно ведь спросят.
6 Темы "Пара вопросов", "Помогите", и подобные им - самый лёгкий путь к бану.
7 Поиск находится вверху справа.
А. Названия подразделов этого раздела уточняются. Советы принимаются.

ТЕМА: Управление. Джойстик. Скрипт "Full Input Keyboard"

Управление. Джойстик. Скрипт "Full Input Keyboard" 7 года 4 мес. назад #94782

  • Рексарыч
  • Рексарыч аватар
  • Вне сайта
  • Мастер
  • Сообщений: 179
  • Спасибо получено: 204
  • РазработчикКоммерсант
Скрипт:
#==============================================================================
# ** Input
#-------------------------------------------------------------------------------
# Created By Cidiomar R. Dias Junior
# Originally posted at 
#
# Terms of Use: Credit "Cidiomar R. Dias Junior"
#
# Maintained on Hime Works
#-------------------------------------------------------------------------------
# ** Description
#
# A module that handles input data from a gamepad or keyboard.
# Managed by symbols rather than button numbers in RGSS3.
#-------------------------------------------------------------------------------
# ** Usage
# 
# Scroll down to the configuration section. It is around line 185.
# You can set up your key mappings there. Use the reference to get the names
# of the keys.
#
#===============================================================================
module Input  
#===============================================================================
# Reference
#
# Use this to determine which keys are available for mapping
#===============================================================================

  #--------------------------------------------------------------------------
  # * Keymap in symbols
  # To get a key from the keymap, you can use Input.key(sym) or Input:KEYMAP[sym]
  # Or if you want to use a symbol in a input function, just pass the symbol
  # as argument.
  #--------------------------------------------------------------------------
  KEYMAP = {
    LBUTTON:             0x01,  RBUTTON:           0x02,
    CANCEL:              0x03,  MBUTTON:           0x04,
    XBUTTON1:            0x05,  XBUTTON2:          0x06,
    BACK:                0x08,  TAB:               0x09,
    CLEAR:               0x0c,  RETURN:            0x0d,
    SHIFT:               0x10,  CONTROL:           0x11,
    MENU:                0x12,  PAUSE:             0x13,
    CAPITAL:             0x14,  KANA:              0x15,
    KANA:                0x15,  KANA:              0x15,
    JUNJA:               0x17,  FINAL:             0x18,
    HANJA:               0x19,  HANJA:             0x19,
    ESCAPE:              0x1b,  CONVERT:           0x1c,
    NONCONVERT:          0x1d,  ACCEPT:            0x1e,
    MODECHANGE:          0x1f,  SPACE:             0x20,
    PRIOR:               0x21,  NEXT:              0x22,
    END:                 0x23,  HOME:              0x24,
    LEFT:                0x25,  UP:                0x26,
    RIGHT:               0x27,  DOWN:              0x28,
    SELECT:              0x29,  PRINT:             0x2a,
    EXECUTE:             0x2b,  SNAPSHOT:          0x2c,
    INSERT:              0x2d,  DELETE:            0x2e,
    HELP:                0x2f,  N0:                0x30,
    KEY_1:               0x31,  KEY_2:             0x32,
    KEY_3:               0x33,  KEY_4:             0x34,
    KEY_5:               0x35,  KEY_6:             0x36,
    KEY_7:               0x37,  KEY_8:             0x38,
    KEY_9:               0x39,  colon:             0x3a,
    semicolon:           0x3b,  less:              0x3c,
    equal:               0x3d,  greater:           0x3e,
    question:            0x3f,  at:                0x40,
    LETTER_A:            0x41,  LETTER_B:          0x42,
    LETTER_C:            0x43,  LETTER_D:          0x44,
    LETTER_E:            0x45,  LETTER_F:          0x46,
    LETTER_G:            0x47,  LETTER_H:          0x48,
    LETTER_I:            0x49,  LETTER_J:          0x4a,
    LETTER_K:            0x4b,  LETTER_L:          0x4c,
    LETTER_M:            0x4d,  LETTER_N:          0x4e,
    LETTER_O:            0x4f,  LETTER_P:          0x50,
    LETTER_Q:            0x51,  LETTER_R:          0x52,
    LETTER_S:            0x53,  LETTER_T:          0x54,
    LETTER_U:            0x55,  LETTER_V:          0x56,
    LETTER_W:            0x57,  LETTER_X:          0x58,
    LETTER_Y:            0x59,  LETTER_Z:          0x5a,
    LWIN:                0x5b,  RWIN:              0x5c,
    APPS:                0x5d,  asciicircum:       0x5e,
    SLEEP:               0x5f,  NUMPAD0:           0x60,
    NUMPAD1:             0x61,  NUMPAD2:           0x62,
    NUMPAD3:             0x63,  NUMPAD4:           0x64,
    NUMPAD5:             0x65,  NUMPAD6:           0x66,
    NUMPAD7:             0x67,  NUMPAD8:           0x68,
    NUMPAD9:             0x69,  MULTIPLY:          0x6a,
    ADD:                 0x6b,  SEPARATOR:         0x6c,
    SUBTRACT:            0x6d,  DECIMAL:           0x6e,
    DIVIDE:              0x6f,  F1:                0x70,
    F2:                  0x71,  F3:                0x72,
    F4:                  0x73,  F5:                0x74,
    F6:                  0x75,  F7:                0x76,
    F8:                  0x77,  F9:                0x78,
    F10:                 0x79,  F11:               0x7a,
    F12:                 0x7b,  F13:               0x7c,
    F14:                 0x7d,  F15:               0x7e,
    F16:                 0x7f,  F17:               0x80,
    F18:                 0x81,  F19:               0x82,
    F20:                 0x83,  F21:               0x84,
    F22:                 0x85,  F23:               0x86,
    F24:                 0x87,  NUMLOCK:           0x90,
    SCROLL:              0x91,  LSHIFT:            0xa0,
    RSHIFT:              0xa1,  LCONTROL:          0xa2,
    RCONTROL:            0xa3,  LMENU:             0xa4,
    RMENU:               0xa5,  BROWSER_BACK:      0xa6,
    BROWSER_FORWARD:     0xa7,  BROWSER_REFRESH:   0xa8,
    BROWSER_STOP:        0xa9,  BROWSER_SEARCH:    0xaa,
    BROWSER_FAVORITES:   0xab,  BROWSER_HOME:      0xac,
    VOLUME_MUTE:         0xad,  VOLUME_DOWN:       0xae,
    VOLUME_UP:           0xaf,  MEDIA_NEXT_TRACK:  0xb0,
    MEDIA_PREV_TRACK:    0xb1,  MEDIA_STOP:        0xb2,
    MEDIA_PLAY_PAUSE:    0xb3,  LAUNCH_MAIL:       0xb4,
    LAUNCH_MEDIA_SELECT: 0xb5,  LAUNCH_APP1:       0xb6,
    LAUNCH_APP2:         0xb7,  cedilla:           0xb8,
    onesuperior:         0xb9,  masculine:         0xba,
    guillemotright:      0xbb,  onequarter:        0xbc,
    onehalf:             0xbd,  threequarters:     0xbe,
    questiondown:        0xbf,  Agrave:            0xc0,
    Aacute:              0xc1,  Acircumflex:       0xc2,
    Atilde:              0xc3,  Adiaeresis:        0xc4,
    Aring:               0xc5,  AE:                0xc6,
    Ccedilla:            0xc7,  Egrave:            0xc8,
    Eacute:              0xc9,  Ecircumflex:       0xca,
    Ediaeresis:          0xcb,  Igrave:            0xcc,
    Iacute:              0xcd,  Icircumflex:       0xce,
    Idiaeresis:          0xcf,  ETH:               0xd0,
    Ntilde:              0xd1,  Ograve:            0xd2,
    Oacute:              0xd3,  Ocircumflex:       0xd4,
    Otilde:              0xd5,  Odiaeresis:        0xd6,
    multiply:            0xd7,  Oslash:            0xd8,
    Ugrave:              0xd9,  Uacute:            0xda,
    Ucircumflex:         0xdb,  Udiaeresis:        0xdc,
    Yacute:              0xdd,  THORN:             0xde,
    ssharp:              0xdf,  agrave:            0xe0,
    aacute:              0xe1,  acircumflex:       0xe2,
    atilde:              0xe3,  adiaeresis:        0xe4,
    PROCESSKEY:          0xe5,  ae:                0xe6,
    PACKET:              0xe7,  egrave:            0xe8,
    eacute:              0xe9,  ecircumflex:       0xea,
    ediaeresis:          0xeb,  igrave:            0xec,
    iacute:              0xed,  icircumflex:       0xee,
    idiaeresis:          0xef,  eth:               0xf0,
    ntilde:              0xf1,  ograve:            0xf2,
    oacute:              0xf3,  ocircumflex:       0xf4,
    otilde:              0xf5,  ATTN:              0xf6,
    CRSEL:               0xf7,  EXSEL:             0xf8,
    EREOF:               0xf9,  PLAY:              0xfa,
    ZOOM:                0xfb,  NONAME:            0xfc,
    PA1:                 0xfd,  thorn:             0xfe,
    ydiaeresis:          0xff
  }
 
#===============================================================================
# Configuration
#===============================================================================
  KEYMAP[:WIN]  = [KEYMAP[:LWIN], KEYMAP[:RWIN]]
 
  #--------------------------------------------------------------------------
  # * Default Keys, you can configure here instead of by pressing F1.
  #--------------------------------------------------------------------------
  UP    = [KEYMAP[:UP]]
  DOWN  = [KEYMAP[:DOWN]]
  LEFT  = [KEYMAP[:LEFT]]
  RIGHT = [KEYMAP[:RIGHT]]
  A     = [KEYMAP[:SHIFT]]
  B     = [KEYMAP[:ESCAPE], KEYMAP[:LETTER_X]]
  C     = [KEYMAP[:RETURN], KEYMAP[:LETTER_Z]]
  X     = []
  Y     = []
  Z     = []
  L     = [KEYMAP[:PRIOR]]
  R     = [KEYMAP[:NEXT]]
  F5    = [KEYMAP[:F5]]
  F6    = [KEYMAP[:F6]]
  F7    = [KEYMAP[:F7]]
  F8    = [KEYMAP[:F8]]
  F9    = [KEYMAP[:F9]]
  SHIFT = [KEYMAP[:SHIFT]]
  CTRL  = [KEYMAP[:CONTROL]]
  ALT   = [KEYMAP[:MENU]]
 
#===============================================================================
# Rest of script
#===============================================================================

  #--------------------------------------------------------------------------
  # * Symbol version of default keys.
  #--------------------------------------------------------------------------
  SYM_KEYS = {
    :UP       => UP,
    :LEFT     => LEFT,
    :DOWN     => DOWN,
    :RIGHT    => RIGHT,
    :A        => A,
    :B        => B,
    :C        => C,
    :X        => X,
    :Y        => Y,
    :Z        => Z,
    :L        => L,
    :R        => R,
    :F5       => F5,
    :F6       => F6,
    :F7       => F7,
    :F8       => F8,
    :F9       => F9,
    :SHIFT    => SHIFT,
    :CTRL     => CTRL,
    :ALT      => ALT
  }
  #--------------------------------------------------------------------------
  # * Key Codes Used in Events Conditional Branchs
  #--------------------------------------------------------------------------
  EventsKeyCodes = {
     2 => :DOWN,
     4 => :LEFT,
     6 => :RIGHT,
     8 => :UP,
    11 => :A,
    12 => :B,
    13 => :C,
    14 => :X,
    15 => :Y,
    16 => :Z,
    17 => :L,
    18 => :R
  }
 
  #--------------------------------------------------------------------------
  # * Internal APIs to handle keyboard functions
  #--------------------------------------------------------------------------
  GetKeyboardState  = Win32API.new("user32.dll", "GetKeyboardState",  "I", "I")
  MapVirtualKeyEx   = Win32API.new("user32.dll", "MapVirtualKeyEx", "IIL", "I")
  ToUnicodeEx      = Win32API.new("user32.dll", "ToUnicodeEx", "LLPPILL", "L")
  #----------
  @language_layout  = Win32API.new("user32.dll", "GetKeyboardLayout", "L", "L").call(0)
  DOWN_STATE_MASK   = (0x8 << 0x04)
  DEAD_KEY_MASK  = (0x8 << 0x1C)
  #-----
  UNICODE_TO_UTF8   = Encoding::Converter.new(Encoding.list[2], Encoding.list[1])
 
  #--------------------------------------------------------------------------
  # * States of keys
  #--------------------------------------------------------------------------
  @state     = DL::CPtr.new(DL.malloc(256), 256)
  @triggered = Array.new(256, false)
  @pressed   = Array.new(256, false)
  @released  = Array.new(256, false)
  @repeated  = Array.new(256, 0)
 
  #--------------------------------------------------------------------------
  # * Singleton attrs of states
  #--------------------------------------------------------------------------
  class << self
    attr_reader :triggered, :pressed, :released, :repeated, :state
  end
 
  #--------------------------------------------------------------------------
  # * Get a key code by simbol
  #--------------------------------------------------------------------------
  def self.key(sym)
    KEYMAP[sym] || 0
  end
 
  #--------------------------------------------------------------------------
  # * Updates input data.
  # As a general rule, this method is called once per frame.
  #--------------------------------------------------------------------------
  def self.update
    GetKeyboardState.call(@state.to_i)
    0.upto(255) do |key|
      if @state[key] & DOWN_STATE_MASK == DOWN_STATE_MASK
        @released[key] = false
        @pressed[key]  = true if (@triggered[key] = !@pressed[key])
        @repeated[key] < 17 ? @repeated[key] += 1 : @repeated[key] = 15
      elsif !@released[key] and @pressed[key]
        @triggered[key] = false
        @pressed[key]   = false
        @repeated[key]  = 0
        @released[key]  = true
      else
        @released[key]  = false
      end
    end
  end
 
  #--------------------------------------------------------------------------
  # * Checks the status of the directional buttons, translates the data into
  # a specialized 4-direction input format, and returns the number pad
  # equivalent (2, 4, 6, 8).
  #
  # If no directional buttons are being pressed (or the equivalent), returns 0.
  #--------------------------------------------------------------------------
  def self.dir4
    return 2 if self.press?(DOWN)
    return 4 if self.press?(LEFT)
    return 6 if self.press?(RIGHT)
    return 8 if self.press?(UP)
    return 0
  end
 
  #--------------------------------------------------------------------------
  # * Checks the status of the directional buttons, translates the data into
  # a specialized 8-direction input format, and returns the number pad
  # equivalent (1, 2, 3, 4, 6, 7, 8, 9).
  #
  #If no directional buttons are being pressed (or the equivalent), returns 0.
  #--------------------------------------------------------------------------
  def self.dir8
    down = self.press?(DOWN)
    left = self.press?(LEFT)
    return 1 if down and left
    right = self.press?(RIGHT)
    return 3 if down and right
    up = self.press?(UP)
    return 7 if up and left
    return 9 if up and right
    return 2 if down
    return 4 if left
    return 6 if right
    return 8 if up
    return 0
  end
 
  #--------------------------------------------------------------------------
  # * Determines whether the button corresponding to the symbol sym is
  # currently being pressed.
  #
  # If the button is being pressed, returns TRUE. If not, returns FALSE.
  #
  #   if Input.press?(:C)
  #      do_something
  #   end
  #--------------------------------------------------------------------------
  def self.press?(keys)
    if keys.is_a?(Numeric)
      k = keys.to_i
      return (@pressed[k] and !@triggered[k])
    elsif keys.is_a?(Array)
      return keys.any? {|key| self.press?(key) }
    elsif keys.is_a?(Symbol)
      if SYM_KEYS.key?(keys)
        return SYM_KEYS[keys].any? {|key| (@pressed[key]  and !@triggered[key]) }
      elsif (KEYMAP.key?(keys))
        k = KEYMAP[keys]
        return (@pressed[k] and !@triggered[k])
      else
        return false
      end
    end
  end
 
  #--------------------------------------------------------------------------
  # * Determines whether the button corresponding to the symbol sym is
  # currently being pressed again.
  # "Pressed again" is seen as time having passed between the button being
  # not pressed and being pressed.
  #
  # If the button is being pressed, returns TRUE. If not, returns FALSE.
  #--------------------------------------------------------------------------
  def self.trigger?(keys)
    if keys.is_a?(Numeric)
      return @triggered[keys.to_i]
    elsif keys.is_a?(Array)
      return keys.any? {|key| @triggered[key]}
    elsif keys.is_a?(Symbol)
      if SYM_KEYS.key?(keys)
        return SYM_KEYS[keys].any? {|key| @triggered[key]}
      elsif KEYMAP.key?(keys)
        return @triggered[KEYMAP[keys]]
      else
        return false
      end
    end
  end
 
  #--------------------------------------------------------------------------
  # * Determines whether the button corresponding to the symbol sym is
  # currently being pressed again.
  # Unlike trigger?, takes into account the repeated input of a button being
  # held down continuously.
  #
  # If the button is being pressed, returns TRUE. If not, returns FALSE.
  #--------------------------------------------------------------------------
  def self.repeat?(keys)
    if keys.is_a?(Numeric)
      key = keys.to_i
      return @repeated[key] == 1 || @repeated[key] == 16
    elsif keys.is_a?(Array)
      return keys.any? {|key| @repeated[key] == 1 || @repeated[key] == 16}
    elsif keys.is_a?(Symbol)
      if SYM_KEYS.key?(keys)
        return SYM_KEYS[keys].any? {|key| @repeated[key] == 1 || @repeated[key] == 16}
      elsif KEYMAP.key?(keys)
        return @repeated[KEYMAP[keys]] == 1 || @repeated[KEYMAP[keys]] == 16
      else
        return false
      end
    end
  end
 
  #--------------------------------------------------------------------------
  # * Determines whether the button corresponding to the symbol sym
  # was released.
  #
  # If the button was released, returns TRUE. If not, returns FALSE.
  #--------------------------------------------------------------------------
  def self.release?(keys)
    if keys.is_a?(Numeric)
      return @released[keys.to_i]
    elsif keys.is_a?(Array)
      return keys.any? {|key| @released[key]}
    elsif keys.is_a?(Symbol)
      if SYM_KEYS.key?(keys)
        return SYM_KEYS[keys].any? {|key| @released[key]}
      elsif KEYMAP.key?(keys)
        return @released[KEYMAP[keys]]
      else
        return false
      end
    end
  end
 
  #--------------------------------------------------------------------------
  # * Gets the character that correspond to vk using the keyboard layout
  #--------------------------------------------------------------------------
  def self.get_character(vk)
    c = MapVirtualKeyEx.call(vk, 2, @language_layout)
    return "" if c < 32 && (c & DEAD_KEY_MASK != DEAD_KEY_MASK)
    result = "\0" * 2
    length = ToUnicodeEx.call(vk, MapVirtualKeyEx.call(vk, 0, @language_layout), @state, result, 2, 0, @language_layout)
    return (length == 0 ? "" : result)
  end
 
  #--------------------------------------------------------------------------
  # * Accents Table, to bo used in conversion from ASCII to UTF8
  #--------------------------------------------------------------------------
  AccentsCharsConv = {
    "A" =>  ["A", "A", "A", "A", "A"],
    "E" =>  ["E", "E", "E",  0,  "E"],
    "I" =>  ["I", "I", "I",  0,  "I"],
    "O" =>  ["O", "O", "O", "O", "O"],
    "U" =>  ["U", "U", "U",  0,  "U"],
    "C" =>  [ 0 , "C",  0 ,  0,  0 ],
    "N" =>  [ 0 ,  0,  0 , "N",  0 ],
    "Y" =>  [ 0 , "Y",  0 ,  0,  "?"],
    "a" =>  ["a", "a", "a", "a", "a"],
    "e" =>  ["e", "e", "e",  0 , "e"],
    "i" =>  ["i", "i", "i",  0 , "i"],
    "o" =>  ["o", "o", "o", "o", "o"],
    "u" =>  ["u", "u", "u",  0 , "u"],
    "c" =>  [ 0 , "c",  0 ,  0 ,  0 ],
    "n" =>  [ 0 ,  0 ,  0 , "n",  0 ],
    "y" =>  [ 0 , "y",  0 ,  0 , "y"],
  }
 
  # Letters that can have accent
  PssbLetters   = "AEIOUCNYaeioucny"
  # Accents, in ASCII, configured at runtime to avoid encoding troubles
  Accents = [96.chr, 180.chr, 94.chr, 126.chr, 168.chr].join
  NonCompatChars = [180, 168]
  @last_accent = nil
 
  #--------------------------------------------------------------------------
  # * Get inputed string transcoded to UTF8
  #--------------------------------------------------------------------------
  def self.UTF8String
    result = ""
    31.upto(255) {|key|
            if self.repeat?(key)
              c = self.get_character(key)
              if (cc = c.unpack("C")[0]) and NonCompatChars.include?(cc)
                    result += cc.chr
              else
                    result += UNICODE_TO_UTF8.convertc if c != ""
              end
            end
    }
    return "" if result == ""
    if @last_accent
      result = @last_accent + result
      @last_accent = nil
    end
    f_result = ""
    jump    = false
    for i in 0 ... result.length
      c = result[i]
      if jump
        jump = false
        next
      end
      if Accents.include?c
        if (nc = result[i+1]) != nil
          if PssbLetters.include?(nc)
            if (ac = AccentsCharsConv[nc][Accents.indexc]) != 0
              f_result << ac
              jump = true
            else
              f_result << c
              f_result << nc
              jump = true
            end
          elsif Accents.include?(nc)
            f_result << c
            f_result << nc
            jump = true
          else
            f_result << c
            f_result << nc
            jump = true
          end
        else
          @last_accent = c
        end
      else
        f_result << c
      end
    end
    return f_result
  end
end
Цель: запилить настройку управления в игре, ведь я хочу печеньку от Эрнеста Адамса. :laugh:

Текущая проблема: посмотреть перезначение дейтсвий.

Клавиатура: всё работает отлично.

Джойстик: что-то я делаю не так, а если учесть (в грубейшем приближении, поскольку не беру в расчёт многие вещи), что у нас 256 клавиш и 8 действий в игре, то выходит, что надо перебрать 2048 вариантов, т.к. 256*8=2048. Соответственно метод тыка тут перерастает в мазохизм.

Попробовал предположить, что <<NUMPAD0>> - <<SUBTRACT>> относятся к джойстику, но просчитался, соответственно прошу тыкнуть меня носом, какие шестнадцатиричные коды являются командами для джойстика.
Мои законченные игры:
1. "Судоку" - reksarych.itch.io/sudoku.

Наша группа в ВК: vk.com/bratstvo_rasskazchikov_istorij.

Моя игровая и околоигровая коллекция

Последнее редактирование: 7 года 4 мес. назад от Рексарыч.
Администратор запретил публиковать записи гостям.

Управление. Джойстик. Скрипт "Full Input Keyboard" 7 года 1 мес. назад #96517

  • Рексарыч
  • Рексарыч аватар
  • Вне сайта
  • Мастер
  • Сообщений: 179
  • Спасибо получено: 204
  • РазработчикКоммерсант
Чтож. Найден другой путь решения проблемы с джойстиками, благодаря демке, которую недавно выложил Эльф. Низкий ему поклон за это и действительно, что порой проще попросить. ;)

Всем спасибо. Тему можно закывать.
Мои законченные игры:
1. "Судоку" - reksarych.itch.io/sudoku.

Наша группа в ВК: vk.com/bratstvo_rasskazchikov_istorij.

Моя игровая и околоигровая коллекция

Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: DeadElf79
Время создания страницы: 0.445 секунд