塔防制作笔记20120423 (1)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
-此文档由TKCB整理制作,仅作学习之用 ----------------------------------------------------
塔防制作笔记
20120423
原文地址:/space-17261-do-blog-id-9325.html
前序
前一段时间开始做对塔防游戏感兴趣了。
于是在纸上写写画画,最终决定还是做出来才有成效,更直观点,就做了一个,期间碰到的总总问题,慢慢的解决了。
现在做笔记(毕竟我不是卡马克,做不到啥玩意儿都
可以不要笔记的,我还是给自己留留印象,省的做完就忘记了)。
写这篇文章的时候,已经做好了一部分,至少是可以玩的。
可惜怪物属性和塔的属性的数值平衡没有调整好,整个操作性也不是很爽,界面就更不说了,咱就是个程序猿,画画这活太高深了……只好从别的地方
抠点图来了,希望看到图发现是自己东西的人,不要扁我(比如:H3, HEZI......)。
反正这些个东
西后期慢慢改进,等到改进的时候,都马克到笔记里面来。
好了,第一个游戏制作笔记,华丽丽的开场,就到这里吧,再多我自己都受不了了。
- 我是分割线 --------------------------------------------- ---------------------------------
既然是塔防,首先要有一个地图才行。
我在设计的时候,确定了我的整个游戏界面为:640×480,而每个格子占32,去掉顶部和侧边的游戏交互栏,就是480×448了,大格子也就是15×14。
由于界面不大,我决定复用我的地表素材,即不要每次新的关卡都生成新的地表并清空原来地表,而是直接将所有的地表素材放到一个MC中,用帧标签或者跳帧来确定当前素材的类型显示,然后每个关卡都重新刷新一下帧,让其显示到正确的地表素材上。
以下是关卡的静态数据类,包括了地表数组,敌人行进数组和敌人类型数组。
1.package com.wm.td.data
2.{
3. /**
4. * 关卡数据
5. * @author wmtiger
6. */
7. public class GateData
8. {
9. // 每三个关卡换一次关卡数据
10. // 当然,这个数据类,别人不可能都觉得我这个方法好,但是它可以解决一些问题,至少在
这里就够了。
11. // 关卡 1 ~ 3 的地表数据 和 敌人路径数据
12. public static const EARTH_LIST_1:Array = [
13. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
14. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
15. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
16. 1, 1, 1, 1, 1, 1, 4, 3, 3, 3, 3, 3, 3, 3, 3,
17. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
18. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
19. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
20. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
21. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
22. 3, 3, 3, 3, 3, 3, 6, 1, 1, 1, 1, 1, 1, 1, 1,
23. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
24. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
25. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
26. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
27. ];// 其中的1为earth这个MC里面的第一帧,2为第二帧,以此类推
28. public static const PATH_LIST_1:Array = [135, 141, 51, 59];// 路径为数组的索引
29. public static const ENEMY_LIST_1:Array = [
30. [0,0,0,0,0],
31. [0,0,0,0,0,0,0,0,0,0],
32. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
33. ];// 敌人的数组,有3个子数组,因为每三个关卡换一次关卡数据,所以有3个,里面的0
代表敌人
34. }
35.}
好了,到这里,我们有了关卡的数据,剩下的事情,就要做敌人了。
我从盒子世界里面,拿了一个幽灵的素材做我塔防游戏里面的敌人。
(当然,我不是做一个收费游戏,呵呵,所以就无偿使用素材了,并且注明出处,还有地表素材来自英雄无敌3)
怎么做敌人MC,这个我就不多说了吧……都懂的。
定好了关键帧,跳到对应帧就好了。
有了敌人的MC显示对象了,剩下的就是做个敌人的类了。
1.package com.wm.td.item
2.{
3. import com.wm.td.data.TData;
4. import com.wm.td.mgr.UIMgr;
5. import flash.display.MovieClip;
6. import flash.display.Sprite;
7.
8. /**
9. * 敌人
10. * @author wmtiger
11. */
12. public class Enemy extends BaseItem
13. {
14. public const EMPTY_FRAME:String = "empty_frame";
15.
16. private var _hp:int = 10;// 敌人的生命值
17. private var _hpMax:int = 10;// 敌人的最大生命值
18. private var _killedGold:int = 1;// 敌人被杀死后掉落的金钱
19. private var _speed:int = 20;// 敌人的速度
20.
21. private var _show:MovieClip;// 敌人的形象显示
22. private var _hpBar:Sprite;// 敌人的血条显示
23.
24. private var _dir:String = "";// 方向
25. private var _next:int = 1;// 敌人当前在路径中的第几个点
26.
27. public function Enemy()
28. {
29. hp = _hpMax;
30. show = new TData.instance.enemy();
31. }
32.
33. public function set hp(value:int):void
34. {
35. _hp = value;
36. setHpBarShow();
37. }
38.
39. private function setHpBarShow():void
40. {
41. if (_hpBar == null)
42. {
43. addChild(createRect(-8, -30, 16, 2, 0xff0000, 1));
44. _hpBar = new Sprite();
45. _hpBar.y = -30;
46. _hpBar.x = -8;
47. addChild(_hpBar);
48. _hpBar.addChild(createRect(0, 0, 16, 2, 0x00ff00, 1));
49. }
50. else
51. {
52. _hpBar.width = _hp / _hpMax * 16;
53. }
54. }
55.
56. public function set show(value:MovieClip):void
57. {
58. _show = value;
59. var w:Number = 26 / _show.width;
60. var h:Number = 26 / _show.height;
61. var s:Number = w > h ? h : w;
62. _show.scaleX = s;
63. _show.scaleY = s;
64. addChild(_show);
65. _show.gotoAndStop(EMPTY_FRAME);// 刚刚初始化以后,将显示调整
到空白帧上,以减少消耗
66. }
67.
68. public function set dir(value:String):void
69. {
70. _dir = value;
71. _show.gotoAndStop(_dir);
72. }
73.
74. public function get next():int { return _next; }
75.
76. public function set next(value:int):void
77. {
78. _next = value;
79. }
80.
81. public function get speed():int
82. {
83. return _speed;
84. }
85.
86. }
87.
88.}
复制代码
简单的敌人类,到这里也就好了。
好,让我们先让敌人在地上跑起来先。
哇哈哈。
我不喜欢用flash直接编译生成swf,所以,我更喜欢应用资源,所以,我先在一个swf里弄好资源文件,比如把敌人啊,地表啊之类的元素,先生成好,弄好对应的类,到时候导入主类,就可以直接在FD里面CTRL+ENTER了,呵呵。
1.private function loadLib():void
2. {
3. var ldr:SwfLdr = new SwfLdr();
4. ldr.addEventListener(Event.INIT, onLoadLib);
5. ldr.load("tdLib.swf");
6. }
7. // 在程序一开始的时候,加载资源
8. private function onLoadLib(e:Event):void
9. {
10. var ldr:SwfLdr = e.currentTarget as SwfLdr;
11. ldr.removeEventListener(Event.INIT, onLoadLib);
12. // 设置类
13. TData.instance.enemy = ldr.getClass("Enemy");// 敌人
14. TData.instance.interactUI = ldr.getClass("InteractPane");// 交互
15. TData.instance.earth = ldr.getClass("Earth");// 地表
16.
17. initUI();
18. }
19. // 加载资源成功以后,就可以设置类,并且初始化界面
20. private function initUI():void
21. {
22. _game = new Game();
23. _game.y = 32;
24. UIMgr.instance.game = _game;
25. addChild(_game);
26.
27. _interact = new InteractUI(TData.instance.interactUI);
28. UIMgr.instance.interactUI = _interact;
29. addChild(_interact);
30.
31. }// 将界面传给一个全局单例,当然,这个是为了方便控制,我懒得在这么小的游戏里面加上
MVC,没意义。
复制代码
主类的主要代码为这些,然后是游戏主类
天啊,游戏主类有点长的,200行了,太恐怖了,居然只是初始化和让敌人跑起来。
反正这样子,敌人就一个接一个的跑起来了,第一步也就OK了。
OH,YEAH~~~
以上就是游戏的工程图,和敌人跑起来的图了,^_^
第一阶段到此结束,马克住,等待第二阶段的码字。
对了,忘记上附件了,呵呵。
上次说到了让敌人跑起来,现在要做的是,让我们的塔攻击敌人。
有了敌人类了,就要有塔类,不然没东西,怎么打敌人呢。
呵呵,塔主要有几个方法:
1、检测范围内的敌人,在攻击间隔内,开火打敌人。
2、跟随范围内的敌人旋转炮塔,不然看起来塔很呆~~
检测是最关键的代码,这一块代码是可以有很多种写法,我这里采用的是最简单的判断距离法。
得到场景敌人列表,然后判断敌人是否在自己的攻击范围内,是就开火攻击他。
1.package com.wm.td.item
2.{
3. import com.wm.td.data.TData;
4. import com.wm.td.mgr.UIMgr;
5. import com.wm.td.tools.Utils;
6. import flash.display.Sprite;
7. import flash.events.Event;
8. import flash.events.TimerEvent;
9. import flash.utils.Timer;
10. /**
11. * 塔
12. * @author wmtiger
13. */
14. public class Tower extends BaseItem
15. {
16. private var _atk:int = 10;// 塔的攻击力
17. private var _atkSpd:int = 2000;// 塔的攻击速度
18. private var _atkArea:int = 50;// 塔的攻击范围
19. private var _targetEnemy:Enemy;// 塔的攻击目标(敌人)
20. private var _area:Sprite;// 塔的攻击范围显示
21. private var _show:Sprite;// 塔的形象显示
22. private var _timer:Timer;// 时间监听,时间到了,条件足够就开炮
23. private var _enemyList:Array;// 当前炮塔监视的场景上的敌人列表
24. private var _canFire:Boolean = true;// 当前是否可以开火
25.
26. public function Tower()
27. {
28. _area = new Sprite();
29. addChild(_area);
30. _area.addChild(createCircle(0, 0, _atkArea, 0xffffff, 0.2));
31. show = new TData.instance.tower();
32. _timer = new Timer(_atkSpd, 1);
33. }
34.
35. private function onScanTarget(e:Event):void
36. {
37. if (Utils.chkElementIsInArray(_enemyList, _targetEnemy))
38. {
39. if (Utils.getDistance(_targetEnemy.x, _targetEnemy.y,
this.x, this.y) < _atkArea)
40. {
41. var dx:Number = _targetEnemy.x - this.x;
42. var dy:Number = _targetEnemy.y - this.y - 16;
43. _show["mc_barrel"].rotation = Math.atan2(dy,
dx) * 180 / Math.PI;
44. }
45. }
46. var l:int = _enemyList.length;
47. var enemy:Enemy;
48. for (var i:int = 0; i < l; i++)
49. {
50. enemy = _enemyList[i];
51. if (Utils.getDistance(enemy.x, enemy.y, this.x, this.y)
< _atkArea)
52. {
53. targetEnemy = enemy;
54. break;
55. }
56. }
57. }
58.
59. private function onTimer(e:TimerEvent):void
60. {
61. _canFire = true;
62. }
63.
64. public function set show(value:Sprite):void
65. {
66. _show = value;
67. addChild(_show);
68. }
69.
70. public function get area():Sprite
71. {
72. return _area;
73. }
74.
75. public function set targetEnemy(value:Enemy):void
76. {
77. _targetEnemy = value;
78. if (_canFire)
79. {
80. canFire = false;
81. UIMgr.instance.game.towerFire(this, _targetEnemy);
82. }
83. }
84.
85. public function set enemyList(value:Array):void
86. {
87. _enemyList = value;
88. _timer.addEventListener(TimerEvent.TIMER, onTimer);
89. _timer.start();
90. this.addEventListener(Event.ENTER_FRAME, onScanTarget);
91. }
92.
93. public function get atk():int
94. {
95. return _atk;
96. }
97.
98. public function get show():Sprite
99. {
100. return _show;
101. }
102.
103. public function set canFire(value:Boolean):void
104. {
105. _canFire = value;
106. _timer.reset();
107. _timer.start();
108. }
109.
110. public function destroy():void
111. {
112. _timer.stop();
113. _timer.removeEventListener(TimerEvent.TIMER, onTimer);
114. this.removeEventListener(Event.ENTER_FRAME, onScanTarget);
115. this.visible = false;
116. }
117.
118. }
119.
120.}
复制代码
----------============-----------
有了塔,有了敌人,好像还差点啥,呵呵,没错,就是差了子弹了。
所以我们再加个子弹类。
子弹类没啥方法,主要是传递塔的攻击用的。
1.package com.wm.td.item
2.{
3. import com.wm.td.data.TData;
4. import flash.display.MovieClip;
5. /**
6. * 子弹
7. * @author wmtiger
8. */
9. public class Bullet extends BaseItem
10. {
11. private var _speed:int = 15;// 子弹跑的速度
12. private var _target:Enemy;// 子弹跟踪的目标
13. private var _atk:int = 0;// 子弹的伤害
14. private var _show:MovieClip;// 子弹的显示
15.
16. public function Bullet()
17. {
18. _show = new MovieClip();
19. _show.addChild(createCircle(0, 0, 2, 0xff0000, 1));
20. addChild(_show);
21. }
22.
23. public function get speed():int { return _speed; }
24.
25. public function get target():Enemy { return _target; }
26.
27. public function set target(value:Enemy):void
28. {
29. _target = value;
30. }
31.
32. public function get atk():int { return _atk; }
33.
34. public function set atk(value:int):void
35. {
36. _atk = value;
37. }
38.
39. }
40.
41.}
复制代码
最后要注意的就是游戏类了。
因为很多的主要逻辑都是写在Game.as里面的。
这次的Game类,比之前要复杂的多,因为多了一些处理,比如:子弹的运行轨迹,塔的列表,子弹的列表,敌人的列表,判断是否游戏结束之类。
1.package com.wm.td.ui
2.{
3. import com.greensock.easing.Linear;
4. import com.greensock.TweenLite;
5. import com.wm.td.data.GateData;
6. import com.wm.td.data.TData;
7. import com.wm.td.item.Bullet;
8. import com.wm.td.item.Enemy;
9. import com.wm.td.item.Tower;
10. import com.wm.td.mgr.UIMgr;
11. import com.wm.td.tools.Utils;
12. import flash.display.Sprite;
13. import flash.events.Event;
14. import flash.events.MouseEvent;
15. import flash.events.TimerEvent;
16. import flash.geom.Rectangle;
17. import flash.utils.Timer;
18.
19. /**
20. * 游戏主类
21. * @author wmtiger
22. */
23. public class Game extends Sprite
24. {
25. private var _bg:Sprite;// 地表层
26. private var _mid:Sprite;// 塔层
27. private var _fg:Sprite;// 敌人层
28. private var _zd:Sprite;// 子弹层
29. private var _bgList:Array = [];// 地表元素列表
30.
31. private var _timer:Timer;// 每一关敌人出现的间隔
32.
33. // 以下是要初始化的变量
34. private var _enemyReadyList:Array = [];// 敌人要出现的准备列表
35. private var _nowGateLevel:int = 0;// 当前的关卡
36. private var _earthList:Array = [];// 当前关卡的地表数据
37. private var _enemyList:Array = [];// 当前在游戏场景里面的敌人的列表
38. private var _pathList:Array = [];// 当前游戏场景中的敌人要行进的路线
39. private var _bulletList:Array = [];
40. private var _towerList:Array = [];
41.
42. private var _isReadyBuildTower:Boolean = false;// 当前是否准备要建造
塔
43. private var _readyTower:Sprite;// 建造塔的预览形象
44.
45. public function Game()
46. {
47. initUI();
48. initEvt();
49. startGame();
50. }
51.
52. private function initUI():void
53. {
54. _bg = new Sprite();
55. addChild(_bg);
56. _mid = new Sprite();
57. addChild(_mid);
58. _fg = new Sprite();
59. addChild(_fg);
60. _zd = new Sprite();
61. addChild(_zd);
62. _timer = new Timer(3000);// 初始化时间监听
63.
64. _readyTower = new Sprite();
65. addChild(_readyTower);
66. }
67.
68. private function initEvt():void
69. {
70. _timer.addEventListener(TimerEvent.TIMER, onTimer);
71._timer.addEventListener(TimerEvent.TIMER_COMPLETE,
onTimerComplete);
72.
73. this.addEventListener(MouseEvent.CLICK, onClick);
74. }
75.
76. private function onClick(e:MouseEvent):void
77. {
78. //trace("e.stage", e.stageX, e.stageY);
79. var index:int = int(e.stageX / 32) + int((e.stageY - 32) / 32)
* 15;
80. if (_earthList[index] == 1)
81. {
82. var tower:Tower = new Tower();
83. tower.enemyList = _enemyList;
84. var mx:int = int(e.stageX / 32) * 32 + 32 / 2;
85. var my:int = int((e.stageY - 32) / 32) * 32 + 32 / 2;
86. tower.x = mx;
87. tower.y = my;
88. _mid.addChild(tower);
89. _towerList.push(tower);
90. _readyTower.visible = false;
91. tower.area.visible = false;
92. }
93. }
94.
95. private function onTimerComplete(e:TimerEvent):void
96. {
97. _timer.stop();
98. }
99.
100. private function onTimer(e:TimerEvent):void
101. {
102. trace("敌人来了");
103. var enemy:Enemy = _enemyReadyList.shift();
104. _enemyList.push(enemy);
105. enemyMove(enemy);
106. }
107.
108. public function enemyMove(enemy:Enemy):void
109. {
110. var tx:int = int(_pathList[enemy.next] % 15) * 32 + 16; 111. var ty:int = int(_pathList[enemy.next] / 15) * 32 + 16; 112. var d:Number = Utils.getDistance(tx, ty, enemy.x, enemy.y); 113. var t:Number = d / enemy.speed;
114. chkDir(enemy, tx, ty);
115. TweenLite.to(enemy, t, { x:tx, y:ty, ease:Linear.easeNone, onComplete:onFinish, onCompleteParams:[enemy] } );
116. }
117.
118. private function onFinish(params:*):void
119. {
120. var enemy:Enemy = params as Enemy;
121. var l:int = _pathList.length;
122. if (++enemy.next < l)
123. {
124. enemyMove(enemy);
125. }
126. else
127. {
128. enemyStop(enemy);
129. }
130. }
131.
132. // 开始游戏
133. public function startGame():void
134. {
135. initGame();
136. createBg();
137. this.addEventListener(Event.ENTER_FRAME, gameLoop);
138. }
139.
140. private function gameLoop(e:Event):void
141. {
142. var bullet:Bullet;
143. for (var i:int = 0; i < _bulletList.length; i++)
144. {
145. bullet = _bulletList[i];
146.if (Utils.chkElementIsInArray(_enemyList, bullet.target))
147. {
148. var v:Number = bullet.speed / 30;
149. var dx:Number = bullet.x - bullet.target.x; 150. var dy:Number = bullet.y - bullet.target.y + 16; 151. bullet.rotation = (270 + Math.atan2(dy, dx) * 180 / Math.PI) % 360;
152. bullet.x -= dx * v;
153. bullet.y -= dy * v;
154. if (bullet.hitTestPoint(bullet.target.x, bullet.target.y + 16))
155. {
156. bullet.target.hp -= bullet.atk; 157. bullet.visible = false;
158. Utils.delElementInArray(_bulletList, bullet);
159. }
160. }
161. else
162. {
163. bullet.visible = false;
164. }
165. }
166. }
167.
168. private function initGame():void
169. {
170. _nowGateLevel = TData.instance.nowGateLevel;
171. var temp:int = int((_nowGateLevel - 1) / 16) + 1;
172. var temp2:int = int(_nowGateLevel - 1) % 16;
173. TData.instance.nowMoeny = 10;
174. _earthList = GateData["EARTH_LIST_" + temp];
175. _pathList = GateData["PATH_LIST_" + temp];
176. _enemyReadyList = createEnemyReadyList(GateData["ENEMY_LIST_"
+ temp][temp2]);
177. _enemyList = [];// 每次游戏开始前,强行清空 _enemyList 里面的数据
178. _towerList = [];// 每次游戏开始前,强行清空 _enemyList 里面的数据
179. resetTimer();// 开始重置时间,准备开始游戏
180. }
181.
182. // 重置时间监听
183. private function resetTimer():void
184. {
185. _timer.repeatCount = _enemyReadyList.length
186. _timer.reset();
187. _timer.start();
188. }
189.
190. private function createEnemyReadyList(arr:Array):Array
191. {
192. var tx:int = int(_pathList[0] % 15) * 32 - 16;
193. var ty:int = int(_pathList[0] / 15) * 32 + 16;
194. var temp:Array = [];
195. var l:int = arr.length;
196. for (var i:int = 0; i < l; i++)
197. {
198. temp[i] = createEnemy();
199. temp[i].x = tx;
200. temp[i].y = ty;
201. }
202. return temp;
203. }
204.
205. private function createEnemy():Enemy
206. {
207. var temp:Enemy = new Enemy();
208. _fg.addChild(temp);
209. return temp;
210. }
211.
212. private function chkDir(enemy:Enemy, nx:int, ny:int):void
213. {
214. if (enemy.x - nx < 0 && enemy.y == ny)
215. {
216. enemy.dir = "right";
217. }
218. else if (enemy.x - nx > 0 && enemy.y == ny)
219. {
220. enemy.dir = "left";
221. }
222. if (enemy.y - ny < 0 && enemy.x == nx)
223. {
224. enemy.dir = "down";
225. }
226. else if (enemy.y - ny > 0 && enemy.x == nx)
227. {
228. enemy.dir = "up";
229. }
230. }
231.
232. private function createBg():void
233. {
234. var l:int = _earthList.length;
235. var i:int = 0;
236. var earth:*;
237. if (_bgList.length == l)
238. {
239. for (i = 0; i < l; i++)
240. {
241. earth = _bgList[i];
242. earth.gotoAndStop(_earthList[i]); 243. }
244. }
245. else
246. {
247. for (i = 0; i < l; i++)
248. {
249. earth = new TData.instance.earth(); 250. _bg.addChild(earth);
251. earth.x = int(i % 15) * 32;
252. earth.y = int(i / 15) * 32;
253. _bgList.push(earth);
254. earth.gotoAndStop(_earthList[i]); 255. }
256. }
257. }
258.
259. public function get isReadyBuildTower():Boolean
260. {
261. return _isReadyBuildTower;
262. }
263.
264. public function set isReadyBuildTower(value:Boolean):void
265. {
266. _isReadyBuildTower = value;
267. Utils.clearAllInMc(_readyTower);
268. var tower:Tower = new Tower();
269. _readyTower.addChild(tower);
270. _readyTower.visible = true;
271. tower.x = mouseX;
272. tower.y = mouseY;
273. _readyTower.startDrag();
274. }
275.
276. public function towerFire(tower:Tower, enemy:Enemy):void
277. {
278. trace("fire");
279. var bullet:Bullet = new Bullet();
280. _bulletList.push(bullet);
281. _zd.addChild(bullet);
282. bullet.x = tower.x + Math.cos(tower.show["mc_barrel"].rotation * Math.PI / 180) * 14;// 14 为炮管的长度
283. bullet.y = tower.y + Math.sin(tower.show["mc_barrel"].rotation * Math.PI / 180) * 14;// 14 为炮管的长度
284. bullet.target = enemy;
285. bullet.atk = tower.atk;
286. }
287.
288. // 判断是否是赢了
289. public function chkIsWin():void
290. {
291. if (_enemyList.length == 0 && _enemyReadyList.length == 0) 292. {
293. trace("win");
294. _timer.stop();
295. clearAllEnemy();
296. clearAllTower();
297. clearAllBullet();
298.this.removeEventListener(Event.ENTER_FRAME, gameLoop);
299. UIMgr.instance.winUI.visible = true;
300. }
301. }
302.
303. public function enemyStop(enemy:Enemy):void
304. {
305. TweenLite.killTweensOf(enemy);
306. enemy.visible = false;
307. Utils.delElementInArray(_enemyList, enemy);
308. Utils.delElementInArray(_enemyReadyList, enemy); 309. _fg.removeChild(enemy);
310. }
311.
312. private function clearAllBullet():void
313. {
314. var l:int = _bulletList.length;
315. var i:int = 0;
316. var bullet:Bullet;
317. for (i = 0; i < l; i++)
318. {
319. bullet = _bulletList[0];
320. Utils.delElementInArray(_bulletList, bullet); 321. _zd.removeChild(bullet);
322. }
323. }
324.
325. private function clearAllTower():void
326. {
327. var l:int = _towerList.length;
328. var i:int = 0;
329. var tower:Tower;
330. for (i = 0; i < l; i++)
331. {
332. tower = _towerList[0];
333. Utils.delElementInArray(_towerList, tower); 334. tower.destroy();
335. }
336. }
337.
338. private function clearAllEnemy():void
339. {
340. var l:int = _enemyList.length;
341. var i:int = 0;
342. for (i = 0; i < l; i++)
343. {
344. enemyStop(_enemyList[0]);
345. }
346. l = _enemyReadyList.length;
347. for (i = 0; i < l; i++)
348. {
349. enemyStop(_enemyReadyList[0]);
350. }
351. }
352.
353. }
354.
355.}
主要的东西就是这些……但是,怎么感觉好像说的东西很少呢……精髓都在代码里面了,代码的注释个人感觉是非常的全了,还有问题,就可以问我了。
呵呵。
这里附上附件: TD_test2.rar (396.19 KB)
附件地址:
/attachment.php?aid=NDY3MTJ8NzM3MjUzNzR8MTMzNTE0OTA0MHw4NDZiYXhyL0xyQkN3 d1c5R0FsQTZUTjd6dnMzNWx4ZHM3d1R2OCtQbDVVNERuMA%3D%3D
图片附上:
第一次的教程,希望能对人有帮助,里面还有很多的不足和可以改进的地方,希望多多包涵,并提出意见。
PS:以前都是看别人的教程,今天终于可以写个教程,对别人可能有所帮助了,呵呵。
有更大的进步的时候,我再出点教程吧~~~。