Newsletter addition: WeightedRandomize

This commit is contained in:
Michael Hadley 2017-12-03 08:56:12 -06:00
parent d686cd7140
commit f7cd3deb93
4 changed files with 89 additions and 0 deletions

View file

@ -1205,6 +1205,23 @@ var Tilemap = new Class({
return TilemapComponents.TileToWorldXY(tileX, tileY, point, camera, layer);
},
/**
* See component documentation. If no layer specified, the map's current layer is used. This
* cannot be applied to StaticTilemapLayers.
*
* @return {this|null} Returns this, or null if the layer given was invalid.
*/
weightedRandomize: function (tileX, tileY, width, height, weightedIndexes, layer)
{
layer = this.getLayer(layer);
if (this._isStaticCall(layer, 'randomize')) { return this; }
if (layer !== null)
{
TilemapComponents.WeightedRandomize(tileX, tileY, width, height, weightedIndexes, layer);
}
return this;
},
/**
* See component documentation. If no layer specified, the map's current layer is used.
*

View file

@ -0,0 +1,60 @@
var GetTilesWithin = require('./GetTilesWithin');
/**
* Randomizes the indexes of a rectangular region of tiles (in tile coordinates) within the
* specified layer. Each tile will recieve a new index. New indexes are drawn from the given
* weightedIndexes array. An example weighted array:
*
* [
* { index: 6, weight: 4 }, // Probability of index 6 is 4 / 8
* { index: 7, weight: 2 }, // Probability of index 7 would be 2 / 8
* { index: 8, weight: 1.5 }, // Probability of index 8 would be 1.5 / 8
* { index: 26, weight: 0.5 } // Probability of index 27 would be 0.5 / 8
* ]
*
* The probability of any index being choose is (the index's weight) / (sum of all weights). This
* method only modifies tile indexes and does not change collisioninformation.
*
* @param {integer} [tileX=0] - [description]
* @param {integer} [tileY=0] - [description]
* @param {integer} [width=max width based on tileX] - [description]
* @param {integer} [height=max height based on tileY] - [description]
* @param {object[]} [weightedIndexes] - An array of objects to randomly draw from during
* randomization. They should be in the form: { index: 0, weight: 4 }.
* @param {LayerData} layer - [description]
*/
var WeightedRandomize = function (tileX, tileY, width, height, weightedIndexes, layer)
{
if (weightedIndexes === undefined) { return; }
var i;
var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer);
var weightTotal = 0;
for (i = 0; i < weightedIndexes.length; i++)
{
weightTotal += weightedIndexes[i].weight;
}
if (weightTotal <= 0) { return; }
for (i = 0; i < tiles.length; i++)
{
var rand = Math.random() * weightTotal;
var sum = 0;
var randomIndex = -1;
for (var j = 0; j < weightedIndexes.length; j++)
{
sum += weightedIndexes[j].weight;
if (rand <= sum)
{
randomIndex = weightedIndexes[j].index;
break;
}
}
tiles[i].index = randomIndex;
}
};
module.exports = WeightedRandomize;

View file

@ -35,6 +35,7 @@ module.exports = {
TileToWorldX: require('./TileToWorldX'),
TileToWorldXY: require('./TileToWorldXY'),
TileToWorldY: require('./TileToWorldY'),
WeightedRandomize: require('./WeightedRandomize'),
WorldToTileX: require('./WorldToTileX'),
WorldToTileXY: require('./WorldToTileXY'),
WorldToTileY: require('./WorldToTileY')

View file

@ -463,6 +463,17 @@ var DynamicTilemapLayer = new Class({
return TilemapComponents.TileToWorldXY(tileX, tileY, point, camera, this.layer);
},
/**
* See component documentation.
*
* @return {this}
*/
weightedRandomize: function (tileX, tileY, width, height, weightedIndexes)
{
TilemapComponents.WeightedRandomize(tileX, tileY, width, height, weightedIndexes, this.layer);
return this;
},
/**
* See component documentation.
*