Викторина во Flash

Исходный файл: Flashquiz.fla

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

Рисунок 12.1 В основном кадре игры показан вопрос и четыре варианта ответа

Задача проекта

Цель проекта – создать программу, которая будет получать вопросы из внешнего текстового файла, затем один за другим предлагать их игроку. Правильность/неправильность ответа обозначается звуковым сигналом.
После того как будут заданны десять вопросов, игра окончится. На экране должно отобразиться набранное количество очков. Запустите ролик Flashquiz.fla, и сыграйте несколько раундов, чтобы получить представление о работе программы.

Подход

Сначала нужно получить вопросы и ответы из текстового файла. Для этого можно воспользоваться объектом loadVars, который позволяет загружать данные из внешнего файла.
К сожалению, объект loadVars не позволяет обрабатывать массивы или объекты, а такая возможность нужна для рационального хранения набора вопросов и ответов. Однако можно прочесть один фрагмент текста, с помощью команды split разбить его на части и сохранить полученное в массиве. Таким образом вы получите из одного текстового блока десять вопросов, четыре варианта ответа на каждый вопрос и номер правильного ответа.
Как только вопросы будут расположены в массиве, сделать все остальное не составит труда. Текст каждого вопроса и ответов помешаются в соответствующих текстовых полях. Номер правильного ответа присваивается переменной. Затем программа ждет, когда игрок щелкнет по кнопке.
Каждая кнопка вызывает функцию, передавая ей соответствующий ответ. Если игрок щелкнул по правильной кнопке, проигрывается звуковой сигнал, и увеличивается число заработанных очков. В противном случае звучит сигнал неправильного ответа и задается следующий вопрос.
После того как будут заданы десять вопросов, игра переходит к кадру "game over", где отображается число набранных очков.
Чтобы сделать игру интереснее, вы можете использовать специальный эффект, благодаря чему текст вопроса будет "въезжать" на экран справа.

Подготовка ролика

Многое нужно определить до того, как начнется выполнение сценария. Первый кадр (рис. 12.2) - это "loading" (загрузка). Так как вопросы загружаются из внешнего текстового файла, прежде чем начать игру, надо убедиться, что все вопросы находятся на месте.
После загрузки вопросов код ActionScript переводит игру ко второму кадру, помеченному "start game". В этом кадре даны указания для игры и показана кнопка (рис. 12.3).
Основной кадр игры (рис. 12.1) - самый сложный. В нем находится текстовое поле для вопроса, четыре текстовых поля для ответов и маленькое текстовое поле для номера вопроса. Слева от ответов расположены четыре кнопки.

Рисунок 12.2 На экране отображается кадр "loading" до тех пор, пока не будут загружены все вопросы

Каждое из пяти основных текстовых полей помечено в клипе словом "text". Один клип называется "question", остальным присвоены имена от "answer0" до "answer3". Так сделано для того, чтобы не создавать простые текстовые поля и иметь возможность перемешать клипы на рабочем поле (об этом эффекте будет рассказано далее).

Рисунок 12.3 Кадр "start game" виден, пока пользователь не щелкнет по кнопке начала игры

Создание кода

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

Метод load объекта LoadVars осуществляет загрузку, обращаясь к указанному URL. Файл данных должен иметь вид "имя переменной = данные". Например, в результате обращения к текстовому файлу myVariable=Hello переменной myvariable будет присвоено значение Hello. Поскольку обращение происходит к удаленному серверу, может пройти некоторое время между вызовом команды load и загрузкой данных.

Итак, в начале сценария создается новый объект loadQuestions. С помощью метода load он обращается к файлу Flashquiz.txt.
Свойство onLoad объекта LoadVars определяет функцию, которая вызывается, когда загрузка завершена. В этом случае будет вызвана функция initQuestions.
После выполнения команды LoadVars. load данные из текстового файла будут доступны к использованию ActionScript. Например, если переменной myProperty присвоено значение myValue, то обращение loadQuestionsmyProperty. вернет значение myValue.

stop();
// Загружаем вопросы.
loadQuestions = new LoadVars();
loadQuestions.load("flashquiz.txt");
// Вызываем initQuestions, когда загрузка окончена.
loadQuestions.onLoad = initQuestions;

