美文网首页
layaair引擎做的一个三消游戏

layaair引擎做的一个三消游戏

作者: 二八二九三十一_9178 | 来源:发表于2021-05-19 16:51 被阅读0次
    动画.gif
    动画2.gif

    入门到放弃,目前已经放弃这个引擎了,下面贴出部分核心代码。不更了。

    import {$ImgUrl, $P2Proxy, $Util} from "../../api/index"
    import DataModel, {T三星条件} from "../../store/DataModel";
    import Sprite = Laya.Sprite;
    import Store from "../../store/index";
    import Person, {Effect, Monster, People, SkillTargetModel, Target, 特效} from "./battle_person";
    import Point = Laya.Point;
    import {ELIMINATE} from "./battle_clearUp";
    import index from "../index";
    import Tween = Laya.Tween;
    
    
    interface ImgObj {
        urlIndex: number,
        script: Sprite
    }
    
    class DebuffItem {
        //debuff
        id: number
        //debuff数量
        count: number
    
        constructor(id, count) {
            this.id = id
            this.count = count
        }
    }
    
    export default class Index extends Laya.Scene {
        public data: any = {};
        //波数
        wave: number = 0;
        random;
        //条件参数
        keys: any = {};
        clear: Laya.Box
        person: Laya.Box
        main: Laya.Box
        energy: Laya.Box
        header: Laya.Box
        //按下时的XY
        downXY: [number, number]
        startX: number
        startY: number
        //棋子数组
        list: []
        //-1: 失败 / 0|1|2|3: 通关的星数
        star: number
        //当前回合数
        round: number = 0
        //需要消除的棋子
        scanResult: ELIMINATE[] = []
        actions: Generator<any, void, unknown>[] = [];
        //互盾
        SP: number
        //最大护盾
        maxSP: number
        //血量
        _HP: number
        hpBar: Laya.ProgressBar
        达成三星条件: T三星条件 = new T三星条件()
        //行动记录
        battleAction: BattleAction[]
        //行动回合
        currentAction: number = 0
        //棋子落下时的锁
        moveAnimationLock = 0
        //技能效果数组
        Effects: Effect[] = [];
    
        //怪物组
        get enemys(): Monster[] {
            return this.person['enemy']
        }
    
        //战士组
        get persons(): People[] {
            return this.person['person']
        }
    
        /**
         * 根据类型获取战士
         * @param type
         */
        getPersonsByType(type: number | string): People {
            return this.persons[Number(type) - 1]
        }
    
        /**
         * 获取单位对象
         * @param sender 战士-1,-2,-3,-4 。 正数怪物 1,2,3,4
         */
        getCharacter(sender: number): People {
            if (sender > 0) {
                return this.enemys[sender]
            } else {
                return this.getPersonsByType(Math.abs(sender))
            }
        }
    
        set HP(hp: number) {
            this.hpBar.value = hp / this.maxHP
            this._HP = hp
        }
    
        get HP() {
            return this._HP
        }
    
        //最大血量
        private get maxHP(): number {
            let person = this.person['person']
            let num = 0
            for (let key of Object.keys(person))
                num += person[key].HP
            return num
        }
    
    
        /// <summary>伤害 / 恢复</summary>
        /// <param name="hp">正数:伤害 / 负数:恢复</param>
        MinusHP(value: number, unit?: People): number {
            // 伤害,需要判定无敌
            if (value > 0 && this.Hit(unit))
                return 0;
            //正数扣血/负数回血
            unit.HP -= (value) | 0;
            if (unit.isDead)
                for (let item of this.getUnitEffects(unit)) {
                    if (item.data.生效状态 == 4)
                        this.EffectTurn(item);
                }
            return (value) | 0
        }
    
        //伤害动画
        MinusHPAnimation(value: number, unit?: People) {
            let hpNode = new Laya.FontClip('comp/num_shield.png', '+-0123456789')
            let node = unit.node as Laya.Sprite
            let point = node.localToGlobal(new Point(0, 0))
            hpNode.pos(point.x, point.y)
    
            if (value > 0) {
                hpNode.value = `-${value}`
            }
            if (value < 0) {
                hpNode.value = `+${value}`
            }
            unit.RHP -= value
            this.stage.addChild(hpNode)
            unit.HPBar.value = unit.HP / unit.maxHP
            Laya.Tween.to(hpNode, {y: point.y - 100}, 500, null, Laya.Handler.create(this, () => {
                hpNode.removeSelf()
            }))
        }
    
        /// <summary>对目标单位造成任意伤害,返回其是否无敌</summary>
        Hit(unit: People): boolean {
            let 无敌: boolean = false;
            for (let item of this.getUnitEffects(unit)) {
                if (item.data.无敌状态) {
                    无敌 = true;
                }
                // 被攻击时效果持续时间减少
                if (item.data.生效状态 == 3) {
                    this.EffectTurn(item);
                }
            }
            return 无敌;
        }
    
        /// <summary>技能效果回合增加,返回技能是否结束</summary>
        EffectTurn(effect: Effect): boolean {
            effect.turn++;
            // 回合加1时效果生效
            this.effect1(effect);
            if (effect.turn == effect.data.持续时间) {
                // 结束效果
                if (effect.data._结束时触发 != null)
                    for (let item of effect.data._结束时触发)
                        this.effect(item, effect.str, effect.sender);
                this.Effects.splice(this.Effects.indexOf(effect), 1);
                return true;
            }
            return false;
        }
    
        /// <summary>伤害 / 恢复,伤害溢出时将对血量造成伤害</summary>
        /// <param name="sp">正数:伤害 / 负数:恢复</param>
        MinusSP(value: number, unit?: People): 特效 {
            let t = new 特效()
            let overflow = 0;
            // 伤害,需要判定无敌
            if (value > 0 && this.Hit(unit))
                return t;
            if (value > unit.SP) {
                // 伤害溢出,伤害血量
                overflow = value - unit.SP;
            } else {
                unit.SP -= value
            }
            t.sp = value
            if (overflow > 0)
                t.hp = this.MinusHP(overflow, unit);
            return t
    
        }
    
    
        clamp(value, min, max): number {
            value = Math.min(...[value, max])
            value = Math.max(...[value, min])
            return value
        }
    
        /**
         * 当前波的战斗是否结束
         * @constructor
         * @return true结束/false未结束
         */
        get IsWaveClear(): boolean {
            let bool: boolean = true
            for (let i = 0; i < this.enemys.length; i++) {
                let item = this.enemys[i]
                if (!item.isDead) {
                    bool = false
                    break
                }
            }
            return bool
        }
    
        constructor() {
            super();
            Laya.stage.bgColor = "#C7C3BC";
    
        }
    
        doAction(): boolean {
            for (let i = this.actions.length - 1; i >= 0; i--) {
                if (this.actions[i].next().done)
                    this.actions.splice(i, 1);
            }
            return this.actions.length == 0;
        }
    
        /**
         * 棋子掉落
         * @param eliminates
         * @param eliminatesXY
         * @param specialIndex 需要留下加强的坐标
         * @param callback
         */
        * drop(callback: Function) {
            //新的棋子落下
            this.moveAnimationLock++
            let lock = true
            let eliminates = []
            // 需要执行破碎动画的棋子
            this.scanResult.forEach(item => {
                eliminates.push(...item.Eliminates)
            })
            eliminates.forEach(item => {
                let point = item.script.localToGlobal(new Point(0, 0))
                this.actions.push(this.dropAnimation(point.x, point.y))
            })
            this.clear['moveAnimation'](this.scanResult, () => {
                //下落完成后减少
                this.moveAnimationLock--
                //当所有棋子落下后开始扫描
                if (this.moveAnimationLock == 0) {
                    callback()
                }
                lock = false
            })
            while (lock) yield
        }
    
        //棋子爆炸效果
        * dropAnimation(x, y) {
            let ani = new Laya.Animation();
            ani.interval = 16;
            ani.name = 'ani';
            ani.loadAtlas(`${$ImgUrl}ui/战斗页面/消除效果.atlas`)
            ani.play(1, false);
            ani.y = y;
            ani.x = x;
            let bool: Boolean = true
            Laya.stage.addChild(ani)
            ani.on(Laya.Event.COMPLETE, this, () => {
                bool = false
                Laya.stage.removeChild(ani)
            })
            while (bool) yield
        }
    
        //战士攻击
        * Attack1(key) {
            // 战士移动动作
    
            /*while (){
                yield
            }*/
    
            // 移动到指定位置
            console.log('战士:' + (key - 1))
            //角色名
            // let name = Store.roles[key].name
            //携程锁
            let lock = true
            let skillID = Store.roles[key].技能ID
            //战士对象
            // let persons = this.persons[name]
            //递归方法
            //目标
            this.skill(key * -1, skillID, undefined, () => {
                lock = false
            })
            // while (lock) yield
            // 弹掉血提示
            // console.log(`弹掉血提示${role.Str}`, role)
        }
    
    
        /**
         * 被攻击时
         * @param people 角色对象
         */
        * beaten(people: People, callback?: Function) {
            let lock = true
            let num = []
            if (people.RHP < 1) {
                num.push('失败')
            } else {
                num.push('受伤')
            }
            /*if (people['HPBar']) {//敌人单位
                let monster = <Monster>people
                monster.HPBar.value = monster.HP / monster.maxHP
            }*/
            people.templet.playNum(people.sk, num, [() => {
                if (callback != undefined)
                    callback()
                lock = false
                if (people.RHP > 0)//动作完成后播放待机动画
                    people.sk.play('待机', true)
            }])
            while (lock) yield
        }
    
        onEnable(): void {
            this.main = this.getChildByName('main') as Laya.Box
            this.energy = this.main.getChildByName('energy') as Laya.Box
            this.hpBar = this.energy.getChildByName('blood').getChildByName('hp') as Laya.ProgressBar
            this.header = this.getChildByName('header') as Laya.Box
            this.initClear()
            this.person = this.main.getChildByName('person') as Laya.Box
        }
    
    //初始化棋盘
        initClear() {
            this.clear = this.main.getChildByName('clearUp') as Laya.Box
            this.clear.on(Laya.Event.MOUSE_DOWN, this, this.mouseDown)
            this.clear.on(Laya.Event.MOUSE_UP, this, this.mouseUp)
    
        }
    
    
        onOpened(param: any): void {
            this.keys = param
            this.header['init']()
            this.random = new $Util(this.keys.Seed)
            this.clear['init'](this.random)
            this.header['leftBox'](this.keys.levelID)
            this.header['leftBox'](this.keys.levelID, this.wave)
            //英雄初始化
            this.person['initPer']()
            this.list = this.clear['list'] as []
            this.HP = this.maxHP
            let run = this.run()
            this.frameLoop(1, this, () => {
                run.next()
            }, null, false)
        }
    
    
        * run() {
            this.round = 0
            while (true) {
                this.wave++
                //出怪
                let monsters = this.getWaveData(this.wave)
                while (!this.doAction()) yield
                if (monsters.length == 0) {
                    let con = DataModel.T三星条件.get(this.keys.levelID)
                    if (con == undefined) {
                        return 3
                    } else {
                        let star = 0;
                        //条件大于等于
                        let tUp = ['消除战士', '消除法师', '消除牧师', '消除野人', '消除棋盘debuff', '消除加成棋子', '消除大招种子']
    
                        tUp.forEach(value => {
                            if (con[value] > 0 && this.达成三星条件[value] >= con[value])
                                star++;
                        })
    
                        if (star > 3)
                            star = 3;
                        // return star;
                        console.log(`${star}星过关`)
                        console.log(this.persons)
                        for (const key of Object.keys(this.persons)) {
                            let person = this.persons[key]
                            person.sk.play('胜利', true)
                        }
                        break
                    }
                } else {
                    console.log('怪物初始化')
                    //怪物初始化
                    this.person['initEnem'](monsters, this.random)
                }
                while (!this.IsWaveClear) {//当前波战斗未结束
                    let enemy = this.enemys
                    //怪物回合
                    for (const key in enemy) {
                        let item = enemy[key]
                        if (item == undefined || item.isDead) continue;
                        item.Turn--;
                        item.updateTurnImg()
                        while (item.Turn <= 0) {
                            let 出招 = this.person['newAttack'](item)
                            item.Turn = 出招.冷却
                            item.attack = 出招
                            item.attack._技能ID.forEach(skillID => {
                                // this.actions.push(this.Attack2(key, skillID))
                                item.attackNum++
                                console.log(key + ' 怪物攻击')
                                this.skill(Number(key) + 1, skillID, 1)
                            })
                            while (!this.doAction()) yield
                            item.updateTurnImg()
                        }
                    }
                    while (!this.doAction()) yield
                    //用户回合
                    //设置为可以移动
                    this.clear['moving'] = false
    
                    //玩家开始移动
                    while (this.scanResult.length == 0) //玩家消除了棋子
                        yield
                    this.eliminate()
                    //开始棋子下落动画
                    while (!this.doAction()) yield
                    this.round++
    
                }
            }
        }
    
        /**
         * 落消除
         * @param
         */
        eliminate() {
            if (this.scanResult.length > 0) {
                // 消除类型/棋子角色
                let clearRole = [];
                console.log(this.scanResult)
                // 需要执行破碎动画的棋子
                this.scanResult.forEach(item => {
                    clearRole.push(item.Role)
                    //获取到战士对象
                    let person = this.getPersonsByType(item.Role)
                    let attackNum = item.EliminatesXY.length - 2
                    //三消时攻击一次,每多一个消除块多一次攻击最多三次攻击
                    attackNum = attackNum > 3 ? 3 : attackNum
                    //攻击次数
                    person.attackNum += attackNum
                    switch (String(item.Role)) {
                        case '1':
                            this.达成三星条件.消除战士 += item.EliminatesXY.length
                            break;
                        case '2':
                            this.达成三星条件.消除法师 += item.EliminatesXY.length
                            break;
                        case '3':
                            this.达成三星条件.消除牧师 += item.EliminatesXY.length
                            break;
                        case '4':
                            this.达成三星条件.消除野人 += item.EliminatesXY.length
                            break;
                    }
                })
                // 人物开始战斗
                for (const k of clearRole) {
                    this.actions.push(this.Attack1(k))
                }
                this.actions.push(this.drop(() => {
                    this.scanResult = this.clear['getScanResult']()
                    if (this.scanResult.length > 0) {
                        this.eliminate()
                    }
                }))
            }
    
        }
    
    
    /// <summary>玩家使用技能</summary>
    /// <param name="sender">负数:-1,-2,-3,-4代表角色 / 正数:代表怪物1,2,3,4</param>
    /// <param name="skillID">技能ID</param>
    /// <param name="powerup">技能伤害加强百分比</param>
        skill(sender: number, skillID: number, powerup = 1, lockCallBack?: Function) {
            let str: number
            let unit: People
            if (sender > 0) {//怪物攻击
                unit = this.enemys[sender - 1]
                str = unit['T关卡配置'].攻击;
            } else {//战士攻击
                unit = this.persons[Math.abs(sender) - 1]
                str = DataModel.getRole(Math.abs(sender)).Str;
            }
            while (unit.attackNum > 0) {
                //动画目标
                let sTarget = new SkillTargetModel()
                //技能攻击目标
                let target = []
    
                // BUFF提升
                for (const item of this.getUnitEffects(unit)) {
                    if (item.data.攻击 != 0)
                        powerup += item.data.攻击;
                }
                //获取技能
                let skill = DataModel.T技能.get(skillID);
                for (let item of skill._引用的技能效果ID) {
                    this.effect(item, Math.max(str * powerup, 0), unit).forEach(item => {
                        target.push(item);
                    })
                }
                if (target.length > 0) {
                    /*console.log('技能目标', target)*/
                    //是否需要上前攻击
                    sTarget.mobile = skill.上前攻击
                    sTarget.target.push(...target)
                    unit.attackArray.push(sTarget)
    
                    if (!unit.attackBool) {//没有在攻击状态
                        unit.attackBool = true
                        this.actions.push(this.attackAnimation(unit))
                    }
                }
                unit.attackNum-- // 减少攻击次数
            } 
    
        }
    
        /**
         * 释放技能效果
         * @constructor
         */
        effect(effectID: number, str: number, sender: People) {
            let e: Effect = new Effect()
            e.data = DataModel.T技能效果.get(effectID)
            e.str = str;
            e.sender = sender;
            let targetArray: Target[] = [];
            // 释放技能特效
            for (let item of this.SkillTarget(sender, e.data.目标, e.data.复活 < 0)) {
                let t = <Target>item
                targetArray.push(t)
            }
            if (e.data.持续时间 == 0) {
                // 立即触发
                for (let item of targetArray) {
                    e.target = item;
    
                    let t = this.effect1(e);
                    let node = item.node as Laya.Sprite
                    let point = node.localToGlobal(new Point(0, 0))
                    item.minusHPAnimation = () => {
                        let hpNode = new Laya.FontClip('comp/num_shield.png', '+-0123456789')
                        hpNode.pos(point.x, point.y)
                        if (t.hp > 0) {
                            hpNode.value = `-${t.hp}`
                        }
                        if (t.hp < 0) {
                            hpNode.value = `+${t.hp}`
                        }
                        item.RHP -= t.hp
                        console.log('伤害:', t)
                        let hpbar = item.RHP / item.maxHP
                        this.stage.addChild(hpNode)
                        item.HPBar.value = hpbar
                        Laya.Tween.to(hpNode, {y: point.y - 100}, 500, null, Laya.Handler.create(this, () => {
                            hpNode.removeSelf()
                        }))
                    }
                }
            } else {
                // 放入游戏
                if (targetArray.length > 0) {
                    e.target = targetArray[0];
                    this.Effects.push(e)
                    // 攻击多个目标时,对每个目标都添加上技能效果
                    for (let i = 1; i < targetArray.length; i++) {
                        let other = new Effect()
                        other.data = e.data;
                        other.str = e.str;
                        other.sender = e.sender;
                        other.target = targetArray[i];
                        this.Effects.push(other)
                    }
                }
    
            }
            console.log('攻击对象', targetArray)
            return targetArray;
    
        }
    
        effect1(effect: Effect): 特效 {
            let t = new 特效()
            //技能对象
            let skill = effect.data;
    
            // 丢出棋盘效果
            if (skill._棋盘效果ID != null)
                this.boardDebuff(skill._棋盘效果ID);
    
            // 攻击盾量 | 基于血量百分比恢复
            if (skill.攻击护盾 != 0) {
                if (effect.target.isMonster)
                    // 按照怪物最大血量百分比加减血量
                    t.hp = this.MinusHP(effect.target.maxHP * skill.攻击护盾, effect.target);
                else
                    t = this.MinusSP(effect.str * skill.攻击护盾, effect.target);
            }
    
            // 攻击血量 | 基于攻击力恢复
            if (skill.攻击血量 != 0) {
                t.hp = this.MinusHP(effect.str * skill.攻击血量, effect.target);
            }
    
            // 复活 | 按照血量最大百分比伤害
            if (skill.复活 != 0)
                t.hp = this.MinusHP(effect.target.maxHP * skill.复活, effect.target);
    
    
            // 消除棋盘效果
            if (skill.消除debuff > 0) {
                /*// 找出有DEBUFF的棋盘格
                var boards = Boards.SelectMany(b => b).Where(b => b.Effect != null).ToList();
                if (boards.Count > 0)
                {
                    // 洗牌
                    Utility.Shuffle(boards, Random);
                    // 消除DEBUFF
                    for (int i = 0; i < skill.消除debuff; i++)
                    boards[i].ReleaseEffect();
                }*/
            }
            return t
        }
    
        /**
         * 获取这个单位的技能效果
         * @param unit
         */
        * getUnitEffects(unit: People) {
            for (let item of this.Effects)
                if (item.sender == unit)
                    yield item;
        }
    
        * beatenCallback(enemyStrArray) {
            enemyStrArray.forEach(item => {
                console.log(item.HP)
                /*if (item.isMonster) {//怪物被攻击
                    if (!item.deadLock) {
                        if (item.isDead) {
                            //设置为已播放死亡动画避免多次播放死亡动画
                            item.deadLock = true
                        }
                        //播放被攻击动画
                        this.actions.push(this.beaten(item, () => {
                            if (item.isDead) {
                                /!* item.node.visible=false
                                 item.node.removeChildByName('sk')*!/
                            }
                        }))
                    }
                } else {
                    //播放被攻击动画
                    this.actions.push(this.beaten(item))
                }*/
    
                if (!item.deadLock) {
                    //播放扣血动画
                    item.minusHPAnimation()
                    if (item.RHP < 1) {
                        //设置为已播放死亡动画避免多次播放死亡动画
                        item.deadLock = true
                    }
                    //播放被攻击动画
                    this.actions.push(this.beaten(item, () => {
    
                    }))
                }
            })
        }
    
        /**
         * 攻击动画
         * @param sender 执行动作的角色
         * @constructor
         */
        * attackAnimation(unit: People) {
    
    
            let lock = true
            //目标
            let theGoal = 0
            while (unit.attackArray.length > 0) {
                let 移动前坐标: Laya.Point = undefined
                let 目标位置基数: Laya.Point = new Point(0, 0)
                //需要移动的本地坐标
                let myLocal = undefined
                //获取攻击者
                let attack = unit.attackArray[0]
                //获取到被攻击的单位
                let targetStr = attack.target[0]
                //单位的node对象
                let pn = targetStr.node as Laya.Sprite
                //获取被攻击单位世界坐标
                let pnPoint = pn.localToGlobal(new Point(0, 0))
                //父容器
                let ow: Laya.Box = undefined
                if (unit.isMonster) {//敌人
                    目标位置基数.x = 150
                    目标位置基数.y = 0
                    ow = this.person.getChildByName('right') as Laya.Box
                } else {//战士
                    目标位置基数.x = -150
                    目标位置基数.y = 0
                    ow = this.person.getChildByName('left') as Laya.Box
                }
    
                //获取到当前单位的node对象
                let myn = unit.node as Laya.Sprite
                let t = myn.localToGlobal(new Point(0, 0))
                myLocal = myn.globalToLocal(pnPoint)
                //获取到当前单位的世界坐标
                移动前坐标 = new Point(myn.x, myn.y)
                unit.templet.playNum(unit.sk, ['行走'])
                if (attack.mobile) {//需要移动过去再攻击
                    console.log('需要上前攻击')
                    Tween.to(myn,
                        {x: (移动前坐标.x + myLocal.x) + 目标位置基数.x, y: (移动前坐标.y + myLocal.y) + 目标位置基数.y},
                        500, null, Laya.Handler.create(this, () => {
                            lock = false
                        }))
                } else {
                    Tween.to(myn, {x: 移动前坐标.x + 50}, 500, null, Laya.Handler.create(this, () => {
                        lock = false
                    }))
                }
                while (lock) yield
                lock = true
                unit.templet.playNum(unit.sk, ['攻击前摇'], [() => {
                    lock = false
                }])
                while (lock) yield
                while (unit.attackArray.length > 0) {
                    lock = true
                    //切换攻击者
                    attack = unit.attackArray[0]
                    if (attack.mobile) {
                        if (theGoal == 0 && !unit.isMonster) {
                            theGoal = attack.target[0]['T关卡配置']['位置']
                        } else if (!unit.isMonster && theGoal != attack.target[0]['T关卡配置']['位置']) {
                            theGoal = attack.target[0]['T关卡配置']['位置']
                            break
                        }
                        unit.templet.playNum(unit.sk, ['攻击'], [() => {
                            lock = false
                        }])
                        while (lock) yield
                        //被攻击动画
                        this.actions.push(this.beatenCallback(attack.target))
                        //删除第一条数据
                        unit.attackArray.splice(0, 1)
                    } else {
                        unit.templet.playNum(unit.sk, ['攻击'], [() => {
                            lock = false
                        }])
                        while (lock) yield
                        //被攻击动画
                        this.actions.push(this.beatenCallback(attack.target))
                        //删除第一条数据
                        unit.attackArray.splice(0, 1)
                    }
                    console.log('删除后的数组长度', unit.attackArray.length)
                }
                lock = true
                unit.templet.playNum(unit.sk, ['攻击后摇'], [() => {
                    unit.sk.scaleX *= -1
                    unit.templet.playNum(unit.sk, ['行走'])
                    Tween.to(myn, {x: 移动前坐标.x, y: 移动前坐标.y}, 500, null, Laya.Handler.create(this, () => {
                        unit.sk.scaleX *= -1
                        lock = false
                    }))
                }])
                while (lock) yield
            }
            unit.sk.play('待机', true)
            //攻击完成,取消攻击状态
            unit.attackBool = false
        }
    
    /// <summary>获取技能攻击的目标</summary>
    /// <param name="sender">负数:-1,-2,-3,-4代表角色 / 正数:0,1,2,3代表怪物</param>
    /// <param name="target">0-3总共4个位置 -1自己 -2全员 -3前排 -4后排 -5随机</param>
        * SkillTarget(sender: People, target: number, withDead: boolean) {
            let units: People[]
            if (target > 0)
                units = this.persons;
            else
                units = this.enemys;
    
            // 直接指定目标
            if (target < 5 && target > -5) {
                // 若不能指定死亡目标且目标已经死亡,则改为随机
                if (!withDead && units[Math.abs(target) - 1].isDead)
                    target = 5;
            }
    
            if (!withDead)
                units = units.filter(u => !u.isDead);
    
            if (units.length != 0) {
                switch (Math.abs(target)) {
                    // 随机
                    case 5:
                        yield units[this.random.Next(0, units.length)];
                        break;
                    // 全部
                    case 11:
                        for (let item of units)
                            yield item;
                        break;
                    // 自己
                    case 12:
                        yield sender;
                        break;
                    // 除自己之外的全部
                    case 13:
                        for (let i = 0; i < units.length; i++)
                            if (units[i] != sender)
                                yield units[i];
                        break;
                    // 除自己之外的随机单个
                    case 14:
                        let copy = units.filter(u => u != sender);
                        if (copy.length > 0)
                            yield units[this.random.Next(0, copy.length)];
                        break;
                    // 从前往后数的第一个单位
                    case 15:
                        yield units[0];
                        break;
                    // 从后往前数的第一个单位
                    case 16:
                        yield units[units.length - 1];
                        break;
                    // 血量最低
                    case 17: {
                        let index = 0;
                        let min = units[0].HP;
                        for (let i = 1; i < units.length; i++)
                            if (units[i].HP < min) {
                                min = units[i].HP;
                                index = i;
                            }
                        yield units[index];
                    }
                        break;
                    // 盾量最低
                    case 18: {
                        let index = 0;
                        let min = units[0].SP;
                        for (let i = 1; i < units.length; i++)
                            if (units[i].SP < min) {
                                min = units[i].SP;
                                index = i;
                            }
                        yield units[index];
                    }
                        break;
                    // 死亡随机,没有死亡就全员随机
                    case 19: {
                        let copy = units.filter(u => u.isDead);
                        if (copy.length > 0)
                            yield units[this.random.Next(0, copy.length)];
                        else
                            // 全员随机
                            yield units[this.random.Next(0, units.length)];
                    }
                        break;
                    // 死亡全部,没有死亡就没有目标
                    case 20: {
                        let copy = units.filter(u => u.isDead);
                        if (copy.length > 0)
                            yield units[this.random.Next(0, copy.length)];
                    }
                        break;
                }
            }
    
    
        }
    
    /// <summary>丢出Debuff</summary>
    /// <param name="position">丢出Debuff的位置,可以是怪物丢出,也可以是Debuff自身丢出</param>
        boardDebuff(effects: DebuffItem[]) {
            let boardArray = this.list.concat.apply([], this.list);
            for (let item of effects) {
                let effect = DataModel.T棋盘效果.get(item.id);
                if (effect.消失时间 < 0) {
                    for (let i = 0; i < item.count; i++) {
                        // 触发伤害
                        if (effect.护盾伤害 != 0) {
                            if (this.SP == 0)
                                // 没有护盾时对血量造成伤害
                                this.MinusHP(this.maxHP * effect.护盾伤害);
                            else
                                this.MinusSP(this.maxSP * effect.护盾伤害);
                        }
                        if (effect.血量伤害 != 0) {
                            this.MinusHP(this.maxHP * effect.血量伤害);
                        }
                        // 丢出其它效果
                        if (effect._随机_棋盘效果ID != null)
                            this.boardDebuff(effect._随机_棋盘效果ID);
                    }
                    // 立刻消失
                    continue;
                }
    
                // 没有Debuff的 & 优先级低的
                let list = boardArray.Where(b => b.Effect == null || b.Effect.优先级 < effect.优先级).ToList();
                console.log('boardDebuff', list)
                // 按照 没有Debuff -> 优先级低 -> 优先级高 排序
                // list.SortQuit(true, b => b.EffectPriority);
                /*
                if (list.Count == 0)
                    // 没有合适的可以放置Debuff的位置
                    break;
                // 优先级排序
                int priority = list[0].EffectPriority;
                int startIndex = 0;
                for (int i = 1; i < list.Count; i++)
                {
                    int p = list[i].EffectPriority;
                    if (p > priority)
                    {
                        // 对前面相同优先级的格子进行随机洗牌
                        list.Shuffle(Random, startIndex, i);
                        priority = p;
                        startIndex = i;
                        // 需要放置Debuff的格子已经够了,后面的不需要了
                        if (i > item.Count)
                        {
                            startIndex = list.Count;
                            break;
                        }
                    }
                }
                list.Shuffle(Random, startIndex, list.Count);
    
                int count = _MATH.Min(list.Count, item.Count);
                for (int i = 0; i < count; i++)
                {
                    var board = Boards[list[i].X][list[i].Y];
                    board.AppendEffect(effect);
                }*/
            }
        }
    
    /// <summary>对数组里的对象进行洗牌交换位置</summary>
    /// <param name="array">要洗牌的数组</param>
    /// <param name="random">随机种子</param>
    
    
        shuffle(array: any[]) {
            let temp: any;
            let index: number;
            for (let i = 0; i < array.length; i++) {
                index = this.random.Next(0, array.length);
                temp = array[index];
                array[index] = array[i];
                array[i] = temp;
            }
    
        }
    
    //扫描是否可以消除
        switchOption() {
            return new Promise(resolve => {
                /*const result = this.clear['scanList']();
                //可以消除
                if (result.length > 0) {
                    resolve(result)
                }*/
                let result = this.clear['getScanResult']();
                resolve(result)
            })
        }
    
    
        /**
         * 获取这波怪的数据
         */
        getWaveData(wave = this.wave) {
            return DataModel.T关卡配置.get(this.keys.levelID).filter(element => element.波数 == wave)
        }
    
        /*鼠标按下*/
        mouseDown(e) {
            this.downXY = this.getListByXY()
            this.startX = e.stageX
            this.startY = e.stageY
            console.log('按下', this.downXY)
    
        }
    
        /*鼠标抬起*/
        mouseUp(e) {
            if (this.getListByXY().toString().includes(this.downXY.toString())) return;
            let x = e.stageX - this.startX
            let y = e.stageY - this.startY
            if (Math.abs(x) < 10 && Math.abs(y) < 10)
                return
            //移动的方向
            let direction: Direction
            //X移动
            if (Math.abs(x) >= Math.abs(y)) {
                if (x > 0) {//往右
                    direction = Direction.R
                } else if (x <= 0) {//往左
                    direction = Direction.L
                }
            } else {
                if (y > 0) {//往下
                    direction = Direction.B
                } else if (y <= 0) {//往上
                    direction = Direction.T
                }
            }
            let [oldx, oldy] = [0, 0]
            //获取需要交换的XY
            switch (direction) {
                case Direction.L:
                    [oldx, oldy] = [this.downXY[0] - 1, this.downXY[1]]
                    break
                case Direction.R:
                    [oldx, oldy] = [this.downXY[0] + 1, this.downXY[1]]
                    break
                case Direction.T:
                    [oldx, oldy] = [this.downXY[0], this.downXY[1] - 1]
                    break
                case Direction.B:
                    [oldx, oldy] = [this.downXY[0], this.downXY[1] + 1]
                    break
            }
            //调用交换方法开始交换
            //交换
            this.clear['imgToImg'](this.downXY[0], this.downXY[1], oldx, oldy).then(res => {
                //移动步数++
                this.currentAction++
                this.scanResult = res
            })
        }
    
    
        //赋值需要消除的棋子
        /*    setCleanAnimationMap(res) {
                let listToMap: any[] = []
                for (const xy of res) {
                    let [x, y] = xy.split("-");
                    let json = {}
                    Object.assign(json, this.list[x][y])
                    json['xy'] = xy
                    listToMap.push(json)
                }
                this.cleanAnimationMap = DataModel.toMap(listToMap, 'urlIndex')
            }*/
    
    
        /**
         * 获取坐标对应棋盘中的坐标
         */
        getListByXY(): [number, number] {
            //正负误差
            // let wc = [-10,10]
    
            let [x, y] = [0, 0]
            for (let i = 0; i < this.list.length; i++) {
                let col = this.list[i] as []
                for (let j = 0; j < col.length; j++) {
                    let item = this.list[i][j] as ImgObj
                    if ((item.script.mouseX >= 0 && item.script.mouseX < item.script.width) &&
                        (item.script.mouseY >= 0 && item.script.mouseY < item.script.height)) {
                        [x, y] = [i, j]
                        break
                    }
                }
            }
            return [x, y]
        }
    
        onDisable(): void {
        }
    
    }
    
    /**
     * 方向枚举
     */
    export enum Direction {
        /**
         * 上
         */
        T
        ,
        /**
         * 右
         */
        R
        ,
        /**
         * 下
         */
        B
        ,
        /**
         * 左
         */
        L
    
    }
    
    export class BattleAction {
        type: EBattleAction
        //移动起始格子索引/卡片:索引
        index1: number
        //结束格子索引/卡片:无
        index2: number
    }
    
    export enum EBattleAction {
        移动消除,
        使用卡片
    }
    
    

    相关文章

      网友评论

          本文标题:layaair引擎做的一个三消游戏

          本文链接:https://www.haomeiwen.com/subject/ebmpjltx.html