UNPKG

lettuce

Version:

Lettuce JS, Mini Mobile Framework for Romantic with DSL.

363 lines (313 loc) 12.4 kB
/* * MelonJS Game Engine * Copyright (C) 2011 - 2013, Olivier BIOT * http://www.melonjs.org * */ (function () { /** * a level manager object <br> * once ressources loaded, the level director contains all references of defined levels<br> * There is no constructor function for me.levelDirector, this is a static object * @namespace me.levelDirector * @memberOf me */ me.levelDirector = (function () { // hold public stuff in our singletong var api = {}; /* * PRIVATE STUFF */ // our levels var levels = {}; // level index table var levelIdx = []; // current level index var currentLevelIdx = 0; /** * Load a TMX level * @name loadTMXLevel * @memberOf me.game * @private * @param {String} level to be loaded * @param {me.Container} target container * @ignore * @function */ var loadTMXLevel = function (level, container) { // disable auto-sort for the given container container.autoSort = false; // load our map me.game.currentLevel = level; // change the viewport bounds me.game.viewport.setBounds( 0, 0, Math.max(level.width, me.game.viewport.width), Math.max(level.height, me.game.viewport.height) ); // adjust map position based on the viewport size // (only update the map position if the map is smaller than the viewport) level.setDefaultPosition(me.game.viewport.width, me.game.viewport.height); // add all defined layers var layers = level.getLayers(); for (var i = layers.length; i--;) { container.addChild(layers[i]); } // game world as default container var targetContainer = container; var isCollisionGroup = false; // load all ObjectGroup and Object definition var objectGroups = level.getObjectGroups(); for (var g = 0; g < objectGroups.length; g++) { var group = objectGroups[g]; // check if this is the collision shape group isCollisionGroup = group.name.toLowerCase().contains(me.TMXConstants.COLLISION_GROUP); if (me.game.mergeGroup === false) { // create a new container with Infinite size (?) // note: initial position and size seems to be meaningless in Tiled // https://github.com/bjorn/tiled/wiki/TMX-Map-Format : // x: Defaults to 0 and can no longer be changed in Tiled Qt. // y: Defaults to 0 and can no longer be changed in Tiled Qt. // width: The width of the object group in tiles. Meaningless. // height: The height of the object group in tiles. Meaningless. targetContainer = new me.Container(); // set additional properties targetContainer.name = group.name; targetContainer.z = group.z; targetContainer.setOpacity(group.opacity); // disable auto-sort targetContainer.autoSort = false; } // iterate through the group and add all object into their // corresponding target Container for (var o = 0; o < group.objects.length; o++) { // TMX object settings var settings = group.objects[o]; var obj; if (isCollisionGroup === false) { obj = me.pool.pull( settings.name, settings.x, settings.y, // 'TileObject' will instantiate a Sprite Object settings.name === "TileObject" ? settings.image : settings ); } else { obj = me.pool.pull( "me.Entity", settings.x, settings.y, settings ); // configure the body accordingly obj.body.collisionType = me.collision.types.WORLD_SHAPE; } // ignore if the pull function does not return a corresponding object if (obj) { // set the obj z order correspondingly to its parent container/group obj.z = group.z; //apply group opacity value to the child objects if group are merged if (me.game.mergeGroup === true && obj.isRenderable === true) { obj.setOpacity(obj.getOpacity() * group.opacity); // and to child renderables if any if (obj.renderable instanceof me.Renderable) { obj.renderable.setOpacity(obj.renderable.getOpacity() * group.opacity); } } // add the obj into the target container targetContainer.addChild(obj); } } // if we created a new container if (me.game.mergeGroup === false) { // add our container to the world container.addChild(targetContainer); // re-enable auto-sort targetContainer.autoSort = true; } } // sort everything (recursively) container.sort(true); // re-enable auto-sort container.autoSort = true; // translate the display if required me.game.world.transform.translateV(me.game.currentLevel.pos); // update the game world size to match the level size me.game.world.resize(me.game.currentLevel.width, me.game.currentLevel.height); // fire the callback if defined if (me.game.onLevelLoaded) { me.game.onLevelLoaded.call(me.game.onLevelLoaded, level.name); } //publish the corresponding message me.event.publish(me.event.LEVEL_LOADED, [level.name]); }; /* * PUBLIC STUFF */ /** * reset the level director * @ignore */ api.reset = function () {}; /** * add a level * @ignore */ api.addLevel = function () { throw new me.Error("no level loader defined"); }; /** * * add a TMX level * @ignore */ api.addTMXLevel = function (levelId, callback) { // just load the level with the XML stuff if (levels[levelId] == null) { //console.log("loading "+ levelId); levels[levelId] = new me.TMXTileMap(levelId); // set the name of the level levels[levelId].name = levelId; // level index levelIdx.push(levelId); } else { //console.log("level %s already loaded", levelId); return false; } // call the callback if defined if (callback) { callback(); } // true if level loaded return true; }; /** * load a level into the game manager<br> * (will also create all level defined entities, etc..) * @name loadLevel * @memberOf me.levelDirector * @public * @function * @param {String} level level id * @example * // the game defined ressources * // to be preloaded by the loader * // TMX maps * ... * {name: "a4_level1", type: "tmx", src: "data/level/a4_level1.tmx"}, * {name: "a4_level2", type: "tmx", src: "data/level/a4_level2.tmx"}, * {name: "a4_level3", type: "tmx", src: "data/level/a4_level3.tmx"}, * ... * ... * // load a level * me.levelDirector.loadLevel("a4_level1"); */ api.loadLevel = function (levelId) { // make sure it's a string levelId = levelId.toString().toLowerCase(); // throw an exception if not existing if (typeof(levels[levelId]) === "undefined") { throw new me.Error("level " + levelId + " not found"); } if (levels[levelId] instanceof me.TMXTileMap) { // check the status of the state mngr var wasRunning = me.state.isRunning(); if (wasRunning) { // stop the game loop to avoid // some silly side effects me.state.stop(); } // reset the gameObject Manager (just in case!) me.game.reset(); // reset the GUID generator // and pass the level id as parameter me.utils.resetGUID(levelId); // clean the current (previous) level if (levels[api.getCurrentLevelId()]) { levels[api.getCurrentLevelId()].destroy(); } // parse the give TMX file into the give level me.mapReader.readMap(levels[levelId], me.loader.getTMX(levelId)); // update current level index currentLevelIdx = levelIdx.indexOf(levelId); // add the specified level to the game world loadTMXLevel(levels[levelId], me.game.world); if (wasRunning) { // resume the game loop if it was // previously running me.state.restart.defer(this); } } else { throw new me.Error("no level loader defined"); } return true; }; /** * return the current level id<br> * @name getCurrentLevelId * @memberOf me.levelDirector * @public * @function * @return {String} */ api.getCurrentLevelId = function () { return levelIdx[currentLevelIdx]; }; /** * reload the current level<br> * @name reloadLevel * @memberOf me.levelDirector * @public * @function */ api.reloadLevel = function () { // reset the level to initial state //levels[currentLevel].reset(); return api.loadLevel(api.getCurrentLevelId()); }; /** * load the next level<br> * @name nextLevel * @memberOf me.levelDirector * @public * @function */ api.nextLevel = function () { //go to the next level if (currentLevelIdx + 1 < levelIdx.length) { return api.loadLevel(levelIdx[currentLevelIdx + 1]); } else { return false; } }; /** * load the previous level<br> * @name previousLevel * @memberOf me.levelDirector * @public * @function */ api.previousLevel = function () { // go to previous level if (currentLevelIdx - 1 >= 0) { return api.loadLevel(levelIdx[currentLevelIdx - 1]); } else { return false; } }; /** * return the amount of level preloaded<br> * @name levelCount * @memberOf me.levelDirector * @public * @function */ api.levelCount = function () { return levelIdx.length; }; // return our object return api; })(); })();