123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814 |
- import DataMgr from "../data/DataMgr";
- import { RESET_GAME } from "../data/Define";
- import TalkMgr from "../game/TalkMgr";
- import { UIGame } from "../UI/UIGame";
- import { xGame } from "../xGame";
- import D2BallSrc from "./D2BallSrc";
- import D2RootBallSrc from "./D2RootBallSrc";
- enum AIState {
- none = 0,
- idle, //闲置状态(对方击球)
- reset, //重置母球
- move, //移动母球
- wait, //
- select, //选择
- turn, //调整杆的角度
- shoot, //击球
- leave, //离线
- }
- export default class AIPlayer {
- private dtime: number = 30;
- private gameSrc: UIGame;
- private awayTime: number = 0;
- private awayNum: number = 0;
- private hideTime: number = 0;
- private rootMoveTime: number = 0;
- private isGuide: boolean = false;
- private tempDir1: Laya.Vector2;
- private tempDir2: Laya.Vector2;
- private tempDir3: Laya.Vector2;
- private state = AIState.none;
- private waitTime = 0;
- private forceNum = 0;
- private forceMax = 0;
- private ballSize = 33;
- //选取次数
- private selectNum = 0;
- //球杆旋转值
- private destRot = 0;
- //AI等级(1-10)
- private aiLv = 10;
- //可以打的球
- private kickBall: D2BallSrc[] = [];
- //可以直线打的球
- private lineBall: D2BallSrc[] = []
- //可以直接进袋的球
- private scoreBall: D2BallSrc[] = [];
- //与袋口没阻挡的球
- private holeBall: D2BallSrc[] = [];
- //调杆次数
- private turnNum: number = 0;
- private setNum: number = 0;
- private setMax: number = 0;
- private setRate: number = 0;
- //球边界坐标
- public rectL: number = 0;
- public rectR: number = 0;
- public rectT: number = 0;
- public rectB: number = 0;
- private wBall: D2RootBallSrc;
- private rootPos = { x: 0, y: 0 };
- private bestForce = 0;
- private bestAngle = 180;
- private bestPos = { x: 0, y: 0 };
- private bestKick = { x: 0, y: 0 };
- private posList = [];
- private posIdx: number = 0;
- private chatTime: number = 3000;
- constructor() {
- this.tempDir1 = new Laya.Vector2();
- this.tempDir2 = new Laya.Vector2();
- this.tempDir3 = new Laya.Vector2();
- Laya.timer.loop(this.dtime, this, this.onUpdate);
- xGame.eventMgr.off(RESET_GAME, this, this.resetAI);
- xGame.eventMgr.on(RESET_GAME, this, this.resetAI);
- this.gameSrc = xGame.common.gameUI;
- this.hideTime = Laya.timer.currTimer;
- Moyu.setOnTipCall((id) => {
- if (id == 20012)
- this.hideTime = Laya.timer.currTimer;
- else (id == 20011)
- {
- let dt = Laya.timer.currTimer - this.hideTime;
- console.log("onshow" + dt);
- if (dt > 30000 && this.state > AIState.none)
- xGame.common.gameMgr.aiGameEnd(false);
- }
- }, this)
- }
- public init() {
- let ggg = 1;
- if (DataMgr.getGuideDefaultModel() === 1) {
- ggg = DataMgr.getLianXiGuide();
- } else {
- ggg = DataMgr.getSkillGuide();
- }
- this.isGuide = ggg < 1 || DataMgr.gameData.gameCount < 1;
- this.awayTime = xGame.tools.random(5000, 10000);
- this.awayNum = 0;
- this.hideTime = Laya.timer.currTimer;
- let rect = xGame.common.d2World.borderRect;
- this.rectL = Math.ceil(rect.x) + 17;
- this.rectT = Math.ceil(rect.y) + 17;
- this.rectR = Math.floor(rect.x + rect.width) - 17;
- this.rectB = Math.floor(rect.y + rect.height) - 17;
- this.wBall = xGame.common.d2World.rootBall; //母球
- this.ballSize = this.wBall.gameObj.width - 1;
- if (this.posList.length < 1) {
- let dp = 40;
- for (let i = this.rectL; i < this.rectR + dp; i = i + dp) {
- for (let j = this.rectT; j < this.rectB + dp; j = j + dp) {
- let dx = i < this.rectR ? i : this.rectR;
- let dy = j < this.rectB ? j : this.rectB;
- let order = xGame.tools.random(0, 1000);
- this.posList.push({ x: dx, y: dy, order: order });
- }
- }
- this.posList.sort(function (a, b) {
- return a.order - b.order;
- });
- this.setMax = this.posList.length;
- }
- this.state = AIState.idle;
- }
- public setAiLevel(num) {
- this.aiLv = num;
- }
- //计算可打的球
- initBall() {
- //this.aiLv = xGame.tools.random(1, 11);
- //console.log("AI等级" + this.aiLv);
- this.rootPos.x = this.wBall.gameObj.x;
- this.rootPos.y = this.wBall.gameObj.y;
- this.initHoleBall();
- }
- initHoleBall() {
- this.kickBall = [];
- this.lineBall = []
- this.scoreBall = [];
- this.holeBall = [];
- this.selectNum = 0;
- this.forceNum = 0;
- this.forceMax = 0;
- this.turnNum = 0;
- let list = xGame.common.d2World.ballArr;
- if (list.length < 20 && !this.isGuide) //大招模式球太多时随机选择
- {
- let holes = xGame.common.gameMgr.holePosList;
- for (let i = 0; i < list.length; i++) {
- let obj = list[i];
- if (!obj)
- continue;
- //重置前面计算了的参数
- obj.kickPos.x = 0;
- obj.kickPos.y = 0;
- obj.poleAngle = 0;
- obj.hard = 0;
- obj.borderDis = 0;
- obj.kickAngle = 180;
- if (obj.number == 0) //母球
- continue;
- if (obj.ballType == xGame.common.gameMgr.selfCamp) //对方球
- continue;
- if (obj.number == 8 && xGame.common.gameMode == 0) {
- if (xGame.common.gameMgr.aiBallArr.length > 0 || !xGame.common.gameMgr.ensureBallType)
- continue;
- }
- let b = obj.gameObj;
- let wbp = this.rootPos;
- let bx = wbp.x - b.x;
- let by = wbp.y - b.y;
- obj.borderDis = xGame.tools.random(0, 100);
- this.kickBall.push(obj);
- //与母球之间有其他球
- if (!this.isLine(wbp, obj))
- continue;
- obj.kickAngle = xGame.tools.random(90, 180);
- obj.kickPos.x = b.x;
- obj.kickPos.y = b.y;
- this.lineBall.push(obj);
- let minDis = 999999;
- let hole = false;
- for (let j = 0; j < holes.length; j++) {
- let hp = holes[j];
- //袋口方向不对
- if (bx >= 0 && hp.x > b.x + 100)
- continue;
- if (bx <= 0 && hp.x < b.x - 100)
- continue;
- if (by < -10 && hp.y < wbp.y)
- continue;
- if (by > 10 && hp.y > wbp.y)
- continue;
- //与袋口之间没有球
- if (!this.isBlock(obj.number, b.x, b.y, hp.x, hp.y)) {
- let dis = xGame.tools.getDeltaxy(b.x, b.y, hp.x, hp.y);
- if (dis < minDis) {
- let dx = b.x - this.tempDir1.x * this.ballSize;
- let dy = b.y - this.tempDir1.y * this.ballSize;
- this.tempDir3.x = this.tempDir1.x;
- this.tempDir3.y = this.tempDir1.y;
- if (!this.isBlock(this.wBall.number, wbp.x, wbp.y, dx, dy, obj.number)) //进球路线上没有其他球
- {
- obj.kickPos.x = dx;
- obj.kickPos.y = dy;
- let num = Laya.Vector2.dot(this.tempDir1, this.tempDir3);
- if (num > 1)
- num = 1;
- obj.kickAngle = Math.acos(num) * 57.3;
- //库边球难度加大
- if (b.x < this.rectL + 2 || b.x > this.rectR - 2 || b.y < this.rectT + 2 || b.y > this.rectB - 2)
- dis = dis * 2;
- //中袋球难度加大
- if (Math.abs(hp.x - 600) < 100)
- dis += 50;
- obj.hard = dis + obj.kickAngle * 3;
- hole = true;
- }
- }
- }
- }
- if (hole) {
- this.scoreBall.push(obj);
- this.holeBall.push(obj);
- }
- }
- this.scoreBall.sort(function (a, b) {
- return a.hard - b.hard;
- });
- this.holeBall.sort(function (a, b) {
- return a.kickAngle - b.kickAngle;
- });
- this.kickBall.sort(function (a, b) {
- return a.borderDis - b.borderDis;
- });
- }
- else {
- let max = list.length - 1;
- let i = xGame.tools.random(0, max);
- for (i; i <= max; i++) {
- let idx = i >= max ? i -= max : i;
- let obj = list[idx];
- if (obj && obj.number != 0) {
- obj.kickAngle = xGame.tools.random(90, 180);
- obj.kickPos.x = obj.gameObj.x + xGame.tools.random(-10, 10);
- obj.kickPos.y = obj.gameObj.y + xGame.tools.random(-10, 10);
- this.lineBall.push(obj);
- break;
- }
- }
- }
- }
- selectBall() {
- let ball: D2BallSrc = null;
- this.destRot = 0;
- let max = this.isGuide ? 1 : 3 - Math.ceil(this.aiLv / 4) + xGame.tools.random(0, 2);
- //let wb=xGame.common.d2World.rootBall;
- let ai = 110 - this.aiLv * 10;
- let mis = xGame.tools.random(-ai, ai) * 0.005;
- let score = false;
- //没有可以直接进袋的球
- if (this.scoreBall.length < 1) {
- if (this.lineBall.length < 1) {
- for (let i = 0; i < this.kickBall.length; i++) {
- let list = [];
- let bo = this.kickBall[i];
- let bobj = bo.gameObj;
- let rect = xGame.common.d2World.borderRect;
- let mobj = this.wBall.gameObj;
- //上边库
- let minb = bobj.y - rect.y - 20;
- let minw = mobj.y - rect.y - 50;
- if (minb > 0 && minw > 0) {
- let dlenx = 0;
- let dleny = mobj.y - rect.y;
- let spx = mobj.x;
- let spy = rect.y - dleny;
- list.push({ order: minb, bx: 0, by: rect.y, spx: spx, spy: spy, dlenx: dlenx, dleny: dleny });
- }
- //下边库
- minb = rect.y + rect.height - bobj.y - 20
- minw = rect.y + rect.height - mobj.y - 50;
- if (minb > 0 && minw > 0) {
- let dlenx = 0;
- let dleny = rect.y + rect.height - mobj.y;
- let spx = mobj.x;
- let spy = rect.y + rect.height + dleny;
- list.push({ order: minb, bx: 0, by: rect.y + rect.height, spx: spx, spy: spy, dlenx: dlenx, dleny: dleny });
- }
- //左边库
- minb = bobj.x - rect.x - 20;
- minw = mobj.x - rect.x - 50;
- if (minb > 0 && minw > 0) {
- let dlenx = mobj.x - rect.x;
- let dleny = 0;
- let spx = rect.x - dlenx;
- let spy = mobj.y;
- list.push({ order: minb, bx: rect.x, by: 0, spx: spx, spy: spy, dlenx: dlenx, dleny: dleny });
- }
- //右边库
- minb = rect.x + rect.width - bobj.x - 20;
- minw = rect.x + rect.width - mobj.x - 50;
- if (minb > 0 && minw > 0) {
- let dlenx = rect.x + rect.width - mobj.x;
- let dleny = 0;
- let spx = rect.x + rect.width + dlenx;
- let spy = mobj.y;
- list.push({ order: minb, bx: rect.x + rect.width, by: 0, spx: spx, spy: spy, dlenx: dlenx, dleny: dleny });
- }
- //按距边排序
- list.sort(function (a, b) {
- return a.order - b.order;
- });
- for (let i = 0; i < list.length; i++) {
- let data = list[i];
- let mx = mobj.x - bobj.x;
- let my = mobj.y - bobj.y;
- xGame.tools.getV2Dir(data.spx, data.spy, bobj.x, bobj.y, this.tempDir1);
- xGame.tools.getV2Dir(data.spx, data.spy, mobj.x, mobj.y, this.tempDir2);
- let num = Laya.Vector2.dot(this.tempDir1, this.tempDir2);
- if (num > 1)
- num = 1;
- let cos = Math.acos(num);
- if (cos > 1.57)
- cos = 1.57;
- else if (cos < 0.01)
- cos = 0.01;
- let tan = Math.tan(cos);
- let dx = tan * data.dleny;
- let dy = tan * data.dlenx;
- let bx = data.bx > 0 ? data.bx : (mobj.x + (mx > 0 ? -dx : dx));
- if (Math.abs(bx - 667) < 40) //避开中袋
- continue;
- let by = data.by > 0 ? data.by : (mobj.y + (my > 0 ? -dy : dy));
- if (!this.isBlock(0, mobj.x, mobj.y, bx, by) && !this.isBlock(bo.number, bobj.x, bobj.y, bx, by)) {
- let dis = Math.abs(data.dlenx) + Math.abs(data.dleny) + xGame.tools.getDistance(bx, by, bo.gameObj.x, bo.gameObj.y);
- this.forceMax = dis * 0.08;
- this.destRot += mis * 0.1;
- this.setKick(bx, by);
- return true;
- }
- }
- }
- }
- else {
- ball = xGame.common.getRandArrEle(this.lineBall);
- }
- }
- else {
- for (let i = 0; i < this.scoreBall.length; i++) {
- if (i < this.scoreBall.length - 1) {
- let rand = 70 + this.aiLv * 10 + i * 10;
- if (xGame.tools.random(0, 100) < rand) {
- ball = this.scoreBall[i];
- break;
- }
- }
- else {
- ball = this.scoreBall[i];
- break;
- }
- }
- score = true;
- this.selectNum++;
- }
- if (!ball)
- ball = xGame.common.getRandArrEle(xGame.common.d2World.ballArr);
- //选取完成
- if (this.selectNum >= max) {
- console.log('zh:jian kong bug1');
- if (ball && ball.gameObj) {
- // 安全访问ball.gameObj的属性
- } else {
- console.log('zh:jian kong bug2 如果到这里应该能看到一个alert弹框报错');
- }
- let dx = ball.gameObj.x;
- let dy = ball.gameObj.y;
- let kickAngle = 0; //击球夹角
- if (score) {
- dx = ball.kickPos.x;
- dy = ball.kickPos.y;
- this.tempDir2 = xGame.tools.getV2Dir(this.wBall.gameObj.x, this.wBall.gameObj.y, dx, dy, this.tempDir2);
- this.tempDir3 = xGame.tools.getV2Dir(dx, dy, ball.gameObj.x, ball.gameObj.y, this.tempDir3);
- let adot = Laya.Vector2.dot(this.tempDir3, this.tempDir2);
- if (adot > 1)
- adot = 1;
- kickAngle = Math.acos(adot) * 57.3;
- if (kickAngle > 45) //大角度的失误不往球外偏移
- {
- let kdx = ball.kickPos.x - ball.gameObj.x;
- let kdy = ball.kickPos.y - ball.gameObj.y;
- dx = ball.kickPos.x - kdx * mis * 0.3;
- dy = ball.kickPos.y - kdy * mis * 0.3;
- }
- else
- this.destRot += mis;
- }
- else if (ball.poleAngle != 0) //插边球
- {
- this.destRot += ball.poleAngle;
- }
- if (xGame.common.gameMode == 0) {
- let af = kickAngle * 0.08;
- this.forceMax = ball.hard * 0.1 + af * af;
- }
- this.setKick(dx, dy);
- }
- else //模拟多次选择
- {
- let rand = this.aiLv * 5 + 40;
- if (xGame.tools.random(0, 100) < rand && this.scoreBall.length > 0)
- ball = xGame.common.getRandArrEle(this.scoreBall);
- else
- ball = xGame.common.getRandArrEle(xGame.common.d2World.ballArr);
- rand = this.aiLv * 3 + 40 + this.selectNum * 20;
- if (xGame.tools.random(0, 100) > rand) {
- this.selectNum = max;
- }
- this.setState(AIState.select, xGame.tools.random(500, 1000));
- this.selectNum++;
- }
- ball.onClick(0, true);
- }
- isBlock(bn, bx, by, hx, hy, dn = -1) {
- this.tempDir1 = xGame.tools.getV2Dir(bx, by, hx, hy, this.tempDir1);
- let balls = xGame.common.d2World.ballArr;
- let max = xGame.tools.getDis(hx, hy, bx, by);
- for (let index = 0; index < balls.length; index++) {
- let obj = balls[index];
- if (obj.number == 0) //母球
- continue;
- if (obj.number == bn || obj.number == dn) //自己
- continue;
- //其他球与该球的方向距离
- let dis = xGame.tools.getDistance(obj.gameObj.x, obj.gameObj.y, bx, by);
- // if(bn==0)
- // dis=obj.getDis(this.wBall);
- // else
- // dis=
- if (dis * dis > max)
- continue;
- this.tempDir2 = xGame.tools.getV2Dir(bx, by, obj.gameObj.x, obj.gameObj.y, this.tempDir2);
- let num = Laya.Vector2.dot(this.tempDir1, this.tempDir2);
- if (num > 1) num = 1;
- if (num < 0) //大于90
- continue;
- let gap = Math.sin(Math.acos(num)) * dis;
- if (gap < this.ballSize)
- return true;
- }
- return false;
- }
- //能否直接打到该球
- isLine(xy, ball: D2BallSrc) {
- let bx = xy.x;
- let by = xy.y;
- if (this.isBlock(0, bx, by, ball.gameObj.x, ball.gameObj.y, ball.number)) {
- let dis = ball.getDestDis(xy);
- let angle = Math.asin((ball.gameObj.width - 3) / dis);
- let sin = Math.sin(angle);
- let cos = Math.cos(angle);
- this.tempDir3 = xGame.tools.getV2Dir(bx, by, ball.gameObj.x, ball.gameObj.y, this.tempDir3);
- this.tempDir2.x = this.tempDir3.x * cos - this.tempDir3.y * sin;
- this.tempDir2.y = this.tempDir3.x * sin + this.tempDir3.y * cos;
- let dx = bx + this.tempDir2.x * dis;
- let dy = by + this.tempDir2.y * dis;
- let isr = this.isBlock(0, bx, by, dx, dy, ball.number);
- sin = Math.sin(-angle);
- cos = Math.cos(-angle);
- this.tempDir2.x = this.tempDir3.x * cos - this.tempDir3.y * sin;
- this.tempDir2.y = this.tempDir3.x * sin + this.tempDir3.y * cos;
- dx = bx + this.tempDir2.x * dis;
- dy = by + this.tempDir2.y * dis;
- let isl = this.isBlock(0, bx, by, dx, dy, ball.number);
- if (isr && isl)
- return false;
- ball.poleAngle = isr ? -angle * 57.3 : angle * 57.3;
- }
- return true;
- }
- //调整球杆
- turnPole() {
- //控制调整频率
- this.turnNum++;
- let rot = xGame.common.d2World.d2Gan.ui.rotation % 360;
- let dr = rot - this.destRot;
- let abs = Math.abs(dr) % 360;
- //不转大圈
- if (abs > 180) {
- if (rot > 180)
- rot -= 360;
- if (this.destRot > 180)
- this.destRot -= 360;
- }
- let max = this.turnNum * 5 + this.aiLv * 5;
- if (abs < 0.2 && xGame.tools.random(0, 100) < max) {
- xGame.common.d2World.d2Gan.rotDest(this.destRot);
- let at = xGame.tools.random(1000, 2000);
- if (!this.onAway(3))
- at += xGame.tools.random(10000, 15000);
- this.setState(AIState.shoot, at);
- //console.log("调杆"+this.turnNum+"次");
- }
- else {
- let mr = 0;
- if (abs > 3)
- mr = 1 + xGame.tools.random(2, 6) * abs * 0.01
- else if (Math.random() > 0.6)
- mr = xGame.tools.random(1, 10) * 0.1
- mr = dr > 0 ? -mr : mr;
- xGame.common.d2World.d2Gan.rotDest(rot + mr);
- //xGame.common.d2World.d2Gan.rotateSelf(mr);
- }
- }
- //击球方向、力
- setKick(dx, dy) {
- this.forceMax += this.wBall.getDestDis({ x: dx, y: dy }) * 0.1;
- this.tempDir2 = xGame.tools.getV2Dir(this.wBall.gameObj.x, this.wBall.gameObj.y, dx, dy, this.tempDir2);
- this.tempDir1.x = 0; this.tempDir1.y = 1;
- this.tempDir2.y = -this.tempDir2.y;
- let num = Laya.Vector2.dot(this.tempDir1, this.tempDir2);
- if (num > 1) num = 1;
- let rot = Math.acos(num) * 57.3;
- //0~360
- if (this.tempDir2.x < 0)
- rot = 360 - rot;
- this.destRot += rot;
- if (!xGame.common.gameMgr.finishOneShoot) //开球可能额外加力
- {
- this.forceMax += xGame.tools.random(10, 50);
- this.forceMax -= this.aiLv * 2; // 高级AI低概率大力开球
- if (this.forceMax < 20)
- this.forceMax = 20;
- }
- if (this.forceMax > 100)
- this.forceMax = 101;
- else if (this.forceMax < 10)
- this.forceMax += xGame.tools.random(0, 10);
- if (xGame.common.gameMode == 1)
- this.forceMax = xGame.tools.random(80, 100);
- else
- this.forceMax = xGame.tools.random(this.forceMax * 0.5, this.forceMax);
- let max = 2000 - this.aiLv * 100;
- if (Math.random() > 0.8)
- max += xGame.tools.random(100, 2000);
- this.setState(AIState.turn, xGame.tools.random(500, max));
- }
- //拉杆击球
- shoot() {
- if (this.waitTime < 0 && Math.abs(this.forceNum - this.forceMax) < 4) {
- if (Math.random() > 0.8) //拉到位后再有点小延迟
- {
- this.gameSrc.aiForce(1);
- this.setState(AIState.wait);
- }
- }
- else {
- let df = xGame.tools.random(3, 8);
- if (this.forceNum < this.forceMax)
- this.forceNum += df;
- else
- this.forceNum -= df;
- let startY = this.gameSrc.ui.powerNode.y;
- let height = this.gameSrc.ui.powerNode.height;
- //
- let force = startY + height * this.forceNum * 0.01;
- this.gameSrc.aiForce(2, force);
- }
- }
- reset() {
- for (let i = 0; i < 4; i++) {
- this.setRate--;
- this.setNum++;
- let pos = this.posList[this.posIdx];
- this.rootPos.x = pos.x + xGame.tools.random(-20, 20);
- this.rootPos.y = pos.y + xGame.tools.random(-20, 20);
- if (!xGame.common.gameMgr.isTouchedBall && this.rootPos.x > 387)
- this.rootPos.x = 387;
- if (this.rootPos.x < this.rectL)
- this.rootPos.x = this.rectL;
- else if (this.rootPos.x > this.rectR)
- this.rootPos.x = this.rectR;
- if (this.rootPos.y < this.rectT)
- this.rootPos.y = this.rectT;
- else if (this.rootPos.y > this.rectB)
- this.rootPos.y = this.rectB;
- this.posIdx++;
- let max = this.posList.length;
- if (this.posIdx >= max)
- this.posIdx -= max;
- this.initHoleBall();
- let ball = null;
- if (this.scoreBall.length > 0)
- ball = this.scoreBall[0];
- else if (this.lineBall.length > 0)
- ball = xGame.common.getRandArrEle(this.lineBall);
- if (ball && ball.kickAngle < this.bestAngle) {
- this.bestAngle = ball.kickAngle;
- this.bestKick.x = ball.kickPos.x;
- this.bestKick.y = ball.kickPos.y;
- this.bestPos.x = this.rootPos.x;
- this.bestPos.y = this.rootPos.y;
- this.bestForce = ball.hard * 0.08;
- }
- }
- if (this.setNum >= this.setMax)
- this.setMax = 0;
- if (this.setRate < 1) {
- this.setState(AIState.move, 0);
- this.rootMoveTime = Laya.timer.currTimer;
- this.gameSrc.aiRootMove(true);
- }
- }
- delayLine() {
- this.gameSrc.aiRootMove(false);
- }
- move() {
- if (this.bestPos.x < 1)
- this.bestPos = this.rootPos;
- let wObj = this.wBall.gameObj;
- let destx = wObj.x;
- let desty = wObj.y;
- let dx = Math.abs(destx - this.bestPos.x);
- let dy = Math.abs(desty - this.bestPos.y);
- let mx = 3 + dx * 0.03;
- let my = 3 + dy * 0.03;
- if (dx < 4 && dy < 4) {
- let dt = Laya.timer.currTimer - this.rootMoveTime;
- dt = dt < 1000 ? 1000 - dt : 0;
- if (this.setMax > 0) {
- let min = this.setMax * 0.3 + this.aiLv * 5;
- this.setRate = xGame.tools.random(min, this.setMax);
- this.setState(AIState.reset, 0);
- }
- else {
- this.destRot = 0; //
- this.forceMax = this.bestForce;
- this.setKick(this.bestKick.x, this.bestKick.y);
- }
- if (dt > 100) {
- Laya.timer.clear(this, this.delayLine)
- Laya.timer.once(dt, this, this.delayLine);
- }
- else
- this.gameSrc.aiRootMove(false);
- }
- else {
- if (dx > 4)
- destx = wObj.x < this.bestPos.x ? wObj.x + mx : wObj.x - mx;
- if (dy > 4)
- desty = wObj.y < this.bestPos.y ? wObj.y + my : wObj.y - my;
- this.gameSrc.onRootMove({ x: destx, y: desty });
- }
- }
- resetRoot() {
- this.bestAngle = 180;
- this.bestForce = 0;
- this.setMax = this.posList.length;
- this.posIdx = xGame.tools.random(0, this.setMax);
- let min = this.setMax * 0.3 + this.aiLv * 5;
- this.setRate = xGame.tools.random(min, this.setMax);
- let max = 2000 - this.aiLv * 100;
- if (Math.random() > 0.8)
- max += xGame.tools.random(100, 1000);
- if (this.isGuide)
- this.setState(AIState.select, 500);
- else if (this.onAway(2))
- this.setState(AIState.reset, xGame.tools.random(400, max));
- else
- this.setState(AIState.none);
- if (xGame.common.gameMgr.finishOneShoot)
- this.chat();
- }
- //运行ai
- runAI() {
- if (this.state > AIState.idle)
- return;
- this.initBall();
- this.onGame(2500);
- if (Math.random() > 0.6)
- this.chat();
- }
- stopRun() {
- this.setState(AIState.idle);
- }
- onGame(base: number) {
- let max = base - this.aiLv * 100;
- if (Math.random() > 0.8)
- max += xGame.tools.random(100, 1000);
- if (this.onAway(2))
- this.setState(AIState.select, xGame.tools.random(500, max));
- else
- this.setState(AIState.none);
- }
- setState(sta, wt = 0) {
- if (this.state == AIState.none)
- return;
- this.state = sta;
- this.waitTime = wt;
- }
- onUpdate() {
- if (this.state == AIState.none)
- return;
- this.awayTime -= this.dtime;
- if (this.awayTime < 1) {
- this.awayTime = xGame.tools.random(6000, 10000);
- this.awayNum += (11 - this.aiLv);
- this.onAway(1);
- }
- if (this.waitTime >= 0) {
- this.waitTime -= this.dtime;
- return;
- }
- switch (this.state) {
- case AIState.idle:
- this.chat();
- break;
- case AIState.reset:
- this.reset();
- break;
- case AIState.move:
- this.move();
- break;
- case AIState.leave:
- this.state = AIState.none;
- xGame.common.gameMgr.aiGameEnd(true);
- break;
- case AIState.select:
- this.selectBall();
- break;
- case AIState.turn:
- this.turnPole();
- break;
- case AIState.shoot:
- this.shoot();
- break;
- }
- }
- onAway(type) {
- if (type == 1)//逃跑
- {
- let db = xGame.common.gameMgr.aiBallArr.length - xGame.common.gameMgr.selfBallArr.length;
- let num = this.awayNum + db * 20;
- if (db > 0 && num > 0 && xGame.tools.random(0, 10000) < num && this.state == AIState.idle) {
- xGame.common.gameMgr.aiLeave();
- this.setState(AIState.leave, 6666);
- }
- }
- else if (type == 2) //不打(超时)
- {
- let db = xGame.common.gameMgr.aiBallArr.length - xGame.common.gameMgr.selfBallArr.length;
- let num = this.awayNum + db * 30;
- if (xGame.tools.random(0, 10000) < num)
- return false
- }
- else if (type == 3) //拉杆延迟(可能超时)
- {
- let db = xGame.common.gameMgr.aiBallArr.length - xGame.common.gameMgr.selfBallArr.length;
- let num = this.awayNum + db * 10;
- if (xGame.tools.random(0, 4000) < num)
- return false
- }
- return true;
- }
- chat() {
- if (this.chatTime > 0) {
- this.chatTime -= this.dtime;
- return;
- }
- this.chatTime = xGame.tools.random(2000, 10000);
- let rand = xGame.tools.random(0, 100);
- if (rand < 15)
- this.talk();
- else if (rand < 35)
- this.emotion();
- }
- talk() {
- xGame.common.talkMgr.showAITalk(0);
- }
- emotion() {
- xGame.common.talkMgr.showAIEmotion(0);
- }
- resetAI() {
- this.stopRun();
- this.state = AIState.none;
- }
- }
|