Опубликован: 07.11.2006 | Доступ: свободный | Студентов: 3398 / 338 | Оценка: 3.94 / 3.71 | Длительность: 37:11:00
Лекция 8:

Обнаружение коллизий

Поддержка множества объектов в массиве

Вместо поддержки объектов самих по себе, которую мы использовали до сих пор, лучше поддерживать их на главной временной диаграмме. Самый удобный способ осуществить это - использовать массив. При создании каждого объекта мы добавляем его в массив, и тогда все наши объекты будут находиться в одном массиве для простоты доступа и управления.

  1. Используйте фильм из последнего упражнения с фильмом ball в Library и сохраните его под другим именем. Удалите все инстансы с рабочего места, а также весь имеющийся код. Начните с добавления в кадр 1 слоя actions этого кода.
    init();
      function init() {
        max = 10;
        balls_array = new Array();
        for (n=0; n<max; n++) {
          balls_array[n] = attachMovie("ball", "b"+n, n) ;
          balls_array[n]._x = Math.random 0*550;
          balls_array[n]._y = Math.random()*400;
          balls_array[n].velX = Math.random()*10-5;
          balls_array[n].velY = Math.random()*10-5;
          balls_array[n]._xscale = balls_array[n]._yscale = 
             Math.random()*50+30;
        }
      }

    Здесь мы установили значение max, которое будет определять число создаваемых шариков. Затем создается массив для хранения в нем фильмов. Цикл для присвоения фильмов практически идентичен предыдущему файлу, за исключением того, что он присваивает фильм элементу массива и осуществляет доступ к нему через этот элемент для присвоения параметров. Мы также опустили управляющий элемент onEnterFrame, так как управление фильмами будет осуществляться извне.

  2. Вместо этого, мы добавим функцию onEnterFrame в _root. Сначала реализуем присвоение в функции init (под строкой max = 10; ):
    _root.onEnterFrame = main;
  3. Теперь мы можем определить функцию main, в которой и будет заключаться весь смысл. Сначала обрабатываем циклом массив для передвижения каждого шарика по отдельности. Здесь все довольно просто.
    function main() {
        for (i=0; i<balls_array.length; i++) {
          balls_array[i] ._x += balls_array[i] .velX;
          balls_array[i] ._y += balls_array[i] .velY;
          if (balls[i]_array._x>550) {
            balls[i]_array._x = 0;
          }
          if (balls[i]_array._x<0) {
            balls[i]_array._x = 550;
          }
          if (balls[i]_array._y>400) {
            balls[i]_array._y = 0;
          }
          if (balls[i]_array._y<0) {
            balls[i]_array._y = 400;
          }
        }
      }

    Выглядит знакомо? Так и должно быть. Это тот же самый код, что и ранее, однако здесь мы осуществляем доступ к фильму извне через элемент массива, в котором он сохранен, вместо внутреннего доступа с использованием this. Запуститe фильм. Вы увидите десять кругов, в случайном порядке двигающихся по экрану. Теперь перейдем к обнаружению столкновений:

  4. В этом шаге мы будем использовать цикл for. Внешний цикл будет обрабатывать каждый элемент массива (содержащий ссылку на фильм), а внутренний цикл будет использоваться для проверки этого элемента относительно каждого последующего элемента в массиве. Приведем псевдокод, чтобы показать, как это реализуется.
    for (i=0; i<balls_array, length-1; i++) {
        for (j=i+l; j<balls_array. length; j++) {
          // test between balls_array[i] and balls_array[j] here
        }
      }

    Это еще одна ваша шпаргалка. Мы будем использовать код проверки коллизий на основе окружностей/расстояния для проверки столкновения шариков. В случае столкновения оба шарика будут удаляться.

  5. Чтобы удалить шарики, нам нужно будет удалить не только фильм, но также его ссылку в массиве. Мы реализуем это с помощью метода array.splice (index, number). Эта команда удаляет число number элементов из массива, начиная с index. Измените функцию main следующим образом.
    function main() {
        for (i=0; i<balls_array.length; i++) {
          balls_array[i]._x += balls_array[i].velX;
          balls_array[i]._y += balls_array[i].velY;
          if (balls_array[i]._x>550) {
            balls_array[i]._x = 0;
          }
          if (balls_array[i]._x<0) {
            balls_array[i]._x = 550;
          }
          if (balls_array[i]._y>400) {
            balls_array[i]._y = 0;
          }
          if (balls_array[i]._y<0) {
            balls_array[i]._y = 400;
          }
        }
        for (i=0; i<balls_array.length-1; i++) {
          for (j=i+1; j<balls_array.length; j++) {
            dx = balls_array[i]._x-balls_array[j]._x;
            dy = balls_array[i]._y-balls_array[j]._y;
            dist = Math.sqrt(dx*dx+dy*dy);
            if (dist<balls_array[i]._width/2+ balls_array [j]._width/2) {
              removeMovieClip(balls_array[j]);
              balls_array.splice(j, 1);
              removeMovieClip(balls_array[i]);
              balls_array. splice(i, 1);
            }
          }
        }
      }
    Пример 7.5.
  6. В конечном итоге все фильмы уничтожат друг друга, поэтому мы сделаем так, чтобы они появлялись заново. Cоздадим управляющий элемент onMouseDown в начале функции init.
    _root.onMouseDown = createBall;
  7. Теперь добавим эту новую функцию под всем имеющимся кодом.
    function createBall() {
        ball_mc = attachMovie("ball", "b"+n, n++);
        ball_mc._x = _root._xmouse;
        ball_mc._y = _root._ymouse;
        ball_mc.velX = Math.random()*10-5;
        ball_mc.velY = Math.random()*10-5;
        ball_mc._xscale = Math.random()*50+30;
        ball_mc._yscale = Math.random()*50+30;
        ball_mc.onEnterFrame = ballMove;
        bal1s_array.push(ball_mc);
      }

    Это похоже на код, использованный в init для создания исходных фильмов ball. Основное отличие заключается в том, что здесь ссылка на фильм записывается во временную переменную, присваиваются все его параметры, и затем используется array.push для добавления его в массив.

    Интересным моментом при настройке наших циклов в функции main является то, что мы использовали balls_array.length для определения числа повторений. Параметр length массива будет обновляться при добавлении и удалении объектов из массива, поэтому наши циклы будут всегда выполняться нужное число раз.

  8. Запустите ваш фильм. Для проверки правильности написания кода, приведем полный исходный код программы.
    init();
      function init () {
        max = 10;
        _root.onEnterFrame = main;
        _root.onMousedown = createBall;
        balls_array = new Array();
        for (n=0; n<max; n++) {
          balls_array[n] = attachMovie("ball", "b"+n, n);
          balls_array[n]._x = Math.random()*550;
          balls_array[n]._y = Math.random()*400;
          balls_array[n].velX = Math.random()*10-5;
          balls_array[n].velY = Math.random()*10-5 ;
          balls_array[n]._xscale = balls_array[n]._yscale= Math. random 0*50+30;
        }
      }
      function main() {
        for (i=0; i<balls_array.length; i++) {
          balls_array[i]._x += balls_array[i].velX;
          balls_array[i]._y += balls_array[i].velY;
          if (balls_array[i]._x>550) {
            balls_array[i]._x = 0;
          }
          if (balls_array[i]._x<0) {
            balls_array[i]._x = 550;
          }
          if (balls_array[i]._y>400) {
            bal1s_array[i]._y = 0;
          }
          if (balls_array[i]._y<0) {
            balls_array[i]._y = 400;
          }
        }
        for (i=0; i<balls_array.length-1; i++) {
          for (j=i+1; j<balls_array.length; j++) {
            dx = balls_array[i]._x-balls_array[j]._x;
            dy = balls_array[i]._y-balls_array[j]._y;
            dist = Math.sqrt(dx*dx+dy*dy);
            if (dist<balls_array[i]._width/2+ balls_array[j] ._width/2) {
              removeMovieClip(balls_array[j]);
              balls_array.splice(j, 1);
              removeMovieClip(balls_array[i]);
              balls_array.splice(i, 1);
            }
          }
        }
      }
      function createBall() {
        ball_mc = attachMovie("ball", "b"+n, n++);
        ball_mc._x = _root._xmouse;
        ball_mc._y = _root._ymouse;
        ball_mc.velX = Math.random()*10-5;
        ball_mc.velY = Math.random()*10-5;
        ball_mc._xscale = Math.random()*50+30;
        ball_mc._yscale = Math.random()*50+30;
        ball_mc.onEnterFrame - ballMove;
        balls_array.push(ball_mc);
      }
    Пример 7.6.
  9. Сохраните ваш фильм и закройте его (или поиграйте в игру, если желаете).
Игорь Хан
Игорь Хан

у меня аналогичная ситуация. Однако, если взять пример из приложения (ball_motion_04_click for trial.fla) то след остается. при этом заметил, что в моем проекте в поле "One item in library" виден кружок, в то время как в приложенном примере такого кружка нет.

Вопрос знатокам, что не так?

Александр Коргапольцев
Александр Коргапольцев

объект созданый мной упорно не желает оставлять след(единственное что добился, так это то что шарик резво гоняется за курсором) функция duplicateMovieClip остаётся не активной, т.е. следа от объекта не остаётся, но если я тоже самый код вбиваю в учебный файл всё работает, не могу понять где я ошибаюсь и почему в документе созданном заново, не работает код начиная от функции duplicateMovieClip?