layaair引擎做的一个三消游戏

动画.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 {
    移动消除,
    使用卡片
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值