Функция initQuestions преобразовывает текстовую строку в массив, состоящий из вопросов, ответов и номера правильного ответа для каждого вопроса.
Вот как выглядит первая часть файла Flashquiz.txt. Первая строчка присваивает свойству topic текст "The Planets". С помощью обращения loadQuestions.topic сценарий получит доступ к этому значению и присвоит его переменной topic. Результат отобразится в динамическом текстовом поле.

topic=The Planet&questions=Which planet is closest to the Sun?:
Jupiter;Saturn;Mercury,-Mars:2:

Обратите внимание, в текстовом файле переменные необходимо разделять знаком "&". Переменная questions состоит из нескольких строчек; в каждой содержится отдельный вопрос. Каждый вопрос состоит из трех частей: текст вопроса, ответы и номер правильного ответа. Части отделяются друг от друга двоеточием, а в качестве разделителя ответов мы используем точку с запятой.

Which planet is titled on its axis the most?:
Earth;Venus;Mars;Uranus:3:
Which planet is the largest?:Jupiter;Earth;Neptune;Pluto:0:
Which planet has exactly two moons?:Venus;Mars,-Saturn;Uranus:1:

тема=планеты&вопросы=Какая планета ближайшая к солнцу?:
Юпитер;Сатурн;Меркурий;Марс:2:
У какой планеты ось имеет наибольший наклон?:
3емля;Венера;арс; Уран :3 :
Какая планета самая большая?:Юпитер;3емля;Нептун;Плутон:0:
Какая планета имеет две луны?:Венера;Марс;Сатурн,-Уран:1:

В конце каждой строки было добавлено двоеточие, чтобы строчка разбивалась кодом, другие дополнительные символы в конце строки будут помешены в четвертую, неиспользуемую часть. Какие могут быть дополнительные элементы? Например, при использовании текстовых редакторов Windows дополнительный невидимый символ помещается в конце каждой строки текста. Если вы позволите программе Flash использовать этот символ для номера правильного ответа, это помешает ей преобразовать номер во что-то еще. То есть лишнее двоеточие помешает дополнительный символ в неиспользуемый четвертый элемент каждой строки без ущерба для работы программы.

Не вставьте ненароком пустую строчку в конец текстового файла. Такая строчка будет создана, если нажать клавишу Enter или Return после ввода последнего вопроса. Если в конец текстового файла добавить пустую строчку, код воспримет ее как одиннадцатый элемент.

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

function initQuestions(questions) {
// Задаем значение переменной topic,
topic = loadQuestions.topic;
// Разбиваем на отдельные вопросы.
// Внимание: в некоторых случаях лучше использовать
// значение 13, а не 10.
qArray = loadQuestions.questions.split(String.fromCharCode(10));
// Разбиваем строчку вопроса на элементы,
for(i=0;i qArray[i] = qArray[i].split(":");
// Отделяем ответы друг от друга.
qArray[i][1] = qArray[i][1].split(";");}
// Начинаем игру. _root.gotoAndPlay("start game");
}

Я использовал выражение String. fromCharCode (13), чтобы получить символ возврата каретки, что нужно для отделения строк в текстовом файле. Почему я не применил константу newline? Дело в том, что newline в программе Flash отличается для систем Macintosh и Windows. В Macintosh возвращается значение 13, а в Windows - 10. Более того, некоторые текстовые редакторы предпочитают значение 10, а некоторые оба! Так что, если игра не движется далее первого вопроса, попробуйте поменять 10 на 13, чтобы проверить, не в этом ли проблема.

Когда игра переходит к кадру "play", код ActionScript в основной временной шкале сразу же вызывает функцию initGame, которая обнуляет переменные questionNum и numRight и вызывает функцию displayQuestion, отображающую первый вопрос.

Функция split берет строчку и разбивает ее на фрагменты, которые помешаются в массив. Единственный параметр, который используется в этой функции, - это символ, необходимый для разделения фрагментов. В предыдущем примере как двоеточие, так и точка с запятой применялись для разбиения строчки и помещения элементов в массив.

function initGameO {
// Устанавливаем значения переменных.
questionName = 0;
numRight = 0;
// Выводим первый вопрос.
displayQuestion();
}

