7Soul

Gamepad script

Jun 15th, 2019
534
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.93 KB | None | 0 0
  1. #==============================================================================
  2. # Gamepad Extender v1.1 (2/20/15)
  3. # by Lone Wolf
  4. #------------------------------------------------------------------------------
  5. # This allows scripters to utilize the extra buttons on modern
  6. # XInput-compatible gamepads. It requires DirectX 9.0 or later and
  7. # an XInput compatible gamepad. Incompatible pads will default to
  8. # using the standard Input module functionality.
  9. #
  10. # This is not a plug-and-play script.
  11. # Some knowledge of RGSS is required for proper use.
  12. #
  13. # Instructions:
  14. # 1) Paste in the Materials section
  15. # 2) Replace button calls in (other) scripts to use gamepad buttons as needed
  16. # (see Command Reference below)
  17. # Optional:
  18. # 2) Use the PadConfig section to specify button differences between
  19. # Gamepad and Keyboard (for players without gamepads)
  20. # 3) Replace direct button calls in your scripts (and the defaults) with
  21. # PadConfig calls or these will do nothing
  22. # (see Command Reference below)
  23. #------------------------------------------------------------------------------
  24. # Command Reference:
  25. #------------------------------------------------------------------------------
  26. # All calls to extended buttons on Pad 1 can be made through the Input module.
  27. # When using multiple pads, send calls to WolfPad with pad number (0...3)
  28. # as the final parameter. (i.e. WolfPad.press?(:A, 3) )
  29. #
  30. # The current list of mappable buttons is as follows:
  31. #
  32. # :A, :B, :X, :Y - XBOX 360 standard face buttons.
  33. # :L1, :L2, :R1, :R2 - Four triggers (LB, LT, RB, RT)
  34. # :SELECT, :START - Back and Start buttons
  35. # :L3, :R3 - Clickable Analog buttons
  36. #
  37. # :UP, :DOWN,
  38. # :LEFT, :RIGHT - D-Pad buttons
  39. #
  40. # :L_UP, :L_DOWN
  41. # :L_LEFT, :L_RIGHT - Left stick directions
  42. #
  43. # :R_UP, :R_DOWN
  44. # :R_LEFT, :R_RIGHT - Right stick directions
  45. #
  46. # NON-STANDARD MAPPINGS WILL DO NOTHING without a compatible gamepad.
  47. # To that end, use calls to PadConfig to remap non-standard keys into
  48. # the standard domain where possible.
  49. #
  50. # for example: Input.trigger?(PadConfig.page_down)
  51. # will return :R1 if a gamepad is plugged in, but :R otherwise
  52. #
  53. # Analog values can be referenced with the following commands:
  54. # left_stick
  55. # right_stick
  56. # left_trigger
  57. # right_trigger
  58. #
  59. # Directional values of analog sticks can be referenced with these:
  60. # lstick4
  61. # lstick8
  62. # rstick4
  63. # rstick8
  64. #
  65. # Controller vibration can be accessed with these:
  66. # vibrate(left_motor, right_motor, frame_duration)
  67. # set_motors(left_motor, right_motor)
  68. #
  69. # All functions take an optional gamepad id (0-3) as their final parameter.
  70. #
  71. #------------------------------------------------------------------------------
  72. # Terms of Use:
  73. #------------------------------------------------------------------------------
  74. # If you use it, give credit. With a few caveats:
  75. #
  76. # Can't call it alpha nay more, but I consider this script in-development.
  77. # I make no guarantees of compatibility with other scripts.
  78. #
  79. # Contact me via PM is you plan on using this in a commercial game.
  80. # I probably won't charge anything, but I will want to know it's out there.
  81. #
  82. # This script was posted at the official RPG Maker forums.
  83. # Do modify or redistribute this script by itself, though you may
  84. # include a configured version with your own script demos provided
  85. # you inclide this header in its entirety.
  86. #------------------------------------------------------------------------------
  87. # Contact Info:
  88. #------------------------------------------------------------------------------
  89. # I can be reached via PM only at the RPG Maker Web forums.
  90. # (http://forums.rpgmakerweb.com)
  91. #
  92. # PM'ing the user Lone Wolf at other RPG Maker sites may have...
  93. # unpredicatable results. I made someone really happy the day I registered...
  94. #------------------------------------------------------------------------------
  95. # Credits:
  96. # Lone Wolf (99% of the code)
  97. # raulf17 (directional movement bug fix; now obsolete)
  98. #------------------------------------------------------------------------------
  99. # 翻訳したいんですか?いいんだが、まだ未完成です。
  100. #==============================================================================
  101. module PadConfig
  102. # Basic configuration settings:
  103. # static:
  104. CONTROLLERS = 1 # can be any number from 1-4, higher values may cause errors
  105.  
  106. # can be redefined by other scripts and changed in-game:
  107. def self.deadzone # Deadzone for axis input (%), may require adjusting
  108. 0.1
  109. end
  110. def self.move_with_stick # Use left-analog stick with dir4 and dir8
  111. false
  112. end
  113. def self.enable_vibration # Enable force-feedback
  114. true
  115. end
  116.  
  117. # Use this section to write flexible button-mappings for your scripts.
  118. # Add additional methods as needed.
  119. # Format:
  120. # WolfPad.plugged_in? ? (gamepad binding) : (fallback binding)
  121. def self.confirm
  122. WolfPad.plugged_in? ? :A : :C
  123. end
  124. def self.cancel
  125. WolfPad.plugged_in? ? :B : :B
  126. end
  127. def self.dash
  128. WolfPad.plugged_in? ? :X : :A
  129. end
  130. def self.menu
  131. WolfPad.plugged_in? ? :Y : :B
  132. end
  133. def self.page_up
  134. WolfPad.plugged_in? ? :L1 : :L
  135. end
  136. def self.page_down
  137. WolfPad.plugged_in? ? :R1 : :R
  138. end
  139. def self.debug
  140. WolfPad.plugged_in? ? :L2 : :CTRL
  141. end
  142. def self.debug2
  143. WolfPad.plugged_in? ? :R3 : :F9
  144. end
  145. end
  146. # Main module:
  147. module WolfPad
  148. def self.update
  149. for pad_index in 0...PadConfig::CONTROLLERS
  150. input = get_state(pad_index)
  151. if @packet[pad_index] == input[0]
  152. set_holds(pad_index)
  153. next
  154. end
  155. @packet[pad_index] = input[0]
  156. @buttons[pad_index] = (input[1] | 0x10000).to_s(2)
  157. if @buttons[pad_index].to_i != 10000000000000000
  158. $game_system.gamepad = true
  159. $game_system.keyboard = false
  160. end
  161. @triggers[pad_index] = [input[2], input[3]]
  162. @lstick[pad_index] = [constrain_axis(input[4]), -constrain_axis(input[5])]
  163. @rstick[pad_index] = [constrain_axis(input[6]), -constrain_axis(input[7])]
  164. set_holds(pad_index)
  165. end
  166. update_vibration
  167. # Extra readout functions go here.
  168. #dircheck
  169. end
  170. def self.test # Prints no. of detected controllers (debugging use only)
  171. detected = 0
  172. for i in 0...PadConfig::CONTROLLERS
  173. self.update
  174. detected += plugged_in?(i) ? 1 : 0
  175. end
  176. puts sprintf("%d XInput controller(s) in use.", detected)
  177. end
  178. def self.readout # prints a range from the holds table (debugging use only)
  179. for i in 00...16
  180. print sprintf(" %d", @holds[0, i])
  181. print sprintf(" %d", @holds[1, i])
  182. end
  183. puts ";"
  184. end
  185. def self.dircheck
  186. for i in 0...PadConfig::CONTROLLERS
  187. print sprintf(" %d", key_holds(:UP, i))
  188. print sprintf(" %d", key_holds(:LEFT, i))
  189. print sprintf(" %d", key_holds(:DOWN, i))
  190. print sprintf(" %d", key_holds(:RIGHT, i))
  191. print " : "
  192. end
  193. puts ";"
  194. end
  195.  
  196. # Basic vibration call.
  197. # For simplicity, motor values should be floats from 0.0 to 1.0
  198. def self.vibrate(left, right, duration, pad_index = 0)
  199. return unless PadConfig.enable_vibration
  200. set_motors(left, right, pad_index)
  201. @vibrations[pad_index] = duration
  202. end
  203. # Counts down vibration event timers
  204. def self.update_vibration
  205. for pad in 0...PadConfig::CONTROLLERS
  206. next if @vibrations[pad] == -1
  207. @vibrations[pad] -= 1
  208. if @vibrations[pad] == 0
  209. @vibrations[pad] = -1
  210. set_motors(0, 0, pad)
  211. end
  212. end
  213. end
  214. # Set left and right motor speeds. Vibration continues until stopped.
  215. # Repeated calls with different values can create vibration effects.
  216. # For simplicity, input values should be floats from 0.0 to 1.0
  217. def self.set_motors(left, right, pad_index = 0)
  218. return unless (PadConfig.enable_vibration) || (left == 0 && right == 0)
  219. left_v = [left * 65535, 65535].min
  220. right_v = [right * 65535, 65535].min
  221. vibration = [left_v, right_v].pack("SS")
  222. @set_state.call(pad_index, vibration)
  223. end
  224. def self.press?(button, pad_index = 0)
  225. key_holds(button, pad_index) > 0
  226. end
  227. def self.trigger?(button, pad_index = 0)
  228. key_holds(button, pad_index) == 1
  229. end
  230. def self.repeat?(button, p_i = 0)
  231. return true if key_holds(button, p_i) == 1
  232. return true if key_holds(button, p_i) > 30 && key_holds(button, p_i) % 5 == 0
  233. end
  234. # Returns left stick as a pair of floats [x, y] between -1.0 and 1.0
  235. def self.left_stick(pad_index = 0)
  236. @lstick[pad_index]
  237. end
  238. # Returns right stick as a pair of floats [x, y] between -1.0 and 1.0
  239. def self.right_stick(pad_index = 0)
  240. @rstick[pad_index]
  241. end
  242. # Returns left trigger as float between 0.0 to 1.0
  243. def self.left_trigger(pad_index = 0)
  244. @triggers[pad_index][0] / 255.0
  245. end
  246. # Returns right trigger as float between 0.0 to 1.0
  247. def self.right_trigger(pad_index = 0)
  248. @triggers[pad_index][1] / 255.0
  249. end
  250. def self.dir4(p_i = 0)
  251. return lstick4(p_i) if PadConfig.move_with_stick
  252. if press?(:UP, p_i)
  253. 8
  254. elsif press?(:RIGHT, p_i)
  255. 6
  256. elsif press?(:LEFT, p_i)
  257. 4
  258. elsif press?(:DOWN, p_i)
  259. 2
  260. else
  261. 0
  262. end
  263. end
  264. def self.dir8(p_i = 0)
  265. return lstick8(p_i) if PadConfig.move_with_stick
  266. if press?(:UP, p_i) and press?(:LEFT, p_i)
  267. 7
  268. elsif press?(:UP, p_i) and press?(:RIGHT, p_i)
  269. 9
  270. elsif press?(:DOWN, p_i) and press?(:LEFT, p_i)
  271. 1
  272. elsif press?(:DOWN, p_i) and press?(:RIGHT, p_i)
  273. 3
  274. else
  275. dir4(p_i)
  276. end
  277. end
  278. # Left-stick direction
  279. def self.lstick8(p_i = 0)
  280. flags_to_dir8(key_holds(:L_RIGHT, p_i),key_holds(:L_LEFT, p_i),
  281. key_holds(:L_DOWN, p_i),key_holds(:L_UP, p_i))
  282. end
  283. def self.lstick4(p_i = 0)
  284. flags_to_dir4(key_holds(:L_RIGHT, p_i),key_holds(:L_LEFT, p_i),
  285. key_holds(:L_DOWN, p_i),key_holds(:L_UP, p_i))
  286. end
  287. # Right-stick direction
  288. def self.rstick8(p_i = 0)
  289. flags_to_dir8(key_holds(:R_RIGHT, p_i),key_holds(:R_LEFT, p_i),
  290. key_holds(:R_DOWN, p_i),key_holds(:R_UP, p_i))
  291. end
  292. def self.rstick4(p_i = 0)
  293. flags_to_dir4(key_holds(:R_RIGHT, p_i),key_holds(:R_LEFT, p_i),
  294. key_holds(:R_DOWN, p_i),key_holds(:R_UP, p_i))
  295. end
  296. def self.plugged_in?(pad_index = 0)
  297. @packet[pad_index] && @packet[pad_index] > 0
  298. end
  299. def self.keyboard_key?(button)
  300. [email protected]_key?(button)
  301. end
  302.  
  303. #Helper functions:
  304. # convert signed half-word axis state to float
  305. def self.constrain_axis(axis)
  306. val = axis.to_f / 2**15
  307. val.abs > PadConfig.deadzone ? val : 0
  308. end
  309.  
  310. # derives a dir8 value from directional hold values
  311. def self.flags_to_dir8(right, left, down, up)
  312. x = right == left ? 0 : (right > left ? 1 : 2)
  313. y = down == up ? 0 : (down > up ? 1 : 2)
  314. table = [[0, 2, 8],
  315. [6, 3, 9],
  316. [4, 1, 7]]
  317. return table[x][y]
  318. end
  319. # derives a dir4 value from directional hold values
  320. def self.flags_to_dir4(right, left, down, up)
  321. selection = [right, left, down, up].max
  322. table = [0,0,down,0,left,0,right,0,up]
  323. return table.index(selection)
  324. end
  325.  
  326. # calculates the precise geometric angle from stick axis values [x,y]
  327. def self.axis_to_angle(axis)
  328. cy = -axis[1]
  329. cx = -axis[0]
  330. return -1 if cy == 0 && cx == 0
  331. angle = Math.atan2(cx, cy) * 180 / Math::PI
  332. angle = angle < 0 ? angle + 360 : angle
  333. return angle
  334. end
  335.  
  336. # Original angle-conversion handlers for analog sticks
  337. # OBSOLETE: preserved for reference only
  338. def self.axis_to_dir8(axis)
  339. angle_to_dir8(axis_to_angle(axis))
  340. end
  341. def self.axis_to_dir4(axis)
  342. angle_to_dir4(axis_to_angle(axis))
  343. end
  344.  
  345. def self.angle_to_dir8(angle)
  346. return 0 if angle == -1
  347. d = 0
  348. if angle < 22.5 || angle >= 337.5
  349. d = 8
  350. elsif angle < 67.5
  351. d = 7
  352. elsif angle < 112.5
  353. d = 4
  354. elsif angle < 157.5
  355. d = 1
  356. elsif angle < 202.5
  357. d = 2
  358. elsif angle < 247.5
  359. d = 3
  360. elsif angle < 292.5
  361. d = 6
  362. elsif angle < 337.5
  363. d = 9
  364. end
  365. return d
  366. end
  367.  
  368. def self.angle_to_dir4(angle)
  369. return 0 if angle == -1
  370. d = 0
  371. if angle < 45 || angle >= 315
  372. d = 8
  373. elsif angle < 135
  374. d = 4
  375. elsif angle < 225
  376. d = 2
  377. elsif angle < 315
  378. d = 6
  379. end
  380. return d
  381. end
  382.  
  383. private # methods past here can't be called from outside
  384. # This hash correlates RM's Input to XInput keys. Experienced Users only!
  385. # The Input module will handle any keys not listed here (i.e. :CTRL) itself.
  386. # Integers refer to specific gamepad button IDs.
  387. @keys = {
  388. :UP => 15, #d-pad up
  389. :DOWN => 14, #d-pad left
  390. :LEFT => 13, #d-pad down
  391. :RIGHT => 12, #d-pad right
  392. :C => 3, #lower face button
  393. :B => 2, #right face button
  394. :A => 1, #left face button
  395. :Y => 0, #upper face button
  396. :L => 7, #upper left trigger
  397. :R => 6, #upper right trigger
  398. :START => 11,
  399. :MENU => 11,
  400. :SELECT => 10,
  401. :L3 => 9, #left thubstick button
  402. :R3 => 8, #right thubstick button
  403. :L2 => 16, #lower left trigger (press only)
  404. :R2 => 17, #lower right trigger (press only)
  405. :L_UP => 21,
  406. :L_DOWN => 20,
  407. :L_LEFT => 19,
  408. :L_RIGHT =>18,
  409. :R_UP => 25,
  410. :R_DOWN => 24,
  411. :R_LEFT => 23,
  412. :R_RIGHT => 22
  413. }
  414. #Win32API calls. Leave these alone.
  415. # Calls to XInput9_1_0.dll now only occur if DirectX is missing
  416. @set_state = Win32API.new("XINPUT1_3", "XInputSetState", "IP", "V") rescue
  417. Win32API.new("XINPUT9_1_0", "XInputSetState", "IP", "V")
  418. @get_state = Win32API.new("XINPUT1_3", "XInputGetState", "IP", "L") rescue
  419. Win32API.new("XINPUT9_1_0", "XInputGetState", "IP", "L")
  420. #Initializers
  421. # Will store data for number of gamepads in use.
  422. @packet = Array.new(PadConfig::CONTROLLERS)
  423. @buttons = Array.new(PadConfig::CONTROLLERS)
  424. @triggers = Array.new(PadConfig::CONTROLLERS)
  425. @lstick = Array.new(PadConfig::CONTROLLERS)
  426. @rstick = Array.new(PadConfig::CONTROLLERS)
  427. # tracks how long buttons have been pressed
  428. @holds = Table.new(PadConfig::CONTROLLERS, 26)
  429. # stores vibration event timers
  430. @vibrations = Array.new(PadConfig::CONTROLLERS, -1)
  431. def self.key_holds(symbol, pad_index)
  432. return 0 if keyboard_key?(symbol)
  433. @holds[pad_index, @keys[symbol]]
  434. end
  435. def self.get_state(pad_index)
  436. state = "\0" * 16
  437. @get_state.call(pad_index, state)
  438. return state.unpack("LSCCssss")
  439. end
  440. def self.set_holds(p_i)
  441. for i in 1...17
  442. @holds[p_i, i-1] = @buttons[p_i][i].to_i > 0 ? @holds[p_i, i-1] + 1 : 0
  443. end
  444. @holds[p_i, 16] = left_trigger(p_i) >= 0.5 ? @holds[p_i, 16]+1 : 0
  445. @holds[p_i, 17] = right_trigger(p_i) >= 0.5 ? @holds[p_i, 17]+1 : 0
  446. @holds[p_i, 18] = left_stick(p_i)[0] >= 0.5 ? @holds[p_i, 18]+1 : 0
  447. @holds[p_i, 19] = left_stick(p_i)[0] <= -0.5 ? @holds[p_i, 19]+1 : 0
  448. @holds[p_i, 20] = left_stick(p_i)[1] >= 0.5 ? @holds[p_i, 20]+1 : 0
  449. @holds[p_i, 21] = left_stick(p_i)[1] <= -0.5 ? @holds[p_i, 21]+1 : 0
  450. @holds[p_i, 22] = right_stick(p_i)[0] >= 0.5 ? @holds[p_i, 22]+1 : 0
  451. @holds[p_i, 23] = right_stick(p_i)[0] <= -0.5 ? @holds[p_i, 23]+1 : 0
  452. @holds[p_i, 24] = right_stick(p_i)[1] >= 0.5 ? @holds[p_i, 24]+1 : 0
  453. @holds[p_i, 25] = right_stick(p_i)[1] <= -0.5 ? @holds[p_i, 25]+1 : 0
  454. end
  455. end
  456.  
  457. # Aliases to tie the above into VXAce's Input module
  458. module Input
  459. class << self
  460. alias :vxa_update :update
  461. alias :vxa_press? :press?
  462. alias :vxa_trigger? :trigger?
  463. alias :vxa_repeat? :repeat?
  464. alias :vxa_dir4 :dir4
  465. alias :vxa_dir8 :dir8
  466. end
  467.  
  468. def self.update
  469. WolfPad.update
  470. vxa_update
  471. end
  472.  
  473. def self.press?(button)
  474. return vxa_press?(button) if !$game_system.gamepad
  475. return WolfPad.press?(button) if WolfPad.plugged_in? && $game_system.gamepad
  476. return vxa_press?(button)
  477. end
  478.  
  479. def self.trigger?(button)
  480. return vxa_trigger?(button) if !$game_system.gamepad
  481. return WolfPad.trigger?(button) if WolfPad.plugged_in? && $game_system.gamepad
  482. return vxa_trigger?(button)
  483. end
  484.  
  485. def self.repeat?(button)
  486. return vxa_repeat?(button) if !$game_system.gamepad
  487. return WolfPad.repeat?(button) if WolfPad.plugged_in? && $game_system.gamepad
  488. return vxa_repeat?(button)
  489. end
  490.  
  491. def self.dir4
  492. WolfPad.plugged_in? && $game_system.gamepad ? WolfPad.dir4 : vxa_dir4
  493. end
  494.  
  495. def self.dir8
  496. WolfPad.plugged_in? && $game_system.gamepad ? WolfPad.dir8 : vxa_dir8
  497. end
  498. end
Advertisement
Add Comment
Please, Sign In to add comment