Статьи

Создание виртуального джойстика для сенсорных устройств

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


Прежде чем вы сможете скомпилировать исходные файлы, предоставленные в этом руководстве, загрузите библиотеку GreenSock TweenLite для AS3 в подпапку «greensock» в папке вашего проекта. (Обсуждается на шаге 18 ).


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

Если у вас есть сенсорное устройство, поддерживающее Flash, откройте на нем эту страницу и попробуйте! В противном случае с помощью мыши перетащите джойстик или нажмите кнопку.


Давайте начнем с создания нового документа AS3 во Flash Professional CS5.

Новый документ AS3

Перейдите в «Настройки документа» на панели «Свойства» и убедитесь, что размер документа (550×400) и цвет фона (# 000000) соответствуют рисунку ниже:

Свойства документа

На панели «Свойства» укажите имя класса документа « com.MyApp ». Это класс, который мы создадим, который будет представлять основное приложение (подробнее здесь ). Мы собираемся позже создать другие классы, специфичные для джойстика, чтобы мы могли включить джойстик в любое другое приложение с парой строк кода.

Сохраните файл как «JoystickApp.fla».


Класс документа

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

Изменить класс документа

Когда вас попросят выбрать программное обеспечение, которое вы хотите использовать для редактирования определения класса, выберите Flash Professional. Вы должны увидеть новое определение класса, предварительно заполненное в новом файле ActionScript:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
package com {
     
    import flash.display.MovieClip;
     
     
    public class MyApp extends MovieClip {
         
         
        public function MyApp() {
            // constructor code
        }
    }
     
}

Сохраните этот файл .as как «MyApp.as» в той же папке, что и файл .fla в подпапках «\ com \». Обратите внимание, что вы можете указать свои собственные имена и структуру папок. Структура папки относится к структуре вашего пакета AS.


На этом шаге мы нарисуем базовый набор кругов для представления нашего джойстика. На более поздних этапах мы улучшим пользовательский интерфейс, чтобы соответствовать нашим джазовым потребностям. Нарисуйте круг на сцене вашего .fla файла. Дайте ему следующие свойства. Ширина: 160, Высота: 160, Цвет: #CCCCCC. Поместите это в x: 100, y: 300.

Преобразуйте этот круг в мувиклип и назовите мувиклип « Joystick ». Также не забудьте выбрать точку регистрации в качестве центра при конвертации ( Пункт регистрации ).

Поместите мувиклип « Joystick » на сцену в левом нижнем углу, как показано на рисунке ниже. Это только для справки. Мы добавим MovieClips динамически на сцене из класса « MyApp » позже.

Джойстик MovieClip на сцене

Нарисуйте еще один круг (поменьше) на сцене со значениями Ширина: 50 пикселей, Высота: 50 пикселей. Преобразуйте то же самое в новый мувиклип и назовите его « JoystickKnob ». Поместите его поверх мувиклипа « Joystick », как показано на рисунке ниже.

JoystickKnob MovieClip

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


Давайте теперь свяжем пользовательский интерфейс с их пользовательскими классами. Перейдите в библиотеку и щелкните правой кнопкой мыши по мувиклипу « Joystick ». Выберите «Свойства».

Установите флажок «Экспорт для ActionScript». Измените имя своего класса на «com.controls.Joystick». Мы создадим подпапку в папке «com», и у нас будет код, связанный с элементами управления в пакете «com.controls».

Класс MovieClip джойстика

Нажмите на значок карандаша рядом с вашим именем класса. Выберите «Flash Professional», если вас попросят редактора. Создается новый файл .as с именем класса « Joystick », расширенный от класса «MovieClip».

Повторите тот же процесс для другого мувиклипа » JoystickKnob «. Укажите имя класса «com.controls.JoystickKnob».

Сохраните два файла классов как «Joystick.as» и «JoystickKnob.as» соответственно.

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

Библиотека

Рекомендуется установить происхождение ручки относительно джойстика. Это поможет нам вернуть ручку в исходное положение, как только ручка будет перетащена в другое место и отпущена.

Для этого мы будем использовать два простых свойства в классе « JoystickKnob ».

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package com.controls {
     
    import flash.display.MovieClip;
     
     
    public class JoystickKnob extends MovieClip {
        private var _origin_x:Number;
        private var _origin_y:Number;
         
        public function JoystickKnob() {
            // constructor code
        }
    }
     
}

Давайте теперь напишем методы getter и setter для чтения и записи свойств _origin_x и _origin_y . Добавьте следующие методы в класс « JoystickKnob ».

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
public function get origin_x():Number {
    return _origin_x;
}
 
public function set origin_x(o_x:Number):void {
    _origin_x = o_x;
}
 
public function get origin_y():Number {
    return _origin_x;
}
 
public function set origin_y(o_y:Number):void {
    _origin_y = o_y;
}

Обратите внимание, что имена функций не имеют «_» (подчеркивание) в начале своих имен. Это потому, что мы просто хотели, чтобы имена внешних классов были origin_x и origin_y .


Начнем с добавления параметров в конструктор класса « Joystick ». Мы примем 2 параметра — left_margin:Number и bottom_margin:Number . Это поможет нам разместить джойстик там, где мы хотим, когда создаем экземпляр мувиклипа.

Позже мы назначим эти два параметра частным переменным класса « Joystick ». Ваш код должен выглядеть примерно так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package com.controls {
     
    import flash.display.MovieClip;
     
    public class Joystick extends MovieClip {
        private var my_x:Number;
        private var my_y:Number;
         
        public function Joystick(margin_left:Number, margin_bottom:Number) {
            my_x = margin_left;
            my_y = margin_bottom;
        }
    }
     
}

Теперь нам нужно написать метод initialize () для установки положения джойстика на экране. Мы также добавим мувиклип JoystickKnob динамически в этом методе. Этот метод содержит параметр типа «Событие». Пока не беспокойся об этом. Мы придем к этому через минуту.

Непосредственно перед динамическим добавлением мувиклипа « JoystickKnob » нам нужно импортировать класс « JoystickKnob » в этот класс. Добавьте следующий оператор импорта:

1
import com.controls.JoystickKnob;

Теперь, когда мы импортировали класс « JoystickKnob », объявите переменную в вашем классе, чтобы представить ручку.

1
private var knob:JoystickKnob;

Теперь добавьте следующую функцию в ваш класс.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
private function init(e:Event=null):void {
    this.x = my_x + this.width / 2;
    this.y = stage.stageHeight — my_y — this.height / 2;
 
    knob = new JoystickKnob();
    knob.x = 0;
    knob.y = 0;
 
    knob.origin_x = 0;
    knob.origin_y = 0;
 
    addChild(knob);
 
    // knob.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
    // stage.addEventListener(MouseEvent.MOUSE_UP, mouseReleased);
     
    knob.buttonMode = true;
}

Как вы можете видеть, мы разместили мувиклип « Joystick » на сцене в соответствии с полями, принятыми конструктором, и добавили « knob » на сцене. Мы также добавили некоторые слушатели событий в « knob » и « stage » для MOUSE_DOWN и MOUSE_UP соответственно. Мы напишем методы mouseDown() и mouseReleased() позже в классе, чтобы разрешить перетаскивание ручки. Слушатели событий в настоящее время закомментированы; НЕ ЗАБЫВАЙТЕ раскомментировать две строки после того, как мы напишем методы.

Обратите внимание, что MouseEvent.<EVENT_NAMES> преобразуется в сенсорные события на сенсорном планшете / устройстве. Поэтому вполне нормально использовать события мыши вместо касания.

Теперь нам нужно вызвать этот метод из конструктора. Вместо того, чтобы вызывать метод вслепую, хорошей практикой является проверка существования « stage » и только затем вызов этого. Если свойство » stage » для MovieClip » Joystick » к этому времени еще не инициализировано (что является угловым случаем), метод init() должен быть вызван после того, как он может определить свойство » stage «. Поэтому мы вызываем метод init() как показано ниже (добавьте этот набор строк внутри вашего конструктора):

1
2
3
4
5
if (stage) {
    init();
} else {
    addEventListener(Event.ADDED_TO_STAGE,init);
}

Мы не должны забывать удалить добавленный EventListener. Поэтому давайте добавим пару строк в метод init() начало init() :

1
2
3
if (hasEventListener(Event.ADDED_TO_STAGE)) {
    removeEventListener(Event.ADDED_TO_STAGE,init);
}

Прежде чем мы выполним этот код и проверим вывод, нам нужно создать экземпляр класса « Joystick » внутри класса «MyApp». Добавьте следующий код в ваш конструктор класса «MyApp». Также импортируйте класс « Joystick » и объявите свойство для представления мувиклипа « Joystick ». Итак, ваш класс «MyApp» должен выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
package com {
     
    import flash.display.MovieClip;
    import com.controls.Joystick;
     
    public class MyApp extends MovieClip {
        private var joystick:Joystick;
         
        public function MyApp() {
            joystick = new Joystick(30, 30);
            addChild(joystick);
        }
    }
}

Теперь вы можете выполнить и протестировать приложение. Это просто динамически добавит мувиклип « Joystick » на сцену, оставляя поле в 30 пикселей слева и снизу, как передано конструктору. Вот скриншот SWF:

Основной SWF

Теперь пришло время добавить взаимодействие к мувиклипу JoystickKnob , сделать его перетаскиваемым по всему периметру джойстика. В классе « Joystick » раскомментируйте два прослушивателя событий, которые мы комментировали ранее. Теперь мы напишем методы mouseDown() и mouseReleased() для « knob ».

Мы просто добавим метод startDrag() внутри метода mouseDown() . Задайте свойства, чтобы указать границу мувиклипа « Joystick ». Не забудьте импортировать классы flash.geom.Rectangle и flash.events.MouseEvent (если вы этого не сделали).

1
2
3
private function mouseDown(event:MouseEvent):void {
    knob.startDrag(false,new Rectangle( — this.width / 2, — this.height / 2,this.width,this.height));
}

mouseReleased() является простым stopDrag() . Позже мы добавим больше кода, чтобы «оживить» назад ручку к ее « origin_x » и « origin_y ». Прямо сейчас, это просто огрызается назад, когда вы отпускаете мышь.

1
2
3
4
5
6
private function mouseReleased(event:MouseEvent):void {
    knob.stopDrag();
     
    knob.x = knob.origin_x;
    knob.y = knob.origin_y;
}

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


Давайте попробуем обнаружить движение « knob » в джойстике и определить, как мы хотим использовать его для простого спрайта вида сверху вниз.

Когда « knob » перемещается, нам нужно прочитать ее положение относительно мувиклипа « Joystick » и изменить спрайт. Мы создадим спрайт позже. А пока давайте просто прочитаем значение положения ручки.

Чтобы прочитать положение ручки при перетаскивании, нам нужно включить метод ENTER_FRAME . Добавьте приведенный ниже метод в класс « Joystick »:

1
2
3
private function knobMoved(event:Event):void {
    trace(knob.x + «, » + knob.y);
}

Добавьте ENTER_FRAME событий ENTER_FRAME непосредственно перед тем, как startDrag() произойдет внутри метода mouseDown() :

1
2
3
4
private function mouseDown(event:MouseEvent):void {
    this.addEventListener(Event.ENTER_FRAME, knobMoved);
    knob.startDrag(false,new Rectangle( — this.width / 2, — this.height / 2,this.width,this.height));
}

Мы не хотим, ENTER_FRAME метод ENTER_FRAME работал все время. Это может оказаться дорогостоящим. Следовательно, мы добавим слушателя только тогда, когда начинается перетаскивание, и удалим слушателя, как только мы stopDrag() . Добавьте removeEventListener сразу после stopDrag() .

1
2
3
if (this.hasEventListener(Event.ENTER_FRAME)) {
    this.removeEventListener(Event.ENTER_FRAME, knobMoved);
}

Скомпилируйте и выполните SWF сейчас, чтобы проверить это. Прочитайте значения в окне вывода.


Поскольку мы стремимся к сенсорным экранам, физическое ощущение элементов управления отсутствует. Следовательно, существует очевидная вероятность того, что пользователь может просто коснуться за пределами ручки и попытаться перетащить джойстик вокруг. Несправедливо и неудобно ожидать, что пользователь точно коснется и перетянет ручку. Чтобы преодолеть эту путаницу, рекомендуется закрепить ручку в том месте, где происходит прикосновение к джойстику.

На этом шаге мы зафиксируем мувиклип « knob » в точке на « Joystick », где может произойти фактическое касание.

В классе « Joystick » добавьте следующий закрытый метод:

1
2
3
4
5
private function snapKnob(event:MouseEvent):void {
    knob.x = this.mouseX;
    knob.y = this.mouseY;
    mouseDown(null);
}

В приведенном выше коде мы устанавливаем координаты x и y MovieClip « mouseX mouseY координат mouseY mouseX и mouseY мувиклипа « Joystick ». Мы также вызываем метод mouseDown(null) чтобы начать процесс перетаскивания.

Этот метод будет вызван добавлением прослушивателя событий. Давайте сделаем это в методе init (). Прямо вокруг слушателя событий, который вызывает метод mouseDown() . Добавьте следующую строку в метод init() :

1
2
3
this.addEventListener(MouseEvent.MOUSE_DOWN, snapKnob);
knob.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseReleased);

