Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Glitchfinder's Gamepad Input Module 1.00

Gamepad Input Module Version: 1.00
By: Glitchfinder


Introduction

Glitchfinder's Gamepad Input Module is an advanced scripting tool that provides full scripted access to to check any and all buttons and axes on an XInput-compatible gamepad. It is useful in the sense that it will not break the default Input module, and because it allows far more use of modern gamepads than you would get from default RMXP or default RMVX. It also does not need to be updated, aside from the default call to Input.update that is used in most cases. It also does not break default scripts or events that use input.

Features
  • Check any button on the gamepad
  • Doesn't break the default Input module
  • Does not break events or scripts that call the default Input module
  • Automatically updated by the default Input module
  • Allows you to check to see if a button has been released
  • Works with all XInput-compatible controllers
  • Doesn't crash on F12

Screenshots

Since this script has no visual elements, a screenshot cannot be taken.

Script

Code:
#≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡

# ** Glitchfinder's Gamepad Input Module          [RPG Maker XP] [RPG Maker VX]

#    Version 1.00

#------------------------------------------------------------------------------

#  This script helps scripters to use an XInput-compatible gamepad with their

#  games.

#==============================================================================

# * Version History

#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#   Version 1.00 ------------------------------------------------- (2010-08-20)

#     - Initial version

#     - Author: Glitchfinder

#==============================================================================

# * Instructions

#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#  Place this script above Main, and below the default scripts. (I realize this

#  is obvious to most, but some people don't get it.)

#

#  You must also place Input.dll into the game's main project folder, since

#  this script needs it to access the XInput functions it uses.

#

#  This module is automatically updated by the default Input module, which

#  means that the only time you need to call the update method is in a scene

#  that does not update the default Input module.

#

#  This module does not break the functionality of the default Input module.

#

#  To use this module to check a gamepad button, simply use one of the four

#  methods (press?(button[, index]), trigger?(button[, index]),

#  repeat?(button[, index]), or release?(button[, index])), where button is the

#  constant of the button you want to check. Button may also be used as

#  Gamepad::BUTTONNAME. For a list of acceptable button names, look below the

#  header, in the section that declares button constants. The methods use index

#  to determine which gamepad to check. If no index is given, they will check

#  gamepad 0. Index is a value from 0 to 3.

#

#  To use this module to check a gamepad trigger or joystick, simply use one of

#  the four methods (axis_press?(axis[, index]), axis_trigger?(axis[, index]),

#  axis_repeat?(axis[, index]), or axis_release?(axis[, index])), where axis is

#  the constant of the axis you want to check. Axis may also be used as

#  Gamepad::AXISNAME. For a list of acceptable axis names, look below the

#  header, in the section that declares axis constants. The methods use index

#  to determine which gamepad to check. If no index is given, they will check

#  gamepad 0. Index is a value from 0 to 3.

#

#  To use this module to check the value on a gamepad triger or joystick axis,

#  use one of the two methods (axis_value(axis[, index]),

#  real_axis_value(axis[, index])), where axis is the constant of the axis you

#  want to check. Axis may also be used as Gamepad::AXISNAME. For a list of

#  acceptable axis names, look below the header, in the section that declares

#  axis constants. The methods use index to determine which gamepad to check.

#  If no index is given, they will check gamepad 0. Index is a value from 0 to

#  3. The difference between these two methods is that real_axis_value() will

#  always return the current value, while axis_value will return 0 if the

#  axis falls within its dead zone.

#

#  To use this module to cause a gamepad to "rumble", or vibrate, use the

#  vibrate() method. Details for that are below, in the method list.

#==============================================================================

# * Method List

#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#  Gamepad.update

#    Updates gamepad input. Calls to this method are not necessary unless the

#    default Input module is not being updated.

#

#  Gamepad.press?(button[, index])

#    Determines whether the gamepad button determined by button is currently

#    being pressed. If the button is being pressed, returns true. If not,

#    returns false. Uses index to determine the gamepad to check, from 0 to 3.

#    The index defaults to 0.

#

#  Gamepad.trigger?(button[, index])

#    Determines whether the gamepad button determined by button is 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. Uses index to determine the

#    gamepad to check, from 0 to 3. The index defaults to 0.

#

#  Gamepad.repeat?(button[, index])

#    Determines whether the gamepad button determined by button is being

#    pressed again. Unlike trigger?(), this takes into account the repeat input

#    of a button being held down continuously. If the button is being pressed,

#    returns true. If not, returns false. Uses index to determine the gamepad

#    to check, from 0 to 3. The index defaults to 0.

#

#  Gamepad.release?(button[, index])

#    Determines whether the gamepad button determined by button has just been

#    released. If the button has been released, returns true. If not, returns

#    false. Uses index to determine the gamepad to check, from 0 to 3. The

#    index defaults to 0.

#

#  Gamepad.axis_press?(axis[, index])

#    Determines whether the gamepad axis determined by axis is currently being

#    pressed. If the button is being pressed, returns true. If not, returns

#    false. Uses index to determine the gamepad to check, from 0 to 3. The

#    index defaults to 0.

#

#  Gamepad.axis_trigger?(axis[, index])

#    Determines whether the gamepad axis determined by axis is 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. Uses index to determine the gamepad

