Даю порулить - программируем движение автомобиля для флэш-игр
09.07.2008, автор Stormit, рубрики: ActionScript, Flash игрыМного есть флэш-игр, связанных с автомобилями, когда игра ведется от третьего лица при виде сверху. В основном это гонки, где нужно намотать круги и обогнать противников. В таких случаях обычно не учитывают колеса автомобиля и при поворотах, просто поворачивают клип вокруг центра. Это не соответствует правде, но если машину окружить выхлопными газами, пылью и другими эффектами, то этого никто и не заметит. Все потому, что игровой движок не на этом строится.
Другое дело, если цель игры - припарковать машину или пройти курсы вождения. Тогда без более-менее реальной модели автомобиля (передние колеса задают поворот, а задний мост - ведущий) ничего не получится.
Решение которое я предлагаю не использует физических законов, по крайней мере я пока об этом не подозреваю, но довольно хорошо имитирует реальное поведение четырехколесного автомобиля с ведущим задним приводом.
Логика здесь такая: автомобиль вначале поворачивается (если передние колеса не смотрят прямо) и едет в этом направлении. Со смещением проблем нет, но вот поворот на правильный угол не давал мне покоя. По логике, скорость поворота прямо пропорциональна поступательной скорости автомобиля и обратно пропорциональна расстоянию между передними и задними колесами. На удивление, этого хватило, и не пришлось подбирать поправочные коэффициенты.
Чтобы это проверить, нам нужен подготовленный символ автомобиля. Достаточно иметь 4 колеса и какой-либо каркас.
- Создаем символ car и внутри него 2 колеса с именами left и right. Центр символа car должен находиться строго между задними колесами. Это ВАЖНО. Это та точка, к которой прикладывается сила тяги.
- В той же линейке, где лежит символ car, кадром выше пишем код:
speed = 0; speedLimit = 8; speedStep = .5; rotLimit = 35; rotStep = 3; processKey = function () { if (Key.isDown(Key.LEFT)) { if (car.left._rotation > -rotLimit) { car.left._rotation = car.right._rotation -= rotStep; } } else if (Key.isDown(Key.RIGHT)) { if (car.left._rotation < rotLimit) { car.left._rotation = car.right._rotation += rotStep; } } if (Key.isDown(Key.UP)) { speed += (speed < speedLimit)? speedStep : 0; } else if (Key.isDown(Key.DOWN)) { speed += (speed > -speedLimit)? -speedStep : 0; } else { speed += (speed < 0)? speedStep : (speed > 0)? -speedStep : 0; } }; function move(){ if(Math.abs(speed) > 0) { car._rotation += car.left._rotation * speed / car.left._x; } angle = car._rotation * Math.PI / 180; speedX = speed * Math.cos(angle); speedY = speed * Math.sin(angle); car._x += speedX; car._y += speedY; } onEnterFrame = function() { processKey(); move(); }
Я постарался разнести все величины по переменным, так что настроить их под другой тип машины дело не сложное. Замедление с ускорением тоже есть - все как учили
- Получаем такой результат. Управление осуществляется с клавиатуры - стрелки ←,↑,→,↓.
- Сразу проверим, как это будет работать, если передвинуть передние колеса вперед. Вроде неплохой автобус.
- Небольшой пример из жизни.
Еще немного о том, как машина исчезает с одной стороны и появляется с другой.
Я люблю наглядные способы, поэтому зону для маневров будет задавать клип box с габаритами, идентичными размеру флэшки. А уже с него я считаю ограничивающие координаты по ширине и по высоте. Тогда в дополнение к вышеизложенному, дописывается такой код:
WIDTH = zone._width; HEIGHT = zone._height; LEFT = zone._x; TOP = zone._y; RIGHT = LEFT + WIDTH; BOTTOM = TOP + HEIGHT; checkCycle = function () { bounds = car.getBounds(this); boundWidth = bounds.xMax - bounds.xMin; boundHeight = bounds.yMax - bounds.yMin if(bounds.xMax < LEFT) { car._x = RIGHT + car._x - bounds.xMin; } else if(bounds.xMin > RIGHT) { car._x = LEFT - (bounds.xMax - car._x); } if(bounds.yMax < TOP) { car._y = BOTTOM + (car._y - bounds.yMin); } else if(bounds.yMin > BOTTOM) { car._y = TOP - (bounds.yMax - car._y); } };
Теперь эту функцию нужно добавить в вызов по событию EnterFrame, после вызова функции move().
Получается вполне универсальный движок для многих видов транспорта. Но все это сделано чисто интуитивно, а я бы не прочь взглянуть, как это объясняется физикой. Так что если кто-то начертит схему с силами и всеми делами,- милости просим.
Интересно на 33%




