JavaScript:Библиотеки/p5.collide2D

Материал из Онлайн справочника
Перейти к навигации Перейти к поиску

Перевод: Максим Кузьмин (Cubewriter) Контакты:</br>* Skype: cubewriter</br>* E-mail: cubewriter@gmail.com</br>* Максим Кузьмин на freelance.ru
Проверка/Оформление/Редактирование: Мякишев Е.А.


Pixel Art Mini Meow Animated.gif Черновик


Содержание

p5.collide2D[1]

P5collide2d js 1.png

Это библиотека, позволяющая определять столкновения между 2D-объектами, созданными с помощью библиотеки p5.js.

Кроме того, библиотека p5.collide2D содержит несколько версий функций из книги «Определение столкновений» (англ. «Collision detection») Джеффри Томпсона. Его код был написан согласно лицензии CC BY-NC-SA 4.0, а это значит, что код этой библиотеки имеет такую же лицензию. О том, как добавить библиотеку в свой скетч p5.js, читайте тут.

Для корректной работы этой библиотеки необходимо, чтобы у функций rectMode() и ellipseMode() были заданы параметры по умолчанию: у первой – «CORNER», а у второй – «CENTER». Все функции p5.collide2D возвращают «true», если объекты столкнулись, и «false», если нет.

Скетчи-примеры

Функции

Вспомогательные функции

  • collideDebug()

Функции для определения столкновений

  • collidePointPoint()
  • collidePointCircle()
  • collidePointRect()
  • collidePointLine()
  • collideRectRect()
  • collideCircleCircle()
  • collideRectCircle()
  • collideLineLine()
  • collideLineCircle()
  • collideLineRect()
  • collidePointPoly()
  • collideCirclePoly()
  • collideRectPoly()
  • collideLinePoly()
  • collidePolyPoly()
  • collidePointTriangle()
  • collidePointArc()

Описание и примеры использования функций

collideDebug(debugMode, size, color)

Включает режим отладки столкновений. Рисует эллипс в точке экрана, где можно применить и рассчитать столкновение между объектами.

Применима для следующих функций:

  • collideLineCircle()
  • collideLineLine()
  • collideLineRect()
  • collideCirclePoly()
  • collideRectPoly()
  • collideLinePoly()
  • collidePolyPoly()
1 function setup() {
2   collideDebug(true);
3 }

collidePointPoint(x, y, x2, y2, [buffer])

Рассчитывает столкновение одной точки с другой. Опционально можно задать «буферную зону», расширяющую область столкновения.

 1 // Простой пример использования функции collidePointPoint()
 2 
 3 var hit = false;
 4 function draw() {
 5       background(255);
 6       ellipse(100,100,1,1);       // если используете вариант
 7                                   // с буферной зоной, 
 8                                   // поменяйте размер эллипса на 10х10 
 9       ellipse(mouseX,mouseY,1,1); // если используете вариант
10                                   // с буферной зоной,
11                                   // поменяйте размер эллипса на 10х10 
12 
13 	// простой вариант без буферной зоны:
14 	hit = collidePointPoint(100,100,mouseX,mouseY)
15 
16 	// вариант с буферной зоной размером 10х10 пикселей:
17 	//hit = collidePointPoint(100,100,mouseX,mouseY,10)
18 
19 	print("colliding? " + hit);
20        //  "столкновение? "
21 }

collidePointCircle(pointX, pointY, circleX, circleY, diameter)

Рассчитывает столкновение точки с эллипсом. Для корректной работы этой функции необходимо, чтобы в функции ellipseMode() был задан параметр «CENTER».

 1 var hit = false;
 2 function draw() {
 3 	background(255);
 4 	ellipse(200,200,100,100);
 5 	point(mouseX,mouseY);
 6 
 7 	hit = collidePointCircle(mouseX,mouseY,200,200,100)
 8 
 9 	print("colliding? " + hit);
10   //  "столкновение? "
11 
12 }

collidePointRect(pointX, pointY, x, y, width, height)

