2014-01-29 00:21:28 +00:00
/ * *
* @ author Richard Davey < rich @ photonstorm . com >
2014-02-05 05:54:25 +00:00
* @ copyright 2014 Photon Storm Ltd .
2014-01-29 00:21:28 +00:00
* @ license { @ link https : //github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
* /
/ * *
* Creates a new Line object with a start and an end point .
* @ class Line
* @ classdesc Phaser - Line
* @ constructor
* @ param { number } [ x1 = 0 ] - The x coordinate of the start of the line .
* @ param { number } [ y1 = 0 ] - The y coordinate of the start of the line .
* @ param { number } [ x2 = 0 ] - The x coordinate of the end of the line .
* @ param { number } [ y2 = 0 ] - The y coordinate of the end of the line .
* @ return { Phaser . Line } This line object
* /
Phaser . Line = function ( x1 , y1 , x2 , y2 ) {
x1 = x1 || 0 ;
y1 = y1 || 0 ;
x2 = x2 || 0 ;
y2 = y2 || 0 ;
/ * *
* @ property { Phaser . Point } start - The start point of the line .
* /
this . start = new Phaser . Point ( x1 , y1 ) ;
/ * *
* @ property { Phaser . Point } end - The end point of the line .
* /
this . end = new Phaser . Point ( x2 , y2 ) ;
} ;
Phaser . Line . prototype = {
/ * *
* Sets the components of the Line to the specified values .
* @ method Phaser . Line # setTo
* @ param { number } [ x1 = 0 ] - The x coordinate of the start of the line .
* @ param { number } [ y1 = 0 ] - The y coordinate of the start of the line .
* @ param { number } [ x2 = 0 ] - The x coordinate of the end of the line .
* @ param { number } [ y2 = 0 ] - The y coordinate of the end of the line .
* @ return { Phaser . Line } This line object
* /
setTo : function ( x1 , y1 , x2 , y2 ) {
this . start . setTo ( x1 , y1 ) ;
this . end . setTo ( x2 , y2 ) ;
return this ;
} ,
2014-01-31 05:42:20 +00:00
/ * *
* Sets the line to match the x / y coordinates of the two given sprites .
* Can optionally be calculated from their center coordinates .
* @ method Phaser . Line # fromSprite
* @ param { Phaser . Sprite } startSprite - The coordinates of this Sprite will be set to the Line . start point .
* @ param { Phaser . Sprite } endSprite - The coordinates of this Sprite will be set to the Line . start point .
2014-03-25 12:44:20 +00:00
* @ param { boolean } [ useCenter = false ] - If true it will use startSprite . center . x , if false startSprite . x . Note that Sprites don 't have a center property by default, so only enable if you' ve over - ridden your Sprite with a custom class .
2014-02-05 05:04:23 +00:00
* @ return { Phaser . Line } This line object
2014-01-31 05:42:20 +00:00
* /
2014-01-29 00:21:28 +00:00
fromSprite : function ( startSprite , endSprite , useCenter ) {
2014-03-25 12:44:20 +00:00
if ( typeof useCenter === 'undefined' ) { useCenter = false ; }
2014-01-29 00:21:28 +00:00
if ( useCenter )
{
2014-02-05 05:04:23 +00:00
return this . setTo ( startSprite . center . x , startSprite . center . y , endSprite . center . x , endSprite . center . y ) ;
2014-01-29 00:21:28 +00:00
}
else
{
2014-02-05 05:04:23 +00:00
return this . setTo ( startSprite . x , startSprite . y , endSprite . x , endSprite . y ) ;
2014-01-29 00:21:28 +00:00
}
} ,
/ * *
2014-01-29 17:10:13 +00:00
* Checks for intersection between this line and another Line .
* If asSegment is true it will check for segment intersection . If asSegment is false it will check for line intersection .
2014-01-29 00:21:28 +00:00
* Returns the intersection segment of AB and EF as a Point , or null if there is no intersection .
*
* @ method Phaser . Line # intersects
* @ param { Phaser . Line } line - The line to check against this one .
* @ param { boolean } [ asSegment = true ] - If true it will check for segment intersection , otherwise full line intersection .
* @ param { Phaser . Point } [ result ] - A Point object to store the result in , if not given a new one will be created .
* @ return { Phaser . Point } The intersection segment of the two lines as a Point , or null if there is no intersection .
* /
intersects : function ( line , asSegment , result ) {
2014-01-29 17:10:13 +00:00
return Phaser . Line . intersectsPoints ( this . start , this . end , line . start , line . end , asSegment , result ) ;
2014-01-29 00:21:28 +00:00
} ,
/ * *
* Tests if the given coordinates fall on this line . See pointOnSegment to test against just the line segment .
* @ method Phaser . Line # pointOnLine
* @ param { number } x - The line to check against this one .
* @ param { number } y - The line to check against this one .
* @ return { boolean } True if the point is on the line , false if not .
* /
pointOnLine : function ( x , y ) {
2014-04-30 09:50:01 +00:00
return ( ( x - this . start . x ) * ( this . end . y - this . start . y ) === ( this . end . x - this . start . x ) * ( y - this . start . y ) ) ;
2014-01-29 00:21:28 +00:00
} ,
/ * *
* Tests if the given coordinates fall on this line and within the segment . See pointOnLine to test against just the line .
* @ method Phaser . Line # pointOnSegment
* @ param { number } x - The line to check against this one .
* @ param { number } y - The line to check against this one .
* @ return { boolean } True if the point is on the line and segment , false if not .
* /
pointOnSegment : function ( x , y ) {
var xMin = Math . min ( this . start . x , this . end . x ) ;
var xMax = Math . max ( this . start . x , this . end . x ) ;
var yMin = Math . min ( this . start . y , this . end . y ) ;
var yMax = Math . max ( this . start . y , this . end . y ) ;
return ( this . pointOnLine ( x , y ) && ( x >= xMin && x <= xMax ) && ( y >= yMin && y <= yMax ) ) ;
2014-03-14 00:05:03 +00:00
} ,
/ * *
* Using Bresenham ' s line algorithm this will return an array of all coordinates on this line .
* The start and end points are rounded before this runs as the algorithm works on integers .
*
* @ method Phaser . Line # coordinatesOnLine
2014-03-14 02:33:58 +00:00
* @ param { number } [ stepRate = 1 ] - How many steps will we return ? 1 = every coordinate on the line , 2 = every other coordinate , etc .
2014-03-14 00:05:03 +00:00
* @ 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 .
* /
2014-03-14 02:33:58 +00:00
coordinatesOnLine : function ( stepRate , results ) {
2014-03-14 00:05:03 +00:00
2014-03-14 02:33:58 +00:00
if ( typeof stepRate === 'undefined' ) { stepRate = 1 ; }
2014-03-14 00:05:03 +00:00
if ( typeof results === 'undefined' ) { results = [ ] ; }
var x1 = Math . round ( this . start . x ) ;
var y1 = Math . round ( this . start . y ) ;
var x2 = Math . round ( this . end . x ) ;
var y2 = Math . round ( this . end . y ) ;
var dx = Math . abs ( x2 - x1 ) ;
var dy = Math . abs ( y2 - y1 ) ;
var sx = ( x1 < x2 ) ? 1 : - 1 ;
var sy = ( y1 < y2 ) ? 1 : - 1 ;
var err = dx - dy ;
results . push ( [ x1 , y1 ] ) ;
2014-03-14 02:33:58 +00:00
var i = 1 ;
2014-03-14 00:05:03 +00:00
while ( ! ( ( x1 == x2 ) && ( y1 == y2 ) ) )
{
var e2 = err << 1 ;
2014-03-23 07:59:28 +00:00
2014-03-14 00:05:03 +00:00
if ( e2 > - dy )
{
err -= dy ;
x1 += sx ;
}
if ( e2 < dx )
{
err += dx ;
y1 += sy ;
}
2014-03-14 02:33:58 +00:00
if ( i % stepRate === 0 )
{
results . push ( [ x1 , y1 ] ) ;
}
i ++ ;
2014-03-14 00:05:03 +00:00
}
return results ;
2014-08-21 21:36:40 +00:00
} ,
/ * *
* Returns a new Line object with the same values for the start and end properties as this Line object .
* @ method Phaser . Line # clone
* @ param { Phaser . Line } output - Optional Line object . If given the values will be set into the object , otherwise a brand new Line object will be created and returned .
* @ return { Phaser . Line } The cloned Line object .
* /
clone : function ( output ) {
if ( typeof output === "undefined" || output === null )
{
output = new Phaser . Line ( this . start . x , this . start . y , this . end . x , this . end . y ) ;
}
else
{
2014-08-22 15:33:42 +00:00
output . setTo ( this . start . x , this . start . y , this . end . x , this . end . y ) ;
2014-08-21 21:36:40 +00:00
}
return output ;
2014-01-29 00:21:28 +00:00
}
} ;
/ * *
* @ name Phaser . Line # length
* @ property { number } length - Gets the length of the line segment .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "length" , {
get : function ( ) {
return Math . sqrt ( ( this . end . x - this . start . x ) * ( this . end . x - this . start . x ) + ( this . end . y - this . start . y ) * ( this . end . y - this . start . y ) ) ;
}
} ) ;
/ * *
* @ name Phaser . Line # angle
* @ property { number } angle - Gets the angle of the line .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "angle" , {
get : function ( ) {
2014-04-15 00:14:31 +00:00
return Math . atan2 ( this . end . y - this . start . y , this . end . x - this . start . x ) ;
2014-01-29 00:21:28 +00:00
}
} ) ;
/ * *
* @ name Phaser . Line # slope
* @ property { number } slope - Gets the slope of the line ( y / x ) .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "slope" , {
get : function ( ) {
return ( this . end . y - this . start . y ) / ( this . end . x - this . start . x ) ;
}
} ) ;
/ * *
* @ name Phaser . Line # perpSlope
* @ property { number } perpSlope - Gets the perpendicular slope of the line ( x / y ) .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "perpSlope" , {
get : function ( ) {
return - ( ( this . end . x - this . start . x ) / ( this . end . y - this . start . y ) ) ;
}
} ) ;
2014-03-14 00:19:45 +00:00
/ * *
* @ name Phaser . Line # x
* @ property { number } x - Gets the x coordinate of the top left of the bounds around this line .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "x" , {
get : function ( ) {
return Math . min ( this . start . x , this . end . x ) ;
}
} ) ;
/ * *
* @ name Phaser . Line # y
* @ property { number } y - Gets the y coordinate of the top left of the bounds around this line .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "y" , {
get : function ( ) {
return Math . min ( this . start . y , this . end . y ) ;
}
} ) ;
/ * *
* @ name Phaser . Line # left
* @ property { number } left - Gets the left - most point of this line .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "left" , {
get : function ( ) {
return Math . min ( this . start . x , this . end . x ) ;
}
} ) ;
/ * *
* @ name Phaser . Line # right
* @ property { number } right - Gets the right - most point of this line .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "right" , {
get : function ( ) {
return Math . max ( this . start . x , this . end . x ) ;
}
} ) ;
/ * *
* @ name Phaser . Line # top
* @ property { number } top - Gets the top - most point of this line .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "top" , {
get : function ( ) {
return Math . min ( this . start . y , this . end . y ) ;
}
} ) ;
/ * *
* @ name Phaser . Line # bottom
* @ property { number } bottom - Gets the bottom - most point of this line .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "bottom" , {
get : function ( ) {
return Math . max ( this . start . y , this . end . y ) ;
}
} ) ;
/ * *
* @ name Phaser . Line # width
* @ property { number } width - Gets the width of this bounds of this line .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "width" , {
get : function ( ) {
return Math . abs ( this . start . x - this . end . x ) ;
}
} ) ;
/ * *
* @ name Phaser . Line # height
* @ property { number } height - Gets the height of this bounds of this line .
* @ readonly
* /
Object . defineProperty ( Phaser . Line . prototype , "height" , {
get : function ( ) {
return Math . abs ( this . start . y - this . end . y ) ;
}
} ) ;
2014-01-29 00:21:28 +00:00
/ * *
2014-01-29 17:10:13 +00:00
* Checks for intersection between two lines as defined by the given start and end points .
* If asSegment is true it will check for line segment intersection . If asSegment is false it will check for line intersection .
2014-01-29 00:21:28 +00:00
* Returns the intersection segment of AB and EF as a Point , or null if there is no intersection .
* Adapted from code by Keith Hair
*
2014-02-20 03:44:44 +00:00
* @ method Phaser . Line . intersectsPoints
2014-01-29 17:10:13 +00:00
* @ param { Phaser . Point } a - The start of the first Line to be checked .
* @ param { Phaser . Point } b - The end of the first line to be checked .
* @ param { Phaser . Point } e - The start of the second Line to be checked .
* @ param { Phaser . Point } f - The end of the second line to be checked .
2014-01-29 00:21:28 +00:00
* @ param { boolean } [ asSegment = true ] - If true it will check for segment intersection , otherwise full line intersection .
* @ param { Phaser . Point } [ result ] - A Point object to store the result in , if not given a new one will be created .
* @ return { Phaser . Point } The intersection segment of the two lines as a Point , or null if there is no intersection .
* /
2014-01-29 17:10:13 +00:00
Phaser . Line . intersectsPoints = function ( a , b , e , f , asSegment , result ) {
2014-01-29 00:21:28 +00:00
if ( typeof asSegment === 'undefined' ) { asSegment = true ; }
if ( typeof result === 'undefined' ) { result = new Phaser . Point ( ) ; }
2014-01-29 17:10:13 +00:00
var a1 = b . y - a . y ;
var a2 = f . y - e . y ;
var b1 = a . x - b . x ;
var b2 = e . x - f . x ;
var c1 = ( b . x * a . y ) - ( a . x * b . y ) ;
var c2 = ( f . x * e . y ) - ( e . x * f . y ) ;
2014-01-29 00:21:28 +00:00
var denom = ( a1 * b2 ) - ( a2 * b1 ) ;
if ( denom === 0 )
{
return null ;
}
2014-06-23 18:25:47 +00:00
result . x = ( ( b1 * c2 ) - ( b2 * c1 ) ) / denom ;
result . y = ( ( a2 * c1 ) - ( a1 * c2 ) ) / denom ;
2014-03-23 07:59:28 +00:00
2014-01-29 00:21:28 +00:00
if ( asSegment )
{
2014-06-23 20:59:47 +00:00
var uc = ( ( f . y - e . y ) * ( b . x - a . x ) - ( f . x - e . x ) * ( b . y - a . y ) ) ;
var ua = ( ( ( f . x - e . x ) * ( a . y - e . y ) ) - ( f . y - e . y ) * ( a . x - e . x ) ) / uc ;
var ub = ( ( ( b . x - a . x ) * ( a . y - e . y ) ) - ( ( b . y - a . y ) * ( a . x - e . x ) ) ) / uc ;
2014-06-23 18:25:47 +00:00
if ( ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1 ) {
return result ;
} else {
2014-01-29 00:21:28 +00:00
return null ;
}
}
return result ;
} ;
2014-01-29 17:10:13 +00:00
/ * *
* Checks for intersection between two lines .
* If asSegment is true it will check for segment intersection .
* If asSegment is false it will check for line intersection .
* Returns the intersection segment of AB and EF as a Point , or null if there is no intersection .
* Adapted from code by Keith Hair
*
* @ method Phaser . Line . intersects
* @ param { Phaser . Line } a - The first Line to be checked .
* @ param { Phaser . Line } b - The second Line to be checked .
* @ param { boolean } [ asSegment = true ] - If true it will check for segment intersection , otherwise full line intersection .
* @ param { Phaser . Point } [ result ] - A Point object to store the result in , if not given a new one will be created .
* @ return { Phaser . Point } The intersection segment of the two lines as a Point , or null if there is no intersection .
* /
Phaser . Line . intersects = function ( a , b , asSegment , result ) {
return Phaser . Line . intersectsPoints ( a . start , a . end , b . start , b . end , asSegment , result ) ;
} ;