| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class YuMenGuan : Boss
- {
- public enum AttackMethods
- {
- none = 0,
- move = 1, //移动
- shockWave1 = 2, //单手砸地,两侧冲击波
- shockWave2 = 3, //双手砸地,两侧冲击波*3
- laser = 4, //眼睛激光
- block = 5, //砖头怪
- blackHand = 6, //黑手
- }
- public enum PoolType
- {
- wave1 = 0,
- wave2 = 1,
- block = 2,
- }
- [System.Serializable]
- public struct AttackAssignment
- {
- public AttackMethods attack;
- public int weight; //权重
- }
- [System.Serializable]
- public struct BossAttackType
- {
- public AttackCategories category;
- public AttackAssignment[] attacks;
- }
- [Header("攻击配置")]
- public BossAttackType[] attackConfigurations;
- private AttackMethods curAttackType;
- [Header("移动")]
- public float maxMoveDis, minMoveDis;
- private float curMoveDis;
- private float hasMoveDis;
- private float origMoveX;
- private bool isAttackWalk; //作为随机到的攻击而移动
- private Character otherTarget;
- [Header("冲击波")]
- public GameObject wave1;
- public GameObject wave2;
- public AttackInfo wave1Damage;
- public AttackInfo[] wave2Damage;
- public Transform wave1pos;
- public Transform wave2pos;
- public float launchDelayTime1, launchDelayTime1loop, launchDelayTime2;
- public float[] waveEnlargeScale;
- public Vector3 wave1Size;
- public Vector3[] wave2Size;
- public float[] intervalTime; //三连冲击波,每个冲击波发射的间隔时间
- private List<Bullet> wave1Pool = new List<Bullet>();
- private List<Bullet> wave2Pool = new List<Bullet>();
- private int[] hasNum; //池中已有的数量
- private List<Bullet> usedWave1 = new List<Bullet>();
- private List<Bullet> usedWave2 = new List<Bullet>();
- private int curWaveIndex = 0;
- private List<Bullet> transit = new List<Bullet>(); //中转
- private int shockWaveTimes; //连续n次单手冲击波
- private bool isContinuous; //连续多次单手冲击波
- public int maxShockTimes, minShockTimes;
- public float wave1aniTime, wave1loopTime;
- public float wave2aniTime;
- public float waveEndTime;
- private float waveTime; //冲击波进行时长
- private bool isWave1; //冲击波1进行中
- private bool isWave2; //冲击波2进行中
- private bool isEndWave;
- [Header("眼睛激光")]
- public EyeLaser laser;
- public Transform eye; //从哪里射出
- public GameObject weakEye; //哪个弱点被打爆后不再发射
- public float waitTime; //蓄力多久后开始发射激光
- [Header("砖头怪")]
- public int minBlocks, maxBlocks;
- public float aniTime;
- private int curBlocks;
- public GameObject block;
- public float minX, maxX;
- private Block[] blocks;
- public GameObject specialBlock;
- public float mostHeight;
- public override void Start()
- {
- base.Start();
- hasNum = new int[3];
- laser.headPos = eye;
- }
- //判断冲击波池中是否有多余的冲击波,没有则实例化新的
- private void ExpandPool(PoolType id, int num)
- {
- int need = num - hasNum[(int)id];
- if (need <= 0)
- {
- return;
- }
- GameObject prefab = null;
- List<Bullet> pool = null;
- List<Bullet> used = null;
- switch (id)
- {
- case PoolType.wave1:
- prefab = wave1;
- pool = wave1Pool;
- used = usedWave1;
- break;
- case PoolType.wave2:
- prefab = wave2;
- pool = wave2Pool;
- used = usedWave2;
- break;
- case PoolType.block:
- break;
- default:
- break;
- }
- foreach(Bullet b in used)
- {
- if (!b.gameObject.activeSelf)
- {
- transit.Add(b);
- pool.Add(b);
- need -= 1;
- hasNum[(int)id] += 1;
- }
- }
- for (int i = 0; i < need; i++)
- {
- GameObject g;
- g = PoolManager.Instantiate(prefab, Vector3.zero, new Quaternion(0, 0, 0, 0), null);
- g.SetActive(false);
- pool.Add(g.GetComponent<Bullet>());
- hasNum[(int)id] += 1;
- }
- foreach (Bullet bu in transit)
- {
- used.Remove(bu);
- transit = new List<Bullet>();
- }
- }
- //移动逻辑,作为随出来的移动时移动一定距离;作为无目标移动时始终捕捉是否有可攻击目标进入范围,有则切出移动状态
- public override void OnMove()
- {
- if (isAttackWalk && (!targetCharacter || targetCharacter.isDie))
- {
- //CheckTarget();
- }
- if (Vector2.Distance(bodyTrans.position, targetCharacter.transform.position) <= 0.5f)
- {
- rb.velocity = new Vector3(0, 0, 0);
- }
- Vector3 dir;
- dir = bodyTrans.position.x <= targetCharacter.transform.position.x ? Vector3.right : Vector3.left;
- if (dir.x * bodyTrans.localScale.x > 0)
- {
- Turn();
- }
- rb.velocity = dir * moveSpeed;
- hasMoveDis = bodyTrans.position.x - origMoveX;
- if (isAttackWalk)
- {
- if (hasMoveDis >= curMoveDis)
- {
- isAttackWalk = false;
- EndCurAttackState(false);
- }
- }
- else
- {
- otherTarget = searchTrigger.GetMinDisTarget(attackController.targetTypes, attackController.canHitFly, attackController.curAttackMethod.searchMode);
- if (otherTarget != null)
- {
- EndCurAttackState(false);
- }
- }
- }
- public override void Update()
- {
- base.Update();
- if (isWave1)
- {
- ContinueShockWave(0);
- }
- if (isWave2)
- {
- ContinueShockWave(1);
- }
- }
- //移动前逻辑
- public override void ToMove()
- {
- ChangeState(CharacterState.Run);
- curMoveDis = Random.Range(minMoveDis, maxMoveDis);
- origMoveX = bodyTrans.position.x;
- curTarget = TargetType.Tower;
- //CheckTarget();
- ani.Play("yumenguan_walk", 0, 0);
- }
- //发射冲击波2号(3连)
- private void ToLaunchWave2()
- {
- LaunchWave(1, curWaveIndex);
- curWaveIndex++;
- if (curWaveIndex == 3)
- {
- curWaveIndex = 0;
- }
- }
- //发射冲击波1号
- private void ToLaunchWave1()
- {
- LaunchWave(0, 0);
- }
- //发射冲击波
- private void LaunchWave(int id, int index)
- {
- Vector3 dir = Vector3.zero;
- Vector3 dir1 = Vector3.left;
- Vector3 dir2 = Vector3.right;
- Bullet wv1, wv2;
- switch (id)
- {
- case 0:
- ExpandPool(PoolType.wave1, 2);
- wv1 = wave1Pool[hasNum[id] - 1];
- wv2 = wave1Pool[hasNum[id] - 2];
- wv1.transform.localScale = wave1Size;
- wv2.transform.localScale = wave1Size;
- wave1Pool.Remove(wv1);
- wave1Pool.Remove(wv2);
- usedWave1.Add(wv1);
- usedWave1.Add(wv2);
- wv1.GetComponent<WaveShockDir>().IsLeft = true;
- wv2.GetComponent<WaveShockDir>().IsLeft = false;
- wv1.GetComponent<WaveShockDir>().CheckTurn();
- wv2.GetComponent<WaveShockDir>().CheckTurn();
- wv1.BeShoot(this, wave1pos.position, dir1,false);
- wv2.BeShoot(this, wave2pos.position, dir2, false);
- wv1.transform.right = dir;
- wv2.transform.right = dir;
- break;
- case 1:
- ExpandPool(PoolType.wave2, 2);
- wv1 = wave2Pool[hasNum[id] - 1];
- wv2 = wave2Pool[hasNum[id] - 2];
- wv1.transform.localScale = wave2Size[index];
- wv2.transform.localScale = wave2Size[index];
- wave2Pool.Remove(wv1);
- wave2Pool.Remove(wv2);
- usedWave2.Add(wv1);
- usedWave2.Add(wv2);
- wv1.GetComponent<WaveShockDir>().IsLeft = true;
- wv2.GetComponent<WaveShockDir>().IsLeft = false;
- wv1.GetComponent<WaveShockDir>().CheckTurn();
- wv2.GetComponent<WaveShockDir>().CheckTurn();
- wv1.BeShoot(this, wave1pos.position, dir1, false);
- wv2.BeShoot(this, wave2pos.position, dir2, false);
- wv1.transform.right = dir;
- wv2.transform.right = dir;
- break;
- default:
- break;
- }
- hasNum[id] -= 2;
- }
- //连续发射冲击波
- private void ContinueShockWave(int id)
- {
- waveTime += Time.deltaTime;
- switch (id)
- {
- case 0:
- if (!isEndWave && ((!isContinuous && waveTime >= wave1aniTime)
- || (isContinuous && waveTime >= wave1loopTime)))
- {
- waveTime = 0;
- if (shockWaveTimes > 0)
- {
- shockWaveTimes--;
- isContinuous = true;
- ShockWave(0);
- }
- else
- {
- ani.Play("yumenguan_smash_r_end", 0, 0);
- isEndWave = true;
- }
- }
- if (isEndWave && waveTime >= waveEndTime)
- {
- isWave1 = false;
- isEndWave = false;
- isContinuous = false;
- waveTime = 0;
- EndCurAttackState(true);
- }
- break;
- case 1:
- if (waveTime >= wave2aniTime + waveEndTime)
- {
- isWave2 = false;
- waveTime = 0;
- EndCurAttackState(true);
- }
- break;
- default:
- break;
- }
- }
- //冲击波攻击
- public void ShockWave(int id)
- {
- switch (id)
- {
- case 0:
- if (!isContinuous)
- {
- isWave1 = true;
- waveTime = 0;
- ani.Play("yumenguan_smash_r", 0, 0);
- Invoke("ToLaunchWave1", launchDelayTime1);
- }
- else
- {
- waveTime = 0;
- ani.Play("yumenguan_smash_r_loop", 0, 0);
- Invoke("ToLaunchWave1", launchDelayTime1loop);
- }
- break;
- case 1:
- waveTime = 0;
- ani.Play("yumenguan_smash_double", 0, 0);
- Invoke("ToLaunchWave2", launchDelayTime2);
- isWave2 = true;
- break;
- default:
- break;
- }
- }
- public void ShootEyeLaser()
- {
- curTarget = TargetType.Player;
- //CheckTarget();
- laser.endPos = targetCharacter.transform;
- laser.DrawLine();
- laser.gameObject.SetActive(true);
- }
- public void BlocksOut()
- {
- mostHeight = 0;
- print(mostHeight);
- curBlocks = Random.Range(minBlocks, maxBlocks);
- blocks = new Block[curBlocks];
- for(int i = curBlocks; i > 0; i--)
- {
- Vector3 pos = new Vector3(transform.position.x + Random.Range(minX, maxX), -2, 0);
- GameObject bl = PoolManager.Instantiate(block, pos, new Quaternion(0, 0, 0, 0), null);
- blocks[i - 1] = bl.GetComponent<Block>();
- blocks[i - 1].ymg = this;
- blocks[i - 1].Ready();
- }
- print(mostHeight);
- EndCurAttackState(true);
- }
- public void SpecialBlockOut(Block bl)
- {
- Vector3 pos = bl.transform.position;
- GameObject sb = PoolManager.Instantiate(specialBlock, pos, new Quaternion(0, 0, 0, 0), null);
- Block speblo = sb.GetComponent<Block>();
- speblo.ymg = this;
- speblo.height = bl.height;
- speblo.isSpecial = true;
- speblo.Ready();
- }
- public void AllBlocksDrop()
- {
- foreach(Block bl in blocks)
- {
- if (!bl.isDie)
- {
- bl.isSpecialDie = true;
- bl.ChangeAttackState(Block.State.drop);
- }
- }
- }
- //攻击
- public override void Attack()
- {
- switch (curAttackType)
- {
- case AttackMethods.move:
- ToMove();
- break;
- case AttackMethods.shockWave1:
- shockWaveTimes = Random.Range(minShockTimes, maxShockTimes);
- ShockWave(0);
- break;
- case AttackMethods.shockWave2:
- ShockWave(1);
- break;
- case AttackMethods.laser:
- ani.Play("yumenguan_eyelight", 0, 0);
- Invoke("ShootEyeLaser", waitTime);
- break;
- case AttackMethods.block:
- ani.Play("yumenguan_smash_double", 0, 0);
- Invoke("BlocksOut", aniTime);
- break;
- default:
- break;
- }
- }
- //根据当前大类随机攻击方式
- public override void RandomAttackType(AttackCategories cate)
- {
- AttackAssignment[] attack = attackConfigurations[(int)cate].attacks;
- switch (cate)
- {
- case AttackCategories.A:
- searchTrigger.enabled = true;
- otherTarget = null;
- otherTarget = searchTrigger.GetMinDisTarget(attackController.targetTypes, attackController.canHitFly, attackController.curAttackMethod.searchMode);
- if (otherTarget == null)
- {
- isAttackWalk = false;
- curAttackType = AttackMethods.move;
- }
- else
- {
- curAttackType = RandomAttack(attackConfigurations[0].attacks);
- if (curAttackType == AttackMethods.move)
- {
- isAttackWalk = true;
- }
- }
- break;
- case AttackCategories.B:
- //CheckTarget();
- if (weakEye.activeSelf && targetCharacter != null)
- {
- curAttackType = RandomAttack(attackConfigurations[1].attacks);
- }
- else
- {
- curAttackType = AttackMethods.block;
- }
- break;
- default:
- break;
- }
- }
- //在某个大类里按权重随机返回一个攻击类型
- public AttackMethods RandomAttack(AttackAssignment[] attackAssigns)
- {
- int weight = 0;
- AttackMethods last = new AttackMethods();
- foreach(AttackAssignment a in attackAssigns)
- {
- weight += a.weight;
- }
- int result = Random.Range(0, weight);
- foreach(AttackAssignment a in attackAssigns)
- {
- last = a.attack;
- result -= a.weight;
- if (result < 0)
- {
- return a.attack;
- }
- }
- return last;
- }
- }
|