Рассчитывает столкновение между точкой и прямоугольником. Для корректной работы этой функции необходимо, чтобы в функции rectMode() был задан параметр «CORNER».

 1 var hit = false;
 2 function draw() {
 3   background(255);
 4 	rect(200,200,100,150);
 5 
 6 	hit = collidePointRect(mouseX,mouseY,200,200,100,150);
 7 
 8 	print("colliding? " + hit);
 9   	  //  "столкновение? "
10 
11 }

collidePointLine(pointX, pointY, x, y, x2, y2, [buffer])

Рассчитывает столкновение между точкой и линией. Опционально можно задать буферную зону, расширяющую область столкновения (по умолчанию в параметре «buffer» стоит «0.1»).

 1 var hit = false;
 2 function draw(){
 3   background(255);
 4 	line(200,300,100,150);
 5 	point(mouseX,mouseY);
 6 
 7   // используем опциональный параметр для буферной зоны 
 8   // и задаем ему значение «0.5»:
 9 	hit = collidePointLine(mouseX,mouseY,200,300,100,150, 0.5);
10 
11 	print("colliding? " + hit);
12   //  "столкновение? " 
13 }

collideCircleCircle(circleX, circleY,circleDiameter, circleX2, circleY2, circleDiameter2)

Рассчитывает столкновение между двумя эллипсами. Для корректной работы этой функции необходимо, чтобы в функции ellipseMode() был выставлен параметр «CENTER».

 1 var hit = false;
 2 function draw() {
 3 	background(255);
 4 	ellipse(200,200,100,100);
 5 	ellipse(mouseX,mouseY,150,150);
 6 
 7 	hit = collideCircleCircle(mouseX,mouseY,150,200,200,100)
 8 
 9 	print("colliding? " + hit);
10   //  "столкновение? "
11 
12 }

collideRectRect(x, y, width, height, x2, y2, width2, height2)

Рассчитывает столкновение между двумя прямоугольниками. Чтобы эта функция работала корректно, в функции rectMode() нужно задать параметр «CORNER».

 1 var hit = false;
 2 function draw() {
 3   background(255);
 4 	rect(200,200,100,150);
 5 	rect(mouseX,mouseY,50,75);
 6 
 7 	hit = collideRectRect(200,200,100,150,mouseX,mouseY,50,75);
 8 
 9 	print("colliding? " + hit);
10    	  //  "столкновение? " 
11 
12 }

collideRectCircle(x1, y1, width1, height1, cx, cy, diameter)

Рассчитывает столкновение между прямоугольником и эллипсом. Чтобы эта функция работала корректно, у функции rectMode() нужно задать режим «CORNER», а у ellipseMode() – «CENTER».

 1 var hit = false;
 2 function draw() {
 3   background(255);
 4 	rect(200,200,100,150);
 5 	ellipse(mouseX,mouseY,100,100);
 6 
 7 	hit = collideRectCircle(200,200,100,150,mouseX,mouseY,100);
 8 
 9 	print("colliding? " + hit);
10   //  "столкновение? "
11 }

collideLineLine(x1, y1, x2, y2, x3, y3, x4, y4, [calcIntersection])

Рассчитывает столкновение между двумя линиями. Принимает опциональный булев параметр «calcIntersection», включающий/выключающий расчет точки пересечения. Если задать в нем «true», то в случае пересечения функция вернет объект с XY-координатами пересечения, а если пересечения зафиксировано не будет, то эта функция с каждым новым кадром будет возвращать объект с XY-координатами со значением «false». Поддерживает отладку с помощью collideDebug().

 1 // простой пример использования функции collideLineLine()
 2 var hit = false;
 3 function draw(){
 4   background(255);
 5   line(200,300,100,150);
 6   line(mouseX,mouseY,350,50);
 7   hit = collideLineLine(200,300,100,150,mouseX,mouseY,350,50);
 8 
 9   print("colliding? " + hit);
10 // "столкновение? "
11 }


 1 // возвращает объект, содержащий XY-координаты места пересечения,
 2 // используя для этого опциональный параметр «calcIntersection»:
 3 var hit = false;
 4 function draw(){
 5   background(255);
 6   line(200,300,100,150);
 7   line(mouseX,mouseY,350,50);
 8 
 9   hit = collideLineLine(200,300,100,150,mouseX,mouseY,350,50,true);
10 
11   print("X-intersection:" + hit.x); 
12     //  "X-координата пересечения:"
13   print("Y-intersection:" + hit.y);
14     //  "Y-координата пересечения:"
15 }

