mirror of
https://github.com/photonstorm/phaser
synced 2024-11-23 13:13:43 +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.
|
||||
* 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.
|
||||
* TilemapLayer.getRayCastTiles will let you get all tiles that hit the given line for further processing.
|
||||
|
||||
|
||||
Updates:
|
||||
|
|
|
@ -6,7 +6,7 @@ function create() {
|
|||
|
||||
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);
|
||||
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.
|
||||
*
|
||||
* @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.
|
||||
* @return {array} An array of coordinates.
|
||||
*/
|
||||
coordinatesOnLine: function (results) {
|
||||
coordinatesOnLine: function (stepRate, results) {
|
||||
|
||||
if (typeof stepRate === 'undefined') { stepRate = 1; }
|
||||
if (typeof results === 'undefined') { results = []; }
|
||||
|
||||
var x1 = Math.round(this.start.x);
|
||||
|
@ -151,6 +153,8 @@ Phaser.Line.prototype = {
|
|||
|
||||
results.push([x1, y1]);
|
||||
|
||||
var i = 1;
|
||||
|
||||
while (!((x1 == x2) && (y1 == y2)))
|
||||
{
|
||||
var e2 = err << 1;
|
||||
|
@ -167,7 +171,13 @@ Phaser.Line.prototype = {
|
|||
y1 += sy;
|
||||
}
|
||||
|
||||
results.push([x1, y1]);
|
||||
if (i % stepRate === 0)
|
||||
{
|
||||
results.push([x1, y1]);
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
return results;
|
||||
|
|
|
@ -44,6 +44,11 @@ Phaser.Physics.Arcade = function (game) {
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -1052,7 +1057,7 @@ Phaser.Physics.Arcade.prototype = {
|
|||
{
|
||||
ox = body.x - tile.right;
|
||||
|
||||
if (ox < -this.OVERLAP_BIAS)
|
||||
if (ox < -this.TILE_BIAS)
|
||||
{
|
||||
ox = 0;
|
||||
}
|
||||
|
@ -1065,7 +1070,7 @@ Phaser.Physics.Arcade.prototype = {
|
|||
{
|
||||
ox = body.right - tile.left;
|
||||
|
||||
if (ox > this.OVERLAP_BIAS)
|
||||
if (ox > this.TILE_BIAS)
|
||||
{
|
||||
ox = 0;
|
||||
}
|
||||
|
@ -1101,7 +1106,7 @@ Phaser.Physics.Arcade.prototype = {
|
|||
{
|
||||
oy = body.y - tile.bottom;
|
||||
|
||||
if (oy < -this.OVERLAP_BIAS)
|
||||
if (oy < -this.TILE_BIAS)
|
||||
{
|
||||
oy = 0;
|
||||
}
|
||||
|
@ -1114,7 +1119,7 @@ Phaser.Physics.Arcade.prototype = {
|
|||
{
|
||||
oy = body.bottom - tile.top;
|
||||
|
||||
if (oy > this.OVERLAP_BIAS)
|
||||
if (oy > this.TILE_BIAS)
|
||||
{
|
||||
oy = 0;
|
||||
}
|
||||
|
|
|
@ -144,6 +144,20 @@ Phaser.Tile = function (layer, index, x, y, width, height) {
|
|||
|
||||
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.
|
||||
*
|
||||
|
|
|
@ -151,6 +151,12 @@ Phaser.TilemapLayer = function (game, tilemap, index, width, height) {
|
|||
*/
|
||||
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.
|
||||
* @private
|
||||
|
@ -457,17 +463,46 @@ Phaser.TilemapLayer.prototype.getTileXY = function (x, y, point) {
|
|||
/**
|
||||
* Gets all tiles that intersect with the given line.
|
||||
*
|
||||
* @method Phaser.TilemapLayer#getIntersectingTiles
|
||||
* @method Phaser.TilemapLayer#getRayCastTiles
|
||||
* @memberof Phaser.TilemapLayer
|
||||
* @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.
|
||||
*/
|
||||
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 set;
|
||||
// var ox = 0;
|
||||
// var oy = 0;
|
||||
|
||||
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);
|
||||
|
||||
// if (tile.debug)
|
||||
// {
|
||||
// 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);
|
||||
// }
|
||||
if (tile.debug)
|
||||
{
|
||||
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._tx += this.map.tileWidth;
|
||||
|
|
Loading…
Reference in a new issue