Создать учебник по Flash Racing Game

Если вы заинтересованы в играх и блогах, YouSayToo позволяет вам зарабатывать на флеш-играх и позволяет зарабатывать деньги блогами ,

В этом уроке мы расскажем о создании флеш гоночной игры.

Я получил разрешение от Ремуса С. от gameSheep опубликовать этот удивительный урок.

Прежде чем мы начнем, я рекомендую всем вам взглянуть на gameSheep , Вы найдете много игр с симпатичной графикой.

Более того, этот урок даст начало еще одной серии уроков по созданию флеш гоночных игр.

Давайте начнем!

Переезд машины

1. Движение автомобиля - не самая сложная часть гоночной игры, но если вы хотите имитировать реалистичное (почти реалистичное) движение, вы должны принять во внимание некоторые аспекты, описанные ниже.

2. Скачать и открыть racing_part1_step1.fla файл.

3. Нажмите на первый кадр (единственный кадр) слоя «defs» и нажмите F9, чтобы отобразить окно действий для этого кадра. Теперь давайте посмотрим, что делают эти переменные:

car1.code = "player"; // эта переменная будет определять, будет ли указанная машина управляться игроком-человеком или компьютером (во второй части этого урока вы узнаете, как добавлять противников, и эта переменная пригодится) ускорение = 0,4; // переменная ускорения будет добавляться к переменной скорости при каждом событии enterFrame (в этом случае 24 раза в секунду); чем выше значение, тем быстрее ускорение автомобиля speedDecay = 0,96; // когда автомобиль не ускоряется (клавиша ВВЕРХ отпущена), автомобиль должен будет плавно замедляться; скорость умножится на это значение (меньше 1); чем ниже это значение, тем быстрее автомобиль будет замедлять вращение. Шаг = 10; // это количество градусов, которое будет увеличивать или уменьшать вращение (угол) автомобиля при нажатии левой или правой клавиши maxSpeed ​​= 10; // это ограничение скорости на нашем треке; увеличьте его, если хотите, чтобы машина ехала быстрее. backSpeed ​​= 1; // это ограничение скорости при движении назад

4. ОК! Теперь давайте вернемся в школу :) и посмотрим, что мы можем сделать с этими переменными.

Нажмите на первый кадр второго слоя («действия») и, если окна действий не открыты, нажмите F9, чтобы отобразить его.

Мы обсудим этот сценарий через несколько минут, но сначала давайте посмотрим, как Flash «понимает» движение и координаты.

Просто немного тригонометрии и Flash

Flash использует классическую декартову систему координат (система на основе сетки с горизонтальной осью OX и вертикальной осью OY).

На прилагаемом рисунке вы заметили, что во Flash ось Y инвертирована, что означает, что отрицательная сторона оси Y расположена выше положительной стороны. Таким образом, чем ниже координата, тем выше будет ее значение.

Поскольку Flash понимает только горизонтальные и вертикальные векторы, нам придется вычислять горизонтальную и вертикальную составляющие фактической «скорости».

Итак, из тригонометрии мы знаем (в данном случае), что:

грех (угол) = скоростьx / скорость и

cos (угол) = скорость / скорость

так что ... мы знаем угол (angle = car._rotation) и знаем скорость. Это все, что нам нужно знать. Это? Вам нужно знать еще одну вещь:

Класс Math, реализованный в Macromedia Flash, не работает с углами, измеренными в градусах. Вместо этого мы должны предоставить углы, измеренные в радианах (альтернативная единица измерения углов).

Единственный случай, когда вы будете использовать градусы, - это вращение видеоклипов.

Используя простое уравнение ниже, вы сможете преобразовать градусы в радианы:

angle_radians = angle_degrees * (PI / 180)

Теперь мы можем легко рассчитать X и Y составляющие скорости автомобиля:

speedx = Math.sin (_rotation * (Math.PI / 180)) * скорость;
speedy = Math.cos (_rotation * (Math.PI / 180)) * speed * -1;

