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)添加冲量,让玩家通过现有移动逻辑逐步移动,既能保留平滑感,又能兼容原有的碰撞检测。
具体修改步骤
添加
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); }修复重复的重力计算
原Step事件里的Movement区域重复添加了重力(vSpd += pGrv出现两次),删掉其中一个,避免重力翻倍影响手感://Player Movement var _horizKey = rightKey - leftKey; hSpd = _horizKey * plrSpd; vSpd = vSpd + pGrv; // 保留这一行 //jumping ... // 删掉下面这行重复的重力代码 // vSpd += pGrv;移除直接修改坐标的代码
删掉之前测试用的y += (sign(vSpd)*-100)这类代码,完全通过速度变量控制移动。
效果说明
修改后,射击时玩家会获得一个与瞄准方向相反的速度冲量,这个冲量会和玩家的移动、重力、碰撞逻辑结合,实现自然的平滑反推效果——比如空中射击会产生类似喷气背包的位移,地面射击会让玩家向后滑动。
内容的提问来源于stack exchange,提问作者BravestMedal
相关产品推荐
相关产品推荐

