我正在为自上而下的2D游戏制作一个移动引擎,但我一直试图解决以下问题:
第一点的伪代码,没有摩擦:
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移动到左边时,开始按下,运动方向没有,或几乎没有变化。
然后我开始考虑使用矢量的众多产品,差异和其他东西,但我大多不能再遵循它或遇到早期问题。
总而言之,有人可以解释一个满足上述所有要点的系统,或指向一篇解释如何实现这样的系统的文章吗?不要担心建议复杂的事情,我可以在一段时间内掌握甚至是困难的概念。
感谢您的帮助!
答案 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以上并简单地应用负加速度。