mirror of
https://github.com/photonstorm/phaser
synced 2024-11-27 07:01:20 +00:00
TilemapLayer.getRayCastTiles will let you get all tiles that hit the given line for further processing.
Fixed Tilemap collision. Added new TILE_BIAS const to aid with fast/small sprites.
This commit is contained in:
parent
f678d1fd31
commit
017a017b96
7 changed files with 208 additions and 18 deletions
|
@ -153,6 +153,7 @@ New features:
|
||||||
* ArcadePhysics.Body has a new gravityScale property, which is a modifier multiplied against the world gravity value on a Body.
|
* ArcadePhysics.Body has a new gravityScale property, which is a modifier multiplied against the world gravity value on a Body.
|
||||||
* Line.coordinatesOnLine will return all coordinates on the line using Bresenhams line algorithm.
|
* Line.coordinatesOnLine will return all coordinates on the line using Bresenhams line algorithm.
|
||||||
* Line now has x, y, width, height, top, bottom, left and right properties, so you can effectively get its bounds.
|
* Line now has x, y, width, height, top, bottom, left and right properties, so you can effectively get its bounds.
|
||||||
|
* TilemapLayer.getRayCastTiles will let you get all tiles that hit the given line for further processing.
|
||||||
|
|
||||||
|
|
||||||
Updates:
|
Updates:
|
||||||
|
|
|
@ -6,7 +6,7 @@ function create() {
|
||||||
|
|
||||||
var line = new Phaser.Line(100, 50, 10, 300);
|
var line = new Phaser.Line(100, 50, 10, 300);
|
||||||
|
|
||||||
var coords = line.coordinatesOnLine();
|
var coords = line.coordinatesOnLine(8);
|
||||||
|
|
||||||
var bmd = game.add.bitmapData(800, 600);
|
var bmd = game.add.bitmapData(800, 600);
|
||||||
bmd.context.fillStyle = '#ffffff';
|
bmd.context.fillStyle = '#ffffff';
|
||||||
|
|
127
examples/wip/tilemap raycast.js
Normal file
127
examples/wip/tilemap raycast.js
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
|
||||||
|
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
|
||||||
|
|
||||||
|
function preload() {
|
||||||
|
|
||||||
|
game.load.tilemap('map', 'assets/tilemaps/maps/collision_test.json', null, Phaser.Tilemap.TILED_JSON);
|
||||||
|
game.load.image('ground_1x1', 'assets/tilemaps/tiles/ground_1x1.png');
|
||||||
|
game.load.image('phaser', 'assets/sprites/phaser-dude.png');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var map;
|
||||||
|
var layer;
|
||||||
|
var cursors;
|
||||||
|
var sprite;
|
||||||
|
var line;
|
||||||
|
var tileHits = [];
|
||||||
|
var plotting = false;
|
||||||
|
|
||||||
|
function create() {
|
||||||
|
|
||||||
|
line = new Phaser.Line();
|
||||||
|
|
||||||
|
map = game.add.tilemap('map');
|
||||||
|
|
||||||
|
map.addTilesetImage('ground_1x1');
|
||||||
|
|
||||||
|
layer = map.createLayer('Tile Layer 1');
|
||||||
|
|
||||||
|
layer.resizeWorld();
|
||||||
|
|
||||||
|
map.setCollisionBetween(1, 12);
|
||||||
|
|
||||||
|
layer.debug = true;
|
||||||
|
|
||||||
|
sprite = game.add.sprite(260, 70, 'phaser');
|
||||||
|
|
||||||
|
game.physics.enable(sprite);
|
||||||
|
|
||||||
|
game.camera.follow(sprite);
|
||||||
|
|
||||||
|
cursors = game.input.keyboard.createCursorKeys();
|
||||||
|
|
||||||
|
var help = game.add.text(10, 10, 'Arrows to move, click and drag to cast a ray', { font: '16px Arial', fill: '#ffffff' });
|
||||||
|
help.fixedToCamera = true;
|
||||||
|
|
||||||
|
game.input.onDown.add(startLine, this);
|
||||||
|
game.input.onUp.add(raycast, this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function startLine(pointer) {
|
||||||
|
|
||||||
|
if (tileHits.length > 0)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < tileHits.length; i++)
|
||||||
|
{
|
||||||
|
tileHits[i].debug = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
layer.dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
line.start.set(pointer.worldX, pointer.worldY);
|
||||||
|
|
||||||
|
plotting = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function raycast(pointer) {
|
||||||
|
|
||||||
|
line.end.set(pointer.worldX, pointer.worldY);
|
||||||
|
|
||||||
|
tileHits = layer.getRayCastTiles(line, 4, false, false);
|
||||||
|
|
||||||
|
if (tileHits.length > 0)
|
||||||
|
{
|
||||||
|
// Just so we can visually see the tiles
|
||||||
|
for (var i = 0; i < tileHits.length; i++)
|
||||||
|
{
|
||||||
|
tileHits[i].debug = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
layer.dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
plotting = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
|
||||||
|
if (plotting)
|
||||||
|
{
|
||||||
|
line.end.set(game.input.activePointer.worldX, game.input.activePointer.worldY);
|
||||||
|
}
|
||||||
|
|
||||||
|
game.physics.arcade.collide(sprite, layer);
|
||||||
|
|
||||||
|
sprite.body.velocity.x = 0;
|
||||||
|
sprite.body.velocity.y = 0;
|
||||||
|
|
||||||
|
if (cursors.up.isDown)
|
||||||
|
{
|
||||||
|
sprite.body.velocity.y = -200;
|
||||||
|
}
|
||||||
|
else if (cursors.down.isDown)
|
||||||
|
{
|
||||||
|
sprite.body.velocity.y = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursors.left.isDown)
|
||||||
|
{
|
||||||
|
sprite.body.velocity.x = -200;
|
||||||
|
}
|
||||||
|
else if (cursors.right.isDown)
|
||||||
|
{
|
||||||
|
sprite.body.velocity.x = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function render() {
|
||||||
|
|
||||||
|
game.debug.geom(line);
|
||||||
|
|
||||||
|
}
|
|
@ -131,11 +131,13 @@ Phaser.Line.prototype = {
|
||||||
* The start and end points are rounded before this runs as the algorithm works on integers.
|
* The start and end points are rounded before this runs as the algorithm works on integers.
|
||||||
*
|
*
|
||||||
* @method Phaser.Line#coordinatesOnLine
|
* @method Phaser.Line#coordinatesOnLine
|
||||||
|
* @param {number} [stepRate=1] - How many steps will we return? 1 = every coordinate on the line, 2 = every other coordinate, etc.
|
||||||
* @param {array} [results] - The array to store the results in. If not provided a new one will be generated.
|
* @param {array} [results] - The array to store the results in. If not provided a new one will be generated.
|
||||||
* @return {array} An array of coordinates.
|
* @return {array} An array of coordinates.
|
||||||
*/
|
*/
|
||||||
coordinatesOnLine: function (results) {
|
coordinatesOnLine: function (stepRate, results) {
|
||||||
|
|
||||||
|
if (typeof stepRate === 'undefined') { stepRate = 1; }
|
||||||
if (typeof results === 'undefined') { results = []; }
|
if (typeof results === 'undefined') { results = []; }
|
||||||
|
|
||||||
var x1 = Math.round(this.start.x);
|
var x1 = Math.round(this.start.x);
|
||||||
|
@ -151,6 +153,8 @@ Phaser.Line.prototype = {
|
||||||
|
|
||||||
results.push([x1, y1]);
|
results.push([x1, y1]);
|
||||||
|
|
||||||
|
var i = 1;
|
||||||
|
|
||||||
while (!((x1 == x2) && (y1 == y2)))
|
while (!((x1 == x2) && (y1 == y2)))
|
||||||
{
|
{
|
||||||
var e2 = err << 1;
|
var e2 = err << 1;
|
||||||
|
@ -167,7 +171,13 @@ Phaser.Line.prototype = {
|
||||||
y1 += sy;
|
y1 += sy;
|
||||||
}
|
}
|
||||||
|
|
||||||
results.push([x1, y1]);
|
if (i % stepRate === 0)
|
||||||
|
{
|
||||||
|
results.push([x1, y1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
|
|
@ -44,6 +44,11 @@ Phaser.Physics.Arcade = function (game) {
|
||||||
*/
|
*/
|
||||||
this.OVERLAP_BIAS = 4;
|
this.OVERLAP_BIAS = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {number} TILE_BIAS - A value added to the delta values during collision with tiles. Adjust this if you get tunnelling.
|
||||||
|
*/
|
||||||
|
this.TILE_BIAS = 16;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property {Phaser.QuadTree} quadTree - The world QuadTree.
|
* @property {Phaser.QuadTree} quadTree - The world QuadTree.
|
||||||
*/
|
*/
|
||||||
|
@ -1052,7 +1057,7 @@ Phaser.Physics.Arcade.prototype = {
|
||||||
{
|
{
|
||||||
ox = body.x - tile.right;
|
ox = body.x - tile.right;
|
||||||
|
|
||||||
if (ox < -this.OVERLAP_BIAS)
|
if (ox < -this.TILE_BIAS)
|
||||||
{
|
{
|
||||||
ox = 0;
|
ox = 0;
|
||||||
}
|
}
|
||||||
|
@ -1065,7 +1070,7 @@ Phaser.Physics.Arcade.prototype = {
|
||||||
{
|
{
|
||||||
ox = body.right - tile.left;
|
ox = body.right - tile.left;
|
||||||
|
|
||||||
if (ox > this.OVERLAP_BIAS)
|
if (ox > this.TILE_BIAS)
|
||||||
{
|
{
|
||||||
ox = 0;
|
ox = 0;
|
||||||
}
|
}
|
||||||
|
@ -1101,7 +1106,7 @@ Phaser.Physics.Arcade.prototype = {
|
||||||
{
|
{
|
||||||
oy = body.y - tile.bottom;
|
oy = body.y - tile.bottom;
|
||||||
|
|
||||||
if (oy < -this.OVERLAP_BIAS)
|
if (oy < -this.TILE_BIAS)
|
||||||
{
|
{
|
||||||
oy = 0;
|
oy = 0;
|
||||||
}
|
}
|
||||||
|
@ -1114,7 +1119,7 @@ Phaser.Physics.Arcade.prototype = {
|
||||||
{
|
{
|
||||||
oy = body.bottom - tile.top;
|
oy = body.bottom - tile.top;
|
||||||
|
|
||||||
if (oy > this.OVERLAP_BIAS)
|
if (oy > this.TILE_BIAS)
|
||||||
{
|
{
|
||||||
oy = 0;
|
oy = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,20 @@ Phaser.Tile = function (layer, index, x, y, width, height) {
|
||||||
|
|
||||||
Phaser.Tile.prototype = {
|
Phaser.Tile.prototype = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given x and y world coordinates are within this Tile.
|
||||||
|
*
|
||||||
|
* @method Phaser.Tile#containsPoint
|
||||||
|
* @param {number} x - The x coordinate to test.
|
||||||
|
* @param {number} y - The y coordinate to test.
|
||||||
|
* @return {boolean} True if the coordinates are within this Tile, otherwise false.
|
||||||
|
*/
|
||||||
|
containsPoint: function (x, y) {
|
||||||
|
|
||||||
|
return !(x < this.worldX || y < this.worldY || x > this.right || y > this.bottom);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for intersection with this tile.
|
* Check for intersection with this tile.
|
||||||
*
|
*
|
||||||
|
|
|
@ -151,6 +151,12 @@ Phaser.TilemapLayer = function (game, tilemap, index, width, height) {
|
||||||
*/
|
*/
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {number} rayStepRate - When ray-casting against tiles this is the number of steps it will jump. For larger tile sizes you can increase this to improve performance.
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
this.rayStepRate = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property {number} _cw - Local collision var.
|
* @property {number} _cw - Local collision var.
|
||||||
* @private
|
* @private
|
||||||
|
@ -457,17 +463,46 @@ Phaser.TilemapLayer.prototype.getTileXY = function (x, y, point) {
|
||||||
/**
|
/**
|
||||||
* Gets all tiles that intersect with the given line.
|
* Gets all tiles that intersect with the given line.
|
||||||
*
|
*
|
||||||
* @method Phaser.TilemapLayer#getIntersectingTiles
|
* @method Phaser.TilemapLayer#getRayCastTiles
|
||||||
* @memberof Phaser.TilemapLayer
|
* @memberof Phaser.TilemapLayer
|
||||||
* @param {Phaser.Line} line - The line used to determine which tiles to return.
|
* @param {Phaser.Line} line - The line used to determine which tiles to return.
|
||||||
|
* @param {number} [stepRate] - How many steps through the ray will we check? If undefined or null it uses TilemapLayer.rayStepRate.
|
||||||
|
* @param {boolean} [collides=false] - If true only return tiles that collide on one or more faces.
|
||||||
|
* @param {boolean} [interestingFace=false] - If true only return tiles that have interesting faces.
|
||||||
* @return {array<Phaser.Tile>} An array of Phaser.Tiles.
|
* @return {array<Phaser.Tile>} An array of Phaser.Tiles.
|
||||||
*/
|
*/
|
||||||
Phaser.TilemapLayer.prototype.getIntersectingTiles = function (line) {
|
Phaser.TilemapLayer.prototype.getRayCastTiles = function (line, stepRate, collides, interestingFace) {
|
||||||
|
|
||||||
var tiles = this.getTiles(x, y, width, height, false);
|
if (typeof stepRate === 'undefined' || stepRate === null) { stepRate = this.rayStepRate; }
|
||||||
|
if (typeof collides === 'undefined') { collides = false; }
|
||||||
|
if (typeof interestingFace === 'undefined') { interestingFace = false; }
|
||||||
|
|
||||||
|
// First get all tiles that touch the bounds of the line
|
||||||
|
var tiles = this.getTiles(line.x, line.y, line.width, line.height, collides, interestingFace);
|
||||||
|
|
||||||
return tiles;
|
if (tiles.length === 0)
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we only want the tiles that intersect with the points on this line
|
||||||
|
var coords = line.coordinatesOnLine(stepRate);
|
||||||
|
var total = coords.length;
|
||||||
|
var results = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < tiles.length; i++)
|
||||||
|
{
|
||||||
|
for (var t = 0; t < total; t++)
|
||||||
|
{
|
||||||
|
if (tiles[i].containsPoint(coords[t][0], coords[t][1]))
|
||||||
|
{
|
||||||
|
results.push(tiles[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,8 +624,6 @@ Phaser.TilemapLayer.prototype.render = function () {
|
||||||
|
|
||||||
var tile;
|
var tile;
|
||||||
var set;
|
var set;
|
||||||
// var ox = 0;
|
|
||||||
// var oy = 0;
|
|
||||||
|
|
||||||
if (this.debug)
|
if (this.debug)
|
||||||
{
|
{
|
||||||
|
@ -618,11 +651,11 @@ Phaser.TilemapLayer.prototype.render = function () {
|
||||||
|
|
||||||
set.draw(this.context, Math.floor(this._tx), Math.floor(this._ty), tile.index);
|
set.draw(this.context, Math.floor(this._tx), Math.floor(this._ty), tile.index);
|
||||||
|
|
||||||
// if (tile.debug)
|
if (tile.debug)
|
||||||
// {
|
{
|
||||||
// this.context.fillStyle = 'rgba(0, 255, 0, 0.4)';
|
this.context.fillStyle = 'rgba(0, 255, 0, 0.4)';
|
||||||
// this.context.fillRect(Math.floor(this._tx), Math.floor(this._ty), this.map.tileWidth, this.map.tileHeight);
|
this.context.fillRect(Math.floor(this._tx), Math.floor(this._ty), this.map.tileWidth, this.map.tileHeight);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._tx += this.map.tileWidth;
|
this._tx += this.map.tileWidth;
|
||||||
|
|
Loading…
Reference in a new issue