Опубликован: 07.11.2006 | Уровень: специалист | Доступ: свободно
Лекция 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. Сохраните ваш фильм и закройте его (или поиграйте в игру, если желаете).
Игорь Хан
Игорь Хан
След не остается
Александр Коргапольцев
Александр Коргапольцев
Вопрос по содержанию лекции №2, курс Flash MX Studio
Евгения Новоселецкая
Евгения Новоселецкая
Россия
Станислав Бакулин
Станислав Бакулин
Эстония, Нарва