Согласно приведенному выше коду, как только мувиклип « Joystick » (« this ») получает событие MOUSE_DOWN , он вызывает метод snapKnob() . В свою очередь, этот метод привязывает MovieClip к « knob » в положение касания. Позже, вызывая метод mouseDown(null) , мы startDrag() процесс startDrag() чтобы пользователь чувствовал, что он коснулся ручки.


Теперь, когда у нас работает базовый джойстик, нам нужно создать мувиклип « Hero », чтобы начать его перемещение в соответствии со значениями положения « knob ».

Перейдите к файлу .fla и нарисуйте круг, как показано ниже. Преобразуйте его в MovieClip и используйте центральную точку регистрации ( Пункт регистрации ) опять таки. Дайте мувиклипу название « Hero ». Вы можете указать свойства — Ширина: 30 пикселей, Высота: 30 пикселей, Цвет: # 0099CC.

Кроме того, экспортируйте в ActionScript при преобразовании в MovieClip и com.Hero ему имя класса « com.Hero ».

Экспорт героя MovieClip

Так будет выглядеть мувиклип после его преобразования.

Hero MovieClip

Теперь мы должны удалить MovieClip со сцены, поскольку мы будем динамически добавлять мувиклип «Hero» на сцене из класса « MyApp ».

После того, как вы экспортировали мувиклип с пользовательским именем класса «com.Hero», не забудьте создать новый файл класса и сохранить его в папке «com».


