Обнаружение столкновения — это ветвь алгоритмов, которая проверяет, перекрываются ли две фигуры. Если вы строите физические или экшн-игры с помощью ActionScript, вы наверняка не избежите знакомства с этой темой. Это первый из серии, касающейся обнаружения столкновений. В этом кратком совете мы рассмотрим встроенный в ActionScript метод обнаружения столкновений hitTestObject() и напишем собственный для обнаружения перекрытия между двумя кругами.
Окончательный результат предварительного просмотра
Это последний SWF, который мы создадим в этом кратком совете. Нажмите на синий круг и перетащите его к зеленому. Как только они перекрываются, зеленый круг изменит свой цвет; если вы снова удалите синий круг, другой снова станет зеленым.
Шаг 1: Проверки ограничивающего прямоугольника
Те, кто знаком с ActionScript 2.0, обязательно узнают метод hitTest() . Эта команда проверяет перекрытие между двумя фигурами или между фигурой и одной точкой. В ActionScript 3.0 он разделен на два отдельных метода: hitTestObject() и hitTestPoint() .
hitTestObject() мы рассмотрим hitTestObject() . Этот comnad обычно подходит для обнаружения столкновений для коробчатых форм (квадраты, прямоугольники). Ограничительная рамка рисуется вокруг фигур, и когда эти ограничивающие hitTestObject() перекрывают друг друга, hitTestObject() возвращает true.
Проверьте пример ниже. Перетащите синюю коробку к зеленой. Когда они перекрываются, оттенок зеленой коробки темнеет.
Я прилагаю здесь соответствующий ActionScript, который генерирует вышеуказанное представление. Box — это пользовательский класс, который легко генерирует квадратные формы. Я включил классы в исходную папку; обращайтесь к ним. Важный скрипт для обнаружения столкновений выделен ниже.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.MouseEvent;
/**
* Simple hitTest with boxes
* @author Shiu
*/
[SWF(width = 400, height = 300)]
public class Simple extends Sprite
{
private var box1:Box, box2:Box;
public function Simple() {
box1 = new Box(0x0000FF);
box1.x = 250;
box1.addEventListener(MouseEvent.MOUSE_DOWN, start);
box1.addEventListener(MouseEvent.MOUSE_UP, end);
box2 = new Box(0x00FF00);
box2.x = 100;
}
private function start(e:MouseEvent):void {
e.target.startDrag();
e.target.addEventListener(MouseEvent.MOUSE_MOVE, check);
}
private function end(e:MouseEvent):void {
e.target.stopDrag();
e.target.removeEventListener(MouseEvent.MOUSE_MOVE, check);
}
private function check(e:MouseEvent):void {
if (e.target.hitTestObject(box2)) box2.color = 0x00AA00;
else box2.color = 0x00FF00;
}
}
}
|
Шаг 2: Недостатки ограничивающих рамок
Однако столкновение между кругами не может быть эффективно проверено с помощью этой команды. Проверьте презентацию ниже. Перетащите синий круг к зеленому. До столкновения фигур их ограничивающие hitTestObject() уже перекрываются, и hitTestObject() имеет значение true. Нам нужно более точное решение.
Эта проблема распространена не только для обнаружения столкновений между кругами, но и вообще не квадратными формами. Соблюдайте схему ниже. Для органических форм, которые трудно разрешить с помощью полигонов, мы будем использовать детектирование столкновений с точностью до пикселя.

Различные неточные столкновения обнаружены через hitTestObject.
Шаг 3: Расстояние между центрами
Решение этой проблемы довольно простое: мы будем измерять расстояние между центрами этих окружностей. Если центры окажутся достаточно близко друг к другу, мы отметим столкновение как истинное. Но как близко достаточно близко?

Расстояние между кругами.
Соблюдайте диаграмму выше. r 1 относится к радиусу круга 1, а r 2 относится к радиусу круга 2. Расстояние между кругами рассчитывается для каждого кадра. Если (и только если) он равен или меньше суммы обоих радиусов (r 1 + r 2 ), то эти два круга должны касаться или перекрывать друг друга.
Шаг 4: Обнаружение столкновения круг-круг
Вот важный ActionScript для реализации концепции выше:
|
1
|
minDist = circle1.radius + circle2.radius;
|
|
1
2
3
4
5
|
private function check(e:MouseEvent):void {
var distance:Number = Math2.Pythagoras(circle1.x, circle1.y, circle2.x, circle2.y);
if (distance <= minDist) circle2.color = 0x00FFAA;
else circle2.color = 0x00FF00;
}
|
Шаг 5: Пример решения
Вот образец решения. Перетащите синий круг к зеленому. Когда они перекрываются, вы увидите изменение зеленого цвета. Он возвращается к нормальному состоянию, когда оба круга не сталкиваются.
Я включил реализацию ActionScript ниже.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
/**
* Simple collision between 2 circles
* @author Shiu
*/
[SWF(width = 400, height = 300)]
public class Simple3 extends Sprite
{
private var circle1:Circle, circle2:Circle;
private var minDist:Number;
public function Simple3() {
circle1 = new Circle(0x0055AA, 30);
circle1.x = 250;
circle1.addEventListener(MouseEvent.MOUSE_DOWN, start);
circle1.addEventListener(MouseEvent.MOUSE_UP, end);
circle2 = new Circle(0x00FF00, 30);
circle2.x = 100;
minDist = circle1.radius + circle2.radius;
}
private function start(e:MouseEvent):void {
e.target.startDrag();
e.target.addEventListener(MouseEvent.MOUSE_MOVE, check);
}
private function end(e:MouseEvent):void {
e.target.stopDrag();
e.target.removeEventListener(MouseEvent.MOUSE_MOVE, check);
}
private function check(e:MouseEvent):void {
var distance:Number = Math2.Pythagoras(circle1.x, circle1.y, circle2.x, circle2.y);
if (distance <= minDist) circle2.color = 0x00FFAA;
else circle2.color = 0x00FF00;
}
}
}
|
Вывод
Как видите, общий принцип обнаружения столкновений заключается в использовании математических формул для проверки перекрытий между различными формами. Векторная математика также играет важную роль. Далее следует столкновение между кругом и линией. Спасибо за чтение и до скорой встречи.