Commit 05fee1ee authored by haiyoucuv's avatar haiyoucuv

init

parent 2a62f6d9
import { _decorator, math, v3, Vec3, Node, Collider2D, Contact2DType, PhysicsGroup } from "cc";
import { _decorator, math, v3, Vec3, Node, Collider2D, Contact2DType, PhysicsGroup, Vec2, IVec2Like, v2 } from "cc";
import { Snake } from "./Snake";
import { DirectionType } from "./Common/Enums";
import { Global } from "./Global";
......@@ -26,14 +26,14 @@ export class AISnake extends Snake {
private currentState: AIState = AIState.WANDERING;
private behaviorTimer: number = 0;
private targetFood: Vec3 = null;
private targetFood: Vec2 = null;
private targetSnake: Snake = null;
private escapeTarget: Snake = null;
private readonly BASE_VIEW_DISTANCE = 300;
private readonly INTERCEPT_DISTANCE = 350; // 降低拦截距离
private readonly PREDICTION_TIME = 1.2; // 增加预测时间
private readonly ESCAPE_BOUNDARY = 150; // 增加边界安全距离
private readonly ESCAPE_BOUNDARY = 250; // 增加边界安全距离
private readonly SAFE_MARGIN = 3.0; // 增加安全边际
private readonly COLLISION_CHECK_DISTANCE = 500; // 增加碰撞检测距离
private readonly ASSIST_DISTANCE = 500; // 协助攻击的最大距离
......@@ -173,7 +173,7 @@ export class AISnake extends Snake {
this.currentState = state;
switch (state) {
case AIState.HUNTING:
this.targetFood = target as Vec3;
this.targetFood = target as Vec2;
break;
case AIState.INTERCEPTING:
this.targetSnake = target as Snake;
......@@ -227,7 +227,6 @@ export class AISnake extends Snake {
}
const playerPos = this.targetSnake.head.getPosition();
const partnerPos = this.assistTarget.head.getPosition();
// 计算包围位置:在玩家和协助目标的另一侧
const angle = this.calculateTargetAngle(playerPos);
......@@ -341,7 +340,7 @@ export class AISnake extends Snake {
if (!this.targetFood) return;
const myPos = this.head.getPosition();
const distance = Vec3.distance(myPos, this.targetFood);
const distance = Vec2.distance(myPos as IVec2Like, this.targetFood);
const targetAngle = this.calculateTargetAngle(this.targetFood);
const angleDiff = Math.abs(this.head.angle - targetAngle);
......@@ -387,10 +386,10 @@ export class AISnake extends Snake {
}
// 寻找更好的替代角度
private findBetterAngleToFood(foodPos: Vec3): number | null {
private findBetterAngleToFood(foodPos: Vec2): number | null {
const myPos = this.head.getPosition();
const directAngle = this.calculateTargetAngle(foodPos);
const currentDistance = Vec3.distance(myPos, foodPos);
const currentDistance = Vec2.distance(myPos as IVec2Like, foodPos);
// 根据当前角度差决定搜索范围
const angleDiff = Math.abs(this.head.angle - directAngle);
......@@ -406,7 +405,7 @@ export class AISnake extends Snake {
if (this.willHitOwnBody(testAngle)) continue;
const futurePos = this.predictFuturePosition(myPos, testAngle, this.radius * 5);
const newDistance = Vec3.distance(futurePos, foodPos);
const newDistance = Vec2.distance(futurePos as IVec2Like, foodPos);
// 计算路径改善程度
const improvement = currentDistance - newDistance;
......@@ -429,7 +428,7 @@ export class AISnake extends Snake {
// 检查与自己身体的碰撞
for (const bodyPart of this.bodyArr) {
const bodyDistance = Vec3.distance(futurePos, bodyPart.getPosition());
const bodyDistance = Vec2.distance(futurePos, bodyPart.getPosition() as IVec2Like);
if (bodyDistance < this.radius * 2.5) { // 略大的碰撞检测范围
return true;
}
......@@ -529,8 +528,8 @@ export class AISnake extends Snake {
// 检查身体威胁
for (let i = 0; i < snake.bodyArr.length; i++) {
const bodyPart = snake.bodyArr[i];
const bodyDistance = Vec3.distance(myPos, bodyPart.getPosition());
const futureDist = Vec3.distance(myFuturePos, bodyPart.getPosition());
const bodyDistance = Vec2.distance(myPos, bodyPart.getPosition());
const futureDist = Vec2.distance(myFuturePos, bodyPart.getPosition() as IVec2Like);
const bodyAngle = this.calculateTargetAngle(bodyPart.getPosition());
const angleDiff = Math.abs(this.head.angle - bodyAngle);
......@@ -569,11 +568,8 @@ export class AISnake extends Snake {
} : null;
}
private predictFuturePosition(currentPos: Vec3, angle: number, speed: number): Vec3 {
const radian = angle * Math.PI / 180;
const futureX = currentPos.x + Math.cos(radian) * speed;
const futureY = currentPos.y + Math.sin(radian) * speed;
return v3(futureX, futureY, 0);
private predictFuturePosition(currentPos: IVec2Like, angle: number, speed: number): IVec2Like {
return Vec2.add(v2(), currentPos, this.getVelocity().multiplyScalar(speed));
}
private executeEscaping() {
......@@ -689,7 +685,7 @@ export class AISnake extends Snake {
let safety = 100;
// 检查与威胁的距离
const threatDistance = Vec3.distance(futurePos, threat.head.getPosition());
const threatDistance = Vec2.distance(futurePos as IVec2Like, threat.head.getPosition());
safety += threatDistance;
// 检查边界距离
......@@ -702,7 +698,7 @@ export class AISnake extends Snake {
.filter(snake => snake && snake !== this && snake !== threat && snake.isLife);
for (const snake of allSnakes) {
const distance = Vec3.distance(futurePos, snake.head.getPosition());
const distance = Vec2.distance(futurePos, snake.head.getPosition() as IVec2Like);
if (distance < this.COLLISION_CHECK_DISTANCE) {
safety -= (this.COLLISION_CHECK_DISTANCE - distance);
}
......@@ -719,7 +715,7 @@ export class AISnake extends Snake {
}
// 获取到边界的距离
private getDistanceToBoundary(position: Vec3): number {
private getDistanceToBoundary(position: IVec2Like): number {
const mapWidth = Global.MAP_WIDTH;
const mapHeight = Global.MAP_HEIGHT;
......@@ -791,7 +787,7 @@ export class AISnake extends Snake {
}
}
private findNearestFood(): Vec3 | null {
private findNearestFood(): Vec2 | null {
const myPos = this.head.getPosition();
let nearestFood = null;
let minDistance = this.difficultyParams.viewDistance;
......@@ -858,7 +854,7 @@ export class AISnake extends Snake {
}
// 寻找替代食物
private findAlternativeFood(foods: Node[], myPos: Vec3, viewDistance: number, competitors: Snake[]): Vec3 | null {
private findAlternativeFood(foods: Node[], myPos: Vec3, viewDistance: number, competitors: Snake[]): Vec2 | null {
let bestAlternative = null;
let bestScore = -1;
......@@ -982,7 +978,7 @@ export class AISnake extends Snake {
return nearestThreat;
}
private calculateEscapeAngle(threatPos: Vec3): number {
private calculateEscapeAngle(threatPos: IVec2Like): number {
const myPos = this.head.getPosition();
return math.toDegree(Math.atan2(
myPos.y - threatPos.y,
......@@ -990,7 +986,7 @@ export class AISnake extends Snake {
));
}
private calculateTargetAngle(targetPos: Vec3): number {
private calculateTargetAngle(targetPos: IVec2Like): number {
const myPos = this.head.getPosition();
return math.toDegree(Math.atan2(
targetPos.y - myPos.y,
......@@ -1002,6 +998,7 @@ export class AISnake extends Snake {
const currentAngle = this.head.angle;
let angleDiff = targetAngle - currentAngle;
// angleDiff %= 360;
// 标准化角度差到 -180 到 180 度范围
while (angleDiff > 180) angleDiff -= 360;
while (angleDiff < -180) angleDiff += 360;
......@@ -1018,16 +1015,15 @@ export class AISnake extends Snake {
);
}
private predictTargetPosition(target: Snake): Vec3 {
private predictTargetPosition(target: Snake): Vec2 {
const targetPos = target.head.getPosition();
const targetAngle = target.head.angle;
const targetSpeed = target.isFast ? target.speed * 2 : target.speed;
const radian = targetAngle * Math.PI / 180;
const predictX = targetPos.x + Math.cos(radian) * targetSpeed * this.PREDICTION_TIME * this.difficultyParams.predictionAccuracy;
const predictY = targetPos.y + Math.sin(radian) * targetSpeed * this.PREDICTION_TIME * this.difficultyParams.predictionAccuracy;
return target.getVelocity()
.add2f(targetPos.x, targetPos.y)
.multiplyScalar(targetSpeed * this.PREDICTION_TIME * this.difficultyParams.predictionAccuracy);
return v3(predictX, predictY, 0);
// return v3(predictX, predictY, 0);
}
setDifficulty(level: number) {
......
......@@ -52,6 +52,7 @@ export class Player extends Snake {
death() {
super.death();
this.length = 0;
// 发送游戏结束事件
director.emit(Events.setGameState, GameState.OVER);
}
......
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