Commit e4c4bde0 authored by haiyoucuv's avatar haiyoucuv

init

parent aa7315ad
...@@ -29,26 +29,26 @@ export class AISnake extends Snake { ...@@ -29,26 +29,26 @@ export class AISnake extends Snake {
private escapeTarget: Snake = null; private escapeTarget: Snake = null;
private readonly BASE_VIEW_DISTANCE = 300; private readonly BASE_VIEW_DISTANCE = 300;
private readonly INTERCEPT_DISTANCE = 400; private readonly INTERCEPT_DISTANCE = 350; // 降低拦截距离
private readonly PREDICTION_TIME = 1.0; private readonly PREDICTION_TIME = 1.2; // 增加预测时间
private readonly ESCAPE_BOUNDARY = 200; private readonly ESCAPE_BOUNDARY = 250; // 增加边界安全距离
private readonly SAFE_MARGIN = 3.0; // 增加安全边际
private readonly COLLISION_CHECK_DISTANCE = 500; // 增加碰撞检测距离
private readonly ASSIST_DISTANCE = 500; // 协助攻击的最大距离 private readonly ASSIST_DISTANCE = 500; // 协助攻击的最大距离
private readonly SAFE_MARGIN = 2; // 安全边际系数 private readonly DANGER_ANGLE_THRESHOLD = 90; // 扩大危险角度范围
private readonly COLLISION_CHECK_DISTANCE = 400; // 增加碰撞检测距离 private readonly COUNTER_ATTACK_THRESHOLD = 0.8; // 反击判定阈值
private readonly BODY_AVOID_MARGIN = 2.5; // 增加身体避让边际 private readonly SAFE_DISTANCE_MULTIPLIER = 1.5; // 安全距离倍数
private readonly DANGER_ANGLE_THRESHOLD = 75; // 扩大危险角度范围
private assistTarget: AISnake = null; // 正在协助的AI蛇 private assistTarget: AISnake = null; // 正在协助的AI蛇
private get difficultyParams() { private get difficultyParams() {
return { return {
reactionTime: math.lerp(0.8, 0.2, (this.difficulty - 1) / 4), reactionTime: math.lerp(0.8, 0.2, (this.difficulty - 1) / 4),
viewDistance: this.BASE_VIEW_DISTANCE * (1 + (this.difficulty - 1) * 0.2), viewDistance: this.BASE_VIEW_DISTANCE * (1 + (this.difficulty - 1) * 0.2),
interceptDistance: this.INTERCEPT_DISTANCE * (1 + (this.difficulty - 1) * 0.2), interceptDistance: this.INTERCEPT_DISTANCE * (1 + (this.difficulty - 1) * 0.2),
aggressiveness: math.lerp(0.3, 0.9, (this.difficulty - 1) / 4), aggressiveness: math.lerp(0.2, 0.7, (this.difficulty - 1) / 4), // 降低激进程度
predictionAccuracy: math.lerp(0.5, 0.9, (this.difficulty - 1) / 4), predictionAccuracy: math.lerp(0.6, 0.9, (this.difficulty - 1) / 4),
turnSpeed: math.lerp(2, 5, (this.difficulty - 1) / 4) turnSpeed: math.lerp(2, 4.5, (this.difficulty - 1) / 4) // 略微降低最大转向速度
}; };
} }
...@@ -231,6 +231,7 @@ export class AISnake extends Snake { ...@@ -231,6 +231,7 @@ export class AISnake extends Snake {
} }
private executeCurrentState(dt: number) { private executeCurrentState(dt: number) {
const threat = this.findNearbyAIToAvoid(); const threat = this.findNearbyAIToAvoid();
if (threat && threat.dangerLevel > 30) { // 降低触发避让的阈值 if (threat && threat.dangerLevel > 30) { // 降低触发避让的阈值
...@@ -295,49 +296,6 @@ export class AISnake extends Snake { ...@@ -295,49 +296,6 @@ export class AISnake extends Snake {
return this.head.angle; return this.head.angle;
} }
// 计算最佳躲避角度
private calculateAvoidanceAngle(threat: Snake): number {
const myPos = this.head.getPosition();
const threatPos = threat.head.getPosition();
const baseEscapeAngle = this.calculateEscapeAngle(threatPos);
// 尝试多个躲避角度
const angles = [
baseEscapeAngle,
baseEscapeAngle + 45,
baseEscapeAngle - 45,
baseEscapeAngle + 90,
baseEscapeAngle - 90
];
// 选择最安全的角度
let bestAngle = baseEscapeAngle;
let maxSafety = -1;
for (const angle of angles) {
const futurePos = this.predictFuturePosition(myPos, angle, this.speed * 3);
let safety = Vec3.distance(futurePos, threatPos);
// 检查这个角度是否会导致撞墙
if (this.willHitBoundary(angle)) {
continue;
}
// 检查与威胁物的身体的距离
for (const bodyPart of threat.bodyArr) {
const bodyDist = Vec3.distance(futurePos, bodyPart.getPosition());
safety = Math.min(safety, bodyDist);
}
if (safety > maxSafety) {
maxSafety = safety;
bestAngle = angle;
}
}
return bestAngle;
}
private canInterceptPlayer(player: Snake): boolean { private canInterceptPlayer(player: Snake): boolean {
if (!player || !player.isLife) return false; if (!player || !player.isLife) return false;
...@@ -346,10 +304,10 @@ export class AISnake extends Snake { ...@@ -346,10 +304,10 @@ export class AISnake extends Snake {
const playerPos = player.head.getPosition(); const playerPos = player.head.getPosition();
const distance = Vec3.distance(myPos, playerPos); const distance = Vec3.distance(myPos, playerPos);
// 降低拦截距离和提高长度要求 return distance < params.interceptDistance * 0.7 && // 进一步减小拦截距离
return distance < params.interceptDistance * 0.8 && // 减小拦截距离 this.getSnakeLen() > player.getSnakeLen() * 1.2 && // 提高长度要求
this.getSnakeLen() > player.getSnakeLen() * 0.8 && // 提高长度要求 math.random() < params.aggressiveness * 0.6 && // 降低激进程度
math.random() < params.aggressiveness * 0.8; // 降低激进程度 !this.isNearBoundary(playerPos); // 不在边界附近才拦截
} }
private executeHunting() { private executeHunting() {
...@@ -357,24 +315,82 @@ export class AISnake extends Snake { ...@@ -357,24 +315,82 @@ export class AISnake extends Snake {
const myPos = this.head.getPosition(); const myPos = this.head.getPosition();
const distance = Vec3.distance(myPos, this.targetFood); const distance = Vec3.distance(myPos, this.targetFood);
// 计算到食物的直接角度
const targetAngle = this.calculateTargetAngle(this.targetFood); const targetAngle = this.calculateTargetAngle(this.targetFood);
const angleDiff = Math.abs(this.head.angle - targetAngle);
// 检查是否需要避开自己的身体 // 检查是否需要避开自己的身体
const needAvoidBody = this.willHitOwnBody(targetAngle); const needAvoidBody = this.willHitOwnBody(targetAngle);
if (needAvoidBody) { if (needAvoidBody) {
// 寻找替代路径 // 寻找更优的替代路径
const alternativeAngle = this.findAlternativeAngleToFood(this.targetFood); const alternativeAngle = this.findBetterAngleToFood(this.targetFood);
this.smoothRotateToAngle(alternativeAngle, this.difficultyParams.turnSpeed); if (alternativeAngle !== null) {
this.smoothRotateToAngle(alternativeAngle, this.difficultyParams.turnSpeed * 1.8);
} else {
// 如果没有找到好的替代路径,执行更激进的转向
this.executeAggressiveTurn(targetAngle);
}
this.isFast = false;
} else { } else {
// 直接前进 // 根据角度差决定转向策略
this.smoothRotateToAngle(targetAngle, this.difficultyParams.turnSpeed * 1.5); if (angleDiff > 90) {
// 大角度差时执行快速转向
this.executeAggressiveTurn(targetAngle);
this.isFast = false;
} else {
// 小角度差时正常追逐
this.smoothRotateToAngle(targetAngle, this.difficultyParams.turnSpeed * 1.5);
this.isFast = distance < this.BASE_VIEW_DISTANCE / 2;
}
} }
}
// 更激进的转向方法
private executeAggressiveTurn(targetAngle: number) {
const currentAngle = this.head.angle;
let angleDiff = targetAngle - currentAngle;
// 标准化角度差到 -180 到 180 度范围
while (angleDiff > 180) angleDiff -= 360;
while (angleDiff < -180) angleDiff += 360;
// 使用更大的转向速度
const turnSpeed = this.difficultyParams.turnSpeed * 2.5;
this.head.angle += math.clamp(angleDiff, -turnSpeed, turnSpeed);
}
// 寻找更好的替代角度
private findBetterAngleToFood(foodPos: Vec3): number | null {
const myPos = this.head.getPosition();
const directAngle = this.calculateTargetAngle(foodPos);
const currentDistance = Vec3.distance(myPos, foodPos);
// 根据当前角度差决定搜索范围
const angleDiff = Math.abs(this.head.angle - directAngle);
const searchRange = angleDiff > 90 ? [-120, -90, -60, -45, -30, 30, 45, 60, 90, 120]
: [-60, -45, -30, -15, 15, 30, 45, 60];
let bestAngle = null;
let bestImprovement = 0;
for (const offset of searchRange) {
const testAngle = directAngle + offset;
if (this.willHitOwnBody(testAngle)) continue;
// 根据距离和路径调整速度 const futurePos = this.predictFuturePosition(myPos, testAngle, this.radius * 5);
this.isFast = distance < this.BASE_VIEW_DISTANCE / 2 && !needAvoidBody; const newDistance = Vec3.distance(futurePos, foodPos);
// 计算路径改善程度
const improvement = currentDistance - newDistance;
// 选择最佳改善路径
if (improvement > bestImprovement) {
bestImprovement = improvement;
bestAngle = testAngle;
}
}
return bestAngle;
} }
// 检查是否会撞到自己的身体 // 检查是否会撞到自己的身体
...@@ -394,32 +410,6 @@ export class AISnake extends Snake { ...@@ -394,32 +410,6 @@ export class AISnake extends Snake {
return false; return false;
} }
// 寻找到食物的替代角度
private findAlternativeAngleToFood(foodPos: Vec3): number {
const myPos = this.head.getPosition();
const directAngle = this.calculateTargetAngle(foodPos);
// 尝试不同的角度偏移
const offsets = [30, -30, 45, -45, 60, -60];
for (const offset of offsets) {
const testAngle = directAngle + offset;
if (!this.willHitOwnBody(testAngle)) {
// 检查这个角度是否会让我们更接近食物
const futurePos = this.predictFuturePosition(myPos, testAngle, this.radius * 4);
const currentDistance = Vec3.distance(myPos, foodPos);
const futureDistance = Vec3.distance(futurePos, foodPos);
if (futureDistance < currentDistance) {
return testAngle;
}
}
}
// 如果没找到更好的角度,返回直接角度
return directAngle;
}
private executeIntercepting() { private executeIntercepting() {
if (!this.targetSnake || !this.targetSnake.isLife) return; if (!this.targetSnake || !this.targetSnake.isLife) return;
...@@ -433,12 +423,11 @@ export class AISnake extends Snake { ...@@ -433,12 +423,11 @@ export class AISnake extends Snake {
// 增加躲避权重 // 增加躲避权重
const aiDistance = Vec3.distance(myPos, nearbyAI.snake.head.getPosition()); const aiDistance = Vec3.distance(myPos, nearbyAI.snake.head.getPosition());
const avoidWeight = math.clamp(1 - aiDistance / (this.BASE_VIEW_DISTANCE * 0.5), 0.3, 0.9); // 提高最小权重 const avoidWeight = math.clamp(1 - aiDistance / (this.BASE_VIEW_DISTANCE * 0.6), 0.4, 0.95); // 增加避让权重
const finalAngle = this.blendAngles(targetAngle, avoidAngle, avoidWeight); const finalAngle = this.blendAngles(targetAngle, avoidAngle, avoidWeight);
// 使用更快的转向速度进行躲避 this.smoothRotateToAngle(finalAngle, this.difficultyParams.turnSpeed * 1.5);
this.smoothRotateToAngle(finalAngle, this.difficultyParams.turnSpeed * 1.8); this.isFast = false; // 避让时始终降速
this.isFast = false; // 躲避时降低速度
} else { } else {
const predictedPos = this.predictTargetPosition(this.targetSnake); const predictedPos = this.predictTargetPosition(this.targetSnake);
const targetAngle = this.calculateTargetAngle(predictedPos); const targetAngle = this.calculateTargetAngle(predictedPos);
...@@ -471,12 +460,15 @@ export class AISnake extends Snake { ...@@ -471,12 +460,15 @@ export class AISnake extends Snake {
} }
// 寻找需要躲避的附近AI // 寻找需要躲避的附近AI
private findNearbyAIToAvoid(): { snake: Snake, dangerLevel: number } | null { private findNearbyAIToAvoid(): { snake: Snake, dangerLevel: number, canCounter: boolean } | null {
const myPos = this.head.getPosition(); const myPos = this.head.getPosition();
const myFuturePos = this.predictFuturePosition(myPos, this.head.angle, this.speed * 2); const myFuturePos = this.predictFuturePosition(myPos, this.head.angle, this.speed * 2);
let maxDanger = 0; let maxDanger = 0;
let mostDangerousSnake = null; let mostDangerousSnake = null;
const myLength = this.getSnakeLen();
let canCounterAttack = false;
const allSnakes = [...MainGame.ins.animalNode.children, MainGame.ins.player.node] const allSnakes = [...MainGame.ins.animalNode.children, MainGame.ins.player.node]
.map(node => node.getComponent(Snake)) .map(node => node.getComponent(Snake))
.filter(snake => snake && snake !== this && snake.isLife); .filter(snake => snake && snake !== this && snake.isLife);
...@@ -484,15 +476,25 @@ export class AISnake extends Snake { ...@@ -484,15 +476,25 @@ export class AISnake extends Snake {
for (const snake of allSnakes) { for (const snake of allSnakes) {
let snakeDanger = 0; let snakeDanger = 0;
const headDistance = Vec3.distance(myPos, snake.head.getPosition()); const headDistance = Vec3.distance(myPos, snake.head.getPosition());
const isPlayer = snake === MainGame.ins.player;
// 对玩家增加额外的危险系数
const playerDangerMultiplier = isPlayer ? 1.5 : 1.0;
// 检查头部威胁 // 检查头部威胁
if (headDistance < this.COLLISION_CHECK_DISTANCE) { if (headDistance < this.COLLISION_CHECK_DISTANCE) {
const angleToHead = this.calculateTargetAngle(snake.head.getPosition()); const angleToHead = this.calculateTargetAngle(snake.head.getPosition());
const headAngleDiff = Math.abs(this.head.angle - angleToHead); const headAngleDiff = Math.abs(this.head.angle - angleToHead);
if (headAngleDiff < this.DANGER_ANGLE_THRESHOLD) { // 对玩家扩大危险角度阈值
snakeDanger = Math.max(snakeDanger, const effectiveAngleThreshold = isPlayer ?
(this.COLLISION_CHECK_DISTANCE - headDistance) / this.COLLISION_CHECK_DISTANCE * 100); this.DANGER_ANGLE_THRESHOLD * 1.2 :
this.DANGER_ANGLE_THRESHOLD;
if (headAngleDiff < effectiveAngleThreshold) {
const baseDanger = (this.COLLISION_CHECK_DISTANCE - headDistance) /
this.COLLISION_CHECK_DISTANCE * 100;
snakeDanger = Math.max(snakeDanger, baseDanger * playerDangerMultiplier);
} }
} }
...@@ -502,21 +504,29 @@ export class AISnake extends Snake { ...@@ -502,21 +504,29 @@ export class AISnake extends Snake {
const bodyDistance = Vec3.distance(myPos, bodyPart.getPosition()); const bodyDistance = Vec3.distance(myPos, bodyPart.getPosition());
const futureDist = Vec3.distance(myFuturePos, bodyPart.getPosition()); const futureDist = Vec3.distance(myFuturePos, bodyPart.getPosition());
// 计算与身体部分的相对运动
const bodyAngle = this.calculateTargetAngle(bodyPart.getPosition()); const bodyAngle = this.calculateTargetAngle(bodyPart.getPosition());
const angleDiff = Math.abs(this.head.angle - bodyAngle); const angleDiff = Math.abs(this.head.angle - bodyAngle);
// 根据距离和角度计算危险程度 // 对玩家的身体也使用更大的检测范围
if (bodyDistance < this.COLLISION_CHECK_DISTANCE && angleDiff < this.DANGER_ANGLE_THRESHOLD) { const effectiveCheckDistance = isPlayer ?
const distanceDanger = (this.COLLISION_CHECK_DISTANCE - bodyDistance) / this.COLLISION_CHECK_DISTANCE; this.COLLISION_CHECK_DISTANCE * 1.2 :
this.COLLISION_CHECK_DISTANCE;
if (bodyDistance < effectiveCheckDistance && angleDiff < this.DANGER_ANGLE_THRESHOLD) {
const distanceDanger = (effectiveCheckDistance - bodyDistance) / effectiveCheckDistance;
const angleDanger = (this.DANGER_ANGLE_THRESHOLD - angleDiff) / this.DANGER_ANGLE_THRESHOLD; const angleDanger = (this.DANGER_ANGLE_THRESHOLD - angleDiff) / this.DANGER_ANGLE_THRESHOLD;
const futureDanger = futureDist < bodyDistance ? 1.5 : 1; // 如果预测位置更近,增加危险系数 const futureDanger = futureDist < bodyDistance ? 2.5 : 1; // 增加未来碰撞的危险系数
const partDanger = (distanceDanger * angleDanger * futureDanger) * 100; const partDanger = (distanceDanger * angleDanger * futureDanger) * 120 * playerDangerMultiplier;
snakeDanger = Math.max(snakeDanger, partDanger); snakeDanger = Math.max(snakeDanger, partDanger);
} }
} }
// 如果是玩家且正在加速,进一步提高危险等级
if (isPlayer && snake.isFast) {
snakeDanger *= 1.3;
}
// 更新最危险的蛇 // 更新最危险的蛇
if (snakeDanger > maxDanger) { if (snakeDanger > maxDanger) {
maxDanger = snakeDanger; maxDanger = snakeDanger;
...@@ -524,7 +534,22 @@ export class AISnake extends Snake { ...@@ -524,7 +534,22 @@ export class AISnake extends Snake {
} }
} }
return maxDanger > 0 ? { snake: mostDangerousSnake, dangerLevel: maxDanger } : null; // 评估是否可以反击
if (mostDangerousSnake) {
const threatLength = mostDangerousSnake.getSnakeLen();
const lengthAdvantage = myLength / threatLength;
const distance = Vec3.distance(myPos, mostDangerousSnake.head.getPosition());
const isSafeDistance = distance > this.COLLISION_CHECK_DISTANCE * this.SAFE_DISTANCE_MULTIPLIER;
canCounterAttack = lengthAdvantage > this.COUNTER_ATTACK_THRESHOLD && isSafeDistance;
}
// 降低触发避让的阈值,使AI更容易进入避让状态
return maxDanger > 15 ? {
snake: mostDangerousSnake,
dangerLevel: maxDanger,
canCounter: canCounterAttack
} : null;
} }
private predictFuturePosition(currentPos: Vec3, angle: number, speed: number): Vec3 { private predictFuturePosition(currentPos: Vec3, angle: number, speed: number): Vec3 {
...@@ -535,63 +560,163 @@ export class AISnake extends Snake { ...@@ -535,63 +560,163 @@ export class AISnake extends Snake {
} }
private executeEscaping() { private executeEscaping() {
if (!this.escapeTarget) {
// 如果没有特定的逃离目标,检查并避开所有潜在威胁
this.avoidAllThreats();
return;
}
const myPos = this.head.getPosition(); const myPos = this.head.getPosition();
const threatPos = this.escapeTarget.head.getPosition();
const distance = Vec3.distance(myPos, threatPos);
if (this.escapeTarget) { // 紧急避让判定
let escapeAngle = this.calculateEscapeAngle(this.escapeTarget.head.getPosition()); const isEmergency = distance < this.radius * 3;
const escapeAngle = this.calculateAvoidanceAngle(this.escapeTarget);
// 考虑身体部分的位置来调整逃跑角度 if (isEmergency) {
for (const bodyPart of this.escapeTarget.bodyArr) { // 紧急情况:直接设置角度
const bodyDistance = Vec3.distance(myPos, bodyPart.getPosition()); this.head.angle = escapeAngle;
if (bodyDistance < this.BASE_VIEW_DISTANCE * 0.7) { this.isFast = false;
const bodyEscapeAngle = this.calculateEscapeAngle(bodyPart.getPosition()); } else {
// 综合考虑头部和身体的逃跑角度 // 非紧急情况:快速但平滑地转向
escapeAngle = (escapeAngle + bodyEscapeAngle) / 2; const angleDiff = escapeAngle - this.head.angle;
// 标准化角度差到 -180 到 180 度范围
const normalizedDiff = (angleDiff + 180) % 360 - 180;
this.head.angle += math.clamp(normalizedDiff, -15, 15);
this.isFast = distance > this.radius * 5;
}
}
// 避开所有潜在威胁
private avoidAllThreats() {
const myPos = this.head.getPosition();
const allSnakes = [...MainGame.ins.animalNode.children, MainGame.ins.player.node]
.map(node => node.getComponent(Snake))
.filter(snake => snake && snake !== this && snake.isLife);
let nearestThreatDistance = Infinity;
let bestEscapeAngle = this.head.angle;
let hasThreats = false;
// 检查所有潜在威胁
for (const snake of allSnakes) {
const distance = Vec3.distance(myPos, snake.head.getPosition());
if (distance < this.COLLISION_CHECK_DISTANCE) {
hasThreats = true;
if (distance < nearestThreatDistance) {
nearestThreatDistance = distance;
bestEscapeAngle = this.calculateAvoidanceAngle(snake);
} }
} }
}
// 检查逃跑方向是否会导致撞墙 if (hasThreats) {
if (this.willHitBoundary(escapeAngle)) { // 有威胁时执行避让
escapeAngle = this.adjustEscapeAngle(escapeAngle); const isEmergency = nearestThreatDistance < this.radius * 3;
if (isEmergency) {
this.head.angle = bestEscapeAngle;
this.isFast = false;
} else {
const angleDiff = bestEscapeAngle - this.head.angle;
const normalizedDiff = (angleDiff + 180) % 360 - 180;
this.head.angle += math.clamp(normalizedDiff, -15, 15);
this.isFast = nearestThreatDistance > this.radius * 5;
} }
this.smoothRotateToAngle(escapeAngle, this.difficultyParams.turnSpeed * 1.8);
} else { } else {
// 没有威胁时检查边界
this.avoidBoundary(); this.avoidBoundary();
} }
this.isFast = true;
} }
private willHitBoundary(angle: number): boolean { // 计算避让角度的方法,增加紧急情况下的处理
private calculateAvoidanceAngle(threat: Snake): number {
const myPos = this.head.getPosition(); const myPos = this.head.getPosition();
const radian = angle * Math.PI / 180; const threatPos = threat.head.getPosition();
const checkDistance = this.ESCAPE_BOUNDARY; const baseEscapeAngle = this.calculateEscapeAngle(threatPos);
const futureX = myPos.x + Math.cos(radian) * checkDistance; // 检查基础逃生角度是否安全
const futureY = myPos.y + Math.sin(radian) * checkDistance; if (!this.willHitBoundary(baseEscapeAngle)) {
return baseEscapeAngle;
}
return this.isInDangerousPosition(v3(futureX, futureY, 0)); // 如果基础角度不安全,寻找最佳替代角度
const angles = [
baseEscapeAngle,
baseEscapeAngle + 45, baseEscapeAngle - 45,
baseEscapeAngle + 90, baseEscapeAngle - 90,
baseEscapeAngle + 135, baseEscapeAngle - 135,
baseEscapeAngle + 180
];
let bestAngle = baseEscapeAngle;
let maxSafety = -Infinity;
for (const angle of angles) {
if (this.willHitBoundary(angle)) continue;
const safety = this.evaluateEscapeAngleSafety(angle, threat);
if (safety > maxSafety) {
maxSafety = safety;
bestAngle = angle;
}
}
return bestAngle;
} }
private adjustEscapeAngle(originalAngle: number): number { // 评估逃生角度的安全性
const adjustAngles = [-45, 45, -90, 90, -135, 135, 180]; private evaluateEscapeAngleSafety(angle: number, threat: Snake): number {
const myPos = this.head.getPosition(); const myPos = this.head.getPosition();
const futurePos = this.predictFuturePosition(myPos, angle, this.radius * 4);
let safety = 100;
for (const adjustment of adjustAngles) { // 检查与威胁的距离
const newAngle = (originalAngle + adjustment) % 360; const threatDistance = Vec3.distance(futurePos, threat.head.getPosition());
if (!this.willHitBoundary(newAngle)) { safety += threatDistance;
return newAngle;
// 检查边界距离
const boundaryDist = this.getDistanceToBoundary(futurePos);
safety += boundaryDist * 2;
// 检查与其他蛇的距离
const allSnakes = [...MainGame.ins.animalNode.children, MainGame.ins.player.node]
.map(node => node.getComponent(Snake))
.filter(snake => snake && snake !== this && snake !== threat && snake.isLife);
for (const snake of allSnakes) {
const distance = Vec3.distance(futurePos, snake.head.getPosition());
if (distance < this.COLLISION_CHECK_DISTANCE) {
safety -= (this.COLLISION_CHECK_DISTANCE - distance);
} }
} }
return originalAngle; // 如果没有找到更好的角度,返回原角度 return safety;
}
private willHitBoundary(angle: number): boolean {
const myPos = this.head.getPosition();
const futurePos = this.predictFuturePosition(myPos, angle, this.radius * 4);
const boundaryDist = this.getDistanceToBoundary(futurePos);
return boundaryDist < this.ESCAPE_BOUNDARY;
}
// 获取到边界的距离
private getDistanceToBoundary(position: Vec3): number {
const mapWidth = Global.MAP_WIDTH;
const mapHeight = Global.MAP_HEIGHT;
return Math.min(
mapWidth / 2 - Math.abs(position.x),
mapHeight / 2 - Math.abs(position.y)
);
} }
private executeWandering() { private executeWandering() {
// 增加方向改变的概率 // 增加方向改变的概率
if (math.randomRangeInt(0, 20) == 0) { // 减少方向改变的频率 if (math.randomRangeInt(0, 30) == 0) {
const direction = math.randomRangeInt(0, 3); const direction = math.randomRangeInt(0, 3);
const speed = math.randomRangeInt(1, 4); const speed = math.randomRangeInt(1, 3);
if (direction === DirectionType.LEFT) { if (direction === DirectionType.LEFT) {
this.head.angle += speed; this.head.angle += speed;
...@@ -601,7 +726,7 @@ export class AISnake extends Snake { ...@@ -601,7 +726,7 @@ export class AISnake extends Snake {
} }
// 减少速度变化的频率 // 减少速度变化的频率
this.isFast = math.random() < this.difficultyParams.aggressiveness * 0.1; this.isFast = math.random() < this.difficultyParams.aggressiveness * 0.05;
} }
private avoidBoundary() { private avoidBoundary() {
...@@ -762,7 +887,6 @@ export class AISnake extends Snake { ...@@ -762,7 +887,6 @@ export class AISnake extends Snake {
return score; return score;
} }
// 判断是否能在竞争者之前到达食物 // 判断是否能在竞争者之前到达食物
private canReachFoodFirst(foodPos: Vec3, myDistance: number, competitors: Snake[]): boolean { private canReachFoodFirst(foodPos: Vec3, myDistance: number, competitors: Snake[]): boolean {
const mySpeed = this.speed * (this.isFast ? 2 : 1); const mySpeed = this.speed * (this.isFast ? 2 : 1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment