2025-04-23 09:34:08 +08:00

249 lines
5.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}