Make Your Game Input Robust

本文探讨游戏开发中输入管理的常见问题,包括输入更新频率、按键状态检测、按键时间记录及click事件实现等,旨在帮助开发者设计更稳健的输入管理系统。

Make Your Game Input Robust

 仅供个人学习使用,请勿转载,勿用于任何商业用途。

    如果你读过 之前 那篇关于InputManager的文章,那么非常抱歉,最近发现那样的设计是有缺陷的。我又一次被隐藏的复杂性打败了-_-#。

    问题一,以什么频率进行输入更新。对于XNA framework来说,每次程序主循环调用Update时,都会刷新KeyboardState和MouseState,通过这2个对象,可以查询某个按键是否处于pressed或者released状态。那么是否每次update时同时更新IM的状态呢? 显然不行。通常来说,人的输入速度极限是相对固定的,比如每秒击键n次,并且只可能在n附近的范围内小幅波动。而Update则不一样,可能每秒更新30次,60次或者更多。之前的文章讨论过合适的更新频率,不再重复。这里要提醒的是过高和过低的更新频率都将会让输入变的不精确。过低的更新频率导致的输入失真是显而易见的。但为什么过高也不行呢?当然,这里IM更新的最高频率只能小于等于主循环update的频率。设想用户正在通过敲击键盘输入文字,假设用户的极限击键速度是0.05秒,也就是至少有0.05秒按键将处于pressed的状态。好了,如果你0.01秒更新一次IM状态,那么在0.05秒内将触发5次KeyPressed事件,结果是用户敲击一个按键,就出现5个相同的字母。当然,可以通过取巧的方法来解决这个问题:只通过KeyDown事件完成输入,如果要重复输入同一文字,则必须反复击键而不能通过一直按下按键来完成——虽然不完美,但也算是可以接受的。

    问题二:IM是否该提供IsKeyDown,IsKeyUp,IsMouseDown,IsMouseUp这四个函数。对问题1的结论稍加推测,你就可以发现答案是否定的。这里明确一下Down和Up的定义,它们描述的都是按键状态改变*瞬间*的状态。也就是说t1时刻a处于released状态,t2时刻a被按下,此时a处于down状态,同时也处于pressed状态,t2之后的任何时刻,即使a仍处于pressed状态,但都不满足down状态。当然,由于采样可能存在的误差,不可能精确的恰好在t2时检测到keydown状态,通常是在t2之后某个很短的时间内才检测到,不过这并不会有太大影响。 有了这个定义,就可以发现,只有在IM的更新频率和主循环的更新频率相同时,这4个函数才有可能正确工作。假设2者更新频率不同,t1时刻,Update和IM同时进行更新,IM发现键a刚好被按下,于是标记为keydown和pressed状态。Update中的逻辑代码通过IsKeyDown查询按键a,获得了keydown和pressed信息;t2时刻,Update再一次被调用,但IM的更新间隔还没有到,这时逻辑代码再次检测a键的状态,将会再次获得keydown信息,而这次的消息显然是错误的。当然,如果你的主循环和IM都以30fps的速率更新,则不会有这样的问题,不过,为了满足更通用的情况,应该完全删除这4个函数,down和up消息都只能通过事件获得,而无法查询。
  
    问题三:IM是否该记录按键被按下的时间。从实践上来看,需要查询按键被按下时间长度的情景是非常少的。不过这并不能成为是否需要这个储存这个值的主要因素。如果继续对问题二的讨论,你就会发现IM所记录的按键时间同样是带有误导性的,只有在IM的更新频率和主循环的更新频率相同时正确。所以同样同样应该删除这个变量,让逻辑代码自己实现是否记录按键所按下的时间。

    问题四:IM是否应该实现click和doubleclick事件。这是我常常看到人问的问题。在IM中添加这2个事件是非常容易的,问题在于当click事件发生以后,谁应该获得这个消息呢?我是这样定义click事件的:当鼠标在某个对象的屏幕范围内,很短时间里相继触发了同一按键的Down和Up事件,则称为一次click。从定义可以看出,问题的关键在于click依赖于某一个IM之外的对象,我们不能仅凭IM在很短时间内探测到的连续Down,Up事件,就触发一次click。很有可能是在a物体的屏幕范围内发生的down,然后在b物体的范围内发生了up,这时无论a还是b都不应该获得click事件。因此,click应该属于更高层的类中,不应该出现在IM里。

 

 

 

<think>好的,我现在需要解决用户关于Trajectory Rollout规划器中设置meter_scoring参数的问题。用户提到,当参数未设置时,系统提示需要将其设为true以确保对成本地图分辨率变化的鲁棒性。首先,我得回忆一下这个参数的作用。根据引用[1],meter_scoring未设置可能导致规划器在成本地图分辨率变化时表现不稳定。设置这个参数为true可以让评分基于实际距离(米)而非网格单位,这样即使分辨率调整,评分标准也能保持一致,提高系统的适应性。接下来,用户需要知道具体的设置方法。 我应该分步骤说明如何通过ROS的参数服务器来设置这个参数。通常,这类参数会在本地规划器的配置文件中,比如trajectory_planner.yaml。用户需要编辑这个文件,添加meter_scoring: true,并确保在启动时加载该配置。此外,可能还需要在启动文件中或命令行中传递参数,比如使用rosrun或launch文件中的<param>标签。另外,引用[2]提到了TrajectoryPlannerROS类的初始化过程,其中initialize函数可能负责读取这些参数。因此,正确设置后,在初始化规划器时,参数会被正确加载,从而影响computeVelocityCommands等核心函数的行为,确保路径评分基于米制单位。最后,需要提醒用户验证设置是否生效,可以通过查看ROS日志或使用rosparam检查参数值。这样用户能确认更改已正确应用,避免配置错误。同时,可能还需要注意其他相关参数的影响,确保整体配置的一致性。</think>关于如何设置Trajectory Rollout规划器的meter_scoring参数以应对costmap分辨率变化,请按以下步骤操作: ### 解决方案 1. **参数作用** meter_scoring参数用于将路径评分的距离单位从"网格单位"切换为"米",确保路径评分不受costmap分辨率影响。当分辨率变化时,基于米制的评分能保持参数设置的鲁棒性[^1]。 2. **设置方式** ```yaml # 在本地规划器的YAML配置文件中添加 TrajectoryPlannerROS: meter_scoring: true # 默认false resolution: 0.1 # 需与costmap实际分辨率一致 ``` 3. **验证方法** - 通过ROS参数服务器检查: ```bash rosparam get /move_base/TrajectoryPlannerROS/meter_scoring ``` - 在规划器初始化日志中确认参数加载状态[^2] $$ \text{评分公式} \rightarrow score = \begin{cases} distance_{grid} \times resolution & \text{if meter\_scoring=false} \\ distance_{meter} & \text{if meter\_scoring=true} \end{cases} $$ ### 注意事项 - 需同时更新`pdist_scale`、`gdist_scale`等距离权重参数的单位量纲 - 若使用动态调整分辨率功能,必须保持meter_scoring=true状态 - 参数修改后需重启规划器节点才能生效
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值