collideLineCircle(x1, y1, x2, y2, cx, cy, diameter)

Рассчитывает столкновение точки и эллипса. Поддерживает отладку с помощью collideDebug().

 1 var hit = false;
 2 function draw(){
 3   background(255);
 4 	line(200,300,100,150);
 5 	ellipse(mouseX,mouseY,50,50);
 6 	hit = collideLineCircle(200,300,100,150,mouseX,mouseY,50);
 7 
 8 	print("colliding? " + hit);
 9        //  "столкновение? "
10 }

collideLineRect(x1, y1, x2, y2, rx, ry, rw, rh, [calcIntersection])

Рассчитывает столкновение между линией и прямоугольником. Принимает опциональный булев параметр «calcIntersection», включающий/выключающий расчет точек пересечения. Если задать в нем «true», то в случае пересечения функция вернет объект, содержащий объекты с XY-координатами пересечений с верхней, нижней, правой и левой сторонами прямоугольника. Если пересечения зафиксировано не будет, то эта функция с каждым новым кадром будет возвращать объект с XY-координатами со значением «false». Поддерживает отладку с помощью collideDebug().

 1 // простой пример использования функции collideLineRect()
 2 var hit = false;
 3 function draw() {
 4 	background(255);
 5 	rect(200,300,100,150);
 6 	line(mouseX,mouseY,350,50);
 7 
 8 	hit = collideLineRect(mouseX,mouseY,350,50,200,300,100,150);
 9 
10 	print("colliding? " + hit);
11    	  //  "столкновение? "
12 }


 1 // возвращает объект, содержащий XY-координаты 
 2 // пересечения со всеми четырьмя сторонами прямоугольника,
 3 // при помощи опционального булева параметра «calcIntersection»:
 4 var hit = false;
 5 function draw() {
 6 	background(255);
 7 	rect(200,300,100,150);
 8 	line(mouseX,mouseY,350,50);
 9 
10 	hit = collideLineRect(mouseX,mouseY,350,50,200,300,100,150,true);
11 
12   // возвращаем объект, содержащий объекты
13   // с XY-координатами пересечения линии
14   // с верхней, нижней, правой и левой сторонами прямоугольника:
15   print("bottomX: " + hit.bottom.x);
16     //  "X-координата пересечения с нижней стороной: "
17   print("bottomY: " + hit.bottom.y);
18     //  "Y-координата пересечения с нижней стороной: "
19   print("topX: " + hit.top.x);
20     //  "X-координата пересечения с верхней стороной: "
21   print("topY: " + hit.top.y);
22     //  "Y-координата пересечения с верхней стороной: "
23   print("leftX: " + hit.left.x);
24     //  "X-координата пересечения с левой стороной: "
25   print("leftY: " + hit.left.y);
26     //  "Y-координата пересечения с левой стороной: "
27   print("rightX: " + hit.right.x);
28     //  "X-координата пересечения с правой стороной: "
29   print("rightY: " + hit.right.y);
30     //  "Y-координата пересечения с правой стороной: "
31 }

collidePointPoly(pointX,pointY,vectorArray)

Рассчитывает столкновение точки с полигоном. В параметрах «pointX» и «pointY» задаются XY-координаты расположения точки. В параметре «vectorArray» задается массив объектов p5.Vector, содержащих XY-координаты вершин полигона. Эта функция работает с многосторонними полигонами, а также с «вогнутыми» полигонами (полигонами, чьи стороны пересекаются друг с другом).

 1 var hit = false;
 2 var poly = []; // массив для хранения вершин полигона 
 3 function setup() {
 4 	createCanvas(500,500);
 5 	poly[0] = createVector(123,231);     // задаем XY-позиции
 6 	poly[1] = createVector(10,111);      // вершин полигона
 7 	poly[2] = createVector(20,23);
 8 	poly[3] = createVector(390,33);
 9 }