Давайте откроем «MyApp.as» и динамически добавим мувиклип «Герой». Так как мы экспортировали мувиклип «Герой» из библиотеки «JoystickApp.fla», откройте «MyApp.as», импортируйте класс «com.Hero», объявите новое свойство « hero » и добавьте следующий код перед «джойстиком». MovieClip создается в конструкторе. Вот так должен выглядеть ваш класс « MyApp »:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
package com {
     
    import flash.display.MovieClip;
    import com.controls.Joystick;
    import com.Hero;
     
    public class MyApp extends MovieClip {
        private var joystick:Joystick;
        private var hero:Hero;
         
        public function MyApp() {
            hero = new Hero();
            hero.x = stage.stageWidth/2;
            hero.y = stage.stageHeight/2;
            addChild(hero);
             
            joystick = new Joystick(30, 30);
            addChild(joystick);
        }
    }
}

Обратите внимание, что мы также выровняли мувиклип по центру сцены. Если вы скомпилируете и запустите SWF, вы должны увидеть мувиклип « hero » в центре сцены.


Теперь, чтобы мувиклип « joystick » получил доступ к мувиклипу « hero », добавленному на сцену, мы будем использовать простой метод передачи мувиклипа « hero » в конструктор мувиклипа « joystick » вместе с « margin_left » и « margin_bottom » свойства.

