(四)战斗逻辑

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/**
 * 游戏管理器
 * 职能
 * 游戏操作引导、关卡管理、创建战斗
 * 
 */
public class GameMgr : MonoBehaviour
{

    //内部属性
    //--------------------------------------------------------------------------


    //内部方法
    //--------------------------------------------------------------------------




    /** 单例模式
     * 
     */
    public static GameMgr instanse;

    /** 战斗管理器
     * 
     */
    [SerializeFieldprivate BattleManager battleManager;

    /** 全局配置
     *  比如 关卡配置
     * 
     */
    [SerializeFieldprivate GlobleConfs globleConfs;

    /** 本地存储记录
     * 
     */
    [SerializeFieldprivate GlobleLocalData globleLocalData;

    [SerializeFieldprivate bool battling = false;


    private void Awake()
    {
        instanse = this;

        // 初始化配置等
        Init();

        //TODO:初始化战斗,后面改成开始按钮触发
        OnBattle();
    }

    private void Update()
    {
        OnUpdate(Time.deltaTime);
    }


    /** 初始化,包括全局配置
     * 
     */
    void Init()
    {
        // 关卡
        globleConfs = new GlobleConfs();
        globleConfs.Load();

        // 本地缓存数据
        globleLocalData = new GlobleLocalData();
        globleLocalData = globleLocalData.GetLocal();
    }

    /** 选择关卡,发起战斗
     * 
     */
    void OnBattle()
    {
        // 初始化战斗配置等
        battleManager = FindObjectOfType<BattleManager>();

        battleManager.InitBattle(globleConfsglobleLocalData);
    

        battling = true;
    }

    /** 选择关卡,发起战斗
   * 
   */
    void OnUpdate(float deltaTime)
    {
        if (battling == falsereturn;

        battleManager.OnUpdate(deltaTime);
    }

    //公开接口
    //--------------------------------------------------------------------------

    /** 暂时所有游戏对象、或者部分游戏对象
    * 
    */
    public void Pause()
    {
        // 暂时所有游戏对象
        Time.timeScale = 0;

        // 遍历数组控制部分对象停止运动

    }

    /** 游戏胜利
     * 
     */
    public void Success()
    {
        battling = false;

    }

    /* 是否战斗中
     * 
     */
    public bool Battling()
    {
        return battling;
    }

    public BattleManager BattleMgr()
    {
        return battleManager;
    }

}
 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/*
 * 战斗管理器 
 * 职能 : 仅负责战斗逻辑
 *       (开始、结束、暂停、加速、广告逻辑)
 * 核心玩法 :
 *       一局游戏大致3分钟,有三波敌人.
 *       一波普通攻击,
 *       一波大波攻击,
 *       最后一波boss攻击.
 *       敌人没被打死, 移动到屏幕外会自动循环,再次从出生点开始移动, 直到被打死.
 *       一波敌人全部被消灭,敌人才会开始第二波进攻.
 * 
**/

[System.Serializable]
public class BattleManager : MonoBehaviour 
{
    //内部属性
    //--------------------------------------------------------------------------

    // TODO:以后做成读取配置表
    public Transform[] enemyBirthTrans;                // 敌人出生点
    public Transform[] skillBirthTrans;                // 技能出生点
    public Transform leftTop;                          // 左上角位置
    public Transform rightBottom;                      // 右下角位置

    /** 记录当前第几波
     * 
     */
    private int wave = 1;

    /** 切换到下一波之前的准备时间,可以进行一些弹字等
     * 
     */
    private bool switching = false;
    private float switchDelta = 0f;
    private float switchTime = 5f;
    private LevelConfig currLevelConf;

    private Coroutine enemyCorotine;

    // 本波敌人总数
    [SerializeFieldprivate int totalNum;


    //外部部属性
    //--------------------------------------------------------------------------
    public BattleConfs battleConfs
    public BattleDatas battleDatas;

    //内部方法
    //--------------------------------------------------------------------------

    /** 敌人出生逻辑
     * 
     */
    private IEnumerator InvokeEnemy(int curentWave)
    {
        Debug.LogError("curentWave; " + curentWave);

        int num = 0;
        string id = "";
        switch (curentWave)
        {
            case 1:
                id = currLevelConf.enemy1Id;
                num = currLevelConf.GetInt(currLevelConf.enemy1Num);
                break;
            case 2:
                id = currLevelConf.enemy2Id;
                num = currLevelConf.GetInt(currLevelConf.enemy2Num);
                break;
            case 3:
                id = currLevelConf.enemy3Id;
                num = currLevelConf.GetInt(currLevelConf.enemy3Num);
                break;
            default:
                break;
        }

        totalNum = num;

        yield return new WaitForSeconds(1f);

        while (num > 0)
        {
            //battleDatas.CreateEnemy(id, new Vector3(0, 4f, 0), Quaternion.identity);

            int index = Random.Range(0enemyBirthTrans.Length);

            battleDatas.CreateEnemy(idenemyBirthTrans[index].positionQuaternion.identity);

            Debug.LogError("num; " + num);


            yield return new WaitForSeconds(2f);
            num--;
        }


    }

    /** 停止出生敌人
     * 
     */
    private void StopInvokeEnemy()
    {
        if (enemyCorotine != null)
        {
            StopCoroutine("InvokeEnemy");
            enemyCorotine = null;

            //Debug.LogError("StopCoroutine");
        }
    }


    /** 敌人产生
    * 
    */
    private void OnWaveStart(int currentWave)
    {
        StopInvokeEnemy();
        //创建每一波敌人
        enemyCorotine = StartCoroutine("InvokeEnemy",currentWave);
    
    }

    /** 玩家胜利
     * 
     */
    private void OnSucces()
    {
        StopInvokeEnemy();
        battleDatas.ClearBattleWave();

        GameMgr.instanse.Success();
    }

    //公开接口
    //--------------------------------------------------------------------------

    // 初始化战斗
    public void InitBattle(GlobleConfs globleConfsGlobleLocalData globleLocalData)
    {
        /** 加载战斗配置
         * 
         */
        battleConfs = new BattleConfs();
        battleConfs.Load();

        /** 初始化战斗数据
         * 
         */
        battleDatas = new BattleDatas();
        battleDatas.Reset();
        battleDatas.SetData(globleConfsglobleLocalDatabattleConfs);

        currLevelConf = globleConfs.GetConfById<LevelConfig>(globleLocalData.currentLevel.ToString(), globleConfs.GetLevelConfs());

        OnStart();
    }


    /** 开始游戏
      * 
      */
    public void OnStart()
    {
        //创建角色和敌人

        battleDatas.OnStart();

        OnWaveStart(wave);
        battleDatas.OnWaveStart(wave);

        battleDatas.CreateRole(currLevelConf.playerIdVector3.zeroQuaternion.identity);
    }

    /** 每帧更新
      * GameMgr 驱动此心跳
      * 
      */
    public void OnUpdate(float deltaTime)
    {
        if (GameMgr.instanse.Battling() == falsereturn;

        if(battleDatas.EnemyAllDeath(totalNum))
        {
            if(switching == false)
            {
                if(wave == 3
                {
                    
                    Debug.LogError("success!");

                    OnSucces();

                } else {
                    
                    switching = true;
                    wave++;

                    battleDatas.ClearBattleWave();
                }

            } else {
                if(switchDelta > switchTime)
                {
                    switchDelta = 0f;
                    switching = false;

                    OnWaveStart(wave);
                    battleDatas.OnWaveStart(wave);

                } else {
                    
                    switchDelta += deltaTime;
                }
            }
        }
        else
        {
            battleDatas.OnUpdate(deltaTime);
        }
    }

    //公开接口
    //--------------------------------------------------------------------------

    /** 收否出界
     *  左右下方判断,上方不用判断
     * 
     */
    public bool IsOutSide(Vector3 pos)
    {
        if (pos.x < leftTop.position.x)
            return true;

        if (pos.x > rightBottom.position.x)
            return true;

        if (pos.y < rightBottom.position.y)
            
            return true;
        
        return false;
    }

    /** 矫正出界点
     * 
     */
    public Vector3 CorrectOutSide(Vector3 pos)
    {
        return new Vector3(pos.xleftTop.position.y0);
    }

}
 

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/**
 * 运行时数据 
 * 职能: 管理(增、删、改、查操作) 角色、敌人、技能、金币 等游戏对象
 * 
 * 玩家   controller
 * 敌人   controller   (数组)
 * 技能   controller   (数组)
 * 障碍物  controller   (数组)
 * 子弹移动ai   (数组, 子弹会持有发射源的controller, 攻击目标的transform, 子弹有个碰撞检测脚本)
 *   
 * 
 * 
**/

[System.Serializable]
public class BattleDatas
{
    //内部属性
    //--------------------------------------------------------------------------
    GlobleLocalData globleLocalData;
    GlobleConfs globleConfs;
    BattleConfs battleConfs;

    // 敌人引用
    [SerializeFieldList<EnemyCtrenmeyCtrs;
    // 子弹引用
    [SerializeFieldList<BulletCtrbulletList;
    // 玩家引用
    [SerializeFieldRoleCtr roleCtr;
    // 本波死亡敌人总数
    [SerializeFieldint deathNum;




    //内部方法
    //--------------------------------------------------------------------------

    /** 玩家 (不需要移动ai,仅加载攻击ai)
     * 
     */
    private T CreateRoleCommon<T>(RoleConfig confVector3 posQuaternion rotwhere T : PlayerCtrBase
    {
        // 加载模型
        var obj = UtilTool.CreateObjByName(conf.prefabposrot);

        // 添加武器ai
        var weaponConf = battleConfs.GetConfById<WeaponConfig>(conf.weaponAiIdbattleConfs.GetWeaponConfs());
        var weaponAI = obj.AddComponent(GlobalFunction.GetTypeByClassName(weaponConf.aiName)) as ShootBaseAI;

        // 添加controller
        var ctr = obj.AddComponent(typeof(T)) as T;

        ctr.SetConfig(confweaponConf);
        ctr.SetWeaponAI(weaponAI);

        ctr.IsEnemy = false;

        return ctr;
    }

    /** 敌人 (加载移动ai, 攻击ai)
     * 
     */
    private T CreateEnemyCommon<T>(RoleConfig confVector3 posQuaternion rotwhere T : PlayerCtrBase
    {
        // 加载模型
        var obj = UtilTool.CreateObjByName(conf.prefabposrot);

        // 添加移动ai
        var moveConf = battleConfs.GetConfById<MoveAIConfig>(conf.moveAiIdbattleConfs.GetMoveAIConfs());
        var moveAI = obj.AddComponent(GlobalFunction.GetTypeByClassName(moveConf.aiName)) as BaseAI;

        // 添加武器ai
        var weaponConf = battleConfs.GetConfById<WeaponConfig>(conf.weaponAiIdbattleConfs.GetWeaponConfs());
        var weaponAI = obj.AddComponent(GlobalFunction.GetTypeByClassName(weaponConf.aiName)) as ShootBaseAI;

        // 添加controller
        var ctr = obj.AddComponent(typeof(T)) as T;

        ctr.SetConfig(confweaponConf);
        ctr.SetMoveAI(moveAI);
        ctr.SetWeaponAI(weaponAI);

        ctr.IsEnemy = true;

        return ctr;
    }

    /** 创建子弹(加载移动ai)
     * 
     */
    private T CreateBulletCommon<T>(BulletConfig confVector3 posQuaternion rotbool isEnemywhere T : BulletCtrBase
    {
        // 加载模型
        var obj = UtilTool.CreateObjByName(conf.prefabposrot);

        // 添加移动ai
        var moveConf = battleConfs.GetConfById<MoveAIConfig>(conf.moveAiIdbattleConfs.GetMoveAIConfs());
        var moveAI = obj.AddComponent(GlobalFunction.GetTypeByClassName(moveConf.aiName)) as BaseAI;

        // 添加controller
        var ctr = obj.AddComponent(typeof(T)) as T;

        ctr.SetMoveAI(moveAI);
        ctr.SetConfig(conf);

        ctr.IsEnemy = isEnemy;

        return ctr;
    }

    /** 回收敌人
     * 
     */
    private void ClearEnemys()
    {
        for (int i = 0i < enmeyCtrs.Counti++)
        {
            enmeyCtrs[i] = null;
        }
        enmeyCtrs.Clear();
    }

    /** 回收子弹
     * 
     */
    private void ClearBullets()
    {

        for (int i = 0i < bulletList.Counti++)
        {
            var obj = bulletList[i];
            if (obj != null)
            {
                GameObject.Destroy(obj.gameObject);
            }

            bulletList[i] = null;
        }
        bulletList.Clear();
    }



    //公开接口
    //--------------------------------------------------------------------------

    /** 重置
     * 
     */
    public void Reset()
    {
        roleCtr = null;
        enmeyCtrs = new List<EnemyCtr>();
        bulletList = new List<BulletCtr>();
    }

    /** 初始化
     * 
     */
    public void SetData(GlobleConfs gConfsGlobleLocalData gLocalDataBattleConfs bConfs)
    {
        globleLocalData = gLocalData;
        globleConfs = gConfs;
        battleConfs = bConfs;
    }

    /** 开始游戏
      * 
      */
    public void OnStart()
    {
    }

    /** 每一波开始
     * 
     */
    public void OnWaveStart(int currentWave)
    {
        deathNum = 0;

    }


    /** 每帧更新
      * BattleManager 驱动此心跳
      * 
      */
    public void OnUpdate(float deltaTime)
    {

        roleCtr.OnUpdate(deltaTime);

        for (int i = 0i < enmeyCtrs.Count;i++)
        {
            enmeyCtrs[i].OnUpdate(deltaTime);
        }

        for (int i = 0i < bulletList.Counti++)
        {
            bulletList[i].OnUpdate(deltaTime);
        }
    }
   

    /** 创建角色
     * 
     */
    public RoleCtr CreateRole(string roleIdVector3 posQuaternion rot)
    {
        var conf = battleConfs.GetConfById<RoleConfig>(roleIdbattleConfs.GetRoleConfs()); //currLevelConf.playerId

        var ctr = CreateRoleCommon<RoleCtr>(confposrot);
        ctr.OnStart();

        roleCtr = ctr;
            
        return ctr;
    }

    /** 创建敌人
     * 
     */
    public EnemyCtr CreateEnemy(string enemyIdVector3 posQuaternion rot)
    {
        var conf = battleConfs.GetConfById<RoleConfig>(enemyIdbattleConfs.GetRoleConfs());

        var ctr = CreateEnemyCommon<EnemyCtr>(confposrot);
        ctr.OnStart();

        enmeyCtrs.Add(ctr);

        return ctr;
    }


    /** 创建子弹
    * 
    *  isEnemy 是玩家还是敌人发射的
    */
    public BulletCtr CreateBullet(string bullectIDVector3 posQuaternion rotbool isEnemy)
    {
        var conf = battleConfs.GetConfById<BulletConfig>(bullectIDbattleConfs.GetBulletConfs());

        var ctr = CreateBulletCommon<BulletCtr>(confposrotisEnemy);
        ctr.OnStart();

        bulletList.Add(ctr);

        return ctr;
    }

    /** 距离参考者最近的敌人
     *  
     */
    public EnemyCtr NearestEnemy(Transform refer)
    {
        EnemyCtr ctr = null;
        float tempDis = float.MaxValue;
        float dis;
        foreach(var v in enmeyCtrs)
        {
            dis = Vector3.Distance(refer.positionv.transform.position);
            if(tempDis > dis)
            {
                tempDis = dis;
                ctr = v;
            }
        }

        return ctr;
    }


    /** 距离参考者最近的玩家
     *  
     */
    public RoleCtr NearestPlayer(Transform refer)
    {
        return roleCtr;
    }

    /** 掉血
     * 
     */
    public void CutHp(PlayerCtrBase roleint dhp)
    {
        role.GetData().CutHP(dhp);
    }

    /** 玩家角色死亡
     * 
     */
    public void RoleDeath(RoleCtr role)
    {
        if(role == roleCtr)
        {
            //roleCtr.IsDead = true;
            roleCtr = null;
        }
    }

    /** 敌人死亡
     * 
     */
    public void EnemyDeath(EnemyCtr enemy)
    {
        if(enmeyCtrs.Contains(enemy))
        {
            //enemy.IsDead = true;

            deathNum++;

            GameObject.Destroy(enemy.gameObject);

            enmeyCtrs.Remove(enemy);


  
        }
    }

    /** 敌人是否全部消灭
     *  用来判断下一波进行何时进行
     *  或者比赛胜利
     * 
     */
    public bool EnemyAllDeath(int totalNum)
    {
        return deathNum == totalNum;
    }

    /** 清理上一波数据
     * 
     */
    public void ClearBattleWave()
    {
        ClearEnemys();
        ClearBullets();
    }
}
 

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveBaseAI : BaseAI
{

    // 移动角色 transform
    [SerializeFieldprotected Transform roleTrans;
    // 移动速度
    [SerializeFieldprotected float moveSpeed;
    // 角色(玩家/敌人) controller
    [SerializeFieldprotected Transform targetTrans;
    // 移动方向
    [SerializeFieldprotected Vector3 moveDir;
    [SerializeFieldprotected bool noTarget;
    // 战斗管理器
    [SerializeFieldprotected BattleManager battle;

    /** 移动朝向
    *   分两种:
    *   一种是朝着固定方向移动,初始化时给予一个direction,
    *   另一种是跟随目标切换移动方向,需要在心跳里面逐帧更新目标.
    * 
    */
    protected virtual Vector3 GetDir()
    {
        if (this.noTarget)
        {
            //Debug.LogError("no target");
            return this.moveDir;

        } else{
            var dir = this.targetTrans.position - this.roleTrans.position;

            return dir.normalized;
        }
    }

    /** 初始化ai (必要的引用、数据)
      *  
      * 
      */
    public override void OnStart(params object[] args)
    {

        if (args == null || args.Length < 4)
        {
            Debug.LogError("args 必须包含 移动transform 、移动速度、移动方向、目标transform");

            return;
        }

        battle = GameMgr.instanse.BattleMgr();
     
        this.roleTrans = (Transform)args[0];
        this.moveSpeed = float.Parse(args[1].ToString());
        if (args[2] != null) {
            
            this.noTarget = true;

            this.moveDir = (Vector3)args[2];
        } else {
            
            this.noTarget = false;

            this.targetTrans = (Transform)args[3];

            this.moveDir = this.GetDir();
        }

        base.OnStart(args);
    }

    /** 每帧更新(外界驱动)
     *
     */
    public override void OnUpdate(float deltaTime)
    {
        //Debug.Log("single forward deltaTime : " + deltaTime);
        //Debug.Log("single forward isStart : " + this.isStart);
        //Debug.Log("single forward roleTrans : " + roleTrans.name);

        base.OnUpdate(deltaTime);

        if(this.roleTrans == null){
            //被消灭
            return;
        }

        if (battle.IsOutSide(this.roleTrans.position))
        {
            // 出界了,强制矫正
            this.roleTrans.position = battle.CorrectOutSide(this.roleTrans.position);
        }

        this.moveDir = this.GetDir();

        this.roleTrans.position += this.moveDir * deltaTime * this.moveSpeed;
    }

}
 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/**  子弹移动ai(数组, 子弹会持有发射源的controller,攻击目标的transform)
 *   子弹有个碰撞检测脚本
 */
public class ShootBaseAI : BaseAI
{
    //内部属性
    //--------------------------------------------------------------------------
    // 发射者 transform
    [SerializeFieldprotected Transform roleTrans;
    // 武器配置
    [SerializeFieldprotected WeaponConfig weaponConf;
    // 角色(玩家/敌人) controller
    [SerializeFieldprotected PlayerCtrBase roleCtr;
    // 攻击频率
    [SerializeFieldprotected float shootInterval;
    // 上次攻击时间
    [SerializeFieldprotected float shootDeltaTime;
    // 战斗管理器
    [SerializeFieldprotected BattleManager battle;
  
    //内部方法
    //--------------------------------------------------------------------------

    /** 发射朝向
     *  
     * 
     */
    protected virtual Vector3 GetDir()
    {
        return Vector3.zero;
    }

    /** 发射子弹
     *  子弹出生点为发射者的位置
     *  子弹的朝向分为三类:
     *  (1) 默认垂直方向,敌人向下发射 ; 玩家向上发射.
     *  (2) 锁定一个目标位置,向目标位置发射
     *  (3) 尾随目标,每帧刷新目标位置.
     * 
     * 
     */
    protected void Shoot()
    {
        var pos = roleTrans.position;


        //Debug.LogError("GetDir "+Quaternion.Euler(this.GetDir()));


        var rot = Quaternion.Euler(this.GetDir());
     
        battle.battleDatas.CreateBullet(weaponConf.bulletIDposrotthis.roleCtr.IsEnemy);
    }

    //公开接口
    //--------------------------------------------------------------------------

    /** 初始化ai (必要的引用、数据)
     *  数组 
     *  支持多个不同类型的参数
     *  比如 var targetTrans = (Transform)args[0];
     * 
     * 
     */
    public override void OnStart(params object[] args)
    {

        if (args == null || args.Length < 3)
        {
            Debug.LogError("args 必须包含 角色transform、武器配置 、角色controller");

            return;
        }

        battle = GameMgr.instanse.BattleMgr();

        this.roleCtr = (PlayerCtrBase)args[0];
        this.roleTrans = (Transform)args[1];
        this.weaponConf = (WeaponConfig)args[2];

        this.shootInterval = this.weaponConf.GetFloat(this.weaponConf.shootInterval);


        base.OnStart(args);
    }


    /** 每帧更新
     *  角色 controller 驱动心跳
     */
    public override void OnUpdate(float deltaTime)
    {
        base.OnUpdate(deltaTime);

        if (this.roleTrans == null)
        {
            //被消灭
            return;
        }

        if (this.shootDeltaTime > this.shootInterval)
        {
            this.shootDeltaTime = 0f;

            this.Shoot();
        } else {
            this.shootDeltaTime += deltaTime;
        }
    }

    /** 每帧更新
      *  角色 controller 驱动心跳
      * 
      *  OnUpdateTimeOnly 与 OnUpdate 互斥 , 同一帧只能执行其中一个.
      *  比如玩家不滑动角色,角色会更新武器时间,但是不会攻击(即使攻击时间到了).
      * 
      */
    public void OnUpdateTimeOnly(float deltaTime)
    {
        base.OnUpdate(deltaTime);

        if (this.roleTrans == null)
        {
            //被消灭
            return;
        }
       
        this.shootDeltaTime += deltaTime;
    }

}
 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值