Comparing version
@@ -7,15 +7,15 @@ var Tower = require('./tower'); | ||
var TowerAOI = function(config){ | ||
this.map = config.map; | ||
this.towerConfig = config.tower; | ||
this.width = config.tower.width; | ||
this.height = config.tower.height; | ||
this.width = config.width; | ||
this.height = config.height; | ||
this.towerWidth = config.towerWidth; | ||
this.towerHeight = config.towerHeight; | ||
this.towers = {}; | ||
this.rangeLimit = 5 || config.limit; | ||
this.init(config); | ||
} | ||
this.init(); | ||
}; | ||
util.inherits(TowerAOI, EventEmitter); | ||
@@ -26,17 +26,14 @@ | ||
pro.init = function(){ | ||
var map = this.map; | ||
var tower = this.towerConfig; | ||
this.max = { | ||
x: Math.ceil(map.width/tower.width) - 1, | ||
y: Math.ceil(map.height/tower.height) - 1 | ||
} | ||
x: Math.ceil(this.width/this.towerWidth) - 1, | ||
y: Math.ceil(this.height/this.towerHeight) - 1 | ||
}; | ||
for(var i = 0; i<Math.ceil(map.width/tower.width); i++){ | ||
for(var i = 0; i<Math.ceil(this.width/this.towerWidth); i++){ | ||
this.towers[i] = {}; | ||
for(var j = 0; j < Math.ceil(map.height/tower.height); j++){ | ||
this.towers[i][j] = Tower.create(); | ||
for(var j = 0; j < Math.ceil(this.height/this.towerHeight); j++){ | ||
this.towers[i][j] = Tower.create(); | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
@@ -46,3 +43,3 @@ /** | ||
* @param pos {Object} The pos to find objects | ||
* @param range {Number} The range to find the object, in tower aoi, it means the tower number from the pos | ||
* @param range {Number} The range to find the object, in tower aoi, it means the tower number from the pos | ||
* @param types {Array} The types of the object need to find | ||
@@ -53,7 +50,8 @@ */ | ||
return []; | ||
var result = {}; | ||
var p = this.transPos(pos); | ||
var limit = getPosLimit(p, range, this.max); | ||
//console.error('get Ids p : %j, range : %j limit : %j, max : %j', p, range, limit, this.max); | ||
for(var i = limit.start.x; i <= limit.end.x; i++){ | ||
@@ -65,3 +63,3 @@ for(var j = limit.start.y; j <= limit.end.y; j++){ | ||
return result; | ||
} | ||
}; | ||
@@ -74,9 +72,9 @@ /** | ||
return []; | ||
var result = []; | ||
range = range>5?5:range; | ||
var p = this.transPos(pos); | ||
var limit = getPosLimit(p, range, this.max); | ||
//console.error('get Ids p : %j, range : %j limit : %j, max : %j', p, range, limit, this.max); | ||
@@ -89,3 +87,3 @@ for(var i = limit.start.x; i <= limit.end.x; i++){ | ||
return result; | ||
} | ||
}; | ||
@@ -102,5 +100,5 @@ /** | ||
} | ||
return false; | ||
} | ||
}; | ||
@@ -117,13 +115,13 @@ /** | ||
} | ||
return false; | ||
} | ||
}; | ||
pro.updateObject = function(obj, oldPos, newPos){ | ||
if(!this.checkPos(oldPos.x, oldPos.y) || !this.checkPos(newPos.x, newPos.y)) | ||
if(!this.checkPos(oldPos) || !this.checkPos(newPos)) | ||
return false; | ||
var p1 = this.transPos(oldPos); | ||
var p2 = this.transPos(newPos); | ||
if(p1.x===p2.x && p1.y===p2.y) | ||
@@ -145,3 +143,3 @@ return true; | ||
} | ||
} | ||
}; | ||
@@ -156,17 +154,17 @@ | ||
return false; | ||
if(pos.x < 0 || pos.y < 0 || pos.x >= this.map.width || pos.y >= this.map.height) | ||
if(pos.x < 0 || pos.y < 0 || pos.x >= this.width || pos.y >= this.height) | ||
return false; | ||
return true; | ||
} | ||
}; | ||
/** | ||
* Trans the absolut pos to tower pos. For example : (210, 110} -> (1, 0), for tower width 200, height 200 | ||
* | ||
* | ||
*/ | ||
pro.transPos = function(pos){ | ||
return { | ||
x : Math.floor(pos.x/this.towerConfig.width), | ||
y : Math.floor(pos.y/this.towerConfig.height) | ||
} | ||
} | ||
x : Math.floor(pos.x/this.towerWidth), | ||
y : Math.floor(pos.y/this.towerHeight) | ||
}; | ||
}; | ||
@@ -176,7 +174,7 @@ pro.addWatcher = function(watcher, pos, range){ | ||
return; | ||
range = range > 5?5:range; | ||
var p = this.transPos(pos); | ||
var limit = getPosLimit(p, range, this.max); | ||
for(var i = limit.start.x; i <= limit.end.x; i++){ | ||
@@ -187,3 +185,3 @@ for(var j = limit.start.y; j <= limit.end.y; j++){ | ||
} | ||
} | ||
}; | ||
@@ -193,8 +191,8 @@ pro.removeWatcher = function(watcher, pos, range){ | ||
return; | ||
range = range > 5?5:range; | ||
var p = this.transPos(pos); | ||
var limit = getPosLimit(p, range, this.max); | ||
for(var i = limit.start.x; i <= limit.end.x; i++){ | ||
@@ -205,20 +203,21 @@ for(var j = limit.start.y; j <= limit.end.y; j++){ | ||
} | ||
} | ||
}; | ||
pro.updateWatcher = function(watcher, oldPos, newPos, oldRange, newRange){ | ||
if(!this.checkPos(oldPos.x, oldPos.y) || !this.checkPos(newPos.x, newPos.y)) | ||
if(!this.checkPos(oldPos) || !this.checkPos(newPos)) | ||
return false; | ||
var p1 = this.transPos(oldPos); | ||
var p2 = this.transPos(newPos); | ||
if(p1.x===p2.x && p1.y===p2.y && oldRange===newRange) | ||
return true; | ||
else{ | ||
if(oldRange < 0 || newRange < 0) | ||
return false; | ||
oldRange = oldRange>5?5:oldRange; | ||
newRange = newRange>5?5:newRange; | ||
if(oldRange < 0 || newRange < 0){ | ||
return false; | ||
} | ||
oldRange = oldRange>5?5:oldRange; | ||
newRange = newRange>5?5:newRange; | ||
var changedTowers = getChangedTowers(p1, p2, oldRange, newRange, this.towers, this.max); | ||
@@ -229,18 +228,20 @@ var removeTowers = changedTowers.removeTowers; | ||
var removeObjs = []; | ||
for(var i = 0; i < addTowers.length; i++){ | ||
addTowers[i].addWatcher(watcher); | ||
var ids = addTowers[i].getIds(); | ||
addMap(addObjs, ids); | ||
var i, ids; | ||
for(i = 0; i < addTowers.length; i++){ | ||
addTowers[i].addWatcher(watcher); | ||
ids = addTowers[i].getIds(); | ||
addMap(addObjs, ids); | ||
} | ||
for(var i = 0; i < removeTowers.length; i++){ | ||
removeTowers[i].removeWatcher(watcher); | ||
var ids = removeTowers[i].getIds(); | ||
addMap(removeObjs, ids); | ||
} | ||
for(i = 0; i < removeTowers.length; i++){ | ||
removeTowers[i].removeWatcher(watcher); | ||
ids = removeTowers[i].getIds(); | ||
addMap(removeObjs, ids); | ||
} | ||
this.emit('updateWatcher', {id: watcher.id, type:watcher.type, addObjs: addObjs, removeObjs:removeObjs}); | ||
return true; | ||
} | ||
} | ||
}; | ||
@@ -255,3 +256,3 @@ /** | ||
* @param max {Object} The position limit of the towers | ||
* | ||
* | ||
*/ | ||
@@ -264,3 +265,3 @@ function getChangedTowers(p1, p2, r1, r2, towers, max){ | ||
var unChangeTowers = []; | ||
for(var x = limit1.start.x; x <= limit1.end.x; x++){ | ||
@@ -274,4 +275,4 @@ for(var y = limit1.start.y; y <= limit1.end.y; y++){ | ||
} | ||
} | ||
} | ||
for(var x = limit2.start.x; x <= limit2.end.x; x++){ | ||
@@ -283,4 +284,4 @@ for(var y = limit2.start.y; y <= limit2.end.y; y++){ | ||
} | ||
} | ||
} | ||
return {addTowers:addTowers, removeTowers: removeTowers, unChangeTowers: unChangeTowers}; | ||
@@ -294,3 +295,3 @@ } | ||
* @param max {max} The limit, the result will not exceed the limit | ||
* @return The pos limitition | ||
* @return The pos limitition | ||
*/ | ||
@@ -300,3 +301,3 @@ function getPosLimit(pos, range, max){ | ||
var start = {}, end = {}; | ||
if(pos.x - range < 0){ | ||
@@ -312,3 +313,3 @@ start.x = 0; | ||
} | ||
if(pos.y - range < 0){ | ||
@@ -324,3 +325,3 @@ start.y = 0; | ||
} | ||
start.x = start.x>=0?start.x:0; | ||
@@ -330,3 +331,3 @@ end.x = end.x<=max.x?end.x:max.x; | ||
end.y = end.y<=max.y?end.y:max.y; | ||
return {start: start, end :end}; | ||
@@ -347,5 +348,5 @@ } | ||
} | ||
return null; | ||
} | ||
}; | ||
@@ -369,6 +370,6 @@ /** | ||
var type = types[i]; | ||
if(!map[type]) | ||
continue; | ||
if(!result[type]){ | ||
@@ -378,3 +379,3 @@ result[type] = []; | ||
for(var key in map[type]){ | ||
result[type].push(map[type][key]); | ||
result[type].push(map[type][key]); | ||
} | ||
@@ -387,3 +388,3 @@ } | ||
return new TowerAOI(config); | ||
} | ||
}; | ||
{ | ||
"name": "pomelo-aoi", | ||
"version": "0.3.33", | ||
"version": "0.3.34", | ||
"main": "./lib/aoiService", | ||
@@ -5,0 +5,0 @@ "author": { |
@@ -52,3 +52,3 @@ # pomelo-aoi | ||
##Hanler aoi event | ||
##Handle aoi event | ||
The aoi service will generate event when the status of objects or watchers changes. You can handler these event : | ||
@@ -55,0 +55,0 @@ ``` javascript |
@@ -6,13 +6,8 @@ var aoiService = require('../lib/aoiService'); | ||
config = { | ||
map:{ | ||
width: 10000, | ||
height: 10000, | ||
id: 1001 | ||
}, | ||
tower:{ | ||
width: 100, | ||
height: 100 | ||
} | ||
} | ||
width: 10000, | ||
height: 10000, | ||
towerWidth: 100, | ||
towerHeight: 100 | ||
}; | ||
return aoiService.getService(config); | ||
@@ -25,11 +20,10 @@ } | ||
var aoi = initAoi(); | ||
var w = config.map.width; | ||
var h = config.map.height; | ||
var count = 5000; | ||
var w = config.width; | ||
var h = config.height; | ||
var count = 10000; | ||
users = {}; | ||
var id = 0; | ||
var types = ['player', 'mob', 'npc']; | ||
for(var i = 0; i < count; i++, id++){ | ||
@@ -43,19 +37,19 @@ users[id] = { | ||
type: types[i%3] | ||
} | ||
}; | ||
} | ||
for(var id in users){ | ||
aoi.addObject(users[id], users[id].pos) | ||
for(id in users){ | ||
aoi.addObject(users[id], users[id].pos); | ||
} | ||
testPos(users, w, h, aoi, types); | ||
//testPath(users, w, h, aoi); | ||
posTest(w, h, aoi, types); | ||
//pathTest(users, w, h, aoi); | ||
} | ||
function testPath(users, w, h, aoi){ | ||
function pathTest(w, h, aoi){ | ||
var testCount = 100; | ||
var testPath = []; | ||
var width = config.map.width; | ||
var height = config.map.height; | ||
var width = config.width; | ||
var height = config.height; | ||
//The max move distance | ||
@@ -66,29 +60,29 @@ var max = 600; | ||
var start = { | ||
x: Math.floor(Math.random()*w), | ||
x : Math.floor(Math.random()*w), | ||
y : Math.floor(Math.random()*h) | ||
}; | ||
//���������ƶ� | ||
var dis = Math.floor(Math.random()*max); | ||
direction = Math.random>0.5?-1:1 | ||
direction = Math.random>0.5?-1:1; | ||
var xMove = Math.floor(Math.random()*dis) * direction; | ||
direction = Math.random>0.5?-1:1 | ||
direction = Math.random>0.5?-1:1; | ||
var yMove = Math.floor(Math.sqrt(dis*dis - xMove*xMove)) * direction; | ||
direction *= -1; | ||
var x = start.x + xMove; | ||
var y = start.y + yMove; | ||
x = x<0?0:x>width?width:x; | ||
y = y<0?0:y>height?height:y; | ||
y = y<0?0:y>height?height:y; | ||
var end = { | ||
x: x, | ||
y: y | ||
} | ||
}; | ||
testPath.push([start, end]); | ||
} | ||
var avg = 0; | ||
@@ -98,6 +92,4 @@ for(var i = 0; i < testCount; i++){ | ||
var ids1 = aoi.getIdsByPath(testPath[i][0], testPath[i][1]).sort(sort); | ||
var ids2 = getRightArrByPath(testPath[i], users) | ||
var ids2 = getRightArrByPath(testPath[i], users); | ||
if(!equals(ids1, ids2)){ | ||
@@ -112,70 +104,63 @@ console.error('test case error, path : ' + JSON.stringify(testPath[i])); | ||
} | ||
avg += (ids1.length -avg)/(i+1); | ||
} | ||
console.error(avg); | ||
console.error(avg); | ||
} | ||
function testPos(users, w, h, aoi, types){ | ||
function posTest(w, h, aoi, types){ | ||
var testCount = 100; | ||
var testPos = []; | ||
for (var i = 0; i < testCount; i++){ | ||
var i; | ||
for (i = 0; i < testCount; i++){ | ||
testPos.push({ | ||
x: Math.floor(Math.random()*w), | ||
x : Math.floor(Math.random()*w), | ||
y : Math.floor(Math.random()*h) | ||
}); | ||
} | ||
var avg = 0; | ||
var range = 3; | ||
for(var i = 0; i < testCount; i++){ | ||
for(i = 0; i < testCount; i++){ | ||
var ids1 = aoi.getIdsByRange(testPos[i], range, types); | ||
for(var type in ids1) | ||
ids1[type].sort(sort); | ||
var ids2 = getRightArrByPos(testPos[i], users, range, types) | ||
//console.error(ids1); | ||
//console.error(ids2); | ||
ids1[type].sort(sort); | ||
var ids2 = getRightArrByPos(testPos[i], range, types); | ||
if(!mapEquals(ids1, ids2, types)){ | ||
//console.error(users); | ||
console.error('test case error'); | ||
console.error('test case error! pos : %j', testPos[i]); | ||
console.error(ids1); | ||
console.error(ids2); | ||
break; | ||
} | ||
//avg += (ids1.length -avg)/(i+1); | ||
} | ||
//console.error(avg); | ||
} | ||
function getRightArrByPos(pos, users, range, types){ | ||
function getRightArrByPos(pos, range, types){ | ||
var result = {}; | ||
var w = config.tower.width; | ||
var h = config.tower.height; | ||
var w = config.towerWidth; | ||
var h = config.towerHeight; | ||
var x = Math.floor(pos.x/w) * w; | ||
var y = Math.floor(pos.y/h) * h; | ||
var x1 = x - w*range, x2 = x + w*(range+1); | ||
var y1 = y - h*range, y2 = y + h*(range+1); | ||
//console.error('x1 : ' + x1 + ' , x2 : ' + x2 + ' , y1 : ' + y1 + ' , y2 : ' + y2) | ||
var limit = getPosLimit(pos, range); | ||
//console.log('right pos start : %j, end : %j', limit.start, limit.end); | ||
for(var id in users){ | ||
var pos = users[id].pos; | ||
var p = users[id].pos; | ||
var type = users[id].type; | ||
if(pos.x >= x1 && pos.x < x2 && pos.y >= y1 && pos.y < y2){ | ||
//result.push(id); | ||
if(p.x >= limit.start.x && p.x < limit.end.x && p.y >= limit.start.y && p.y < limit.end.y){ | ||
if(!result[type]) | ||
result[type] = []; | ||
result[type].push(users[id].id); | ||
} | ||
} | ||
for(var type in result){ | ||
@@ -189,15 +174,15 @@ result[type].sort(sort); | ||
var result = []; | ||
var w = config.tower.width; | ||
var h = config.tower.height; | ||
var w = config.towerWidth; | ||
var h = config.towerHeight; | ||
var p1 = path[0], p2 = path[1]; | ||
var x1 = Math.floor((p1.x<p2.x?p1.x:p2.x)/w) * w - w; | ||
var y1 = Math.floor((p1.y<p2.y?p1.y:p2.y)/h) * h - h; | ||
var x2 = Math.floor((p1.x>p2.x?p1.x:p2.x)/w) * w + w + w; | ||
var y2 = Math.floor((p1.y>p2.y?p1.y:p2.y)/h) * h + h + h; | ||
//console.error('x1 : ' + x1 + ' , x2 : ' + x2 + ' , y1 : ' + y1 + ' , y2 : ' + y2) | ||
for(var id in users){ | ||
@@ -220,3 +205,3 @@ var pos = users[id].pos; | ||
} | ||
for(var i = 0; i < arr1.length; i++){ | ||
@@ -226,5 +211,4 @@ if(arr1[i] != arr2[i]) | ||
} | ||
return true; | ||
} | ||
@@ -235,13 +219,14 @@ | ||
var key = keys[i]; | ||
if(!map1[key] && !map2[key]) | ||
continue; | ||
if(!map1[key] || !map2[key]) | ||
if(!map1[key] || !map2[key]){ | ||
return false; | ||
} | ||
if(!arrayEquals(map1[key], map2[key])){ | ||
return false; | ||
return false; | ||
} | ||
} | ||
return true; | ||
@@ -256,2 +241,55 @@ } | ||
} | ||
function getPosLimit(p, range){ | ||
var w = config.towerWidth; | ||
var h = config.towerHeight; | ||
var max = { | ||
x : config.width/w, | ||
y : config.height/h | ||
}; | ||
var pos = { | ||
x : Math.floor(p.x/w), | ||
y : Math.floor(p.y/h) | ||
}; | ||
var result = {}; | ||
var start = {}, end = {}; | ||
if(pos.x - range < 0){ | ||
start.x = 0; | ||
end.x = 2*range; | ||
}else if(pos.x + range >= max.x){ | ||
end.x = max.x; | ||
start.x = max.x - 2*range - 1; | ||
}else{ | ||
start.x = pos.x - range; | ||
end.x = pos.x + range; | ||
} | ||
if(pos.y - range < 0){ | ||
start.y = 0; | ||
end.y = 2*range; | ||
}else if(pos.y + range >= max.y){ | ||
end.y = max.y; | ||
start.y = max.y - 2*range - 1; | ||
}else{ | ||
start.y = pos.y - range; | ||
end.y = pos.y + range; | ||
} | ||
start.x = (start.x>=0?start.x:0) * w; | ||
end.x = (end.x<=max.x?end.x:max.x) * w + w; | ||
start.y = (start.y>=0?start.y:0) * h; | ||
end.y = (end.y<=max.y?end.y:max.y) * h + h; | ||
return {start: start, end :end}; | ||
} | ||
var start = Date.now(); | ||
testCase(); | ||
var end = Date.now(); | ||
console.log('test success for %jms!', end-start); |
23005
2.17%715
4.99%