На этом уроке мы собираемся создать небольшое приложение для перемещения танков. Суть этого конкретного руководства заключается в том, чтобы навести курсор на указатель мыши и двигаться в направлении щелчка мыши.
Окончательный результат предварительного просмотра
Давайте посмотрим на конечный результат, к которому мы будем стремиться:
Переместите мышь, чтобы нацелить башню, и щелкните в любом месте, чтобы танк подъехал к этой точке.
Шаг 1: Графика Введение
Что ж, давайте начнем .. Для этого урока нам понадобится танк и башня. Я использовал Google SketchUp 7, чтобы сделать мой.
Сначала я создал танк в целом. Затем я переключил режим просмотра программы на «параллельную проекцию», расположив камеру под углом 45 ° к резервуару, чтобы создать иллюзию изометрии в игре.
Пожалуйста, не судите меня за ужасную графику, я действительно могу сделать намного лучше, но это только для объяснения 🙂
Затем я спрятал турель, оставив видимым только корпус танка, и повернул корпус на 45 ° восемь раз, представляя каждую позицию отдельно. Таким образом, я достиг 8 различных видов тела. Я сделал то же самое с башней, пока танк был спрятан. Я сохранил все 16 фото в формате PNG 24 с альфа-каналом. Вы можете увидеть окончательный результат ниже. (На самом деле этого недостаточно для такого движения, было бы лучше иметь вдвое больше просмотров танка, но этого достаточно для целей данного урока.)
,
Конечно, вам не обязательно использовать Google SketchUp, вы можете использовать 3ds Max или Maya или что угодно, вы также можете использовать мою графику на практике, если вы не хотите или не можете создавать свою собственную графику.
Шаг 2: Новый проект Flash
Теперь откройте Flash (я использую Adobe Flash CS4) и выберите «Создать новый Flash-файл» (Actionscript 3.0). Нам понадобится только сделать MovieClip танка и подключить к нему класс Game позже.
,
Шаг 3. Установите свойства документа
Щелкните правой кнопкой мыши по сцене и перейдите к пункту «Свойства документа». Сделайте это 600 x 400 (или как хотите) и 21 кадр в секунду (эта частота кадров кажется мне оптимальной, поэтому я почти всегда использую ее. Хотя это не имеет значения).
Нажмите ОК. Перейдите в File> Save as и сохраните этот файл как tank.fla в какой-то папке на вашем компьютере (я рекомендую вам создать папку Tank и поместить файл внутрь).
Шаг 4: Импортируйте ваши изображения танка в библиотеку
Теперь перейдите в File> Import> Import to library . Найдите папку, в которой вы сохранили свои восемь изображений танков, выберите их все и импортируйте в библиотеку.
,
Шаг 5: Новый символ
Создайте новый пустой символ, нажав на этот маленький значок в библиотеке:
Выберите тип MovieClip и назовите символ «танк». Поместите точку регистрации в центр (точка регистрации — это крошечный черный квадрат в сетке белых квадратов для тех, кто не знает).
Шаг 6: отредактируйте символ
После того, как символ создан, он появляется в библиотеке (его имя «tank» — это просто косметическое имя, которое используется исключительно в библиотеке, поэтому не имеет значения, как вы его называете). Откройте его, дважды щелкнув его значок. Затем возьмите 1.png из библиотеки и перетащите его на сцену символа. Совместите изображение с точкой регистрации символа, как на этом скриншоте:
Вы хотите, чтобы точка регистрации находилась в центре круга поворота танка.
Шаг 7: создайте семь пустых ключевых кадров
Перейти на временную шкалу символа. Переименуйте «Слой 1» в «Танк». Изображение тела вашего танка (1.png) должно быть в первом кадре этого слоя. Щелкните второй кадр и, не отпуская кнопку мыши, перетащите курсор на восьмой кадр, выбирая кадры со 2 по 8. Затем щелкните правой кнопкой мыши эту выбранную область и выберите «Преобразовать в пустые ключевые кадры».
Шаг 8: перетащите все изображения на сцену
Когда 7 пустых ключевых кадров созданы, выберите второй кадр и перетащите 2.png к нему, выровняв изображение с точкой регистрации (так же, как вы сделали с 1.png); воображая, что точка регистрации — это ось, по которой танк будет вращаться при повороте. Сделайте то же самое с остальными кадрами. Вам не нужно выравнивать его очень точно, но чем точнее вы выровняете его, тем лучше будет выглядеть движение, когда танк пытается следовать за курсором по ходу игры.
Шаг 9. Запрет воспроизведения временной шкалы.
После того, как вы перетащили каждое изображение на сцену символа и выровняли их, выберите первый кадр и нажмите F9, чтобы открыть панель действий. Введите единственный метод «stop ();» в нем и закройте панель. Это важный шаг, потому что мы не хотим, чтобы наш танк автоматически начал вращаться, как только он будет добавлен на сцену.
Шаг 10: создай турель ролик
Перейдите в библиотеку и создайте новый символ MovieClip. Назовите это турель . Дважды щелкните значок символа и сделайте то же самое, что вы сделали с танковым MovieClip (шаги 4–8) к башне, но используя изображения башни. Выровняйте его по точке регистрации таким образом, в точке, вокруг которой турель естественно повернет:
Обратите внимание, что я назвал изображения башен следующим образом: 1-.png, 2-.png и т. Д., Чтобы они не заменяли изображения танка при импорте в библиотеку. Вы можете использовать папки для размещения ваших изображений. В этом случае ваши изображения башни и танка могут иметь одинаковые имена.
Шаг 11: Сборка танка
После того, как мы закончили с символом башни, снова откройте символ танка, создайте новый слой над слоем «Танк» и перетащите фрагмент ролика из библиотеки на этот слой. Совместите башню с корпусом резервуара. Результат должен выглядеть так:
Шаг 12: Дайте башне имя экземпляра
Нажмите один раз на башню, чтобы выбрать ее (синий прямоугольник вокруг нее укажет, что она выбрана):
… затем перейдите в свойства и дайте ему имя экземпляра mTurret (для башни MovieClip):
Нажмите на ссылку «Сцена 1», чтобы выйти из режима редактирования символов.
Шаг 13: Экспортируй свой танк для ActionScript
Щелкните правой кнопкой мыши символ резервуара в библиотеке, выберите «Свойства» (или «Связывание», если вы используете Flash CS3) в раскрывающемся меню (убедитесь, что вы находитесь в расширенном режиме), выберите «Экспорт для Actionscript» и для класса Имя типа в «Танк» (с большой буквы). Этот шаг позволит нам в будущем подключить наш Tank MovieClip к экземплярам, созданным с использованием нашего класса Tank.
Графическая часть на этом закончена; Вы можете удалить танк со сцены. Мы добавим это программно позже.
Шаг 14. Создайте новый файл ActionScript
В инструменте Flash Authoring перейдите в « Файл»> «Создать» и создайте новый файл ActionScript.
Шаг 15: сохраните ваш файл
Перейдите в папку, в которой вы сохранили файл tank.fla, и создайте новую папку с именем «main» внутри. Сохраните файл ActionScript в этой папке как TankMaker.as . Поэтому местоположение этого файла должно быть: tank / main / TankMaker.as
Шаг 16: Давайте напишем некоторый код
Прежде всего, создайте пакет и импортируйте в него необходимые классы:
1
2
3
4
5
6
|
package main {
import flash.display.*;
import flash.events.*;
}
|
Слово «основной» здесь означает расположение этого файла относительно нашего tank.fla.
Нам понадобятся классы «display» для отображения наших активов на экране и «events» для отслеживания событий мыши.
Шаг 17: Открытый класс и переменные
Теперь нам нужно объявить открытый класс TankMaker (в соответствии с именем файла Actionscript) и необходимые переменные:
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
|
package main {
import flash.display.*;
import flash.events.*;
public class TankMaker extends Sprite {
// the instance of our Tank class (which we exported for actionscript before)
private var tank:Tank;
// the vars to keep the coordinates of the point where we want our tank to move
private var moveTankToX:Number;
private var moveTankToY:Number;
// coordinates of the point at which the tank aims its turret
private var turnTurretToX:Number;
private var turnTurretToY:Number;
// current position of the tank
private var currentTankPositionX:Number;
private var currentTankPositionY:Number;
private var tankSpeed:Number = 2;
// the point at which the tank moves after a mouse click
private var clickPoint:Object;
// the angle of tank and turret rotation in radians
private var Atan2:Number;
private var turretAtan2:Number;
}
}
|
Я объявил все переменные как «частные», потому что я не хочу, чтобы они были доступны из любого места за пределами этого класса.
Шаг 18: создайте метод конструктора
Непосредственно под последней переменной создайте публичную функцию и назовите ее TankMaker. Это будет конструктор класса. Затем добавьте в него прослушиватель событий для Event.ADDED_TO_STAGE, чтобы мы могли создать наш объект-танк только после этапа. Затем передайте это событие методу addStage.
1
2
3
4
5
|
public function TankMaker() {
addEventListener(Event.ADDED_TO_STAGE, addStage);
}
|
Шаг 19: создайте экземпляр Tank
После того, как этап создан и событие ADDED_TO_STAGE вызвало метод addStage (), самое время создать экземпляр танка.
Объявите приватную функцию и назовите ее addStage. Тип данных функции будет: Событие. И возвращаемый тип будет «void», потому что мы не собираемся ничего возвращать из него.
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 addStage (e:Event):void {
//create a new tank instance of the movie clip
// which you had exported for actionscript
tank = new Tank();
// now a little trick, I scaled my tank down
// to the size of about one fourth of its original size
// so that is wasn’t so huge
tank.scaleX = 0.25;
tank.scaleY = 0.25;
// set the initial position of the tank right
// in the center of the stage
tank.x = stage.stageWidth / 2;
tank.y = stage.stageHeight / 2;
// and add it to the display list
addChild(tank);
// now add event listeners for mouse down and mouse move
// events to the stage
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownListener);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener);
}
|
Шаг 20: Обработка движений мыши
Создайте приватную функцию mouseMoveListener () с типом данных события мыши, чтобы обрабатывать движения мыши по сцене. Прослушиватель событий для запуска этой функции был создан на последнем шаге.
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
private function mouseMoveListener(e:MouseEvent):void {
// create a variable to keep the relative angle
// between mouse’s current position in degrees
// and the tank’s current position
var angle:Number;
// the next 2 variables are gonna be
// equal to the the mouse’s current position
turnTurretToX = e.stageX;
turnTurretToY = e.stageY;
// calculate the relative angle in radians
// between the mouse’s curent position
// and the tank’s current position
turretAtan2 = Math.atan2(turnTurretToY — currentTankPositionY, turnTurretToX — currentTankPositionX);
// calculate the same angle in degrees.
// to get degrees out of radians we have to
// multiply radians by 180 and divide the result by PI
// But here are some specifics of Flash
// it calculates the angle not from 0 thru 360
// but from 0 thru 180 and from — 180 thru 0
// so let’s add some conditional to get rid of this problem
if (Math.round(turretAtan2 * 180 / Math.PI) < 0) {
// if angle is between 0 and -180 add 360 to it
angle = Math.round(turretAtan2 * 180 / Math.PI) + 360;
} else {
// if not, calculate it as usual
angle = Math.round(turretAtan2 * 180 / Math.PI);
}
// having our angle value stored in a variable
// let’s rotate our turret towards the mouse pointer
// I’ve done a lot of calculations trying to
// figure it all out, so you may try to undestand my logic
// I’m just picking the right frame of the turret MC depending
// on the angle of the mouse from the turret
if (angle > 240 && angle < 300) {
// go inside the tank MovieClip then inside mTurret
// go to the frame 1 and stop
tank.mTurret.gotoAndStop(1);
}
if (angle > 300 && angle < 340) {
tank.mTurret.gotoAndStop(2);
}
if ((angle >= 0 && angle < 20) || (angle > 340 && angle <= 360)) {
tank.mTurret.gotoAndStop(3);
}
if (angle > 20 && angle < 60) {
tank.mTurret.gotoAndStop(4);
}
if (angle > 60 && angle < 120) {
tank.mTurret.gotoAndStop(5);
}
if (angle > 120 && angle < 160) {
tank.mTurret.gotoAndStop(6);
}
if (angle > 160 && angle < 200) {
tank.mTurret.gotoAndStop(7);;
}
if (angle > 200 && angle < 240) {
tank.mTurret.gotoAndStop(8);
} // end
}
|
Шаг 21: обработчик щелчка мыши
Ниже конца нашей функции mouseMoveListener () создайте закрытую функцию mouseDownListener () с типом данных MouseEvent и передайте ее методу moveTankOnEnterFrame:
01
02
03
04
05
06
07
08
09
10
|
private function mouseDownListener(e:MouseEvent):void {
// when click occurs assign the next variable
// the coordinates of the mouse pointer’s current position
moveTankToX = e.stageX;
moveTankToY = e.stageY;
// and add event listener to move the tank frame by frame
addEventListener(Event.ENTER_FRAME, moveTankOnEnterFrame);
}
|
Шаг 22: передвигай танк кадр за кадром
Создайте новую частную функцию с именем moveTankOnEnterFrame () и внутри нее вызовите метод moveToCoordinates () с 3 параметрами:
1
2
3
|
private function moveTankOnEnterFrame(e:Event) {
moveToCoordinates(tank, moveTankToX, moveTankToY);
}
|
Это, в конце концов, заставит танк двигаться к точке щелчка, в каждом кадре.
Шаг 23: научи танк двигаться
Теперь мы вызвали метод moveToCoordinates (), но мы еще не создали его. Давайте сделаем это сейчас.
TX и TY не будут использоваться, но мы должны создать столько параметров, сколько мы назвали. Вот как это выглядит:
1
|
private function moveToCoordinates(tank_mc:Tank, tX:Number, tY:Number) { // create a variable to keep the relative angle // between mouse’s current position in degrees // and the tank’s current position // this variable exists only inside this function so // you we can use the same name as we used before var angle:Number;
|
Зачем использовать расстояние 15? Ну, я обнаружил, что он никогда не выходит за пределы 15, просто проследив его так:
1
|
trace(Math.abs(tank_mc.x — clickPoint.x));
|
… вы можете сделать то же самое, если хотите;)
Шаг 24: Обзор всего класса
Поскольку наш класс готов, давайте посмотрим на него в целом:
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
package main {
import flash.display.*;
import flash.events.*;
public class TankMaker extends Sprite {
private var tank:Tank;
private var moveTankToX:Number;
private var moveTankToY:Number;
private var turnTurretToX:Number;
private var turnTurretToY:Number;
private var currentTankPositionX:Number;
private var currentTankPositionY:Number;
private var tankSpeed:Number = 2;
private var clickPoint:Object;
private var Atan2:Number;
private var turretAtan2:Number;
public function TankMaker() {
addEventListener(Event.ADDED_TO_STAGE, addStage);
}
private function addStage (e:Event):void {
tank = new Tank();
tank.scaleX = 0.25;
tank.scaleY = 0.25;
tank.x = stage.stageWidth / 2;
tank.y = stage.stageHeight / 2;
addChild(tank);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownListener);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener);
}
private function mouseMoveListener(e:MouseEvent):void {
var angle:Number;
turnTurretToX = e.stageX;
turnTurretToY = e.stageY;
turretAtan2 = Math.atan2(turnTurretToY — currentTankPositionY, turnTurretToX — currentTankPositionX);
if (Math.round(turretAtan2 * 180 / Math.PI) < 0) {
angle = Math.round(turretAtan2 * 180 / Math.PI) + 360;
} else {
angle = Math.round(turretAtan2 * 180 / Math.PI);
}
if (angle > 240 && angle < 300) {
tank.mTurret.gotoAndStop(1);
}
if (angle > 300 && angle < 340) {
tank.mTurret.gotoAndStop(2);
}
if ((angle >= 0 && angle < 20) || (angle > 340 && angle <= 360)) {
tank.mTurret.gotoAndStop(3);
}
if (angle > 20 && angle < 60) {
tank.mTurret.gotoAndStop(4);
}
if (angle > 60 && angle < 120) {
tank.mTurret.gotoAndStop(5);
}
if (angle > 120 && angle < 160) {
tank.mTurret.gotoAndStop(6);
}
if (angle > 160 && angle < 200) {
tank.mTurret.gotoAndStop(7);;
}
if (angle > 200 && angle < 240) {
tank.mTurret.gotoAndStop(8);
}
}
private function mouseDownListener(e:MouseEvent):void {
moveTankToX = e.stageX;
moveTankToY = e.stageY;
addEventListener(Event.ENTER_FRAME,moveTankOnEnterFrame);
}
private function moveTankOnEnterFrame(e:Event) {
moveToCoordinates(tank, moveTankToX, moveTankToY);
}
private function moveToCoordinates(tank_mc:Tank, tX:Number, tY:Number) {
var angle:Number;
if (Math.round(Atan2 * 180 / Math.PI) < 0) {
angle = Math.round(Atan2 * 180 / Math.PI) + 360;
} else {
angle = Math.round(Atan2 * 180 / Math.PI);
}
if (angle > 240 && angle < 300) {
tank.gotoAndStop(1);
}
if (angle > 300 && angle < 340) {
tank.gotoAndStop(2);
}
if ((angle >= 0 && angle < 20) || (angle > 340 && angle <= 360)) {
tank.gotoAndStop(3);
}
if (angle > 20 && angle < 60) {
tank.gotoAndStop(4);
}
if (angle > 60 && angle < 120) {
tank.gotoAndStop(5);
}
if (angle > 120 && angle < 160) {
tank.gotoAndStop(6);
}
if (angle > 160 && angle < 200) {
tank.gotoAndStop(7);
}
if (angle > 200 && angle < 240) {
tank.gotoAndStop(8);
}
clickPoint = {x:moveTankToX, y:moveTankToY};
Atan2 = Math.atan2(clickPoint.y — tank_mc.y, clickPoint.x — tank_mc.x);
tank_mc.x += Math.cos(Atan2) * tankSpeed;
tank_mc.y += Math.sin(Atan2) * tankSpeed;
currentTankPositionX = tank_mc.x;
currentTankPositionY = tank_mc.y;
if (Math.abs(tank_mc.x — clickPoint.x) < 15 && Math.abs(tank_mc.y — clickPoint.y) < 15) {
removeEventListener(Event.ENTER_FRAME,moveTankOnEnterFrame);
}
}
}
}
|
Шаг 25: последние штрихи
Перейдите в File> New и создайте новый файл ActionScript. Сохраните его как «Game.as» в той же папке, что и файл tank.fla. Это будет наш класс документов .
Вот код для класса Game.as:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
package {
import flash.display.*;
// import the contents of our main folder
import main.*;
public class Game extends MovieClip {
private var newTank:TankMaker;
public function Game () {
// create a new instance of our tank maker class
newTank = new TankMaker();
// and add it to the stage of course
addChild(newTank);
}
}
}
|
Сохраните файл. Все, что он делает, это создает танк и добавляет его на основную сцену, готовую к контролю.
Шаг 26: прикрепить игровой класс к FLA
Откройте tank.fla и перейдите на панель свойств. Для класса введите «Игра» и сохраните файл.
Ага! Вот и мы. Теперь вы можете нажать CTRL + ENTER на ПК (CMD + RETURN на Mac) и протестировать игру.
Надеюсь, вам понравился этот урок, спасибо за чтение 🙂