Ну, вы уже поняли, почему знак компонента Y должен быть инвертирован;)

А теперь давайте вернемся к Flash и нашему окну действий. Далее я объясню, что такое функция «step». Функция «step» будет выполняться для каждого события enterFrame (на слое «stepper» вы найдете пустой мувиклип, который выполняет процедуру onClipEvent (enterFrame)).

function step (who) {// проверить, управляется ли рассматриваемый автомобиль игроком или компьютером if (_root ["car" + who] .code == "player") {// мы будем постоянно уменьшаться скорость, умножая его на число ниже 1, но только если скорость больше 0,3; более низкое значение будет потреблять только ресурсы, а движение даже не будет замечено, поэтому мы установим переменную скорости в 0, если (this ["speed" + who]> 0.3) {this ["speed" + who] * = _root.speedDecay ; } else {this ["speed" + who] = 0; } // машина будет реагировать на определенные нажатия клавиш, которые мы будем захватывать, используя метод Key.isDown следующим образом // ускоряться - мы добавляем определенное значение в переменную скорости, если нажата клавиша ВВЕРХ и скорость ниже максимальной допустимое значение if (Key.isDown (Key.UP) && this ["speed" + who] <_ root.maxspeed this = "" _root.acceleration = "" same = "" thing = "" but = "" here = " "we =" "subtract =" "if =" "_root.backspeed =" "left =" "well =" "могли =" "просто =" "добавить =" "или =" "a =" "fixed =" "angle =" "градус =" "to =" "the =" "car =" "вращение =" "that =" "not =" "good =" "достаточно. =" "in =" "order =" " simulate = "" natural = "" motion = "" Steve = "" must = "" зависимость = "" on = "" speed = "" иначе = "" you = "" will = "" be = "" able = "" rotate = "" your = "" even = "" it = "" Почти = "" Stop = "" и = "" look = "" like = "" propeller = "": = ""> 0.3) { _root ["машина" + кто] ._ вращение - = _root.rotationStep * (this ["скорость" + кто] / _ root.maxSpeed); } // держитесь правее - вы уже знаете, что здесь происходит, если (Key.isDown (Key.RIGHT) && this ["speed" + who]> 0.3) {_root ["car" + who] ._ вращение + = _root.rotationStep * (это [ "скорость" + кто] / _ root.maxSpeed); } this ["вращение" + кто] = _root ["автомобиль" + кто] ._ вращение; // мы вычисляем две составляющие скорости (ось X и ось Y) - мы уже обсуждали эту часть функции над этим ["speedx" + who] = Math.sin (this ["вращение" + кто] * ( Math.PI / 180)) * это [ "скорость" +, которые]; this ["speedy" + who] = Math.cos (this ["вращение" + who] * (Math.PI / 180)) * this ["speed" + who] * - 1; // применяем компоненты к фактическому положению автомобиля - мы добавляем компонент X скорости к координате X автомобиля, а компонент Y скорости к координате Y _root ["car" + who] ._ x + = это ["speedx" + кто]; _root ["car" + who] ._ y + = this ["speedy" + who]; // позиционируем тень машины - когда машина поворачивает, мы хотим, чтобы тень сохраняла координаты X и Y и всегда оставалась на одной стороне машины (с какой бы стороны это ни было) _root ["shadow" + who]. _x = _root ["car" + who] ._ x-4; _root ["shadow" + who] ._ y = _root ["car" + who] ._ y + 2; _root ["тень" + кто] ._ вращение = _root ["автомобиль" + кто] ._ вращение; } if (_root ["car" + who] .code == "computer") {// в нашем следующем уроке "Racing Game Part II" мы добавим противников, чтобы сделать игру более динамичной и интерактивной}} </ _ root. MaxSpeed>

Это оно! У нас уже есть движущаяся машина. Теперь мы можем перейти к столкновениям.

Столкновения

1. Мы все знаем, почему столкновения важны в гоночной игре ... Потому что мы не хотим, чтобы машина покидала трассу, потому что мы хотим заставить игрока использовать определенный путь, потому что мы хотим, чтобы он / она избегал столкновений в Чтобы получить лучшее время (или выиграть гонку).

Столкновения - очень важная часть гоночной игры, и 70% игрового ощущения и успеха зависит от хороших столкновений.

Мы не хотим, чтобы автомобиль застрял в недоступных областях (NAA), мы не хотим, чтобы он терял скорость, хотя он едва касается этих областей, и мы определенно не хотим, чтобы он пришел в норму (путем изменения направления движения). скорость).

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