10 
11 function draw() {
12 	background(255);
13 
14   // рисуем полигон на основе заданных выше вершин:
15 	beginShape();
16 	for(i=0; i < poly.length; i++){
17 		vertex(poly[i].x,poly[i].y);
18 	}
19 	endShape(CLOSE);
20 
21 	ellipse(mouseX,mouseY,10,10); // рисуем маленький эллипс
22                               // в месте курсора мыши
23 
24 // третий параметр – это массив вершин: 
25 	hit = collidePointPoly(mouseX,mouseY,poly);
26 
27 	print("colliding? " + hit);
28   //  "столкновение? "
29 }

collideCirclePoly(x,y,diameter,vectorArray, [interiorCollision])

Рассчитывает столкновение эллипса и полигона. В параметрах «x», «y» и «diameter» задаются XY-координаты и диаметр эллипса, а в параметре «vectorArray» – массив объектов p5.Vector с XY-координатами вершин полигона. Эта функция работает с многосторонними полигонами, а также с «вогнутыми» полигонами (полигонами, чьи стороны пересекаются друг с другом). Также принимает опциональный пятый булев параметр «interiorCollision», включающий/выключающий определение столкновений, если эллипс полностью находится внутри полигона. По умолчанию эта функция выключена, чтобы не рассчитывать столкновение эллипса с краями полигона по два раза (и тем самым сэкономить вычислительные ресурсы). Поддерживает отладку с помощью функции collideDebug().

 1 var hit = false;
 2 var poly = [];
 3 function setup() {
 4 	createCanvas(windowWidth,windowHeight);
 5 	collideDebug(true)
 6 	poly[0] = createVector(123,231);  // задаем XY-координаты 
 7 	poly[1] = createVector(10,111);   // вершин полигона
 8 	poly[2] = createVector(20,23);
 9 	poly[3] = createVector(390,33);
10 }
11 
12 function draw() {
13 	background(255);
14 
15   // рисуем полигон на основе заданных выше вершин:
16 	beginShape();
17 	for(i=0; i < poly.length; i++){
18 		vertex(poly[i].x,poly[i].y);
19 	}
20 	endShape(CLOSE);
21 
22 	ellipse(mouseX,mouseY,45,45);
23 
24 	hit = collideCirclePoly(mouseX,mouseY,45,poly);
25 
26 	// используйте этот вариант, если нужно рассчитать
27 // столкновение эллипса, находящегося внутри полигона:
28 	// hit = collideCirclePoly(mouseX,mouseY,45,poly,true);
29 
30 	print("colliding? " + hit);
31   //  "столкновение? "
32 }

collideRectPoly(x,y,width,height,vectorArray, [interiorCollision])

Рассчитывает столкновение прямоугольника с полигоном. В параметрах «x», «y», «width» и «height» задаются XY-координаты, ширина и высота прямоугольника. В параметре «vectorArray» – массив объектов p5.Vector, содержащих XY-координаты вершин полигона. Эта функция работает с многосторонними полигонами, а также с «вогнутыми» полигонами (полигонами, чьи стороны пересекаются друг с другом). Также принимает опциональный шестой булев параметр «interiorCollision», включающий/выключающий определение столкновений, если прямоугольник полностью находится внутри полигона. По умолчанию эта функция выключена, чтобы не рассчитывать столкновения с одними и теми же краями по два раза (и тем самым сэкономить вычислительные ресурсы). Поддерживает отладку при помощи collideDebug().

 1 var hit = false;
 2 var poly = [];
 3 function setup() {
 4 	createCanvas(windowWidth,windowHeight);
 5 	collideDebug(true)
 6 	poly[0] = createVector(323,431);     // задаем XY-координаты 
 7 	poly[1] = createVector(210,311);     // вершин полигона
 8 	poly[2] = createVector(220,223);
 9 	poly[3] = createVector(590,233);
10 }
11 
12 function draw() {
13 	background(255);
14 	push()
15 	beginShape();
16 	// рисуем полигон на основе заданных выше вершин:
17 	for(i=0; i < poly.length; i++){
18 		vertex(poly[i].x,poly[i].y);
19 	}
20 	endShape(CLOSE);
21 
22 	rect(mouseX,mouseY,45,100);
23 
24 	hit = collideRectPoly(mouseX,mouseY,45,100,poly);
25 	
26      // используйте этот вариант, если прямоугольник
27      // находится полностью внутри полигона:
28 	// hit = collideRectPoly(mouseX,mouseY,45,100,poly,true);
29 
30 	print("colliding? " + hit);
31       "столкновение? "
32 }

