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

Интерфейсы AсtionScript

  1. Если нам требуется найти определенный кусок кода, можно вывести логическим путем, в каком месте он находится. Но помните, что функция init не будет выполняться сама по себе. Поэтому нам нужно добавить одну строку вверху кода.
    init();
  2. Теперь нужно создать цель для стрельбы! Я нарисовал космический корабль и преобразовал его в фильм с именем ship. Не забудьте указать, что нужно выполнить экспорт для AсtionScript, тоже с именем ship, и удалить все инстансы с рабочего места для инициализации.

    Сейчас мы создадим функцию, которая будет рисовать корабль.

    function createShip() {
        currShip_mc = attachMovie("ship", "ship"+shipCounter, shipCounter);
        currShip_mc._x = 0;
        currShip_mc._y = Math.random 0*300;
        currShip_mc.speed = Math.random 0*10+5;
        currShip_mc.onEnterFrame = shipMove;
        shipCounter++;
      }

    Весь этот код вам уже знаком. Мы присвоили фильм, установили его позиции _x и _y, создали переменную с именем speed, присвоили функцию onEnterFrame и увеличили переменную, используемую для имени фильма и установки его уровня.

  3. Однако теперь мы столкнемся с определенной проблемой. Сейчас мы располагаем наш первый корабль на глубине 0 и увеличиваем значение с нуля. Мы также располагаем первую пулю на глубине 0 и так же увеличиваем значение с нуля. В конечном счете возникнет конфликт. Либо пуля попытается занять глубину, на которой уже расположен корабль, либо наоборот. Но так как известно, что глубина пули всегда будет в пределах 0-9, мы можем решить эту проблему, начав отсчет уровней корабля с 10. Это можно сделать, добавив следующую строку кода в функцию init.
    shipCounter=10;
  4. Теперь, если вы внимательно следили за происходящим, вы сможете предсказать следующий шаг. Мы присвоили функцию shipMove нашему управляющему элементу корабля onEnterFrame. Сейчас нам нужно определить эту функцию. Мы уже установили для нее случайную скорость. Нам нужно просто использовать эту скорость для контроля позиции корабля.
    function shipMove() {
        this._x += this.speed;
      }
  5. У нас есть функция для создания корабля. Как и когда нужно вызывать эту функцию? Нам придется делать это не один раз, иначе у нас будет только один корабль. Не следует делать это в функции onEnterFrame, так как через несколько секунд кораблей станет слишком много. Нам нужно, чтобы каждый корабль появлялся, скажем, каждые две секунды. Так как это на самом деле не делается с помощью обработки событий, мы реализуем это в качестве бонуса (так как нам это нужно для функционирования игры!).

    Flash MX содержит очень полезную команду setInterval. С ее помощью можно указывать функции, что необходимо выждать определенный промежуток времени перед выполнением, и затем выполняться каждый раз по прошествии этого интервала. Так как это понадобится нам в начале фильма, введем команду в функцию init.

    setInterval (createShip, 2000);

    Аргументами здесь являются выполняемая функция и интервал ожидания. Обратите внимание, что здесь мы опустили скобки в имени функции. Мы просто сделали так, чтобы setInterval содержал ссылку на саму функцию. Интервал указывается в миллисекундах, поэтому 2000 будет соответствовать интервалу в две секунды. Когда мы выполним функцию init, setInterval сообщит createShip о необходимости ожидания в течение двух секунд, после чего функция выполнится. С этого момента функция будет выполняться каждые две секунды.

    Несмотря на то, что мы не будем использовать здесь эту функцию, я скажу несколько слов о сопровождающем объекте для setInterval - clearInterva l. Существует множество обстоятельств, когда нужно, чтобы функция выполнялась через интервал времени, но потом прекращала свое выполнение. clearInterval (intervalID) используется для прекращения выполнения этой функции. Как узнать ID интервала? Он возвращается при выполнении setInterval. Следовательно, нужно ввести примерно следующий код:

    intervalID = setInterval (createShip, 2000);

    Теперь предположим, что нам нужно создать только 100 кораблей. Мы можем следить за числом кораблей с помощью нашей переменной shipCounter. С учетом того, что shipCounter начинается со значения 10, по достижении значения 110 у нас будет 100 кораблей. Исходя из этого, нужно добавить в функцию createShip следующую функцию:

    if (shipCounter = = 110) {
        clearInterval (shipIntervalID);
      }:

    Это предотвратит повторное выполнение createShip. На этом этапе можно установить новый интервал, в котором createShip будет выполняться каждые 1,5 вместо 2 секунд, что ускорит действие игры. Оставляю эти дополнительные настройки на ваше усмотрение!

    Приведем весь созданный нами код.

    init ();
      function init() {
        Mouse.hide();
        trigger = new Object ();
        Key.addListener(trigger);
        trigger.onKeyDown = shoot;
        i = 0;
        FIRELEFT = 122;
        FIREMID = 120;
        FIRERIGHT = 99;
        shipCounter = 10;
        setInterval(createShip, 2000);
      }
      cursor_mc. onEnterFrame = function()
        this._x += (_root._xmouse-this._x)/5;
        this._y += (_root._ymouse-this._y)/5;
      };
      function shoot() {
        keyPressed = Key.getAscii();
        switch(keyPressed){
          case FIRELEFT:
            startX = 50;
            break;
          case FIREMID:
            startX = 275;
            break;
          case FIRERIGHT:
            startX = 500;
            break;
          default:
            startX = 0;
      }
      if(startX){
          currBullet_mc = _root.attachMovie ("bullet", "bullet"+i, i);
          currBullet_mc._x = startX;
          currBullet_mc._y = 400;
          currBullet_mc.onEnterFrame = bulletMove;
          i++;
          if (i>9) {
            i = 0;
          }
        }
      }
      function bulletMove() {
        if (!this.shot) {
          this.xSpeed = (_root.cursor_mc._x-this._x)/20;
          this.ySpeed = (_root.cursor_mc._y-this._y)/20;
          this.shot = true;
        }
        this._x += this.xSpeed;
        this._y += this.ySpeed;
        if (this._y<0) {
          removeMovieClip(this);
        }
      }
      function createShip() {
        currShip_mc = attachMovie("ship", "ship"+shipCounter, shipCounter);
        currShip_mc._x = 0;
        currShip_mc._y = Math.Random()*300;
        currShip_mc.speed = Math.random()*10+5;
        currShip_mc.onEnterFrame = shipMove;
        shipCounter++;
      }
      function shipMove()  {
        this._x += this.speed;
      }
    Пример 6.2.

    Советую сейчас просмотреть каждую строку кода и убедиться в понимании каждой команды и символа, их назначения, а также их расположения в коде.

  6. Небольшим недостатком нашей игры является то, что при попадании пули в корабль ничего не происходит. Поэтому мы добавим проверку попадания для законченности игры. В следующей лекции мы уделим много внимания обнаружению коллизий, поэтому мы остановимся здесь лишь на общей функции hitTest, которая выглядит так.
    movieclip1.hitTest (movieclip2)

    Нам необходимо постоянно проверять попадания, поэтому лучше добавить эту функцию в блок кода onEnterFrame. Так как мы уже имеем управляющий элемент onEnterFrame, определенный для каждого корабля, это место как нельзя лучше подходит для проверки на попадание. Одновременно на рабочем месте будут присутствовать до десяти пуль, и нам нужно проверять корабль на попадание каждой пули. Это легко осуществить с помощью цикла for, динамически создавая имя каждой пули. Если hitTest возвратит попадание, пуля будет просто удалена, а также будет удален сам корабль. Функция shipMove становится такой.

    function shipMove() {
        this._x += this.speed;
        for (test=0; test<10; test++) {
          if (this.hitTest(_root["bullet"+test])) {
            removeMovieClip(_root["bullet"+test]);
            removeMovieClip(this);
          }
        }
      }
  7. Добавим удаление всех кораблей, которые вышли за пределы экрана. Используем произвольное большое число для проверки того, что корабль вышел за пределы экрана. Если это так, корабль будет удален.
    function shipMove() {
        this._x += this.speed;
        if(this._x > 700){
        removeMovieClip(this);
        }
        for (test=0; test<10; test++) {
          if (this.hitTest(_root["bullet"+test])) {
            removeMovieClip(_root["bullet"+test]);
            removeMovieClip(this);
          }
        }
      }

    Надеемся, что весь рассмотренный материал вам понятен (и что ваша игра работает корректно!). Это не самая захватывающая игра в мире, но она дает вам возможность попрактиковаться в программировании поддержки событий и несложных функций. Вы также получили представление об основной модели программирования. Играйте в вашу игру и добавляйте в нее все новые и новые возможности. Вы сможете добавить в нее столько функций, сколько захотите, поддерживать любые события, а также делать любую функцию настолько простой или сложной, насколько это требуется.


    Полный код игры вы можете найти в файле shootemup.fla в папке Chapter 6.

Игорь Хан
Игорь Хан

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

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

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

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