[add] first
This commit is contained in:
50
assets/scripts/core/ai/actor-task-go-target.ts
Normal file
50
assets/scripts/core/ai/actor-task-go-target.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { Vec3 } from "cc";
|
||||
import { ITask, TaskBase } from "./actor-tasks";
|
||||
import { ActorBase } from "../actor/actor-base";
|
||||
|
||||
export class ActorTaskGoTarget extends TaskBase {
|
||||
|
||||
name = 'ActorActionWay';
|
||||
actor:ActorBase | undefined;
|
||||
index = 0;
|
||||
waypoints = [];
|
||||
|
||||
isStart = false;
|
||||
|
||||
public init(_actor:ActorBase) {
|
||||
this.actor = _actor;
|
||||
}
|
||||
|
||||
public initWayPoints(_waypoints) {
|
||||
this.index = 0;
|
||||
this.waypoints = _waypoints;
|
||||
}
|
||||
|
||||
public update() {
|
||||
if (!this.isStart) return;
|
||||
if (!this.isWait) return;
|
||||
// check arrived
|
||||
if (Vec3.distance(this.actor!._data.pos, this.waypoints[this.index].pos) < 0.1) {
|
||||
|
||||
if (this.index >= this.waypoints.length) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// check actor direction.
|
||||
var dir = this.waypoints[this.index + 1].clone();
|
||||
dir.subtract(this.actor!._data.pos);
|
||||
this.actor!.setDir(dir);
|
||||
|
||||
// check action.
|
||||
this.onAction(this.waypoints[this.index].action);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onAction(action: string) {
|
||||
this.actor!.do(action);
|
||||
}
|
||||
|
||||
}
|
||||
9
assets/scripts/core/ai/actor-task-go-target.ts.meta
Normal file
9
assets/scripts/core/ai/actor-task-go-target.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "1cc27925-9541-445f-8e42-e93fbc26e5e3",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
141
assets/scripts/core/ai/actor-tasks.ts
Normal file
141
assets/scripts/core/ai/actor-tasks.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { game } from "cc";
|
||||
|
||||
export class TaskBase implements ITask {
|
||||
|
||||
name: string = '';
|
||||
isStart: boolean = false;
|
||||
isWait: boolean = false;
|
||||
tasks:ITask[] = [];
|
||||
|
||||
onCompleteFun:Function | undefined = undefined;
|
||||
|
||||
add(...tasks:ITask[]) {
|
||||
for(let i = 0; i < tasks.length; i++) {
|
||||
this.tasks.push(tasks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
start() {
|
||||
this.isStart = true;
|
||||
}
|
||||
|
||||
public sequence(task:ITask) {
|
||||
let sequence = new TaskSequence();
|
||||
sequence.add(task);
|
||||
this.tasks.push(sequence);
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public parallel(task:ITask) {
|
||||
let parallel = new TaskParallel();
|
||||
parallel.add(task);
|
||||
this.tasks.push(parallel);
|
||||
return parallel;
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!this.isStart) return;
|
||||
if (this.isWait) return;
|
||||
this.end();
|
||||
}
|
||||
|
||||
end() {
|
||||
this.isStart = false
|
||||
this.isWait = false;
|
||||
if (this.onCompleteFun !== null) {
|
||||
this.onCompleteFun();
|
||||
console.log('on complete:', this);
|
||||
}
|
||||
this.onCompleteFun = undefined;
|
||||
|
||||
console.log('on end:', this.name, game.frameTime);
|
||||
}
|
||||
|
||||
break() {
|
||||
for(let i = 0; i < this.tasks.length; i++) {
|
||||
this.tasks[i].break();
|
||||
}
|
||||
}
|
||||
|
||||
onComplete(call:Function) {
|
||||
this.onCompleteFun = call;
|
||||
}
|
||||
}
|
||||
|
||||
export class TaskSequence extends TaskBase {
|
||||
|
||||
index = 0;
|
||||
|
||||
start(): void {
|
||||
super.start();
|
||||
this.index = 0;
|
||||
this.tasks[this.index].start();
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!this.isStart) return;
|
||||
if (this.isWait) return;
|
||||
if (!this.tasks[this.index].isStart) {
|
||||
this.next();
|
||||
}else{
|
||||
this.tasks[this.index].update();
|
||||
}
|
||||
}
|
||||
|
||||
next() {
|
||||
this.index++;
|
||||
if (this.index >= this.tasks.length) {
|
||||
this.end();
|
||||
}else{
|
||||
this.tasks[this.index].start();
|
||||
}
|
||||
}
|
||||
|
||||
end(){
|
||||
super.end();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class TaskParallel extends TaskBase {
|
||||
|
||||
start(): void {
|
||||
super.start();
|
||||
for(let i = 0; i < this.tasks.length; i++) {
|
||||
this.tasks[i].start();
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!this.isStart) return;
|
||||
if (this.isWait) return;
|
||||
|
||||
for(let i = 0; i < this.tasks.length; i++) {
|
||||
this.tasks[i].update();
|
||||
}
|
||||
|
||||
// check all task is end.
|
||||
for(let i = 0; i < this.tasks.length; i++) {
|
||||
if (this.tasks[i].isStart) return;
|
||||
}
|
||||
this.end();
|
||||
}
|
||||
|
||||
end() {
|
||||
super.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export interface ITask {
|
||||
|
||||
name:string;
|
||||
isStart:boolean;
|
||||
isWait:boolean;
|
||||
start();
|
||||
end();
|
||||
break();
|
||||
update();
|
||||
|
||||
}
|
||||
|
||||
9
assets/scripts/core/ai/actor-tasks.ts.meta
Normal file
9
assets/scripts/core/ai/actor-tasks.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "1c3d50d3-1919-47cf-948b-1629335a8ec5",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
202
assets/scripts/core/ai/astar.ts
Normal file
202
assets/scripts/core/ai/astar.ts
Normal file
@@ -0,0 +1,202 @@
|
||||
import { instantiate, math, Node } from "cc";
|
||||
import { Singleton } from "../pattern/singleton";
|
||||
import { Stack } from "../util/data-structure";
|
||||
|
||||
|
||||
export class AStar extends Singleton {
|
||||
|
||||
map:any[];
|
||||
start_pos;
|
||||
end_pos;
|
||||
|
||||
closeTable = [];
|
||||
openTable:Stack<any[]>;
|
||||
|
||||
max_x = 0;
|
||||
max_z = 0;
|
||||
|
||||
dir = [
|
||||
[-1, 1], [0, 1], [1, 0],
|
||||
[-1, 0], [1, 0],
|
||||
[-1, -1], [0, -1], [1, -1]
|
||||
]
|
||||
|
||||
_tempNode:Node;
|
||||
|
||||
_stop = true;
|
||||
|
||||
public initMap(_map:[][]) {
|
||||
|
||||
this.map = [];
|
||||
this.max_x = _map.length;
|
||||
this.max_z = _map[0].length;
|
||||
|
||||
// init map
|
||||
for(let i = 0; i < this.max_x; i++) {
|
||||
let m = [];
|
||||
for(let j = 0; j < this.max_z; j++) {
|
||||
var v = {'f':-1, 'state': _map[i][j]};
|
||||
m.push(v);
|
||||
}
|
||||
this.map.push(m);
|
||||
}
|
||||
|
||||
console.log(this.map);
|
||||
|
||||
this.openTable = new Stack(20);
|
||||
this.closeTable = this.createTable(this.max_x, this.max_z, 0);
|
||||
this.copyTable(this.closeTable, this.map);
|
||||
}
|
||||
|
||||
setTestNode(node) {
|
||||
this._tempNode = node;
|
||||
}
|
||||
|
||||
testNode(pos) {
|
||||
let inst = instantiate(this._tempNode);
|
||||
inst.parent = this._tempNode.parent;
|
||||
inst.setPosition(pos[0],0,pos[1]);
|
||||
}
|
||||
|
||||
find(start_pos, end_pos) {
|
||||
|
||||
console.log('start:', start_pos, 'end:', end_pos);
|
||||
this._stop = false;
|
||||
this.start_pos = start_pos;
|
||||
this.end_pos = end_pos;
|
||||
// Set start pos into open table.
|
||||
this.openTable.push([start_pos.x, start_pos.z]);
|
||||
this.checkCurrent(start_pos);
|
||||
}
|
||||
|
||||
update() {
|
||||
|
||||
if (this._stop) return;
|
||||
|
||||
if (this.openTable.size() > 0) {
|
||||
var np = this.openTable.pop();
|
||||
this.testNode(np);
|
||||
this.checkCurrent({'x': np[0], 'z': np[1] });
|
||||
}else{
|
||||
console.log('can not find target pos.');
|
||||
}
|
||||
}
|
||||
|
||||
checkCurrent(pos) {
|
||||
|
||||
|
||||
|
||||
// Check is end pos.
|
||||
if (pos.x === this.end_pos.x && pos.z === this.end_pos.z) {
|
||||
console.log('find end pos.');
|
||||
this._stop = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set remove state in open table.
|
||||
this.map[pos.x][pos.z].state = 0;
|
||||
this.openTable.pop();
|
||||
|
||||
// Set current pos in close table.
|
||||
this.closeTable[pos.x][pos.z] = 1;
|
||||
|
||||
var min_index = -1;
|
||||
// Calculate around
|
||||
for(let i = 0; i < this.dir.length; i++) {
|
||||
|
||||
var nx = pos.x + this.dir[i][0];
|
||||
var nz = pos.z + this.dir[i][1];
|
||||
|
||||
// Check bounder.
|
||||
if (nx < 0 || nz < 0 || nx >= this.max_x || nz >= this.max_z) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check is not close table.
|
||||
if (this.closeTable[nx][nz] === 1) continue;
|
||||
|
||||
// Check is dir cost.
|
||||
var f = this.f_cost({'x': nx, 'z': nz}, this.end_pos);
|
||||
this.map[nx][nz].cost = f;
|
||||
|
||||
// Push new check point into open table.
|
||||
this.openTable.push([nx, nz]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public f_cost(cur_pos, end_pos) {
|
||||
return Math.abs(cur_pos.x - end_pos.x) + Math.abs(cur_pos.z - end_pos.z)
|
||||
}
|
||||
|
||||
createTable(x:number, y:number, value) {
|
||||
var l0 = x;
|
||||
var l1 = y;
|
||||
var table = [];
|
||||
for(let i = 0; i < l0; i++) {
|
||||
var m = [];
|
||||
for(let j = 0; j < l1; j++) {
|
||||
m.push(value);
|
||||
}
|
||||
table.push(m);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
copyTable(target, source) {
|
||||
var l0 = this.max_x;
|
||||
var l1 = this.max_z;
|
||||
for(let i = 0; i < l0; i++) {
|
||||
for(let j = 0; j < l1; j++) {
|
||||
target[i][j] = source[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearTable(table) {
|
||||
var l0 = table.length;
|
||||
var l1 = table[0].length;
|
||||
for(let i = 0; i < l0; i++) {
|
||||
for(let j = 0; j < l1; j++) {
|
||||
table[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
findMinCostPoint(cur_pos) {
|
||||
|
||||
var min_cost_pos = { 'x': -1, 'z': -1 };
|
||||
|
||||
// Calculate f_cost
|
||||
for(let i = 0; i < this.dir.length; i++) {
|
||||
var nx = cur_pos.x + this.dir[i][0];
|
||||
var nz = cur_pos.z + this.dir[i][1];
|
||||
|
||||
// Check bounder.
|
||||
if (nx < 0 || nz < 0 || nx >= this.max_x || nz >= this.max_z) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check is not close table.
|
||||
if (this.closeTable[nx][nz] === 1) continue;
|
||||
|
||||
// Check is
|
||||
|
||||
}
|
||||
|
||||
if (min_cost_pos.x === -1) {
|
||||
console.error(' can not find min cost pos:', cur_pos);
|
||||
}
|
||||
|
||||
//for()
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
9
assets/scripts/core/ai/astar.ts.meta
Normal file
9
assets/scripts/core/ai/astar.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "9adbae1b-78aa-476e-b7a4-106d73f978af",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
81
assets/scripts/core/ai/brain.ts
Normal file
81
assets/scripts/core/ai/brain.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { _decorator, Component, Node, random } from 'cc';
|
||||
import { ResCache } from '../res/res-cache';
|
||||
import { ActorBase } from '../actor/actor-base';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
export class Brain {
|
||||
|
||||
data = {};
|
||||
|
||||
actor:ActorBase;
|
||||
|
||||
constructor(dataPath:string, actor:ActorBase) {
|
||||
|
||||
this.data = ResCache.Instance.getJson(dataPath).json;
|
||||
this.actor = actor;
|
||||
|
||||
}
|
||||
|
||||
update(deltaTime:number) {
|
||||
|
||||
}
|
||||
|
||||
runNode(data) {
|
||||
|
||||
// find action.
|
||||
if (data.children === undefined) {
|
||||
this.action(data.action);
|
||||
}else{
|
||||
console.log('run node:', data.node);
|
||||
this[data.node](data.children);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
random(data) {
|
||||
var rand = random();
|
||||
for(let i = 0; i < data.length; i++) {
|
||||
let info = data[i];
|
||||
if (info.value < rand) {
|
||||
this.runNode(info);
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.error('bad config data:', data);
|
||||
}
|
||||
|
||||
condition(data) {
|
||||
|
||||
console.log('condition:', data);
|
||||
|
||||
for(let i = 0; i < data.length; i++) {
|
||||
let info = data[i];
|
||||
if (info.value === 'canEatPlayer') {
|
||||
this.runNode(info);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('bad logic design:', data);
|
||||
|
||||
}
|
||||
|
||||
sequence(data) {
|
||||
|
||||
console.log('sequence:', data);
|
||||
|
||||
for(let i = 0; i < data.length; i++) {
|
||||
let info = data[i];
|
||||
this.runNode(info);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
action(data) {
|
||||
|
||||
console.log('do action:', data);
|
||||
this.actor.do(data);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
9
assets/scripts/core/ai/brain.ts.meta
Normal file
9
assets/scripts/core/ai/brain.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "e413c24f-b1a6-4f54-a679-f358292cf9fe",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/scripts/core/ai/steering-behaviors.meta
Normal file
12
assets/scripts/core/ai/steering-behaviors.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "6f763d6d-aa7e-49f9-a175-3dcd81456f09",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
15
assets/scripts/core/ai/steering-behaviors/steering-basic.ts
Normal file
15
assets/scripts/core/ai/steering-behaviors/steering-basic.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { _decorator, Component, Node, v3, Vec3 } from 'cc';
|
||||
import { UtilVec3 } from '../../util/util';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('SteeringBasic')
|
||||
export class SteeringBasic extends Component {
|
||||
|
||||
moveVelocity = v3(0, 0, 0);
|
||||
desiredVelocity = v3(0, 0, 0);
|
||||
|
||||
target:Node | undefined;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "12bbaeaa-0095-45f4-a525-d9427a0415ae",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { _decorator, Component, Node, v3, Vec3 } from 'cc';
|
||||
import { UtilVec3 } from '../../util/util';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('SteeringBehaviors')
|
||||
export class SteeringBehaviors extends Component {
|
||||
|
||||
moveVelocity = v3(0, 0, 0);
|
||||
desiredVelocity = v3(0, 0, 0);
|
||||
|
||||
start() {
|
||||
|
||||
}
|
||||
|
||||
update(deltaTime: number) {
|
||||
|
||||
}
|
||||
|
||||
Seek(targetPos:Vec3) {
|
||||
UtilVec3.copy(this.desiredVelocity, targetPos);
|
||||
this.desiredVelocity.subtract(this.node.worldPosition);
|
||||
return this.desiredVelocity.subtract(this.moveVelocity);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "c08e76ca-d8f3-4903-a1ac-8925fc3175e1",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
37
assets/scripts/core/ai/steering-behaviors/steering-seek.ts
Normal file
37
assets/scripts/core/ai/steering-behaviors/steering-seek.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { _decorator, Component, Node, v3, Vec3 } from 'cc';
|
||||
import { UtilVec3 } from '../../util/util';
|
||||
import { SteeringBasic } from './steering-basic';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('SteeringSeek')
|
||||
export class SteeringSeek extends Component {
|
||||
|
||||
moveVelocity = v3(0, 0, 0);
|
||||
desiredVelocity = v3(0, 0, 0);
|
||||
|
||||
steeringBasic:SteeringBasic | undefined;
|
||||
|
||||
start() {
|
||||
|
||||
this.steeringBasic = this.getComponent(SteeringBasic)!;
|
||||
|
||||
}
|
||||
|
||||
update(deltaTime: number) {
|
||||
|
||||
}
|
||||
|
||||
SeekToward() {
|
||||
|
||||
}
|
||||
|
||||
Seek(targetPos:Vec3) {
|
||||
|
||||
const target = this.steeringBasic?.target!;
|
||||
UtilVec3.copy(this.desiredVelocity, target.position);
|
||||
|
||||
this.desiredVelocity.subtract(this.node.worldPosition);
|
||||
return this.desiredVelocity.subtract(this.moveVelocity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "28c76b96-63e9-4483-ab6f-29cba727408f",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
Reference in New Issue
Block a user