Гэри Розенцвейг - Adobe Flash. Создание аркад, головоломок и других игр с помощью ActionScript
// находится курсор.
for(i=0;i<maxHole;i++) {
hole = _root["hole"+i];
if (hole.hitTest(_xmouse, _ymouse)) {
overeHole = true;
break;
}
}
(10) → // Выясняем, свободно ли отверстие.
if (!pegThere(hole._x, hole._y)) {
(11) → // Определяем различие между исходным и конечным
// положениями.
dx = 0;
dy = 0;
if ((pegx == hole._x) and (pegy-holeSpace*2 == hole._y)) {
// сверху
dy = -1;
} else if (pegx==hole._x) and (pegy+holeSpace*2==hole._y)) {
// внизу
dy = 1;
} else if (pegy==hole._y) and (pegx-holeSpace*2==hole._x)) {
// слева
dx = -1;
} else if (pegy==hole._y) and (pegx+holeSpace*2==hole._x)) {
// справа
dx = 1;
}
(12) → // Значения dx и dy будут равны 0, если целевое отверстие
// не находится на необходимом расстоянии.
if ((dx != 0) or (dy != 0)) {
(13) → // Выясняем, есть ли колышек посередине.
midThere = false;
for(i=0;i<maxHole;i++) {
mid = _root["peg"+i];
if ((mid._x == pegx + dx*holeSpace) and (mid._y == pegy + dy*holeSpace)) {
// Раз колышек здесь находится,
// значит, ход верный.
// Указываем новое положение колышка.
peg._x = hole._x;
peg._y = hole._y;
// Удаляем колышек посередине.
mid.removeMovieClip();
// Запоминаем, что ход верен.
placed = true;
break;
}
}
}
}
(14) → // Проверяем, верный ли ход был сделан, и если нет,
// восстанавливаем исходное положение колышка.
if (placed) {
peg._x = pegx;
peg._y = pegy;
}
}Функция dropPeg использует полезную функцию pegThere, которой передается расположение отверстия и которая возвращает значение true, если именно в этом месте обнаружен клип peg.
function pegThere(x.y) {
// Выясняем, находится ли в этом месте колышек.
for (i=0;i<maxHole;i++) {
peg = _root["peg"+i];
if ((peg._x == x) and (peg._y == y)) {
return true;
}
}
return false;
}Во время игры внизу экрана все время находится кнопка Restart Game (Начать заново), которая позволяет заново начать игру, когда больше нельзя сделать ни одного действия или когда пользователь понимает, что плохо начал игру. Эта кнопка должна не только вызывать функцию initGame, но и очищать оставшиеся клипы «peg» и «hole».
function restartGame() {
// Удаляем все клипы.
for (i=0;i<maxHole;i++) {
_root["peg"+i].removeMovieClip();
_root["hole"+i].removeMovieClip();
}
// Начинаем новую игру.
initGame();
}Код, прикрепленный к кнопке, расположенной внутри клипа «peg», очень прост. Все, что он делает, это передает функциям действия press и release.
on (press) {
_root.dragPeg(this);
}
on (release) {
_root.dropPeg(this);
}Другие возможности
Главный способ изменения игры – создание другой доски. Существует множество вариантов, например, колышек можно перемещать не только по вертикали и горизонтали, но и по диагонали. В данном случае нужно переписать код.
Еще одно изменение – создать колышек, который по цвету отличается от других. Таким образом можно усложнить игру: последним нужно оставить именно этот колышек.
Рекурсивные блоки
Исходный файл: Blocks.fla
Я встречал эту игру в разных вариациях под разными названиями. Основная идея ее в том, что экран заполнен большой решеткой, состоящей из цветных блоков. Игрок может нажать на блок, чтобы удалить его из решетки. Но чтобы удаление блока стало возможным, он должен иметь сверху, снизу или рядом соседний блок того же цвета.
Когда игрок нажимает на доступный для удаления блок, он убирается. К тому же, убирается и соседний блок того же цвета. Все соседи одного цвета с удаленным блоком удаляются тоже. Таким образом, связанная область блоков одного цвета может быть удалена нажатием на любой из блоков этой области.
После удаления группы блоков их верхние соседи спускаются вниз на освободившиеся места. Если какая-нибудь колонка блоков оказывается совершенно пустой, решетка сдвигается влево, чтобы заполнить свободные места.
На рис. 14.8 показано начало игры. В добавление к одному из четырех цветов я поместил на каждый блок маленький рисунок, соответствующий цвету блока. Это облегчает распознавание блоков на черно-белом рисунке. Единственный способ действительно понять игру – это сыграть в нее, поэтому сделайте это прямо сейчас, прежде чем продолжать читать дальше.
Рисунок 14.8. Игра «Рекурсивные блоки» начинается со случайной решетки цветных блоков
Задача проекта
Цель этого проекта в том, чтобы создать игру, дающую лишь основное представление об игровом процессе. В добавление к уже обсуждавшимся общим правилам нужно сделать еще простую систему подсчета очков. Однако не будет предпринято никакой попытки определить, когда игра заканчивается. Предложения, как можно это сделать, даны в конце этой главы.
Подход
Решетка представляет собой серию клипов, созданных с помощью Action-Script. Когда пользователь щелкает по блоку, он удаляется из решетки после того, как отмечен его цвет. Потом каждый из его четырех соседей подвергается проверке, не того же ли он цвета. Если не того же, удаленный блок восстанавливает свой исходный цвет.
Метод удаления блоков является рекурсивным. Каждый сосед выделенного курсором блока проверяется, какого он цвета. Если того же, проверяется каждый его сосед, и т. д. Этот рекурсивный метод в конце концов находит блок, который не имеет соседей того же цвета, и рекурсия заканчивается.
Если вы не вполне уверены, что понимаете, как работает эта рекурсия, посмотрите пример шаг за шагом. Например, пользователь щелкнул по красному блоку. Из четырех его соседей блок сверху и блок справа тоже красные. Возьмите блок сверху. Среди его соседей нет красных блоков. Возьмите блок справа. Блок снизу от него тоже красный. Возьмите этот третий красный блок. Среди его соседей нет красных блоков. Таким образом, блок, по которому пользователь щелкнул, удаляется. Удаляется также блок сверху, блок справа и блок снизу от блока справа.
Хотя игра не определяет, сделал ли пользователь все возможное, она присуждает очки. Лучший способ определения очков в подобной игре – это экспоненциальная система присуждения очков. Таким образом, если удаляется группа из двух блоков, игрок получает 4 очка: 2 раза по 2. Если удаляется группа из 3 блоков, игрок получает 3 раза по 3, или 9 очков. Если же удаляется группа из 4 блоков, игрок получает 4 раза по 4, или 16 очков.
Эта система подсчета очков поощряет игрока находить большие группы блоков. Например, удаление 10 групп по 2 блока принесет пользователю 40 очков (2 раза по 2 будет 4, 10 раз по 4 будет 40). Удаление же одной группы из 20 блоков приносит пользователю 400 очков (20 раз по 20). Пользователь должен не только искать большие группы блоков, но пытаться сам их создавать, вытаскивая маленькие группы таким образом, чтобы большие группы пришли в соприкосновение и сформировали еще большую группу.
Подготовка ролика
Ролик содержит довольно мало элементов, за исключением клипа в библиотеке, представляющего блоки. Этот клип содержит 4 кадра, по кадру для каждого цвета. Также в каждом кадре есть маленькая картинка. Пятый кадр пустой и представляет пустое место в решетке. Первые четыре блока имеют кнопку, чтобы по ним можно было щелкнуть. Клипу необходимо присвоить имя в панели Linkage Properties, поскольку он не находится изначально на рабочем поле.
Главная временная шкала ролика включает в себя два кадра: первый, содержащий инструкции и кнопку Play, а второй – это кадр "Play".
Создание кода
Создание блоков происходит в функции startGame. Функция совершает циклы по 20 горизонтальным колонкам и 12 вертикальным рядам и создает 240 блоков. Каждый блок – это новый экземпляр клипа «block», созданного функцией attachMovie. Кроме того, чтобы оказаться в нужном месте рабочего поля, каждый блок обладает свойствами х и у, таким образом, позже он сможет определить свое положение.
Выбирается случайное число от 1 до 4, и клип с блоком отправляется к этому кадру.
function startGame() {
// Переходим к кадру игры.
gotoAndStop("Play");
score = 0;
// Создаем решетку из блоков.
level = 0;
for(var x=0;x<20;x++) {
for(var y=0;y<12;y++) {
mc = _root.attachMovie("block","block "+x+" "+y,level);
mc._x = 20*x + 85;
mc._y = 20*y + 60;
mc.x = x;
mc.y = y;
// Выбираем случайный цвет.
mc.gotoAndStop(Math.ceil(Math.random()*4));
level++;
}
}
}Когда пользователь щелкает по блоку, чтобы выбрать его, короткий сценарий посылает свойства х и у блока функции, чтобы программа могла решить, какие действия предпринять.
on(release) {
_root.clickBlock(x,y);
}Функция clickBlock определяет цвет блоков и хранит его в переменной с. Затем блок удаляется (точнее, его клип переходит к пустому кадру). Функция testNeighbor вызывается четыре раза, один раз для каждого соседа. Функция возвращает количество подходящих соседей, найденных в данном направлении. Если, например, сосед сверху того же цвета и три его соседа тоже, возвращается число 4. Добавляя это число к переменной n, вы получаете полное количество блоков в группе. Если обнаружено, что группа состоит более чем из одного блока, вызываются функции collapseDown и collapseAcross, чтобы удалить все блоки группы. В противном случае выделенный блок возвращается к прежнему цвету, и кажется, что ничего не произошло.