Уроки Flash: Metro Siberia Undeground (части 3-4)

Источник: demiart
Emanuele Ferontano (Перевод: Stasan)

Примечание от переводчика:
У автора оригинала урока скрипт и пояснение к нему разбит на две части, для удобства, я выкладываю все сразу.

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

Нам надо будет создать три новых символа, первым будет символ rock в нем рисуем квадрат, вторым создаем символ fuel в нем рисуем кружок, это будет наш резервуар с топливом, третьим создаем символ с именем score в нем создаем динамическое текстовое поле в Instance name пишем sc. Всем символам врубаем linkage.

Теперь код, будут объяснены только новые фрагменты, комментарии к остальному смотрите в первой и второй части.

В руте в первом кадре пишем следующее.


CODE

1. import flash.filters.GlowFilter;
2. var ship_filter:GlowFilter = new GlowFilter(0x00ff00, 0.8, 4, 4, 2, 3, false, false);
3. var smoke_filter:GlowFilter = new GlowFilter(0xff0000, 0.8, 4, 4, 2, 3, false, false);
4. var tunnel_filter:GlowFilter = new GlowFilter(0xffff00, 0.8, 4, 4, 2, 3, false, false);
5. var fuel_filter:GlowFilter = new GlowFilter(0x00ffff, 0.8, 4, 4, 2, 3, false, false);
6. var rock_filter:GlowFilter = new GlowFilter(0xffffff, 0.8, 4, 4, 2, 3, false, false);
7. var score_filter:GlowFilter = new GlowFilter(0xff00ff, 0.8, 2, 4, 2, 3, false, false);
8. gravity = 0.1;
9. thrust = 0.25;
10. yspeed = 0;
11. xspeed = 5;
12. distance = 0;
13. smoke_interval = 10000;
14. frames_passed = 0;
15. tunnel_height = 150;
16. fuel_freq = 10;
17. gasoline = 500;
18. rock_freq = 50;
19. engines = false;
20. _root.attachMovie("ship", "ship", _root.getNextHighestDepth(), {_x:150, _y:200});
21. _root.createEmptyMovieClip("fuel_movie", _root.getNextHighestDepth());
22. _root.createEmptyMovieClip("deadly_movie", _root.getNextHighestDepth());
23. _root.attachMovie("score", "score", _root.getNextHighestDepth());
24. ship.filters = new Array(ship_filter);
25. score.filters = new Array(score_filter);
26. ship.onEnterFrame = function() {
27.     score.sc.text = "Distance: "+distance+" - "+"Fuel: "+gasoline;
28.     if ((gasoline>0)and(engines)) {
29.         yspeed -= thrust;
30.         smoke_interval -= 0.25;
31.         gasoline -= 1;
32.     }
33.     if (Math.random()*1000<fuel_freq) {
34.         fuel = fuel_movie.attachMovie("fuel", "fuel"+fuel_movie.getNextHighestDepth(), fuel_movie.getNextHighestDepth(), {_x:510, _y:Math.random()*400+50});
35.         fuel.filters = new Array(fuel_filter);
36.         fuel.onEnterFrame = function() {
37.             this._x -= (xspeed*1.2);
38.             dist_x = ship._x+28*Math.cos(angle)-this._x;
39.             dist_y = ship._y+28*Math.sin(angle)-this._y;
40.             dist = Math.sqrt(dist_x*dist_x+dist_y*dist_y);
41.             if (dist<10) {
42.                 gasoline += 100;
43.                 this.removeMovieClip();
44.             }
45.             if (this._x<-10) {
46.                 this.removeMovieClip();
47.             }
48.         };
49.     }
50.     if (Math.random()*1000<rock_freq) {
51.         rock = deadly_movie.attachMovie("rock", "rock"+deadly_movie.getNextHighestDepth(), deadly_movie.getNextHighestDepth(), {_x:510, _y:Math.random()*400+50, _rotation:Math.random()*360});
52.         rock.filters = new Array(rock_filter);
53.         rock.onEnterFrame = function() {
54.             this._x -= xspeed;
55.             if (this._x<-10) {
56.                 this.removeMovieClip();
57.             }
58.         };
59.     }
60.     yspeed += gravity;
61.     this._y += yspeed;
62.     angle = Math.atan2(yspeed, xspeed);
63.     this._rotation = angle*180/Math.PI;
64.     frames_passed++;
65.     distance += xspeed;
66.     if (frames_passed>=smoke_interval) {
67.         sm = _root.attachMovie("smoke", "smoke"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:this._x-2, _y:this._y});
68.         sm.filters = new Array(smoke_filter);
69.         sm.onEnterFrame = function() {
70.             this._x -= xspeed;
71.             this._width += 0.2;
72.             this._height += 0.2;
73.             this._alpha -= 2;
74.             if (this._alpha<=0) {
75.                 this.removeMovieClip();
76.             }
77.         };
78.         frames_passed = 0;
79.     }
80.     if ((this._y>400) or (this._y<0) or deadly_movie.hitTest(this._x+28*Math.cos(angle), this._y+28*Math.sin(angle), true) or deadly_movie.hitTest(this._x+8*Math.cos(angle+Math.PI/2), this._y+8*Math.sin(angle+Math.PI/2), true) or deadly_movie.hitTest(this._x+8*Math.cos(angle-Math.PI/2), this._y+8*Math.sin(angle-Math.PI/2), true)) {
81.         yspeed = 0;
82.         this._y = 200;
83.         gasoline = 500;
84.         distance = 0;
85.         deadly_movie.removeMovieClip();
86.         fuel_movie.removeMovieClip();
87.         _root.createEmptyMovieClip("fuel_movie", _root.getNextHighestDepth());
88.         _root.createEmptyMovieClip("deadly_movie", _root.getNextHighestDepth());
89.     }
90. };
91. _root.onMouseDown = function() {
92.     engines = true;
93.     smoke_interval = 10;
94. };
95. _root.onMouseUp = function() {
96.     engines = false;
97.     smoke_interval = 100000;
98. };

