import Player, { PlayerStatus } from "./Player";
import Random from "../util/Random";
import GameManager, { GameStatus } from "../core/GameManager";
import GameScene from "./GameScene";
import Vector2 from "../util/Vector2";
import Mathf from "../util/Mathf";
import Knife from "./Knife";
// Learn TypeScript:
// - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/typescript.html
// - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/typescript.html
// Learn Attribute:
// - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
// - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
// - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
// - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/life-cycle-callbacks.html
const {ccclass, property} = cc._decorator;
export enum PlayerAILevel
{
none = 0,
level1 = 1,
level2 = 2,
level3 = 3,
level4 = 4,
}
@ccclass
export default class PlayerAI extends cc.Component {
public aiLevel:PlayerAILevel = PlayerAILevel.level1;
/**
* AI指令
*/
public cmd:Command = new Command();
public player:Player = null;
private timer:number = 0.01;
/**
* 警戒范围
*/
public alertRange:number = 1250;
public gameScene:GameScene = null;
onLoad () {
this.gameScene = this.node.parent.getComponent(GameScene);
}
start () {
this.player = this.getComponent(Player);
/*this.node.on(cc.Node.EventType.TOUCH_START,(event:cc.Event.EventTouch)=>{
if(this.player.isAI)
{
this.node.active = !this.node.active;
}
},this);*/
this.cmd.Reset();
}
public onGameStart()
{
this.player = this.getComponent(Player);
if(this.aiLevel == PlayerAILevel.level1)
{
this.player.knifePool.initKnife(3);
}else if(this.aiLevel == PlayerAILevel.level2)
{
this.player.knifePool.initKnife(4);
}else if(this.aiLevel == PlayerAILevel.level3)
{
this.player.knifePool.initKnife(6);
}else if(this.aiLevel == PlayerAILevel.level4)
{
this.player.knifePool.initKnife(8);
}else
{
this.player.knifePool.initKnife(3);
}
}
update2 (dt)
{
if(GameManager.instance.gameStatus != GameStatus.start)
{
this.player.moveDir = cc.Vec2.ZERO;
return;
}
if(!this.player.isAI)
{
return;
}
this.timer -= dt;
if(this.timer <= 0)
{
if(Random.Range(0,1) < 0.25)
{
if(this.player.status != PlayerStatus.defence)
{
this.player.changeDefenceState();
}
this.player.moveDir = cc.Vec2.ZERO;
}else
{
if(this.player.status != PlayerStatus.attack)
{
this.player.changeAttackState();
}
this.player.moveDir = cc.v2(Random.Range(-1,1),Random.Range(-1,1));
}
this.timer = Random.Range(1.0,2.0);
}
}
update(dt):void
{
if(GameManager.instance.gameStatus != GameStatus.start)
{
this.player.stopMove();
return;
}
if(!this.player.isAI)
{
return;
}
if (this.player.status == PlayerStatus.die)
{
this.player.stopMove();
return;
}
this.cmd.Update(dt);
switch (this.cmd.type)
{
case CommandType.none:
this.OnWhatToDoNext(dt);
break;
case CommandType.pickKnife:
this.OnPickKnifeHandler(dt);
break;
case CommandType.patrol:
this.OnPatrolHandler(dt);
break;
case CommandType.scared:
this.OnScareHandler(dt);
break;
case CommandType.moveToTarget:
this.OnMoveToTargetHandler(dt);
break;
case CommandType.run:
this.OnRunHandler(dt);
break;
case CommandType.defenced:
this.OnDefencedHandler(dt);
break;
case CommandType.outflank:
this.OnOutflankHandler(dt);
break;
case CommandType.track:
this.OnTrackHandler(dt);
break;
case CommandType.attack:
this.OnAttackHandler(dt);
break;
}
}
///
/// 下一步做什么
///
public OnWhatToDoNext(dt)
{
this.AnalysisEnvironment(dt);
}
///
/// 捡刀命令的处理
///
public OnPickKnifeHandler(dt:number)
{
if (this.cmd.process == CommandProcess.none)
{
this.cmd.process = CommandProcess.execute;
this.cmd.timer = Vector2.distance(this.player.node.position,this.cmd.targetPos) / this.player.getMoveSpeed();
this.player.moveToTarget(this.cmd.targetPos);
}
if (this.cmd.process == CommandProcess.execute)
{
}
}
//巡逻时处理
public OnPatrolHandler(dt:number)
{
if (this.cmd.process == CommandProcess.none)
{
this.cmd.process = CommandProcess.execute;
//this.cmd.timer = Vector2.distance(this.player.node.position,this.cmd.targetPos) / this.player.getMoveSpeed();
//this.player.moveToTarget(this.cmd.targetPos);
this.cmd.timer = Random.Range(1, 2);
this.player.moveDir = cc.v2(Random.Range(-1,1),Random.Range(-1,1)).normalize();
this.player.changeAttackState();
}
if (this.cmd.process == CommandProcess.execute)
{
if (Vector2.distance(this.player.node.position,this.cmd.targetPos) <= this.player.getMoveSpeed() * dt)
{
this.cmd.process = CommandProcess.complete;
}
}
}
//惊吓时处理
public OnScareHandler(dt:number)
{
if (this.cmd.process == CommandProcess.none)
{
this.cmd.process = CommandProcess.execute;
this.cmd.timer = Random.Range(5.25, 6.75);
}
if (this.cmd.process == CommandProcess.execute)
{
}
}
///
/// 逃跑时处理
///
public OnRunHandler(dt:number)
{
if (this.cmd.process == CommandProcess.none)
{
this.cmd.process = CommandProcess.execute;
this.cmd.timer = Random.Range(3.25, 5.0);
this.player.changeAttackState();
}
if (this.cmd.process == CommandProcess.execute)
{
this.player.moveDir = this.player.node.position.sub(this.cmd.targetPlayer.node.position).normalize();
}
}
///
/// 防御状态
///
public OnDefencedHandler(dt:number)
{
if (this.cmd.process == CommandProcess.none)
{
this.cmd.process = CommandProcess.execute;
this.cmd.timer = Random.Range(2, 4);
this.player.changeDefenceState();
this.player.stopMove();
}
if (this.cmd.process == CommandProcess.execute)
{
}
}
///
/// 迂回战术
///
public OnOutflankHandler(dt:number)
{
if (this.cmd.process == CommandProcess.none)
{
this.cmd.process = CommandProcess.execute;
this.cmd.timer = Random.Range(5.25, 6.75);
}
if (this.cmd.process == CommandProcess.execute)
{
}
}
///
/// 跟踪目标
///
public OnTrackHandler(dt:number)
{
if (this.cmd.process == CommandProcess.none)
{
this.cmd.process = CommandProcess.execute;
this.cmd.timer = Random.Range(5.25, 6.75);
}
if (this.cmd.process == CommandProcess.execute)
{
}
}
//移动到目标处理
public OnMoveToTargetHandler(dt:number)
{
if (this.cmd.process == CommandProcess.none)
{
this.cmd.process = CommandProcess.execute;
this.cmd.timer = Random.Range(5.25, 6.75);
this.player.changeAttackState();
}
if (this.cmd.process == CommandProcess.execute)
{
}
}
///
/// 移动到目标完成
///
public OnMoveToTargetComplete(target:Player)
{
}
///
/// 目标进入攻击范围时
///
///
public OnTargetInAttackRange(target:Player)
{
}
///
/// 攻击处理
///
public OnAttackHandler(dt:number)
{
if (this.cmd.process == CommandProcess.none)
{
this.cmd.process = CommandProcess.execute;
this.cmd.timer = Random.Range(2.25, 3.5);
this.player.changeAttackState();
}
if (this.cmd.process == CommandProcess.execute)
{
this.player.moveToTarget(this.cmd.targetPlayer.node.position)
if (Vector2.distance(this.player.node.position,this.cmd.targetPos) <= this.player.getMoveSpeed() * dt)
{
this.cmd.process = CommandProcess.complete;
}
}
}
///
/// 分析环境
///
protected AnalysisEnvironment(dt:number)
{
this.cmd.Reset(); //重置指令
this.cmd.timer = Random.Range(2.0,3.6);
switch(this.aiLevel)
{
case PlayerAILevel.level1:
this.AnalysisEnvironment_Level1(dt);
break;
case PlayerAILevel.level2:
this.AnalysisEnvironment_Level2(dt);
break;
case PlayerAILevel.level3:
this.AnalysisEnvironment_Level3(dt);
break;
case PlayerAILevel.level4:
this.AnalysisEnvironment_Level4(dt);
break;
}
}
protected AnalysisEnvironment_Level1(dt:number)
{
if(Mathf.probability(0.25))
{
this.UseDefenseCmd();
}else
{
this.UsePatrolCmd();
}
}
protected AnalysisEnvironment_Level2(dt:number)
{
if(Mathf.probability(0.5))
{
var lastPlayer:Player = this.GetLastestPlayerInAlert(); //警戒范围距离最近的玩家
var myKfLen:number = this.player.knifePool.knifes.length;
if (lastPlayer != null)
{
var otherKflen:number = lastPlayer.knifePool.knifes.length;
if(myKfLen - otherKflen > 0)
{
if(myKfLen < 8)
{
this.UsePickKnifeCmd();
}else
{
this.UseAttackCmd(lastPlayer);
}
}else
{
if(Mathf.probability(0.4))
{
this.UseDefenseCmd();
}else
{
this.UseRunCmd(lastPlayer);
}
}
}else
{
this.UsePickKnifeCmd();
}
}else
{
this.UsePatrolCmd();
}
}
protected AnalysisEnvironment_Level3(dt:number)
{
if(Mathf.probability(0.7))
{
var lastPlayer:Player = this.GetLastestPlayerInAlert(); //警戒范围距离最近的玩家
var myKfLen:number = this.player.knifePool.knifes.length;
if (lastPlayer != null)
{
var otherKflen:number = lastPlayer.knifePool.knifes.length;
if(myKfLen - otherKflen > 0)
{
if(myKfLen < 8)
{
this.UsePickKnifeCmd();
}else
{
this.UseAttackCmd(lastPlayer);
}
}else
{
if(Mathf.probability(0.4))
{
this.UseDefenseCmd();
}else
{
this.UseRunCmd(lastPlayer);
}
}
}else
{
this.UsePickKnifeCmd();
}
}else
{
this.UsePatrolCmd();
}
}
protected AnalysisEnvironment_Level4(dt:number)
{
var lastPlayer:Player = this.GetLastestPlayerInAlert(); //警戒范围距离最近的玩家
var myKfLen:number = this.player.knifePool.knifes.length;
if (lastPlayer != null)
{
var otherKflen:number = lastPlayer.knifePool.knifes.length;
if(myKfLen - otherKflen > 2)
{
if(myKfLen < 10)
{
this.UsePickKnifeCmd();
}else
{
this.UseAttackCmd(lastPlayer);
}
}else
{
if(Mathf.probability(0.4))
{
this.UseDefenseCmd();
}else
{
this.UseRunCmd(lastPlayer);
}
}
}else
{
this.UsePickKnifeCmd();
}
}
///
/// 获得距离最近的玩家
///
public GetLastestPlayer():Player
{
var playerArr:Array = this.gameScene.playerArr;
var lastPlayer:Player = null; //距离最近的玩家
var dis:number = 0;
playerArr.forEach((otherPlayer:Player)=>{
if (!otherPlayer)
return;
if (otherPlayer.status == PlayerStatus.die)
return;
if(otherPlayer == this.player)
return;
var dis2:number = Vector2.distance(this.player.node.position,otherPlayer.node.position); //Vector3.Distance(m_transform.position, player.node.position);
if (dis == 0)
{
dis = dis2;
lastPlayer = otherPlayer;
}
else
{
if (dis2 < dis)
{
dis = dis2;
lastPlayer = otherPlayer;
}
}
});
return lastPlayer;
}
///
/// 获得警戒范围内距离最近的玩家
///
public GetLastestPlayerInAlert():Player
{
var playerArr:Array = this.gameScene.playerArr;
var lastPlayer:Player = null; //距离最近的玩家
var dis:number = 0;
playerArr.forEach((otherPlayer:Player)=>{
if (!otherPlayer)
return;
if (otherPlayer.status == PlayerStatus.die)
return;
if(otherPlayer == this.player)
return;
var dis2:number = Vector2.distance(this.player.node.position,otherPlayer.node.position); //Vector3.Distance(m_transform.position, player.node.position);
if (dis2 < this.alertRange)
{
if (dis == 0)
{
dis = dis2;
lastPlayer = otherPlayer;
}
else
{
if (dis2 < dis)
{
dis = dis2;
lastPlayer = otherPlayer;
}
}
}
});
return lastPlayer;
}
///
/// 获得随机一个玩家
///
public GetRandomPlayer():Player
{
var playerArr:Array = this.gameScene.playerArr;
var tempPlayer:Player = null;
var playerList:Array = [];
playerArr.forEach((otherPlayer:Player)=>{
if (!otherPlayer)
return;
if (otherPlayer.status == PlayerStatus.die)
return;
if(otherPlayer == this.player)
return;
playerList.push(otherPlayer);
});
if (playerList.length != 0)
tempPlayer = playerList[Random.RangeInteger(0, playerList.length)];
return tempPlayer;
}
///
/// 获得摄像机视野范围内随机一个点
///
///
public GetRandomPointInScene():cc.Vec2
{
var halfWidth:number = this.gameScene.sceneSize.width / 2;
var halfHeight:number = this.gameScene.sceneSize.height / 2;
return cc.v2(Random.Range(-halfWidth,halfWidth),Random.Range(-halfHeight,halfHeight));
}
///
/// 获得场景内距离玩家最近的一把飞刀
///
public GetLastestKnife():Knife
{
var knifeArr:Array = this.gameScene.knifeArr;
var lastKnife:Knife = null;
var dis:number = 0;
var halfWidth:number = this.gameScene.sceneSize.width / 2;
var halfHeight:number = this.gameScene.sceneSize.height / 2;
knifeArr.forEach((knife:Knife)=>{
if(knife.node.x < -halfWidth || knife.node.x > halfWidth || knife.node.x < -halfHeight || knife.node.y > halfHeight)
{
return;
}
var dis2:number = Vector2.distance(this.player.node.position,knife.node.position); //Vector3.Distance(m_transform.position, player.node.position);
if (dis2 < this.alertRange)
{
if (dis == 0)
{
dis = dis2;
lastKnife = knife;
}
else
{
if (dis2 < dis)
{
dis = dis2;
lastKnife = knife;
}
}
}
});
return lastKnife;
}
///
/// 使用待机指令
///
public UsePickKnifeCmd()
{
this.cmd.type = CommandType.pickKnife;
var lastestKnife:Knife = this.GetLastestKnife();
if(lastestKnife)
{
this.cmd.targetPos = lastestKnife.node.position;
}else
{
this.cmd.targetPos = this.GetRandomPointInScene();
}
}
///
/// 使用巡逻指令
///
protected UsePatrolCmd()
{
this.cmd.type = CommandType.patrol;
this.cmd.targetPos = this.GetRandomPointInScene();
}
///
/// 使用防御指令
///
protected UseDefenseCmd()
{
this.cmd.type = CommandType.defenced;
//this.cmd.targetPlayer = player;
//this.cmd.targetPos = player.node.position;
}
///
/// 使用攻击指令
///
protected UseAttackCmd(player:Player)
{
this.cmd.type = CommandType.attack;
if (player != null)
{
//enemy.FaceToPosition(player.node.position);
this.cmd.targetPlayer = player;
this.cmd.targetPos = player.node.position;
}
}
///
/// 使用攻击指令
///
protected UseRunCmd(player:Player)
{
this.cmd.type = CommandType.run;
if (player != null)
{
//enemy.FaceToPosition(player.node.position);
this.cmd.targetPlayer = player;
this.cmd.targetPos = player.node.position;
}
}
///
/// 使用移动到目标指令
///
protected UseMoveToTargetCmd(player:Player)
{
this.cmd.type = CommandType.moveToTarget;
this.cmd.targetPlayer = player;
this.cmd.targetPos = player.node.position;
}
///
/// 使用跟踪目标指令
///
protected UseTrackCmd(player:Player)
{
this.cmd.type = CommandType.track;
this.cmd.targetPlayer = player;
this.cmd.targetPos = player.node.position;
}
}
///
/// 指令数据
///
class Command
{
///
/// 指令类型
///
public type:CommandType;
///
/// 目标玩家对象
///
public targetPlayer:Player;
///
/// 目标点
///
public targetPos:cc.Vec2;
///
///
///
public roadPath:cc.Vec2[] = [];
///
/// 指令执行时间
///
public timer:number = 0;
public cd:number = 0;
///
/// 执行进程
///
public process:CommandProcess;
public Reset()
{
this.type = CommandType.none;
this.targetPlayer = null;
this.targetPos = cc.Vec2.ZERO;
this.roadPath.length = 0;
this.timer = 0;
this.cd = 0;
this.process = CommandProcess.none;
}
public Update(dt:number)
{
if(this.type == CommandType.moveToTarget || this.type == CommandType.outflank || this.type == CommandType.track)
{
if(!this.targetPlayer || this.targetPlayer.status == PlayerStatus.die) //玩家已经不存在
this.Reset();
}
if (this.process == CommandProcess.complete)
{
this.Reset();
}
else
{
if (this.timer > 0)
{
this.timer -= dt;
if (this.timer <= 0)
{
this.Reset();
}
}
}
}
}
///
/// 指令类型
///
enum CommandType
{
///
/// 不做任何事
///
none = 0,
///
/// 待机
///
pickKnife = 1,
///
/// 巡逻
///
patrol = 2,
///
/// 被惊吓
///
scared = 3,
///
/// 移动到目标
///
moveToTarget = 4,
///
/// 绕着走
///
run = 5,
///
/// 防御
///
defenced = 6,
///
/// 迂回
///
outflank = 7,
///
/// 跟踪
///
track = 8,
///
/// 组合攻击
///
comboAttack = 100,
///
/// 攻击1
///
attack = 101,
///
/// 攻击2
///
attack2 = 102,
///
/// 攻击3
///
attack3 = 103,
}
///
/// 指令进程
///
enum CommandProcess
{
///
/// 未执行
///
none = 0,
///
/// 执行中
///
execute = 1,
///
/// 执行完成
///
complete = 2
}