Игровой баннер типа “Шутер”
07.08.2008, автор Stormit, рубрики: ActionScript, Игровые баннерыНедавно я говорил, что обзавелся собственным игровым баннером. Теперь хочу рассказать, как я делаю подобные штуки.
Некоторые приемы уже были описаны ранее в статьях. Из нового здесь только такое физическое явление, как гравитация (новое на сайте). Можно было выкрутиться и сделать подпрыгивание бутылок анимацией, но мне захотелось внести больше разнообразия - пусть подпрыгивают на разную высоту, крутятся с разной скоростью, по разному в стороны разлетаются. Тем более, что сделать это программно совсем не сложно.
В нашем случае удобно хранить скорость в разложенном по осям виде. То есть не величина и угол поворота (как в управлении автомобилем), а в виде speedX и speedY. Далее каждую составляющую мы будем прибавлять к соответствующей координате (отрицательные значения смещают в другую сторону).
При равномерном движении можно просто прибавлять к координате число. Но введение понятия “Скорость” позволяет организовать замедление и ускорение.
Осталось разобраться с гравитацией. Это сила, которая с постоянной величиной действует вертикально вниз на все объекты (в программировании обычно на все незакрепленные объекты). То есть постоянно (по событию enterFrame) прибавляет какое-то значение к скорости (переменной speedY). Почему именно к скорости? Потому что к координатам применяется уже суммарный вектор всех сил (у нас пока только скорость и гравитация). Поэтому вначале применяем гравитацию к скорости, а потом скорость к координатам. Надеюсь, не намудрил.
Теперь по порядку:
- Рисуем объект, который должен подскакивать - бутылка. Называем его target.
- Слоем выше пишем код:
lev = 0; gravity = 1;//величина гравитации подбирается (визуально зависит от frameRate) function placeTarget() { lev++; var d = target.duplicateMovieClip("t" + lev, lev); d.speedY = -15 - Math.random() * 5;//начальные значения скорости d.speedX = Math.random() * 4;// плюс небольшой разброс d.rotSpeed = (Math.random() - .5) * 20;//случайный шаг для вращения if (Math.random() < .5) { d.speedX = -d.speedX;//больше разницы - отражаем бутылку по горизонтали } d.onEnterFrame = function() { this.speedY += gravity; this._y += this.speedY; this._x += this.speedX; this._rotation += this.rotSpeed; if (this._y > target._y) { this.removeMovieClip();//удаляем если улетела ниже экрана } }; } count = 0; onEnterFrame = function () { if (count++ > 15) {//добавляем бутылку каждый 15-й кадр count = 0; placeTarget(); } };
Символ с бутылкой лучше сдвинуть вниз за пределы флэшки, чтобы не было видно оригинала. Уже хорошо, но бутылка вылетает всегда из одной точки. Если у нас широкий баннер, много места будет не использовано.
- Поэтому на уровне бутылки добавляем символ box в виде полоски (центр слева). И располагать дубликаты теперь будем случайно по ее длине. В функции placeTarget нужно дописать Одну строку:
d._x = box._x + Math.random() * box._width;
- Вот так это выглядит, если отъехать камерой в космос.
- Чтобы интереснее было играть, устроим борьбу штрафов и бонусов. Бутылки выбивать можно, а пачки с соком нельзя. Поэтому в символе target теперь 2 кадра: в первом сок, во втором спиртное. Теперь эти символы, бутылку и сок, назовем obj. А чтобы еще интереснее было, сделаем несколько видов бутылок - внутри клипа obj (бутылка) тоже 3 кадра, в каждом свое состояние. Из рисунка выше должно быть понятно.
- Не сильно доверяя функции Math.random(), я ввел переменные pos и neg (позитив и негатив), которые показывают, сколько подряд вылетело бутылок или пачек с соком. Сейчас может вылететь максимум 5 бутылок подряд, потом обязательно сок. Полный код теперь такой:
lev = 0; gravity = 1; pos = 0; neg = 0; function placeTarget() { lev++; var d = target.duplicateMovieClip("t" + lev, lev); d.speedY = -15 - Math.random() * 5; d.speedX = Math.random() * 4; d.rotSpeed = (Math.random() - .5) * 20; d._x = box._x + Math.random() * box._width; if (Math.random() < .5) { d.speedX = -d.speedX; } if ((Math.random() < .5 && pos < 1) || neg >= 5) { d.gotoAndStop(1);//пакет с соком pos++; neg = 0; } else { d.gotoAndStop(2);//бутылка var t = Math.random();//дополнительно случайно определяем тип бутылки if(t < .33) { d.obj.gotoAndStop(1); } else if(t < .66) { d.obj.gotoAndStop(2); } else{ d.obj.gotoAndStop(3); } neg++; pos = 0; } d.onEnterFrame = function() { this.speedY += gravity; this._y += this.speedY; this._x += this.speedX; this._rotation += this.rotSpeed; if (this._y > box._y) { this.removeMovieClip(); } }; } count = 0; onEnterFrame = function () { if (count++ > 15) { count = 0; placeTarget(); } };
- Рисуем прицел - символ cursor. Внутри символа анимация выстрела. В первом кадре:
stop();
- Рисуем взрыв - символ crash. Его можно нарисовать руками, а можно использовать программный вариант. Я использую комбинированный - жидкость прорисована покадрово руками, а осколки стекла дублируются и разлетаются программно. Символ crash будет общим для всех. Все отличия будут уже внутри него. Если для разного отображения бутылок я использовал прямое назначение, то здесь символ сам определяет каким ему быть. Для этого (дальше при создании взрыва) ему будет назначаться переменная type. А потом все внутренние символы (всплеск и очки) будут при появлении считывать эту переменную с родителя и переводить себя в нужный кадр (что-то типа: gotoAndStop(_parent.type)). Подробнее и нагляднее об этом можно почитать здесь (раздел “Полезности”, слайд 25-й). Главный плюс такого подхода - символам не обязательно быть в первом кадре чтобы самоопределиться - они могут появиться со второго кадра и более.
- Собираем все вместе. Добавилась переменная для хранения очков.
Итого, имеем символ с бутылками (target), символ с прицелом (cursor), символ взрыва (crash), символ - полоску (box). Все объекты после дублирования помещаются в стек (массив all). По клику перебираем их и проверяем на пересечение с курсором. Если есть попадание, определяем тип объекта, создаем взрыв (сообщаем ему этот тип), добавляем очки, проверяем на выигрыш и удаляем объект из стека. Если объект улетает вниз экрана, он тоже удаляет себя из стека (функция removeObj()).
Код в полном объеме теперь выглядит так:score = 0; all = [];//тут хранятся все летающие объекты lev = 0; gravity = 1; pos = 0; neg = 0; count = 0; crash._visible = false; cursor.swapDepths(12002432);//прицел выше всех бутылок Mouse.hide(); function placeTarget() { lev++; var d = target.duplicateMovieClip("t" + lev, lev); d.speedY = -15 - Math.random() * 5; d.speedX = Math.random() * 4; d.rotSpeed = (Math.random() - .5) * 20; d._x = box._x + Math.random() * box._width; if (Math.random() < .5) { d.speedX = -d.speedX; } if ((Math.random() < .5 && pos < 1) || neg >= 5) { d.gotoAndStop(1); pos++; neg = 0; } else { d.gotoAndStop(2); var t = Math.random(); if(t < .33) { d.obj.gotoAndStop(1); } else if(t < .66) { d.obj.gotoAndStop(2); } else{ d.obj.gotoAndStop(3); } neg++; pos = 0; } d.onEnterFrame = function() { this.speedY += gravity; this._y += this.speedY; this._x += this.speedX; this._rotation += this.rotSpeed; if (this._y > box._y) { removeObj(this); this.removeMovieClip(); } }; all.push(d); } function removeObj(obj){ var i = all.length; while(i--) { if(all[i] == obj) { all.splice(i, 1); } } } function placeCrash(x, y, _t) { lev++; var d = crash.duplicateMovieClip("c" + lev, lev); d.type = _t; d._x = x; d._y = y; } onEnterFrame = function () { if (count++ > 15) { count = 0; placeTarget(); } cursor._x = _xmouse; cursor._y = _ymouse; }; onMouseDown = function(){ cursor.play();//анимация выстрела var i = all.length; while(i--) { var curT = all[i]; if(curT.hitTest(_root._xmouse, _root._ymouse, true)) { if(curT._currentframe == 1) { var type = 1; } else{ var type = curT.obj._currentframe + 1; } placeCrash(curT._x, curT._y, type); if(curT._currentframe == 2) { score += 20; if(score >= 100) { trace("Вы победили"); } }else { score -= 25; score = (score < 0)? 0 : score; } curT.removeMovieClip(); all.splice(i, 1); } } }
- Осталось добавить приятный фон и текстовое поле, которое будет следить (или назначать напрямую) за переменной score.
Тема с бутылками конечно не единственная, стрелять можно по чему угодно: по яблокам, летающим тарелкам, мячикам жонглера. Можно довести идею до абсурда. Например, черепахи, летающие на воздушных шариках - стреляем по шарикам и слоган - “Рожденный ползать - летать не должен!”.
Интересно на 68%




забыл еще добавить — по завершению игры обнулять очки. А то после 100 очков, каждый следующий выстрел по бухлу — МОЛОДЕЦ. Видать это зависимость, пристрастился и нужно совсем немного =).
Это не суть важно, но более точно координата при ускоренном движении меняется не линейно по времени, а по формуле - x += speedx * time + accel * time * time * 0.5, где speedx это скорость в предудыщей координате, а “accel * time * time * 0.5″ это путь пройденный точкой под влиянием ускорения.
нелинейно меняется не x, а y – и автор правильно все считает, – вместо 1ого уравнения пишет 2, и получается численное интегрирование, в данных условиях весьма приемлемое — хотя ваша формула все же более точная (и как раз работает при постоянном ускорении — наш случай).
Что то вы палку перегибаете - смотрите проще, выглядит натурально? натурально, а по какой формуле это высчитано - неважно, главное результат!
Зритель смотрит не код программы, а то как это выглядит на экране! 
Прикольно

А главное, как это просто выглядит со стороны
Может показаться, что подготовка клипа с примерами заняла больше времени, чем изгоовление баннера
ps


хотел спросить про такую ситуацию, может быть тоже есть какая то хитрость
Есть изображение ветки дерева, довольно детальное, т.е. веточки-листики нарисованы отчетливо
Как проще всего анимировать появление “дерева” из-за горизонта и “вырастание” листиков на веточке?
В моем случае, переданный мне дизайнером исходник представляет из себя всего несколько слоев, т.е. для анимации каждого листика надо резать картинку или все-таки есть хитрость?
Вот картинка слоев имеющегося исходника: http://s42.radikal.ru/i098/0808/80/176b8dd649d4.jpg
спасибо за доходчивую информацию, не мог ты объяснить как ты сделал появление красной плашки со словом “молодец”, програмно или анимировал?
Достаточно креативненько. Может пригодиться
to Hyzhak
Да, забыл сброс сделать. Он так же как и здесь реализован: http://xitri.com/2008/04/28/loop-background3-game-banner.html (шаг 12, 13)
to unodj
Наверное проще всего анимировать маску - шейпом или покадрово
to zlodey
Плашка появляется шейп-твиннингом. Сделал захлест краев для пущей эффектности.
Тема на самом деле оч интересная, подумать есть о чем, но подход сложный, попроще никак низя? для простго блогера это архи сложно.
Конечно можно.
Можно сделать анимацией как подскакивает и крутится бутылка (все в одном символе). Потом сделать несколько копий и проверять все по клику на hitTest c координатами мыши (или вообще бутылки кнопками сделать). И проще всего открывать ссылку по первому удачному попаданию.
Думаю такой вид баннеров может стать новой тенденцией в интернет-рекламе
to Макс: ну тут вроде, не просто блогеры — тут флешеры.
to Hyzhak: тогда уж не просто флешеры, а флешеры-аниматоры… и сочувствующие
Михаил, сегодня заметил рекламу одного сайта знакомств, уже эксплуатируют

Правда сюжета никакого, тупо падают рандомные фотографии людей, вместо курсора мышки прицел и надпись “поймай свой идеал” или что то в этом роде
ну про гравитацию я думаю многие слышали еще со школы
Stormit, ты же сам писал что “водка - вредно”, а в этом варианте все совсем наоборот =)
Очки “+” за спиртное, а “-” за сок =)
Все правильно
“+” за уничтожение спиртного
На самом деле настолько забавная штука, что каждый раз у Дизайнфрика её прохожу))
Блин, а я чет тупил… Хорошо, что все доходчиво расписано, как раз для меня)))
спасибо прикольно я попробую создать када получится или нет отпишуся! спс За инфу!!!
[…] автор сайта преподносит интересную информацию на следующие темы […]
Уважуха за составление и постинг таких материалов. Я Вас очень поддерживаю за эти материалы. Кул
Я вот не дружу с флешем, но наш дезингер попробует повторить этот эксперимент;) Спасибо
Классный банер)
Отличный материал и банер, спасибо!)
Флеш баннеры скоро потеснят анимацию и т.п., единственный минус - многие пользователи имеют слабый инет в настоящее время, хотя это не важно
Норм игра, тока быстро надоедает. Это на каком языке программный код?
Прикольно…А вообще у Вас очень хороший блог, информация всегда новая и интересная, это очень привлекает. Приглашаю пообщаться на форум с Вашими любимыми женщинами:)
Ух-ты, какой классный сайт. И урок интересный похоже на шапку сайта www.rangers.ru
Интересно и позновательно, а будет еще что-то по этой теме?
Блог сдулся? Жаль…
Вернись, солнышко, мы тебя любим.
Добавил в закладки. Теперь буду почаще читать!
Chital pro yeto uzhe na kakom to drugom sajte, no u vas gorazdo prikolmznej napisano
Кажись блог накрылся медным тазом и автор на него забил - уже месяц никакой активности, или же с автором что то случилось,не дай бог конечно. Будем надеятся ,что это не так.
Да все нормально.
Просто отпуск и новая игра забирают все время
Отличная статья.Респект автору.
Добавил в Закладки, очень интересный блог, таких бы по больше…
Этот сайт еще жив?
блог интересный
Сколько полезного нашел для себя на блоге
Народ очень интересный блог согласен с вами совсеми
Я новичок и мало что понимаю.Хочу узнать: куда вставлять код, и если делаю flash-игру
на Macromedia Flash 8
Делаи и все получиться, почитаи литературу.
Как привязать размер объекта к размеру окна во FLASH, т.е. чтобы увеличивая размер окна (разворачивая или сужая) соответственно увеличивалось изображение?
балин, у меня функция с выпрыгиванием не работает,. Запускается без ошибок, но бутылка просто стоит, пробую задать анимацию ни вращения, ни падения… Подскажите как это исправить.
некто-то пошел дальше, и сделал шутер на двоих:
http://www.newgrounds.com/portal/view/514433
Было бы ещё круче, если бы противник был реальный
Добрый день. Выложите пожалуйста исходник. (просто не могу разобраться)
А можно исходник посмотреть? Что то не очень выходит… (
Привет всем. Я всё создал, всё прелесть балгодарю админа… Я хотел бы спросить а как зделать так что бы эта игра была с меню, и мела несколько уровней? Плиз подскажите!
Еще раз привет. Тоже все получилось, но немного другая версия. Вот там можно и меню и несколько уровней и т.д. Вот если бы уроки можно было пользователям писать как на демиарте было бы круто!