Skip to content

Commit af15b9b

Browse files
committed
Line.reflect will calculate the reflected, or outgoing angle of the line and a given line if they intersect. This can be used for Body vs. Line collision responses and rebounds.
Line.normalX and Line.normalY contain the x and y components of the left-hand normal of the line. Line.fromAngle will sets this line to start at the given `x` and `y` coordinates and for the segment to extend at `angle` for the given `length`.
1 parent 1ceec8e commit af15b9b

2 files changed

Lines changed: 108 additions & 6 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ Version 2.2.2 - "Alkindar" - in development
7474
### New Features
7575

7676
* Phaser.Loader now supports BLOB urls for audio files (thanks @aressler38 #1462)
77+
* Line.reflect will calculate the reflected, or outgoing angle of the line and a given line if they intersect. This can be used for Body vs. Line collision responses and rebounds.
78+
* Line.normalX and Line.normalY contain the x and y components of the left-hand normal of the line.
79+
* Line.fromAngle will sets this line to start at the given `x` and `y` coordinates and for the segment to extend at `angle` for the given `length`.
7780

7881
### Updates
7982

src/geom/Line.js

Lines changed: 105 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Phaser.Line.prototype = {
3737

3838
/**
3939
* Sets the components of the Line to the specified values.
40+
*
4041
* @method Phaser.Line#setTo
4142
* @param {number} [x1=0] - The x coordinate of the start of the line.
4243
* @param {number} [y1=0] - The y coordinate of the start of the line.
@@ -56,6 +57,7 @@ Phaser.Line.prototype = {
5657
/**
5758
* Sets the line to match the x/y coordinates of the two given sprites.
5859
* Can optionally be calculated from their center coordinates.
60+
*
5961
* @method Phaser.Line#fromSprite
6062
* @param {Phaser.Sprite} startSprite - The coordinates of this Sprite will be set to the Line.start point.
6163
* @param {Phaser.Sprite} endSprite - The coordinates of this Sprite will be set to the Line.start point.
@@ -75,6 +77,25 @@ Phaser.Line.prototype = {
7577

7678
},
7779

80+
/**
81+
* Sets this line to start at the given `x` and `y` coordinates and for the segment to extend at `angle` for the given `length`.
82+
*
83+
* @method Phaser.Line#fromAngle
84+
* @param {number} x - The x coordinate of the start of the line.
85+
* @param {number} y - The y coordinate of the start of the line.
86+
* @param {number} angle - The angle of the line in radians.
87+
* @param {number} length - The length of the line in pixels.
88+
* @return {Phaser.Line} This line object
89+
*/
90+
fromAngle: function (x, y, angle, length) {
91+
92+
this.start.setTo(x, y);
93+
this.end.setTo(x + (Math.cos(angle) * length), y + (Math.sin(angle) * length));
94+
95+
return this;
96+
97+
},
98+
7899
/**
79100
* Checks for intersection between this line and another Line.
80101
* If asSegment is true it will check for segment intersection. If asSegment is false it will check for line intersection.
@@ -92,8 +113,25 @@ Phaser.Line.prototype = {
92113

93114
},
94115

116+
/**
117+
* Returns the reflected, or outgoing angle of intersection between this and the given line in radians.
118+
* If asSegment is true it will check for segment intersection. If asSegment is false it will check for line intersection.
119+
* If the lines don't intersect then it returns `null`.
120+
*
121+
* @method Phaser.Line#reflect
122+
* @param {Phaser.Line} line - The line to check against this one.
123+
* @param {boolean} [asSegment=true] - If true it will check for segment intersection, otherwise full line intersection.
124+
* @return {number} The reflected angle of the intersection in radians, or null if there is no intersection.
125+
*/
126+
reflect: function (line, asSegment) {
127+
128+
return Phaser.Line.reflect(this, line, asSegment);
129+
130+
},
131+
95132
/**
96133
* Tests if the given coordinates fall on this line. See pointOnSegment to test against just the line segment.
134+
*
97135
* @method Phaser.Line#pointOnLine
98136
* @param {number} x - The line to check against this one.
99137
* @param {number} y - The line to check against this one.
@@ -107,6 +145,7 @@ Phaser.Line.prototype = {
107145

108146
/**
109147
* Tests if the given coordinates fall on this line and within the segment. See pointOnLine to test against just the line.
148+
*
110149
* @method Phaser.Line#pointOnSegment
111150
* @param {number} x - The line to check against this one.
112151
* @param {number} y - The line to check against this one.
@@ -360,6 +399,32 @@ Object.defineProperty(Phaser.Line.prototype, "height", {
360399

361400
});
362401

402+
/**
403+
* @name Phaser.Line#normalX
404+
* @property {number} normalX - Gets the x component of the left-hand normal of this line.
405+
* @readonly
406+
*/
407+
Object.defineProperty(Phaser.Line.prototype, "normalX", {
408+
409+
get: function () {
410+
return Math.cos(this.angle - 1.5707963267948966);
411+
}
412+
413+
});
414+
415+
/**
416+
* @name Phaser.Line#normalY
417+
* @property {number} normalY - Gets the y component of the left-hand normal of this line.
418+
* @readonly
419+
*/
420+
Object.defineProperty(Phaser.Line.prototype, "normalY", {
421+
422+
get: function () {
423+
return Math.sin(this.angle - 1.5707963267948966);
424+
}
425+
426+
});
427+
363428
/**
364429
* Checks for intersection between two lines as defined by the given start and end points.
365430
* If asSegment is true it will check for line segment intersection. If asSegment is false it will check for line intersection.
@@ -372,7 +437,7 @@ Object.defineProperty(Phaser.Line.prototype, "height", {
372437
* @param {Phaser.Point} e - The start of the second Line to be checked.
373438
* @param {Phaser.Point} f - The end of the second line to be checked.
374439
* @param {boolean} [asSegment=true] - If true it will check for segment intersection, otherwise full line intersection.
375-
* @param {Phaser.Point} [result] - A Point object to store the result in, if not given a new one will be created.
440+
* @param {Phaser.Point|object} [result] - A Point object to store the result in, if not given a new one will be created.
376441
* @return {Phaser.Point} The intersection segment of the two lines as a Point, or null if there is no intersection.
377442
*/
378443
Phaser.Line.intersectsPoints = function (a, b, e, f, asSegment, result) {
@@ -398,12 +463,16 @@ Phaser.Line.intersectsPoints = function (a, b, e, f, asSegment, result) {
398463

399464
if (asSegment)
400465
{
401-
var uc = ((f.y-e.y)*(b.x-a.x) - (f.x-e.x)*(b.y- a.y));
402-
var ua = (((f.x-e.x)*(a.y-e.y)) - (f.y-e.y)*(a.x-e.x)) / uc;
403-
var ub = (((b.x- a.x)*(a.y- e.y)) - ((b.y-a.y)*(a.x- e.x))) / uc;
404-
if (ua >=0 && ua<=1 && ub >=0 && ub <=1) {
466+
var uc = ((f.y - e.y) * (b.x - a.x) - (f.x - e.x) * (b.y - a.y));
467+
var ua = (((f.x - e.x) * (a.y - e.y)) - (f.y - e.y) * (a.x - e.x)) / uc;
468+
var ub = (((b.x - a.x) * (a.y - e.y)) - ((b.y - a.y) * (a.x - e.x))) / uc;
469+
470+
if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1)
471+
{
405472
return result;
406-
} else {
473+
}
474+
else
475+
{
407476
return null;
408477
}
409478
}
@@ -431,3 +500,33 @@ Phaser.Line.intersects = function (a, b, asSegment, result) {
431500
return Phaser.Line.intersectsPoints(a.start, a.end, b.start, b.end, asSegment, result);
432501

433502
};
503+
504+
/**
505+
* Returns the reflected angle of intersection between two lines. This is the outgoing angle based on the angle of Line 1.
506+
* If asSegment is true it will check for segment intersection.
507+
* If asSegment is false it will check for line intersection.
508+
*
509+
* @method Phaser.Line.reflect
510+
* @param {Phaser.Line} a - The first Line to be checked.
511+
* @param {Phaser.Line} b - The second Line to be checked.
512+
* @param {boolean} [asSegment=true] - If true it will check for segment intersection, otherwise full line intersection.
513+
* @return {number} The reflected angle of the intersection in radians, or null if there is no intersection.
514+
*/
515+
Phaser.Line.reflect = function (a, b, asSegment) {
516+
517+
var p = { x: 0, y: 0 };
518+
519+
if (Phaser.Line.intersectsPoints(a.start, a.end, b.start, b.end, asSegment, p) !== null)
520+
{
521+
var ex = p.x + b.normalX;
522+
var ey = p.y + b.normalY;
523+
var normalAngle = Math.atan2(ey - p.y, ex - p.x);
524+
return 2 * normalAngle - 3.141592653589793 - a.angle;
525+
}
526+
else
527+
{
528+
return null;
529+
}
530+
531+
};
532+

0 commit comments

Comments
 (0)