Lordofpomelo源碼分析 (一): World初始化之讀取地圖配置

凡事總有個起點, 咱們先從 world.init開始吧! json

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

這段代碼位於lordofpomelo的game-server下的app.js文件,咱們先看這句world.init(dataApi.area.all()),它對應調用的是./app/domain/world.js文件的init方法,代碼以下: api

exp.init = function(areasConfig){
	//Init areas
	for(var key in areasConfig){
		//init map
		var areaConfig = areasConfig[key];
		areaConfig.weightMap = false;
		maps[areaConfig.id] = new Map(areaConfig);
	}
};

內容很簡單,傳入的參數是全部的area服務器,lordofpomelo中默認配了3個area服務器,分別對應遊戲中的3個地圖,初始化world時逐個循環進行area的map初始化,這裏調用到的是maps[areaConfig.id] = new Map(areaConfig);接下來進入map的構造方法,對應的文件是./app/domain/map/map.js 數組

/**
 * The data structure for map in the area
 */
var Map = function(opts) {
	this.mapPath = process.cwd() + opts.path;
	this.map = null;
	this.weightMap = null;
	this.name = opts.name;

	this.init(opts);
};

首先this.mapPath 是取得第一張地圖的配置文件,位於 ./config/map/desert.json。看名字就能猜出來,是張沙漠的地圖。this.name 就是desert,緊接着執行this.init(opts)方法 服務器

/**
 * Init game map
 * @param {Object} opts
 * @api private
 */
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));
			}

		}
	}
};

這段代碼比較長,不用心急,咱們慢慢看。首先var map = require(this.mapPath);其實就是讀取前面的地圖配置文件。而後是這句this.configMap(map); app

Map.prototype.configMap = function(map){
	this.map = {};
	var layers = map.layers;
	for(var i = 0; i < layers.length; i++){
		var layer = layers[i];
		if(layer.type === 'objectgroup'){
			this.map[layer.name] = configObjectGroup(layer.objects);
		}
	}
};

這個不復雜,就是讀取配置中的layers,這裏面第一張地圖一共有5個layer,分別爲desert、birth、mob、npc、collision,看名字也能猜出來,就是背景地板、出生地、怪物、npc和障礙物5層了,其中後四個都是屬於objectgroup類型,所以都會調用到 this.map[layer.name] = configObjectGroup(layer.objects) 這句,繼續看代碼; dom

function configObjectGroup(objs){
	for(var i = 0; i < objs.length; i++){
		objs[i] = configProps(objs[i]);
	}

	return objs;
}

逐個循環layer裏面的object,而後調用configProps(objs[i]) ui

function configProps(obj){
	if(!!obj && !!obj.properties){
		for(var key in obj.properties){
			obj[key] = obj.properties[key];
		}

		delete obj.properties;
	}

	return obj;
}

這裏面就是把每一個obj的屬性讀取出來,返回上層,造成一個數組繼續向上返回到this.map[layer.name]這個變量中存儲。 this

好了,源碼好多,慢慢來,這一章就到這。。 spa

各位保重,88 prototype

相關文章
相關標籤/搜索