Функция displayQuestion определяет, закончена ли игра или нет, и в случае положительного ответа отображает окончательное количество набранных очков и переходит к кадру "game over". В противном случае она берет вопрос и каждый ответ и помешает их в текстовые поля внутри соответствующих клипов. Номер правильного ответа присваивается переменной correctAnswer.

function displayQuestion() {
// Проверяем, все ли вопросы уже заданы,
if (questionNum >= qArray.length) {
// Отображаем окончательное число очков и завершаем игру
finalScore = numRight + "out of" + qArray.length;
gotoAndPlay("game over");
} else {
// Отображаем вопрос и ответы на экране.
question.text = qArray[questionNum][0];
answer0.text = qArray[questionNum][1][0];
answer1.text = qArray[questionNum][1][1];
answer2.text = qArray[questionNum][1][2];
answer3.text =qArray[questionNum][1][3];
// Выводим номер ответа.
questionNumDisplay = questionNum+1;
// Запоминаем, какой ответ верный.
correctAnswer = int(qArray[questionNum][2]
// Делаем так, чтобы текст "въезжал" на экран
animatein();
}
}

Когда у вас массив содержится в другом массиве (двумерный массив), к элементу вложенного массива можно обратиться с помощью нескольких скобок. Например, выражение myArray[3] [8] обращается в восьмому значению третьего элемента массива myArray. Массив ту Array СОСТОИТ ИЗ четырех или более элементов, в третьем элементе содержится, в свою очередь, массив по меньшей мере из девяти элементов.

Функция animatein позволяет создать эффект появляющегося из-за экрана текста. Она устанавливает положение каждого текстового клипа за рабочим полем справа. Затем для каждого из этих клипов с помощью переменной xstop присваивается нужное горизонтальное положение. Код, прикрепленный к каждому из этих клипов, перемешает его влево до тех пор, пока он не дойдет до положения xstop.

function animatein() {
// Определяем положение каждого элемента текста,
//а также указываем место, где клип должен остановиться.
question.xstop = 300;
question._x = 800;
answerO.xstop = 400;
answer0._x = 1000;
answerl.xstop = 400;
answerl._x = 1200;
answer2.xstop = 400;
answer2._x = 1400;
answer3.xstop = 400;
answer3._x = 1600;
}

Когда пользователь щелкает по одной из четырех кнопок, вызывается функция selectAnswer, которой передается номер выбранного ответа (от 0 до 3). Если эта величина равна correctAnswer, звучит сигнал правильного ответа и увеличивается значение numRight. В противном случае воспроизводится сигнал неверного ответа. В любом случае увеличивается значение переменной guestionNum и отображается следующий вопрос.

function selectAnswer(n) {
// Добавляем очко, если ответ правильный,
if (n == correctAnswer) {
triggerSoundf"right") ; numRight++;
} else {
triggerSound("wrong") ;
}
// Отображаем следующий вопрос.
questionNum++;
displayQuestion();
}

Функция triggersound проста, но очень полезна во многих игровых ситуациях. Ее назначение - проигрывать звук, сопровождающий правильный ответ.

function triggerSoundfsoundName) {
// Проигрываем звук,
soundfx.stop();
soundfx = new Sound();
soundfx.attachSoundfsoundName);
soundfx.start();
}

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

onClipEvent(enterFrame) { if (_x != xstop) _x -= 20;
}

К каждой кнопке также прикреплен короткий сценарий, который при щелчке по ней вызывает функцию selectAnswer и передает ей значение от 0 до 3. Сценарий следующий:

on (release) {
selectAnswer(0); }

Для других кнопок вместо 0 будет указано либо 1, либо 2, либо 3.

К сведению

Вам понадобятся два звука, один с именем "right", а другой - "wrong". Также потребуется кнопка "continue", похожая на изображенную на рис. 12.3. Если у вас есть вопросы по работе программы, просмотрите ролик Flashquiz.fla.

Другие возможности

Хотя цель игры заключается в отображении только 10 вопросов, ни одна строчка кода не ограничивает их число. Можно запросить большее или меньшее количество вопросов из файла Flashquiz.txt.
Вместе с выводом строки пользователю можно показывать некое сообщение. Например, при отображении строчки "8 out of 10" можно подбодрить пользователя следующим образом: "You know your planets!" (Вы знаете планеты!), а при двух не правильных ответах из 10 будет выводиться сообщение "Go back to school" (Снова идите в школу).