凡事總有個起點, 咱們先從 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