Уроки Flash: Pac-ManИсточник: demiart Ra1nbow
В этом уроке я расскажу Вам, как сделать легендарную игру - Pac-Man. Будет показано, как делать уровни с помощью двумерного массива, как заставить пак-мана бегать по уровню, будет код искусственного интеллекта, то есть будет код перемещения врага по уровню, но сразу хочу предупредить, что здесь на рассказано, как сделать несколько уровней, и как организовать подсчет очков. Подготовка. Теперь преступим к подготовке нашей сцены. Для начала зададим размер сцены. Сделаем ширину 300 пикселей, и высоту 300(см. рис.1). Рис. 1. Параметры сцены. Теперь создадим на сцене квадрат со стороной 30(в качестве заливки я выбрал светло-серый цвет, а обводку сделал черным). Затем выделите квадрат и нажмите F8. Дальше сделайте, как показано на рис. 2. На сцене теперь лежит Movie Clip, два раза щелкните по нему. Вы оказались внутри объекта square. Слой, который там уже есть, назовите - square, а затем создайте еще два слоя - "sc" и "object". Затем в слое "square" и "sc" сделайте еще по два keyframe’а, а в слое "object" только в третьем кадре(см. рис. 3). После этого в каждом кадре слоя "sc" пропишите stop(). Затем во втором кадре слоя "square" залейте квадрат черным цветом, а в третьем кадре слоя "object" нарисуйте оранжевый кружок размера приблизительно 13x13 посредине квадрата. То есть в первом кадре у вас должно получиться серый квадрат, во втором черный, а в третьем серый квадрат, с оранжевым кружочком посредине. Теперь настало время нарисовать самого Pac-man’а. Для этого нажмите Ctrl+F8. И в поле name напишите hero Слой "Layer 1" переименуйте в "hero", нарисуйте желтенький кружок размера 25x25, и задайте ему координаты по x и y 0. Затем нажмите два раза F5, а затем F6, с делайте "надрез", как показано на рисунке ниже, после чего нажмите F5 еще раз. В итоге timeline объекта "hero" должна выглядеть как на рис. 4. Далее нажмите Ctrl+F8, и заполните форму Creating New Symbol, как показано на рисунке 5. Слой "Layer 1" переименуйте в "hero". И перетащите из библиотеки объект "hero" и задайте ему координаты по x и y 0. Затем нажмите F6, выделите наш кружок, далее нажмите Modify -> Transform -> Fip Horizontal. Затем нажмите F6 два раза. Затем перейдите в 3 кадр нажмите один раз на наш кружок и нажмите Ctrl+Shift+7(поворот на 90 градусов против часовой стрелки), затем перейдите в 4 кадр и нажмите один раз на наш кружок и нажмите Ctrl+Shift+9(поворот на 90 градусов по часовой стрелке). Затем сделайте объект "enemy", также как делали "hero", а заем ‘enemy_dyn" так же как "hero_dyn". Значение поля Indetifier должно быть enemy Все, мы подготовили все, что нужно нам для создания игры. Теория. Теперь я расскажу Вам, как будем делать уровни. А делать будем их просто - с помощью двумерной матрицы(массива). И матрица каждого уровня будет выглядеть примерно вот так: [1, 1, 1, 1, 1, 1, 1, 1, 3, 1], Где 1 - это стена, 2 - это наш герой, 3- это враг, а 0 - проход. Написание кода. Выйдите на сцену, у вас там должен быть один квадратик, если есть удалите его. Теперь нажмите F9.
CODE
function number_not(a:Number, b:Number) { if (a>b // a<b) { return true; } } //Переменные posx и posy - это коэффециенты координат, для простоты дальше называются координатами function creatinglevel():Void { // функция, которая загружает уровень // увеличиваем число отвечающее за место клетки // m,r - место, ряд // присваиваем месту и ряду соответствующие значения var r:Number = j; var m:Number = i; // начинем загружать уровень. "square" - имя клетки в блиотеке(linkage). ["r_"+j+"_m_"+i] - новое имя клетки (r_ряд_m_место). Координата по х расчитывается место*30, по у: ряд*30 this.attachMovie("square", ["r_"+j+"_m_"+i], (10*j+i), {_x:m*30, _y:r*30}); // проверяем что должно быть: кружок(0) или барьер(1) switch (map[j][i]) { case 2 : // Достаем игрока из библиотеки и ставим по центру клетки this.attachMovie("hero", "hero", (max*max+1), {_x:m*30+2.5, _y:r*30+2.5}); //posx и posy позиция игрока по х и у соответственно hero.posx = i; hero.posy = j; hero.stop(); break; case 3 : //Достаем компьютера из библиотеки и ставим по центру клетки this.attachMovie("enemy", "enemy", (max*max+2), {_x:m*30+2.5, _y:r*30+2.5}); //posx и posy позиция компьютера по х и у соответственно enemy.posx = i; enemy.posy = j; //lastx и lasty предидущая позиция компьютера по х и у соответственно, служит при алгоритме движения компьютера enemy.lastx = i-1; enemy.lasty = j; enemy.stop(); break; case 1 : _root["r_"+j+"_m_"+i].gotoAndStop(2); break; case 0 : _root["r_"+j+"_m_"+i].gotoAndStop(3); break; } i++; // Переключаемся на следующий ряд, при том условии, что место равно максмальное -1 if (i == max) { i = 0; j++; } // Выходим из функции(очищая интервал), если кол-во рядов равно максимальному if (j>=max) { // Убираем блок функции game _root.block = 0; // очищаем интервал clearInterval(creatingInterval); } } function game():Void { // функция, отвечающая за движение игрока и компьютера и следящая за выигрышем, проигрышем if (block == 0) { // работает только в том случае,если снята блокировка // Если герой млм враг коснулись кружочка, то убираем его. for (var i = 0; i<max; i++) { for (var j = 0; j<max; j++) { if (map[j][i] == 0 && (hero.posx == i && hero.posy == j) // (enemy.posx == i && enemy.posy == j)) { _root["r_"+j+"_m_"+i].gotoAndStop(1); _root.map[j][i] = 4; } } } //__________Движение__________ //=-=-=-=-=-=ИГРОК=-=-=-=-=-= if (Key.isDown(Key.LEFT)) { // при нажатии левой стрелки смотрим, можем ли мы пойти налево(проверяем, чтобы значение map[ряд][место-1] не было равно 1 с помощью функции number_not) if (number_not(map[_root.hero.posy][_root.hero.posx-1], 1)) { //Если учлове выполняется, то мувик игрока идет во второй кадр _root.hero.gotoAndStop(2); // координата игрока по x уменьшается _root.hero.posx--; // перемещаем игрока _root.hero._x = _root.hero.posx*30+2.5; } } //Остальные стрелки обрабаываются так же как и левая стрелка if (Key.isDown(Key.RIGHT)) { if (number_not(map[_root.hero.posy][_root.hero.posx+1], 1)) { _root.hero.gotoAndStop(1); _root.hero.posx++; _root.hero._x = _root.hero.posx*30+2.5; } } if (Key.isDown(Key.DOWN)) { if (number_not(map[_root.hero.posy+1][_root.hero.posx], 1)) { _root.hero.posy++; _root.hero.gotoAndStop(4); _root.hero._y = _root.hero.posy*30+2.5; } } if (Key.isDown(Key.UP)) { if (number_not(map[_root.hero.posy-1][_root.hero.posx], 1)) { _root.hero.posy--; _root.hero.gotoAndStop(3); _root.hero._y = _root.hero.posy*30+2.5; } } //=-=-=-=-=-=Компьютер=-=-=-=-=-= //лево //Смотрим может ли компьютер пойти налево(проверяем, чтобы значение map[ряд][место-1] не было равно 1) if (number_not(map[_root.enemy.posy][_root.enemy.posx-1], 1)) { //И смотрим, чтоб координата по х куда идет компьютер не была равна предидущей коорденате по х if (number_not(_root.enemy.posx-1, _root.enemy.lastx)) { // если всеудовлетворяет условию, то в массив moveenemy добовляем 1 - это значит, что компьютер может пойти на лево. Это будет использовано дальше, когда будет расчитываться следующее передвижение компьютера moveenemy.push(1); } } //Аналогично рассматриваем и остальное //право if (number_not(map[_root.enemy.posy][_root.enemy.posx+1], 1)) { if (number_not(_root.enemy.posx+1, _root.enemy.lastx)) { moveenemy.push(2); } } //Низ if (number_not(map[_root.enemy.posy+1][_root.enemy.posx], 1)) { if (number_not(_root.enemy.posy+1, _root.enemy.lasty)) { moveenemy.push(3); } } //Верх if (number_not(map[_root.enemy.posy-1][_root.enemy.posx], 1)) { if (number_not(_root.enemy.posy-1, _root.enemy.lasty)) { moveenemy.push(4); } } //Если длинна массива равна 0, тогда ы понимаем, что компьютер попал в тупик if (moveenemy.length == 0) { //для этого мы ввели переменные lastx0 и lasty0. Они служат буффером. в них кидаем значения posx и posy соответственно _root.enemy.lastx0 = _root.enemy.posx; _root.enemy.lasty0 = _root.enemy.posy; //Затем координате компьютера posy и posx присваиваем координаты lasty и lastx _root.enemy.posy = _root.enemy.lasty; _root.enemy.posx = _root.enemy.lastx; //Затем перемещем компьютера на эти координаты _root.enemy._x = _root.enemy.posx*30+2.5; _root.enemy._y = _root.enemy.posy*30+2.5; //Затем предидущем значениям координат присваиваем значения из буффера _root.enemy.lasty = _root.enemy.lasty0; _root.enemy.lastx = _root.enemy.lastx0; } //Если длинна массива больше 0 if (moveenemy.length>0) { //переменной napr присваиваем значение рандом от длинны массива napr = random(moveenemy.length); //теперь проверяем чему равно знаение массива moveenemy от napr switch (moveenemy[napr]) { //Если 1, то компьютера перемещаем налево case 1 : //Пердидущем координатам присваиваем нынешне _root.enemy.lasty = _root.enemy.posy; _root.enemy.lastx = _root.enemy.posx; //Теперь изменяем координату по х _root.enemy.posx--; // и перемещаем компьютера на его новые координаты _root.enemy._x = _root.enemy.posx*30+2.5; _root.enemy._y = _root.enemy.posy*30+2.5; //так же мувик enemy перемещаем во второй кадр _root.enemy.gotoAndStop(2); break; //Если 2, то компьютера перемещаем направо case 2 : _root.enemy.lasty = _root.enemy.posy; _root.enemy.lastx = _root.enemy.posx; _root.enemy.posx++; _root.enemy._x = _root.enemy.posx*30+2.5; _root.enemy._y = _root.enemy.posy*30+2.5; _root.enemy.gotoAndStop(1); break; //Если 3, то компьютера перемещаем вниз case 3 : _root.enemy.lasty = _root.enemy.posy; _root.enemy.lastx = _root.enemy.posx; _root.enemy.posy++; _root.enemy._x = _root.enemy.posx*30+2.5; _root.enemy._y = _root.enemy.posy*30+2.5; _root.enemy.gotoAndStop(4); break; //Если 4, то компьютера перемещаем наверх case 4 : _root.enemy.lasty = _root.enemy.posy; _root.enemy.lastx = _root.enemy.posx; _root.enemy.posy--; _root.enemy._x = _root.enemy.posx*30+2.5; _root.enemy._y = _root.enemy.posy*30+2.5; _root.enemy.gotoAndStop(3); break; } //Очищаем массив moveenemy moveenemy = []; } } } //Матрица уровеня var map:Array = [[1, 1, 1, 1, 1, 1, 1, 1, 3, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 2, 1], [1, 1, 1, 1, 1, 1, 1, 1, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]]; // размер поля(ширина, высота) var max:Number = 10; //Массив отвечающий за передвижение компьютера(в нем храняться направления) moveenemy = new Array(); i = 0; j = 0; // интервал функции game var gameDuration:Number = 95; // интервал функции creatinglevel var loadDuration:Number = 0; //Запускаем функции creatinglevel и game с помощью интервала var creatingInterval:Number = setInterval(this, "creatinglevel", loadDuration); var gameInterval:Number = setInterval(this, "game", gameDuration); Вот что должно у нас получиться, только без кнопки start Вот вобщем и конец. |