#    to check, from 0 to 3. The index defaults to 0.

#

#  Gamepad.axis_repeat?(axis[, index])

#    Determines whether the gamepad axis determined by axis is being pressed

#    again. Unlike trigger?(), this takes into account the repeat input of a

#    button being held down continuously. If the button is being pressed,

#    returns true. If not, returns false. Uses index to determine the gamepad

#    to check, from 0 to 3. The index defaults to 0.

#

#  Gamepad.axis_release?(axis[, index])

#    Determines whether the gamepad axis determined by axis has just been

#    released. If the button has been released, returns true. If not, returns

#    false. Uses index to determine the gamepad to check, from 0 to 3. The

#    index defaults to 0.

#

#  Gamepad.axis_value(axis[, index])

#    Returns the current value of the gamepad axis determined by axis. The

#    gamepad checked is determined by index, from 0 to 3. The value for index

#    is 0 if none is provided. If the value for the axis falls within the dead

#    zone specified for that axis, then axis_value() will return 0.

#

#  Gamepad.real_axis_value(axis[, index])

#    Returns the current value of the gamepad axis determined by axis. The

#    gamepad checked is determined by index, from 0 to 3. The value for index

#    is 0 if none is provided. This method ignores the dead zone for the axis,

#    and will always return the current value.

#

#  Gamepad.vibrate(left_motor, right_motor, frames[, index])

#    Causes the motors to vibrate for the number of frames specified. The

#    values for left_motor and right_motor range from 0 to 65535, though the

#    motors themselves may differ in function, as they do in an Xbox 360

#    controller, resulting in a different "feel" depending on the motor you

#    select. Uses index to determine the gamepad to check, from 0 to 3. The

#    index defaults to 0.

#==============================================================================

# * Known Issues

#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#  This script currently has trouble with the vibrate method, which does not

#  allow you to set one motor independently of the other. This part of a

#  planned update sometime in the future.

#==============================================================================

# * Glitchfinder's Advice

#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#  This script is meant for people with a medium or advanced level of scripting

#  knowledge and ability, or for those using scripts that require this module.

#==============================================================================

# * Contact

#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#  Glitchfinder, the author of this script, may be contacted through his

#  website, found at [url=http://www.glitchkey.com]http://www.glitchkey.com[/url]

#

#  You may also find Glitchfinder at [url=http://www.hbgames.org]http://www.hbgames.org[/url]

#==============================================================================

# * Usage

#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#  This script may be used with the following terms and conditions:

#

#    1. This script is free to use in any noncommercial project. If you wish to

#       use this script in a commercial (paid) project, please contact

#       Glitchfinder at his website.

#    2. This script may only be hosted at the following domains:

#         [url=http://www.glitchkey.com]http://www.glitchkey.com[/url]

#         [url=http://www.hbgames.org]http://www.hbgames.org[/url]

#    3. If you wish to host this script elsewhere, please contact Glitchfinder.

#    4. If you wish to translate this script, please contact Glitchfinder. He

#       will need the web address that you plan to host the script at, as well

#       as the language this script is being translated to.

#    5. This header must remain intact at all times.

#    6. Glitchfinder remains the sole owner of this code. He may modify or

#       revoke this license at any time, for any reason.

#    7. Any code derived from code within this script is owned by Glitchfinder,

#       and you must have his permission to publish, host, or distribute his

#       code.

#    8. This license applies to all code derived from the code within this

#       script.

#    9. If you use this script within your project, you must include visible

#       credit to Glitchfinder, within reason.

#≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡

 

#==============================================================================

# ** Gamepad

#------------------------------------------------------------------------------

#  This module performs gamepad input processing

#==============================================================================

 

module Gamepad

  #--------------------------------------------------------------------------

  # * Declare Button Constants

  #--------------------------------------------------------------------------

  DPAD_UP        = 0  # Directional pad up button

  DPAD_DOWN      = 1  # Directional pad down button

  DPAD_LEFT      = 2  # Directional pad left button

  DPAD_RIGHT     = 3  # Directional pad right button

  START          = 4  # Start button

  BACK           = 5  # Back button

  LEFT_THUMB     = 6  # Left thumb button

  RIGHT_THUMB    = 7  # Right thumb button

  LEFT_SHOULDER  = 8  # Left shoulder button

  RIGHT_SHOULDER = 9  # Right shoulder button

  A              = 10 # A button

  B              = 11 # B button

  X              = 12 # X Button

  Y              = 13 # Y Button

  #--------------------------------------------------------------------------

  # * Declare Axis Constants

  #--------------------------------------------------------------------------

  LEFT_TRIGGER   = 0  # Left trigger axis       (0 to 255)

  RIGHT_TRIGGER  = 1  # Right trigger axis      (0 to 255)

  LX             = 2  # Left thumbstick x axis  (-32768 to 32767)

  LY             = 3  # Left thumbstick y axis  (-32768 to 32767)

  RX             = 4  # Right thumbstick x axis (-32768 to 32767)

  RY             = 5  # Right thumbstick y axis (-32768 to 32767)

  #--------------------------------------------------------------------------

  # * Declare Module Variables

  #--------------------------------------------------------------------------

  begin

    # Declare API calls

    @gamepadGetCapabilities = Win32API.new('Input.dll',

      'GamepadGetCapabilities', 'IIP', 'I')

    @gamepadGetDSoundAudioDeviceGuids = Win32API.new('Input.dll',

      'GamepadGetDSoundAudioDeviceGuids', 'IPP', 'I')

    @gamepadGetState = Win32API.new('Input.dll', 'GamepadGetState', 'IP', 'I')

    @gamepadSetState = Win32API.new('Input.dll', 'GamepadSetState', 'IP', 'I')

    # Declare blank structures

    @capabilities = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].pack('c2S2c2s4S2')

    @gamepad = [0, 0, 0, 0, 0, 0, 0].pack('Sc2s4')

    @state = [0, 0, 0, 0, 0, 0, 0, 0].pack('ISc2s4')

    @vibrate = [0, 0].pack('n2')

    @gamepadGetCapabilities.call(0, 0, @capabilities)

    @capabilities.unpack('C2S2C2n6')

    # Create blank button array

    @buttons = Array.new(14, false)

    # Create a blank axis array

    @axis = Array.new(6, false)

    values = Array.new(6, 0)

    zones = [30, 30, 7849, 7849, 8689, 8689]

    # Declare controller information storage

    @controllers = {}

    # Declare default controller information

    @controllers.default = {

      'Active' => false,                   # Controller active flag

      'Change ID' => 0,                    # Current state change ID

      'Press' => @buttons.clone,           # Flags for button press state

      'Trigger' => @buttons.clone,         # Flags for button trigger state

      'Repeat' => @buttons.clone,          # Flags for button repeat state

      'Release' => @buttons.clone,         # Flags for button release state

      'Repeat Timer' => Array.new(14, 0),  # Timer for button repeat state

      'Base Repeat' => 15,                 # Base time for repeat flag (frames)

      'Axes' => Array.new(6, 0),           # Axis values

      'Axis Dead Zones' => zones.clone,    # Dead zone for the axes

      'Axis Press' => @axis.clone,         # Flags for axis press state

      'Axis Trigger' => @axis.clone,       # Flags for axis trigger state

      'Axis Repeat' => @axis.clone,        # Flags for axis repeat state

      'Axis Release' => @axis.clone,       # Flags for axis release state

      'Axis Repeat Timer' => values.clone, # Timer for axis repeat state

      'Vibrate State' => [0, 0],           # Current vibrate state

      'Vibrate Timer' => 0,                # Current vibrate timer

      'Vibrate Repeat Timer' => 0,         # Current rumbe repeat timer

      'Vibrate Minimum Timer' => 0         # Min. time before changing vibrate

    }

    # Iterate through the total number of controllers allowed

    for i in 0..3

      # Add a new controller to the controller array

      @controllers[i] = @controllers.default.clone

    end

  end

  #--------------------------------------------------------------------------

  # * Frame Update

  #--------------------------------------------------------------------------

  def self.update

    # Iterate through all controllers

    for i in 0..3

      # Set up a blank state structure

      state = @state

      # Detect the controller state

      success = @gamepadGetState.call(i, state)

      # If the state was successfully obtained

      if success == 1

        # Set the controller to active

        @controllers[i]['Active'] = true

        # Backup the previous button states

        controller = @controllers[i].clone

        # Reset the controller button states

        @controllers[i]['Press']        = @buttons.clone

        @controllers[i]['Trigger']      = @buttons.clone

        @controllers[i]['Repeat']       = @buttons.clone

        @controllers[i]['Release']      = @buttons.clone

        @controllers[i]['Axis Press']   = @axis.clone

        @controllers[i]['Axis Trigger'] = @axis.clone

        @controllers[i]['Axis Repeat']  = @axis.clone

        @controllers[i]['Axis Release'] = @axis.clone

        # Unpack the controller state

        state = state.unpack('ISC2s4')

        # If the controller state has changed

        if state[0] != @controllers[i]['Change ID']

          # Add the controller button states to the controller state

          @controllers[i]['Press'][0]  = (state[1] & 0x00000001 == 0x00000001)

          @controllers[i]['Press'][1]  = (state[1] & 0x00000002 == 0x00000002)

          @controllers[i]['Press'][2]  = (state[1] & 0x00000004 == 0x00000004)

          @controllers[i]['Press'][3]  = (state[1] & 0x00000008 == 0x00000008)

          @controllers[i]['Press'][4]  = (state[1] & 0x00000010 == 0x00000010)

          @controllers[i]['Press'][5]  = (state[1] & 0x00000020 == 0x00000020)

          @controllers[i]['Press'][6]  = (state[1] & 0x00000040 == 0x00000040)

          @controllers[i]['Press'][7]  = (state[1] & 0x00000080 == 0x00000080)

          @controllers[i]['Press'][8]  = (state[1] & 0x0100 == 0x0100)

          @controllers[i]['Press'][9]  = (state[1] & 0x0200 == 0x0200)

          @controllers[i]['Press'][10] = (state[1] & 0x1000 == 0x1000)

          @controllers[i]['Press'][11] = (state[1] & 0x2000 == 0x2000)

          @controllers[i]['Press'][12] = (state[1] & 0x4000 == 0x4000)

          @controllers[i]['Press'][13] = (state[1] & 0x8000 == 0x8000)

          # Add the controller trigger states to the current controller state

          @controllers[i]['Axes'][0]   = state[2]

          @controllers[i]['Axes'][1]   = state[3]

          # Add the controller thumb coords to the current controller state

          @controllers[i]['Axes'][2]   = state[4]

          @controllers[i]['Axes'][3]   = state[5]

          @controllers[i]['Axes'][4]   = state[6]

          @controllers[i]['Axes'][5]   = state[7]

        end

        # Iterate through the buttons

        for button in 0...@controllers[i]['Press'].size

          # If the button is pressed, and the repeat count is at 0

          if ((@controllers[i]['Press'][button] == true) &&

            (@controllers[i]['Repeat Timer'][button] <= 0))

            # Set the button to repeat

            @controllers[i]['Repeat'][button] = true

            # Get the base repeat time

            repeat_timer = @controllers[i]['Base Repeat']

            # Reset the repeat timer

            @controllers[i]['Repeat Timer'][button] = repeat_timer

          # If the repeat timer is above 0

          elsif @controllers[i]['Repeat Timer'][button] > 0

            # Cycle down the repeat timer

            @controllers[i]['Repeat Timer'][button] -= 1

          end

          # If the button is pressed, and it wasn't pressed previously

          if ((@controllers[i]['Press'][button] == true) &&

            (controller['Press'][button] == false))

            # Set the button to trigger

            @controllers[i]['Trigger'][button] = true

          # If the button is not pressed, and it was previously

          elsif ((@controllers[i]['Press'][button] == false) &&

            (controller['Press'][button] == true))

            # Set the button to release

            @controllers[i]['Release'][button] = true

          end

        end

        # Iterate through the buttons

        for axis in 0...@controllers[i]['Axes'].size

          # If the trigger is greater than the dead zone, set it to pressed

          if (@controllers[i]['Axes'][axis].abs > 

            @controllers[i]['Axis Dead Zones'][axis])

            # Set the axis to pressed

            @controllers[i]['Axis Press'][axis] = true

          end

          # If the axis is pressed, and the repeat count is at 0

          if ((@controllers[i]['Axis Press'][axis] == true) &&

            (@controllers[i]['Axis Repeat Timer'][axis] <= 0))

            # Set the axis to repeat

            @controllers[i]['Axis Repeat'][axis] = true

            # Get the base repeat time

            repeat_timer = @controllers[i]['Base Repeat']

            # Reset the repeat timer

            @controllers[i]['Axis Repeat Timer'][axis] = repeat_timer

          # If the repeat timer is above 0

          elsif @controllers[i]['Axis Repeat Timer'][axis] > 0

            # Cycle down the repeat timer

            @controllers[i]['Axis Repeat Timer'][axis] -= 1

          end

          # If the axis is pressed, and it wasn't pressed previously

          if ((@controllers[i]['Axis Press'][axis] == true) &&

            (controller['Axis Press'][axis] == false))

            # Set the axis to trigger

            @controllers[i]['Axis Trigger'][axis] = true

          # If the axis is not pressed, and it was previously

          elsif ((@controllers[i]['Press'][axis] == false) &&

            (controller['Axis Press'][axis] == true))

            # Set the axis to release

            @controllers[i]['Axis Release'][axis] = true

          end

        end

        # If the controller is set to vibrate

        if @controllers[i]['Vibrate Timer'] > 0

          # If the vibrate repeat timer has reached 0

          if @controllers[i]['Vibrate Repeat Timer'] <= 0

            # Get the current vibration values

            left_motor = @controllers[i]['Vibrate State'][0] - 1

            right_motor = @controllers[i]['Vibrate State'][1] - 1

            # Correct the motor values

            left_motor = 0 if left_motor < 0

            right_motor = 0 if right_motor < 0

            # Create the vibration state structure

            vibrate = [left_motor, right_motor].pack('n2')

            # Reset the controller vibrate state

            @gamepadSetState.call(i, vibrate)

            # Pack the current vibrate state

            vibrate_state = @controllers[i]['Vibrate State'].pack('n2')

            # Set the vibrate state to the current controller vibrate state

            @gamepadSetState.call(i, vibrate_state)

            # Reset the vibrate repeat timer

            @controllers[i]['Vibrate Repeat Timer'] = Graphics.frame_rate

          # If the vibrate repeat timer is greater than 0

          else

            # Decrement the vibrate repeat timer

            @controllers[i]['Vibrate Repeat Timer'] -= 1

          end

          # Decrement the vibrate timer

          @controllers[i]['Vibrate Timer'] -= 1

        # If the vibrate timer is 0, and the vibrate state is still set

        elsif ((@controllers[i]['Vibrate Timer'] <= 0) &&

          (@controllers[i]['Vibrate State'] != [0, 0]))

          # Reset the vibrate state

          @controllers[i]['Vibrate State'] = [0, 0]

          # Set the vibrate repeat timer to 1/3 of a second

          @controllers[i]['Vibrate Repeat Timer'] = Graphics.frame_rate / 3

        # If the vibrate timer is 0 and the vibrate state is cleared

        elsif ((@controllers[i]['Vibrate Timer'] <= 0) &&

          (@controllers[i]['Vibrate State'] == [0, 0]))

          # If the vibrate repeat timer is running

          if @controllers[i]['Vibrate Repeat Timer'] >= 0

            # Decrement the vibrate repeat timer

            @controllers[i]['Vibrate Repeat Timer'] -= 1

          # If the timer has run out

          else

            # Reset the vibrate repeat timer

            @controllers[i]['Vibrate Repeat Timer'] = 0

            # Reset the controller vibrate state

            @gamepadSetState.call(i, @vibrate)

          end

        end

        # If the controller's minimum vibrate update timer is running

        if @controllers[i]['Vibrate Minimum Timer'] > 0

          # Decrement the timer

          @controllers[i]['Vibrate Minimum Timer'] -= 1

        end

      # If the controller is not connected, or the state could not be read

      elsif success == 2 || success == -1

        # Set the controller to inactive

        @controllers[i]['Active'] = false

      end

    end

  end

  #--------------------------------------------------------------------------

  # * Get Button Pressed State

  #     button : button number

  #     index  : controller number (0 to 3)

  #--------------------------------------------------------------------------

  def self.press?(button, index = 0)

    # Return false if the controller is inactive

    return false if @controllers[index]['Active'] == false

    # Return button pressed state

    return @controllers[index]['Press'][button]

  end

  #--------------------------------------------------------------------------

  # * Get Button Triggered State

  #     button : button number

  #     index  : controller number (0 to 3)

  #--------------------------------------------------------------------------

  def self.trigger?(button, index = 0)

    # Return false if the controller is inactive

    return false if @controllers[index]['Active'] == false

    # Return button triggered state

    return @controllers[index]['Trigger'][button]

  end

  #--------------------------------------------------------------------------

  # * Get Button Repeated State

  #     button : button number

  #     index  : controller number (0 to 3)

  #--------------------------------------------------------------------------

  def self.repeat?(button, index = 0)

    # Return false if the controller is inactive

    return false if @controllers[index]['Active'] == false

    # Return button repeated state

    return @controllers[index]['Repeat'][button]

  end

  #--------------------------------------------------------------------------

  # * Get Button Released State

  #     button : button number

  #     index  : controller number (0 to 3)

  #--------------------------------------------------------------------------

  def self.release?(button, index = 0)

    # Return false if the controller is inactive

    return false if @controllers[index]['Active'] == false

    # Return button released state

    return @controllers[index]['Release'][button]

  end

  #--------------------------------------------------------------------------

  # * Get Axis Pressed State

  #     axis  : axis number

  #     index : controller number (0 to 3)

  #--------------------------------------------------------------------------

  def self.axis_press?(axis, index = 0)

    # Return false if the controller is inactive

    return false if @controllers[index]['Active'] == false

    # Return axis pressed state

    return @controllers[index]['Axis Press'][axis]

  end

  #--------------------------------------------------------------------------

  # * Get Axis Triggered State

  #     axis  : axis number

  #     index : controller number (0 to 3)

  #--------------------------------------------------------------------------

  def self.axis_trigger?(axis, index = 0)

    # Return false if the controller is inactive

    return false if @controllers[index]['Active'] == false

    # Return axis triggered state

    return @controllers[index]['Axis Trigger'][axis]

  end

  #--------------------------------------------------------------------------

  # * Get Axis Repeated State

  #     axis  : axis number

  #     index : controller number (0 to 3)

  #--------------------------------------------------------------------------

  def self.axis_repeat?(axis, index = 0)

    # Return false if the controller is inactive

    return false if @controllers[index]['Active'] == false

    # Return axis repeated state

    return @controllers[index]['Axis Repeat'][axis]

  end

  #--------------------------------------------------------------------------

  # * Get Axis Released State

  #     axis  : axis number

  #     index : controller number (0 to 3)

  #--------------------------------------------------------------------------

  def self.axis_release?(axis, index = 0)

    # Return false if the controller is inactive

    return false if @controllers[index]['Active'] == false

    # Return axis released state

    return @controllers[index]['Axis Release'][axis]

  end

  #--------------------------------------------------------------------------

  # * Get Axis Value

  #     axis  : axis number

  #     index : controller number (0 to 3)

  #--------------------------------------------------------------------------

  def self.axis_value(axis, index = 0)

    # Set a temporary variable to the axis value

    value = self.real_axis_value(axis, index)

    # Return axis value

    return value unless value.abs < @controllers[index]['Axis Dead Zones'][axis]

    # Return 0 if the axis is within the dead zone

    return 0

  end

  #--------------------------------------------------------------------------

  # * Get Real Axis Value

  #     axis  : axis number

  #     index : controller number (0 to 3)

  #--------------------------------------------------------------------------

  def self.real_axis_value(axis, index = 0)

    # Return the axis value

    return @controllers[index]['Axes'][axis]

  end

  #--------------------------------------------------------------------------

  # * Set Controller to Vibrate

  #     left_motor  : left motor value (0 to 65535)

  #     right_motor : right motor value (0 to 65535)

  #     frames      : number of frames to vibrate

  #     index       : controller number (0 to 3)

  #--------------------------------------------------------------------------

  def self.vibrate(left_motor, right_motor, frames, index = 0)

    # Return false if the vibrate has updated too recently

    return false if @controllers[index]['Vibrate Minimum Timer'] > 0

    # Set the controller vibrate timer to the number of frames

    @controllers[index]['Vibrate Timer'] = frames

    # Correct the motor values if out of range

    left_motor = 0 if left_motor < 0

    left_motor = 65535 if left_motor > 65535

    right_motor = 0 if right_motor < 0

    right_motor = 65535 if right_motor > 65535

    # Set the controller motor values

    @controllers[index]['Vibrate State'] = [left_motor.to_i, right_motor.to_i]

    # Set the minimum update timer

    @controllers[index]['Vibrate Minimum Timer'] = Graphics.frame_rate / 4

    # Return true if the vibrate was successfully set

    return true

  end

  #--------------------------------------------------------------------------

  # * Initialize Module

  #--------------------------------------------------------------------------

  begin

    # Force an initial update of the gamepad

    self.update

  end

end

 

#==============================================================================

# ** Input

#------------------------------------------------------------------------------

#  This module performs input processing

#==============================================================================

 

module Input

  # Add class data

  class << self

    #------------------------------------------------------------------------

    # * Alias Methods

    #------------------------------------------------------------------------

    # If the update method has not been aliased

    unless method_defined?(:glitch_gamepad_input_update)

      # Alias the update method

      alias glitch_gamepad_input_update update

    end

    #------------------------------------------------------------------------

    # * Frame Update

    #------------------------------------------------------------------------

    def update

      # Call original method

      glitch_gamepad_input_update

      # Update Gamepad module

      Gamepad.update

    end

  end

end

Requirements

This script requires Glitchfinder's Input.dll file to be placed in the game directory.

Instructions

Place this script above Main, and below the default scripts. (I realize this is obvious to most, but some people don't get it.)

You must also place Input.dll into the game's main project folder, since this script needs it to access the XInput functions it uses.

This module is automatically updated by the default Input module, which means that the only time you need to call the update method is in a scene that does not update the default Input module.

This module does not break the functionality of the default Input module.

To use this module to check a gamepad button, simply use one of the four methods (press?(button[, index]), trigger?(button[, index]), repeat?(button[, index]), or release?(button[, index])), where button is the constant of the button you want to check. Button may also be used as Gamepad::BUTTONNAME. For a list of acceptable button names, look below the header, in the section that declares button constants. The methods use index to determine which gamepad to check. If no index is given, they will check gamepad 0. Index is a value from 0 to 3.

To use this module to check a gamepad trigger or joystick, simply use one of the four methods (axis_press?(axis[, index]), axis_trigger?(axis[, index]), axis_repeat?(axis[, index]), or axis_release?(axis[, index])), where axis is the constant of the axis you want to check. Axis may also be used as Gamepad::AXISNAME. For a list of acceptable axis names, look below the header, in the section that declares axis constants. The methods use index to determine which gamepad to check. If no index is given, they will check gamepad 0. Index is a value from 0 to 3.

To use this module to check the value on a gamepad triger or joystick axis, use one of the two methods (axis_value(axis[, index]), real_axis_value(axis[, index])), where axis is the constant of the axis you want to check. Axis may also be used as Gamepad::AXISNAME. For a list of acceptable axis names, look below the header, in the section that declares axis constants. The methods use index to determine which gamepad to check. If no index is given, they will check gamepad 0. Index is a value from 0 to 3. The difference between these two methods is that real_axis_value() will always return the current value, while axis_value will return 0 if the axis falls within its dead zone.

To use this module to cause a gamepad to "rumble", or vibrate, use the vibrate() method. Details for that are below, in the method list.

Method List

Gamepad.update

Updates gamepad input. Calls to this method are not necessary unless the default Input module is not being updated.

Gamepad.press?(button[, index])

Determines whether the gamepad button determined by button is currently being pressed. If the button is being pressed, returns true. If not, returns false. Uses index to determine the gamepad to check, from 0 to 3. The index defaults to 0.

Gamepad.trigger?(button[, index])

Determines whether the gamepad button determined by button is 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. Uses index to determine the gamepad to check, from 0 to 3. The index defaults to 0.

Gamepad.repeat?(button[, index])

Determines whether the gamepad button determined by button is being pressed again. Unlike trigger?(), this takes into account the repeat input of a button being held down continuously. If the button is being pressed, returns true. If not, returns false. Uses index to determine the gamepad to check, from 0 to 3. The index defaults to 0.

Gamepad.release?(button[, index])

Determines whether the gamepad button determined by button has just been released. If the button has been released, returns true. If not, returns false. Uses index to determine the gamepad to check, from 0 to 3. The index defaults to 0.

Gamepad.axis_press?(axis[, index])

Determines whether the gamepad axis determined by axis is currently being pressed. If the button is being pressed, returns true. If not, returns false. Uses index to determine the gamepad to check, from 0 to 3. The index defaults to 0.

Gamepad.axis_trigger?(axis[, index])

Determines whether the gamepad axis determined by axis is 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. Uses index to determine the gamepad to check, from 0 to 3. The index defaults to 0.

Gamepad.axis_repeat?(axis[, index])

Determines whether the gamepad axis determined by axis is being pressed again. Unlike trigger?(), this takes into account the repeat input of a button being held down continuously. If the button is being pressed, returns true. If not, returns false. Uses index to determine the gamepad to check, from 0 to 3. The index defaults to 0.

Gamepad.axis_release?(axis[, index])

Determines whether the gamepad axis determined by axis has just been released. If the button has been released, returns true. If not, returns false. Uses index to determine the gamepad to check, from 0 to 3. The index defaults to 0.

Gamepad.axis_value(axis[, index])

Returns the current value of the gamepad axis determined by axis. The gamepad checked is determined by index, from 0 to 3. The value for index is 0 if none is provided. If the value for the axis falls within the dead zone specified for that axis, then axis_value() will return 0.

Gamepad.real_axis_value(axis[, index])

Returns the current value of the gamepad axis determined by axis. The gamepad checked is determined by index, from 0 to 3. The value for index is 0 if none is provided. This method ignores the dead zone for the axis, and will always return the current value.

Gamepad.vibrate(left_motor, right_motor, frames[, index])
Causes the motors to vibrate for the number of frames specified. The values for left_motor and right_motor range from 0 to 65535, though the motors themselves may differ in function, as they do in an Xbox 360 controller, resulting in a different "feel" depending on the motor you select. Uses index to determine the gamepad to check, from 0 to 3. The index defaults to 0.

Known Issues

This script currently has trouble with the vibrate method, which does not allow you to set one motor independently of the other. This part of a planned update sometime in the future.

Terms and Conditions

  • This script is free to use in any noncommercial project. If you wish to use this script in a commercial (paid) project, please contact Glitchfinder at his website.
  • This script may only be hosted at the following domains:
    http://www.glitchkey.com
    http://www.hbgames.org
  • If you wish to host this script elsewhere, please contact Glitchfinder.
  • If you wish to translate this script, please contact Glitchfinder. He will need the web address that you plan to host the script at, as well as the language this script is being translated to.
  • The script header must remain intact at all times.
  • Glitchfinder remains the sole owner of this code. He may modify or revoke this license at any time, for any reason.
  • Any code derived from code within this script is owned by Glitchfinder, and you must have his permission to publish, host, or distribute his code.
  • This license applies to all code derived from the code within this script.
  • If you use this script within your project, you must include visible credit to Glitchfinder, within reason.
 
Alright, this is the straw(script) that broke the camel's(AInput) back. This will work pefectly for what I have in mind for my games: Fully customizable button configuration in game (not using f1 menu) including gamepad. I will now officially make the switch from Alework's to Glitchfinder's scripts. Congrats, and thanks.
 
Well, I've worked with the script for a while, and I can only say it's a pleasure to use... works like a charm with my Windows Live Controller (the X-Box 360 one), and i'm about to test it with my G25 whenever I got it back on the PC.

I'd like to drag special attention - even though that's kinda there as it's a feature list - to the bunhc of functions included, from analog recognition to Force Feedback. I was there from somewhat halfway through to it's current state to test it, and it's come a long way and is, well... ingeniously improving RMVX's functionality range ;)
Big suggestion from my end if you were looking for a Gamepad script - this is where you can stop and rejoice.
 
i have no idea how to use this :cry:
wanted to use gamepad and use the START button for [cross pause] script ,
but dunno what to do :tongue:
 
mouse_std":351n47up said:
i have no idea how to use this :cry:
wanted to use gamepad and use the START button for [cross pause] script ,
but dunno what to do :tongue:

If you're not a scripter, my recommendation is that you put in a script modification request, since this is a bit advanced. Anyway, I'll go into a basic explanation of how to check the start button, I suppose.

Code:
if Gamepad.trigger?(Gamepad::START)

  #do stuff here

end

Code:
if Gamepad.trigger?(Gamepad::START, 0)

  #do stuff here

end

These would allow any code placed where the comment is to activate if the start button on controller one (the first controller plugged in) was pressed. The only requirement for this code to work is that you add my gamepad script and place the Input.dll file into the game folder. That being said, I'm unfamiliar with the script you wanted to add it to, so I'm not certain where you would need to replace existing lines with calls to my script, which is why I would suggest putting in a request.
 
okay, i finally got around to testing this out, and I have to say.... I don't have a xbox360 controller. :sad:

I have a usb controller that is very similar to a Dualshock 2 controller. I don't like RMXP's default control setup as it seems more suited to a SNES style controller layout. I did find Trebor777's Joypad Module but it isn't complete. It does allow for more use of the controller, but not the analog sticks or vibration. If you could make a script using DirectInput or winmm to allow all of us with controllers other than XBox360 compatible a chance to have a fully functional joypad, I would greatly appreciate it.

Unfortunately I am actually confused by api implementation in rgss otherwise I would do it myself.

Thank you,
Draycos Goldaryn
 
DraycosGoldaryn":yilwnlyt said:
okay, i finally got around to testing this out, and I have to say.... I don't have a xbox360 controller. :sad:

I have a usb controller that is very similar to a Dualshock 2 controller. I don't like RMXP's default control setup as it seems more suited to a SNES style controller layout. I did find Trebor777's Joypad Module but it isn't complete. It does allow for more use of the controller, but not the analog sticks or vibration. If you could make a script using DirectInput or winmm to allow all of us with controllers other than XBox360 compatible a chance to have a fully functional joypad, I would greatly appreciate it.

Unfortunately I am actually confused by api implementation in rgss otherwise I would do it myself.

Thank you,
Draycos Goldaryn

Actually, in this case, there's a reason this script uses a .dll file. That because both XInput and DirectInput have no native Windows implementation. I have to actually program the access points into the .dll files. And last time I looked at DirectInput, I was left extremely confused. Official documentation on it is sorely lacking, unfortunately. That being said, I still have plans to look into it sometime. However, if I do, I'll be making sure to make it into a separate script, instead of trying to merge it into this one. (This will become the XInput Gamepad Module, and the other will become the DirectInput Gamepad Module)

