Guest User

Untitled

a guest
Aug 19th, 2019
83
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 'use strict';
  2.  
  3.  
  4. const minMaxProjection = (axis, object) => {
  5. let minPr, maxPr;
  6. minPr = maxPr = object.vertices[0].vectorProjection(axis);
  7. for (let i = 1; i < 4; i++) {
  8. let projection = object.vertices[i].vectorProjection(axis);
  9. if (projection > maxPr) {
  10. maxPr = projection;
  11. } else if (projection < minPr) {
  12. minPr = projection;
  13. }
  14. }
  15. return {
  16. min: minPr,
  17. max: maxPr
  18. };
  19. };
  20.  
  21. const overlap = (pr1, pr2) => {
  22. let max, min;
  23.  
  24. if (pr1.max < pr2.max) {
  25. max = pr1.max;
  26. min = pr2.min;
  27. } else {
  28. max = pr2.max;
  29. min = pr1.min;
  30. }
  31. return min - max;
  32. };
  33.  
  34. const AABBvsCircle=(object,obstacle)=> {
  35. let axis = obstacle.centre.sub(object.centre, new Vector2d());
  36. let thisProjection = minMaxProjection(axis, object);
  37.  
  38. let centreProjection = obstacle.centre.vectorProjection(axis);
  39.  
  40. let struct = {
  41. min: centreProjection - obstacle.radius,
  42. max: centreProjection + obstacle.radius
  43. };
  44.  
  45. let depth;
  46.  
  47. if ((depth = overlap(thisProjection, struct)) < 0) {
  48. return new Collision(axis.normalize().mul(depth), obstacle);
  49. }
  50. return null
  51. }
  52.  
  53. const getCollision=(objectCommon,obstacleCommon)=>{
  54. let object,obstacle
  55.  
  56. if (objectCommon instanceof Hitbox ){
  57. object=objectCommon.hitbox
  58. }else if (objectCommon instanceof AABB || CircleHitbox){
  59. object=objectCommon
  60. }
  61.  
  62. if (obstacleCommon instanceof Hitbox ){
  63. obstacle=obstacleCommon.hitbox
  64. }else if (obstacleCommon instanceof AABB || CircleHitbox){
  65. obstacle=obstacleCommon
  66. }
  67.  
  68. if (object instanceof AABB) {
  69. if (obstacle instanceof AABB) {
  70. return object.getCollision(obstacle)
  71. }else if (obstacle instanceof CircleHitbox){
  72. return AABBvsCircle(object,obstacle)
  73. }
  74. }else if (object instanceof CircleHitbox){
  75. if (obstacle instanceof AABB){
  76. let collision=AABBvsCircle(obstacle,object)
  77. if (collision){
  78. collision.distance.mul(-1)
  79. collision.obstacle=obstacle
  80. }
  81. return collision
  82. }else if (obstacle instanceof CircleHitbox){
  83. return object.getCollision(obstacle)
  84. }
  85. }
  86. return null
  87. }
  88.  
  89. class AABB {
  90. constructor(centre,vertices,id=Game.getUniqId()){
  91. this.centre=centre;
  92. this.vertices=vertices;
  93. let firstSide=this.vertices[1].sub(this.vertices[0],new Vector2d());
  94. let secondSide=this.vertices[2].sub(this.vertices[1],new Vector2d());
  95. this.firstAxis=firstSide.normal();
  96. this.secondAxis=secondSide.normal();
  97. this.id=id;
  98. }
  99.  
  100. getCollision(obstacle) {
  101. let thisPr1 = minMaxProjection(this.firstAxis, this);
  102. let thisPr2 = minMaxProjection(this.secondAxis, this);
  103. let objPr1 = minMaxProjection(this.firstAxis, obstacle);
  104. let objPr2 = minMaxProjection(this.secondAxis, obstacle);
  105.  
  106. let secThisPr1 = minMaxProjection(obstacle.firstAxis, this);
  107. let secThisPr2 = minMaxProjection(obstacle.secondAxis, this);
  108. let secObjPr1 = minMaxProjection(obstacle.firstAxis, obstacle);
  109. let secObjPr2 = minMaxProjection(obstacle.secondAxis, obstacle);
  110.  
  111. let dx, dy, dX, dY;
  112.  
  113. if ((dx = overlap(thisPr1, objPr1)) < 0 && (dy = overlap(thisPr2, objPr2)) < 0
  114. && (dX = overlap(secThisPr1, secObjPr1)) < 0 && (dY = overlap(secThisPr2, secObjPr2)) < 0) {
  115.  
  116. const getMin = (dx, dy, firstAxis, secondAxis) => {
  117. let depth, axis;
  118. if (dx < dy) {
  119. depth = dy;
  120. axis = new Vector2d(secondAxis);
  121. } else {
  122. depth = dx;
  123. axis = new Vector2d(firstAxis);
  124. }
  125. return {
  126. depth: depth,
  127. axis: axis
  128. };
  129. };
  130.  
  131. let thisMin = getMin(dx, dy, this.firstAxis, this.secondAxis);
  132. let objMin = getMin(dX, dY, obstacle.firstAxis, obstacle.secondAxis);
  133. let res = getMin(thisMin.depth, objMin.depth, thisMin.axis, objMin.axis);
  134.  
  135. let centre_to_centre = obstacle.centre.sub(this.centre, new Vector2d());
  136.  
  137. if (centre_to_centre.vectorProjection(res.axis) < 0) res.axis.mul(-1);
  138.  
  139. return new Collision(res.axis.normalize().mul(res.depth), obstacle);
  140. }
  141. return null
  142. }
  143.  
  144. changePosition(newCentre){
  145. let delta=newCentre.sub(this.centre,new Vector2d());
  146. this.centre.set(newCentre);
  147. for (let vertex of this.vertices){
  148. vertex.add(delta);
  149. }
  150. }
  151.  
  152. correctPosition(collision){
  153. this.changePosition(this.centre.add(collision.distance,new Vector2d()));
  154. }
  155.  
  156. getMinMax(x_or_y){
  157. let min,max;
  158. min=max=this.vertices[0][x_or_y];
  159. for (let i=1;i<4;i++){
  160. if (this.vertices[i][x_or_y]>max){
  161. max=this.vertices[i][x_or_y]
  162. }
  163. if (this.vertices[i][x_or_y]<min){
  164. min=this.vertices[i][x_or_y];
  165. }
  166. }
  167. return {
  168. max:max,
  169. min:min
  170. }
  171. }
  172.  
  173. /**
  174. * @param {AABB} object
  175. * @return {boolean}
  176. */
  177. equals(object){
  178. return object instanceof AABB && this.id===object.id;
  179. }
  180.  
  181. setId(id){
  182. this.id=id;
  183. return this;
  184. }
  185. }
  186.  
  187. class CircleHitbox {
  188. constructor(centre,radius,id=Game.getUniqId()){
  189. this.radius=radius;
  190. this.centre=centre;
  191. this.id=id;
  192. }
  193.  
  194. getCollision(obstacle) {
  195. let axis = this.centre.sub(obstacle.centre, new Vector2d());
  196. let dist = axis.length();
  197. if (this.radius + obstacle.radius > dist) {
  198. return new Collision(axis.normalize().mul(obstacle.radius + this.radius - dist), obstacle);
  199. }
  200. return null;
  201. }
  202.  
  203. changePosition(newCentre){
  204. this.centre.set(newCentre);
  205. }
  206. correctPosition(collision){
  207. this.changePosition(this.centre.add(collision.distance,new Vector2d()));
  208. }
  209.  
  210. getMinMax(x_or_y){
  211. return {
  212. max:this.centre[x_or_y]+this.radius,
  213. min:this.centre[x_or_y]-this.radius
  214. }
  215. }
  216.  
  217. /**
  218. * @param {CircleHitbox} object
  219. * @return {boolean}
  220. */
  221. equals(object){
  222. return object instanceof CircleHitbox
  223. && this.id===object.id;
  224. }
  225.  
  226. setId(id){
  227. this.id=id;
  228. return this;
  229. }
  230. }
  231.  
  232. class Collision{
  233. constructor(dist,obstacle){
  234. this.distance=dist
  235. this.obstacle=obstacle
  236. }
  237. }
RAW Paste Data