Опубликован: 07.11.2006 | Уровень: специалист | Доступ: платный
Лекция 12:

Изучение SphereCage

Код программы

Хочу сразу вас предупредить - вас ждет работа над достаточно большим количеством кода, поэтому будет лучше сейчас потратить некоторое время и разобраться в том, что мы будем писать, чтобы в дальнейшем не запутаться. Я разделил код на четыре логических части. Рассмотрим, что будет реализовываться в каждой из них.

Интерфейс SphereCage
  • Объявление переменных для игры.
  • Создание фильмов, в которых будут находиться рисунки.
  • Создание звуковых объектов для управления звуковыми эффектами.
  • Создание и форматирование текстовых полей для хранения данных о количестве очков.
  • Рисование фоновых рисунков

Классы
  • Создание отдельного класса Class LightSource для информации об источнике света.
  • Создание отдельного класса Class Model для информации о нашей трехмерной модели.
Наследственность
  • Создание BallModel, подкласса Model, который будет содержать информацию о шарике.
  • Создание PlaneModel, подкласса Model, который будет содержать информацию о ракетках.
  • Создание PopUp, подкласса Model, который будет содержать информацию о всплывающих окнах.
Функции игры и реализация объектов
  • Создание общих функций игры
  • Рисование изображений первого плана.
  • Инициализация игры.
  • Учет очков.
  • Управление звуками.
  • Сортировка глубин.
  • Обновление моделей по нажатию клавиш.
  • Форматирование всплывающих окон.
  • Создание инстансов объектов классов (ракетки, шарик и цели).

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

