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