Воспоминания о 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). Конечно, попутно меняя скорость движения, время, очки и т.д.

Ещё пример как можно использовать плавный поворот:

Интересно на 74%

(25) Хитрых на тему «Воспоминания о Crimsonland 2: наведение на цель»

  1. Сталекс

    Прикольно! когда можно будет поиграть в окончательные варианты? с зомби оч интересно) музычку б подложить, мрачненькую, покряхкивания монстров при их смерти, ну и бонусы, пушки, нунчаки, мечи, адуванчики в качестве оружия:) плюс вести онлайн рекорды, эх:)

  2. Stormit

    3-й слайд это почти окончательный вариант игрового баннера. Правда в оригинале главный герой бегал за мышкой. Хочу в следующей статье написать о том как запускать снаряды и разводить зомби.

  3. smival

    какой то странный глюк в нижней влешке, иногда прицел плавно сам по себе съезжает в сторону ближе к башне %)

  4. smival

    ещё очень не хватает инерции, все равно пушка дергается когда поворот из одной стороны сменяешь на другую.

  5. Zloba

    Этот способ более ресурсозатратный чем если ипользовать векторное произведение векторов

  6. Stormit

    >>иногда прицел плавно сам по себе съезжает…
    Это не глюк, прицел выстраивается по центру если им не водить 5 секунд (осталось с баннера)
    >>Этот способ более ресурсозатратный чем если ипользовать векторное…
    класс Вектор ещё будет, потом сравним плюсы и минусы

  7. Zloba

    Нее я про векторное произведение 2х векторов а не класс “вектор”. Или что ты имел в виду?

  8. Сашка

    if (dAngleD > 180) {
    dAngleD = -360 + dAngleD;
    } else if (dAngleD < -180) {
    dAngleD = 360 + dAngleD;
    }

    Спасибо! Когда-то голову сломал об это (компас рисовал, будто курсор выполняет функцию магнита).

  9. Stormit

    Я про класс Vector, а как здесь работает векторное произведение векторов?

  10. Georgi

    Все отлично работает, а как сделать выстрел, что бы цель поражать? Я так понимаю снаряд каким то образом по координатам должен совпасть с целью? Нельзя ли какой нибудь простенький пример на эту тему? Очень был бы благодарен.

  11. Zloba

    “Я про класс Vector, а как здесь работает векторное произведение векторов?”

    Просто смотришь знак векторного произведения и исходя из него поворачиваешь объект. При нахождении дэтерменанта матрицы координаты Z считать равными 0

  12. Domik

    2Georgi, самый простой вариант:
    if (Bullet.hitTest(Zombie)) {
    Zombie.gotoAndPlay(”dead”);
    }
    Bullet - это мувик пули, а Zombie - это мувик зомби. Только с пулей тоже надо что-то делать когда попадаем в зомби, например скрывать.

  13. Georgi

    Domik, Спосибо буду пробовать!

  14. Georgi

    Попробывал,ничего не выходит с пересечением объектов, создал мувик торпеды(tor) и мувик цели(zombie),которая при попадании должна измениться.В мувике торпеды написал код:
    onClipEvent (load) {
    speed=10;
    onEnterFrame=function(){
    _x+=speed;
    if (tor.hitTest(Zombie)) {
    Zombie.play();

    }
    }
    }
    торпеда проходит,а условие не выполняется. Подскажите пожалуйста где ошибка?

  15. dedpbIxto

    Georgi : У тебя же зомби находятся не внутри торпеды? Тогда возможно следует так
    onClipEvent (load) {
    speed=10;
    onEnterFrame=function(){
    _x+=speed;
    if (this.hitTest(_parent.Zombie)) {
    _parent,Zombie.play();
    } } }
    Если у тебя код весит на самой торпеде то не обязательно указывать при проверке if (tor.hitTest(Zombie)) - достаточно использовать this (он будет указывать на себя (на торпеду)), а вот если ты в торпеде поместил какой-то символ с которым будеш выполнять проверку тогда нужно будет указывать его имя.
    Указывай правильный путь к Zombi, не забывай что они находятся на разной глубине клипов.

  16. Georgi

    вот теперь дошло.спосибо. Все работает.

  17. Georgi

    У меня опять вопрос, есле можно. Пытаюсь сделать игру. Такая раньше в автоматах(атракционы) была.Плывут корабли и с перескопа подлодки торпедами их топишь. Проблема вот в чем: Корабль плывет я в него попадаю он взрывается и тонет, на этом игра останавливается. а как сделать чтобы как то зациклить что ли, т.е обратно с начала она началась? Посоветуйте что нибудь пожалуйста!

  18. dedpbIxto

    Georgi - а зачем вам эта игра?

  19. Stormit

    Вариант: раз в 5 секунд (например) создаётся программно корабль (attachMovie() или duplicateMovieClip()) и начинает двигаться. Если уходит за край экрана или умирает, просто удаляется (removeMovieClip()). Такая игра будет вечной, пока вы не определите условие для победы.

  20. Georgi

    dedpbIxto-Зачем игра? да все просто: в детстве она мне очень нравилась, а на ее примере мне легче продвигаться в изучении флеш.
    Stormit-Большое спосибо за подсказку теперь понял как.

  21. Georgi

    Что то у меня не идет! Дублирую клип, он дублируется, задаю другое место-появляется два, но вот как это связать чтоб они ходили друг за другом? Например создаю мувик в нутри програмно задаю движение. В кадре дублирую-двое движуться, а как сделать так чтоб они постояно ходилили друг за другом? Примерно как в этой флешке самолеты постоянно появляются. На этом полностью застопорился. Помогите пожалуйста!

  22. Leo

    Респект!

    Но почему вы никогда не выкладываете код полностью?

  23. Leo

    (исходник)

  24. Stormit

    Исходники я удаляю сразу после написания статьи чтобы не было соблазнов.

  25. Leo

    *спустя год*
    все получилось :D
    большое спасибо!

Оставить комментарий