Откройте класс «com.controls.Joystick». Импортируйте класс com.Hero и добавьте третий параметр в конструктор, как показано ниже:

1
public function Joystick(margin_left:Number, margin_bottom:Number, hero_mc:Hero) {

Теперь, так как мы хотим, чтобы этот параметр был доступен через этот класс, мы создадим приватную переменную с именем « hero » в этом классе:

1
private var hero:Hero;

Позже назначьте третий параметр, который мы только что передали этой переменной внутри конструктора, как показано ниже.

1
hero = hero_mc;

Последний шаг — передача мувиклипа « hero » из класса «MyApp» после его добавления в мувиклип « joystick » во время его создания. Добавьте (передайте) третий параметр в конструктор MovieClip « joystick ».

1
joystick = new Joystick(30, 30, hero);

На этом этапе MovieClip « hero » на сцене доступен из MovieClip « joystick ».


Давайте подготовим класс «Герой», чтобы иметь возможность передвигаться, как диктует мувиклип « joystick ». К настоящему времени мы должны были создать базовый класс, который выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
package com {
     
    import flash.display.MovieClip;
     
    public class Hero extends MovieClip {
         
        public function Hero() {
             
        }
    }
}

Добавьте следующие свойства в класс. Мы будем использовать их во время движения.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
package com {
     
    import flash.display.MovieClip;
     
    public class Hero extends MovieClip {
        private var walk_speed = 2;
         
        public var move_left:Boolean = false;
        public var move_up:Boolean = false;
        public var move_right:Boolean = false;
        public var move_down:Boolean = false;
         
        public function Hero() {
             
        }
    }
}

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

Четыре булевых свойства, которые мы добавили, используются для определения направления движения героя. Мы установим эти свойства в true или false через класс «Джойстик». Прежде чем мы это сделаем, давайте подготовим класс «Герой» с возможностью двигаться.

Добавьте пустой метод с именем heroMove() в класс Hero.

1
2
3
private function heroMove(event:Event):void {
             
}

Мы будем вызывать этот метод через ENTER_FRAME событий ENTER_FRAME . Добавьте прослушиватель событий в конструктор этого класса.

1
2
3
public function Hero() {
    this.addEventListener(Event.ENTER_FRAME, heroMove);
}

Опять же, пожалуйста, не забудьте импортировать универсальные классы, такие как » flash.events.Event » и т. Д.


Теперь мы попросили heroMove() метод heroMove() в классе Hero для события ENTER_FRAME . Здесь мы проверим 4 булевых переменных и переместим героя соответственно. Но прежде чем мы это сделаем, давайте добавим конкретный код в класс «Джойстик». Откройте файл «Joystick.as» и перейдите к методу « knobMoved() ».

В методе есть трассировка, которая отслеживает координаты x и y мувиклипа « knob ». Замените оператор трассировки следующими выделенными строками, и ваш knobMoved() » knobMoved() » должен выглядеть следующим образом:

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
private function knobMoved(event:Event):void {
    // LEFT OR RIGHT
    if (knob.x > 20) {
        hero.move_right = true;
        hero.move_left = false;
    } else if (knob.x < -20) {
        hero.move_right = false;
        hero.move_left = true;
    } else {
        hero.move_right = false;
        hero.move_left = false;
    }
     
    // UP OR DOWN
    if (knob.y > 20) {
        hero.move_down = true;
        hero.move_up = false;
    } else if (knob.y < -20) {
        hero.move_down = false;
        hero.move_up = true;
    } else {
        hero.move_down = false;
        hero.move_up = false;
    }
}

В приведенном выше коде мы разделили код, связанный с движением «Влево или Вправо» и «Вверх или Вниз», поскольку не будет сценария, в котором Герой будет двигаться влево и вправо или двигаться вверх и вниз. Таким образом, мы устанавливаем для 4 переменных направления MovieClip « hero » значение true или false основываясь на положениях x и y MovieClip « knob » относительно центра MovieClip « joystick ».

На рисунке ниже показана простая логика:

Обзор области джойстика

На рисунке выше показаны 2 красные пунктирные линии, пересекающиеся в центре, которые представляют (0,0) или «точку начала» или «точку регистрации» мувиклипа « joystick ».

4 красных заштрихованных прямоугольника представляют область, в которой значения x и y мувиклипа « knob » будут переданы мувиклипу « hero ». Также текст на красных заштрихованных прямоугольниках представляет направления.

Синие прямоугольники представляют одно простое направление. Пока сенсорная / ручная ручка находится здесь, она просто приказывает двигаться в одном направлении.

Также обратите внимание на квадрат 40х40 пикселей (серый) в центре. Они представляют область желоба, в которой, если мувиклип « knob » перемещен, ничего не происходит. Эта область желоба предназначена для легкого движения пальцем по экрану при прикосновении, не нарушая поведение игры. Поскольку пользователь не ощущает никакой физической поверхности, эта область желоба необходима, по крайней мере, для некоторых основных игр, если только предполагается, что игра не является сверхчувствительной к джойстику.

Давайте посмотрим на разделение «Влево или Вправо»:

Разрыв джойстика влево или вправо

Вот разделение «вверх и вниз»:

Разрыв джойстика вверх и вниз

Теперь мы попросили heroMove() метод heroMove() в классе Hero для события ENTER_FRAME . Здесь мы проверим 4 булевых свойства мувиклипа « hero » и переместим его соответственно.

heroMove() включим следующие выражения в heroMove() чтобы MovieClip «hero» перемещался в соответствии с основным движением ручки.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
private function heroMove(event:Event):void {
    if (move_left) {
        this.x -= walk_speed;
    }
    if (move_up) {
        this.y -= walk_speed;
    }
    if (move_right) {
        this.x += walk_speed;
    }
    if (move_down) {
        this.y += walk_speed;
    }
}

Наконец, не забудьте сбросить 4 логические переменные в « false » в mouseReleased() « mouseReleased() » класса «Joystick». Невыполнение этого условия приведет к постоянному движению мувиклипа « hero », даже если не перетаскивать ручку (это вызывается heroMove() « heroMove() » из класса «Hero» через событие ENTER_FRAME ).

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
private function mouseReleased(event:MouseEvent):void {
    knob.stopDrag();
     
    hero.move_left = false;
    hero.move_up = false;
    hero.move_right = false;
    hero.move_down = false;
     
    if (this.hasEventListener(Event.ENTER_FRAME)) {
        this.removeEventListener(Event.ENTER_FRAME, knobMoved);
    }
     
    knob.x = knob.origin_x;
    knob.y = knob.origin_y;
}

Вот как должен вести себя ваш SWF:

Идите вперед и переместите джойстик внизу.


Мы пытаемся провести игру сверху вниз с изображением человека, который ходит вокруг. Разделяя сложную графику и анимацию, мы по крайней мере хотели бы охватить направление или вращение Героя в соответствии с его движением. Для этого мы сделаем небольшое дополнение к мувиклипу «hero» в файле .fla. Мы добавим что-то похожее на нос.

Откройте символ «Герой» в библиотеке и добавьте маленький кружок, который будет представлять нос. Ниже приведена увеличенная версия объекта, нарисованного внутри символа «Герой», а рядом с ним — фактический размер мувиклипа.

Герой нос

Давайте теперь изменим свойство «вращения» мувиклипа «герой» в классе «Герой». Откройте класс Hero и добавьте следующий код в начало метода heroMove ():

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
private function heroMove(event:Event):void {
    if (move_left && move_up) {
        this.rotation = -45;
    } else if (move_right && move_up) {
        this.rotation = 45;
    } else if (move_left && move_down) {
        this.rotation = 225;
    } else if (move_right && move_down) {
        this.rotation = 135;
    } else if (move_right) {
        this.rotation = 90;
    } else if (move_left) {
        this.rotation = -90;
    } else if (move_up) {
        this.rotation = 0;
    } else if (move_down) {
        this.rotation = 180;
    }
     
    if (move_left) {
        this.x -= walk_speed;
    }
    if (move_up) {
        this.y -= walk_speed;
    }
    if (move_right) {
        this.x += walk_speed;
    }
    if (move_down) {
        this.y += walk_speed;
    }
}

В приведенном выше коде мы сделали проверки для всех 8 направлений и соответственно повернули мувиклип «герой». Компиляция и запуск вашего кода теперь должны привести к следующему:

На этом завершается основное поведение джойстика и героя.


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

Мы решим использовать библиотеку TweenLite, разработанную GreenSock . Это очень легкий движок анимации, который быстр для разработчика и меньше влияет на производительность вашей анимации.

  1. Перейдите по адресу http://www.greensock.com/tweenlite/ и нажмите кнопку «Скачать AS3» с правой стороны.
  2. Прочитайте и примите условия и положения, и как только загрузка будет завершена, вы должны иметь greensock-as3.zip.
  3. Распакуйте его в папку.
  4. Найдите папку «com» ​​внутри извлеченной папки. Перейдите в папку «com».
  5. Вы должны найти подпапку с именем «greensock». Это папка, которая нам нужна.

Теперь есть 2 распространенных способа настройки этой библиотеки для использования в ваших проектах.

  1. Скопируйте эту папку в папку вашего проекта.
  2. ИЛИ

  3. Свяжите это динамически от того, где это когда-либо до вашего проекта.

Связывание динамически имеет преимущество. Вы можете использовать одну и ту же папку, которая существует в каком-то другом общем месте во многих разных проектах. Если вы решите скопировать папку «greensock» в папку вашего проекта, вы сможете использовать ее только в этом проекте. Выполнение этого в конечном итоге для другого проекта может привести к дублированию библиотеки GreenSock, и если сам движок выпущен с исправлениями ошибок или новыми функциями, вам потребуется обновить локальные папки для многих различных проектов.

Однако для этого проекта мы просто скопируем папку в местоположение нашего проекта.

  • Скопируйте папку «greensock» в папку «com» ​​вашего проекта. Изображение ниже должно помочь вам понять окончательное местоположение папки «greensock».
Папка библиотеки GreenSock

Теперь мы импортируем классы, необходимые для анимации регулятора. Откройте файл «Joystick.as» и добавьте этот оператор импорта:

1
import com.greensock.*;

Давайте добавим простую анимацию к кнопке, когда она будет выпущена и должна вернуться к своему источнику. Это делается в файле «Joystick.as».

Добавьте следующий метод в класс:

1
2
3
private function mover():void {
    TweenLite.to(knob, 0.5, {x: knob.origin_x, y:knob.origin_y});
}

Теперь добавьте вызов функции «mover ()» в метод «mouseReleased ()» в конце:

1
mover();

Не забудьте удалить следующие 2 строки в методе mouseReleased ():

1
2
knob.x = knob.origin_x
knob.y = knob.origin_y;

Теперь попробуйте перетащить ручку и отпустить ее от центра. Обратите внимание на анимацию в приведенном ниже SWF:


Поскольку джойстик возвращает ручку в исходное положение, он также добавляет естественный эффект отскока. К счастью, у нас очень мало работы для достижения этой цели с использованием TweenLite.

Откройте «Joystick.as» и импортируйте пакет TweenLite, который включает эффекты замедления:

1
import com.greensock.easing.*;

TweenLite поддерживает свойство, которое позволяет вам определять тип анимации. В нашем случае нам нужен эффект отскока. Итак, давайте включим свойство » ease » в метод » TweenLite.to() «, как показано ниже:

1
TweenLite.to(knob, 0.5, {x: knob.origin_x, y:knob.origin_y, ease:Bounce.easeOut});

Проверьте ниже SWF:

Ошибка

Вы должны быть в состоянии найти небольшой глюк или ошибку в вышеуказанном SWF. Если вы быстро попытаетесь нажать «вокруг» ручки и отпустить ее, ручка не будет реагировать. Это из-за анимации. К тому времени, когда вы быстро нажмете более одного раза, анимация, которая была запущена с первого касания, еще не закончена. Без завершения анимации TweenLite заставляет «ручку» анимировать обратно к своему источнику.

Исправление

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

Мы начнем с создания идентификатора (переменной) типа «TweenLite». Создайте эту новую переменную в классе «Джойстик»:

1
private var knob_tween:TweenLite;

Теперь анимация, которую мы выполняем с использованием «TweenLite.to ()», должна быть назначена для идентификации с помощью этого свойства, которое мы создали. Нам нужно сделать небольшое изменение в заявлении об анимации движения. Удалите вызов статического метода to () и измените его следующим образом:

1
knob_tween = new TweenLite(knob, 0.5, {x: knob.origin_x, y:knob.origin_y, ease:Bounce.easeOut});

Новое свойство «knob_tween» — это то, которое мы используем для принудительной остановки анимации. Перейдите к методу «mouseDown ()» и добавьте следующие операторы в начало метода:

1
2
3
if (knob_tween) {
    knob_tween.kill();
}

Проверьте и сравните SWF ниже с предыдущим. Быстро нажмите на «Джойстик» MovieClip. Обратите внимание на изменение в поведении.

Это охватывает окончательное поведение джойстика.


До сих пор мы просто использовали 2 плоских цветных круга для обозначения джойстика и ручки. Я не буду подробно останавливаться на этом разделе учебника, так как он субъективен и не имеет пределов тому, насколько креативным он может стать. Я покажу вам несколько примеров конструкций, которые можно адаптировать к этой логике, чтобы улучшить впечатление от вашей игры.

Пример 1 (скриншот)

Пример дизайна 1

Пример 2 (скриншот)

Пример дизайна 2

Пример 3 (скриншот)

Пример дизайна 3

Мы рассмотрим окончательный код для вашей ссылки на каждый файл .as ниже.

MyApp.as

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
package com {
     
    import flash.display.MovieClip;
    import com.controls.Joystick;
    import com.Hero;
     
    public class MyApp extends MovieClip {
        private var joystick:Joystick;
        private var hero:Hero;
         
        public function MyApp() {
            hero = new Hero();
            hero.x = stage.stageWidth/2;
            hero.y = stage.stageHeight/2;
            addChild(hero);
             
            joystick = new Joystick(30, 30, hero);
            addChild(joystick);
        }
    }
}

JoystickKnob.as

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
package com.controls {
     
    import flash.display.MovieClip;
     
    public class JoystickKnob extends MovieClip {
        private var _origin_x:Number;
        private var _origin_y:Number;
         
        public function JoystickKnob() {
        }
         
        public function get origin_x():Number {
            return _origin_x;
        }
 
        public function set origin_x(o_x:Number):void {
            _origin_x = o_x;
        }
 
        public function get origin_y():Number {
            return _origin_x;
        }
 
        public function set origin_y(o_y:Number):void {
            _origin_y = o_y;
        }
    }
}

Hero.as

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
package com {
     
    import flash.display.MovieClip;
    import flash.events.Event;
     
    public class Hero extends MovieClip {
        private var walk_speed = 2;
         
        public var move_left:Boolean = false;
        public var move_up:Boolean = false;
        public var move_right:Boolean = false;
        public var move_down:Boolean = false;
         
        public function Hero() {
            this.addEventListener(Event.ENTER_FRAME, heroMove);
        }
         
        private function heroMove(event:Event):void {
            if (move_left && move_up) {
                this.rotation = -45;
            } else if (move_right && move_up) {
                this.rotation = 45;
            } else if (move_left && move_down) {
                this.rotation = 225;
            } else if (move_right && move_down) {
                this.rotation = 135;
            } else if (move_right) {
                this.rotation = 90;
            } else if (move_left) {
                this.rotation = -90;
            } else if (move_up) {
                this.rotation = 0;
            } else if (move_down) {
                this.rotation = 180;
            }
             
            if (move_left) {
                this.x -= walk_speed;
            }
            if (move_up) {
                this.y -= walk_speed;
            }
            if (move_right) {
                this.x += walk_speed;
            }
            if (move_down) {
                this.y += walk_speed;
            }
        }
    }
}

Joystick.as

001
002
003
004
005
006
007
008
009
010
011
012
013
014
+015
016
+017
018
019
020
021
022
023
024
025
026
027
028
029
+030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
+055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package com.controls {
     
    import flash.events.Event;
    import flash.display.MovieClip;
    import flash.events.MouseEvent;
    import flash.geom.Rectangle;
     
    import com.controls.JoystickKnob;
    import com.Hero;
     
    import com.greensock.*;
    import com.greensock.easing.*;
     
    public class Joystick extends MovieClip {
        private var my_x:Number;
        private var my_y:Number;
         
        private var knob:JoystickKnob;
        private var hero:Hero;
         
        private var knob_tween:TweenLite;
         
        public function Joystick(margin_left:Number, margin_bottom:Number, hero_mc:Hero) {
            my_x = margin_left;
            my_y = margin_bottom;
            hero = hero_mc;
             
            if (stage) {
                init();
            } else {
                addEventListener(Event.ADDED_TO_STAGE,init);
            }
        }
         
        private function init(e:Event=null):void {
            if (hasEventListener(Event.ADDED_TO_STAGE)) {
                removeEventListener(Event.ADDED_TO_STAGE,init);
            }
             
            this.x = my_x + this.width / 2;
            this.y = stage.stageHeight — my_y — this.height / 2;
 
            knob = new JoystickKnob();
            knob.x = 0;
            knob.y = 0;
 
            knob.origin_x = 0;
            knob.origin_y = 0;
 
            addChild(knob);
 
            this.addEventListener(MouseEvent.MOUSE_DOWN, snapKnob);
            knob.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
            stage.addEventListener(MouseEvent.MOUSE_UP, mouseReleased);
             
            knob.buttonMode = true;
        }
         
        private function snapKnob(event:MouseEvent):void {
            knob.x = this.mouseX;
            knob.y = this.mouseY;
            mouseDown(null);
        }
         
        private function mouseDown(event:MouseEvent):void {
            if (knob_tween) {
                knob_tween.kill();
            }
            this.addEventListener(Event.ENTER_FRAME, knobMoved);
            knob.startDrag(false,new Rectangle( — this.width / 2, — this.height / 2,this.width,this.height));
        }
         
        private function knobMoved(event:Event):void {
            // LEFT OR RIGHT
            if (knob.x > 20) {
                hero.move_right = true;
                hero.move_left = false;
            } else if (knob.x < -20) {
                hero.move_right = false;
                hero.move_left = true;
            } else {
                hero.move_right = false;
                hero.move_left = false;
            }
             
            // UP OR DOWN
            if (knob.y > 20) {
                hero.move_down = true;
                hero.move_up = false;
            } else if (knob.y < -20) {
                hero.move_down = false;
                hero.move_up = true;
            } else {
                hero.move_down = false;
                hero.move_up = false;
            }
        }
         
        private function mouseReleased(event:MouseEvent):void {
            knob.stopDrag();
             
            hero.move_left = false;
            hero.move_up = false;
            hero.move_right = false;
            hero.move_down = false;
             
            if (this.hasEventListener(Event.ENTER_FRAME)) {
                this.removeEventListener(Event.ENTER_FRAME, knobMoved);
            }
             
            mover();
        }
 
        private function mover():void {
            knob_tween = new TweenLite(knob, 0.5, {x: knob.origin_x, y:knob.origin_y, ease:Bounce.easeOut});
        }
    }
}

Это было базовое руководство о том, как сделать ваши игры готовыми для сенсорных устройств, добавив элемент управления на экране.

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

Для получения дополнительных руководств, советов по разработке Flash для устройств и импровизаций в приведенном выше коде посетите веб- сайт http://www.hsharma.com/tech .