mirror of
https://github.com/wassname/phaser.git
synced 2026-07-16 01:20:13 +08:00
Lots of new tilemap code in here. If your game relies on tilemaps then please don't update to this commit unless you want to help debugging!
This commit is contained in:
+29
-12
@@ -17,18 +17,29 @@
|
||||
* @param {number} width - Width of the tile.
|
||||
* @param {number} height - Height of the tile.
|
||||
*/
|
||||
Phaser.Tile = function (tileset, index, x, y, width, height) {
|
||||
// Phaser.Tile = function (tileset, index, x, y, width, height) {
|
||||
Phaser.Tile = function (index, x, y, width, height) {
|
||||
|
||||
/**
|
||||
* @property {Phaser.Tileset} tileset - The tileset this tile belongs to.
|
||||
*/
|
||||
this.tileset = tileset;
|
||||
// this.tileset = tileset;
|
||||
|
||||
/**
|
||||
* @property {number} index - The index of this tile within the tileset.
|
||||
*/
|
||||
this.index = index;
|
||||
|
||||
/**
|
||||
* @property {number} x - The x map coordinate of this tile.
|
||||
*/
|
||||
this.x = x;
|
||||
|
||||
/**
|
||||
* @property {number} y - The y map coordinate of this tile.
|
||||
*/
|
||||
this.y = y;
|
||||
|
||||
/**
|
||||
* @property {number} width - The width of the tile in pixels.
|
||||
*/
|
||||
@@ -40,14 +51,9 @@ Phaser.Tile = function (tileset, index, x, y, width, height) {
|
||||
this.height = height;
|
||||
|
||||
/**
|
||||
* @property {number} x - The top-left corner of the tile within the tileset.
|
||||
* @property {number} alpha - The alpha value at which this tile is drawn to the canvas.
|
||||
*/
|
||||
this.x = x;
|
||||
|
||||
/**
|
||||
* @property {number} y - The top-left corner of the tile within the tileset.
|
||||
*/
|
||||
this.y = y;
|
||||
this.alpha = 1;
|
||||
|
||||
// Any extra meta data info we need here
|
||||
|
||||
@@ -55,7 +61,18 @@ Phaser.Tile = function (tileset, index, x, y, width, height) {
|
||||
* @property {number} mass - The virtual mass of the tile.
|
||||
* @default
|
||||
*/
|
||||
this.mass = 1.0;
|
||||
// this.mass = 1.0;
|
||||
|
||||
|
||||
// Keep track of our interesting faces
|
||||
this.faceTop = false;
|
||||
this.faceBottom = false;
|
||||
this.faceLeft = false;
|
||||
this.faceRight = false;
|
||||
|
||||
this.collides = false;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @property {boolean} collideNone - Indicating this Tile doesn't collide at all.
|
||||
@@ -91,13 +108,13 @@ Phaser.Tile = function (tileset, index, x, y, width, height) {
|
||||
* @property {boolean} separateX - Enable separation at x-axis.
|
||||
* @default
|
||||
*/
|
||||
this.separateX = true;
|
||||
// this.separateX = true;
|
||||
|
||||
/**
|
||||
* @property {boolean} separateY - Enable separation at y-axis.
|
||||
* @default
|
||||
*/
|
||||
this.separateY = true;
|
||||
// this.separateY = true;
|
||||
|
||||
/**
|
||||
* @property {boolean} collisionCallback - Tilemap collision callback.
|
||||
|
||||
@@ -123,6 +123,140 @@ Phaser.Tilemap.prototype = {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets collision values on a tile in the set.
|
||||
*
|
||||
* @method Phaser.Tileset#setCollision
|
||||
* @param {number} index - The index of the tile within the set.
|
||||
* @param {boolean} left - Should the tile collide on the left?
|
||||
* @param {boolean} right - Should the tile collide on the right?
|
||||
* @param {boolean} up - Should the tile collide on the top?
|
||||
* @param {boolean} down - Should the tile collide on the bottom?
|
||||
*/
|
||||
|
||||
// Sets all tiles matching the given index to collide on the given faces
|
||||
// Recalculates the collision map
|
||||
setCollisionByIndex: function (index, layer) {
|
||||
|
||||
if (typeof layer === "undefined") { layer = this.currentLayer; }
|
||||
|
||||
for (var y = 0; y < this.layers[layer].height ; y++)
|
||||
{
|
||||
for (var x = 0; x < this.layers[layer].width; x++)
|
||||
{
|
||||
var tile = this.layers[layer].data[y][x];
|
||||
|
||||
if (tile && tile.index === index)
|
||||
{
|
||||
tile.collides = true;
|
||||
tile.faceTop = true;
|
||||
tile.faceBottom = true;
|
||||
tile.faceLeft = true;
|
||||
tile.faceRight = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now re-calculate interesting faces
|
||||
this.calculateFaces(layer);
|
||||
|
||||
},
|
||||
|
||||
calculateFaces: function (layer) {
|
||||
|
||||
var above = null;
|
||||
var below = null;
|
||||
var left = null;
|
||||
var right = null;
|
||||
|
||||
console.log(this.layers[layer].width, 'x', this.layers[layer].height);
|
||||
|
||||
for (var y = 0; y < this.layers[layer].height ; y++)
|
||||
{
|
||||
for (var x = 0; x < this.layers[layer].width; x++)
|
||||
{
|
||||
var tile = this.layers[layer].data[y][x];
|
||||
|
||||
if (tile)
|
||||
{
|
||||
above = this.getTileAbove(layer, x, y);
|
||||
below = this.getTileBelow(layer, x, y);
|
||||
left = this.getTileLeft(layer, x, y);
|
||||
right = this.getTileRight(layer, x, y);
|
||||
|
||||
if (above && above.collides)
|
||||
{
|
||||
// There is a tile above this one that also collides, so the top of this tile is no longer interesting
|
||||
tile.faceTop = false;
|
||||
}
|
||||
|
||||
if (below && below.collides)
|
||||
{
|
||||
// There is a tile below this one that also collides, so the bottom of this tile is no longer interesting
|
||||
tile.faceBottom = false;
|
||||
}
|
||||
|
||||
if (left && left.collides)
|
||||
{
|
||||
// There is a tile left this one that also collides, so the left of this tile is no longer interesting
|
||||
tile.faceLeft = false;
|
||||
}
|
||||
|
||||
if (right && right.collides)
|
||||
{
|
||||
// There is a tile right this one that also collides, so the right of this tile is no longer interesting
|
||||
tile.faceRight = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
getTileAbove: function (layer, x, y) {
|
||||
|
||||
if (y > 0)
|
||||
{
|
||||
return this.layers[layer].data[y - 1][x];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
},
|
||||
|
||||
getTileBelow: function (layer, x, y) {
|
||||
|
||||
if (y < this.layers[layer].height - 1)
|
||||
{
|
||||
return this.layers[layer].data[y + 1][x];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
},
|
||||
|
||||
getTileLeft: function (layer, x, y) {
|
||||
|
||||
if (x > 0)
|
||||
{
|
||||
return this.layers[layer].data[y][x - 1];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
},
|
||||
|
||||
getTileRight: function (layer, x, y) {
|
||||
|
||||
if (x < this.layers[layer].width - 1)
|
||||
{
|
||||
return this.layers[layer].data[y][x + 1];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Internal function that calculates the tile indexes for the map data.
|
||||
*
|
||||
@@ -130,6 +264,7 @@ Phaser.Tilemap.prototype = {
|
||||
*/
|
||||
calculateIndexes: function () {
|
||||
|
||||
/*
|
||||
for (var layer = 0; layer < this.layers.length; layer++)
|
||||
{
|
||||
this.layers[layer].indexes = [];
|
||||
@@ -147,6 +282,7 @@ Phaser.Tilemap.prototype = {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
},
|
||||
|
||||
|
||||
+107
-27
@@ -286,8 +286,9 @@ Phaser.TilemapLayer.prototype.constructor = Phaser.TilemapLayer;
|
||||
*/
|
||||
Phaser.TilemapLayer.prototype.postUpdate = function () {
|
||||
|
||||
Phaser.Sprite.prototype.postUpdate.call( this );
|
||||
Phaser.Sprite.prototype.postUpdate.call(this);
|
||||
|
||||
// Stops you being able to scroll the camera if it's not following a sprite
|
||||
this.scrollX = this.game.camera.x * this.scrollFactorX;
|
||||
this.scrollY = this.game.camera.y * this.scrollFactorY;
|
||||
|
||||
@@ -357,6 +358,8 @@ Phaser.TilemapLayer.prototype.updateMapData = function (tilemap, layer) {
|
||||
{
|
||||
this.tilemap = tilemap;
|
||||
this.layer = this.tilemap.layers[layer];
|
||||
this.tileWidth = this.layer.tileWidth;
|
||||
this.tileHeight = this.layer.tileHeight;
|
||||
this.index = layer;
|
||||
this.updateMax();
|
||||
this.tilemap.layers[layer].dirty = true;
|
||||
@@ -507,7 +510,7 @@ Phaser.TilemapLayer.prototype.getTileXY = function (x, y, point) {
|
||||
* @param {number} y - Y position of the top left of the area to copy (given in tiles, not pixels)
|
||||
* @param {number} width - The width of the area to copy (given in tiles, not pixels)
|
||||
* @param {number} height - The height of the area to copy (given in tiles, not pixels)
|
||||
* @param {boolean} collides - If true only return tiles that collide on one or more faces.
|
||||
* @param {boolean} [collides=false] - If true only return tiles that collide on one or more faces.
|
||||
* @return {array} Array with tiles informations (each contains x, y, and the tile).
|
||||
*/
|
||||
Phaser.TilemapLayer.prototype.getTiles = function (x, y, width, height, collides) {
|
||||
@@ -533,8 +536,8 @@ Phaser.TilemapLayer.prototype.getTiles = function (x, y, width, height, collides
|
||||
}
|
||||
|
||||
// adjust the x,y coordinates for scrollFactor
|
||||
x = this._fixX( x );
|
||||
y = this._fixY( y );
|
||||
x = this._fixX(x);
|
||||
y = this._fixY(y);
|
||||
|
||||
if (width > this.widthInPixels)
|
||||
{
|
||||
@@ -546,6 +549,9 @@ Phaser.TilemapLayer.prototype.getTiles = function (x, y, width, height, collides
|
||||
height = this.heightInPixels;
|
||||
}
|
||||
|
||||
this.context.fillStyle = 'rgba(255,0,255,0.5)';
|
||||
// this.context.fillRect(x, y, width, height);
|
||||
|
||||
var tileWidth = this.tileWidth * this.scale.x;
|
||||
var tileHeight = this.tileHeight * this.scale.y;
|
||||
|
||||
@@ -555,19 +561,19 @@ Phaser.TilemapLayer.prototype.getTiles = function (x, y, width, height, collides
|
||||
this._tw = (this.game.math.snapToCeil(width, tileWidth) + tileWidth) / tileWidth;
|
||||
this._th = (this.game.math.snapToCeil(height, tileHeight) + tileHeight) / tileHeight;
|
||||
|
||||
this.context.fillRect(this._tx * tileWidth, this._ty * tileHeight, this._tw * tileWidth, this._th * tileHeight);
|
||||
|
||||
// This should apply the layer x/y here
|
||||
|
||||
// this._results.length = 0;
|
||||
this._results = [];
|
||||
|
||||
// pretty sure we don't use this any more?
|
||||
// this._results.push( { x: x, y: y, width: width, height: height, tx: this._tx, ty: this._ty, tw: this._tw, th: this._th });
|
||||
this._results.length = 0;
|
||||
|
||||
var _index = 0;
|
||||
var _tile = null;
|
||||
var sx = 0;
|
||||
var sy = 0;
|
||||
|
||||
this.context.fillStyle = 'rgba(255,0,0,0.5)';
|
||||
this.context.strokeStyle = 'rgba(0,0,0,1)';
|
||||
|
||||
for (var wy = this._ty; wy < this._ty + this._th; wy++)
|
||||
{
|
||||
for (var wx = this._tx; wx < this._tx + this._tw; wx++)
|
||||
@@ -575,19 +581,42 @@ Phaser.TilemapLayer.prototype.getTiles = function (x, y, width, height, collides
|
||||
if (this.layer.data[wy] && this.layer.data[wy][wx])
|
||||
{
|
||||
// Could combine
|
||||
_index = this.layer.data[wy][wx] - 1;
|
||||
_tile = this.tileset.getTile(_index);
|
||||
// _index = this.layer.data[wy][wx] - 1;
|
||||
// _tile = this.tileset.getTile(_index);
|
||||
_tile = this.layer.data[wy][wx];
|
||||
|
||||
sx = _tile.width * this.scale.x;
|
||||
sy = _tile.height * this.scale.y;
|
||||
|
||||
if (collides === false || (collides && _tile.collideNone === false))
|
||||
if (_tile)
|
||||
{
|
||||
// convert tile coordinates back to camera space for return
|
||||
var _wx = this._unfixX( wx*sx ) / tileWidth;
|
||||
var _wy = this._unfixY( wy*sy ) / tileHeight;
|
||||
this._results.push({ x: _wx * sx, right: (_wx * sx) + sx, y: _wy * sy, bottom: (_wy * sy) + sy, width: sx, height: sy, tx: _wx, ty: _wy, tile: _tile });
|
||||
|
||||
// sx = _tile.width * this.scale.x;
|
||||
// sy = _tile.height * this.scale.y;
|
||||
sx = this.tileWidth * this.scale.x;
|
||||
sy = this.tileHeight * this.scale.y;
|
||||
|
||||
if (collides === false || (collides && _tile.collides))
|
||||
{
|
||||
this.context.fillRect(_tile.x * this.tileWidth, _tile.y * this.tileHeight, this.tileWidth, this.tileHeight);
|
||||
this.context.strokeRect(_tile.x * this.tileWidth, _tile.y * this.tileHeight, this.tileWidth, this.tileHeight);
|
||||
|
||||
// convert tile coordinates back to camera space for return
|
||||
var _wx = this._unfixX(wx * sx) / this.tileWidth;
|
||||
var _wy = this._unfixY(wy * sy) / this.tileHeight;
|
||||
|
||||
this._results.push({
|
||||
x: _wx * sx,
|
||||
y: _wy * sy,
|
||||
width: sx,
|
||||
height: sy,
|
||||
right: (_wx * sx) + sx,
|
||||
bottom: (_wy * sy) + sy,
|
||||
tx: _wx,
|
||||
ty: _wy,
|
||||
tile: _tile
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -633,34 +662,82 @@ Phaser.TilemapLayer.prototype.updateMax = function () {
|
||||
*/
|
||||
Phaser.TilemapLayer.prototype.render = function () {
|
||||
|
||||
if (this.tilemap && this.tilemap.layers[this.index].dirty )
|
||||
if (this.tilemap && this.tilemap.layers[this.index].dirty)
|
||||
{
|
||||
this.dirty = true;
|
||||
}
|
||||
|
||||
if (!this.dirty || !this.tileset || !this.tilemap || !this.visible)
|
||||
{
|
||||
return;
|
||||
// return;
|
||||
}
|
||||
|
||||
this._prevX = this._dx;
|
||||
this._prevY = this._dy;
|
||||
|
||||
// console.log('render', this._x);
|
||||
|
||||
this._dx = -(this._x - (this._startX * this.tileWidth));
|
||||
this._dy = -(this._y - (this._startY * this.tileHeight));
|
||||
|
||||
// this._dx = Math.floor(this._dx);
|
||||
// this._dy = Math.floor(this._dy);
|
||||
|
||||
this._tx = this._dx;
|
||||
this._ty = this._dy;
|
||||
|
||||
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
// this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
// this.context.fillStyle = '#000000';
|
||||
// this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
|
||||
for (var y = this._startY; y < this._startY + this._maxY; y++)
|
||||
this.context.strokeStyle = '#00ff00';
|
||||
|
||||
for (var y = this._startY, lenY = this._startY + this._maxY; y < lenY; y++)
|
||||
{
|
||||
this._column = this.layer.data[y];
|
||||
|
||||
for (var x = this._startX; x < this._startX + this._maxX; x++)
|
||||
for (var x = this._startX, lenX = this._startX + this._maxX; x < lenX; x++)
|
||||
{
|
||||
var tile = this._column[x];
|
||||
|
||||
if (tile && (tile.faceTop || tile.faceBottom || tile.faceLeft || tile.faceRight))
|
||||
{
|
||||
this._tx = Math.floor(this._tx);
|
||||
|
||||
this.context.beginPath();
|
||||
|
||||
if (tile.faceTop)
|
||||
{
|
||||
this.context.moveTo(this._tx, this._ty);
|
||||
this.context.lineTo(this._tx + this.tileWidth, this._ty);
|
||||
}
|
||||
|
||||
if (tile.faceBottom)
|
||||
{
|
||||
this.context.moveTo(this._tx, this._ty + this.tileHeight);
|
||||
this.context.lineTo(this._tx + this.tileWidth, this._ty + this.tileHeight);
|
||||
}
|
||||
|
||||
if (tile.faceLeft)
|
||||
{
|
||||
this.context.moveTo(this._tx, this._ty);
|
||||
this.context.lineTo(this._tx, this._ty + this.tileHeight);
|
||||
}
|
||||
|
||||
if (tile.faceRight)
|
||||
{
|
||||
this.context.moveTo(this._tx + this.tileWidth, this._ty);
|
||||
this.context.lineTo(this._tx + this.tileWidth, this._ty + this.tileHeight);
|
||||
}
|
||||
|
||||
this.context.stroke();
|
||||
|
||||
// this.context.fillRect(this._tx, this._ty, this.tileWidth, this.tileHeight);
|
||||
// this.context.strokeRect(this._tx, this._ty, this.tileWidth, this.tileHeight);
|
||||
}
|
||||
|
||||
// only -1 on TILED maps, not CSV
|
||||
/*
|
||||
var tile = this.tileset.tiles[this._column[x]-1];
|
||||
|
||||
if (tile)
|
||||
@@ -677,6 +754,7 @@ Phaser.TilemapLayer.prototype.render = function () {
|
||||
this.tileHeight
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
this._tx += this.tileWidth;
|
||||
|
||||
@@ -684,17 +762,18 @@ Phaser.TilemapLayer.prototype.render = function () {
|
||||
|
||||
this._tx = this._dx;
|
||||
this._ty += this.tileHeight;
|
||||
|
||||
}
|
||||
|
||||
// Only needed if running in WebGL, otherwise this array will never get cleared down I don't think!
|
||||
if (this.game.renderType == Phaser.WEBGL)
|
||||
if (this.game.renderType === Phaser.WEBGL)
|
||||
{
|
||||
PIXI.texturesToUpdate.push(this.baseTexture);
|
||||
}
|
||||
|
||||
this.dirty = false;
|
||||
|
||||
if( this.tilemap.layers[this.index].dirty )
|
||||
if (this.tilemap.layers[this.index].dirty)
|
||||
{
|
||||
this.tilemap.layers[this.index].dirty = false;
|
||||
}
|
||||
@@ -764,6 +843,7 @@ Object.defineProperty(Phaser.TilemapLayer.prototype, "scrollX", {
|
||||
this._x = this.widthInPixels - this.renderWidth;
|
||||
}
|
||||
|
||||
|
||||
this._startX = this.game.math.floor(this._x / this.tileWidth);
|
||||
|
||||
if (this._startX < 0)
|
||||
|
||||
@@ -140,6 +140,8 @@ Phaser.TilemapParser = {
|
||||
}
|
||||
}
|
||||
|
||||
// Build collision map
|
||||
|
||||
return [{ name: 'csv', width: width, height: height, alpha: 1, visible: true, indexes: [], tileMargin: 0, tileSpacing: 0, data: output }];
|
||||
|
||||
},
|
||||
@@ -147,11 +149,19 @@ Phaser.TilemapParser = {
|
||||
/**
|
||||
* Parses a Tiled JSON file into valid map data.
|
||||
* @method Phaser.TilemapParser.parseJSON
|
||||
* @param {object} json- The Tiled JSON data.
|
||||
* @param {object} json - The Tiled JSON data.
|
||||
* @return {object} Generated map data.
|
||||
*/
|
||||
parseTiledJSON: function (json) {
|
||||
|
||||
// Let's work out which tilesets are in here
|
||||
var tilesets = [];
|
||||
|
||||
for (var i = 0; i < json.tilesets.length; i++)
|
||||
{
|
||||
tilesets.push(json.tilesets[i].firstgid);
|
||||
}
|
||||
|
||||
var layers = [];
|
||||
|
||||
for (var i = 0; i < json.layers.length; i++)
|
||||
@@ -168,29 +178,69 @@ Phaser.TilemapParser = {
|
||||
var layer = {
|
||||
|
||||
name: json.layers[i].name,
|
||||
x: json.layers[i].x,
|
||||
y: json.layers[i].y,
|
||||
width: json.layers[i].width,
|
||||
height: json.layers[i].height,
|
||||
alpha: json.layers[i].opacity,
|
||||
visible: json.layers[i].visible,
|
||||
properties: {},
|
||||
tileWidth: json.tilewidth,
|
||||
tileHeight: json.tileheight,
|
||||
|
||||
indexes: [],
|
||||
|
||||
tileMargin: json.tilesets[0].margin,
|
||||
tileSpacing: json.tilesets[0].spacing
|
||||
// tileset specific
|
||||
// tileMargin: json.tilesets[0].margin,
|
||||
// tileSpacing: json.tilesets[0].spacing
|
||||
|
||||
};
|
||||
|
||||
if (json.layers[i].properties)
|
||||
{
|
||||
layer.properties = json.layers[i].properties;
|
||||
}
|
||||
|
||||
var x = 0;
|
||||
var row = [];
|
||||
var output = [];
|
||||
var c = 0;
|
||||
var row;
|
||||
|
||||
// Loop through the data field in the JSON.
|
||||
|
||||
// This is an array containing the tile indexes, one after the other. 0 = no tile, everything else = the tile index (starting at 1)
|
||||
// If the map contains multiple tilesets then the indexes are relative to that which the set starts from
|
||||
// Need to set which tileset in the cache = which tileset in the JSON, if you do this manually it means you can use the same map data but a new tileset.
|
||||
|
||||
for (var t = 0; t < json.layers[i].data.length; t++)
|
||||
{
|
||||
// index, x, y, width, height
|
||||
if (json.layers[i].data[t] > 0)
|
||||
{
|
||||
row.push(new Phaser.Tile(json.layers[i].data[t], x, output.length, json.tilewidth, json.tileheight));
|
||||
}
|
||||
else
|
||||
{
|
||||
row.push(null);
|
||||
}
|
||||
|
||||
x++;
|
||||
|
||||
if (x === json.layers[i].width)
|
||||
{
|
||||
output.push(row);
|
||||
x = 0;
|
||||
row = [];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (c === 0)
|
||||
{
|
||||
row = [];
|
||||
}
|
||||
|
||||
row.push(json.layers[i].data[t]);
|
||||
|
||||
c++;
|
||||
|
||||
if (c == json.layers[i].width)
|
||||
@@ -198,9 +248,13 @@ Phaser.TilemapParser = {
|
||||
output.push(row);
|
||||
c = 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
layer.data = output;
|
||||
|
||||
// Build collision map
|
||||
// console.log(output);
|
||||
|
||||
layers.push(layer);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user