EnemyComponent.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. import { _decorator, Component, Node, Vec2, RigidBody2D } from 'cc';
  2. import { ConfigManager, EnemyConfig } from './ConfigManager';
  3. import { EnemySpawnerExample } from './EnemySpawnerExample';
  4. const { ccclass, property } = _decorator;
  5. /**
  6. * 敌人组件
  7. * 用于存储敌人的配置信息和行为逻辑
  8. */
  9. @ccclass('EnemyComponent')
  10. export class EnemyComponent extends Component {
  11. public enemyConfig: EnemyConfig = null;
  12. public spawner: EnemySpawnerExample = null;
  13. private currentHealth: number = 0;
  14. private moveTimer: number = 0;
  15. private attackTimer: number = 0;
  16. private isAlive: boolean = true;
  17. start() {
  18. if (this.enemyConfig) {
  19. this.currentHealth = this.enemyConfig.stats.health;
  20. this.setupMovement();
  21. }
  22. }
  23. update(deltaTime: number) {
  24. if (!this.isAlive || !this.enemyConfig) return;
  25. this.updateMovement(deltaTime);
  26. this.updateAttack(deltaTime);
  27. this.checkBounds();
  28. }
  29. // 设置移动行为
  30. private setupMovement() {
  31. const rigidBody = this.node.getComponent(RigidBody2D);
  32. if (rigidBody && this.enemyConfig) {
  33. const movement = this.enemyConfig.movement;
  34. const speed = this.enemyConfig.stats.speed;
  35. switch (movement.type) {
  36. case 'straight':
  37. rigidBody.linearVelocity = new Vec2(-speed, 0);
  38. break;
  39. case 'sway':
  40. rigidBody.linearVelocity = new Vec2(-speed, 0);
  41. break;
  42. default:
  43. rigidBody.linearVelocity = new Vec2(-speed, 0);
  44. break;
  45. }
  46. }
  47. }
  48. // 更新移动
  49. private updateMovement(deltaTime: number) {
  50. if (!this.enemyConfig) return;
  51. const movement = this.enemyConfig.movement;
  52. if (movement.type === 'sway') {
  53. this.moveTimer += deltaTime;
  54. const rigidBody = this.node.getComponent(RigidBody2D);
  55. if (rigidBody) {
  56. const speed = this.enemyConfig.stats.speed;
  57. const swayAmplitude = movement.swayAmplitude || 20;
  58. const swayFrequency = movement.swayFrequency || 2.0;
  59. const yVelocity = Math.sin(this.moveTimer * swayFrequency) * swayAmplitude;
  60. rigidBody.linearVelocity = new Vec2(-speed, yVelocity);
  61. }
  62. }
  63. }
  64. // 更新攻击
  65. private updateAttack(deltaTime: number) {
  66. if (!this.enemyConfig) return;
  67. this.attackTimer += deltaTime;
  68. if (this.attackTimer >= this.enemyConfig.combat.attackCooldown) {
  69. this.performAttack();
  70. this.attackTimer = 0;
  71. }
  72. }
  73. // 执行攻击
  74. private performAttack() {
  75. if (!this.enemyConfig) return;
  76. const combat = this.enemyConfig.combat;
  77. switch (combat.attackType) {
  78. case 'magic_projectile':
  79. case 'arrow_projectile':
  80. this.fireProjectile();
  81. break;
  82. case 'melee':
  83. case 'heavy_melee':
  84. this.performMeleeAttack();
  85. break;
  86. default:
  87. break;
  88. }
  89. }
  90. // 发射投射物
  91. private fireProjectile() {
  92. console.log(`${this.enemyConfig.name} 发射投射物`);
  93. // 这里应该创建子弹并发射
  94. }
  95. // 执行近战攻击
  96. private performMeleeAttack() {
  97. console.log(`${this.enemyConfig.name} 执行近战攻击`);
  98. // 这里应该检测攻击范围内的目标
  99. }
  100. // 检查边界
  101. private checkBounds() {
  102. const position = this.node.getPosition();
  103. // 如果敌人移动到屏幕左侧外,销毁它
  104. if (position.x < -900) {
  105. this.die();
  106. }
  107. }
  108. // 受到伤害
  109. public takeDamage(damage: number) {
  110. if (!this.isAlive) return;
  111. this.currentHealth -= damage;
  112. console.log(`${this.enemyConfig.name} 受到 ${damage} 点伤害,剩余血量: ${this.currentHealth}`);
  113. if (this.currentHealth <= 0) {
  114. this.die();
  115. }
  116. }
  117. // 死亡
  118. private die() {
  119. if (!this.isAlive) return;
  120. this.isAlive = false;
  121. console.log(`${this.enemyConfig.name} 死亡`);
  122. // 处理爆炸类型敌人的死亡爆炸
  123. if (this.enemyConfig.type === 'explosive') {
  124. this.explode();
  125. }
  126. // 通知生成器
  127. if (this.spawner) {
  128. this.spawner.onEnemyDeath(this.node);
  129. }
  130. }
  131. // 爆炸
  132. private explode() {
  133. console.log(`${this.enemyConfig.name} 爆炸!`);
  134. // 这里应该创建爆炸效果和伤害判定
  135. }
  136. // 获取敌人信息
  137. public getEnemyInfo(): string {
  138. if (!this.enemyConfig) return '未知敌人';
  139. return `${this.enemyConfig.name}\n` +
  140. `类型: ${this.enemyConfig.type}\n` +
  141. `血量: ${this.currentHealth}/${this.enemyConfig.stats.health}\n` +
  142. `速度: ${this.enemyConfig.stats.speed}\n` +
  143. `伤害: ${this.enemyConfig.stats.damage}`;
  144. }
  145. // 获取当前血量
  146. public getCurrentHealth(): number {
  147. return this.currentHealth;
  148. }
  149. // 获取最大血量
  150. public getMaxHealth(): number {
  151. return this.enemyConfig?.stats?.health || 100;
  152. }
  153. // 获取移动速度
  154. public getSpeed(): number {
  155. return this.enemyConfig?.stats?.speed || 50;
  156. }
  157. // 获取攻击力
  158. public getDamage(): number {
  159. return this.enemyConfig?.stats?.damage || 20;
  160. }
  161. // 检查是否有特殊能力
  162. public hasSpecialAbility(ability: string): boolean {
  163. if (!this.enemyConfig || !this.enemyConfig.specialAbilities) return false;
  164. // 使用循环代替includes方法
  165. for (let i = 0; i < this.enemyConfig.specialAbilities.length; i++) {
  166. if (this.enemyConfig.specialAbilities[i] === ability) {
  167. return true;
  168. }
  169. }
  170. return false;
  171. }
  172. }