That way, you'll be able to check both modules without them interfering with each other, thus giving you the best of both worlds. One thing to note is that I'm sort of on a scripting binge right now, as evidenced by the fact that I've updated all but one of my posted scripts in the last few days, and posted a couple of new ones to boot. I have several more oldies queued for release, and then I'll get around to either picking up old unfinished scripts or working on dropped ideas like DirectInput.
 
Glitchfinder":ei83lbrm said:
Actually, in this case, there's a reason this script uses a .dll file. That because both XInput and DirectInput have no native Windows implementation. I have to actually program the access points into the .dll files. And last time I looked at DirectInput, I was left extremely confused. Official documentation on it is sorely lacking, unfortunately. That being said, I still have plans to look into it sometime. However, if I do, I'll be making sure to make it into a separate script, instead of trying to merge it into this one. (This will become the XInput Gamepad Module, and the other will become the DirectInput Gamepad Module)

That way, you'll be able to check both modules without them interfering with each other, thus giving you the best of both worlds. One thing to note is that I'm sort of on a scripting binge right now, as evidenced by the fact that I've updated all but one of my posted scripts in the last few days, and posted a couple of new ones to boot. I have several more oldies queued for release, and then I'll get around to either picking up old unfinished scripts or working on dropped ideas like DirectInput.

