| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- import { _decorator, Component, Node, ProgressBar, Label, Vec3, find, UITransform, Collider2D, Contact2DType, IPhysics2DContact } from 'cc';
- const { ccclass, property } = _decorator;
- // 前向声明EnemyController接口,避免循环引用
- interface EnemyControllerType {
- gameBounds: {
- left: number;
- right: number;
- top: number;
- bottom: number;
- };
- damageWall: (damage: number) => void;
- }
- // 敌人状态枚举
- enum EnemyState {
- MOVING, // 移动中
- ATTACKING // 攻击中
- }
- // 单个敌人实例的组件
- @ccclass('EnemyInstance')
- export class EnemyInstance extends Component {
- // 敌人属性
- public health: number = 30;
- public maxHealth: number = 30;
- public speed: number = 50;
- public attackPower: number = 10;
-
- // 移动属性
- public movingDirection: number = 1; // 1: 向右, -1: 向左
- public targetY: number = 0; // 目标Y位置
- public changeDirectionTime: number = 0; // 下次改变方向的时间
-
- // 攻击属性
- public attackInterval: number = 2; // 攻击间隔(秒)
- private attackTimer: number = 0;
-
- // 对控制器的引用
- public controller: EnemyControllerType = null;
-
- // 敌人当前状态
- private state: EnemyState = EnemyState.MOVING;
-
- // 游戏区域中心
- private gameAreaCenter: Vec3 = new Vec3();
-
- // 碰撞的墙体
- private collidedWall: Node = null;
- start() {
- // 初始化敌人
- this.initializeEnemy();
- }
-
- // 初始化敌人
- private initializeEnemy() {
- this.health = this.maxHealth;
- this.state = EnemyState.MOVING;
- this.speed = 50; // 默认速度
- this.attackPower = 10; // 默认攻击力
- this.attackInterval = 2.0; // 默认攻击间隔
- this.attackTimer = 0;
-
- // 计算游戏区域中心
- this.calculateGameAreaCenter();
-
- // 初始化碰撞检测
- this.setupCollider();
- }
-
- // 设置碰撞器
- setupCollider() {
- // 检查节点是否有碰撞器
- let collider = this.node.getComponent(Collider2D);
- if (!collider) {
- return;
- }
-
- // 设置碰撞事件监听
- collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
- }
-
- // 碰撞开始事件
- onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
- const nodeName = otherCollider.node.name;
-
- // 如果碰到墙体,停止移动并开始攻击
- if (nodeName.includes('Wall') || nodeName.includes('wall') || nodeName.includes('Fence') || nodeName.includes('Jiguang')) {
- this.state = EnemyState.ATTACKING;
- this.attackTimer = 0; // 立即开始攻击
- }
- }
-
- // 获取节点路径
- getNodePath(node: Node): string {
- let path = node.name;
- let current = node;
-
- while (current.parent) {
- current = current.parent;
- path = current.name + '/' + path;
- }
-
- return path;
- }
- // 计算游戏区域中心
- private calculateGameAreaCenter() {
- const gameArea = find('Canvas/GameLevelUI/GameArea');
- if (gameArea) {
- this.gameAreaCenter = gameArea.worldPosition;
- }
- }
- // 更新血量显示
- updateHealthDisplay() {
- // 更新血条
- const hpBar = this.node.getChildByName('HPBar');
- if (hpBar) {
- const progressBar = hpBar.getComponent(ProgressBar);
- if (progressBar) {
- progressBar.progress = this.health / this.maxHealth;
- }
- }
-
- // 更新血量数字
- const hpLabel = this.node.getChildByName('HPLabel');
- if (hpLabel) {
- const label = hpLabel.getComponent(Label);
- if (label) {
- label.string = this.health.toString();
- }
- }
- }
- // 受到伤害
- takeDamage(damage: number) {
- this.health -= damage;
-
- // 更新血量显示
- this.updateHealthDisplay();
- }
- update(deltaTime: number) {
- if (this.state === EnemyState.MOVING) {
- this.updateMovement(deltaTime);
- } else if (this.state === EnemyState.ATTACKING) {
- this.updateAttack(deltaTime);
- }
- }
-
- // 更新移动逻辑
- private updateMovement(deltaTime: number) {
- // 检查是否接近游戏区域边界
- if (this.checkNearGameArea()) {
- // 如果接近游戏区域,停止移动并开始攻击
- this.state = EnemyState.ATTACKING;
- this.attackTimer = 0; // 立即开始攻击
- return;
- }
-
- // 继续移动
- this.moveTowardsTarget(deltaTime);
- }
- // 检查是否接近游戏区域
- private checkNearGameArea(): boolean {
- const currentPos = this.node.worldPosition;
-
- // 获取游戏区域边界
- const gameArea = find('Canvas/GameLevelUI/GameArea');
- if (!gameArea) return false;
-
- const uiTransform = gameArea.getComponent(UITransform);
- if (!uiTransform) return false;
-
- const gameAreaPos = gameArea.worldPosition;
- const halfWidth = uiTransform.width / 2;
- const halfHeight = uiTransform.height / 2;
-
- const bounds = {
- left: gameAreaPos.x - halfWidth,
- right: gameAreaPos.x + halfWidth,
- top: gameAreaPos.y + halfHeight,
- bottom: gameAreaPos.y - halfHeight
- };
-
- // 检查是否在游戏区域内或非常接近
- const safeDistance = 50; // 安全距离
-
- const isInside = currentPos.x >= bounds.left - safeDistance &&
- currentPos.x <= bounds.right + safeDistance &&
- currentPos.y >= bounds.bottom - safeDistance &&
- currentPos.y <= bounds.top + safeDistance;
-
- if (isInside) {
- return true;
- }
-
- return false;
- }
- // 移动到目标位置
- private moveTowardsTarget(deltaTime: number) {
- const currentPos = this.node.position;
-
- // 简单的向中心移动
- const targetPos = new Vec3(0, 0, 0); // 移动到中心
- const direction = targetPos.subtract(currentPos).normalize();
-
- // 应用移动
- const moveDistance = this.speed * deltaTime;
- const newPos = currentPos.add(direction.multiplyScalar(moveDistance));
- this.node.position = newPos;
- }
- // 更新攻击逻辑
- private updateAttack(deltaTime: number) {
- this.attackTimer -= deltaTime;
-
- if (this.attackTimer <= 0) {
- // 执行攻击
- this.performAttack();
-
- // 重置攻击计时器
- this.attackTimer = this.attackInterval;
- }
- }
- // 执行攻击
- private performAttack() {
- if (!this.controller) {
- return;
- }
-
- // 对墙体造成伤害
- this.controller.damageWall(this.attackPower);
- }
- }
|