Commit 347b2218 authored by haiyoucuv's avatar haiyoucuv

init

parent c4f50802
......@@ -185,7 +185,7 @@
"_priority": 1073741824,
"_fov": 45,
"_fovAxis": 0,
"_orthoHeight": 519.611404435058,
"_orthoHeight": 406,
"_near": 1,
"_far": 2000,
"_color": {
......@@ -478,7 +478,7 @@
"y": -180,
"z": -12.000012657215834
},
"_id": "8amC7TF0BOsZWvkBkG8lNj"
"_id": "fdvqQDUxpOLJ0rhXLRo9zZ"
},
{
"__type__": "cc.UITransform",
......@@ -500,7 +500,7 @@
"x": 0,
"y": 1
},
"_id": "d86sYWM9JIaJOQEiG9Zkmc"
"_id": "12thVjbmlEDboOejGnRXNX"
},
{
"__type__": "cc.Sprite",
......@@ -536,7 +536,7 @@
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": "94DOEnBANHLrmeSW/4N472"
"_id": "5fQlXait1Jg5w/kZjZVqhK"
},
{
"__type__": "cc.Node",
......@@ -584,7 +584,7 @@
"y": -180,
"z": -11.00000220913452
},
"_id": "9c87j9BVRAPr32XWzONFGD"
"_id": "55I6NzpHhFEpXutaDmZthD"
},
{
"__type__": "cc.UITransform",
......@@ -606,7 +606,7 @@
"x": 0,
"y": 1
},
"_id": "948HnQ4xFEAKarVyqXVWGf"
"_id": "e1j1d2y/1I/5HYVlJxtxyo"
},
{
"__type__": "cc.Sprite",
......@@ -642,7 +642,7 @@
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": "68n/iNFjFDO4HY8YutEUdd"
"_id": "b01Hm5w3hNuIuoJcuK5aw6"
},
{
"__type__": "cc.Node",
......@@ -690,7 +690,7 @@
"y": -180,
"z": -64.00000614258742
},
"_id": "2aewByPdBGMIWsCUULvHxI"
"_id": "1bGvYlT+ZFKYxAkaWqX5zq"
},
{
"__type__": "cc.UITransform",
......@@ -712,7 +712,7 @@
"x": 0,
"y": 1
},
"_id": "c3eXBJIT9HErXhNU97syaX"
"_id": "1chqaPZMlCZrjZXPt7V3aH"
},
{
"__type__": "cc.Sprite",
......@@ -748,7 +748,7 @@
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": "6bmNzil95PgJTPZlmTVv2i"
"_id": "cekF8/UiRJeKkeEUFNB8PY"
},
{
"__type__": "cc.Node",
......@@ -796,7 +796,7 @@
"y": 180,
"z": 25.99999385741257
},
"_id": "8c8+ADBsNL7Zt6M9wstupZ"
"_id": "3cjT5U+D5PH69HnyySWgGC"
},
{
"__type__": "cc.UITransform",
......@@ -818,7 +818,7 @@
"x": 0,
"y": 1
},
"_id": "6eDUuJMMZPkqGKoZybiU23"
"_id": "77jz7V3tdFWJ2QQI8SV8fA"
},
{
"__type__": "cc.Sprite",
......@@ -854,7 +854,7 @@
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": "c4MWuHUoBHsYgLOW+v/CFq"
"_id": "51J7S31vhN17XqwOzds1+A"
},
{
"__type__": "cc.UITransform",
......
......@@ -199,7 +199,7 @@
"_priority": 40000,
"_fov": 45,
"_fovAxis": 0,
"_orthoHeight": 867.8166939443535,
"_orthoHeight": 406,
"_near": 0,
"_far": 2000,
"_color": {
......@@ -2184,7 +2184,7 @@
"_priority": 50000,
"_fov": 45,
"_fovAxis": 0,
"_orthoHeight": 867.8166939443535,
"_orthoHeight": 406,
"_near": 1,
"_far": 2000,
"_color": {
......
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "ec4a8db1-4c28-4a38-9c1b-865f022880d5",
"files": [],
"subMetas": {},
"userData": {}
}
......@@ -35,10 +35,13 @@
},
{
"__id__": 20
},
{
"__id__": 22
}
],
"_prefab": {
"__id__": 22
"__id__": 24
},
"_lpos": {
"__type__": "cc.Vec3",
......@@ -465,6 +468,25 @@
"__type__": "cc.CompPrefabInfo",
"fileId": "d4nguP1hRPj6hmP9ugayLT"
},
{
"__type__": "286b3aq+hdCBZY0eOC3v+JS",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 23
},
"tag": 5,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "e299xPkRBDFpe3N9Ai7xC0"
},
{
"__type__": "cc.PrefabInfo",
"root": {
......
......@@ -480,6 +480,7 @@
"__prefab": {
"__id__": 23
},
"tag": 1,
"_id": ""
},
{
......
......@@ -79,8 +79,8 @@ export class AIDecision {
// 更自然的威胁反应
if (perception.nearestThreat) {
const distanceToThreat = Vec3.distance(myPos, perception.nearestThreat.head.getPosition());
const threatLength = perception.nearestThreat.getSnakeLen();
const myLength = perception.snake.getSnakeLen();
const threatLength = perception.nearestThreat.length;
const myLength = perception.snake.length;
// 根据体型差异调整反应
const lengthRatio = myLength / threatLength;
......@@ -125,8 +125,8 @@ export class AIDecision {
private calculateAttackScore(perception: PerceptionResult): number {
if (!perception.player?.isLife || perception.dangerLevel > 0.3) return 0;
const myLength = perception.snake.getSnakeLen();
const playerLength = perception.player.getSnakeLen();
const myLength = perception.snake.length;
const playerLength = perception.player.length;
if (myLength <= playerLength * this.LENGTH_ADVANTAGE_THRESHOLD) return 0;
......@@ -150,9 +150,9 @@ export class AIDecision {
if (!perception.assistPartner || !perception.player?.isLife ||
perception.dangerLevel > 0.3) return 0;
const combinedLength = perception.snake.getSnakeLen() +
perception.assistPartner.getSnakeLen();
const playerLength = perception.player.getSnakeLen();
const combinedLength = perception.snake.length +
perception.assistPartner.length;
const playerLength = perception.player.length;
if (combinedLength <= playerLength * 1.5) return 0;
......
......@@ -54,7 +54,7 @@ export class AIPerception {
}
private analyzeSituation(myPos: Vec3) {
const myLength = this.snake.getSnakeLen();
const myLength = this.snake.length;
let territoryControl = 0;
let threatLevel = 0;
let powerRatio = 1;
......@@ -64,7 +64,7 @@ export class AIPerception {
for (const competitor of competitors) {
const distance = Vec3.distance(myPos, competitor.head.getPosition());
const competitorLength = competitor.getSnakeLen();
const competitorLength = competitor.length;
const strengthRatio = myLength / competitorLength;
// 计算影响力衰减
......@@ -83,7 +83,7 @@ export class AIPerception {
}
// 计算整体实力比
const totalLength = competitors.reduce((sum, snake) => sum + snake.getSnakeLen(), 0);
const totalLength = competitors.reduce((sum, snake) => sum + snake.length, 0);
powerRatio = totalLength > 0 ? myLength / (totalLength / competitors.length) : 2;
// 考虑边界威胁
......@@ -163,7 +163,7 @@ export class AIPerception {
for (const threat of situation.threats) {
const distance = Vec3.distance(myPos, threat.head.getPosition());
const lengthRatio = threat.getSnakeLen() / this.snake.getSnakeLen();
const lengthRatio = threat.length / this.snake.length;
const threatScore = lengthRatio * (1 - distance / this.THREAT_DETECTION_RANGE);
if (threatScore > highestThreatScore) {
......@@ -215,7 +215,7 @@ export class AIPerception {
if (!player?.isLife || situation.threatLevel > 0.6) return null;
const myPos = this.snake.head.getPosition();
const myLength = this.snake.getSnakeLen();
const myLength = this.snake.length;
let bestPartner: AISnake = null;
let bestScore = 0;
......@@ -225,8 +225,8 @@ export class AIPerception {
const distance = Vec3.distance(myPos, competitor.head.getPosition());
if (distance > this.params.params.viewDistance * 0.7) continue;
const combinedLength = myLength + competitor.getSnakeLen();
const playerLength = player.getSnakeLen();
const combinedLength = myLength + competitor.length;
const playerLength = player.length;
if (combinedLength > playerLength * 1.3) {
const score = this.evaluateAssistPartner(competitor, player, distance);
......@@ -241,9 +241,9 @@ export class AIPerception {
}
private evaluateAssistPartner(partner: AISnake, target: Snake, distance: number): number {
const partnerLength = partner.getSnakeLen();
const targetLength = target.getSnakeLen();
const myLength = this.snake.getSnakeLen();
const partnerLength = partner.length;
const targetLength = target.length;
const myLength = this.snake.length;
let score = (partnerLength + myLength) / targetLength;
score *= (1 - distance / this.params.params.viewDistance);
......@@ -255,7 +255,7 @@ export class AIPerception {
private findNearestThreat(): Snake | null {
const myPos = this.snake.head.getPosition();
const myLength = this.snake.getSnakeLen();
const myLength = this.snake.length;
let nearestThreat = null;
let minDistance = this.params.params.viewDistance;
......@@ -266,7 +266,7 @@ export class AIPerception {
if (snake === this.snake || !snake?.isLife) continue;
// 增加长度检查的阈值,更容易将其他蛇视为威胁
if (snake.getSnakeLen() > myLength * 0.8) {
if (snake.length > myLength * 0.8) {
const headDistance = Vec3.distance(myPos, snake.head.getPosition());
if (headDistance < minDistance) {
minDistance = headDistance;
......@@ -351,7 +351,7 @@ export class AIPerception {
if (!player?.isLife) return null;
const myPos = this.snake.head.getPosition();
const myLength = this.snake.getSnakeLen();
const myLength = this.snake.length;
let bestPartner: AISnake = null;
let bestScore = 0;
......@@ -386,7 +386,7 @@ export class AIPerception {
if (threat) {
const distance = Vec3.distance(position, threat.head.getPosition());
const threatFactor = 1 - (distance / this.params.params.viewDistance);
dangerLevel += threatFactor * (threat.getSnakeLen() / this.snake.getSnakeLen());
dangerLevel += threatFactor * (threat.length / this.snake.length);
}
return math.clamp(dangerLevel, 0, 1);
......@@ -394,9 +394,9 @@ export class AIPerception {
// 辅助方法
private calculateAssistScore(partner: AISnake, target: Snake): number {
const partnerLength = partner.getSnakeLen();
const targetLength = target.getSnakeLen();
const myLength = this.snake.getSnakeLen();
const partnerLength = partner.length;
const targetLength = target.length;
const myLength = this.snake.length;
return (partnerLength + myLength) / targetLength;
}
......
......@@ -68,9 +68,9 @@ export class AISnake extends Snake {
super.onBeginEye(selfCollider, otherCollider);
if (otherCollider.group === PhysicsGroup["Body"] && otherCollider.tag != this.tag) {
// 碰到其他蛇身
this.setAngle(this.head.angle + 180);
this.head.angle += 180;
this.isFast = true;
// this.setState(AIState.ESCAPING, otherCollider.node?.parent?.getComponent(Snake));
this.setState(AIState.ESCAPING, otherCollider.node?.parent?.getComponent(Snake));
}
}
......@@ -146,7 +146,7 @@ export class AISnake extends Snake {
// 默认追击玩家
if (player && player.isLife
&& Vec3.distance(myPos, player.head.getPosition()) < this.BASE_VIEW_DISTANCE // 只在较近距离时考虑追击
&& this.getSnakeLen() > player.getSnakeLen() * 0.8 // 保持一定实力优势
&& this.length > player.length * 0.8 // 保持一定实力优势
&& math.random() < this.difficultyParams.aggressiveness * 0.6) { // 追击概率
this.setState(AIState.INTERCEPTING, player);
} else {
......@@ -176,7 +176,7 @@ export class AISnake extends Snake {
return (
distance < this.BASE_VIEW_DISTANCE * 0.5 && // 减小威胁判定距离
threat.getSnakeLen() > this.getSnakeLen() * 1.5 // 只有当对方明显比自己强时才逃跑
threat.length > this.length * 1.5 // 只有当对方明显比自己强时才逃跑
);
}
......@@ -222,7 +222,7 @@ export class AISnake extends Snake {
const distance = Vec3.distance(myPos, aiSnake.head.getPosition());
// 减小协助范围,提高协助条件
if (distance < this.ASSIST_DISTANCE * 0.7 && // 减小协助范围
this.getSnakeLen() > player.getSnakeLen() * 0.7 && // 保持一定实力才协助
this.length > player.length * 0.7 && // 保持一定实力才协助
Vec3.distance(myPos, player.head.getPosition()) < this.ASSIST_DISTANCE * 0.8) { // 确保玩家在较近范围内
return aiSnake;
}
......@@ -342,7 +342,7 @@ export class AISnake extends Snake {
const distance = Vec3.distance(myPos, playerPos);
return distance < params.interceptDistance * 0.7 && // 进一步减小拦截距离
this.getSnakeLen() > player.getSnakeLen() * 1.2 && // 提高长度要求
this.length > player.length * 1.2 && // 提高长度要求
math.random() < params.aggressiveness * 0.6 && // 降低激进程度
!this.isInDangerousPosition(playerPos); // 不在边界附近才拦截
}
......@@ -504,7 +504,7 @@ export class AISnake extends Snake {
let maxDanger = 0;
let mostDangerousSnake = null;
const myLength = this.getSnakeLen();
const myLength = this.length;
let canCounterAttack = false;
const allSnakes = [...MainGame.ins.animalNode.children, MainGame.ins.player.node]
......@@ -951,7 +951,7 @@ export class AISnake extends Snake {
private findNearestThreat(): Snake | null {
const myPos = this.head.getPosition();
const myLength = this.getSnakeLen();
const myLength = this.length;
let nearestThreat = null;
let minDistance = this.difficultyParams.viewDistance;
......@@ -964,7 +964,7 @@ export class AISnake extends Snake {
// 检查头部威胁,使用两条蛇的实际半径
const headDistance = Vec3.distance(myPos, snake.head.getPosition());
const combinedRadius = (this.radius + snake.radius) * this.SAFE_MARGIN;
if (headDistance < combinedRadius && snake.getSnakeLen() > myLength * 1.2) {
if (headDistance < combinedRadius && snake.length > myLength * 1.2) {
minDistance = headDistance;
nearestThreat = snake;
}
......
......@@ -7,11 +7,16 @@ export const Events = {
// 食物类型枚举
export enum EPropType {
FOOD = 0, // 普通食物
LUCK_BAG = 1, // 福袋
CARD_A = 2,
CARD_B = 3,
CARD_C = 4,
FOOD, // 普通食物
LUCK_BAG, // 福袋
CARD_A, // 卡片A
CARD_B, // 卡片B
CARD_C, // 卡片C
MAGNET, // 磁铁
SPEED, // 加速
SHIELD, // 护盾
GROW, // 加长
DOUBLE_EXP, // 双倍经验
}
ccenum(EPropType);
......
......@@ -15,6 +15,7 @@ export class FastBtn extends Component {
// 设置是否处于加速状态
set isFast(value: boolean) {
this._isFast = value;
console.log(this.node, this.uuid);
this.node.emit("fast", value);
}
......@@ -23,12 +24,18 @@ export class FastBtn extends Component {
sp: Sprite = null;
onLoad() {
// 注册触摸事件
this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
this.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
}
onDestroy() {
this.node.targetOff(this);
this.node.off(Node.EventType.TOUCH_START, this.onTouchStart, this);
this.node.off(Node.EventType.TOUCH_END, this.onTouchEnd, this);
this.node.off(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
}
// 按下时的处理
onTouchStart() {
this.isFast = true;
......
......@@ -99,6 +99,7 @@ export class MainGame extends Scene {
MainGame._ins = null;
}
director.off(Events.Death, this.playerDeath, this);
this.player.node.destroy();
clearAllPool();
}
......
......@@ -11,6 +11,7 @@ import { Global } from "db://assets/Scripts/Scenes/MainGame/Global";
import { executePreFrame, getItemGenerator } from "db://assets/Scripts/Utils/ExecutePreFrame";
import { Food } from "../Props/Food";
import { foodPool } from "./CommonPool";
import { PropBase } from "../Props/PropBase";
const { ccclass, property } = _decorator;
......
......@@ -59,7 +59,7 @@ export class Player extends Snake {
onDestroy() {
input.off(Input.EventType.KEY_DOWN, this.onKeyDown, this);
input.off(Input.EventType.KEY_UP, this.onKeyUp, this);
this.fastBtn.node.off("fast", this.onFast, this);
this.fastBtn?.node?.off("fast", this.onFast, this);
}
onFast(isFast: boolean) {
......@@ -124,7 +124,7 @@ export class Player extends Snake {
}
onUpdate(dt: number) {
this.setAngle((360 - this.joystick.angle) % 360);
this.head.angle = (360 - this.joystick.angle) % 360;
super.onUpdate(dt);
}
......
......@@ -29,9 +29,9 @@ export class Food extends PropBase {
this.energy = energy;
}
beEaten=(target: Snake) => {
beEaten = (target: Snake) => {
target.addEnergy(this.energy);
}
};
recycle() {
super.recycle();
......
import { _decorator } from "cc";
import { PropBase } from "./PropBase";
import { Snake } from "db://assets/Scripts/Scenes/MainGame/Snake";
import { CardManager } from "../Manager/CardManager";
const { ccclass, property } = _decorator;
@ccclass("Magnet")
export class Magnet extends PropBase {
onLoad() {
super.onLoad();
}
beEaten = (target: Snake) => {
target.useMagnet();
};
recycle() {
super.recycle();
CardManager.ins.check();
this.node.removeFromParent();
this.node.destroy();
// propPool.put(this.node);
}
}
\ No newline at end of file
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "286b36aa-fa17-4205-9634-78e0b7bfe252",
"files": [],
"subMetas": {},
"userData": {}
}
......@@ -8,7 +8,7 @@ const { ccclass, property, requireComponent } = _decorator;
@requireComponent(RigidBody2D)
export class PropBase extends Component {
canEaten: boolean = false;
canEaten: boolean = true;
@property({ type: EPropType })
tag: ECard = EPropType.CARD_A;
......
......@@ -7,10 +7,10 @@ import {
PhysicsGroup,
Prefab,
Sprite, SpriteAtlas,
SpriteFrame,
SpriteFrame, Tween,
tween, UITransform,
v2,
v3,
v3, Vec2,
Vec3,
} from "cc";
import { Global, SkinName } from "./Global";
......@@ -111,6 +111,7 @@ export class Snake extends Component {
onDestroy() {
}
// 初始化方法
public async init(config: IInitConfig) {
......@@ -210,17 +211,19 @@ export class Snake extends Component {
if (otherCollider.group === PhysicsGroup["Prop"]) {
const propTs = otherCollider.getComponent(PropBase);
if (propTs && !propTs.canEaten) {
if (propTs && propTs.canEaten) {
propTs.canEaten = false;
// 食物吃掉的动画
Tween.stopAllByTarget(otherCollider.node);
tween(otherCollider.node)
.to(0.3, {
position: this.head.getPosition(),
scale: v3(0, 0)
})
.call(() => {
if (!this.isLife) return;
propTs.beEaten(this);
if (this.isLife) {
propTs.beEaten(this);
}
propTs.recycle();
})
.start();
......@@ -240,9 +243,12 @@ export class Snake extends Component {
}
// 能量与成长
// 上次生长富余的能量
private lastRemaining = 0;
/**
* 加能量
*/
addEnergy(value: number) {
this.energy += value;
const growthThreshold = Math.floor(4 * this.scale);
......@@ -263,7 +269,9 @@ export class Snake extends Component {
// this.speed = 600 * this.scale;
}
// 蛇身体生长
/**
* 生长
*/
private grow() {
if (!this.isValid) return;
......@@ -298,12 +306,6 @@ export class Snake extends Component {
this.bodyArr.splice(len, 0, newBody);
}
setAngle(angle: number) {
if (this.isLife) {
this.head.angle = angle;
}
}
isFast = false;
positions: IVec2Like[] = []; // 存储历史位置点
private readonly HISTORY_LENGTH = 10; // 增加历史点数量
......@@ -335,8 +337,11 @@ export class Snake extends Component {
const bodyLen = this.bodyArr.length;
const headAngle = this.head.angle;
// 更新头部位置
const newHeadPos = this.getNewPos(headAngle, dt * this.speed, this.head.position);
const newHeadPos = this.getVelocity(headAngle)
.multiplyScalar(dt * this.speed)
.add2f(this.head.position.x, this.head.position.y);
this.head.setPosition(newHeadPos.x, newHeadPos.y);
const flipY = headAngle > 90 && headAngle < 270;
......@@ -400,6 +405,9 @@ export class Snake extends Component {
}
/**
* 加速特效
*/
updateAccEffect() {
if (!this.isFast) {
this.accEffectNode.active = false;
......@@ -431,12 +439,10 @@ export class Snake extends Component {
}
getSnakeLen() {
return this.bodyArr.length;
}
// 死亡处理
public death() {
/**
* 死亡
*/
death() {
if (!this.isLife) return;
this.positions.length = 0;
......@@ -444,12 +450,6 @@ export class Snake extends Component {
this.node.removeFromParent();
this.clearInvincible();
const foodArr = this.recycleBody();
FoodManger.ins.initFoods(foodArr);
}
recycleBody() {
const len = this.bodyArr.length;
const foodArr = this.bodyArr.map((body) => {
body.removeFromParent();
......@@ -462,22 +462,54 @@ export class Snake extends Component {
};
});
this.bodyArr.length = 0;
return foodArr;
}
protected getNewPos(angle: number, dt: number, currentPos: Vec3): IVec2Like {
const direction = this.getVelocity(angle).multiplyScalar(dt);
return {
x: currentPos.x + direction.x,
y: currentPos.y + direction.y,
};
FoodManger.ins.initFoods(foodArr);
}
/**
* 获得方向
*/
getVelocity(angle = this.head.angle) {
const radian = angle / 180 * Math.PI;
return v2(Math.cos(radian), Math.sin(radian));
}
/****************************** 磁铁 ******************************/
useMagnet() {
this.clearMagnet();
this.schedule(() => {
this.flushMagnet();
}, 0.5, 3);
}
flushMagnet() {
FoodManger.ins.node.children.forEach((child) => {
const propTs = child.getComponent(PropBase);
if (propTs.canEaten) {
propTs.canEaten = false;
Tween.stopAllByTarget(child);
tween(child)
.to(0.5, {
position: this.head.getPosition(),
})
.call(() => {
if (this.isLife) {
propTs.beEaten(this);
}
propTs.recycle();
})
.start();
}
});
}
clearMagnet() {
this.unschedule(this.flushMagnet);
}
/****************************** 护盾 ******************************/
/**
* 护盾时间
* 假如有两个护盾同时生效,则取时间大的,正是因为这样,才设计成数字
......
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