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

问题描述:

我已经创建了一个非常简单的游戏,用于模拟在Gamemaker Studio中“滚球迷宫”式游戏中滚动球的非常简单的游戏。它仅由玩家对象和无法穿过的墙壁组成。玩家对象在简单的物理模拟中移动不正确GMS

玩家对象有一个垂直速度和一个水平速度,当你按下移动键时增加/减少,然后它的位置每步移动一次这些速度(直到碰到墙壁)。当没有按钮被按下时,我还添加了基本减速。

它主要工作,但我有一个非常具体的错误。当非常迅速和+正(唐氏; 小号dWASD而言)移动沿着x或y轴,如果我在相反的方向上提供的输入(交换到W¯¯当拿着S等),当非常接近墙壁时,玩家对象立即眨眼,直到它可以沿着相反的方向行进。

应该发生什么事情是物体在开始减速前不可避免地碰撞到它正在注意的那堵墙,这是在相反的情况下做同样的事情时会发生的事情;即沿着Y轴在负极方向上快速移动,方法是保持W然后切换到S就在撞击墙壁之前。

我并不确定,但我非常肯定它发生在物体朝向墙壁快速向+正方向行进时,它没有足够的时间减速到停止之前通过向相反的方向施加力来击打墙壁。

这里是不正确的行为的short clip

这里是正确的行为在其他方向上工作的short clip

这里是简单的步骤脚本:

// 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 
} 

这应该防止/帮助你的问题,因为你不能再一次提供多个方向的加速度,如果完全不起作用,可能是因为您递增轴运动进入墙,当你改变方向时,你正朝着这个方向加速,因为碰撞检查不再是问题,因为你在按键内部进行了碰撞检查,当你碰到墙时不应该因为这个原因而加速,只会让玩家反弹回来。 我有一个项目从几年前就做了你想做的事,生病试图找到它不起作用,让我知道。

+0

我实际上发现了这个问题,我需要为动量的每个方向做一个单独的变量,vNegSpd vPosSpd等,所以当检查碰撞时,我只使用该方向的变量。 问题是,当我说举行“D”和vspd超高,我交换了“A”,“A”分支将检查使用相同的超高vspd碰撞,并将触发“抓到最近墙“解决方案,将其一直捕捉到屏幕的另一侧。 – user3776749

+0

尽管打破输入可能是一个有用的补充,无论。虽然我可能只会把它分成两个(WA和SD),因为我想支持对角线移动。 – user3776749