You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GameMaker Studio 2多IF语句代码简化及循环疑问求助

问题描述

本人此前主要使用VBA编程,刚接触GameMaker Studio 2(语法类似Java/C)。现有一段实现玩家水平移动(含加速、摩擦)的代码,功能正常但IF语句冗余,希望获得简化方案及原理说明;同时不解为何repeat语句可行,while语句却无法正常工作。

当前代码

hsp = 0; // 水平速度
frctn = 0.8; // 摩擦系数
acclrtn = 0.7; // 加速度
walksp = 6; // 步行速度
dashsp = 12; // 冲刺速度

var _keyLeft = keyboard_check(vk_left); 
var _keyRight = keyboard_check(vk_right);
var _keyA = keyboard_check(ord("A"));
var _speed = walksp;

if(_keyLeft || _keyRight) // 若左或右键被按下
{
    if (_keyLeft && _keyRight) // 若左右键同时被按下
    {
        repeat(abs(hsp) > 1) // 当水平速度绝对值大于1时重复执行
        {
            hsp -= frctn * sign(hsp); // 水平速度减去摩擦值
        }
        if(abs(hsp) <= 1) hsp = 0; // 速度绝对值≤1时归0,避免微小负值
    }
    
    if (_keyA) _speed = dashsp; // 按住A键时切换为冲刺速度
    
    repeat(abs(hsp) < _speed) // 速度绝对值小于上限时重复加速
    {
        hsp += (_keyRight - _keyLeft)*acclrtn; // 按方向累加加速度
    }
    
    repeat(abs(hsp) > _speed) // 速度绝对值超过上限时重复减速
    {
        hsp -= (_keyRight - _keyLeft)*frctn; // 按方向减去摩擦值修正速度
    }

}

else // 若左右键都未按下
{
    repeat(abs(hsp) > 0.5) // 速度绝对值大于0.5时重复减速
    {
        hsp -= frctn * sign(hsp); // 水平速度减去摩擦值
    }
    if(abs(hsp) <= 0.5) hsp = 0; // 速度绝对值≤0.5时归0
}

补充说明

最初未加入物理效果的代码为基础方向控制逻辑(仅处理左右移动的输入映射)。

解决方案与解析

一、代码简化方案及原理

简化后的代码

hsp = 0; // 水平速度
frctn = 0.8; // 摩擦系数
acclrtn = 0.7; // 加速度
walksp = 6; // 步行速度上限
dashsp = 12; // 冲刺速度上限

var _keyLeft = keyboard_check(vk_left); 
var _keyRight = keyboard_check(vk_right);
var _keyA = keyboard_check(ord("A"));
var _input = _keyRight - _keyLeft; // 合成方向输入:右为1、左为-1、无输入为0
var _speedCap = _keyA ? dashsp : walksp; // 用三元运算符直接切换速度上限

// 左右同时按视为无有效输入
if (_keyLeft && _keyRight) _input = 0;

// 统一处理移动逻辑
if (_input != 0) {
    // 加速并限制速度在上下限内
    hsp += _input * acclrtn;
    hsp = clamp(hsp, -_speedCap, _speedCap);
} else {
    // 逐帧衰减速度,小于阈值直接归0
    hsp *= frctn;
    if (abs(hsp) <= 0.5) hsp = 0;
}

简化原理

  1. 方向输入合成:用_keyRight - _keyLeft直接得到-1/0/1的方向值,省去多次判断左右键组合的冗余IF
  2. 三元运算符替代分支:_keyA ? dashsp : walksp直接替换原单独的if(_keyA)赋值,精简单行分支逻辑
  3. 合并减速逻辑:原左右同时按的减速和无输入的减速本质都是无有效方向时的摩擦衰减,合并后减少代码重复;用hsp *= frctn逐帧衰减替代循环,更符合GMS2的帧更新机制
  4. 内置函数简化速度限制:用GMS2内置的clamp()函数直接将速度限制在上下限内,省去原加速/超速修正的循环判断

二、repeat与while的差异解析

原代码中repeat的实际作用

你写的repeat(abs(hsp) > 1)是错误用法:GMS2的repeat参数是循环次数,不是条件判断。这里abs(hsp) > 1会被转为布尔值:条件成立时为1(循环1次),不成立时为0(不循环)。所以你的代码实际只执行0或1次循环,并非持续到条件不满足。

while无法正常工作的原因

如果换成while(abs(hsp) > 1),会导致单帧无限循环:GMS2逻辑是逐帧执行,单帧内hsp的衰减会瞬间完成,若衰减逻辑无边界(比如摩擦系数设置问题)或条件判断有误差,可能导致循环无法退出,游戏直接卡住。

正确的做法

GMS2的移动逻辑应逐帧更新,不需要用循环模拟连续物理:每次只计算当前帧的速度变化(比如hsp *= frctn),而非一次性把速度衰减到0。这样既符合引擎帧更新机制,也避免了循环带来的性能问题和逻辑混乱。


内容的提问来源于stack exchange,提问作者Nathan surv genorpg20

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 03:55:19