玩家对象在简单物理模拟 GMS 中移动不正确



我创建了一个非常简单的游戏,用于在Gamemaker Studio的"球迷宫"风格的游戏中模拟滚球。它仅由玩家对象和无法移动的墙壁组成。

玩家对象具有垂直速度和 horiz 速度,当您按下移动键时,它们会增加/减少,然后它的位置每一步移动一次这些速度(直到它撞到墙上)。我还添加了未按下按钮时的基本减速。

它主要有效,但我有一个非常具体的错误。当移动非常快速和+积极(;WASD而言的 S 或D)沿 x 或 y 轴,如果我在非常靠近墙壁时以相反的方向提供输入(按住S等时交换为W),则玩家对象会立即向后闪烁,尽可能向相反的方向前进。

应该发生的事情是物体应该在不可避免地撞到它正在向的墙壁之前开始减速,这就是反向做同样事情时发生的情况; 即通过按住W然后在撞墙之前切换到S沿 y 轴在负方向上快速移动。

我不确定,但我很确定当物体以+正方向足够快的速度向墙壁移动时,它就发生了,它没有足够的时间减速到停止,然后通过增加相反方向的力来撞击墙壁。

这是不正确行为的简短剪辑

这是在另一个方向上工作的正确行为的简短剪辑。

这是简单的步骤脚本:

// determine which input keys are being pressed and 
// increment/decrement vspd and hspd respectively
if (vspd < 0 || keyboard_check(ord('W'))){
if place_meeting(x, y+vspd, block_obj)
{
// pixel-perfect collision resolution
while(!place_meeting(x, y-1, block_obj))
{
y -= 1;
}
vspd = 0;
}
else if keyboard_check(ord('W'))
{
if(!place_meeting(x, y-1, block_obj))
vspd -= 2;
}
else
{
if(vspd < -2) 
{
vspd += 1;
}
else
{ 
vspd = 0;
}
}
} 
if (vspd > 0 || keyboard_check(ord('S'))){
if place_meeting(x, y+vspd, block_obj)
{
// pixel-perfect collision resolution
while(!place_meeting(x, y+1, block_obj))
{
y += 1;
}
vspd = 0;
}
else if keyboard_check(ord('S'))
{
if(!place_meeting(x, y+1, block_obj))
vspd += 2;
}
else
{
if(vspd > 2)
{
vspd -= 1;
}
else
{
vspd = 0;
}
}
}
if (hspd < 0 || keyboard_check(ord('A'))){
if place_meeting(x+hspd, y, block_obj)
{
// pixel-perfect collision resolution
while(!place_meeting(x-1, y, block_obj))
{
x -= 1;
}
hspd = 0;
}
else if keyboard_check(ord('A'))
{
if(!place_meeting(x-1, y, block_obj))
hspd -= 2;
}
else
{
if(hspd < -2) 
{
hspd += 1;
}
else
{
hspd = 0;
}
}
}
if (hspd > 0 || keyboard_check(ord('D'))){
if place_meeting(x+hspd, y, block_obj)
{
// pixel-perfect collision resolution
while(!place_meeting(x+1, y, block_obj))
{
x += 1;
}
hspd = 0;
}
else if keyboard_check(ord('D'))
{
if(!place_meeting(x+1, y, block_obj))
hspd += 2;
}
else
{
if(hspd > 2)
{
hspd -= 1;
}
else
{
hspd = 0;
}
}
}
x += hspd;
y += vspd;

我似乎找不到导致问题的步骤代码部分。

如果我这样做,我会通过使用else if语句使每个控件彼此分开。伪代码,例如:

if (w) {
//code
} else if (a) {
//code
} else if (s) {
//code
} else if (d) {
//code
}

这应该可以防止/帮助您解决问题,因为您无法再同时在多个方向上提供加速,如果这不能完全起作用,那可能是因为您正在将轴运动增加到墙中,并且当您改变方向时,您正在加速朝那个方向加速,您只是因为碰撞检查不再是问题,因为您在按键内部进行了碰撞检查, 当你撞到墙上时,你不应该因为这个原因允许加速,只能将玩家弹回来。 我几年前有一个项目,可以做你想做的事情,我试着找到它不起作用,让我知道。

最新更新