You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
7.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AI : Character
{
public List<Cell> frontier = new List<Cell>();
public List<Cell> explored = new List<Cell>();
public int sensingRange = 6; //感知范围
public int attackRange = 1; //攻击范围
public int attackCost = 4; //攻击消耗
public AISkill skill;
Character goal = null;
Cell cell;
float timer = 0.5f;
public IEnumerator ApplyAI()
{
//Debug.Log("StartAI");
if(FindNearestEnemy() > sensingRange) //观测周围是否有敌人
yield return null;
//Debug.Log("The goal is " + goal.transform.position.x + "," + goal.transform.position.y);
RaycastHit2D hit = Physics2D.Raycast(transform.position,Vector2.up,1.0f,LayerMask.GetMask("Cells"));
cell = hit.collider.GetComponent<Cell>();
cell.parent = null;
cell.gCost = 0;
cell.hCost = 1000;
frontier.Add(cell);
yield return StartCoroutine(SearchEnemy()); //发现敌人并向敌人移动
//TestThePath(path);
}
IEnumerator SearchEnemy()
{
int nearestCell = 1000;
List<Cell> path = new List<Cell>();
Cell endNode = null;
while(frontier.Count != 0)
{
Cell node = LowestCost(); //总是找出fCost最低的节点
//Debug.Log("Node =" + node.transform.position.x + "," + node.transform.position.y);
frontier.Remove(node);
//若找到目标所在Cell则返回其父结点
if(node.currentCharacter != null && node.currentCharacter.groupNumber != groupNumber)
{
//Debug.Log(node.transform.position.x + "," + node.transform.position.y);
endNode = node.parent;
break;
}
//Debug.Log("node is " + node.transform.position.x + "," +node.transform.position.y + " hCost is " + node.hCost);
//找到离目标预测最近的单元格
if(node.hCost < nearestCell)
{
endNode = node;
nearestCell = node.hCost;
}
explored.Add(node);
List<Cell> neighbors = node.GetNeighbor();
foreach (var neighbor in neighbors)
{
if(!frontier.Contains(neighbor) && !explored.Contains(neighbor))
{
if(neighbor.currentCharacter != null && neighbor.currentCharacter.groupNumber == groupNumber)
continue;
neighbor.parent = node;
neighbor.CalculateCosts(goal.transform.position);
if(neighbor.gCost <= maxMovement)
frontier.Add(neighbor);
}
}
}
// if(endNode != null)
// Debug.Log("endNode is " + endNode.transform.position.x + "," +endNode.transform.position.y);
int count = 0;
// if(!found)
// endNode = frontier[frontier.Count - 1];
while(endNode != null)
{
path.Add(endNode);
endNode = endNode.parent;
count ++;
if(count > 10) break;
}
frontier.Clear();
explored.Clear();
//if(found == true)
{
for(int i = 0; i < attackRange - 1; i++)
path.RemoveAt(0);
path.Reverse();
if(path.Count > 0)
path.RemoveAt(0);
//Debug.Log("path.Count = " + path.Count);
}
yield return StartCoroutine(ActionAI(path));
}
void TestThePath(List<Cell> path) //测试用函数
{
Debug.Log("The path :");
foreach(var node in path)
{
Debug.Log(node.transform.position.x + "," + node.transform.position.y);
}
}
int FindNearestEnemy() //找到最近距离的敌人
{
int minDistance = 1000;
GameObject[] pieces = GameManager.instance.pieces;
foreach(var piece in pieces)
{
Character character = piece.GetComponent<Character>();
int distance = GameSettlement.Manhattan(transform.position,character.transform.position);
if(character.groupNumber != groupNumber && distance < minDistance)
{
minDistance = distance;
goal = character;
}
}
//Debug.Log("minDistance = " + minDistance);
return minDistance;
}
Cell LowestCost() //找出frontier里fCost最低的节点
{
Cell lowestCost = frontier[0];
foreach(var node in frontier)
{
if(node.fCost < lowestCost.fCost)
lowestCost = node;
}
return lowestCost;
}
IEnumerator ActionAI(List<Cell> path)
{
Selected();
//移动阶段
foreach(var node in path)
{
Vector2 position1 = cell.transform.position;
Vector2 position2 = node.transform.position;
float deltaX = position2.x - position1.x;
float deltaY = position2.y - position1.y;
Vector2 deviation = new Vector2(deltaX,deltaY);
yield return StartCoroutine(Move(deviation, 0.1f));
cell = node;
}
//攻击阶段
if(GameSettlement.Manhattan(goal.transform.position,transform.position) <= attackRange)
while(currentMovement >= attackCost)
{
yield return new WaitForSeconds(0.2f);
AIAttack();
}
yield return new WaitForSeconds(2 * timer);
Cancel();
}
void AIAttack()
{
if(skill.CheckRequest(currentMana, currentMovement, goal))
{
Debug.Log("AISkill released");
skill.ApplySkill(this, goal);
return;
}
int damage = GameSettlement.AIAttackSettlement(this, goal);
goal.ChangeHealth(damage);
goal.ChangePoise(-str);
ChangeMovement(-attackCost);
ChangeMana(inte/3 + san/5);
//buffManager.ApplyActiveSpecial(goal);
goal.buffManager.ApplyPassiveSpecial(this);
}
public override void Selected() //AI不需要武器
{
if(GameManager.instance.selected != null) return;
if(GameManager.instance.currentGroup != groupNumber)
return;
animator.SetFloat("selected", 1);
GameManager.instance.SetSelected(gameObject.GetComponent<Character>());
movementBar.SetMovementActive(true);
}
public override void Cancel() //AI不需要武器
{
animator.SetFloat("selected", 0);
GameManager.instance.SetSelected(null);
movementBar.SetMovementActive(false);
}
protected override void OnMouseOver()
{
//鼠标右键点击查看角色信息
if(Input.GetMouseButton(1) && GameManager.instance.GetSelected() == null)
{
GameManager.instance.CheckDetailInformation(str,inte,dex,san,vig,def,
currentHealth,maxHealth,currentPoise,maxPoise,currentMana,maxMana);
}
}
}