Пятнашки

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

В отличие от пазла игра "Пятнашки" куда интереснее в качестве компьютерной игры, чем в виде обычной игры. "Пятнашки" обычно состоят из 15 квадратных элементов, которые перемешаются вдоль сетки, рассчитанной на 16 элементов. Пустое место - дополнительная область, куда может быть перемещен элемент мозаики.
На рис. 13.3 показана мозаика с изображением лисы. Попробуйте сыграть в эту игру, открыв файл Slidingpuzzle.fla. Вы можете щелкнуть по любому из четырех элементов, смежных с пустым квадратиком, чтобы переместить его. Цель игры - правильно собрать картинку, оставив пустым место в нижнем правом углу.

Рисунок 13.3 В "Пятнашках" используется 15 элементов и один пустой квадрат

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

Цель проекта - создать простую, легкую игру по принципу "Пятнашек". Игрок будет щелкать по элементу: если рядом есть пустой квадрат, элемент будет перемешен.
Очень важно в начале игры случайным образом расположить элементы. Для этого Flash-ролик сначала нарисует все элементы мозаики на своих местах, а затем будет выполнено 100 произвольных перемещений. Таким образом, элементы окажутся перемешаны, и собрать такую мозаику будет сложно, но возможно.

Подход

Большая часть рассматриваемой программы представляет собой по сути подготовку к собственно игре, обеспечивая перемешивание элементов мозаики. Сначала случайным образом выбирается элемент. Потом выполняется проверка, является ли один из четырех смежных элементов пустым. Если да, то выбранный элемент перемещается туда. В противном случае выбирается другой элемент до тех пор, пока не будет найден элемент, смежный с пустым квадратом. Этот процесс повторяется 100 раз.
Когда перемешивание закончено, пользователь может передвигать элементы сам. Когда он щелкает по элементу, код проверяет, есть ли рядом с этим элементом пустой квадрат, если да, выбранный элемент перемещается туда.

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

Можно воспользоваться любым понравившимся вам методом создания элементов. Чтобы получить 15 элементов, я выделял квадраты на графическом изображении. В отличие от элементов составной картинки-загадки здесь не нужно размешать их определенным образом. Центром каждого элемента мозаики может бьпъ его собственный геометрический центр. То есть для этой игры создать элементы гораздо проще.
После того как вы создали все элементы, поместите их на рабочее поле так, как они должны располагаться в собранной мозаике. Я сделал кусочки размером 54x54 пиксела, то есть они должны бьпъ расположены друг от друга на расстоянии 54 пиксела как по вертикали, так и по горизонтали. Поскольку Flash не гарантирует точность при размещении клипов вручную, даже если показана сетка, выравнивать элементы перед началом игры лучше с помощью ActionScript.
Очень важно поместить элементы близко к их исходному положению и присвоить им имена. Я дал им имена от tilel до tileis, чтобы к ним можно было обращаться в коде программы.

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

Большая часть кода находится в основной временной шкале. Он начинается с выравнивания элементов на расстоянии точно в 54 пиксела, затем 100 раз выполняется цикл, перемещающий случайно выбранный элемент на пустую позицию.

function initGame() {
// Устанавливаем горизонтальное и вертикальное расстояние
// между элементами.
tileDist = 54;
// Помещаем все элементы на свои места,
for (x=l;x<=4;x++) {
for (y=0;y<=3;y++) {
tile = х+у*4;
_root["tile"+tile];
_x = x*tileDist;
_root["tile"+tile];
_y = y*tileDist+tileDist;
}}
// Совершаем 100 произвольных перемещений,
for(tilenum=0;tilenum<100;tilenum++) {
do {
// Выбираем элемент случайным образом.
tile = "tile"+(random(15)+1);
//- Проверяем, есть ли рядом свободный квадрат.
emptySpace = findEmpty(tile);
// Цикл продолжается до тех пор, пока не будет найден
// элемент, рядом с которым расположен свободный квадрат.
} while (emptySpace == "none");
// Перемещаем элемент на свободное место.
moveTile(tile,findEmpty(tile));
}}

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