collideLinePoly(x1, y1, x2, y2, vertices)

Рассчитывает столкновение линии с полигоном. В параметрах «x1», «y1», «x2» и «y2» задаются координаты линии, а в параметре «vertices» – массив объектов p5.Vector с XY-координатами вершин полигона. Эта функция работает с многосторонними полигонами, а также с «вогнутыми» полигонами (полигонами, чьи стороны пересекаются друг с другом). Поддерживает отладку с помощью функции collideDebug().

 1 var hit = false;
 2 var poly = new Array(16);;
 3 function setup() {
 4 	createCanvas(windowWidth,windowHeight);
 5 	collideDebug(true)
 6 
 7 	// создаем 16-сторонний полигон:
 8   var angle = TWO_PI / poly.length;
 9   for (var i=0; i<poly.length; i++) {
10     var a = angle * i;
11     var x = 300 + cos(a) * 100;
12     var y = 200 + sin(a) * 100;
13     poly[i] = createVector(x,y);
14   }
15 }
16 function draw() {
17 	background(255);
18 	beginShape();
19 	// рисуем полигон на основе заданных выше вершин:
20 	for(i=0; i < poly.length; i++){
21 		vertex(poly[i].x,poly[i].y);
22 	}
23 	endShape(CLOSE);
24 
25 	line(10,10,mouseX,mouseY);
26 
27 	hit = collideLinePoly(mouseX,mouseY,45,100,poly);
28 
29 	print("colliding? " + hit);
30   //  "столкновение? "
31 }

collidePolyPoly(polygon1, polygon2, [interiorCollision])

Рассчитывает столкновение между двумя полигонами. В параметрах «polygon1» и «polygon2» задаются массивы объектов p5.Vector с XY-координатами вершин двух этих полигонов. Эта функция работает с многосторонними полигонами, а также с «вогнутыми» полигонами (полигонами, чьи стороны пересекаются друг с другом). Также принимает опциональный третий булев параметр «interiorCollision», включающий/выключающий определение столкновений, если один полигон полностью находится внутри другого полигона. По умолчанию эта функция выключена, чтобы не рассчитывать по два раза столкновение с одними и теми же сторонами (и тем самым сэкономить вычислительные ресурсы). Поддерживает отладку с помощью функции collideDebug().

 1 // этот скетч-пример – адаптация кода Джеффри Томпсона
 2 
 3 var hit = false;
 4 var poly = new Array(8);
 5 var randomPoly = []
 6 function setup() {
 7 	createCanvas(windowWidth,windowHeight);
 8 	collideDebug(true) // включаем режим отладки
 9 
10 	// создаем полигон с одинаковыми сторонами:
11   var angle = TWO_PI / poly.length;
12   for (var i=0; i<poly.length; i++) {
13     var a = angle * i;
14     var x = 300 + cos(a) * 100;
15     var y = 200 + sin(a) * 100;
16     poly[i] = createVector(x,y);
17   }
18 
19   // создаем полигон со сторонами случайного размера:
20   var a = 0;
21   var i = 0;
22   while (a < 360) {
23     var x = cos(radians(a)) * random(30,50);
24     var y = sin(radians(a)) * random(30,50);
25     randomPoly[i] = createVector(x,y);
26     a += random(15, 40);
27     i += 1;
28   }
29 }
30 function draw() {
31 	background(255);
32  // привязываем позицию полигона 
33  // со сторонами случайного размера
34  // к позиции мышки: 
35   var mouse = createVector(mouseX, mouseY);
36   var diff = mouse.sub(randomPoly[0]);
37 
38   for (i=0; i < randomPoly.length; i++) {
39     randomPoly[i].add(diff);
40   }
41 
42 	beginShape();
43 	// рисуем полигон на основе заданных выше вершин:
44 	for(i=0; i < poly.length; i++){
45 		vertex(poly[i].x,poly[i].y);
46 	}
47 	endShape(CLOSE);
48 	beginShape();
49 	for(i=0; i < randomPoly.length; i++){
50 		vertex(randomPoly[i].x,randomPoly[i].y);
51 	}
52 	endShape(CLOSE);
53 
54 	hit = collidePolyPoly(poly,randomPoly,true);
55 	print("colliding? " + hit);
56    	  //  "столкновение? "
57 
58 }

