坚持制作2D游戏运动引擎

时间:2011-05-31 17:17:20

标签: 2d

我正在为自上而下的2D游戏制作一个移动引擎,但我一直试图解决以下问题:

  • 玩家可以使用箭头键移动,这会使您在各自的方向上加速。有摩擦力,所以你在释放钥匙后停止移动,但不是立刻。
  • 当您按住两个垂直键时,在此45°方向上加速的速度与在一个轴上的速度相同
  • 有一个最高速度超过你无法加速行走,这也明显限制了你的最大步行速度。你可以被撞倒,然后超过这个速度。
  • 如果你移动速度超过最大值。如果你按相反的方向按键,你可以更快地减速

第一点的伪代码,没有摩擦:

gameTick(){

  tempX += LeftKeyHeld ? -1 : 0;
  tempX += RightKeyHeld ? 1 : 0;
  tempY += UpKeyHeld ? -1 : 0;
  tempY += DownKeyHeld ? 1 : 0;
  ratio = 0.71;

  if( |tempX| == |tempY| ) {
    tempX =tempX* ratio;
    tempY =tempY* ratio;
  }
  player.x += tempX;
  player.y += tempY;
}

我可以解决摩擦力(获得运动矢量的长度,通过摩擦减少它,以相同的x:y比率将其投射回来),然而,我无法绕过头部来完成maxSpeed。

我尝试了一种不允许玩家在超过maxSpeed时完全行走的解决方案,但这违反了第4点。此外,它还有令人讨厌的副作用,当你向MaxSpeed移动到左边时,开始按下,运动方向没有,或几乎没有变化。

然后我开始考虑使用矢量的众多产品,差异和其他东西,但我大多不能再遵循它或遇到早期问题。

总而言之,有人可以解释一个满足上述所有要点的系统,或指向一篇解释如何实现这样的系统的文章吗?不要担心建议复杂的事情,我可以在一段时间内掌握甚至是困难的概念。

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

很抱歉,不要让你考虑这一天超过一天,但我设法解决了它,并不是两行代码。 (虽然仍然感谢每个人的想法)

因为我懒惰而且累了,除了以下两种方法外,我不会将其改为伪代码:

updateGame(){
  player.walk();
  player.move();
}
player.move(){
  player.x += player.speedX
  player.y += player.speedY
}  

代码(java):

public void walk() {
    float tempX = 0;
    float tempY = 0;
    float accelX;
    float accelY;
    float nextSpeedX;
    float nextSpeedY;
    float nextSpeed;
    float speed;
    tempX += walkLeft ? -1 : 0;
    tempX += walkRight ? 1 : 0;
    tempY += walkUp ? -1 : 0;
    tempY += walkDown ? 1 : 0;

    if (Math.abs(tempX) == Math.abs(tempY)) {
        tempX = (float) tempX * rat;
        tempY = (float) tempY * rat;
    }

    accelX = tempX * (float) runSpeed;
    accelY = tempY * (float) runSpeed;
    speed = (float) Math.sqrt(speedX * speedX + speedY * speedY);
    nextSpeedX = speedX + accelX;
    nextSpeedY = speedY + accelY;
    nextSpeed = (float) Math.sqrt(nextSpeedX * nextSpeedX + nextSpeedY * nextSpeedY);

    if (nextSpeed > maxSpeed) { //can't accelerate by running
        if (nextSpeed > speed) {  //wants to accelerate
            if (speed > maxSpeed) {  //the current speed is larger than maximum.
                float diff = (float)(speed / nextSpeed);
                float greenX = nextSpeedX*diff;
                float greenY = nextSpeedY*diff;
                accelX = greenX-speedX;
                accelY = greenY-speedY;
            } else { //speed <= maxspeed
                float diff = (float)(maxSpeed / nextSpeed);
                float greenX = nextSpeedX*diff;
                float greenY = nextSpeedY*diff;
                accelX = greenX-speedX;
                accelY = greenY-speedY;
            }
        } else { //wants to slow! allow it!
            //acceleration doesn't need to be changed
        }
    } else { //no problem, allow it!
        //acceleration doesn't need to be changed
    }
    speedX += accelX;
    speedY += accelY;
}

可能更短,可以更优化,但它的工作原理。我希望这将有助于将来偶然发现这个问题的任何人。

答案 1 :(得分:0)

添加到底部:

 If (|tempX|>maxSpeed)
   tempX=maxSpeed*sign(tempX);

 If (|tempY|>maxSpeed)
   tempY=maxSpeed*sign(tempX);

其中      int sign(x)      {          如果x <0           返回-1;      }

答案 2 :(得分:0)

除了位置之外,我建议将特定的速度与播放器相关联,并且仅在按下箭头键时检查速度与maxSpeed的对比。

如果速度DOES超过maxSpeed,但是正在按下来自对面的箭头键,那么你将当前速度保持在maxSpeed以上并简单地应用负加速度。