Вах
маладэц 
Супер! Спасибо. И как всегда классно оформлена флешка =)
Кто нибудь может разжевать эту сточку
” speed += (speed 0)? -speedStep : 0; ”
Просто такую форму записи я вроде ещё не видел
Это альтернативный вариант if…else
Если условие в скобках истинно, то вместо всего этого подставляется значение идущее после вопросительного знака, иначе - после двоеточия.
а реально прицеп сзади прикрутить ?
Очередной отличный урок! Спасибо!
Про прицеп - очень класный вопрос.
Если уж пошли такие навороты, можно и дрифт на скорости просчитать!
Но это уже совсем другие гигабайты кода 
Супер, а когда комбайн увидел, вспомнил Вангеров.
Но с точки зрения реализма (небольшое дополнение) колеса поворачиваться должны на разный угол, т.к. радиусы они описывают при повороте разные (дальнее колесо относительно точки поворота) должно поворачиваться на меньший угол.
ну это так - если кто будет реалистичное что то творить.
Придумаю что-нибуть с прицепом
погоняв трактор, стало ясно, что игры в гонки надо делать не вертикальные, а горизонтальные, так интереснее управлять))
Отличный пример. А траектория практически верна, маленькая неточность - не грех )
Прикольно, посмотрл подзадумался. Автор молодец одним словом! респект!
Супер! Вот это профессионал! Доделай в игру про парковку. Кстати в IE комментарии съезжают вниз некрасиво.
А какой у тебя IE?
У меня в 6-м не съезжают
Ай, зачем таким пользоваться а, IE - ну его, юзайте лучеше Оперу или Файрфокс, и наслаждайтесь творениями автора.
По поводу дрифта.Нашёл классную игруху
http://www.demonfiles.my1.ru/load/7-1-0-198
осталось тока узнать как это реализовать )))
А в этом “дрифте” машина поворачивается по центровой оси =)
А можете дать исходник, а то мне ваш трактор сильно понравился? =)
Здорова Стормит зацини прикол: http://www.free-lance.ru/blogs/view.php?tr=236455&ord=new Там в середине парню одному ответил зип архивом. Посмотри его))) и обрати внимание на даты) ты кстате никак с этим несвязан? а то уж больно похоже получилось) (зы код да разный))
Нет, я никак с этим не связан =)
Славентий (Zloba), спасибо конечно, но это не то, о чем я просил =) Мне нужен вот именно этот трактор =)
А еще, как можно сделать чтобы следы от машины оставались?
to Славентий (Zloba)
нет, не связан, этому комбайну уже несколько лет
>>Мне нужен вот именно этот трактор =)
А зачем? Плагиат это плохо, а суть движка и код приведен выше, осталось только обрисовать фото любого трактора при виде сверху.
>>А еще, как можно сделать чтобы следы от машины оставались
рисуешь квадратный отпечаток по ширине колеса и дальше либо на EnterFrame (либо когда проехал минимально допустимое расстояние) дублируешь его и ложишь точно под колесом (машине swapDepths(10000000000)). Для остальных колес тоже самое.
Еще, дублированием (по тому же типу что и огонь), можно сделать и выброс грязи из-под задних колес.
Stormit, спасибо!
А как можно сделать такой дымок, как в тракторе? Я понимаю, что по принципу огня, но непонимаю как привязать дымок в клип с машиной. Я вставляю мувик дымка в машину, а дальше что? Какой код?
Разжуйте пожалуйста.
А вот мне нужно впихнуть все это в мувиклип. Что изменить в коде, чтобы он работал?
Ну, мне кто-то поможет?
Ало-о!
Destroyer - есть ресурсы где разжовывают (чаще форумы). В этом блоге рассказывают о хитростях. Если Художник нарисовал картину - это не обязывает его рассказывать как он ложит масло на холст. Если тебе так уж хочеться такой трактор - напряги себя и сделай. В этом блоге есть все что бы сделать самостоятельно такой трактор.
Ну как еще нужно попросить…
Господа! А мне кажется, что колеса с рулем все-таки должны сами возвращаться в центральное положение во время движения! Так реалистичней!
Да, я тоже заметил что было бы неплохо сделать возвращение колес при движении в зависимости от скорости. То есть, наверное. должно получатся, что колеса должны оставаться под одним углом относительно земли если клавиша “влево” или “вправо” не нажаты.
Заметил одну вещь - при повороте скорость машинки сильно возрастает…
Занос машины не учитывается. По идее, при повороте на быстрой скорости, машину должно нести по инерции (по касательной к радиусу поворота)
to Dmitry Matyukhin
if(!Key.isDown(Key.LEFT) && !Key.isDown(Key.RIGHT)) { car.left._rotation = car.right._rotation *= .8 * (speed / speedLimit); }типа того (нужно еще и к скорости движения привязаться)
to Destroyer
Дымок так же как и в примере с огнем, остается огненный шлейф за мячиком.
Не вижу проблем чтобы все это в мувик засунуть. У меня так все и работает. Конкретно, как обернуть несколько слоев в символ описано здесь: http://xitri.com/2008/05/17/tools-for-flash.html
спасибо очень круто
Спасибо за статью оказалась очень полезной.
Отличная идея. Сначала пытался сам спрограмировать автомобиль, но потом нашел этот сайт. Идея очень понравилась. Только немножко физики добавил, ну там инерция, автоматическое возвращение колес в исходное положение, занос автомобиля при движении на большой скорости и т.д. Только вот пришлось код писать не на кадре а на самом клипе автомобиля, так как надо было сделать много автомобилей, чтобы код не переписывать для каждого в отдельности.
Здраствуйте Stormit пытался разобрать ваш код но сколько не пробую невыходит (неработает) если вам не сложно немоглибы вы выслать на SilverForce@yandex.ru исходник (рабочий). буду очень благодарен
Здраствуйте! У меня ничего не получилось!
А не поделитесь исходничком? сюда - RuStep@list.ru
Исходники потерялись, но могу подсказать, если скажете с какого момента перестало получаться (какие переменные становятся undefined и т.д.).
Дело в том, что сам “car” и колёса я сделал! Но вот когда вставляю в это кадр код - он не работает! Не пойму в чём проблема!
плохо что нет исходника, а вы не могли бы составить его по уроку?
Если компилятор не выдаёт никаких ошибок, пройдитесь по коду и проверьте функцией trace(), какие переменные становятся NaN, null или undefined. Там и нужно искать причину.
В первую очередь, стоит проверить видны ли сами символы машины и колёс в коде.
Извините но в AS я не особый мастер :), поэтому не очень понимаю что вы написали, но всё же прошёлся по коду - нашёл эти элементы в коде, то есть они там присутствуют!
Вы уж меня извините что я подряд пишу, но система комментариев обрезает код, а я подумал что я ошибся. Немогу сюда вставить то что хочу. Вобщем действие в else после после key.DOWN.
Модеры удалите плиз все лишнее что наговорил
if (Key.isDown(Key.UP)) { speed += (speed < speedLimit)? speedStep : 0; } else if (Key.isDown(Key.DOWN)) { speed += (speed > -speedLimit)? -speedStep : 0; } else { speed += (speed < 0)? speedStep : (speed > 0)? -speedStep : 0; }Если клавиша “UP” нажата, то скорость увеличивается (но не больше speedLimit), если “DOWN” - уменьшается (но не меньше -speedLimit), иначе - скорость постепенно падает до нуля (прибавляется или вычитается в зависимости от знака).
у меня нечего не вышло :(((
С дымом тоже не понял. Помещаю его в клип с машиной и он “не тянется”. Просто дымик “внутри” машины.
Сделал автоматический возврат колёс в исходное положение, снижение скорости при повороте. Делаю заносы, ручник, следы при торможении.
Я в AS не профи, но пока всё получается. Но с дымом так и не разобрался.
Если клип (объект) внутри другого клипа, его координаты (и вообще его бытие) относительны родительского клипа? Т.е. не удивительно, что клубья дыма копируются внутри машины. Как сделать, чтобы дым коптил с нужной точки автомобиля?
Помести внутри символа с машинкой невидимый символ (помести его центр на выхлопную трубу). Потом, при помощи методов localToGlobal() и globalToLocal() пересчитывай координаты этого символа в тот timeline где лежит машина и клип дыма. Дальше дублируй клип дыма и помещай в полученные координаты.
Спасибо, Stormit! Просто не знал эти методы.
Машинка задымила, а теперь еще больше люблю этот бложик
Nice tutorial.
I try your tutorial everything is fine, but i want to add collision detection against wall and bounce back but no idea where to start ?
You can place 8 or more point clips in the car and arrange them on perimetre and check collision with hitTest() function. After that, return the car to the previous position and rotate around collided point. I didn’t do it but I think similar way.
Спасибо очень класно! Stormit могли бы вы идейки подкинуть, насчет заноса и вращение машины волчком (если сильно занесет), а то неполучается что-то
я во флеше не очень хорошо разбираюсь. но не могли бы вы мне прислать код того, чтобы когда авто попадало на определенныю територию её скорость менялась
Пробуйте hitTest()
Если координаты 4-х колёс совпадают с вашей зоной, уменьшайте скорость. Так будет даже круче - чем больше колёс в штрафной зоне - тем медленней едет машинка.
А как бы сделать чтобы привод можно было передвинуть? Или сделать полноприводную? Это какой-то оффсет надо класть, не могу сообразить куда.
Здравствуйте Stormit у меня к вам вопрос при изменении параметра SpeedStep авто неприобретает состояния “покоя” тоесть флешка всегда в движении, как это можно поправить? пытался прописывать нечто вроде “если скорость меньше 1 то присваиваем ей значение 0″ но видать невте дебри лезу…
Пробывал сделать…выдал=> **Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 1: Statement must appear within on/onClipEvent handler
speed = 0;
**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 2: Statement must appear within on/onClipEvent handler
speedLimit = 8;
**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 3: Statement must appear within on/onClipEvent handler
speedStep = .5;
**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 4: Statement must appear within on/onClipEvent handler
rotLimit = 35;
**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 5: Statement must appear within on/onClipEvent handler
rotStep = 3;
**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 6: Statement must appear within on/onClipEvent handler
processKey = function () {
**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 24: Statement must appear within on/onClipEvent handler
function move(){
**Error** Scene=Scene 1, layer=Layer 1, frame=1:Line 34: Statement must appear within on/onClipEvent handler
onEnterFrame = function() {
Total ActionScript Errors: 8 Reported Errors: 8
подскажите как исправить?…плиз!!!
….или поделитесь исходником=> morozov-dedulya@mail.ru
У меня такая же ошибка как у Moroz777. Что за шляпа? =( Подскажите
Люди!я в ActionScript вообще ничего не понимаю,а научиться блин хочется!
Я вот по какому вопросу…вы не могли бы написать код(ну или написать че нужно исправить)чтоб как в самых обычных гонках нажатие вправо-поворот направо нажатие влево…Пожалуйста напишите!!!!а то я вообще не знаю где еще мона это посмотреть!!!!!
а как зделать границу, за которую машина заехать не может? и бокс для парковки, чтоб игру полноценную создать.
to Nikolaus
car._x += speedX;
car._y += speedY;
Вот тут делайте проверку. Если координата выходит за пределы зоны, то её не менять.
Бокс для парковки проще всего проверять на hitTest() по колёсам.
и куда это вставлять? да, и как сделать границу, за которую машина заехать не может? Можно как нибудь типо создать символ “graniza” и при наезжании на него символа “car” игра переходила на другой кадр?
P.S.мой id7418368 атор этого всего, если не трудно добавься в друзья, но только с пометкой “флэш”
Спасибо за урок. Утащил к себе код частично. (:
Давно хотел такую штуку сделать - знакомым начинающим водителям практиковаться.
Там небольшая поправка только.
В описании ко второй части кода - там зону для манёвров создаёт не клип BOX а клип ZONE.
Ещё раз спасиба.
Здраствуйте! Пробывал машину сделать,но не получилось код не работает и выдает ошибку А не сделаете исходник для скачки, чтобы посмотреть что не так сделал? А то хочется чтобы все таки машина ездила!!! или скиньте мне на email terminator200911@mail.ru
Statement must appear within on/onClipEvent handler speed = 0;
Statement must appear within on/onClipEvent handler speedLimit = 8;
Statement must appear within on/onClipEvent handler speedStep = .5;
Statement must appear within on/onClipEvent handler rotLimit = 35;
Statement must appear within on/onClipEvent handler rotStep = 3;
Statement must appear within on/onClipEvent handler processKey = function () {
Statement must appear within on/onClipEvent handler function move(){
Statement must appear within on/onClipEvent handler onEnterFrame = function() {
Помогите, машину сделал и выдает ошибку!!! что делать и как исправить машина мертвым грузом стоит!!!
Народ машина назад в перед едит,а вот калеса не поворачивают что мне делать?
Спасибо за идею! Незнаю почему но только чтобы у меня все работало норм на AS2 пришлось несколько переработать ваш код. Кому нужен исходник вот моя почта corsar-2232@rambler.ru
Stormit а как можно сделать что бы если машина встала в определёную зону он
переходил на следущий кадр
я не не понял куда вписывать скрипт ?
Подскажите пожалуйста почему у меня колеса поворачивается не по центру а с угла?
http://dmhope.ru/mycar.swf
onEnterFrame = function() {
processKey();
move();
погдскажите зачем это здесь?
Все просто и гениально. Автор огромное спасибо за урок.
Вот моя реализация.
http://dmhope.ru/flash/mycar2.swf
В той же линейке, где лежит символ car, кадром выше пишем код как это понять ???
Сашка, Добавь новый слой и в нем в первом фрейме пиши код.
http://s52.radikal.ru/i137/1004/a6/452d02a8a3ae.png
ок спс попробую )
а писать в муве или нет ?
блин не получается я просто мало знаю чего во флеше ((
Сайшка, что именно не получилось?
ёмаё у мну тож палучилось))) http://my.mail.ru/mail/morozov-dedulya/app-canvas?appid=460207
Сашка, кщё важно кадры подписать!!..а не только мувики))
…ой, наврал!..кароче в панельке properties не забудь вписать имена
извиняюсь, а какие именно имена ?))
точнее как назвать их
Не могу понять как сделать символ, по подробее сам символ создал в него поместил символы left и right а как поместить его в монтажный кадр, кто нить может дать исходник
ктонить дайте исходник плиз
Пытаюсь придумать занос и следы от колёс.