2. Загрузите и откройте racing_part1_step2.fla файл.

3. Прежде чем мы вернемся к функции «step», я объясню, как будут работать столкновения.

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

Как вы можете видеть на прилагаемой картинке, мы выберем четыре точки, по одной на каждой стороне автомобиля, и проверим, касается ли какая-либо из них «НАА».

Например, если левая боковая точка находится внутри NAA (попадает в NAA), тогда мы должны будем применить штраф за скорость и увеличить угол (вращение) автомобиля. Зачем мы это делаем? Из-за того, что мы обсуждали ранее: мы должны попытаться скорректировать траекторию автомобиля. Итак, что мы делаем здесь, это заставляем машину поворачивать направо .

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

Когда вращение автомобиля равно 0, наша работа очень проста: координаты LSP: x = car._x-20 (20 пикселей слева от центральной точки автомобиля) и y = car._y

Но у машины не всегда будет угол наклона 0. Ну, тут начинается сложная часть. Есть несколько способов вычислить четыре точки, даже если угол не равен 0 (например, вы можете использовать функции синуса и косинуса), и для этого урока я выбрал простой способ (я не знаю, является ли это оптимальным способом) , но это очень просто)

Мы определяем левую боковую точку, как если бы вращение машины было 0:

car.pointLeft = {x: -20, y: 0}; // это объект

и затем мы преобразуем координату точки из локальной (связанной с клипом автомобиля) в глобальную (связанную с клипом _root, где мы будем проверять столкновения):

car.localToGlobal (car.pointLeft);

Теперь у нас есть координаты левой боковой точки, которые мы можем использовать для проверки столкновения:

car.pointLeft.x и car.pointLeft.y

Может ли это быть проще? :)

4. И снова вернемся к нашему окну действий. Нажмите на первый кадр слоя «Actions» и, если окно действий не открыто, нажмите F9, чтобы отобразить его.

Вы заметите, что я добавил несколько строк в функцию «step», и вы, вероятно, уже знаете, что делают эти строки :), но все же я буду вдаваться в некоторые детали.

