В данной статье Вы узнаете как написать или создать игру пятнашки online с помощью action script в формате flash для публикации в сети интернет. Для успешного знакомства с этим материалом Вам необходимы первичные представления о языке программирования action script (очень похож на C#) , а так же опыт работы с Adobe Flash или другими инструментальными средствами.
Наконец то Мы приступил к написанию серии статей о разработке и создании игр, после непродолжительного перерыва. И так приступим...
Об алгоритме игры и основных ее принципах было описано в предыдущей статье. Так что, если Вы еще не ознакомились с ней, то рекомендуем пройти краткий инструктаж на этой страничке (об игре пятнашки) или поискать информацию в сети интернет.
Этап первый. Создадим проект и в нем укажем класс MainApp.as, который будет у нас основным. Для каждого класса в action script создается соответствующий файл обернутый в package:
Package { // импорт различных библиотек Import flash.events.event; import flash.events.Event; import flash.display.Sprite; import flash.display.Graphics; import flash.events.MouseEvent; import flash.display.MovieClip; import cell; Public class MainApp extends MovieClips // наш класс наследующий основные свойства от класса MovieClips (Кинокадров) { // тело нашего класса } }
И еще создадим второй класс и назовем его cell.as. В этом классе опишем свойства игровой кости (ячейки) всего их у нас 15
Этап второй. Создадим два кадра. Первый кадр будет у нас игровым, на котором расположено игровое поле (доска для пятнашек), кнопка «новая игра» и текстовое поле для отображения счетчика ходов. Для их создания перетащите, расположите (и нарисуйте) из панели инструментов текстовое поле, прямоугольник...
На втором кадре все тоже самое, только добавим надпись «Вы Выиграли». Можно еще создать. Необходимости создания третьего кадра с надписью «Вы проиграли» нет необходимости.
Этап третий. Рассмотрим алгоритм создания игры на action script. И так алгоритм:
1. Мы должны нарисовать игровое поле и заполнить его пятнашками. Для этого создадим два массива размером в 16 элементов. Один эталонный и второй игровой (текущий). В эталонном будут храниться элементы соответствующие правильному (по порядку) расположению фишек.
2. Затем Мы должны перемешать игровой массив. Учтите, что простое перемешивание с помощью рандомной функции (Randomize) в данном случае на подойдет, т.к. можно создать такую комбинацию, что ее решение будет невозможно. Почему? Если Вы хотите узнать ответ на этот вопрос, то смотрите предыдущую статью. Перемешивание будет заключаться в произвольном перемещении пятнашек из начального (правильного положения) в конечное игровое.
3. Мы должны отследить нажатие левой клавиши мыши, определить игровую фишку и переместить ее на место пустой клетки в зависимости от игрового положения.
4. После перемещения нам необходимо проверить на окончание игры, т.е. победы. Для этого необходимо сравнить эталонный массив с текущим и при совпадении всех его элементов вернуть результат равный истине.
Этап четвертый. Написание исходного кода.
Объявим в классе MainApp три глобальных элемента:
private var field:Array=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]; // игровое поле сохраняющее текущую комбинацию private var field_mask:Array=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]; // эталонное поле, можно типа const (маска) private var steps:Number=0; // счетчик числа шагов
Конструктор нашего класса:
public function MainApp() { shake_board(); // перемешаем игровые фишки Create(); // создадим визуальные элементы (графическое представление костяшек) this.addEventListener(MouseEvent.CLICK,addetClikHandler); // обработчик нажатия кнопки мышки this.gotoAndStop(1); // установим 1-й кадр }
Функция создания графического представления костяшек (пятнашек, фишек). В этой функции нам необходимо создать пятнадцать костяшек + одно пустое поле. Присвоим каждой название как конкатенация строк: “cell_”+индекс ячейки –> (cell_1,…,cell_16)
private function Create() { var tmp:cell; var x0,y0,dx0,dy0:Number; dx0=board.width/4.0; dy0=board.height/4.0; for(y0=0;y0<4;y0++) { for(x0=0;x0<4;x0++) { tmp = new cell(); tmp.x=x0*dx0+2; tmp.y=y0*dy0+2; tmp.name="cell_"+field_mask[y0*4+x0]; tmp.gotoAndStop(field[y0*4+x0]); board.addChild(tmp); } } }
Функция обработки нажатия кнопки мышки:
// По событию нажатия кнопки private function addetClikHandler(event:MouseEvent):void { var str:String = event.target.name; update_board_elements(); // переместим фишки если необходимо if(str.substr(0,5)=="cell_") // если игрок нажал на одну из 15 игровых фишек, увеличим число ходов steps++; this.txt_step.text="Steps: "+steps; if(event.target.name=="new_game") // если игрок нажал на кнопку «новая игра» { this.gotoAndStop(1); reinit(); } }
Функция проверки на успешное решение головоломки. Простое сравнение двух массивов:
private function check_win():Boolean { for(var i:Number=0;i<15;i++) if(field[i]!=field_mask[i]) return false; return true; }
Функция обработки игрового нажатия мышки и перемещения пятнашки на пустое пространство. Заметьте, что эта функция не была оптимизирована для более простого и наглядного ее понимания
При успешной проверки на перемещение пятнашки, мы меняем элементы игрового массива fields местами. Пустому полю у нас соответствует число 16, следовательно, если соседняя ячейка содержит это число, то эти костяшки можно поменять местами. На рис. 3 показана идея алгоритма.
// переместим пятнашки (exchange fithting) private function update_board_elements():void { var x0,y0,dx0,dy0:Number; // преобразуем координаты мыши к координатам сетки dx0=board.width/4; dy0=board.height/4; x0=Math.floor((stage.mouseX-board.x)/dx0); y0=Math.floor((stage.mouseY-board.y)/dy0); // теперь проверим есть ли рядом пустое поле и сдвинем его туда // если нужно сдвинуть вправо? if(x0<3) { if(field[x0+1+y0*4]==16) // ячейка пустая? { field[x0+1+y0*4]=field[x0+y0*4]; field[x0+y0*4]=16; refresh_display_elements(1,x0,y0); // теперь перерисуем эти две фишки на игровом поле } } // в лево? if(x0>0) { if(field[x0-1+y0*4]==16) { field[x0-1+y0*4]=field[x0+y0*4]; field[x0+y0*4]=16; refresh_display_elements(0,x0,y0); } } // может вверх? if(y0>0) { if(field[x0+(y0-1)*4]==16) { field[x0+(y0-1)*4]=field[x0+y0*4]; field[x0+y0*4]=16; refresh_display_elements(2,x0,y0); } } // или все таки вниз? if(y0<3) { if(field[x0+(y0+1)*4]==16) { field[x0+(y0+1)*4]=field[x0+y0*4]; field[x0+y0*4]=16; refresh_display_elements(3,x0,y0); } } if(check_win()==true) // проверим на окончание игры (решение головоломки) { this.gotoAndStop(2); // покажем кадр завершения игры } }
Функция для перерисовки элементов пятнашек, при их перемещении. В этой функции мы перемещаем фишку в одну из четырех сторон (вверх, вниз, влево или вправо). На самом деле мы просто меняем у соответствующих ячеек отображаемый текст, т.е. для клетки где было пустое мы установим значение перемещаемой, а на месте перемещаемой установим пустое значение. Тут можно было бы сделать гораздо проще, пройти по всем элементам и установить их отображаемый текст на соответствие игровому массиву.
private function refresh_display_elements(type,x0,y0:Number):void { var cell_1:cell; var cell_0:cell; var pos_1,pos_0:Number; switch(type) // тип перемещения { case 0: pos_1=x0+y0*4+1; pos_0=x0-1+y0*4+1; cell_1=cell(board.getChildByName("cell_"+pos_1)); cell_0=cell(board.getChildByName("cell_"+pos_0)); cell_1.gotoAndStop(field[pos_1-1]); cell_0.gotoAndStop(field[pos_0-1]); break; case 1: pos_1=x0+y0*4+1; pos_0=x0+1+y0*4+1; cell_1=cell(board.getChildByName("cell_"+pos_1)); cell_0=cell(board.getChildByName("cell_"+pos_0)); cell_1.gotoAndStop(field[pos_1-1]); cell_0.gotoAndStop(field[pos_0-1]); break; case 2: pos_1=x0+y0*4+1; pos_0=x0+(y0-1)*4+1; cell_1=cell(board.getChildByName("cell_"+pos_1)); cell_0=cell(board.getChildByName("cell_"+pos_0)); cell_1.gotoAndStop(field[pos_1-1]); cell_0.gotoAndStop(field[pos_0-1]); break; case 3: pos_1=x0+y0*4+1; pos_0=x0+(y0+1)*4+1; cell_1=cell(board.getChildByName("cell_"+pos_1)); cell_0=cell(board.getChildByName("cell_"+pos_0)); cell_1.gotoAndStop(field[pos_1-1]); cell_0.gotoAndStop(field[pos_0-1]); break; } }
Функция для перемешивания пятнашек. Для перемешивания воспользуемся перестановкой из начального положения в произволное и используем двести ходов. Она довльно проста и имитирует работу игрока, пытающегося перемешать клетки самостоятельно.
private function shake_board():void { var rnd:Number; var x0,y0:Number; x0=3; y0=3; // небольшое приготовление field[x0+y0*4]=field[x0+(y0-1)*4]; field[x0+(y0-1)*4]=16; y0--; field[x0+y0*4]=field[x0-1+y0*4]; field[x0-1+y0*4]=16; x0--; for(var i:Number=0;i<200;i++) { rnd=Math.floor((Math.random()*11)/3); // с помощью случайной функции выберем направление перемещения на i-м шаге switch(rnd) { case 0: if(x0>0) { field[x0+y0*4]=field[x0-1+y0*4]; field[x0-1+y0*4]=16; x0--; } break; case 1: if(x0<3) { field[x0+y0*4]=field[x0+1+y0*4]; field[x0+1+y0*4]=16; x0++; } break; case 2: if(y0>0) { field[x0+y0*4]=field[x0+(y0-1)*4]; field[x0+(y0-1)*4]=16; y0--; } break; case 3: if(y0<3) { field[x0+y0*4]=field[x0+(y0+1)*4]; field[x0+(y0+1)*4]=16; y0++; } break; } } }
И наконец класс для описания клетки (костяшки, пятнашки):
package { import flash.display.MovieClip; import flash.events.MouseEvent; public class cell extends MovieClip { public function cell() { this.gotoAndStop(1); } public function eventOverHandler(event:MouseEvent):void { this.gotoAndStop(4); } public function eventOutHandler(event:MouseEvent):void { this.gotoAndStop(1); } } }
В итоге у нас должна получиться подобная картинка:



