凡事总有个起点, 咱们先从 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