原文:https://github.com/SilverTiger/lwjgl3-tutorial/wiki/Game-logic
译注:并没有逐字逐句翻译一切,只翻译了自己觉得有用的部分。另外此翻译仅供参考,请一切以原文为准。代码例子文件链接什么的都请去原链接查找。括号里的内容一般也是译注,供理解参考用。总目录传送门:http://blog.csdn.net/zoharwolf/article/details/49472857
现在我们已经知道怎样渲染游戏和怎样处理输入,但是怎样做游戏呢?本教程来我们来看看游戏逻辑。
之前提过时间间隔这个概念,即两次循环的时间差,更新实体的时候需要它。
为此需要些物理知识。物理中,力是质量乘以加速度(F = m*a),也就是加速度是力除以质量(a = F/m)。加速度即速度的变化率,a = dv/dt, 其中dt就是时间间隔。速度是时间经过时的位置变化率,v = dx/dt。
用这些定义,就可以更新位置了。时间间隔很明确了,速度可以用speed变量计算出来,这个变量表示物体每秒的移动距离。还需要一个单位向量表示移动方向。这样就可以用以下伪代码计算速度了。
// You shouldn't normalize a null vectorif (direction.length() != 0) {
direction = direction.normalize();
}
velocity = direction * speed;
用欧拉积分可以更新实体的位置和速度,伪代码如下:
position += velocity * delta;
velocity += (force / mass) * delta;
例子里没有加速度,所以实体的更新方法如下:
public void update(float delta) {
previousPosition = new Vector2f(position.x, position.y);
if (direction.length() != 0) {
direction = direction.normalize();
}
Vector2f velocity = direction.scale(speed);
position = position.add(velocity.scale(delta));
}
第一行可有可无,当你需要用插值时有用。
有许多算法可以检测碰撞,比如轴分离定理(Separating Axis Theorem ,SAT)或包围盒算法(Axis-Aligned Bounding Boxes ,AABB)。对于简单的程序来说,AABB就够了,更复杂的需求可以使用SAT等更复杂的算法。
定义一个包围盒很容易,用两点创建一个矩形,这两点被称为最小和最大向量。在2D的程序里,你可以认为一个实体的左下角是最小向量,右上角是最大向量。
有了这些点,就可以检查两个AABB的碰撞了。
boolean intersects(AABB first, AABB second) {
if (first.max.x < second.min.x)
return false;
if (first.max.y < second.min.y)
return false;
if (first.min.x > second.max.x)
return false;
if (first.min.y > second.max.y)
return false;
// All tests failed, we have a intersectionreturn true;
}
另一个使用AABB的方法就是定义一个中心点变量,然后用矩形的半宽。
boolean intersects(AABB first, AABB second) {
if (Math.abs(first.center.x - second.center.x) > first.halfWidth.x + second.halfWidth.x)
return false;
if (Math.abs(first.center.y - second.center.y) > first.halfWidth.y + second.halfWidth.y)
return false;
// All tests failed, we have a intersectionreturn true;
}
哪个适合你的程序就用哪个。当然你也需要根据新的位置坐标来更新你的AABB。
检测碰撞后,需要调整实体位置。假设你有一个原点在左下角的实体,可以用以下伪代码调整位置。
if (entity.collided(otherEntity) == COLLISION_TOP_SIDE)
entity.position.y = otherEntity.y + otherEntity.height;
if (entity.collided(otherEntity) == COLLISION_BOTTOM_SIDE)
entity.position.y = otherEntity.y - entity.height;
if (entity.collided(otherEntity) == COLLISION_LEFT_SIDE)
entity.position.x = otherEntity.x - entity.width;
if (entity.collided(otherEntity) == COLLISION_RIGHT_SIDE)
entity.position.x = otherEntity.x + otherEntity.width;
如果不这样做,在下一个循环中还会再有碰撞,实体将一直缓缓地从另一个实体身上穿过去。
既然这已经是最后一篇教程了,那么接下来就看你了。如果你想做游戏,不妨先试着做些简单的游戏,比如俄罗斯方块或者太空入侵者。
如果想学更多LWJGL3的东西,你应该看看DEMO(这个DEMO其实是一个PONG游戏)。
你可能也想要用像libGDX或者jMonkeyEngine之类的类库来做游戏,它们将帮你完成样板代码。
关于碰撞检测,如果你不想手动实现你自己的物理引擎,你也可以看看JBox2D或JBullet。
但是当然,你也可以从零开始去搞自己的小游戏。
想要怎么做,随你,祝你开心,感谢阅读本教程。