Player.ts 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. import { _decorator, Node, SkeletalAnimation, Tween, Vec3 } from 'cc';
  2. import { BaseExp } from '../core/base/BaseExp';
  3. import { PoolManager } from '../core/manager/PoolManager';
  4. import { uiMgr } from '../core/manager/UIManager';
  5. import { Constants } from '../data/Constants';
  6. import { userIns } from '../data/UserData';
  7. import { autoBind } from '../extend/AutoBind';
  8. import { GunBase } from '../items/base/GunBase';
  9. import { GunfightShootUI } from '../ui/GunfightShootUI';
  10. import { ResUtil } from '../utils/ResUtil';
  11. import { Game } from './Game';
  12. import MsgHints from '../utils/MsgHints';
  13. import { PlayerCamera } from './PlayerCamera';
  14. import { audioMgr } from '../core/manager/AudioManager';
  15. import { Utils } from '../utils/Utils';
  16. const { ccclass, property } = _decorator;
  17. //玩家动作类型
  18. export enum PAnimType {
  19. idle = "idle",//idle 待机状态
  20. die = "die",//die 死亡状态
  21. reload = "reload",//reload 换弹夹状态
  22. }
  23. @ccclass('Player')
  24. export class Player extends BaseExp {
  25. @autoBind({type: Node,tooltip: "创建枪的位置"})
  26. public gun_pos: Node = null!;
  27. @autoBind({type: Node,tooltip: "玩家头的位置"})
  28. public head: Node = null!;
  29. @autoBind({type: Node,tooltip: "敌人埋伏点"})
  30. public ambush: Node = null!;
  31. @autoBind({type: Node,tooltip: "玩家身子的位置"})
  32. public body: Node = null!;
  33. @autoBind({type: SkeletalAnimation,tooltip: "玩家人物动画节点"})
  34. public player_skeletal: SkeletalAnimation = null!;
  35. @autoBind({type: PlayerCamera,tooltip: "玩家摄像机抖动控制"})
  36. public mainCamera: PlayerCamera = null!;
  37. /**玩家的位置节点*/
  38. public playPosNodes: Node[] = []!;
  39. /**玩家当前血量*/
  40. public curHP: number = 0;
  41. /**玩家是否死亡*/
  42. public isDead: boolean = false;
  43. /**玩家拥有的枪*/
  44. public gun: GunBase = null;
  45. //是否去设置gunfightShootUI的基础信息
  46. public isCutShoot:boolean = false;
  47. //射击ui类
  48. private _shootUI: GunfightShootUI | null = null;
  49. //懒获取射击界面
  50. public get shootUI(): GunfightShootUI {
  51. if (!this._shootUI) {
  52. this._shootUI = uiMgr.getPageComponent(Constants.popUIs.gunfightShootUI);
  53. }
  54. return this._shootUI!;
  55. }
  56. //是否是换弹夹状态
  57. public isReloadMagazine: boolean = false;
  58. //玩家打敌人爆头的个数
  59. public headShotNum:number = 0;
  60. //玩家数据改为私有属性
  61. private _pData: any = null;
  62. public get pData(): any {
  63. if (!this._pData) {
  64. this._pData = userIns.getCurUseGun();
  65. }
  66. return this._pData;
  67. }
  68. public set pData(value: any) {
  69. this._pData = value;
  70. }
  71. onEnable() {
  72. //隐藏玩家设置的位置坐标节点
  73. (this.playPosNodes = this.node.parent.getChildByName('player_points').children)
  74. .forEach(e => e.active = false);
  75. //隐藏的枪的位置节点
  76. this.gun_pos.children.forEach(e => e.active = false);
  77. //创建玩家拥有的枪
  78. this.loadGunName(this.pData.prb_name);
  79. }
  80. /**
  81. * 加载枪
  82. * @param name 枪的名字
  83. * @param isCut 是否是切换枪
  84. */
  85. public loadGunName(name: string = this.pData.prb_name,isCut: boolean = false){
  86. if(Utils.isNull(name))return;
  87. //玩家待机状态
  88. this.player_skeletal.play(PAnimType.idle);
  89. this.pData = userIns.getCurUseGun();
  90. this.curHP = this.pData.hp;
  91. if(!isCut && this.gun)return;
  92. if(isCut && this.gun){
  93. PoolManager.putNode(this.gun.node);
  94. }
  95. ResUtil.loadRes(`player/${name}`).then((gunNode: Node) => {
  96. if(!gunNode)return;
  97. this.isCutShoot = true;
  98. gunNode.parent = this.node;
  99. this.gun = gunNode.getComponent(GunBase);
  100. let pos_ui: Node = this.gun_pos.children.find(e=>e.name == this.pData.prb_name);
  101. if(!pos_ui){
  102. MsgHints.show("未找到武器没有对应的位置节点");
  103. }
  104. pos_ui = pos_ui || this.gun_pos;
  105. if(pos_ui){
  106. gunNode.worldPosition = pos_ui.worldPosition.clone();
  107. gunNode.eulerAngles = pos_ui.parent.eulerAngles.clone();
  108. gunNode.scale = pos_ui.scale.clone();
  109. }
  110. this.gun.init(this.pData,this,()=>{},this.reloadMagazine.bind(this));
  111. });
  112. }
  113. /**
  114. * 更换弹匣
  115. */
  116. public reloadMagazine(data:any){
  117. if(!data || this.isReloadMagazine)return;
  118. this.isReloadMagazine = true;
  119. //基准速度值 基准时间3秒
  120. const baseSpeed = 450;
  121. const baseTime = 3;
  122. //时间 = (基准速度 / 当前速度) * 基准时间
  123. let time: number = (baseSpeed / data.reloadingSpeed) * baseTime;
  124. //换弹匣动画
  125. ResUtil.playSkeletalAnim(this.player_skeletal,PAnimType.reload,time);
  126. this.shootUI.reloadMagazineing(time,()=>{
  127. this.isReloadMagazine = false;
  128. this.shootUI.gunDataUI();
  129. this.player_skeletal?.play(PAnimType.idle);
  130. });
  131. }
  132. /**
  133. * 重置
  134. */
  135. public restart(){
  136. Game.I.isGameOver = Game.I.isPause = false;
  137. this._pData = userIns.getCurUseGun();
  138. this.isDead = false;
  139. this.isReloadMagazine = false;
  140. if(this.shootUI){
  141. this.shootUI.hpProgressBar.progress = 1;
  142. Tween.stopAllByTarget(this.shootUI.injury_blood);
  143. this.shootUI.injury_blood.active = false;
  144. }
  145. this.loadGunName();
  146. this.player_skeletal.unscheduleAllCallbacks();
  147. this.player_skeletal.stop();
  148. this.player_skeletal.node.active = true;
  149. this.player_skeletal.play(PAnimType.idle);
  150. }
  151. /**
  152. * 玩家发射子弹
  153. */
  154. public shoot() {
  155. if(!this.gun
  156. || this.isReloadMagazine)return;
  157. this.gun.fire();
  158. this.shootUI.crossHairStability();
  159. Game.I.player.mainCamera.shake(0.2,0,0.1);
  160. }
  161. /**
  162. * 随机切枪
  163. */
  164. public randomCutGun(){
  165. if(this.isReloadMagazine){
  166. MsgHints.show("The gun is reloading, please wait!");
  167. return;
  168. }
  169. let guns = userIns.data.guns;
  170. if(guns.length > 1){
  171. let idx : number = guns.findIndex(e=>e.id == this.pData.id);
  172. let next:number = (idx + 1) % guns.length;
  173. const cutGun:any = guns[next];
  174. userIns.changeGun(cutGun.id);
  175. this.loadGunName(cutGun.prb_name,true);
  176. }
  177. }
  178. /**
  179. * 移除枪回收武器
  180. */
  181. public removeGun(){
  182. if(!this.gun)return;
  183. this.gun.endFire();
  184. PoolManager.putNode(this.gun.node);
  185. this.gun = null;
  186. }
  187. /**
  188. * 玩家扣掉血
  189. * @param hp 血
  190. * @param eData 敌人数据
  191. */
  192. public subHP(hp: number,eData:any){
  193. if(Game.I.isPause
  194. ||Game.I.isGameOver
  195. ||this.isDead
  196. ||hp <= 0){
  197. return;
  198. }
  199. this.curHP -= hp;
  200. this.curHP = this.curHP < 0 ? 0 : this.curHP;
  201. //设置血条
  202. const progress:number = this.curHP / this.pData.hp;
  203. this.shootUI.playerHurtTwinkle(progress);
  204. //敌人死亡
  205. if(this.curHP <= 0 && !this.isDead){
  206. Game.I.isGameOver = true;
  207. audioMgr.playOneShot(Constants.audios.loss);
  208. uiMgr.show(Constants.popUIs.settleUI,[{
  209. isWin: false,
  210. headShotNum: this.headShotNum,
  211. cb: ()=>{}
  212. }]);
  213. this.isDead = true;
  214. this.recycle();
  215. ResUtil.playSkeletalAnim(this.player_skeletal,PAnimType.die,1.5,()=>{
  216. this.player_skeletal.stop();
  217. this.player_skeletal.node.active = false;
  218. });
  219. }
  220. }
  221. /**
  222. * 根据关卡设置玩家的位置
  223. */
  224. public setPlayerPos(){
  225. if(!this.pData)return;
  226. let length:number = this.playPosNodes.length;
  227. const data = userIns.getCurLevelData();
  228. const safeIndex = Math.min(data.point -1, length - 1);
  229. const n: Node = this.playPosNodes[safeIndex];
  230. this.node.worldPosition = n.worldPosition.clone();
  231. this.node.eulerAngles = n.eulerAngles.clone();
  232. }
  233. /**
  234. * 回收
  235. */
  236. public recycle(){
  237. this.removeGun();
  238. this.isReloadMagazine = false;
  239. this.headShotNum = 0;
  240. }
  241. /**
  242. * 设置枪的数据
  243. */
  244. protected update(dt: number): void {
  245. if(this.isCutShoot){
  246. //设置玩家枪的信息
  247. if(this.shootUI && this.pData){
  248. this.shootUI.gunDataUI();
  249. this.isCutShoot = false;
  250. //初始信息记录
  251. this.shootUI.originalInitial();
  252. }
  253. }
  254. }
  255. }