// столкновения // определяют четыре точки столкновения _root ["car" + who] .pointLeft = {x: -20, y: 0}; _root [ "автомобиль" + кто] .localToGlobal (_root [ "автомобиль" + кто] .pointLeft); _root ["car" + who] .pointRight = {x: 20, y: 0}; _root [ "автомобиль" + кто] .localToGlobal (_root [ "автомобиль" + кто] .pointRight); _root ["car" + who] .pointFront = {x: 0, y: -25}; _root [ "автомобиль" + кто] .localToGlobal (_root [ "автомобиль" + кто] .pointFront); _root ["car" + who] .pointBack = {x: 0, y: 25}; _root [ "автомобиль" + кто] .localToGlobal (_root [ "автомобиль" + кто] .pointBack); // давайте использовать более короткие имена переменных :) - это просто для лучшего понимания и упрощения кода this ["lpx" + who] = _root ["car" + who] .pointLeft.x; this ["lpy" + who] = _root ["car" + who] .pointLeft.y; this ["rpx" + who] = _root ["car" + who] .pointRight.x; this ["rpy" + who] = _root ["car" + who] .pointRight.y; this ["fpx" + who] = _root ["car" + who] .pointFront.x; this ["fpy" + who] = _root ["car" + who] .pointFront.y; this ["bpx" + who] = _root ["car" + who] .pointBack.x; this ["bpy" + who] = _root ["car" + who] .pointBack.y; // проверка столкновений - мы проверяем столкновения, используя встроенный в Flash метод hitTest. Эти методы могут использоваться для сравнения координат x и y с формой или ограничительной рамкой указанного экземпляра (в нашем случае _root.terrain) в соответствии с флагом формы (третий параметр: true-shape / false - ограничивающая рамка) установка или проверка, перекрывают ли ограничивающие рамки цели и указанного экземпляра. Мы используем первый. if (_root.terrain.hitTest (this ["lpx" + who], this ["lpy" + who], true)) {// направо направо _root ["car" + who] ._ вращение + = 5; // штраф скорости speed this ["speed" + who] * = 0.85; } if (_root.terrain.hitTest (this ["rpx" + who], this ["rpy" + who], true)) {// повернуть налево _root ["car" + who] ._ вращение - = 5; // штраф скорости speed this ["speed" + who] * = 0.85; } if (_root.terrain.hitTest (this ["fpx" + who], this ["fpy" + who], true)) {// остановить машину this ["speed" + who] = -1; } if (_root.terrain.hitTest (this ["bpx" + who], this ["bpy" + who], true)) {// остановить машину this ["speed" + who] = 1; }

Жесткий? Не так сложно :) А следующие два шага еще проще.

Куда мы бежим?

1. До сих пор у нас есть 100% функциональный игровой движок, но нет игры. У нас нет цели. Так что нам придется добавить один, и поскольку этот урок посвящен гоночной игре на время, мы добавим круги и таймеры.

2. Загрузите и откройте racing_part1_step3.fla файл.

3. Вы заметили, что я добавил два кадра на каждый слой и пометил их «готово», «идти» и «закончить». В первом кадре будет воспроизведен фрагмент ролика с надписью «готово, установи, иди». Когда отображается «go», _root переместится в рамку с надписью «go», по которой автомобиль может двигаться.

Почему машина не будет двигаться в первом кадре? Ну, это потому, что «пошаговый» мувиклип существует только во втором кадре, поэтому здесь будет выполняться функция «шаг».

Во втором кадре слоя «Actions» вы также найдете две новые переменные. Эти переменные будут использоваться для хранения точного времени начала гонки (initialTime |) и точного времени начала текущего круга (lapTime).

Когда игра закончится, после того, как игрок закончит десять кругов, _root перейдет к фрейму «финиш», где будет отображаться информационный мувиклип.

4. ОК! Далее нам нужно определить, закончил ли игрок круг или нет, поэтому мы добавим два мувиклипа (красная линия на правой стороне) и проверим, «коснулась» ли машина этого мувиклипа, и если это так, то Вы знаете, что круг закончен ... хм ... не совсем :)

Прежде всего автомобиль будет «трогать» этот мувиклип более чем на один кадр. Может быть, для двоих, может быть для десяти, может быть для ста кадров, вы не можете определить это число, потому что оно зависит от скорости автомобиля. И вместо того, чтобы увеличить количество кругов на один, вы увеличите его на два, десять или сто кругов, поэтому гонка будет готова довольно быстро.

Вторая проблема, при условии, что вы решили первую, состоит в том, что один игрок пройдет финишную черту (красная линия справа), а затем сразу же вернется к той же самой линии и снова «дотронется» до нее, увеличивая количество кругов даже хотя круг не закончен. Эта проблема может быть решена несколькими способами, но мы выберем решение, которое решает обе наши проблемы: мы добавим контрольную точку (красная линия слева). Эта контрольная точка будет размещена где-то в середине гонки, чтобы игрок потерял больше времени, возвращаясь к финишу, чем потеряет, пройдя круг. Конечно, если вы хотите более безопасную гонку, вы добавите более одной контрольной точки. Вы сможете легко добавить больше контрольных точек после окончания этого урока.