collidePointTriangle(px, py, x1, y1, x2, y2, x3, y3)

Рассчитывает столкновение точки и треугольника. Для этого также можно использовать collidePointPoly(), но эта функция более эффективна.

 1 var hit = false;
 2 function draw() {
 3 	background(255);
 4 	triangle(300,200,350,300,250,300)
 5 	ellipse(mouseX,mouseY,10,10);
 6 
 7 	hit = collidePointTriangle(mouseX,mouseY, 300,200,350,300,250,300)
 8 	print("colliding? " + hit)
 9   //  "столкновение? "
10 }

Функции для столкновения с треугольником

Расчет столкновения нужной фигуры (будь то эллипс, прямоугольник, линия или другой треугольник) с треугольником осуществляется при помощи функции для расчета столкновения этой фигуры с полигоном. Соответственно, в качестве полигона должен быть задан трехсторонний полигон (то есть, по сути, треугольник).

Примечание: Вершины треугольного полигона задаются с помощью трех объектов p5.Vector (см. пример ниже).

  • collideCirclePoly() – для расчета столкновения эллипса с треугольником
  • collideRectPoly() – для расчета столкновения прямоугольника с треугольником
  • collideLinePoly() – для расчета столкновения линии с треугольником
  • collidePolyPoly() – для расчета столкновения треугольника с треугольником
 1 var hit = false;
 2 var triPoly = []
 3 function setup() {
 4 	createCanvas(windowWidth,windowHeight);
 5 	collideDebug(true)
 6 
 7 	triPoly[0] = createVector(300,200);
 8 	triPoly[1] = createVector(350,300);
 9 	triPoly[2] = createVector(250,300);
10 }
11 
12 function draw() {
13 	background(255);
14 
15   // мы можем нарисовать этот треугольник
16   // с помощью beginShape() и endShape() 
17   // и итерирования через массив «triPoly», но так – проще:
18 	triangle(300,200,350,300,250,300)
19 	ellipse(mouseX,mouseY,45,45);
20 
21 	hit = collideCirclePoly(mouseX,mouseY,45, triPoly)
22 
23 	print("colliding? " + hit)
24   //  "столкновение "
25 }

collidePointArc(pointX, pointY, arcCenterX, arcCenterY, arcRadius, arcRotationAngle, arcAngle, [buffer])

Рассчитывает столкновение точки с аркой.

P5.collide2D collidePointArc 1.png
 1 var ARC_RADIUS = 100;
 2 var ARC_ANGLE = Math.PI/3;
 3 var ROTATION_ANGLE = -Math.PI / 4;
 4 var hit = false;
 5 function draw() {
 6 	background(220);
 7 	push();
 8 	// перемещаемся к центру холста:
 9 	translate(width / 2, height / 2);
10 	// вращаем под некоторым углом:
11 	rotate(ROTATION_ANGLE);
12 	fill(color(180, 220, 210));
13 	stroke(10);
14 	arc(0, 0, 2 * ARC_RADIUS, 2 * ARC_RADIUS, -ARC_ANGLE/2, ARC_ANGLE/2, PIE);
15 	pop();
16 	point(mouseX, mouseY);
17 	hit = collidePointArc(mouseX, mouseY, width / 2, height / 2, ARC_RADIUS, ROTATION_ANGLE, ARC_ANGLE);
18 
19 	print("colliding? " + hit);
20    	  //  "столкновение? " 
21 }

См.также

Внешние ссылки