.
This commit is contained in:
parent
66c949e47d
commit
8e68202b23
@ -49,6 +49,16 @@ class Player {
|
|||||||
this.homePosition = new Vector2(x, y);
|
this.homePosition = new Vector2(x, y);
|
||||||
this.angle = 0;
|
this.angle = 0;
|
||||||
this.targetAngle = 0;
|
this.targetAngle = 0;
|
||||||
|
|
||||||
|
// Stuck detection and pathfinding
|
||||||
|
this.stuckDetection = {
|
||||||
|
lastPosition: new Vector2(x, y),
|
||||||
|
stuckTimer: 0,
|
||||||
|
isStuck: false,
|
||||||
|
alternativeTarget: null,
|
||||||
|
stuckThreshold: 500, // 500ms
|
||||||
|
movementThreshold: 5 // minimum movement distance to not be considered stuck
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,12 +82,21 @@ class Player {
|
|||||||
/**
|
/**
|
||||||
* Updates player physics including movement toward target, velocity limits, and collision bounds
|
* Updates player physics including movement toward target, velocity limits, and collision bounds
|
||||||
* Applies acceleration toward target position with deceleration when close
|
* Applies acceleration toward target position with deceleration when close
|
||||||
|
* Includes stuck detection and alternative pathfinding when blocked
|
||||||
* @param {number} deltaTime - Time elapsed since last frame in seconds
|
* @param {number} deltaTime - Time elapsed since last frame in seconds
|
||||||
* @param {Object} gameState - Current game state for boundary checking
|
* @param {Object} gameState - Current game state for boundary checking
|
||||||
*/
|
*/
|
||||||
updateMovement(deltaTime, gameState) {
|
updateMovement(deltaTime, gameState) {
|
||||||
const direction = this.targetPosition.subtract(this.position).normalize();
|
// Update stuck detection before movement
|
||||||
const distance = this.position.distance(this.targetPosition);
|
this.updateStuckDetection(deltaTime);
|
||||||
|
|
||||||
|
// Choose target - either original or alternative if stuck
|
||||||
|
const currentTarget = this.stuckDetection.isStuck && this.stuckDetection.alternativeTarget
|
||||||
|
? this.stuckDetection.alternativeTarget
|
||||||
|
: this.targetPosition;
|
||||||
|
|
||||||
|
const direction = currentTarget.subtract(this.position).normalize();
|
||||||
|
const distance = this.position.distance(currentTarget);
|
||||||
|
|
||||||
if (distance > 10) {
|
if (distance > 10) {
|
||||||
const force = direction.multiply(this.acceleration * deltaTime);
|
const force = direction.multiply(this.acceleration * deltaTime);
|
||||||
@ -85,6 +104,11 @@ class Player {
|
|||||||
} else {
|
} else {
|
||||||
// Slow down when close to target
|
// Slow down when close to target
|
||||||
this.velocity = this.velocity.multiply(0.8);
|
this.velocity = this.velocity.multiply(0.8);
|
||||||
|
|
||||||
|
// If we reached alternative target, clear stuck state
|
||||||
|
if (this.stuckDetection.isStuck && this.stuckDetection.alternativeTarget) {
|
||||||
|
this.clearStuckState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.velocity = this.velocity.limit(this.maxSpeed);
|
this.velocity = this.velocity.limit(this.maxSpeed);
|
||||||
@ -112,6 +136,98 @@ class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates stuck detection system - tracks if player hasn't moved significantly
|
||||||
|
* and triggers alternative pathfinding when stuck for more than threshold time
|
||||||
|
* @param {number} deltaTime - Time elapsed since last frame in seconds
|
||||||
|
*/
|
||||||
|
updateStuckDetection(deltaTime) {
|
||||||
|
const currentPosition = this.position;
|
||||||
|
const deltaTimeMs = deltaTime * 1000;
|
||||||
|
|
||||||
|
// Calculate movement since last position check
|
||||||
|
const movementDistance = currentPosition.distance(this.stuckDetection.lastPosition);
|
||||||
|
|
||||||
|
if (movementDistance < this.stuckDetection.movementThreshold) {
|
||||||
|
// Player hasn't moved much, increment stuck timer
|
||||||
|
this.stuckDetection.stuckTimer += deltaTimeMs;
|
||||||
|
|
||||||
|
if (this.stuckDetection.stuckTimer >= this.stuckDetection.stuckThreshold) {
|
||||||
|
if (!this.stuckDetection.isStuck) {
|
||||||
|
// Player just became stuck, find alternative path
|
||||||
|
this.handleStuckState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Player moved significantly, reset stuck detection
|
||||||
|
this.stuckDetection.stuckTimer = 0;
|
||||||
|
if (this.stuckDetection.isStuck) {
|
||||||
|
this.clearStuckState();
|
||||||
|
}
|
||||||
|
this.stuckDetection.lastPosition = currentPosition.copy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles when a player becomes stuck - finds alternative pathfinding target
|
||||||
|
* Creates waypoint around obstacles to reach the original target
|
||||||
|
*/
|
||||||
|
handleStuckState() {
|
||||||
|
this.stuckDetection.isStuck = true;
|
||||||
|
|
||||||
|
// Find alternative target by trying different angles around the obstacle
|
||||||
|
const originalTarget = this.targetPosition;
|
||||||
|
const currentPos = this.position;
|
||||||
|
const directionToTarget = originalTarget.subtract(currentPos).normalize();
|
||||||
|
|
||||||
|
// Try different angles (45°, 90°, -45°, -90°) to find a clear path
|
||||||
|
const angles = [Math.PI / 4, Math.PI / 2, -Math.PI / 4, -Math.PI / 2];
|
||||||
|
const wayPointDistance = 60; // Distance to create waypoint
|
||||||
|
|
||||||
|
for (let angle of angles) {
|
||||||
|
const rotatedDirection = this.rotateVector(directionToTarget, angle);
|
||||||
|
const wayPoint = currentPos.add(rotatedDirection.multiply(wayPointDistance));
|
||||||
|
|
||||||
|
// Simple bounds check for waypoint
|
||||||
|
if (wayPoint.x > 50 && wayPoint.x < 950 &&
|
||||||
|
wayPoint.y > 50 && wayPoint.y < 550) {
|
||||||
|
this.stuckDetection.alternativeTarget = wayPoint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no good waypoint found, try backing up slightly
|
||||||
|
if (!this.stuckDetection.alternativeTarget) {
|
||||||
|
const backupDirection = directionToTarget.multiply(-1);
|
||||||
|
this.stuckDetection.alternativeTarget = currentPos.add(backupDirection.multiply(30));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears stuck state and resets stuck detection variables
|
||||||
|
*/
|
||||||
|
clearStuckState() {
|
||||||
|
this.stuckDetection.isStuck = false;
|
||||||
|
this.stuckDetection.alternativeTarget = null;
|
||||||
|
this.stuckDetection.stuckTimer = 0;
|
||||||
|
this.stuckDetection.lastPosition = this.position.copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotates a 2D vector by the given angle
|
||||||
|
* @param {Vector2} vector - Vector to rotate
|
||||||
|
* @param {number} angle - Rotation angle in radians
|
||||||
|
* @returns {Vector2} Rotated vector
|
||||||
|
*/
|
||||||
|
rotateVector(vector, angle) {
|
||||||
|
const cos = Math.cos(angle);
|
||||||
|
const sin = Math.sin(angle);
|
||||||
|
return new Vector2(
|
||||||
|
vector.x * cos - vector.y * sin,
|
||||||
|
vector.x * sin + vector.y * cos
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main AI decision making system - handles reaction timing, faceoffs, and behavioral switching
|
* Main AI decision making system - handles reaction timing, faceoffs, and behavioral switching
|
||||||
* Delegates to specific behavior methods based on team puck possession
|
* Delegates to specific behavior methods based on team puck possession
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user