у меня аналогичная ситуация. Однако, если взять пример из приложения (ball_motion_04_click for trial.fla) то след остается. при этом заметил, что в моем проекте в поле "One item in library" виден кружок, в то время как в приложенном примере такого кружка нет. Вопрос знатокам, что не так? |
Обнаружение коллизий
Математическое обнаружение коллизий
Несмотря на то, что мы рассказали все о hitTest и рассмотрели его преимущества и ограничения, мы еще очень далеки от нашей цели. hitTest является встроенным во Flash методом обнаружения коллизий, однако существуют несколько созданных вручную альтернативных способов, которые в определенных задачах могут быть гораздо мощнее.
Что мы на самом деле ищем при проверке на коллизию? Коллизия - это столкновение или соприкосновение двух объектов.
Пусть у нас есть объект в определенном месте. Если другой объект находится в том же самом месте, тогда между ними происходит коллизия. Предположим, имеется стена, расположение которой _x=500. Если координата _x другого объекта больше 500, то он должен быть в состоянии столкновения со стеной, так? Да, поскольку мы решили, что у стены бесконечная высота, так как мы не проверяем значение _y. Самое замечательное заключается в том, что нам даже не нужно создавать стену. Мы просто говорим, что она там есть, посредством указания значений ее позиции. Самый простой способ - установить константу в начале фильма, к примеру right=500 ;. Давайте рассмотрим этот случай и попробуем с ним поработать.
Живой шарик
- Откройте новый фильм. Находясь в нем, установите левую стенку, реализуя ее в функции init. Переименуйте слой по умолчанию actions и введите следующий код.
init(); function init () Х right = 500; left = 50; }
- Теперь нужно реализовать некоторую коллизию с участием стенок. Начнем с простого шарика. Нарисуйте шарик, преобразуйте его в фильм с именем ball и дайте его инстансу имя ball_mc.
- Далее нужно обеспечить движение шарика. До этого мы использовали термин speed. Здесь мы поступим несколько более точно с технической точки зрения и используем velocity. Velocity - это скорость в определенном направлении. Мы ограничим возможные направления правой и левой сторонами, поэтому нашей скоростью Velocity будет либо +speed, либо -speed. Мы назовем ее velX, в виде сокращения от "Velocity по оси x". Добавим нужный код в init.
init (); function init() { right = 500; left = 50; ball_mc. velX = 5; }
- Для функции реализации движения шарика используем управляющий элемент onEnterFrame. Присвоим функцию управления в секции init и после этого создадим функцию move. Добавьте следующий код в имеющуюся программу.
init (); function init() { right = 500; left = 50; ball_mc.velX = 5; ball_mc.onEnterFrame = move; } function move() { this._x += this.velX; }
Здесь берется скорость velocity и прибавляется к позиции _x. Так как velX = 5, эта функция прибавляет 5 к позиции _x шарика в каждом кадре. Запустив этот фильм, вы увидите, что шарик переместится вправо и исчезнет. Итак, сейчас мы займемся обнаружением столкновений с использованием стенки.
- Вспомните нашу прежнюю проверке коллизий с точкой: контур всегда больше той точки, в которой он находится. При проверке удара объекта о стенку нужно учитывать толщину объекта. Предположим, что шарик имеет диаметр 20 пикселей. Это означает, что край шарика находится в 10 пикселях от центра (если шарик имеет центральную точку регистрации). Мы можем принимать это в расчет при проверке позиции шарика относительно стенки. Код будет выглядеть примерно так.
if (this._x>right-(this._width/2)) { // then we have a hit }
Мы добавим этот код в функцию move сразу после того, как настроим позицию шарика.
Берем параметр _width фильма ball и делим его на два. Это даст расстояние от центра круга до его края (т.е. радиус). Имейте в виду, что это будет работать только в случае с объектами, у которых имеется центральная точка регистрации, и которые отцентрированы по оси x.
- Ударившись о стенку, шарик отскакивает. В нашем случае он двигается строго перпендикулярно к поверхности, поэтому после удара просто будет двигаться в обратном направлении. Другими словами, если до столкновения его скорость равна +5, после столкновения она будет равна -5. Вместо реализации скорости -5 мы просто будем умножать любую скорость на -1. Давайте добавим эту функциональность в наш код в функции move.
function move() { this._x += this.velX; if (this._x>right-(this._width/2)) { this.velX *= -1; } }
- Теперь можном немного изменить этот код, чтобы создать аналогичное выражение if для проверки столкновения между шариком и левой стенкой. Добавьте следующий новый код в функцию move.
if (this._x<left+(this._width/2)) { this.velX *= -1; }
- Вот весь код, который мы имеем на данный момент.
init(); function init() { right = 500; left = 50; ball_mc.velX = 5; ball_mc.onEnterFrame = move; } function move() { this._x += this.velX; if (this._x>right-(this._width/2)) { this.velX *= -1; } if (this._x<left+(this._width/2)) { this.velX *= -1; } }
- Вы можете нарисовать линии на позициях 50 и 500 по оси x, чтобы видеть, что именно происходит. Помните, что эти линии являются лишь графическими элементами, которые не взаимодействуют с кодом и действием в фильме. Проверка коллизий - процесс сугубо математический.
- Запустив фильм, вы увидите, что шарик скачет туда и обратно между двумя линиями. Если у вас достаточно хорошее зрение, вы заметите нечто довольно неприятное. Шарик на самом деле немного проникает в стену, прежде чем отскочить от нее.
Если вы не видите этого, уменьшите либо частоту кадров фильма, либо значение скорости. Когда вы бросаете мяч в направлении стены, он ведь не проникает в нее, а просто отскакивает! (Имеется в виду обычный человек, бросающий в стену обычный теннисный мячик, а не Арнольд Шварценеггер, кидающий железное ядро). Сейчас мы постараемся решить эту проблему.
- Мы видим, что при ударе о стенку шарик немного проникает внутрь стены. Это показано на рисунке выше. Вручную переместим шарик так, чтобы он лишь касался края стены. Внесите следующие изменения в функцию move (функция init остается прежней)
function move() { this._x += this.velX; if (this._x>right-(this._width/2)) { this.velX *= -1; this, x = right-(this, width/2); } if (this._x<left+(this._width/2)) { this.velX *= -1; this._x = left+(this._width/2); } }
- Если вы запустите фильм сейчас, шарик немного войдет в стенку, будет зарегистрировано столкновение, и шарик переместится к краю стенки. Но, так как Flash не обновляет экран, пока не выполнится весь код, мы на самом деле никогда не увидим, как шарик проникнет в стенку, а будем наблюдать лишь касание. Итак, одна из "странных" особенностей функционирования Flash была использована на наше же благо!
- Теперь я совершу "квантовый скачок" и добавлю в фильм совершенно новое измерение. Я продублирую строки, содержащие _x или velX с использованием _y и velY, а также добавлю новые переменные с именами top и bottom. Также _width будет заменено на _height. Нарисуйте еще две линии вверху и внизу рабочего места на позициях (x,50) и (x, 350) для отображения стенок. Следующий код не представляет проблем.
init(); function init() { right = 500; left = 50; top = 50; bottom = 350; ball_mc.velX = 5; ball_mc.velY = 5; ball_mc.onEnterFrame = move; } function move() { this._x += this.velX; this._y += this.velY; if (this._x>right-(this._width/2)) { this.velX *= -1; this._x = right-(this._width/2); } if (this._x<left+(this._width/2)) { this.velX *= -1; this._x = left+(this._width/2); } if (this._y>bottorn-(this._height/2)) { this.velY *= -1; this._y = bottom-(this._height/2); } if (this._y<top+(this._height/2)) { this.velY *= -1; this._y = top+(this._height/2); } }
Пример 7.1. - Запустите фильм. Теперь все это напоминает старый добрый пинг-понг, в который я играл еще ребенком. Ну, раз уж на то пошло, давайте доведем дело до конца.