我目前正在 Gamemaker 2 中制作 2D 平台游戏,并使用 GML 作为语言。
我的想法是在我的游戏中制作一个机制,让玩家能够在 360 度半径范围内用枪瞄准自己。我希望它是这样的,这样我就可以单击来射击枪,并且我会被推向与射击方向相反的方向。我不确定如何实际解决这个问题,因为我已经做了相当多的研究,但无法在我的代码中提出解决方案。
首先,我找到了一个公式来计算我最初瞄准的相反方向,这样我就能够弄清楚射击时需要推动玩家的方向,但现在我在移动目标时遇到了麻烦玩家朝该方向移动。我试过:
{ y += (sign(vSpd)*-100); }
只是为了测试一下它是否有效,但我不确定该往哪个方向让玩家顺利移动,而不是传送/跳跃到计算的点。请帮助任何信息或帮助,非常感谢!
注意我的对象是 oPlayer 和 oBlock,我的 Sprite 是 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;
}
创建活动:
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
步骤事件:
//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 Event: // 仅用于调试过程
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));
为了让推进运动更顺畅,您首先需要在创建事件中定义更多值:
recoilMax = 8; // Initial speed when shooting
recoilDeceleration = 0.8; // How quickly recoil decreases.
curRecoil = 0; // Tracks current recoil speed
recoilDir = 0; // Direction of recoil
然后在您的步数活动中您将更新您的推进力:
//propulsion mechanic
if shootKey {
weapon_propulsion(); // it may make more sense to apply recoil in here but I do not know what the contents of this function are.
// Apply Recoil
recoilDir = aimDir + 180; // Opposed direction of current aim direction
curRecoil = recoilMax; // Set recoil spd to initial value
};
最后,您将通过您的运动部分应用此功能,也在步骤事件中:
//Player Movement
var _horizKey = rightKey - leftKey;
hSpd = _horizKey * plrSpd;
vSpd = vSpd + pGrv;
// Apply recoil
hSpd += lengthdir_x(curRecoil, recoilDir);
vSpd += lengthdir_y(curRecoil, recoilDir);
curRecoil *= recoilDeceleration;
实际上,您希望对角色施加最大的初始力,然后让它随着时间的推移而减速。我们通过每帧仅移动有限数量的像素来实现这一点,然后随着“反冲”持续模拟空气阻力的时间越长,减少该数量。当然,随着时间的推移,您开始移动的速度和减速的具体值将会发生变化,因为上面提供的数字只是填充/示例。
除此之外,我的建议是考虑实现有限状态机。这需要一些设置和习惯,但从长远来看,它会为您省去很多麻烦。如果您有兴趣,游戏制作者网站上有一篇很好的文章,其中介绍了相关的基础知识。希望这可以帮助: https://gamemaker.io/en/tutorials/coffee-break-tutorials-finite-state-machines-gml