fix boss tank cross brick

This commit is contained in:
jakciehan
2026-06-07 22:08:00 +08:00
parent c3a4aa8f15
commit e4140f073f
29 changed files with 2689 additions and 1240 deletions
+34 -29
View File
@@ -38,8 +38,11 @@ class Tank {
this.alive = true;
this.visible = true;
// Collision size (can differ from visual size for large tanks like Boss)
this.colliderSize = config.colliderSize || this.size;
// Half-size for collision calculations
this.halfSize = this.size / 2;
this.colliderHalfSize = this.colliderSize / 2;
}
/**
@@ -70,10 +73,10 @@ class Tank {
// Clamp to map boundaries instead of rejecting movement entirely.
// This allows the tank to slide along the edge smoothly.
const minX = MAP_OFFSET_X + this.halfSize;
const minY = MAP_OFFSET_Y + this.halfSize;
const maxX = MAP_OFFSET_X + MAP_WIDTH - this.halfSize;
const maxY = MAP_OFFSET_Y + MAP_HEIGHT - this.halfSize;
const minX = MAP_OFFSET_X + this.colliderHalfSize;
const minY = MAP_OFFSET_Y + this.colliderHalfSize;
const maxX = MAP_OFFSET_X + MAP_WIDTH - this.colliderHalfSize;
const maxY = MAP_OFFSET_Y + MAP_HEIGHT - this.colliderHalfSize;
newX = Math.max(minX, Math.min(newX, maxX));
newY = Math.max(minY, Math.min(newY, maxY));
@@ -84,11 +87,11 @@ class Tank {
}
// Calculate bounding box at clamped position
const left = newX - this.halfSize;
const top = newY - this.halfSize;
const left = newX - this.colliderHalfSize;
const top = newY - this.colliderHalfSize;
// Terrain collision check
if (mapManager && mapManager.rectCollidesWithTerrain(left, top, this.size, this.size)) {
if (mapManager && mapManager.rectCollidesWithTerrain(left, top, this.colliderSize, this.colliderSize)) {
// Try to align to grid for smoother movement along walls
return this._tryAlignedMove(dir, dt, mapManager);
}
@@ -107,10 +110,10 @@ class Tank {
*/
_snapToGrid(oldDir) {
const halfTile = TILE_SIZE / 2;
const minX = MAP_OFFSET_X + this.halfSize;
const minY = MAP_OFFSET_Y + this.halfSize;
const maxX = MAP_OFFSET_X + MAP_WIDTH - this.halfSize;
const maxY = MAP_OFFSET_Y + MAP_HEIGHT - this.halfSize;
const minX = MAP_OFFSET_X + this.colliderHalfSize;
const minY = MAP_OFFSET_Y + this.colliderHalfSize;
const maxX = MAP_OFFSET_X + MAP_WIDTH - this.colliderHalfSize;
const maxY = MAP_OFFSET_Y + MAP_HEIGHT - this.colliderHalfSize;
if (oldDir === DIRECTION.UP || oldDir === DIRECTION.DOWN) {
// Was moving vertically → snap Y to nearest grid-cell center
@@ -146,6 +149,8 @@ class Tank {
const moveAmount = this.speed * dt * 60;
const vec = DIR_VECTORS[dir];
const halfTile = TILE_SIZE / 2;
const colliderHS = this.colliderHalfSize;
const colliderS = this.colliderSize;
if (dir === DIRECTION.UP || dir === DIRECTION.DOWN) {
// Moving vertically but blocked — try to slide horizontally into a gap
@@ -164,14 +169,14 @@ class Tank {
// Check whether moving in the desired direction would be clear at this aligned X
const testX = alignedX;
const testY = this.y + vec.dy * moveAmount;
const left = testX - this.halfSize;
const top = testY - this.halfSize;
const left = testX - colliderHS;
const top = testY - colliderHS;
if (
left >= MAP_OFFSET_X &&
top >= MAP_OFFSET_Y &&
left + this.size <= MAP_OFFSET_X + MAP_WIDTH &&
top + this.size <= MAP_OFFSET_Y + MAP_HEIGHT &&
!mapManager.rectCollidesWithTerrain(left, top, this.size, this.size)
left + colliderS <= MAP_OFFSET_X + MAP_WIDTH &&
top + colliderS <= MAP_OFFSET_Y + MAP_HEIGHT &&
!mapManager.rectCollidesWithTerrain(left, top, colliderS, colliderS)
) {
candidates.push({ alignedX, diffX: Math.abs(diffX) });
}
@@ -186,7 +191,7 @@ class Tank {
const slideAmount = Math.min(Math.abs(diffX), moveAmount);
this.x += Math.sign(diffX) * slideAmount;
// Clamp to map bounds after sliding
this.x = Math.max(MAP_OFFSET_X + this.halfSize, Math.min(this.x, MAP_OFFSET_X + MAP_WIDTH - this.halfSize));
this.x = Math.max(MAP_OFFSET_X + colliderHS, Math.min(this.x, MAP_OFFSET_X + MAP_WIDTH - colliderHS));
return false;
}
@@ -198,7 +203,7 @@ class Tank {
const slideAmount = Math.min(Math.abs(diffX), moveAmount);
this.x += Math.sign(diffX) * slideAmount;
// Clamp to map bounds after sliding
this.x = Math.max(MAP_OFFSET_X + this.halfSize, Math.min(this.x, MAP_OFFSET_X + MAP_WIDTH - this.halfSize));
this.x = Math.max(MAP_OFFSET_X + colliderHS, Math.min(this.x, MAP_OFFSET_X + MAP_WIDTH - colliderHS));
}
} else {
// Moving horizontally but blocked — try to slide vertically into a gap
@@ -214,14 +219,14 @@ class Tank {
if (Math.abs(diffY) < TILE_SIZE * 0.55) {
const testX = this.x + vec.dx * moveAmount;
const testY = alignedY;
const left = testX - this.halfSize;
const top = testY - this.halfSize;
const left = testX - colliderHS;
const top = testY - colliderHS;
if (
left >= MAP_OFFSET_X &&
top >= MAP_OFFSET_Y &&
left + this.size <= MAP_OFFSET_X + MAP_WIDTH &&
top + this.size <= MAP_OFFSET_Y + MAP_HEIGHT &&
!mapManager.rectCollidesWithTerrain(left, top, this.size, this.size)
left + colliderS <= MAP_OFFSET_X + MAP_WIDTH &&
top + colliderS <= MAP_OFFSET_Y + MAP_HEIGHT &&
!mapManager.rectCollidesWithTerrain(left, top, colliderS, colliderS)
) {
candidates.push({ alignedY, diffY: Math.abs(diffY) });
}
@@ -235,7 +240,7 @@ class Tank {
const slideAmount = Math.min(Math.abs(diffY), moveAmount);
this.y += Math.sign(diffY) * slideAmount;
// Clamp to map bounds after sliding
this.y = Math.max(MAP_OFFSET_Y + this.halfSize, Math.min(this.y, MAP_OFFSET_Y + MAP_HEIGHT - this.halfSize));
this.y = Math.max(MAP_OFFSET_Y + colliderHS, Math.min(this.y, MAP_OFFSET_Y + MAP_HEIGHT - colliderHS));
return false;
}
@@ -247,7 +252,7 @@ class Tank {
const slideAmount = Math.min(Math.abs(diffY), moveAmount);
this.y += Math.sign(diffY) * slideAmount;
// Clamp to map bounds after sliding
this.y = Math.max(MAP_OFFSET_Y + this.halfSize, Math.min(this.y, MAP_OFFSET_Y + MAP_HEIGHT - this.halfSize));
this.y = Math.max(MAP_OFFSET_Y + colliderHS, Math.min(this.y, MAP_OFFSET_Y + MAP_HEIGHT - colliderHS));
}
}
@@ -370,10 +375,10 @@ class Tank {
*/
getBounds() {
return {
x: this.x - this.halfSize,
y: this.y - this.halfSize,
w: this.size,
h: this.size,
x: this.x - this.colliderHalfSize,
y: this.y - this.colliderHalfSize,
w: this.colliderSize,
h: this.colliderSize,
};
}