HuaweiDemo/assets/script/core/fighter.ts

588 lines
21 KiB
TypeScript
Raw Permalink Normal View History

2023-11-07 01:17:57 +00:00
import { _decorator, Component, Node, SkinningModelComponent, ParticleSystemComponent, Vec3, Mat4, log } from 'cc';
import { ClientEvent }from '../framework/clientEvent';
import { AudioManager } from '../framework/audioManager';
import { PoolManager} from '../framework/poolManager';
import { ResourceUtil } from '../framework/resourceUtil';
import { Constant } from '../framework/constant';
import { DisplayManager } from './displayManager';
import { FighterModel } from './fighterModel';
import { Player, PropType} from './gameState';
import { EffectManager } from '../framework/effectManager';
import { Util } from '../framework/util';
import { PlayerData } from '../framework/playerData';
import { LogicManager } from './logicManager';
import { GobeUtil } from './gobeUtil';
const { ccclass, property } = _decorator;
/**
* Predefined variables
* Name = Player
* DateTime = Tue Sep 07 2021 12:38:14 GMT+0800 ()
* Author = yanli.huang
* FileBasename = player.ts
* FileBasenameNoExtension = player
* URL = db://assets/script/core/player.ts
* ManualUrl = https://docs.cocos.com/creator/3.3/manual/zh/
*
*/
enum PlayType {
null,
idle,
run,
attack,
is_attack,
game_over,
}
let vec_0:Vec3 = new Vec3();
let vec_1:Vec3 = new Vec3();
let vec_2:Vec3 = new Vec3();
@ccclass('Fighter')
export class Fighter extends Component {
@property(Node)
public ndSocketCrown: Node = null!;//皇冠挂载节点
@property(SkinningModelComponent)
public model: SkinningModelComponent = null!;
@property(FighterModel)
public fighterModel: FighterModel = null!;
@property(Node)
public ndSocketWeapon: Node = null!;//武器挂载节点
private _aiPosNode:Node = null!; // ai点
public playerState: Player = null!;//玩家状态信息
private _ndCrown: Node = null!;//皇冠
private _ndHammer: Node = null!;//锤子
private _isPlayRunningEffect: boolean = false;
private _runEffect: Node = null!;
private _score: number = 0;
private _mat:Mat4 = new Mat4();
private _ndHammerTrial: Node = null!;//挂在锤子上的拖尾特效节点
private _parent: DisplayManager = null!;
private vec3_pos: Vec3 = new Vec3();
private vec3_angle: Vec3 = new Vec3();
private vec3_lastPos: Vec3 = new Vec3();
private vec3_pos_1: Vec3 = new Vec3();
private _moveIndex:number = 0;
private _playType:PlayType = PlayType.null;
public init(parent: DisplayManager, aiPosNode:Node) {
this._aiPosNode = aiPosNode;
this._parent = parent;
this._isPlayRunningEffect = false;
this._runEffect = null!;
this._score = 0;
this._aiPosIndex = 0;
this.playIdle();
if (!this._ndCrown) {
ResourceUtil.loadModelRes("crown/crown").then((pf: any)=>{
this._ndCrown = PoolManager.instance.getNode(pf, this.ndSocketCrown);
this.ndSocketCrown.active = false;
})
} else {
this.ndSocketCrown.active = false;
}
if (!this._ndHammer) {
ResourceUtil.loadModelRes("hammer/hammerProp").then((pf: any)=>{
this._ndHammer = PoolManager.instance.getNode(pf, this.ndSocketWeapon);
this._ndHammer.setPosition(0, 0, 0);
this.ndSocketWeapon.active = false;
this._hideHammerTrial();
})
} else {
this.ndSocketWeapon.active = false;
this._hideHammerTrial();
}
this.vec3_pos.set(0, 0, 0);
this.vec3_angle.set(0, 0, 0);
this.vec3_lastPos.set(0, 0, 0);
this.vec3_pos_1.set(0, 0, 0);
this._lastIndex = 0;
vec_0.set(50, 0, 0);
var index = Math.floor(Math.random() * Constant.AI_POS_INDEX[this._lastIndex].length);
this._nextIndex = Constant.AI_POS_INDEX[this._lastIndex][index];
vec_1.set(this._aiPosNode.children[this._nextIndex - 1].position);
var dis:number = Vec3.distance(vec_0, vec_1);
this._posPer = Constant.AI_SPEED / dis;
// console.log("1", this._nextIndex);
}
/**
*
*
* @private
* @memberof Fighter
*/
private _hideHammerTrial () {
if (!this._ndHammer) {
return;
}
if (!this._ndHammerTrial) {
this._ndHammerTrial = this._ndHammer.getChildByName("trail01") as Node;
}
if (this._ndHammerTrial && this._ndHammerTrial.active) {
this._ndHammerTrial.active = false;
}
}
/**
*
*/
public playRun() {
if(this._playType == PlayType.run){
return;
}
this._playType = PlayType.run;
if (!this.fighterModel.isRunning) {
this._isPlayRunningEffect = true;
//播放移动粒子特效
if (this._runEffect) {
this._runEffect.active = true;
let particle = this._runEffect.getComponentInChildren(ParticleSystemComponent) as ParticleSystemComponent;
particle.loop = true;
particle.clear();
particle.stop();
particle.play();
} else {
ResourceUtil.loadEffectRes("runningSmoke").then((pf: any)=>{
if (!this.fighterModel.isRunning) {
return; //已经没在跑了
}
this._runEffect = PoolManager.instance.getNode(pf, this.node);
this._runEffect.active = true;
let particle = this._runEffect.getComponentInChildren(ParticleSystemComponent) as ParticleSystemComponent;
particle.loop = true;
particle.clear();
particle.stop();
particle.play();
})
}
}
if (this.ndSocketWeapon.active) {
this.fighterModel.playAni(Constant.ANI_TYPE.RUN_1, true, false, ()=>{}, 1);
this._hideHammerTrial();
} else {
this.fighterModel.playAni(Constant.ANI_TYPE.RUN, true, false, ()=>{}, 1);
}
}
/**
*
* @param value
*/
public playAttack(value:Player, isActick:boolean) {
if(this._playType == PlayType.attack){
return;
}
this._playType = PlayType.attack;
value.hammerCount = 0;
value.attackPropType = PropType.NULL;
//使用锤子
AudioManager.instance.playSound(Constant.AUDIO_NAME.HIT);
this._ndHammerTrial.active = true;
EffectManager.instance.playTrail(this._ndHammerTrial);
this.fighterModel.isActick = isActick;
this.fighterModel.playAni(Constant.ANI_TYPE.ATTACK, false, false, ()=>{
this._hideHammerTrial();
this.ndSocketWeapon.active = false; //武器消失
this.playIdle();
}, 1);
}
/**
*
*/
public playIdle() {
if(this._playType == PlayType.idle){
return;
}
this._playType = PlayType.idle;
this.fighterModel.playAni(Constant.ANI_TYPE.IDLE, true, false, ()=>{}, 2);
if (this._runEffect && this._isPlayRunningEffect) {
let particle2 = this._runEffect.getComponentInChildren(ParticleSystemComponent) as ParticleSystemComponent;
particle2.loop = false;
}
this._isPlayRunningEffect = false;
}
/**
*
*/
public playMove(logicManager: LogicManager, dt:number, otherNode:Node, player:Player){
if(!(this._playType == PlayType.idle || this._playType == PlayType.run)){
return;
}
if(player.hammerCount > 0){
var distance:number = Vec3.distance(this.vec3_lastPos, otherNode.position);
if(distance < 5){
Vec3.subtract(this.vec3_pos_1, this.node.position, otherNode.position);
var angleY:number = Math.atan(this.vec3_pos_1.z/this.vec3_pos_1.x) * 180 / Math.PI;
if(this.vec3_pos_1.x < 0){
if(this.vec3_pos_1.z < 0){
angleY = 180 - angleY;
}else {
angleY = (angleY + 180) * -1;
}
}else{
angleY *= -1;
}
angleY-=90;
GobeUtil.instance.sendFrame({'A': Constant.ACTION.HIT, 'V': angleY});
this.vec3_angle.y = angleY;
this.node.eulerAngles = this.vec3_angle;
this.playAttack(player, true);
return;
}
}
var leftY:number = PlayerData.instance.getEasyTouchInfo(Constant.EASY_TOUCH.TOUCH_LEFT_Y);
var leftX:number = PlayerData.instance.getEasyTouchInfo(Constant.EASY_TOUCH.TOUCH_LEFT_X);
if (leftY == 0 && leftX == 0) {
if(this._playType != PlayType.idle){
this.vec3_angle.set(this.node.eulerAngles.clone());
this.vec3_lastPos.set(this.node.position.clone());
GobeUtil.instance.sendFrame({'A': Constant.ACTION.MOVE, 'V': this.vec3_angle.y, 'X': this.vec3_lastPos.x, 'Z': this.vec3_lastPos.z, 'MX': leftX, 'MY': leftY});
}
this.playIdle();
return;
}
this.playRun();
var angleY:number = Math.atan(leftX / leftY) * 180 / Math.PI;
if(leftY < 0){
angleY -= 180;
}
this.vec3_angle.y = 180 - angleY;
this.node.eulerAngles = this.vec3_angle;
this.vec3_lastPos.set(this.node.position.clone());
this.vec3_pos.set(this.node.position.clone());
var speed:number = 1 - (this.node.scale.x - 1) * Constant.MIN_SPEED_PERCENT;
this.vec3_pos.x += leftX * 0.2 * dt * 60 * speed;
this.vec3_pos.z -= leftY * 0.2 * dt * 60 * speed;
this._mat.m12 = this.vec3_pos.x;
this._mat.m13 = this.vec3_pos.y;
this._mat.m14 = this.vec3_lastPos.z;
if (!logicManager.playerLogic.intersectWithObstacle(this._mat, this.node.rotation, this.node.scale, this.node.parent?.scale)) {
this.vec3_lastPos.x = this.vec3_pos.x;
}
this._mat.m12 = this.vec3_lastPos.x;
this._mat.m13 = this.vec3_pos.y;
this._mat.m14 = this.vec3_pos.z;
if (!logicManager.playerLogic.intersectWithObstacle(this._mat, this.node.rotation, this.node.scale, this.node.parent?.scale)) {
this.vec3_lastPos.z = this.vec3_pos.z;
}
if(this._moveIndex == 0){
GobeUtil.instance.sendFrame({'A': Constant.ACTION.MOVE, 'V': this.vec3_angle.y, 'X': this.vec3_lastPos.x, 'Z': this.vec3_lastPos.z, 'MX': leftX, 'MY': leftY});
}
this.node.setPosition(this.vec3_lastPos);
this._moveIndex ++;
if(this._moveIndex > 4){
this._moveIndex = 0;
}
}
private _aiPosIndex:number = 0;
private _nextIndex:number = 0;
private _lastIndex:number = 0;
private _posPer:number = 0;
/**
*
*/
public playMoveAi(logicManager: LogicManager, dt:number, otherNode:Node, player:Player){
if(!(this._playType == PlayType.idle || this._playType == PlayType.run)){
return;
}
if(player.hammerCount > 0){
var distance:number = Vec3.distance(this.vec3_lastPos, otherNode.position);
if(distance < 5){
Vec3.subtract(this.vec3_pos_1, this.node.position, otherNode.position);
var angleY:number = Math.atan(this.vec3_pos_1.z/this.vec3_pos_1.x) * 180 / Math.PI;
if(this.vec3_pos_1.x < 0){
if(this.vec3_pos_1.z < 0){
angleY = 180 - angleY;
}else {
angleY = (angleY + 180) * -1;
}
}else{
angleY *= -1;
}
angleY-=90;
GobeUtil.instance.sendFrame({'A': Constant.ACTION.HIT, 'V': angleY, 'AI': 1});
this.vec3_angle.y = angleY;
this.node.eulerAngles = this.vec3_angle;
this.playAttack(player, true);
return;
}
}
this.playRun();
var speed:number = 1 - (this.node.scale.x - 1) * Constant.MIN_SPEED_PERCENT;
this._aiPosIndex += this._posPer * speed;
if(this._aiPosIndex >= 1){
vec_0.set(vec_1);
var nextPos:number[] = [];
for(var index:number = 0; index < Constant.AI_POS_INDEX[this._nextIndex].length; index ++){
if(Constant.AI_POS_INDEX[this._nextIndex][index] != this._lastIndex){
nextPos.push(Constant.AI_POS_INDEX[this._nextIndex][index]);
}
}
this._lastIndex = this._nextIndex;
var index = Math.floor(Math.random() * nextPos.length);
this._nextIndex = nextPos[index];
vec_1.set(this._aiPosNode.children[this._nextIndex - 1].position);
this._aiPosIndex -= 1;
var dis:number = Vec3.distance(vec_0, vec_1);
this._posPer = Constant.AI_SPEED / dis;
}
// 坐标
Vec3.lerp(this.vec3_pos, vec_0, vec_1, this._aiPosIndex);
var leftX:number = vec_1.x - vec_0.x;
var leftY:number = vec_0.z - vec_1.z;
if(!(leftX == 0 && leftY == 0)){
var angleY:number = Math.atan(leftX / leftY) * 180 / Math.PI;
if(leftY < 0){
angleY -= 180;
}
this.vec3_angle.y = 180 - angleY;
this.node.eulerAngles = this.vec3_angle;
}
this.vec3_lastPos.set(this.node.position.clone());
this._mat.m12 = this.vec3_pos.x;
this._mat.m13 = this.vec3_pos.y;
this._mat.m14 = this.vec3_lastPos.z;
if (!logicManager.playerLogic.intersectWithObstacle(this._mat, this.node.rotation, this.node.scale, this.node.parent?.scale)) {
this.vec3_lastPos.x = this.vec3_pos.x;
}
this._mat.m12 = this.vec3_lastPos.x;
this._mat.m13 = this.vec3_pos.y;
this._mat.m14 = this.vec3_pos.z;
if (!logicManager.playerLogic.intersectWithObstacle(this._mat, this.node.rotation, this.node.scale, this.node.parent?.scale)) {
this.vec3_lastPos.z = this.vec3_pos.z;
}
if(this._moveIndex == 0){
GobeUtil.instance.sendFrame({'A': Constant.ACTION.MOVE, 'V': this.vec3_angle.y, 'X': this.vec3_lastPos.x, 'Z': this.vec3_lastPos.z, 'AI' : 1});
}
this.node.setPosition(this.vec3_lastPos);
this._moveIndex ++;
if(this._moveIndex > 4){
this._moveIndex = 0;
}
}
/**
* 线
*
* @param value
*/
public updateStateRecovery(value: Player){
this.node.eulerAngles = value.eulerAngles;
this.node.setPosition(value.position);
//锤头显示
if (value.hammerCount && this.ndSocketWeapon.active === false) {
this.ndSocketWeapon.active = true;
} else if (value.hammerCount === 0 && this.ndSocketWeapon.active && !this.fighterModel.isAttacking){
this.ndSocketWeapon.active = false;
}
}
/**
*
* @param deltaTime
* @param value
*/
public updateState (deltaTime: number, value: Player, isCheck:boolean) {
if(!(this._playType == PlayType.idle || this._playType == PlayType.run)){
return;
}
this.playerState = value;
// 其他玩家移动
if(isCheck || value.channel.openId != GobeUtil.instance.ownPlayerId && !GobeUtil.instance.isAi){
var isAngle:boolean = false;
//玩家转向
if (!value.eulerAngles.equals(this.node.eulerAngles)) {
if(value.channel.openId != GobeUtil.instance.ownPlayerId){
this.node.eulerAngles = value.eulerAngles;
}
isAngle = true;
}
// var dis:number = Vec3.distance(value.position, this.node.position);
if(!(value.moveX == 0 && value.moveY == 0)){
Vec3.lerp(this.vec3_pos_1, this.node.position, value.position, 0.2);
this.node.setPosition(this.vec3_pos_1);
this.playRun();
}else if(isAngle){
this.playRun();
}else if (this._isPlayRunningEffect){
this.playIdle();
}
// 吃道具
if (value.attackPropType === PropType.HAMMER) {
this.node.setPosition(value.position);
this.playAttack(value, false);
}
}
if(value.attackPropType === PropType.HAMMER_ED){
value.attackPropType = PropType.NULL;
// 被锤子攻击
this.onHammerHit(value);
}
//得分tips
if (value.score > this._score) {
let num: number = value.score - this._score;
AudioManager.instance.playSound(Constant.AUDIO_NAME.GOLD);
ClientEvent.dispatchEvent(Constant.EVENT_NAME.ON_SHOW_COIN_TIPS, '+' + num, this.node.worldPosition.clone());
this._score = value.score;
}
//玩家大小
let size: number = (Constant.PLAYER_ORIGIN_SCALE + this._score * Constant.ADD_SIZE_PER_COIN);
size = size >= 2 ? 2 : size;
if (size !== this.node.scale.x) {
let targetSize = Util.lerp(size, this.node.scale.x, deltaTime * 10);
this.node.setScale(targetSize, targetSize, targetSize);
this._ndHammer.setScale(targetSize, targetSize, targetSize);
}
//皇冠显示
if (value.isScoreLead && !this.ndSocketCrown.active) {
this.ndSocketCrown.active = true;
} else if (!value.isScoreLead && this.ndSocketCrown.active) {
this.ndSocketCrown.active = false;
}
//锤头显示
if (value.hammerCount && this.ndSocketWeapon.active === false) {
this.ndSocketWeapon.active = true;
// 获得锤子切换动作
if(this._playType == PlayType.run){
this.fighterModel.playAni(Constant.ANI_TYPE.RUN_1, true, false, ()=>{}, 1);
this._hideHammerTrial();
}
} else if (value.hammerCount === 0 && this.ndSocketWeapon.active && !this.fighterModel.isAttacking){
// this.ndSocketWeapon.active = false;
}
}
/**
*
*
* @param {Player} value
* @memberof Fighter
*/
public onHammerHit (value: Player) {
if(this._playType == PlayType.is_attack){
return;
}
this._playType = PlayType.is_attack;
EffectManager.instance.playEffect(this.node, "dizzyEff", true, true, 1);
this.fighterModel.playAni(Constant.ANI_TYPE.HIT, false, true, ()=>{
this.fighterModel.playAni(Constant.ANI_TYPE.DIZZY, false, false, ()=>{
this.playIdle();
}, 11);
}, 9);
// //更新分数
// let num: number = value.score - this._score;
// if (num !== 0) {
// ClientEvent.dispatchEvent(Constant.EVENT_NAME.ON_SHOW_COIN_TIPS, num, this.node.worldPosition.clone());
// }
// this._score = value.score;
// this._parent.dropCoin();
}
/**
*
* @param posWorld
* @param scale
* @param endCb
*/
private _playHitEffect (posWorld: Vec3, scale: number = 1, endCb?: Function) {
posWorld.y = 0.1;
EffectManager.instance.playParticle("hitNew1", posWorld, 0, scale, null, ()=>{
endCb && endCb();
});
}
/**
* 3
*/
public showFighterGameOverAni (isWin: boolean = false) {
this._playType = PlayType.game_over;
if (isWin) {
this.fighterModel.playAni(Constant.ANI_TYPE.VICTORY, true, false, ()=>{}, 13);
} else {
this.fighterModel.playAni(Constant.ANI_TYPE.LOSE, false, false, ()=>{
this.fighterModel.playAni(Constant.ANI_TYPE.LOSE_1, true, false, ()=>{}, 15);
}, 14);
}
}
}
/**
* [1] Class member could be defined like this.
* [2] Use `property` decorator if your want the member to be serializable.
* [3] Your initialization goes here.
* [4] Your update function goes here.
*
* Learn more about scripting: https://docs.cocos.com/creator/3.3/manual/zh/scripting/
* Learn more about CCClass: https://docs.cocos.com/creator/3.3/manual/zh/scripting/ccclass.html
* Learn more about life-cycle callbacks: https://docs.cocos.com/creator/3.3/manual/zh/scripting/life-cycle-callbacks.html
*/