Что ж поехали разбираться, что к чему.

5-7. Создание фильтров для новых объектов астероидов, резервуаров с горючим и текстового поля показывающего пройденное расстояние и кол-во горючего в баках.
Так в этой части уже нет туннелей, то можно удалить четвертую строчку.
15. Это тоже можно удалять если хотите.
16. Переменная, отвечающая за частоту появления сосудов с топливом, чем больше значение, тем чаще они выпадают.
17. Кол-во топлива на корабле.
18. Частота появления астероидов.
21. Создаем новый Movie Clip для размещения всех резервуаров с топливом.
22. Клип для астероидов.
23. Аттачим Movie Clip score.
25. Применяем к нему фильтр.
27. Показываем пройденное расстояние и кол-во топлива.
28. Как видно из if теперь должно быть горючее, чтобы двигатель сработал.
31. Срабатывание двигателя будет забирать определенное кол-во топлива.
33. Проверка не пора ли добавлять резервуар с топливом.
34. Если пора, тогда аттачим клип fuel в случайное местоположение.
35. Применяем фильтр к клипу с топливом.
36. Функция которая будет выполняться каждый кадр для клипа fuel.
37. Передвигаем клип fuel со скоростью корабля помноженной на 1.2 Чтобы топливо двигалось быстрее астероидов.
38-40. Рассчитываем расстояние между носом корабля и сосудом с топливом. Я хочу, чтобы пересечение рассчитывалось только с носом корабля чтобы добавить реализма.
41-44. Если расстояние меньше 10(радиус кружочка) то увеличиваем кол-во топлива и удаляем резервуар.
45-47. Если резервуар вышел за левый край, то удаляем его.
50. Проверка не пора ли добавлять астероид.
51. Если пора, тогда аттачим клип rock в случайное местоположение со случайным поворотом.
53. Функция, которая будет выполняться для астероида каждый кадр.
54-57. Перемещаем астероид влево со скоростью корабля и удаляем его если он пересек левый край.
80-89. Если корабль задевает астероид, или опускается слишком низко или слишком высоко, то рестартим игру.

Вот что у нас получилось.


Страница сайта http://185.71.96.61
Оригинал находится по адресу http://185.71.96.61/home.asp?artId=17683