// Проверяем, есть ли свободное место около данного элемента,
function findEmpty (tile) {
// Определяем положение элемента.
tilex = _root[tile]._x;
tiley = _root[tile]._y;
// Проверяем, есть ли элемент мозаики слева,
if (tilex > tileDist) {
if (!tileThere(tilex-tileDist, tiley)) {
return("left");
}}
// Проверяем, есть ли элемент мозаики справа,
if (tilex > tileDistM) {
if (!tileThere(tilex+tileDist, tiley)) {
return("right");
}} // Проверяем, есть ли элемент мозаики сверху. if (tiley > tileDist) { if (!tileThere(tilex, tiley-tileDist)) { return)"above");
}}
// Проверяем, есть ли элемент мозаики снизу,
if (tiley > tileDistM) {
if (!tileThere(tilex, tiley+tileDist)) {
return("below");
}}
// Элементы мозаики имеются со всех сторон,
return ("none");
}

Если перед выражением стоит восклицательный знак, значит, OHO отрицается, то есть true превращается в false, a false в true. Эта операция известна как логическое не (not). Например, в предыдущем коде проверяется не tileThere, a not tileThere.

Функция findEmpty использует метод tileThere, чтобы определить, находится ли элемент на определенном месте. Метод tileThere вызывается для определения элементов слева, справа, снизу и сверху.

// Проверяем, находится ли элемент мозаики на определенном месте,
function tileThere (thisx, thisy) {
// Просматриваем элементы на предмет совпадения координат,
for (i=l;i<=15;i++) {
// Выясняем, совпадают ли значения положения
//по горизонтали,
if (_root["tile"+i]._x == thisx) {
// Совпадает ли положение по вертикали,
if (_root["tile"+i]._у == thisy) {
return true;
}
}} // Эти координаты соответствуют пустому квадратику,
return false;
}

После того как было решено переместить элемент, вызывается функция moveTile. Эта же функция используется, когда игрок перемешает элементы.

// Перемещаем элемент в определенном направлении,
function moveTile (tile, direction) {
if (direction == "above") {
_root[tile]._y -= tileDist;
} else if (direction == "below") {
_root[tile]._y += tileDist;
} else if (direction == "left") {
_root[tile]._x -= tileDist;
} else if (direction == "right") {
_root[tile]._x += tileDist;
}}

После того как контроль передается игроку, надо определить, по какому элементу щелкнули мышкой. Для этого вызывается функция tileUnderMouse.

// Определяем, по какому элементу щелкнул игрок,
function tileUnderMouse О {
for (i = l; i< = 15; i + +) {
if (_root["tile"+i].hitTest(_xmouse, _ymouse)) {
return (i);
}
}}

Сценарий в основной временной шкале заканчивается вызовом функции initGame и выводом на экран перемешанных элементов.

initGame();
stop();

Игрок взаимодействует с картинкой мозаики посредством клипа "actions», расположенным вне рабочего поля. Клип воспринимает щелчок мыши, определяет, по какому элементу щелкнул пользователь, и перемещает этот элемент.

onClipEvent (mouseDown) {
// Определяем, по какому элементу щелкнул пользователь.
tileClicked = _root.tileUnderMouse();
// Определяем, есть ли рядом пустое пространство.
emptySpace = _root.findEmpty("tile"+tileClicked);
// Перемещаем элемент на свободное место.
_root.moveTile("tile"+tileClicked, emptySpace);
}

К сведению

В рассмотренном варианте игры элементы мозаики расположены друг от друга на расстоянии 54 пиксела, а игровое пространство представлено сеткой 4x4. Если вы хотите изменить один из этих параметров, необходимо тщательно проверить код и внести необходимые изменения.

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

Игра будет интереснее, если программа будет определять, когда картинка полностью собрана, и на экране будет появляться кадр с поздравлением. Это можно сделать, сохранив исходное положение элементов в массиве и выясняя после каждого шага, в нужном ли месте оказался элемент. Когда все позиции совпадут, картинка собрана.