import FObject, { GroupType } from "./FObject"; import CMath from "../../../util/CMath"; import BObject from "../../fight/bullet/BObject"; import FPanel from "./FPanel"; import { FFAttr } from "../../data/FFCalAttr"; import AIBase from "./AI/AIBase"; import FPanelIcon from "./FPanelIcon"; import Equip from "../../home/equip/Equip"; import { __SkillData } from "../../data/sdata/SManage"; const { ccclass, property } = cc._decorator; /** * 精灵状态 */ export const SpriteType = cc.Enum({ NONE: 0,//站立 MOVE: 1,//移动 // ATK: 2, //攻击 }); /** * 动画类型 */ export const SpriteActionType = cc.Enum({ stand: 'idle',//站立 move: 'move',//移动 run: 'run',//跑步 atk: 'atk',//行走攻击 atk1: 'atk1',//站立攻击 dead: 'dead',//死亡 yun: 'yun',//倒地晕 yun2: 'yun2',//晕倒地上 dang: 'dang',//惊吓 chuizi: 'chuizi',//锤子 shiqu: 'shiqu'//捡起 }); /** * 碰撞精灵 */ export interface ColliderSprite { sprite: FSprite, dis: number, } /** * 精灵 */ @ccclass export default class FSprite extends FObject { /** * 当前调用的动画 */ public spine: sp.Skeleton = null; // public hurtSpine: sp.Skeleton = null; // public hurtParticle: cc.ParticleSystem = null; mBullet: cc.Prefab = null;//攻击效果 // @property(cc.Node) // mWeapon: cc.Node = null;//武器 public mAtkSite: sp.spine.Bone = null;//子弹发射插槽 public mWeapon1: sp.spine.Bone = null;//武器 mPanels: Array = [];//显示面板 public mRigidBody: cc.RigidBody;//刚体 public status = SpriteType.NONE;//当前状态 /** * 当前剩余血量 */ public hp: number = -1; /** * 属性 */ public attrData: FFAttr = null; /** * 是否被激活 */ public isActive = true; public SPEED_WALK = 300;//行走速度 // public SPEED_RUN = 350;//跑步速度 public SPEED_SHOOT = 100;//攻击时候的移动速度 /** * 当前移动的方向 */ private dir = { x: 0, y: 0 }; public moveV2: cc.Vec2 = cc.v2(1, 0); public isWalk = false;//是否行走 public isRuning = false;//是否跑 public isShooting = false;//是否按住攻击按钮 public wAngle = 0;//当前操作武器旋转角度 /** * 当前是否暂停状态 */ public gamePause: boolean = false; public hitCount = 0; private yanwu: cc.Node = null; /** * 当前是否有盾,有盾的时候减少50%伤害 */ public hasDun = false; /** * 当前是否处于无敌状态 */ public hasWudi = false; onLoad() { let spriteNode = this.node.getChildByName('juese01'); let spineNode0 = spriteNode.getChildByName('spineRight'); if (this.node.name == "s1") { this.yanwu = spriteNode.getChildByName("yanwu_gs"); } // this.hurtSpine = spriteNode.getChildByName("hurt").getComponent(sp.Skeleton); // this.hurtParticle = spriteNode.getChildByName("particle").getComponent(cc.ParticleSystem); this.mRigidBody = this.node.getComponent(cc.RigidBody); this.mRigidBody.allowSleep = false; this.spine = spineNode0.getComponent(sp.Skeleton); this.mAtkSite = this.spine.findBone('zidan'); this.mWeapon1 = this.spine.findBone('control'); } start() { if (this.id > 0) {//载入预设怪物数据 let main = this.map.ff.main; let attrData = main.sManage.getMonsterData(this.id); this.setAttrData(attrData); this.hp = this.attrData.hp; for (let i = 0; i < this.mPanels.length; i++) { const element = this.mPanels[i]; element.updatePanel() } } this.setYanwu(false); this.updateSkin() } /** * 使用锤子 */ public useHammer() { Equip.chaneWeapon(this.spine, '1000') } public updateSkin() { // if (this.hp <= 0) { // return // } // if (this.attrData.skin) { // this.spine.setSkin(this.attrData.skin) // } // if (this.attrData.weapon) { // Equip.chaneWeapon(this.spine, this.attrData.weapon) // } } update(dt) { if (this.gamePause) { return; } this.updateMove(dt) } public setPause(pause: boolean) { this.gamePause = pause if (this.gamePause) { this.setDir({ x: 0, y: 0 }); this.setWalk(false); } } /** * 设置坐标和方向 */ public setPosition(pos) { this.node.setPosition(pos); } /** * 设置子弹 * @param mBullet */ public setBullet(mBullet) { this.mBullet = mBullet; } /** * 设置属性 * @param attrData */ public setAttrData(attrData: FFAttr) { this.attrData = attrData; //mBullet if (this.mBullet) { let node = cc.instantiate(this.mBullet); node.destroy(); } else { if (!attrData.bullet) { attrData.bullet = '1001' } attrData.bullet = '1101' cc.resources.load('prefab/bullet/' + attrData.bullet, cc.Prefab, (err, prefab: cc.Prefab) => { if (err) { cc.error(err); } else { //加载结束 this.mBullet = prefab; let node = cc.instantiate(this.mBullet); node.destroy(); } }); } let asset = 'prefab/common/hp_monter'; if (this.node.group == 'B') { asset = 'prefab/common/hp_monter_red' } cc.resources.load(asset, cc.Prefab, (err, prefab: cc.Prefab) => { if (err) { cc.error(err); } else { //加载结束 let node = cc.instantiate(prefab); let panel = node.getComponent(FPanel); panel.sprite = this; this.mPanels.push(panel); node.y = -10; node.parent = this.node; panel.updatePanel(); } }); } public flushAttrData(attrData: FFAttr) { this.attrData = attrData; this.updateSkin() if (!attrData.bullet) { attrData.bullet = '1001' } cc.resources.load('prefab/bullet/' + attrData.bullet, cc.Prefab, (err, prefab: cc.Prefab) => { if (err) { cc.error(err); } else { //加载结束 this.mBullet = prefab; let node = cc.instantiate(this.mBullet); node.destroy(); } }); } /** * 添加面板显示 */ public addPanelHUD() { let res = this.ff.fres; let node = cc.instantiate(res.mHudPrefab) node.parent = res.mHudNode; let panelIcon = node.getComponent(FPanelIcon) panelIcon.sprite = this panelIcon.setIcon() this.mPanels.push(panelIcon) } protected setWeaponAngle(angle: number) { if (this.mWeapon1) { this.wAngle = angle * 180 / Math.PI; // console.log("=====wAngle===", this.wAngle); this.mWeapon1.rotation = this.wAngle + 180;//this.spine.node.scaleX > 0 ? this.wAngle - 90 : -(this.wAngle - 90); } } /** * 更新武器旋转角度 */ protected updateWeaponAngle(angle: number) { if (this.mWeapon1) { // this.mWeapon1.data.rotation = (angle - 90) * this.spine.node.scaleX + 90 this.mWeapon1.rotation = (angle - 90) * this.spine.node.scaleX // console.log("======武器角度=====", this.mWeapon1.rotation) } } /** * 角色状态改变后更新角色动作 */ public updateAction() { if (this.isWalk) { if (this.isShooting) { this.createBullet(); this.playAction(SpriteActionType.atk, false, () => { this.updateSpine(); // this.tmpDir.x = this.dir.x; // this.tmpDir.y = this.dir.y; this.updateAction(); }); } else { this.playAction(SpriteActionType.move, true); } } else { if (this.isShooting) { this.createBullet(); this.playAction(SpriteActionType.atk1, false, () => { this.updateSpine(); // this.tmpDir.x = this.dir.x; // this.tmpDir.y = this.dir.y; this.updateAction(); }); } else { this.playAction(SpriteActionType.stand, true); } } } /** * 更新动画朝向 */ public updateSpine(): boolean { let csprite: FSprite = this.findEnemy(1300).sprite; let p1 = this.node.getPosition(); if (csprite && csprite.isValid) { let p2 = csprite.node.getPosition(); if (p1.x == p2.x) { } else if (p1.x - p2.x > 3) { this.setLR(-1); } else { this.setLR(1); } //计算弧度 // let angle = Math.floor(CMath.getAngle(p1, p2) * (180 / Math.PI)); //this.wAngle = angle // this.updateWeaponAngle(angle); } else { // this.updateSpineByDir(); // this.updateWeaponAngle(this.wAngle); } return false; } private updateSpineByDir() { if (this.dir.x >= 0) { this.setLR(1); } else { this.setLR(-1); } } /** * 设置精灵方向 */ public setDir(dir): boolean { if (this.gamePause) { return; } if (dir.x == 0 && dir.y == 0) { this.setWalk(false); return false; } if (this.isWalk && this.dir.x == dir.x && this.dir.y == dir.y) { return true; } this.dir.x = dir.x; this.dir.y = dir.y; this.setWalk(true); return true; } /** * 设置是否移动 * @param isWalk */ public setWalk(isWalk: boolean) { this.isWalk = isWalk; // this.updateSpine() // this.updateAction(); } /** * 设置是否跑 * @param isRuning */ // public setRuning(isRuning: boolean) { // this.isRuning = isRuning; // this.updateAction(); // } /** * 攻击时候的方向 */ /** * 设置攻击 * @param isShooting */ public setShooting(isShooting: boolean) { this.isShooting = isShooting; if (isShooting && this.status == SpriteType.NONE) { // this.tmpDir.x = this.dir.x; // this.tmpDir.y = this.dir.y; this.updateAction(); } } public updateMove(dt) { if (this.isWalk) { // this.mRigidBody.allowSleep = false; let speed = 0; if (this.isShooting) { speed = this.SPEED_SHOOT; } else { speed = this.SPEED_WALK; } this.node.x += this.dir.x * dt * speed; this.node.y += this.dir.y * dt * speed; this.setYanwu(true); } else { // this.mRigidBody.allowSleep = true; this.setYanwu(false); } } /** * 移动到某个点 * @param x * @param y */ public moveTo(pos: cc.Vec2, dt): boolean { // this.node.x = pos.x; // this.node.y = pos.y; let speed = 1200; let px = this.node.x > pos.x ? -speed : speed; let py = this.node.y > pos.y ? -speed : speed; this.node.x += dt * px; this.node.y += dt * py; if (px > 0) { if (this.node.x > pos.x) { this.node.x = pos.x; } } else { if (this.node.x < pos.x) { this.node.x = pos.x; } } if (py > 0) { if (this.node.y > pos.y) { this.node.y = pos.y; } } else { if (this.node.y < pos.y) { this.node.y = pos.y; } } return false; } // public playAction(nActionType, loop?: boolean, finishBack?: () => void) { // if (finishBack) { // this.spine.setCompleteListener(() => { // this.spine.setCompleteListener(null); // finishBack(); // }); // } // if (!this.isActive) { // return; // } // this.spine.setAnimation(0, nActionType, loop); // } public setLR(lr: number) { let scaleX = Math.abs(this.spine.node.scaleX); if (lr == -1) { this.spine.node.scaleX = -scaleX; } else { this.spine.node.scaleX = scaleX; } } public getLR(): number { if (this.spine.node.scaleX > 0) { return 1 } else { return -1; } } /** * hit事件回调 */ public fireCallback: () => void; public setFireCallback(fireCallback: () => void) { this.fireCallback = fireCallback; } /** * * @param prefab 添加攻击特效 */ public addSendEffect(prefab: cc.Prefab, target: cc.Node) { if (prefab) { let node = cc.instantiate(prefab); let x = this.mAtkSite.worldX * this.spine.node.scaleX let y = this.mAtkSite.worldY let pos = cc.v2(x, y); node.setPosition(pos); node.parent = this.node; // if(this.mWeapon1){ // node.angle = this.mWeapon1.data.rotation*this.spine.node.scaleX // node.scaleX = this.spine.node.scaleX // } if (target) { let p1 = this.node.getPosition(); let p2 = target.getPosition(); //计算弧度 let angle = Math.floor(CMath.getAngle(p1, p2) * (180 / Math.PI)); node.angle = angle } else { node.angle = this.wAngle } let spine = node.getComponent(sp.Skeleton) spine.setCompleteListener(() => { node.destroy() }); spine.setAnimation(0, 'atk', false) } } createBullet() { if (this.isValid && !this.gamePause) { let node = cc.instantiate(this.mBullet); node.group = 'bullet'; let x = this.node.x + this.mAtkSite.worldX * this.spine.node.scaleX let y = this.node.y + this.mAtkSite.worldY let pos = cc.v2(x, y); node.setPosition(pos); let bObject = node.getComponent(BObject); bObject.setSprite(this); let csprite: FSprite = this.findEnemy(2000).sprite; node.parent = this.map.mSprites; if (csprite && csprite.isValid) { bObject.fire(csprite.node); this.addSendEffect(bObject.mStartEffect, csprite.node); } else {//没有目标的时候,向朝向开火 bObject.fireAngle1(this.wAngle); this.addSendEffect(bObject.mStartEffect, null); } if (this.fireCallback) { this.fireCallback(); } if (this.node == this.ff.mainSprite.node) { if (this.hitCount > 4) { this.ff.shockMap(); this.hitCount = 0; } else { this.hitCount++; } } this.ff.main.playerEffectByPath('music/magic_1001_fs'); } } public tmpActionType = null; public playAction(nActionType, loop?: boolean, finishBack?: () => void): boolean { if (!this.isActive) { return false; } if (!this.spine) { return false; } // cc.log('nActionType : ',this.tmpActionType,nActionType); if (nActionType == this.tmpActionType) { return false; } if (finishBack) { this.spine.setCompleteListener(() => { this.spine.setCompleteListener(null); this.tmpActionType = null; finishBack(); }); } //this.spine.setEventListener(null); // cc.log('nActionType : ',this.tmpActionType,nActionType); this.tmpActionType = nActionType; this.spine.setAnimation(0, nActionType, loop); return true } public playAction2(nActionType, loop?: boolean, finishBack?: () => void) { this.status = SpriteType.NONE if (finishBack) { this.spine.setCompleteListener(() => { this.spine.setCompleteListener(null); this.tmpActionType = null; finishBack(); }); } this.spine.setEventListener(null); this.spine.setAnimation(0, nActionType, loop); } /** * 攻击对手进行结算 * @param target */ public atkjs(target: FSprite, _skillData?: __SkillData) { let reslut = this.calculate(this.attrData, target.attrData, _skillData); target.reduce(reslut); if (this == this.ff.mainSprite as FSprite) { this.ff.flushHP(target); } else { this.ff.updateHP(target); } // this.ff.main.playSound2('music/magic_1001_sj'); //对方存在AI,设置仇恨 if (target.hp > 0) { let baseAI = target.node.getComponent(AIBase); if (baseAI) { baseAI.setTarget(this); } // 播放受击动画和粒子特效 // if (target.node.group == "B") { // target.hurtParticle.enabled = true; // target.hurtSpine.enabled = true; // target.hurtSpine.setAnimation(0, "hurt", false); // target.hurtSpine.setCompleteListener(() => { // target.hurtParticle.enabled = false; // }) // } } } /** * 被攻击 * @param attrData */ public bAtkjs(attrData: FFAttr) { let reslut = this.calculate(attrData, this.attrData); this.reduce(reslut); } /** * 计算攻击 * @param fd */ private calculate(A: FFAttr, B: FFAttr, _skillData?: __SkillData): any { let xx = A.atk - B.def; if (_skillData) { // 1 水 // 2 火 // 3 土 // 4 风 // 5 雷 // 6 光 // 7 暗 if (_skillData.value4 == 1) { xx += A.water } else if (_skillData.value4 == 2) { xx += A.fire } else if (_skillData.value4 == 3) { xx += A.earth } else if (_skillData.value4 == 4) { xx += A.wind } else if (_skillData.value4 == 5) { xx += A.thunder } } if (xx <= 0) { xx = 1; } let hp = xx * 500 / (B.def + 300); if (hp < 1) { hp = 1; } let bj = false let sk = false let rand = CMath.getRandom(1, 100) if (rand < 30) { bj = true hp += hp * 3 / 10 } if (_skillData) { hp = hp * _skillData.value1 / 100 sk = true } let xd = hp / 10; let xxd = CMath.getRandom(-xd, xd); hp += xxd; if (hp < 10) { hp = CMath.getRandom(1, 10); } hp = Math.floor(hp) return { hp: Math.floor(hp), bj: bj, sk: sk } } /** * 返回敌人的分组 */ public getEnemyGroup() { return this.node.group == 'A' ? 'B' : 'A'; } /** * 查找周边可攻击对象 */ public findEnemy(radius: number): ColliderSprite { let mGroup = this.getEnemyGroup(); let minDis = 0 let targetSprite = null; if (this.map) { let nodes = this.map.getSprites(); for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; let sobj = node.getComponent(FSprite); if (sobj && node.active && sobj.isActive && sobj.hp > 0 && sobj.node.group == mGroup) { let dis = cc.Vec2.distance(this.node.getPosition(), node.getPosition()); if (dis < radius) { if (targetSprite == null) { targetSprite = sobj; minDis = dis; } else if (dis < minDis) { targetSprite = sobj; minDis = dis; } } } } } return { sprite: targetSprite, dis: minDis }; } public wudi(time) { this.hasWudi = true cc.tween(this.node).sequence( cc.delayTime(time), cc.callFunc(() => { this.hasWudi = false }) ).start() } public reduce(result: any) { let hp = result.hp if (hp <= 0) { return } if (this.hasWudi) { return } if (this.hp <= 0) {//已经死了 return } if (!this.ff.lockCamera) { return } let bj = result.bj let sk = result.sk this.playHit(); if (this.hasDun) { hp = Math.floor(hp / 2); } if (sk) { this.showNumber('/' + hp, this.ff.mSkillFont); } else if (bj) { this.showNumber('/' + hp, this.ff.mBjFont, null, true); } else { this.showNumber('/' + hp, this.ff.mRed); } this.hp -= hp; if (this.hp <= 0) { this.hp = 0; this.isActive = false; if (this.ff.clearCallback) { this.ff.clearCallback(this); } if (this.ff.removeCallback) { this.ff.removeCallback(this); } if (this == this.ff.mainSprite as FSprite) { // this.ff.mainSprite = null; } else { this.removeSelf(); } } this.updatePanel(); } public updatePanel() { for (let i = 0; i < this.mPanels.length; i++) { const element = this.mPanels[i]; element.updatePanel(); } } public removeSelf() { this.gamePause = true; this.playAction2(SpriteActionType.dead, false, () => { this.node.destroy(); }); } /** * 显示字符 * ; + * : - * @param hp * @param font */ private showNumber(str: string, font: cc.Font, color?: cc.Color, bs?: boolean) { let node: cc.Node = new cc.Node('hp'); node.group = 'map'; let lable: cc.Label = node.addComponent(cc.Label); lable.fontSize = 30; if (font) { lable.font = font; } if (color) { node.color = color; } lable.string = str; node.x = this.node.x; node.y = this.node.y + this.node.height * 3 / 4; this.map.node.addChild(node); let moveBy = cc.moveBy(2, cc.v2(0, 150)).easing(cc.easeSineOut()); let fadeout = cc.fadeOut(2); let spawn = null if (bs) { let seq = cc.sequence(cc.scaleTo(0.05, 1.5), cc.scaleTo(0.2, 1.2)); spawn = cc.spawn(moveBy, fadeout, seq); } else { spawn = cc.spawn(moveBy, fadeout); } let seq = cc.sequence(cc.delayTime(0.1), spawn, cc.callFunc(() => { node.removeFromParent(true); node.destroy(); })); node.runAction(seq); } /** * 播放受击动作 */ public playHit() { let spriteNode = this.node.getChildByName('juese01'); if (spriteNode) { cc.tween(spriteNode).sequence( cc.scaleTo(0.06, 1.1, 0.95), cc.scaleTo(0.06, 1, 1.1), cc.scaleTo(0.06, 1, 1), ).start(); // cc.tween(spriteNode).sequence( // cc.moveTo(0.1,cc.v2(0,-9)), // cc.moveTo(0.16,cc.v2(0,6)), // cc.moveTo(0.23,cc.v2(0,-6)), // cc.moveTo(0.3,cc.v2(0,0)), // ).start(); } } public addActiveIcon(): cc.Node { let node = new cc.Node('activeIcon'); let sprite = node.addComponent(cc.Sprite); sprite.spriteFrame = this.ff.mActiveIcon; node.parent = this.node; node.y = this.node.height + 20 return node; } public removeActiveIcon() { let node = this.node.getChildByName('activeIcon'); if (node) { node.destroy(); } } /** * 后面的 */ public nextSprite: FSprite; public setNext(sprite: FSprite) { this.nextSprite = sprite; } /** * 目标位置的切线方向移动 * @param target */ public tangentMove(target: cc.Node) { } public setYanwu(status: boolean) { if (this.yanwu) { if (this.yanwu.active == status) return this.yanwu.active = status; } } public dead(){ } }