Интерфейс SphereCage

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

  1. На главной точке временной шкалы переименуйте слой по умолчанию, присвоив ему имя Actions. Весь код этой игры будет располагаться в первом кадре этого слоя. Откройте панель Actions и введите следующий ActionScript.
    stageHeight = Stage.height; 
    stageWidth = stageHeight*1.375; 
    centerX = stageWidth*2/3; 
    centerY = stageHeight/2; 
    focalLength = stageHeight; 
    radius = stageHeight*.4; 
    radAdj = radius*.8; 
    planeSize = stageHeight/20; 
    smoothness = 80;
    
    this.createEmptyMovieClip("backShadow", 1);
    this.createEmptyMovieClip("targetMC", 2);
    this.attachMovie("ball", "ballMC", 10);
    this.createEmptyMovieClip("planeMC", 20);
    this.createEmptyMovieClip("paddleMC", 30);
    this.createEmptyMovieClip("sphere", 100);
    this.createEmptyMovieClip("painting", 150);
    this.createEmptyMovieClip("paintMask", 151);
    this.createEmptyMovieClip("blip0MC", 250);
    this.createEmptyMovieClip("blip1MC", 251);
    this.createEmptyMovieClip("blip2MC", 252);
    this.createEmptyMovieClip("missMC", 253);
    this.attachMovie("reflect", "reflect", 200);
    reflect._height = reflect._width=radius*2; 
    reflect._alpha = 4;
    
    sphere.createEmptyMovieClip("rim", 0);
    sphere.createEmptyMovieClip("shadow", 1);
    sphere.createEmptyMovieClip("highlight", 2);
    targetMC.createEmptyMovieClip("topTarget", 0);
    targetMC.createEmptyMovieClip("bottomTarget", 1);
    reflect._x = targetMC._x=ballMC._x=planeMC._x=paddleMC._x=sphere._x=
    КbackShadow._x=centerX;
    reflect._y = targetMC._y=ballMC._y=planeMC._y=paddleMC._y=sphere._y=
    КbackShadow._y=centerY;
    blip0 = new Sound (blip0MC);
    blip1 = new Sound(blip1MC); 
    blip2 = new Sound(blip2MC); 
    miss = new Sound(missMC); 
    blip0.attachSound("blip0");
    blip1.attachSound("blip1");
    blip2.attachSound("blip2");
    miss.attachSound("miss");
    Пример 11.1.

    В этом коде нет ничего особо удивительного. Сначала устанавливаем число переменных, включая размеры рабочего места. Заметьте, что все основано на высоте рабочего места, даже переменная stageWidth. Это означает, что изменение размера рабочего места будет также изменять все параметры игры при управлении пропорциями, включая размер шрифта.

    centerX и centerY являются координатами центра сферы, а также центра трехмерного пространства. radius является радиусом нашего круга, а radAdj - это просто небольшой сдвиг, находящийся внутри radius. Этот сдвиг является местом расположения ракетки игрока для защиты периметра и придает сфере толщину, что вы можете наблюдать в конечной версии игры. Наконец, planeSize будет размером наших двух ракеток, а smoothness будет указывать число линий, используемых для рисования наших сфер - чем больше число, тем более гладкая поверхность. Я думаю, что значение, равное 80, нас устроит.

    После этого мы создаем все необходимые фильмы, а также добавляем шарик и карту отражения. Мы не раз возвратимся к этому при работе с нашими объектами. Обратите внимание, что мы применили к фильму reflect размытие со значением 4%. Если результат кажется вам слишком нечетким, увеличьте это значение.

    targetMC (маленькие значки "x", представляющие траекторию шарика) и sphereMC имеют вложенные фильмы, которые здесь и создаются.

    Далее мы устанавливаем большинство рисунков на позицию centerX и centerY. Сейчас, при доработке, я, наверное, и дальше использовал бы наследование (с размещением этих фильмов в фильме-родителе и перемещением его на позицию centerX и centerY ), однако наш способ также годится.

    Наконец, создаем новые объекты Sound для каждого звукового фильма и добавляем соответствующие звуки из Library. Если вам интересно, почему мы создали фильмы, на которые ссылаются звуковые объекты, вместо использования _root, объясняю: связывание звуков с различными точками временной шкалы позволяет управлять каждым звуком независимо от других при необходимости настройки громкости или проигрывания. На самом деле это не обязательно для нашей игры, однако это хороший способ настройки звуков, который вы сможете использовать для добавления этой функциональности впоследствии.

  2. Введите этот фрагмент кода, рисующий фоновое изображение.
    this.lineStyle(10, 0x222222, 100); 
    this.beginFill(0, 100); 
    this.lineTo(stageWidth/3, 0); 
    this.lineTo(stageWidth/3, stageHeight); 
    this.lineTo(0, stageHeight); 
    this.lineTo(0, 0); 
    this.endFill(); 
    this.lineTo(stageWidth, 0); 
    this.lineTo(stageWidth, stageHeight); 
    this.lineTo(0, stageHeight);
    
    this.lineStyle(2, 0xEEEEEE, 60); 
    this.moveTo(0, 0); 
    this.lineTo(stageWidth/3, 0); 
    this.lineTo(stageWidth/3, stageHeight);
    this.lineTo(0, stageHeight); 
    this.lineTo(0, 0); 
    this.lineTo(stageWidth, 0); 
    this.lineTo(stageWidth, stageHeight); 
    this.lineTo(0, stageHeight);
    
    paintMask.beginFill(0, 100);
    paintMask.moveTo(3, 3);
    paintMask.lineTo(stageWidth/3-3, 3);
    paintMask.lineTo(stageWidth/3-3, stageHeight-3);
    paintMask.lineTo(3, stageHeight-3);
    paintMask.endFill();
    painting.setMask(paintMask);
    Пример 11.2.

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

    paintMask - это фильм, который будет маскировать наше градиентное закрашивание внутри темной области с левой стороны. Последняя строка устанавливает маску (хотя мы еще должны нарисовать что-либо в фильме painting).

  3. Теперь пришло время подготовить форматирование шрифтов и добавить поля статистики. Здесь хочу сказать, что одной из моих любимых возможностей Flash MX является элемент управления шрифтами, поэтому я не могу не использовать его в программе.
    textHeight = stageHeight/20;
    
    statsTitle = new TextFormat(); 
    statsTitle.color = 0x449944; 
    statsTitle.font = "statsTitleFont";
    statsTitle.size = stageHeight*.04;
    statsTitle.underline = 1;
    
    stats = new TextFormat(); 
    stats.color = 0xFFFFFF; 
    stats.font = "statsFont";
    stats.size = stageHeight*.05; 
    stats.bold = 1;
    
    this.createTextField("livesTitleTF", 501, stageWidth/40, textHeight, 0, 0);
    this.createTextField("highTitleTF", 502, stageWidth/40, textHeight*4, 0, 0);
    this.createTextField("scoreTitleTF", 503, stageWidth/40, textHeight*7, 0, 0);
    this.createTextField("highTF", 504, stageWidth/40, textHeight*5, 0, 0);
    this.createTextField("scoreTF", 505, stageWidth/40, textHeight*8, 0, 0);
    
    livesTitleTF.setNewTextFormat(statsTitle);
    highTitleTF.setNewTextFormat(statsTitle);
    scoreTitleTF.setNewTextFormat(statsTitle);
    highTF.setNewTextFormat(stats);
    scoreTF.setNewTextFormat(stats);
    highTitleTF.embedFonts = scoreTitleTF.embedFonts = livesTitleTF.embedFonts=1;
    highTF.embedFonts = scoreTF.embedFonts=1;
    highTitleTF.autoSize = scoreTitleTF.autoSize = livesTitleTF.autoSize="left";
    highTF.autoSize = scoreTF.autoSize="left";
    livesTitleTF.text = "LIVES";
    highTitleTF.text = "HIGH SCORE";
    scoreTitleTF.text = "SCORE";
    highTF.text = "00000000";
    Пример 11.3.

    Здесь мы создаем два объекта TextFormat: stats и statsTitle. Устанавливаем их размер, цвет и стиль, а также шрифт (идентификаторы связей шрифтов в Library). Затем создаем пять текстовых полей, используя переменные stageHeight и stageWidth для настройки расположения.

    Теперь рассмотрим код, приведенный выше, еще раз и обратим внимание на то, что мы устанавливаем ширину и высоту для каждого текстового поля на ноль. Это возможно благодаря тому, что при форматировании текстовых полей мы устанавливаем их параметр autoSize на значение "left", а значит, текстовое поле будет расширяться в правую сторону по мере добавления в него текста. Это полезная возможность. При необходимости можно также использовать "center" и "right".

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

  4. Запустите фильм, чтобы отобразить фон и текст, который мы создали до сих пор. С этого момента мы не сможем видеть какие-либо изменения на рабочем столе до полного завершения кода.
Игорь Хан
Игорь Хан

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

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

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

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

Тамара Ионова
Тамара Ионова
Россия, Нижний Новгород, НГПУ, 2009
Магомед Алисултанов
Магомед Алисултанов
Россия, Волгоград, лицей 2