设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 2198|回复: 7
打印 上一主题 下一主题

[讨论] Input內建按键模块当游戏效率差时出现延迟或无效情况

[复制链接]

Lv4.逐梦者

梦石
0
星屑
14629
在线时间
2152 小时
注册时间
2016-9-20
帖子
861
跳转到指定楼层
1
发表于 2022-2-24 16:06:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 ppspssss 于 2022-2-24 16:11 编辑

以下内容为楼主猜测, 请自行判断 不要尽信

我一开始是觉得游戏中自带的游戏按键, 在游戏中貌似和全键盘一样没什么问题, print出来的的数值和全键盘一样没有延迟和无效, 但貌似在如脚运算计算量大, 并行事件大的时候 ,或游戏不足以稳定维持一般帧率(如40帧)等等...时候 , 我就发现按键会出现一时有效, 一时无效的情况, 具体症状为手感极为差, 走动还会出现松开键后还一直走的情况, 一开始以为事件问题,用脚本就好 ,然后去了用脚本测试一下的print一下Input, 发现游戏效率不足时, 时使脚本也是按下成功率低和延迟 ,若使用全键盘的话则不会有这个问题, 每次按键均成功, 我推测Input模块应该是和游戏的运算连为一体, 所以当游戏帧数不稳时, 虽然游戏卡, 但连带Input检测次数一起降低, 而全键盘脚本因使用Win32的Api, 因而为后台获取不受游戏帧数效率影响, 这个问题我觉得还是太大了  ,因此我认为最好还是用上全键盘脚本 , 不过缺点好像是不能改键用手柄, 这个问题好像即使RGSS3, RGD 一样会卡, 是因为一样使用Input内建模块? 如何避免这个情况, 我方案(仅参考)使用Input的换成全键盘脚本, 2.不要把游戏做得卡, 3.不做要精准动作的游戏, 比如做成回合制按键就延迟一点应该没所谓


例如: (参考)
if Input.trigger?(Input::C)#自带的Input会时常响应失败
全键盘脚本
if Kboard.trigger?($R_Key_C)#换了全键盘后,没有延时问题,

我发的贴子大多未经整理是草稿抱歉

Lv5.捕梦者 (版主)

梦石
1
星屑
23994
在线时间
3339 小时
注册时间
2011-7-8
帖子
3926

开拓者

2
发表于 2022-2-24 16:55:13 | 只看该作者
本帖最后由 guoxiaomi 于 2022-2-24 16:57 编辑

印象中全键盘好像是调用了GetAsyncKeyState,也就是此刻下的按键信息。
RM,我的猜测是每次调用Input.update的时候,会获取从上一次调用Input.update到此刻间的所有按键信息,然后储存起来。如果你不调用Input.update,那么按键信息永远不会更新。如果因为某些原因导致“按键抬起”的信息丢失,RM就会认为这个按键是一直按下的,从而无限撞墙。

参考:https://blog.csdn.net/feidegengao/article/details/8528911

点评

在两次调用Input.update之间,Input的各项判定保证一致,是RM这个引擎的特色  发表于 2022-2-24 21:42
比如在update加入该按键的无效return判定。(默认的input在这方面做的还是挺好的,二者的优点结合起来使用比如wasd按键精度或者说体验感觉上好很多。  发表于 2022-2-24 19:22
怎么抵消无效按键?  发表于 2022-2-24 18:04
全键盘脚本给人的感觉就像是一个“全局变量”,在任一场景按下,如果没有及时抵消无效按键,那么在之后场景的任一个相同按键判断都是有效的。  发表于 2022-2-24 17:30
熟悉rgss和ruby,xp区版主~
正在填坑:《膜拜组传奇》讲述膜拜组和学霸们的故事。
已上steam:与TXBD合作的Reformers《变革者》
* 战斗调用公共事件 *
* RGSOS 网络脚本 *
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
7921
在线时间
1049 小时
注册时间
2012-4-3
帖子
1271

开拓者

3
发表于 2022-2-24 17:05:43 手机端发表。 | 只看该作者
我记得论坛有发布过input的内核脚本,也就是可以把全键盘的按键移入input里面,最直接的应用是wasd替代默认的方向键。
游戏卡顿吞键已经不是什么新鲜事了,机能不足的各游戏世代很常见。而无视卡顿仍然保留按键输入依然有明显问题,常见的操作系统出现无响应,输入的保留,在恢复响应之后,就是一顿猛如虎的“反扑”,只能说不要乱动是最好操作了。
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

遠航の猫咪

梦石
3
星屑
23191
在线时间
2387 小时
注册时间
2005-10-15
帖子
1166

开拓者

4
发表于 2022-2-24 20:14:24 | 只看该作者
可以试一下这个版本
已经删除了对SEP公共核心的依赖,当然也删除了自动绑定窗口事件按键处理的功能
因为插件自己保留了一个Flag用于更新状态,不是完全依赖GetAsyncKeyState,所以不会出现更新延迟时丢失按键的问题,除非延迟到两帧之间存在了完整的按键+弹起的过程
RUBY 代码复制
  1. #==============================================================================
  2. # ■ [Keyboard Indie] 全键盘处理核心 v1.1 by SailCat
  3. #------------------------------------------------------------------------------
  4. #   方法:本脚本插入Main之前使用
  5. #   依赖:无
  6. #   版本:v1.1 (Build 220224)
  7. #   效果:
  8. #     1. 全键盘按键响应
  9. #     2. 注入Input模块的update处理
  10. #     3. Lock键、Shift/Ctrl/Alt/Win键状态的响应
  11. #     4. 获得输入的字符
  12. #   配置:重复延迟和重复间隔速率
  13. #   冲突:其他类似脚本
  14. #   说明:
  15. #     1. 调用全键盘方法为Keyboard.press?(键名常量、符号或字符)。
  16. #     2. 上述press?也可替换为trigger?或repeat?,含义与Input中的同名方法相同。
  17. #     3. 其他检测包括对于Lock键的状态,Shift/Ctrl/Alt/Win的状态检测等。
  18. #     4. 使用Keyboard.type_char可以获得打字键入的字符。
  19. #==============================================================================
  20. #==============================================================================
  21. # ■ SailCat's 插件公用
  22. #==============================================================================
  23. module SailCat
  24.   #--------------------------------------------------------------------------
  25.   # ● 脚本配置区
  26.   #--------------------------------------------------------------------------
  27.   module Keyboard_Config
  28.     REPEAT_DELAY = 8            # 首次重复前的延迟值(帧)
  29.     REPEAT_SPEED = 4            # 每次重复按键的间隔(帧),越大越慢
  30.     #--------------------------------------------------------------------------
  31.     # ● 配置检查,请勿更改
  32.     #--------------------------------------------------------------------------
  33.     raise "重复按键的间隔不能低于1帧" unless REPEAT_SPEED > 0
  34.   end
  35. end
  36.  
  37. #==============================================================================
  38. # ■ 全键盘处理核心
  39. #==============================================================================
  40. module Keyboard
  41.   include SailCat::Keyboard_Config
  42.   #--------------------------------------------------------------------------
  43.   # ● 常量
  44.   #--------------------------------------------------------------------------
  45.   NONE = 0
  46.   L_BUTTON, R_BUTTON, CANCEL, M_BUTTON, X_BUTTON1, X_BUTTON2 = *1..6
  47.   BACKSPACE, TAB, LINE_FEED, V_TAB, CLEAR, ENTER = *8..13
  48.   SHIFT_KEY, CONTROL_KEY, ALT_KEY, PAUSE_KEY = *16..19
  49.   CAPS_LOCK, KANA_MODE, JUNJA_MODE, DUMMY, FINAL_MODE, KANJI_MODE = *20..25
  50.   ESCAPE, IME_CONVERT, IME_NONCONVERT, IME_ACCEPT, IME_MODECHANGE = *27..31
  51.   SPACE, PAGEUP, PAGEDOWN, ENDKEY, HOME, LEFT, UP, RIGHT, DOWN = *32..40
  52.   SELECT, PRINT, EXECUTE, PRINTSCREEN, INSERT, DELETE, HELP = *41..47
  53.   D0, D1, D2, D3, D4, D5, D6, D7, D8, D9 = *48..57
  54.   A, B, C, D, E, F, G, H, I, J, K, L, M = *65..77
  55.   N, O, P, Q, R, S, T, U, V, W, X, Y, Z = *78..90
  56.   LWIN, RWIN, APPS, SLEEP = 91, 92, 93, 95
  57.   NUM0, NUM1, NUM2, NUM3, NUM4, NUM5, NUM6, NUM7, NUM8, NUM9 = *96..105
  58.   MULTIPLY, ADD, SEPARATOR, SUBTRACT, DECIMAL, DIVIDE = *106..111
  59.   F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12 = *112..123
  60.   F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24 = *124..135
  61.   NUM_LOCK, SCROLL_LOCK = 144, 145
  62.   L_SHIFT, R_SHIFT, L_CTRL, R_CTRL, L_ALT, R_ALT = *160..165
  63.   B_BACK, B_FORWARD, B_REFRESH, B_STOP, B_SEARCH, B_FAVOR, B_HOME = *166..172
  64.   VOL_MUTE, VOL_DOWN, VOL_UP = *173..175
  65.   MEDIA_NEXT, MEDIA_PREVIOUS, MEDIA_STOP, MEDIA_PLAYPAUSE = *176..179
  66.   LAUNCH_MAIL, SELECT_MEDIA, LAUNCH_APP1, LAUNCH_APP2 = *180..183
  67.   SEMICOLON, PLUS, COMMA, MINUS, PERIOD, QUESTION, TILDE = *186..192
  68.   L_BRACE, PIPE, R_BRACE, QUOTE, OEM8 = *219..223
  69.   BACKSLASH, PROCESS_KEY, PACKET = 226, 229, 231
  70.   ATTN, CRSEL, EXSEL, ERASE_EOF, PLAY, ZOOM, NONAME, PA1, OEM_CLEAR = *246..254
  71.   ANY_BUTTON = [1, 2, 4, 5, 6]
  72.   ANY_KEY = [8..13, 27, 32..57, 65..90, 96..135, 186..192, 219..223].map do |x|
  73.     x.to_a
  74.   end.flatten
  75.   #--------------------------------------------------------------------------
  76.   # ● API
  77.   #--------------------------------------------------------------------------
  78.   GetAsyncKeyState = Win32API.new("user32", "GetAsyncKeyState", "i", "i")
  79.   GetKeyState = Win32API.new("user32", "GetKeyState", "i", "i")
  80.   #--------------------------------------------------------------------------
  81.   # ● 用于检测重复按键的标记器
  82.   #--------------------------------------------------------------------------
  83.   Flags = {}
  84.   #--------------------------------------------------------------------------
  85.   # ● 更新键盘输入,该方法每帧调用1次
  86.   #--------------------------------------------------------------------------
  87.   def self.update
  88.     @keychar = nil
  89.     Flags.each_key do |k|
  90.       GetAsyncKeyState.call(k) & 32768 != 0 ? Flags[k] += 1 : Flags.delete(k)
  91.     end
  92.   end
  93.   #--------------------------------------------------------------------------
  94.   # ● 判断对应的键是否现在被按下
  95.   #--------------------------------------------------------------------------
  96.   def self.press?(key)
  97.     key = get_key(key) unless key.is_a?(Numeric) or key.is_a?(Array)
  98.     return key.any?{|k| press?(k)} if key.is_a?(Array)
  99.     GetAsyncKeyState.call(key) & 32768 != 0 ? (Flags[key] ||= 0; true) : false
  100.   end
  101.   #--------------------------------------------------------------------------
  102.   # ● 判断对应的键是否重新被按下
  103.   #--------------------------------------------------------------------------
  104.   def self.trigger?(key)
  105.     key = get_key(key) unless key.is_a?(Numeric) or key.is_a?(Array)
  106.     return key.any?{|k| trigger?(k)} if key.is_a?(Array)
  107.     Flags[key] ? Flags[key] == 0 : press?(key)
  108.   end
  109.   #--------------------------------------------------------------------------
  110.   # ● 判断对应的键是否重复被按下
  111.   #--------------------------------------------------------------------------
  112.   def self.repeat?(key)
  113.     key = get_key(key) unless key.is_a?(Numeric) or key.is_a?(Array)
  114.     return key.any?{|k| repeat?(k)} if key.is_a?(Array)
  115.     Flags[key] ? (Flags[key] == 0 or Flags[key] >= REPEAT_DELAY and
  116.     (Flags[key] - REPEAT_DELAY) % REPEAT_SPEED == 0) : press?(key)
  117.   end
  118.   #--------------------------------------------------------------------------
  119.   # ● 键盘状态判断
  120.   #--------------------------------------------------------------------------
  121.   def self.lock?(key);    GetKeyState.call(key) & 1 == 1;           end
  122.   def self.caps_lock?;    lock?(CAPS_LOCK);                         end
  123.   def self.num_lock?;     lock?(NUM_LOCK);                          end
  124.   def self.scroll_lock?;  lock?(SCROLL_LOCK);                       end
  125.   #--------------------------------------------------------------------------
  126.   # ● 修饰键判断
  127.   #--------------------------------------------------------------------------
  128.   def self.shift?;        press?([SHIFT_KEY, L_SHIFT, R_SHIFT]);    end
  129.   def self.ctrl?;         press?([CONTROL_KEY, L_CTRL, R_CTRL]);    end
  130.   def self.alt?;          press?([ALT_KEY, L_ALT, R_ALT]);          end
  131.   def self.win?;          press?([L_WIN, R_WIN]);                   end
  132.   #--------------------------------------------------------------------------
  133.   # ● 当前按下的键名
  134.   #--------------------------------------------------------------------------
  135.   def self.key_code
  136.     a = ANY_KEY.select{|key| repeat?(key)}
  137.     a.empty? ? 0 : a[0]
  138.   end
  139.   #--------------------------------------------------------------------------
  140.   # ● 当前输入的字符
  141.   #--------------------------------------------------------------------------
  142.   def self.type_char
  143.     @keychar ||= key2char(key_code, shift?, caps_lock?, num_lock?)
  144.   end
  145.   #--------------------------------------------------------------------------
  146.   # ● 打字中判定
  147.   #--------------------------------------------------------------------------
  148.   def self.typing?
  149.     not type_char.empty?
  150.   end
  151.   #--------------------------------------------------------------------------
  152.   # ● 根据字符或符号取得键名
  153.   #--------------------------------------------------------------------------
  154.   def self.get_key(key)
  155.     if key.is_a?(Symbol)
  156.       const_get(key) rescue NONE
  157.     elsif key.is_a?(String)
  158.       char2key(key)
  159.     end
  160.   end
  161.   #--------------------------------------------------------------------------
  162.   # ● 将按键转化为字符
  163.   #--------------------------------------------------------------------------
  164.   def self.key2char(code, shift = false, caps = false, num = true)
  165.     case code
  166.     when NONE
  167.       ""
  168.     when BACKSPACE..ENTER, ESCAPE, SPACE
  169.       code.chr
  170.     when D0..D9
  171.       shift ? ")!@#\$%^&*("[code - D0].chr : code.chr
  172.     when A..Z
  173.       shift ^ caps ? code.chr : (code + 32).chr
  174.     when NUM0..NUM9
  175.       num ? (code - 48).chr : ""
  176.     when MULTIPLY..DIVIDE
  177.       (num || code != DECIMAL) ? "*+,-./"[code - 106].chr : ""
  178.     when SEMICOLON..TILDE
  179.       ";:=+,<-_.>/?`~"[(code - SEMICOLON << 1) + (shift ? 1 : 0)].chr
  180.     when L_BRACE..QUOTE
  181.       "[{\\|]}\'\""[(code - L_BRACE << 1) + (shift ? 1 : 0)].chr
  182.     else
  183.       ""
  184.     end
  185.   end
  186.   #--------------------------------------------------------------------------
  187.   # ● 将字符转化为按键
  188.   #--------------------------------------------------------------------------
  189.   def self.char2key(char)
  190.     return NONE if char.empty?
  191.     case char[0]
  192.     when 8..13, 27, 32, 48..57, 65..90
  193.       char[0]
  194.     when 97..122
  195.       char[0] - 32
  196.     else
  197.       pindex = ")!@#\$%^&*(".index(char[0])
  198.       return D0 + pindex if pindex
  199.       pindex = ";:=+,<-_.>/?`~".index(char[0])
  200.       return SEMICOLON + (pindex >> 1) if pindex
  201.       pindex = "[{\\|]}\'\"".index(char[0])
  202.       return L_BRACE + (pindex >> 1) if pindex
  203.       NONE
  204.     end
  205.   end  
  206. end
  207.  
  208. #==============================================================================
  209. # ■ Input 模块的注入
  210. #==============================================================================
  211. module Input
  212.   unless method_defined?(:sailcat_kb_update)
  213.     alias sailcat_kb_update update
  214.     def update
  215.       sailcat_kb_update
  216.       Keyboard.update
  217.     end
  218.   end
  219. end
SailCat (小猫子·要开心一点) 共上站 24 次,发表过 11 篇文章 上 次 在: [2006年01月28日11:41:18 星期六] 从 [162.105.120.91] 到本站一游。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

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

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

GMT+8, 2024-11-25 14:04

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表