Есть много игр с ворчливыми, нереалистичными движениями, которые могут сделать только одно для вашего продукта: сделать его непривлекательным для аудитории. Но плавного движения достичь не сложно — приступим к работе!
Окончательный результат предварительного просмотра
Давайте посмотрим на конечный результат, к которому мы будем стремиться:
Шаг 1: настройка среды
Это прямое руководство, поэтому настройка также будет прямой.
Создайте новый проект FlashScript 3.0. Размер сцены и цвет не имеют значения, просто используйте то, что вам удобно.
Я использую FlashDevelop для кодирования, но это также можно сделать в любом редакторе AS, например, в Flash Pro (или любом текстовом редакторе, может быть, Notepad;)) Итак, создайте файл Class, убедитесь, что ваш код очень похож на мой; см. ниже. Я назвал мое «Движение». (Если вы используете Flash Pro, ознакомьтесь с этим руководством по созданию класса .)
|
01
02
03
04
05
06
07
08
09
10
11
|
package {
import flash.display.Sprite;
public class Movement extends Sprite {
public function Movement():void {
}
}
}
|
После того, как вы закончите, убедитесь, что ваш класс связан с проектом Flash в качестве основного класса.
Шаг 2: Создайте квадрат и переменные
Поэтому после того, как вы связали класс Movement со своим документом, определите переменные, как я сделал ниже
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
package {
import flash.display.Sprite;
import flash.events.Event;
public class Movement extends Sprite {
//The object that will move
private var square:Sprite;
//The maximum speed
private var _max:Number = 10;
//The variables that are going to be applied to move the square
private var dx:Number = 0;
private var dy:Number = 0;
public function Movement():void {
//Listen for added to stage event
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
//Creating a new Sprite and draw inside a square
square = new Sprite();
square.graphics.beginFill(0x333333);
square.graphics.drawRect(0, 0, 30, 30);
square.x = stage.stageWidth / 2 — square.width / 2;
square.y = stage.stageHeight / 2 — square.height / 2;
addChild(square);
}
}
}
|
Это почти все, что мы сделаем для создания объекта. Вы можете использовать свой собственный объект, но для этого простого урока движения я использовал этот простой квадрат.
Шаг 3: Введение в класс Input.as
Привет, ребята, это класс Input.as; Input.as Класс это парни, о которых я тебе говорил — будь к ним добр! 🙂
Итак, о чем этот класс, вы можете спросить. В основном это делает вашу работу с ключами для вас. Он добавляет прослушиватель событий ENTER_FRAME — с низким приоритетом — и ключевой прослушиватель, который заполняет некоторые частные словари. Также он использует другой класс для кодов ключей. Вы можете заглянуть внутрь и увидеть, как это работает.
Примечание. Класс Input.as не принадлежит мне. Он был создан Мэтью Бушем, который портировал Box2D на Flash .
|
01
02
03
04
05
06
07
08
09
10
11
12
|
//Example of Input.as Class usage
//You have to always initialize it as this with the stage parameter
Input.initialize(stage);
//After initializing, you can use kd(), kp() or ku() methods, which
//return a Boolean value if the conditions are met.
//These methods accept multiple arguments,
//so for one event you can use multiple keys.
//This makes it a lot easier to give a boost of accessibility to your app.
//eg See below as I use one call for detecting UP arrow or W for going up.
Input.kd(«UP», «W»);
|
Шаг 4: Импорт классов
Итак, теперь, когда вы знакомы с классом Input.as, мы собираемся импортировать его в наш класс Movement и инициализировать его.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
package {
import flash.display.Sprite;
import flash.events.Event;
import Input;
public class Movement extends Sprite {
//The object that will move
private var square:Sprite;
//The maximum speed
private var _max:Number = 10;
//The variables that are going to be applied to move the square
private var dx:Number = 0;
private var dy:Number = 0;
public function Movement():void {
//Listen for added to stage event
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
//Creating a new Sprite and draw inside a square
square = new Sprite();
square.graphics.beginFill(0x333333);
square.graphics.drawRect(0, 0, 30, 30);
square.x = stage.stageWidth / 2 — square.width / 2;
square.y = stage.stageHeight / 2 — square.height / 2;
addChild(square);
//Initialize the Input.as Class with handler on stage
Input.initialize(stage);
//Add the refresh loop
addEventListener(Event.ENTER_FRAME, refresh);
}
private function refresh(e:Event):void {
}
}
}
|
Шаг 5: Обработка ключевых входов
Я использую цикл на основе ENTER_FRAME для обнаружения ключевых вводов; ниже приведен метод refresh() который является функцией-обработчиком этого события.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
private function refresh(e:Event):void {
//Key Handler
if (Input.kd(«A», «LEFT»)) {
//Move to the left
}
if (Input.kd(«D», «RIGHT»)) {
//Move to the right
}
if (!Input.kd(«A», «LEFT», «D», «RIGHT»)) {
//If there is no left/right pressed
}
if (Input.kd(«W», «UP»)) {
//Move up
}
if (Input.kd(«S», «DOWN»)) {
//Move down
}
if (!Input.kd(«W», «UP», «S», «DOWN»)) {
//If there is no up/down action
}
}
|
Шаг 6: Объяснение расчетов — управление скоростью
Это довольно просто. Определите, нажата ли какая-либо из клавиш, и действуйте соответствующим образом.
Я часто использую троичный оператор: value = condition ? true : false; value = condition ? true : false;
Это в основном оператор if, который сжат в одну строку.
Для каждого определения ключа я использую этот метод: если значение больше, чем _max тогда установите его равным _max ; в противном случае, увеличивайте или уменьшайте это конкретное значение по мере необходимости. Таким образом, это держится в определенных пределах. Просто, правда?
Ниже вы можете ознакомиться с условиями:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
private function refresh(e:Event):void {
//Key Handler
if (Input.kd(«A», «LEFT»)) {
//Move to the left
dx = dx < 0.5 — _max ?
}
if (Input.kd(«D», «RIGHT»)) {
//Move to the right
dx = dx > _max — 0.5 ?
}
if (!Input.kd(«A», «LEFT», «D», «RIGHT»)) {
//If there is no left/right pressed
if (dx > 0.5) {
dx = dx < 0.5 ?
} else {
dx = dx > -0.5 ?
}
}
if (Input.kd(«W», «UP»)) {
//Move up
dy = dy < 0.5 — _max ?
}
if (Input.kd(«S», «DOWN»)) {
//Move down
dy = dy > _max — 0.5 ?
}
if (!Input.kd(«W», «UP», «S», «DOWN»)) {
//If there is no up/down action
if (dy > 0.5) {
dy = dy < 0.5 ?
} else {
dy = dy > -0.5 ?
}
}
//After all that, apply these to the object
square.x += dx;
square.y += dy;
}
|
Если вы не знакомы с троичным оператором, возьмите лист бумаги и ручку и запишите несколько из них в формате if … else; Это отличное упражнение, чтобы справиться с происходящим.
Имейте в виду, что я манипулирую переменными dx и dy и в конце устанавливаю только фактические значения x и y. Это помогает нам сделать движение жидкости; это не дергается, поскольку мы изменяем их значения непосредственно во всей функции ..
Давай, проверь это! Видишь, как хорошо он движется?
Шаг 7: Обработка граничных коллизий
Ладно. Все правильно, движется плавно — но вне сцены! Ниже я добавил условия обнаружения столкновений.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
private function refresh(e:Event):void {
//Key Handler
if (Input.kd(«A», «LEFT»)) {
//Move to the left
dx = dx < 0.5 — _max ?
}
if (Input.kd(«D», «RIGHT»)) {
//Move to the right
dx = dx > _max — 0.5 ?
}
if (!Input.kd(«A», «LEFT», «D», «RIGHT»)) {
//If there is no left/right pressed
if (dx > 0.5) {
dx = dx < 0.5 ?
} else {
dx = dx > -0.5 ?
}
}
if (Input.kd(«W», «UP»)) {
//Move up
dy = dy < 0.5 — _max ?
}
if (Input.kd(«S», «DOWN»)) {
//Move down
dy = dy > _max — 0.5 ?
}
if (!Input.kd(«W», «UP», «S», «DOWN»)) {
//If there is no up/down action
if (dy > 0.5) {
dy = dy < 0.5 ?
} else {
dy = dy > -0.5 ?
}
}
//Boundary detection
if (square.x — dx < 0 || square.x + dx + square.width > stage.stageWidth) {
//x axis detection
}
if (square.y — dy < 0 || square.y + dy + square.height > stage.stageHeight) {
//y axis detection
}
//After all that, apply these to the object
square.x += dx;
square.y += dy;
}
|
Он ищет границы более точным способом, проверяя, попадают ли края квадрата в границы (до этого он просто проверял центр квадрата относительно границ).
Отлично. Теперь нам нужно добавить код, чтобы заставить квадрат отскочить от границ. Для этого я умножаю на -1 значение оси dx или dy . Но этого недостаточно! Если скорость достаточно высокая, то квадрат пройдет через поля или просто сойдет с ума. Поэтому, прежде чем мы умножим, мы должны установить x или y объекта так же, как и границу, с которой он встречается.
Так что если x object.x = 0; а затем умножьте dx на -1.
|
01
02
03
04
05
06
07
08
09
10
11
12
|
//Margin detection
if (square.x — dx < -dx || square.x + dx + square.width > stage.stageWidth) {
//x axis detection
square.x = square.x — dx < -dx ?
dx *= -1;
}
if (square.y — dy < -dy || square.y + dy + square.height > stage.stageHeight) {
//y axis detection
square.y = square.y — dy < -dy ?
dy *= -1;
}
|
Проверьте это сейчас! Бодрая правда? 🙂
Чтобы сделать это еще лучше, продолжайте экспериментировать с различными значениями — например, вместо умножения на -1, попробуйте -0,7 и посмотрите результаты.
Вывод
Итак, вы познакомились с классом Input.as, узнали, как с ним работать, и сделали несколько плавных движений всего за несколько минут. Я думаю, это считается отличным временем!
Пожалуйста, оставьте свои комментарии ниже и любые другие вопросы, я с удовольствием отвечу.
Но если у вас возникнут какие-либо проблемы, пожалуйста, проверьте ваш код дважды, сравните его с исходным файлом, а затем, если вы не можете заставить его работать, не стесняйтесь отправить вопрос.