Tôi đang làm việc trên một bản sao Mario dựa trên gạch.
Điều này hoạt động tốt khi đi bộ và rơi. Nhưng khi người chơi nhảy gần một bức tường và đi về phía bên phải trong không trung, thì người chơi bị mắc kẹt trên tường. Sprite của người chơi lại rơi khi người chơi nhả phím.
Việc thiết lập khá dễ dàng và tôi không thể tìm thấy vấn đề. Bản đồ được xây dựng dưới dạng một mảng 2D với các khối bản đồ. Một khối có thể rắn hoặc không. Người chơi không thể di chuyển các vật thể rắn, duh ..
Trong vòng lặp trò chơi:
- vị trí của người chơi được cập nhật (trọng lực, chuyển động ect.)
- kiểm tra bản đồ về va chạm. Khi tìm thấy xung đột trong Y, thì vị trí của người chơi sẽ được cập nhật để nó ở trên hoặc bên dưới khối (tùy theo hướng của người chơi), sau đó hộp va chạm sẽ được cập nhật với vị trí mới. Sau đó, quá trình tương tự cho X.
- Hộp va chạm được cập nhật đến vị trí mới (một vị trí miễn phí). Hộp được điều chỉnh sao cho cao hơn một chút để đưa khối bên dưới người chơi kiểm tra xem anh ta đã hạ cánh chưa. Điều này là để thay đổi trạng thái của người chơi, từ bay sprite sang nhàn rỗi.
Tôi cũng đã thử chuyển đổi kiểm tra X và Y để người chơi được di chuyển trên dòng X. Sau đó khi người chơi di chuyển, chuyển động sẽ rất chậm. Khi tôi ấn và nhả nút để di chuyển, thì người chơi sẽ di chuyển nhanh hơn nhưng ở trong mâm cặp. Rất nhanh
Có ai nhìn thấy lỗi hoặc có thể cho tôi một thuật toán va chạm tốt hơn cho điều này?
CẬP NHẬT (không cập nhật mã)
Tôi đã thay đổi phương thức kiểm tra x và y và thực hiện biến isonland. Vì vậy, khi đi bộ và nhảy vào tường hoạt động hoàn hảo. Chỉ bây giờ, khi người chơi nhảy Mario được đặt trở lại khi hạ cánh. Điều này là do phương pháp kiểm tra X đi trước và điều chỉnh vị trí của Mario.
Làm thế nào tôi có thể giải quyết điều đó?
Phương pháp cập nhật lớp bản đồ:
public void update(int timeElapsed) {
//update entities
for(Entity entity : _mapEntities) {
entity.update(timeElapsed);
}
//update objects
for(MapObject mapObt : _mapObjects) {
mapObt.update(timeElapsed);
}
//check for collisions
checkMapCollision();
}
Phương thức cập nhật thực thể (trừu tượng):
public void update(int timeElapsed) {
_velocity = new Vector2d(0.0F, 0.0F);
//add gravity
_velocity.y = Map._GRAVITY_PER_SEC * timeElapsed;
}
Mario (mở rộng thực thể) cập nhật methos:
@Override
public void update(int timeElapsed) {
super.update(timeElapsed);
if(_state == STATES.IDLE) {
} else if(_isMoving) {
_marioSmallWalk.update(timeElapsed);
}
if(_state == STATES.JUMPING) {
setVelocityY(getVelocity().y + _jumpSpeed);
_jumpSpeed += _JUMP_DECREASE * timeElapsed;
//falling?
if(getVelocity().y > 0) {
setState(STATES.FALLING);
}
}
if(_isMoving) {
double walkSpd = (_WALK_SPEED_SEC * timeElapsed);
if(getFacing() == FACING.LEFT) {
walkSpd = -walkSpd;
}
setVelocityX(getVelocity().x + walkSpd);
}
//falling?
if(getVelocity().y > (Map._GRAVITY_PER_SEC * timeElapsed) + 1.0F) {
setState(STATES.FALLING);
}
setPosition((int)(getX() + getVelocity().x), (int)(getY() + getVelocity().y));
}
Phương pháp lớp MapMapCollision:
public void checkMapCollision() {
//enteties move so check it
for(Entity entity : _mapEntities) {
//get the corners
Rectangle bounds = entity.getBounds();
Block[] corners = getCornerBlocks(bounds);
Vector2d dir = entity.getDirection();
//moving down
if(dir.y > 0) {
if(corners[2].isSolid() || corners[3].isSolid()) {
Rectangle blkBounds = null;
if(corners[2].isSolid()) {
blkBounds = corners[2].getBounds();
} else {
blkBounds = corners[3].getBounds();
}
entity.setPositionY(blkBounds.y);
}
} else {
if(corners[0].isSolid() || corners[1].isSolid()) {
Rectangle blkBounds = null;
if(corners[0].isSolid()) {
blkBounds = corners[0].getBounds();
} else {
blkBounds = corners[1].getBounds();
}
entity.setPositionY(blkBounds.y + blkBounds.height + bounds.height);
}
}
bounds = entity.getBounds();
corners = getCornerBlocks(bounds);
//moving to the right
if(dir.x > 0) {
if(corners[1].isSolid() || corners[3].isSolid()) {
Rectangle blkBounds;
if(corners[1].isSolid()) {
blkBounds = corners[1].getBounds();
} else {
blkBounds = corners[3].getBounds();
}
entity.setPositionX(blkBounds.x - (bounds.width-entity.getCurrentSprite().getOffsetX())-1);
}
} else {
if(corners[0].isSolid() || corners[2].isSolid()) {
Rectangle blkBounds;
if(corners[0].isSolid()) {
blkBounds = corners[0].getBounds();
} else {
blkBounds = corners[2].getBounds();
}
entity.setPositionX(blkBounds.x + blkBounds.width + (bounds.width/2));
}
}
bounds = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height+1);
corners = getCornerBlocks(bounds);
//moving down
if(dir.y > 0) {
if(corners[2].isSolid() || corners[3].isSolid()) {
Rectangle blkBounds = null;
if(corners[2].isSolid()) {
blkBounds = corners[2].getBounds();
} else {
blkBounds = corners[3].getBounds();
}
entity.landed();
System.out.println("landed");
}
}
}
}
entity.setPositionX()
hoặc entity.setPositionY()
được gọi sau khi kiểm tra va chạm. Khi tôi đi dựa vào tường mà không nhảy thì người chơi bị đẩy lùi chính xác.