5. Откройте окно действий для первого кадра слоя «действия». Нам нужны новые функции, связанные как с выбором времени гонки - setTimes (вычисляет и устанавливает общее время гонки) и setBestLap (рассчитывает и устанавливает лучшее время круга). Мы будем принимать их по одному и посмотрим, что они делают.

function setTimes () {// мы вычисляем время, прошедшее с момента начала гонки в миллисекундах timeElapsed = getTimer () -_ root.initialTime; // мы вычисляем минуты, секунды и десятки секунд и устанавливаем их соответствующие переменные milliseconds = timeElapsed; секунд = Math.floor (миллисекунды / 1000); минуты = Math.floor (секунд / 60); minutesTXT = минуты; secondsTXT = секунды-минуты * 60; tenTXT = Math.round ((миллисекунды-секунды * 1000) / 10); // если число минут, секунд или десятков секунд содержит только один символ, мы добавляем перед ним «0» - это просто потому, что мы хотим, чтобы время выглядело хорошо;) if (minutesTXTmilliseconds || oldMilliseconds == null) {oldMilliseconds = миллисекунды; секунд = Math.floor (миллисекунды / 1000); минуты = Math.floor (секунд / 60); minutesTXT = минуты; secondsTXT = секунды-минуты * 60; tenTXT = Math.round ((миллисекунды-секунды * 1000) / 10); if (minutesTXT
6. А теперь еще раз (обещаю, что это последний раз) вернемся к функции «step» и давайте проанализируем новые строки. // контрольные точки // мы проверяем, касается ли автомобиль "текущей" контрольной точки (в данном случае текущая контрольная точка может быть контрольной точкой1 или контрольной точкой2, потому что у нас только две контрольные точки; контрольная точка1 - линия начала / финиша) if (_root ["car" + who] .hitTest (_root ["контрольная точка" + _ root ["currentCheckpoint" + who]])) {// если текущая контрольная точка является стартовой линией - увеличить номер круга if (_root ["currentCheckpoint" + who] == 1) {// если текущий круг не равен 0, мы проверяем, является ли он лучшим кругом if (_root ["currentLap" + who]! = 0) {_root.setBestLap (); } // если это последний круг, _root переместится в финишный фрейм if (_root ["currentLap" + who] == _root.totalLaps) {_root.gotoAndStop ("finish"); } else {_root ["currentLap" + who] ++; } _root.currentLapTXT = _root ["currentLap" + who] + "/ 10"; } // мы установили контрольную точку для проверки следующей контрольной точки _root ["currentCheckpoint" + who] ++; // если текущая контрольная точка является последней контрольной точкой - установите следующую контрольную точку в стартовой строке if (_root ["currentCheckpoint" + who]> _ root.checkpoints) {_root ["currentCheckpoint" + who] = 1; }}
7. Вот и все :) Теперь давайте перейдем к последним графическим штрихам и увидим нашу законченную игру.
Завершение игры
1. Последний штрих ... Ну, тут нечего объяснять. Вы можете выразить себя в любом случае и создавать графику на свой вкус.
Просто не забудьте установить альфа зеленого клипа и красного клипа на 0.
2. Это файл racing_part1_step4.fla, прилагаемый к данному руководству. Загрузить!
3. Помните, что это всего лишь учебник. Вы должны работать над этим, чтобы построить действительно захватывающую игру. В следующем уроке мы добавим в игру противников. До тех пор, получайте удовольствие, создавая свою гоночную игру на время;)
И, кстати, мое лучшее время круга 9,84: D
На этом учебник Ремуса заканчивается. Я многому научился из этой статьи и буду использовать ее для улучшения игрового процесса с некоторыми дополнениями.
Тем временем, оставьте отзыв Ремусу и попытайтесь побить это время прохождения n00b !!Это?
Зачем мы это делаем?
Куда мы бежим?
Почему машина не будет двигаться в первом кадре?