本週的目標是要讓橫向卷軸中的角色可以左右移動及跳躍, 在沒有碰到場景物件時自由落體, 碰到牆壁時被阻擋在牆的一側。
在限定所有物件的形狀都是沒有對座標軸旋轉的長方體時,可以使用簡單的AABB碰撞盒來檢測是否碰撞
private boolean isCollision(GameObj obj) {
if (this.left() > obj.right()) return false;
if (this.right() < obj.left()) return false;
if (this.top() > rect.bottom()) return false;
if (this.bottom() < rect.top()) return false;
return true;
}
為了讓角色有越掉越快, 需要讓角色的速度每次更新一個定值
private void update(){
velocity.offsetY(Gravity) // y 軸速度每次增加
offsetX = velocity(x);
offsetY = velocity(y)
}
為了讓角色合理的被場景物件阻擋, 要和場景物件判定碰撞, 並因碰撞結果設定角色位置和歸零速度
原本的AABB碰撞僅依據物件的位置獲得是否碰撞的結果,
因此需要知道物件的速度, 才會知道是與場景的哪個邊碰撞,
再者, 因為與頂點接觸時會判定為碰撞, 將使角色在行走在互相連接的下一塊底板時,
無法判定與下一塊地板的頂點碰撞是"牆壁或地板", 因此將角色碰撞後的位置設定在地板的上緣之上(1 單位)
actor.update();
for (int i = 0; i < gameObjects.size(); i++) {
GameObject obj = gameObjects.get(i);
if (actor.isCollision(obj)) {
actor.preMove();
actor.moveY();
if (actor.isCollision(obj)) { // 撞到 Y
actor.jumpReset();
if (actor.velocity().y() < 0) {
actor.setY(obj.collider().bottom() +1 );
actor.velocity().stopY();
} else if (actor.velocity().y() > 0) {
actor.setY(obj.collider().top() - actor.painter().height() -1);
actor.velocity().stopY();
}
actor.moveX();
}
if (actor.collider().bottom() == obj.collider().top() |
actor.collider().top() == obj.collider().bottom()) {
actor.moveX();
}
}
}