directions.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. DIRECTIONS
  3. We have six Directions which we map in a spiral around a cube: front, up,
  4. right, down, left, and back. That's nice on its own but what's important
  5. is the relationships between faces. For example, What's to the left of the
  6. Front face? Well that depends on what the Front faace considers "up" to
  7. be. The Direction class handles these relationships and calculates clock-
  8. wise and anticlockwise relationships.
  9. -------------
  10. | |
  11. | 0 | opposite
  12. | |
  13. | getUp() |
  14. | |
  15. ------------- ------------- -------------
  16. | | | |
  17. | 3 | | 1 |
  18. | | | |
  19. | getLeft() | this | getRight() |
  20. | | | |
  21. ------------- ------------- -------------
  22. | |
  23. | 2 |
  24. | |
  25. | getDown() |
  26. | |
  27. -------------
  28. The following equalities demonstrate how Directions operate:
  29. FRONT.getOpposite() === BACK
  30. FRONT.getUp() === UP
  31. FRONT.getUp( LEFT ) === LEFT
  32. FRONT.getRight() === RIGHT
  33. FRONT.getRight( DOWN ) === LEFT
  34. FRONT.getClockwise() === RIGHT
  35. FRONT.getClockwise( RIGHT ) === DOWN
  36. RIGHT.getOpposite() === LEFT
  37. RIGHT.getUp() === UP
  38. RIGHT.getUp( FRONT ) === FRONT
  39. RIGHT.getRight() === BACK
  40. RIGHT.getRight( DOWN ) === FRONT
  41. RIGHT.getClockwise() === BACK
  42. RIGHT.getClockwise( FRONT ) === UP
  43. Keep in mind that a direction cannot use itself or its opposite as the
  44. normalized up vector when seeking a direction!
  45. RIGHT.getUp( RIGHT ) === null
  46. RIGHT.getUp( LEFT ) === null
  47. */
  48. export function Direction( id, name ){
  49. this.id = id
  50. this.name = name.toLowerCase()
  51. this.initial = name.substr( 0, 1 ).toUpperCase()
  52. this.neighbors = []
  53. this.opposite = null
  54. }
  55. Direction.prototype.setRelationships = function( up, right, down, left, opposite ){
  56. this.neighbors = [ up, right, down, left ]
  57. this.opposite = opposite
  58. }
  59. Direction.getNameById = function( id ){
  60. return [
  61. 'front',
  62. 'up',
  63. 'right',
  64. 'down',
  65. 'left',
  66. 'back'
  67. ][ id ]
  68. }
  69. Direction.getIdByName = function( name ){
  70. return {
  71. front: 0,
  72. up : 1,
  73. right: 2,
  74. down : 3,
  75. left : 4,
  76. back : 5
  77. }[ name ]
  78. }
  79. Direction.getDirectionById = function( id ){
  80. return [
  81. FRONT,
  82. UP,
  83. RIGHT,
  84. DOWN,
  85. LEFT,
  86. BACK
  87. ][ id ]
  88. }
  89. Direction.getDirectionByInitial = function( initial ){
  90. return {
  91. F: FRONT,
  92. U: UP,
  93. R: RIGHT,
  94. D: DOWN,
  95. L: LEFT,
  96. B: BACK
  97. }[ initial.toUpperCase() ]
  98. }
  99. Direction.getDirectionByName = function( name ){
  100. return {
  101. front: FRONT,
  102. up : UP,
  103. right: RIGHT,
  104. down : DOWN,
  105. left : LEFT,
  106. back : BACK
  107. }[ name.toLowerCase() ]
  108. }
  109. // If we're looking at a particular face
  110. // and we designate an adjacet side as up
  111. // then we can calculate what adjacent side would appear to be up
  112. // if we rotated clockwise or anticlockwise.
  113. Direction.prototype.getRotation = function( vector, from, steps ){
  114. if( from === undefined ) from = this.neighbors[ 0 ]
  115. if( from === this || from === this.opposite ) return null
  116. steps = steps === undefined ? 1 : steps.modulo( 4 )
  117. for( var i = 0; i < 5; i ++ ){
  118. if( this.neighbors[ i ] === from ) break
  119. }
  120. return this.neighbors[ i.add( steps * vector ).modulo( 4 )]
  121. }
  122. Direction.prototype.getClockwise = function( from, steps ){
  123. return this.getRotation( +1, from, steps )
  124. }
  125. Direction.prototype.getAnticlockwise = function( from, steps ){
  126. return this.getRotation( -1, from, steps )
  127. }
  128. // Similar to above,
  129. // if we're looking at a particular face
  130. // and we designate an adjacet side as up
  131. // we can state what sides appear to be to the up, right, down, and left
  132. // of this face.
  133. Direction.prototype.getDirection = function( direction, up ){
  134. return this.getRotation( 1, up, direction.id - 1 )
  135. }
  136. Direction.prototype.getUp = function( up ){
  137. return this.getDirection( UP, up )
  138. }
  139. Direction.prototype.getRight = function( up ){
  140. return this.getDirection( RIGHT, up )
  141. }
  142. Direction.prototype.getDown = function( up ){
  143. return this.getDirection( DOWN, up )
  144. }
  145. Direction.prototype.getLeft = function( up ){
  146. return this.getDirection( LEFT, up )
  147. }
  148. // An convenience method that mimics the verbiage
  149. // of the getRotation() and getDirection() methods.
  150. Direction.prototype.getOpposite = function(){
  151. return this.opposite
  152. }
  153. // Create facing directions as global constants this way we can access from
  154. // anywhere in any scope without big long variables names full of dots and
  155. // stuff. Sure, ES5 doesn't really have constants but the all-caps alerts you
  156. // to the fact that them thar variables ought not to be messed with.
  157. var
  158. FRONT = new Direction( 0, 'front' ),
  159. UP = new Direction( 1, 'up' ),
  160. RIGHT = new Direction( 2, 'right' ),
  161. DOWN = new Direction( 3, 'down' ),
  162. LEFT = new Direction( 4, 'left' ),
  163. BACK = new Direction( 5, 'back' )
  164. // Now that they all exist we can
  165. // establish their relationships to one another.
  166. FRONT.setRelationships( UP, RIGHT, DOWN, LEFT, BACK )
  167. UP.setRelationships( BACK, RIGHT, FRONT, LEFT, DOWN )
  168. RIGHT.setRelationships( UP, BACK, DOWN, FRONT, LEFT )
  169. DOWN.setRelationships( FRONT, RIGHT, BACK, LEFT, UP )
  170. LEFT.setRelationships( UP, FRONT, DOWN, BACK, RIGHT )
  171. BACK.setRelationships( UP, LEFT, DOWN, RIGHT, FRONT )