Воспоминания о Crimsonland 2: наведение на цель
27.02.2009, автор Stormit, рубрики: ActionScript, Flash игры, Игровые баннерыЭто небольшое дополнение к предыдущему посту, которое может сделать флеш-игру ещё интересней.
Очень часто разработчики, когда им нужно навести дуло на цель или направить монстра на жертву, делают это мгновенно. То есть, объект шёл в одну сторону, и тут бац.. идёт уже в другую. Это подходит для многих случаев и повышает контроль над ситуацией, мотивируя игрока проявить свои возможности, но иногда (а может и часто :)) нужно сделать чтобы дуло пушки или персонаж наводились на цель плавно.
Собственно небольшой код для реализации плавного поворота за мышкой (башня на слайде 1 крутится таким образом):
rotToMouseSpeed = 3;//скорость поворота function onEnterFrame() { mDx = _xmouse - body._x; mDy = _ymouse - body._y; mAngle = Math.atan2(mDy, mDx); //получаем угол между мышкой и башней в градусах mAngleD = mAngle / Math.PI * 180; //сколько градусов нехватает для полного поворота на мышь dAngleD = body._rotation - mAngleD; //без этой проверки башня будет неправильно крутиться //при переходе границы -180 и +180 градусов if (dAngleD > 180) { dAngleD = -360 + dAngleD; } else if (dAngleD < -180) { dAngleD = 360 + dAngleD; } //поворачиваем башню с нашей скоростью if(Math.abs(dAngleD) < rotToMouseSpeed) { body._rotation -= dAngleD; } else if(dAngleD > 0) { body._rotation -= rotToMouseSpeed; } else { body._rotation += rotToMouseSpeed; } }
Естественно вращение происходит вокруг центра клипа body, поэтому располагайте графику корректно.
Если вернуться к нашему Рэмбо, то же самое можно применить и к нему, нужно только учитывать ещё угол поворота самого клипа hero. Там упоминали что при переходе из крайне-левого положения в крайне-правое корпус неестественно дёргается - теперь этого не будет. Новый код выглядит теперь так (слайд 2):
var step = 2; var rotDirSpeed = 5; var rotToMouseSpeed = 7; onEnterFrame = function () { if (Key.isDown(Key.LEFT)) { hero._rotation -= rotDirSpeed; } else if (Key.isDown(Key.RIGHT)) { hero._rotation += rotDirSpeed; } var mDx = _xmouse - hero._x; var mDy = _ymouse - hero._y; //угол поворота между клипом hero и мышкой в градусах var mAngleD = Math.atan2(mDy, mDx) / Math.PI * 180; //угол поворота между башней и мышкой в градусах var dAngleD = hero._rotation + hero.body._rotation - mAngleD; //без этой проверки башня будет неправильно крутиться //при переходе границы -180 и +180 градусов if (dAngleD > 180) { dAngleD = -360 + dAngleD; } else if (dAngleD < -180) { dAngleD = 360 + dAngleD; } //поворачиваем башню с нашей скоростью if(Math.abs(dAngleD) < rotToMouseSpeed) { hero.body._rotation -= dAngleD; } else if(dAngleD > 0) { hero.body._rotation -= rotToMouseSpeed; } else { hero.body._rotation += rotToMouseSpeed; } //проверка на реализм поворота корпуса человека if(hero.body._rotation < -90) { hero.body._rotation = -90; } else if(hero.body._rotation > 90) { hero.body._rotation = 90; } var dirAngle = hero._rotation / 180 * Math.PI; if (Key.isDown(Key.UP)) { hero.foot.play(); hero._x += step * Math.cos(dirAngle); hero._y += step * Math.sin(dirAngle); } else if (Key.isDown(Key.DOWN)) { hero.foot.play(); hero._x -= step * Math.cos(dirAngle); hero._y -= step * Math.sin(dirAngle); } else { hero.foot.stop(); } }; onMouseDown = function () { hero.body.play(); };
Если у вас что-то не получается, убедитесь что на линейке присутствуют все необходимые символы, правильно вложены друг в друга, правильно названы и код прописан в нужных местах. Об этом говорилось накануне.
Ну и в жизни это стало немного по другому (слайд 3). Подобными вещами можно задавать сложность игры (помните, при старте: easy, medium, hard, nightmare). Конечно, попутно меняя скорость движения, время, очки и т.д.
Ещё пример как можно использовать плавный поворот:
Интересно на 87%




Прикольно! когда можно будет поиграть в окончательные варианты? с зомби оч интересно) музычку б подложить, мрачненькую, покряхкивания монстров при их смерти, ну и бонусы, пушки, нунчаки, мечи, адуванчики в качестве оружия:) плюс вести онлайн рекорды, эх:)
3-й слайд это почти окончательный вариант игрового баннера. Правда в оригинале главный герой бегал за мышкой. Хочу в следующей статье написать о том как запускать снаряды и разводить зомби.
какой то странный глюк в нижней влешке, иногда прицел плавно сам по себе съезжает в сторону ближе к башне %)
ещё очень не хватает инерции, все равно пушка дергается когда поворот из одной стороны сменяешь на другую.
Этот способ более ресурсозатратный чем если ипользовать векторное произведение векторов
>>иногда прицел плавно сам по себе съезжает…
Это не глюк, прицел выстраивается по центру если им не водить 5 секунд (осталось с баннера)
>>Этот способ более ресурсозатратный чем если ипользовать векторное…
класс Вектор ещё будет, потом сравним плюсы и минусы
Нее я про векторное произведение 2х векторов а не класс “вектор”. Или что ты имел в виду?
if (dAngleD > 180) {
dAngleD = -360 + dAngleD;
} else if (dAngleD < -180) {
dAngleD = 360 + dAngleD;
}
Спасибо! Когда-то голову сломал об это (компас рисовал, будто курсор выполняет функцию магнита).
Я про класс Vector, а как здесь работает векторное произведение векторов?
Все отлично работает, а как сделать выстрел, что бы цель поражать? Я так понимаю снаряд каким то образом по координатам должен совпасть с целью? Нельзя ли какой нибудь простенький пример на эту тему? Очень был бы благодарен.
“Я про класс Vector, а как здесь работает векторное произведение векторов?”
Просто смотришь знак векторного произведения и исходя из него поворачиваешь объект. При нахождении дэтерменанта матрицы координаты Z считать равными 0
2Georgi, самый простой вариант:
if (Bullet.hitTest(Zombie)) {
Zombie.gotoAndPlay(”dead”);
}
Bullet - это мувик пули, а Zombie - это мувик зомби. Только с пулей тоже надо что-то делать когда попадаем в зомби, например скрывать.
Domik, Спосибо буду пробовать!
Попробывал,ничего не выходит с пересечением объектов, создал мувик торпеды(tor) и мувик цели(zombie),которая при попадании должна измениться.В мувике торпеды написал код:
onClipEvent (load) {
speed=10;
onEnterFrame=function(){
_x+=speed;
if (tor.hitTest(Zombie)) {
Zombie.play();
}
}
}
торпеда проходит,а условие не выполняется. Подскажите пожалуйста где ошибка?
Georgi : У тебя же зомби находятся не внутри торпеды? Тогда возможно следует так
onClipEvent (load) {
speed=10;
onEnterFrame=function(){
_x+=speed;
if (this.hitTest(_parent.Zombie)) {
_parent,Zombie.play();
} } }
Если у тебя код весит на самой торпеде то не обязательно указывать при проверке if (tor.hitTest(Zombie)) - достаточно использовать this (он будет указывать на себя (на торпеду)), а вот если ты в торпеде поместил какой-то символ с которым будеш выполнять проверку тогда нужно будет указывать его имя.
Указывай правильный путь к Zombi, не забывай что они находятся на разной глубине клипов.
вот теперь дошло.спосибо. Все работает.
У меня опять вопрос, есле можно. Пытаюсь сделать игру. Такая раньше в автоматах(атракционы) была.Плывут корабли и с перескопа подлодки торпедами их топишь. Проблема вот в чем: Корабль плывет я в него попадаю он взрывается и тонет, на этом игра останавливается. а как сделать чтобы как то зациклить что ли, т.е обратно с начала она началась? Посоветуйте что нибудь пожалуйста!
Georgi - а зачем вам эта игра?
Вариант: раз в 5 секунд (например) создаётся программно корабль (attachMovie() или duplicateMovieClip()) и начинает двигаться. Если уходит за край экрана или умирает, просто удаляется (removeMovieClip()). Такая игра будет вечной, пока вы не определите условие для победы.
dedpbIxto-Зачем игра? да все просто: в детстве она мне очень нравилась, а на ее примере мне легче продвигаться в изучении флеш.
Stormit-Большое спосибо за подсказку теперь понял как.
Что то у меня не идет! Дублирую клип, он дублируется, задаю другое место-появляется два, но вот как это связать чтоб они ходили друг за другом? Например создаю мувик в нутри програмно задаю движение. В кадре дублирую-двое движуться, а как сделать так чтоб они постояно ходилили друг за другом? Примерно как в этой флешке самолеты постоянно появляются. На этом полностью застопорился. Помогите пожалуйста!
Респект!
Но почему вы никогда не выкладываете код полностью?