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

GameMaker 2中2D平台玩家射击反推平滑移动实现求助

解决GameMaker 2射击反推的平滑移动问题

我用GameMaker 2和GML制作2D平台游戏,想要实现360度瞄准枪械+射击时向反方向平滑推进的机制。已经算出射击反方向,但测试时玩家是瞬移而非平滑移动,试过{ y += (sign(vSpd)*-100); }能生效但没有平滑效果。现有对象:oPlayer、oBlock;精灵:sPlayer、sBlock、sAimHelp。

现有代码

函数脚本

function draw_aim_help()
{
    //Drawing Sprite
        //Spacing of the sprite
            var _XOffset = lengthdir_x( weaponOffsetDist, aimDir );
            var _YOffset = lengthdir_y( weaponOffsetDist, aimDir );
    
        //Flipping the sprite
            var _weaponYscl = 1; // direction of sprite < or >
                // edit out if needed
            /*if aimDir > 90 and aimDir < 270
                {
                    _weaponYscl = -1;
                }
            */
        draw_sprite_ext( sAimHelp, 0, x + _XOffset, centerY + _YOffset, 1, _weaponYscl, aimDir, c_white, 1)
        depth = -bbox_bottom;
    
};

function get_aim_direction()
{
    if aimDir >= 90 and aimDir < 270
        {
            dirCheck = -1;
        }  
    else dirCheck = 1;
        
}

Create事件

hSpd = 0;
vSpd = 0;
pGrv = 0.3;
plrSpd = 4;
grounded = 0;
vSpd_max = 15;
jump = -10;
jumpMod = 1.5;
//variables for aim
#region
    weaponOffsetDist = 128;
    centerYOffset = 0;
    centerY = y + centerYOffset;
    aimDir = 0;
    dirCheck = 0;
#endregion

Step事件

//Movement Inputs
#region
leftKey = keyboard_check( ord("A")); 
rightKey = keyboard_check( ord("D"));
jumpKey = keyboard_check_pressed(vk_space);
jumpKeyHeld = keyboard_check(vk_space);

//Weapon Inputs
swapKeyPos = keyboard_check_pressed( ord("W")); 
swapKeyNeg = keyboard_check_pressed( ord("S"));
shootKey = mouse_check_button_pressed( mb_left );

//get aiming direction
get_aim_direction()
#endregion


    
    //propulsion mechanic
    if shootKey
        {
            weapon_propulsion();
        };
//Movement
#region
    //Player Movement
        var _horizKey = rightKey - leftKey;
        hSpd = _horizKey * plrSpd;
        vSpd = vSpd + pGrv;
    //jumping
        if jumpKey = 1 and grounded = true
            {
                vSpd += jump;
            }
            
        if vSpd < 0 and (!jumpKeyHeld)
            {
                vSpd = max(vSpd, jump / jumpMod)
            }
            
        //Gravity
            vSpd += pGrv;
            
        //Max speeds
            vSpd = clamp(vSpd, -vSpd_max, vSpd_max);
            
        
    //Horizontal movement
        if (place_meeting( x+hSpd, y, oBlock ))
        {
            while (!place_meeting( x+sign( hSpd ), y, oBlock ))
                {
                    x = x + sign( hSpd );
                }
                hSpd = 0;
        }
        
    //Vertical Movement
        if (place_meeting( x, y+vSpd, oBlock))
        {
            while (!place_meeting( x, y+sign(vSpd), oBlock))
            {
                y = y + sign(vSpd);
            }
            vSpd = 0;
            grounded = true;
        }
        else { grounded = false; };
        x += hSpd;
        y += vSpd;
#endregion

//Aiming
    centerY = y + centerYOffset;
    aimDir = round(point_direction( x, centerY, mouse_x, mouse_y));
    aimDirInv = ( aimDir + 180 ) mod 360;
    pushVar = degtorad(aimDirInv);

Draw事件(调试用)

draw_self();
draw_aim_help();
draw_text( x, y, string(aimDir));
draw_text( x, y+20, string(aimDirInv));
draw_text( x, y+40, string(pushVar));
draw_text( x, y+60, string(dirCheck));

平滑反推的解决方案

核心思路

直接修改x/y坐标会导致瞬移,正确做法是给玩家的速度变量(hSpd/vSpd)添加冲量,让玩家通过现有移动逻辑逐步移动,既能保留平滑感,又能兼容原有的碰撞检测。

具体修改步骤

  1. 添加weapon_propulsion函数
    在函数脚本里补充这个缺失的函数,计算反方向的速度分量并叠加到玩家速度上:

    function weapon_propulsion() {
        // 推进力度,可根据手感调整数值
        var _pushForce = 8;
        // 计算反方向的水平/垂直速度分量
        var _pushX = lengthdir_x(_pushForce, aimDirInv);
        var _pushY = lengthdir_y(_pushForce, aimDirInv);
        // 将冲量叠加到玩家速度
        hSpd += _pushX;
        vSpd += _pushY;
        // 可选:限制最大速度,防止推进后速度失控
        hSpd = clamp(hSpd, -plrSpd * 1.5, plrSpd * 1.5);
        vSpd = clamp(vSpd, -vSpd_max * 1.2, vSpd_max * 1.2);
    }
    
  2. 修复重复的重力计算
    原Step事件里的Movement区域重复添加了重力(vSpd += pGrv出现两次),删掉其中一个,避免重力翻倍影响手感:

    //Player Movement
        var _horizKey = rightKey - leftKey;
        hSpd = _horizKey * plrSpd;
        vSpd = vSpd + pGrv; // 保留这一行
    //jumping
        ...
        // 删掉下面这行重复的重力代码
        // vSpd += pGrv;
    
  3. 移除直接修改坐标的代码
    删掉之前测试用的y += (sign(vSpd)*-100)这类代码,完全通过速度变量控制移动。

效果说明

修改后,射击时玩家会获得一个与瞄准方向相反的速度冲量,这个冲量会和玩家的移动、重力、碰撞逻辑结合,实现自然的平滑反推效果——比如空中射击会产生类似喷气背包的位移,地面射击会让玩家向后滑动。

内容的提问来源于stack exchange,提问作者BravestMedal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 13:22:33