接上回,咱們看到map的初始化,代碼以下: json
Map.prototype.init = function(opts) { var weightMap = opts.weightMap || false; var map = require(this.mapPath); if(!map) { logger.error('Load map failed! '); } else { this.configMap(map); this.id = opts.id; this.width = opts.width; this.height = opts.height; this.tileW = 20; this.tileH = 20; this.rectW = Math.ceil(this.width/this.tileW); this.rectH = Math.ceil(this.height/this.tileH); this.pathCache = new PathCache({limit:1000}); this.pfinder = buildFinder(this); if(weightMap) { //Use cache map first var path = process.cwd() + '/tmp/map.json'; var maps = fs.existsSync(path)?require(path) : {}; if(!!maps[this.id]){ this.collisions = maps[this.id].collisions; this.weightMap = this.getWeightMap(this.collisions); }else{ this.initWeightMap(); this.initCollisons(); maps[this.id] = {version : Date.now(), collisions : this.collisions}; fs.writeFileSync(path, JSON.stringify(maps)); } } } };
上回看到了this.configMap(map);這句的就是把地圖配置文件讀取存入this.map變量中,接下來,從opts中取出地圖的id/width/height,那麼這些值是從哪裏來的呢?還記得以前app.js中的 world.init(dataApi.area.all()) 嗎?從新看下以前的代碼 api
// Configure for area server app.configure('production|development', 'area', function(){ app.filter(pomelo.filters.serial()); app.before(playerFilter()); var areaId = app.get('curServer').area; if(!areaId || areaId < 0) { throw new Error('load area config failed'); } world.init(dataApi.area.all()); area.init(dataApi.area.findById(areaId)); });
這裏面實際上還先執行了dataApi.area.all(),該方法位於./app/util/dataApi.js, 內容以下: 緩存
/** * find all item * * @return {array} * @api public */ Data.prototype.all = function() { return this.data; }; module.exports = { area: new Data(area), character: new Data(character), equipment: new Data(equipment), experience: new Data(experience), npc: new Data(npc), role: new Data(role), talk: new Data(talk), item: new Data(item), fightskill: new Data(fightskill), task: new Data(task) };
實際上它返回的就是new Data(area),該方法對應的引用是var area = require('../../config/data/area');打開改路徑下的文件,文件內容以下, app
["id","name","areaName","level","width","height","path","towerWidth","towerHeight"],
["1","desert","沙漠",0,4200,2800,"/config/map/desert.json",300,300], ui
這裏定義了前面opts用到的id/width/height等數值。搞清楚了數值來源後咱們繼續回到map.ini中 看下面代碼: this
this.tileW = 20; this.tileH = 20; this.rectW = Math.ceil(this.width/this.tileW); this.rectH = Math.ceil(this.height/this.tileH);
這一段很簡單,就是定義地圖的tile爲20*20構成,而後再計算出地圖的總的tile寬度與高度。 spa
this.pathCache = new PathCache({limit:1000}); this.pfinder = buildFinder(this);
而後是這兩句,咱們先看第一句this.pathCache = new PathCache({limit:1000}); PathCache構造方法位於./app/util/pathCache.js文件,代碼以下: prototype
var PathCache = function(opts) { this.id = id++; this.limit = opts.limit||30000; this.size = 0; this.queue = new PriorityQueue(comparator); this.cache = {}; };
這裏面主要調用到的是new PriorityQueue(comparator); 其中comparator是一個比較大小的function,先看代碼: code
var comparator = function(a, b) { return a.time < b.time; };
內容很簡單,比較兩個值的造成時間,a時間比b時間早則返回true,具體有什麼用,請接着咱們繼續看PriorityQueue該方法位於pomelo-collection模塊中的./lib/PriorityQueue.js文件中,這是一個獨立的模塊, server
var PriorityQueue = function(comparator){ this.init(comparator); } var pro = PriorityQueue.prototype; pro.init = function(comparator){ this._comparator = typeof(comparator)=='function'?comparator:this._defaultComparator; this._queue = []; this._tailPos = 0; }
調用本身的init方法,初始化了比較方法,若是傳入的參數不是一個function時,則採用默認的比較方法,這裏不是採用默認方法,因此暫時不看默認方法;
看到這裏你們可能比較疑惑,這個PriorityQueue究竟是個什麼東西,實際上它就是一個順序隊列,它可以保證每次提供給你最先加入隊列中的路徑被取出並刪除。
經過這種機制保證了pathCache在預先設定的limit範圍內保存尋路路徑的緩存,避免緩存無限制增加,這裏咱們的limit就是前面提到的pathCache = new PathCache({limit:1000});指定的1000這個數值。具體的代碼暫時不分析了,等後面用到時在詳細說明.
好了,這篇就到這來,下一篇開始說明buildFinder(this);
你們88