Lordofpomelo源码分析 (二): World初始化之pathCache

接上回,咱们看到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

相关文章
相关标签/搜索