/**
* @file MBS - FPLE MV
* @author Masked
* @version 1.1.0 2016-02-27
*/
/*:
* @plugindesc This plugin makes your game a first person labyrinth explorer.
*
* @author Masked
*
* @param View Distance
* @desc The amount of tiles ahead the player can see by default.
* @default 3
*
* @param Light Color
* @desc The hex code for the color used on the light.
* @default #ffffff
*
* @param Wall Terrain
* @desc The ID for wall tiles terrain tag on FPLE tilesets.
* @default 1
*
* @param Ceiling Region
* @desc The Region ID for ceiled tiles.
* @default 0
*
* @param 3D Anaglyph
* @desc Whether to use 3D cyan and red anaglyph to give your game depth. 1 = YES, 0 = NO.
* @default 0
*
* @param Texture Filter
* @desc The texture's filter type. (nearest/linear)
* @default linear
*
* @param Texture Format
* @desc The texture file format used. (png/jpg/dds/gif/...)
* @default png
*
* @param Texture Anisotropy
* @desc The amount of samples taken from textures. (usually a power of 2)
* @default 1
*
* @param Antialiasing
* @desc Whether to use antialiasing or not (expensive). 1 = YES, 0 = NO.
* @default 0
*
* @param Optimization Level
* @desc The level of optimization applied (degrading). (none/low/medium/high)
* @default none
*
* @help
* #
* First Person Labyrinth Explorer
* by Masked
*
* This plugin makes your game a kind of 3D so it looks like a first person
* labyrinth explorer.
*
*
* How to use
*
* 1. Setup
*
* I really recommend you using the Demo as a base for creating your FPLE
* projects, so you can skip this part.
* If you create the project from scratch, however, you'll need to download
* babylon.js by yourself from http://cdn.babylonjs.com/2-3/babylon.js and
* save it at your project's "js/libs" folder. This plugin was made using
* babylon.js 2.3, so you should use this version too to avoid possible
* bugs, but feel free to try later versions.
* Then, edit your index.html and add this after line 14:
*
* Now, you're half a step nearer to be ready to go.
*
* 2. Textures
*
* Textures can be set creating a file named "{tileset}_{row}-{col}",
* replacing '{tileset}' by the FPLE tileset number on the database and
* '{row}' and '{col}' with, respectively, the row and column the tile you are
* texturing is on the tileset's A5 layer, and placing it at your game's
* img/textures folder.
* There's no maximum/minimum size for the textures, but keep in mind that
* bigger textures are more expensive and can cause some serious performance
* decrease, specially on older computers.
*
* 3. Tilesets
*
* Setting tilesets up for FPLE is quite simple: first, create the tileset
* and set just the A5 layer (which is, currently, the only one supported by
* FPLE). Then, you can set passability flags as you want, and mark wall
* tiles with the terrain tag you choose on your plugin settings.
* Note that the first tile at the first row is always invisible, so it's
* recommended you use a black tile or something like that.
*
* 4. Mapping
*
* Mapping is quite intuitive, just put wall tiles wherer you want to be walls
* and floor tiles where you don't, you can use the first tile at the first
* wall to create holes since it's invisible. Also, you may want your map to
* have a ceiling, if so, you just have to set the tiles you want with the
* ceil region you choose on the plugin settings.
*
* 5. Plugin commands
*
* FPLE setResolution : Sets the FPLE canvas resolution (higher
* is better)
* FPLE setViewDistance : Sets the FPLE view distance in tile
*
* Examples:
* FPLE setResolution 0.5 : Sets the resolution at half
* FPLE setResolution v[42] : Sets the resolution to the value of
* variable 42
*
* FPLE setViewDistance 3 : Sets the view radius to 3 tiles
* FPLE setViewDistance v[42] : Sets the view radius to the value of
* variable 42
*
*
* Credits
*
* - Masked, for creating;
* - babylon.js team (https://github.com/BabylonJS/Babylon.js/graphs/contributors),
* for their aweasomer library.
*/
/*:pt
* @plugindesc Esse plugin transforma seu jogo em um explorador de labirinto em primeira pessoa.
*
* @author Masked
*
* @param View Distance
* @desc Número de tiles à frente que o jogador vê por padrão.
* @default 3
*
* @param Light Color
* @desc Código hexadecimal da cor da luz do jogador.
* @default #ffffff
*
* @param Wall Terrain
* @desc ID do terreno usado para identificar paredes nos tilesets.
* @default 1
*
* @param Ceiling Region
* @desc ID da região usada em tiles com teto no mapa.
* @default 0
*
* @param 3D Anaglyph
* @desc Quando usar ou não um efeito de vermelho e ciano para dar profundidade ao jogo. 1 = SIM, 0 = NÃO.
* @default 0
*
* @param Texture Filter
* @desc Filtro usado nas texturas. (nearest/linear)
* @default linear
*
* @param Texture Format
* @desc Formato dos arquivos de textura. (png/jpg/dds/gif/...)
* @default png
*
* @param Texture Anisotropy
* @desc Número de amostras tiradas das texturas. (geralmente uma potência de 2)
* @default 1
*
* @param Antialiasing
* @desc Quando usar antialiasing ou não (alto custo de performance). 1 = SIM, 0 = NÃO.
* @default 0
*
* @param Optimization Level
* @desc Nível de otimização da cena aplicado (degradante). (none/low/medium/high)
* @default none
*
* @help
* #
* First Person Labyrinth Explorer
* por Masked
*
* Esse plugin constrói um cenário 3D para o seu jogo a partir de mapas simples,
* tornando-o um explorador de labirinto em primeira pessoa.
*
*
* Como Usar
*
* 1. Instalação
*
* Eu recomendo fortemente que use a DEMO do FPLE como base para seu projeto,
* se estiver usando-a, pule esta parte.
* Caso você queira criar seu projeto do zero, no entanto, é necessário baixar
* o babylon.js de http://cdn.babylonjs.com/2-3/babylon.js e salvá-lo na pasta
* "js/libs" do seu jogo. Esse plugin foi feito e testado usando a versão r74,
* por isso é recomendado usar esta versão para evitar problemas.
* Depois, edite o index.html do seu jogo e adicione isso após a linha 14:
*
* Pronto, plugin instalado, agora estamos meio passo mais próximos do final :D
*
* 2. Texturas
*
* Texturas são definidas criando arquivos com nomes seguindo o padrão
* "{tileset}_{linha}-{coluna}", substituindo '{tileset}' pelo ID do tileset do
* FPLE no database e '{linha}' e '{coluna}' com, respectivamente, o número da
* linha e coluna do tile correspondente à textura no tileset. Note que apenas
* tiles A5 podem ser usados no momento.
* Arquivos de textura devem estar na pasta "img/textures" do seu projeto.
* Não há valor mínimo ou máximo para o tamanho das texturas, mas recomenda-se
* usar texturas quadradas e com tamanhos que sejam potências de 2. É importante
* perceber que usar texturas maiores pode causar lag, especialmente em
* computadores antigos.
*
* 3. Tilesets
*
* Configurar tilesets no FPLE é bem simples: primeiro, crie um tileset com
* apenas a camada A5. Então, configure a passabilidade normalmente e marque tiles
* de paede com o terreno que você escolheu nas configurações do plugin.
* Note que o primeiro tile da primeira coluna é sempre invisível, então é
* recomendado deixar isso sinalizado no próprio tileset.
*
* 4. Mapeamento
*
* O mapeamento não muda muito, na verdade, a única alteração é que tiles sem
* textura, vazios ou o primeiro tile da primeira linha do tileset são
* transparentes e ficam parecendo buracos no jogo, e você pode configurar como
* o teto aparece mudando a região dos tiles. Se a região de teto for 0, então
* todos os tiles sem região terão um teto.
*
* 5. Comandos de pugin
*
* FPLE setResolution : Define a resolução do canvas do FPLE
* (quanto maior, melhor)
* FPLE setViewDistance : Define o raio de visão do jogador
*
* Exemplos:
* FPLE setResolution 0.5 : Define a resolução como metade do normal
* FPLE setResolution v[42] : Define a resolução como o valor da
* variável número 42
*
* FPLE setViewDistance 3 : Define o raio de visão como 3 tiles
* FPLE setViewDistance v[42] : Define o raio de visão como o valor da
* variável número 42
*
*
* Créditos
*
* - Masked, por criar;
* - Equipe do babylon.js (https://github.com/BabylonJS/Babylon.js/graphs/contributors),
* pela biblioteca mais lindona.
*/
"use strict";
// This plugin uses babylon.js (http://babylonjs.com/)
if (!BABYLON)
throw new error('FPLE: Unable to find babylon.js, please follow the plugin' +
' instructions and try again.');
if (!BABYLON.Engine.isSupported())
throw new error('FPLE: Browser not supported by babylon.js.');
// Import for compatibility check
var Imported = Imported || {};
Imported['MBS - FPLE'] = 1.10;
// MBS module
var MBS = MBS || {};
MBS.FPLE = {};
// Global babylonJS engine object
var $babylon;
// Global fple scene object
var $fple;
//-----------------------------------------------------------------------------
// MBS.FPLE
//
// FPLE settings module
(function ($) {
// Parameter loading
$.Filename = document.currentScript.src;
$.Params = PluginManager.parameters(decodeURI(/([^\/]+)\.js$/.exec($.Filename)[1]));
// Settings
$.viewRadius = Number($.Params['View Distance']);
$.lightColor = $.Params['Light Color'];
$.wallTerrain = Number($.Params['Wall Terrain']);
// $.ceilRegion = Number($.Params['Ceiling Region']);
$.ceilRegion = String($.Params['Ceiling Region']);
$.ceilRegion = $.ceilRegion.split(' ');
if ($.ceilRegion === '') $.ceilRegion = [];
for (var temp = 0; temp < $.ceilRegion.length; ++temp) {
$.ceilRegion[temp] =
parseInt($.ceilRegion[temp]);
};
$.anaglyph3d = !!Number($.Params['3D Anaglyph']);
$.textureFilter = $.Params['Texture Filter'];
$.textureFormat = $.Params['Texture Format'];
$.anisotropy = Number($.Params['Texture Anisotropy']);
$.antialias = !!Number($.Params['Antialiasing']);
$.optimization = $.Params['Optimization Level'];
// Heights
$.floorHeight = 0;
$.wallHeight = 1;
$.ceilHeight = 2;
$.cameraHeight = 1;
// Image files format string
$.textureFileFormat = "img/textures/%1_%2-%3.%4";
$.bumpTextureFileFormat = "img/bump/%1_%2-%3.%4";
$.parallaxFileFormat = "img/parallaxes/%1.%2";
// Resizes the FPLE canvas to change the game resolution
$.setPixelRate = function(n) {
if (!Graphics._fple_renderer) return;
Graphics._fple_renderer.setSize(Graphics.width * n, Graphics.height * n);
Graphics._updateFPLE();
};
})(MBS.FPLE);
//-----------------------------------------------------------------------------
// MBS.FPLE.Map
//
// FPLE Map, this converts $dataMap into a 3D cubic map
MBS.FPLE.Map = function() {
this.initialize.apply(this, arguments);
};
(function() {
/**
* Map initialization.
*/
MBS.FPLE.Map.prototype.initialize = function() {
this.clearCache();
this.refresh();
};
/**
* Clears the map cache.
* Used just for creating '_cache' and/or reloading textures.
*/
MBS.FPLE.Map.prototype.clearCache = function() {
this._cache = {
textures: {},
materials: {}
};
};
/**
* Extracts $dataMap data.
*/
MBS.FPLE.Map.prototype.refresh = function() {
// Clears all loaded data
this._data = [];
// Loads mapa data
var width = $dataMap.width;
var height = $dataMap.height;
var data = $dataMap.data;
for (var x = 0; x < width; x++) {
this._data[x] = [];
for (var y = 0; y < height; y++) {
// Store tile ID
this._data[x][y] = data[y * width + x];
}
}
};
/**
* Gets a cached texture or loads it if it's hasn't been used yet.
*
* @param {String} filename The file from where to load the texture.
*/
MBS.FPLE.Map.prototype.getTexture = function(filename, scene) {
// Load texture from cache or from file
var cache = this._cache.textures[filename];
if (cache)
return cache;
var texture = new BABYLON.Texture( filename, scene, false );
texture.anisotropicFilteringLevel = MBS.FPLE.anisotropy;
// Apply desired filter
if (MBS.FPLE.textureFilter.match(/^nearest$/i))
texture.updateSamplingMode(BABYLON.Texture.NEAREST_SAMPLINGMODE);
else
texture.updateSamplingMode(BABYLON.Texture.NEAREST_BILINEARMODE);
// Store it on cache
this._cache.textures[filename] = texture;
return texture;
};
/**
* Gets a cached material or loads it if it's hasn't been used yet.
*
* @param {String} filename The file from where to load the material texture.
*/
MBS.FPLE.Map.prototype.getMaterial = function(tile_id, row, col, scene) {
var filename = MBS.FPLE.textureFileFormat.format(
$dataMap.tilesetId,
row,
col,
MBS.FPLE.textureFormat);
var material;
// Don't lose your time if it has already been loaded
if (this._cache.materials[filename]) {
material = this._cache.materials[filename];
// Load it otherwise
} else {
material = new BABYLON.MultiMaterial(filename, scene);
var texture = this.getTexture(filename, scene);
var f = new BABYLON.StandardMaterial(filename + "_front",scene);
f.diffuseTexture = texture.clone();
f.specularColor = new BABYLON.Color3(0, 0, 0);
f.diffuseTexture.uScale = -1;
f.diffuseTexture.vScale = -1;
var ba = new BABYLON.StandardMaterial(filename + "_back",scene);
ba.diffuseTexture = texture.clone();
ba.specularColor = new BABYLON.Color3(0, 0, 0);
ba.diffuseTexture.uScale = 1;
ba.diffuseTexture.vScale = 1;
var l = new BABYLON.StandardMaterial(filename + "_left",scene);
l.diffuseTexture = texture.clone();
l.specularColor = new BABYLON.Color3(0, 0, 0);
l.diffuseTexture.wAng = 0.5 * Math.PI;
var r = new BABYLON.StandardMaterial(filename + "_right",scene);
r.diffuseTexture = texture.clone();
r.specularColor = new BABYLON.Color3(0, 0, 0);
r.diffuseTexture.wAng = 0.5 * Math.PI;
var t = new BABYLON.StandardMaterial(filename + "_top",scene);
t.diffuseTexture = texture.clone();
t.specularColor = new BABYLON.Color3(0, 0, 0);
t.diffuseTexture.wAng = -0.5 * Math.PI;
var bo = new BABYLON.StandardMaterial(filename + "_bottom",scene);
bo.diffuseTexture = texture.clone();
bo.specularColor = new BABYLON.Color3(0, 0, 0);
bo.diffuseTexture.wAng = 0.5 * Math.PI;
bo.diffuseTexture.uScale = 1;
material.subMaterials.push(f);
material.subMaterials.push(ba);
material.subMaterials.push(l);
material.subMaterials.push(r);
material.subMaterials.push(t);
material.subMaterials.push(bo);
// Store it on cache
this._cache.materials[filename] = material;
}
return material;
};
/**
* Adds this map's data to a babylonJS scene
*
* @param {BABYLON.Scene} scene The scene to add the objects into.
* @returns The scene where the objects were added.
*/
MBS.FPLE.Map.prototype.toScene = function(scene) {
this._applyTiles(scene);
this._applyEvents(scene);
};
/**
* Creates a cube to add into a FPLE scene.
*/
MBS.FPLE.Map.prototype._createCube = function(name, scene) {
var cube;
if (!this._cubeMesh) {
cube = BABYLON.Mesh.CreateBox(name, 1.0, scene);
this._cubeMesh = cube;
}
cube = this._cubeMesh.clone(name);
return cube;
};
MBS.FPLE.Map.prototype._buildMesh = function(cubes, material) {
var mesh = BABYLON.Mesh.MergeMeshes(cubes, true);
mesh.subMeshes=[];
var verticesCount=mesh.getTotalVertices();
var
i = 0,
n;
if (cubes[0]) {
n = 0;
mesh.subMeshes.push(new BABYLON.SubMesh(0, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(1, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(2, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(3, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(4, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(5, n++, verticesCount, i++ * 6, 6, mesh));
}
if (cubes[1]) {
n = 6;
mesh.subMeshes.push(new BABYLON.SubMesh(0, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(1, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(2, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(3, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(4, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(5, n++, verticesCount, i++ * 6, 6, mesh));
}
if (cubes[2]) {
n = 12;
mesh.subMeshes.push(new BABYLON.SubMesh(0, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(1, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(2, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(3, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(4, n++, verticesCount, i++ * 6, 6, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(5, n++, verticesCount, i++ * 6, 6, mesh));
}
mesh.material = material;
return mesh;
};
/**
* Adds this map's tiles to a babylonJS scene
*
* @param {BABYLON.Scene} scene The scene to add the cubes into. If not
* defined, a new scene is used.
*/
MBS.FPLE.Map.prototype._applyTiles = function(scene) {
// Forward declarations
var tile,
row,
col,
filename,
material,
cube;
for (var x = 0; x < this._data.length; x++) {
for (var y = 0; y < this._data[x].length; y++) {
tile = this._data[x][y];
col = (Math.floor(tile / 128) % 2 * 8 + tile % 8); // srsly?
row = (Math.floor(tile % 256 / 8) % 16); // wow, such formula
// Do not draw the first tile at the first row
if (col === 0 && row === 0) continue;
material = this.getMaterial($dataMap.tilesetId, row, col, scene);
var cubes = [];
// Floor
cube = this._createCube('floor' + x + '-' + y, scene);
cube.position = new BABYLON.Vector3(-x, MBS.FPLE.floorHeight, y);
cubes.push(cube);
// Wall
if ($gameMap.terrainTag(x, y) === MBS.FPLE.wallTerrain) {
cube = this._createCube('wall' + x + '-' + y, scene);
cube.position = new BABYLON.Vector3(-x, MBS.FPLE.wallHeight, y);
cubes.push(cube);
}
// Ceiling
/*if ($gameMap.regionId(x, y) === MBS.FPLE.ceilRegion) {
cube = this._createCube('ceil' + x + '-' + y, scene);
cube.position = new BABYLON.Vector3(-x, MBS.FPLE.ceilHeight, y);
cubes.push(cube);
}*/
for(var Lian=0;Lian