249 lines
5.5 KiB
TypeScript
249 lines
5.5 KiB
TypeScript
|
import BattleObj from "../object/BattleObj";
|
|||
|
|
|||
|
var assert = require('assert');
|
|||
|
|
|||
|
/* object 格式
|
|||
|
obj = {
|
|||
|
onlyid = onlyid,
|
|||
|
x = x,
|
|||
|
y = y,
|
|||
|
dir = dir,
|
|||
|
aoi_model = "w", // "w"、"m"、“wm "、"mw "
|
|||
|
dst = 10, --观察半径
|
|||
|
isplayer = false,
|
|||
|
ismonster = false,
|
|||
|
isnpc = false,
|
|||
|
}
|
|||
|
*/
|
|||
|
|
|||
|
export default class Aoi{
|
|||
|
w:number;
|
|||
|
h:number;
|
|||
|
obj_list:any;
|
|||
|
obj_list_x:any;
|
|||
|
obj_list_y:any;
|
|||
|
dst_max:number;
|
|||
|
|
|||
|
constructor() {
|
|||
|
this.w = 300;
|
|||
|
this.h = 300;
|
|||
|
this.obj_list = {}
|
|||
|
this.obj_list_x = {}
|
|||
|
this.obj_list_y = {}
|
|||
|
this.dst_max = 40 //最大观察半径
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
is_watcher(obj:any):boolean{
|
|||
|
if (obj.aoi_model == "w" || obj.aoi_model == "wm" || obj.aoi_model == "mw") {
|
|||
|
return true;
|
|||
|
} else {
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
is_maker(obj:any):boolean{
|
|||
|
if (obj.aoi_model == "m" || obj.aoi_model == "wm" || obj.aoi_model == "mw") {
|
|||
|
return true;
|
|||
|
} else {
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
dispatch_message(obj:any, func:any) {
|
|||
|
assert(func);
|
|||
|
if (this.is_maker(obj)) {
|
|||
|
// 按照设置的最大视野范围遍历x轴
|
|||
|
let tmps = obj.x - this.dst_max;
|
|||
|
if (tmps <= 0) {
|
|||
|
tmps = 1;
|
|||
|
}
|
|||
|
let tmpe = obj.x + this.dst_max;
|
|||
|
if (tmpe > this.w) {
|
|||
|
tmpe = this.w;
|
|||
|
}
|
|||
|
|
|||
|
for (let i = tmps; i < tmpe; i++) {
|
|||
|
if (i <= 0) {
|
|||
|
break;
|
|||
|
}
|
|||
|
if (this.obj_list_x[i]) {
|
|||
|
for (const k in this.obj_list_x[i]) {
|
|||
|
if (this.obj_list_x[i].hasOwnProperty(k)) {
|
|||
|
const v = this.obj_list_x[i][k];
|
|||
|
if (v == null) continue;
|
|||
|
// 是观察者,并且在他的视野范围内
|
|||
|
if (this.is_watcher(v) && Math.abs(v.x - obj.x) <= this.dst_max && Math.abs(v.y - obj.y) <= this.dst_max && v != obj) {
|
|||
|
// 执行更新回调
|
|||
|
func(obj, v)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
get_watcher(obj:any) {
|
|||
|
let list:any = {};
|
|||
|
let tmps = obj.x - this.dst_max;
|
|||
|
if (tmps <= 0) {
|
|||
|
tmps = 1;
|
|||
|
}
|
|||
|
|
|||
|
let tmpe = obj.x + this.dst_max;
|
|||
|
if (tmpe > this.w) {
|
|||
|
tmpe = this.w;
|
|||
|
}
|
|||
|
|
|||
|
for (let i = tmps; i <= tmpe; i++) {
|
|||
|
if (i <= 0) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (this.obj_list_x[i]) {
|
|||
|
for (const k in this.obj_list_x[i]) {
|
|||
|
if (this.obj_list_x[i].hasOwnProperty(k)) {
|
|||
|
const v = this.obj_list_x[i][k];
|
|||
|
if (v == null) continue;
|
|||
|
if (this.is_watcher(v) && Math.abs(v.y - obj.y) <= this.dst_max && Math.abs(v.x - obj.x) <= this.dst_max && v != obj) {
|
|||
|
list[k] = v;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return list;
|
|||
|
}
|
|||
|
|
|||
|
get_maker(obj:any, isproto?:any) {
|
|||
|
let list:any = {};
|
|||
|
let tmps = obj.x - this.dst_max;
|
|||
|
if (tmps < 0) {
|
|||
|
tmps = 0;
|
|||
|
}
|
|||
|
|
|||
|
let tmpe = obj.x + this.dst_max;
|
|||
|
if (tmpe > this.w) {
|
|||
|
tmpe = this.w;
|
|||
|
}
|
|||
|
|
|||
|
for (let i = tmps; i <= tmpe; i++) {
|
|||
|
if (i < 0) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (this.obj_list_x[i]) {
|
|||
|
for (const k in this.obj_list_x[i]) {
|
|||
|
if (this.obj_list_x[i].hasOwnProperty(k)) {
|
|||
|
const v = this.obj_list_x[i][k];
|
|||
|
if (v == null) continue;
|
|||
|
if (this.is_maker(v) && Math.abs(v.y - obj.y) <= this.dst_max && Math.abs(v.x - obj.x) <= this.dst_max && v != obj) {
|
|||
|
list[k] = v;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return list;
|
|||
|
}
|
|||
|
|
|||
|
init(width:any, height:any, maxdst:any) {
|
|||
|
this.w = width == null ? this.w : width;
|
|||
|
this.h = height == null ? this.h : height;
|
|||
|
this.dst_max = maxdst == null ? this.dst_max : maxdst;
|
|||
|
}
|
|||
|
|
|||
|
enter(obj:any, func:any) {
|
|||
|
this.obj_list[obj.onlyid] = obj;
|
|||
|
|
|||
|
if (!this.obj_list_x[obj.x]) {
|
|||
|
this.obj_list_x[obj.x] = {};
|
|||
|
}
|
|||
|
|
|||
|
if (!this.obj_list_y[obj.y]) {
|
|||
|
this.obj_list_y[obj.y] = {};
|
|||
|
}
|
|||
|
|
|||
|
this.obj_list_x[obj.x][obj.onlyid] = obj;
|
|||
|
this.obj_list_y[obj.y][obj.onlyid] = obj;
|
|||
|
|
|||
|
// 如果是maker模式, 广播给所有视野范围的带w模式的obj
|
|||
|
this.dispatch_message(obj, func);
|
|||
|
|
|||
|
// 如果是watcher模式, 在进入之后返回视野上所有带m模式的obj
|
|||
|
if (this.is_watcher(obj)) {
|
|||
|
return this.get_maker(obj);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
remove(obj:any, func:any) {
|
|||
|
delete this.obj_list[obj.onlyid];
|
|||
|
delete this.obj_list_x[obj.x][obj.onlyid];
|
|||
|
delete this.obj_list_y[obj.y][obj.onlyid];
|
|||
|
// 如果是m活着mw模式, 需要广播给其他所有视野范围的w
|
|||
|
this.dispatch_message(obj, func)
|
|||
|
}
|
|||
|
// 需要计算更新之前和更新之后的交集作为广播集合
|
|||
|
update(obj:any, x:any, y:any, updatefunc:any, enterfunc:any, exitfunc:any):BattleObj[]{
|
|||
|
let bef_w_list = this.get_watcher(this.obj_list[obj.onlyid])
|
|||
|
let bef_m_list = this.get_maker(this.obj_list[obj.onlyid])
|
|||
|
|
|||
|
delete this.obj_list_x[obj.x][obj.onlyid];
|
|||
|
delete this.obj_list_y[obj.y][obj.onlyid];
|
|||
|
|
|||
|
obj.x = x;
|
|||
|
obj.y = y;
|
|||
|
if (!this.obj_list_x[obj.x]) {
|
|||
|
this.obj_list_x[obj.x] = {};
|
|||
|
}
|
|||
|
|
|||
|
if (!this.obj_list_y[obj.y]) {
|
|||
|
this.obj_list_y[obj.y] = {};
|
|||
|
}
|
|||
|
|
|||
|
this.obj_list[obj.onlyid] = obj;
|
|||
|
this.obj_list_x[obj.x][obj.onlyid] = obj;
|
|||
|
this.obj_list_y[obj.y][obj.onlyid] = obj;
|
|||
|
|
|||
|
let aft_w_list = this.get_watcher(obj);
|
|||
|
let aft_m_list = this.get_maker(obj);
|
|||
|
|
|||
|
if (this.is_maker(obj)) {
|
|||
|
for (const k in aft_w_list) {
|
|||
|
if (aft_w_list.hasOwnProperty(k)) {
|
|||
|
const v = aft_w_list[k];
|
|||
|
if (bef_w_list[k]) {
|
|||
|
updatefunc(obj, v); // 更新交集
|
|||
|
} else {
|
|||
|
enterfunc(obj, v); //新增进入视野
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 走出对方的视野了也通知对方做退出视野的相关操作
|
|||
|
for (const k in bef_w_list) {
|
|||
|
if (bef_w_list.hasOwnProperty(k)) {
|
|||
|
const v = bef_w_list[k];
|
|||
|
if (!aft_w_list[k]) {
|
|||
|
exitfunc(obj, v);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
let list = [];
|
|||
|
if (this.is_watcher(obj)) {
|
|||
|
//找出新增的部分,需要更新到前端
|
|||
|
for (const k in aft_m_list) {
|
|||
|
if (aft_m_list.hasOwnProperty(k)) {
|
|||
|
const v = aft_m_list[k];
|
|||
|
if (!bef_m_list[k]) {
|
|||
|
list.push(v);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return list;
|
|||
|
}
|
|||
|
}
|