Alright. Until then, I'm looking into Trebor777's, trying to edit it to improve it (I already have some ideas on how to achieve this. For example, removing the dependency on AInput. It isn't really needed anyway.). I'll use my edited version until if and when a better one is released. I'm learning a little about winmm. It seems to allow everything except force feedback. I'll look into that after I finish tweaking this one first. I may not post it though as it might still contain too much of Trebor's original code... we'll see.

Don't change this script's name. Instead, call the other Glitchfinder's Joypad Input Module That way all your input modules will have the following initials to tell them apart:
GF::KIM #Keyboard
GF::MIM #Mouse
GF::GIM #Gamepad
GF::JIM #Joypad

This is actually how I have them labeled in my script editor. :wink:
 
Line 220: RuntimeError occured. LoadLibrary: Input.dll

Tried it my current project, and in new project as well, got the error both times. I copied the .dll to the main project directory of both the project folders before testing. Am I just missing something?
 
Ace of Spades":2p9f9goz said:
Line 220: RuntimeError occured. LoadLibrary: Input.dll

Tried it my current project, and in new project as well, got the error both times. I copied the .dll to the main project directory of both the project folders before testing. Am I just missing something?

Generally speaking, no. RMXP has an issue where .dll files that should work and/or have worked in the past cease to function and give this error instead. I've talked to a few people about it in the past, and the only solution I've ever found is giving them a recompiled version of the exact same .dll file. I was actually working with theory on my transition.dll file, and the same thing happened to him. It stopped working, and gave that message, and wouldn't work at all until I sent him a newer version that I had been working on to tweak the visual effect it caused.

To be honest, I'm not entirely certain what causes the issue, as the error message is actually intended to be shown if a .dll file cannot be loaded due to a dependency of some sort. (Though you generally get an error regarding what's missing, in that case)

I'm still looking at my older .dll files, this one included, though. I just recently switched from Microsoft Visual Studio Express to Code::Blocks, so I might give a go at recompiling the .dll file for this in the next couple of days using mingw, to see if that helps.
 
Hello,

I am enjoying the script and so far its working for me. However when the project starts, before the title screen, a window pops up with various numbers like "[1,1,4,6292,1,256,256,256,256]" click the ok button and the game loads normally. I am rather new to scripting so I'm sorry for the hassle, I know its coming from your script - because it popped up before I made any changes. I am not sure where exactly in your script - any direction would be greatly appreciated.

Oh, I am running the project from inside rpgmakerxp - not independently, still learning the scripting.
 
newcoda":izc8vmb7 said:
Hello,

I am enjoying the script and so far its working for me. However when the project starts, before the title screen, a window pops up with various numbers like "[1,1,4,6292,1,256,256,256,256]" click the ok button and the game loads normally. I am rather new to scripting so I'm sorry for the hassle, I know its coming from your script - because it popped up before I made any changes. I am not sure where exactly in your script - any direction would be greatly appreciated.

Oh, I am running the project from inside rpgmakerxp - not independently, still learning the scripting.
I could have sworn I removed that. I just updated the script in the first post so that it no longer does that. Thanks for the quick response, BlueScope.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top