当前位置:首页 >> 学科竞赛 >> Flash游戏开发教材

Flash游戏开发教材


牌头中学校本教材

Flash 小游戏开发基础

主编:李琦

牌头中学校本教材审定委员会
牌头中学 . 选修课教材 知识拓展。字数 32 千

作者声明

1、 本教材著作权归教材作者所有,未经作者授权,任何组织或个人不得以任何形式对本教材 进行出版、发行。 2、 本

教材由作者授权在浙江教育资源网独家发布,其他组织和个人不得进行转载、发布。 3、 本教材供浙江省普通高中选用,全省普通高中学校可以通过浙江教育资源网实名下载本教 材的电子版及相关教育资源,允许并仅供在本校范围内用于选修课教学。 4、 本教材存在的疏漏、错误之处敬请批评指正,欢迎相关专家老师与作者联系,共同参与本教材 的研究和完善工作。

前言
Flash 是高中信息技术必修课程, 本选修课教材在原信息技术必修教材基础上, 着重阐述 flash 脚本的知识,并在 flash 脚本的基础上手把手教学生制作 flash 小游戏,以达到寓教于乐的目的。

目 录 Flash 游戏制作常用代码解析 .......................................1 FLASH 游戏制作基础:响应键盘的四种方法 ............7 Flash 游戏制作--空战 ..................................................10 Flash 飞行游戏制作全解 .............................................17 Flash 游戏制作--迷宮 ..................................................27 Flash 游戏制作规划与流程漫谈 .................................34 用 Flash 制作互动的小人 .............................................43 常见的飞机发射子弹的控制 ........................................47 一个完全使用 AS2 编制的飞机游戏之制作详解 .......48

Flash 小游戏开发基础

Flash 游戏制作常用代码解析
1.获取随机数 随机函数在 flash 游戏制作中很常用,例如在拼图游戏中,每次开始新的游戏时可以利用随机函数使图块获得 新的位置,试想一个千篇一律的游戏谁会有兴趣玩下去。 现在我们有两种产生随机数的方式:random()和 Math.random(),举例来讲,如果我们相随机赋给 x 一个 0-5 的数,我们可以使用 x=random(6)或者 x=Math.random()*5。 但这两种方式产生的随机数是有区别的,用 random(6)方法返回的 x 是 0<=x<=5 的整数,而另外一种返回的 x 则是 0<=x<5 的小数。 试着在第一帧中写入下面的 AS,并在第二帧创建内容帧以形成循环: x = random(6); y = Math.random()*5; trace("x="+x+",y="+y); 在 output 窗口中将得到以下数据: ... x=1,y=3.66887632058933 x=2,y=4.39878350123763 x=0,y=0.522367884404957 x=3,y=2.95675310306251 x=5,y=4.03038211166859 x=2,y=0.223042098805308 ... 区别一目了然。 2.获得鼠标及 MC(MovieClip)的位置 另外一个在 flash 游戏制作使用频率比较高的参数就是坐标了,鼠标的坐标和 MC 的坐标的获得方式是不同的, 鼠标的坐标可以用_xmouse 和_ymouse 获得,MC 的坐标可以用 MovieClip._x 和 MovieClip._y 获得。值得注意 的是在获得坐标时要考虑实际需要的坐标值是相对的还是绝对的,下面给出了一个典型的获得鼠标相对坐标和绝 对坐标的例子(例 1): 其中浅色的正方形是一个被命名为 mc 的 MovieClip,四个文本框属性均被设置为 Dynamic Text(请参阅 《Flash MX 文本工具详解》),场景中的两个用于获得变量 x_timeline 和 y_timeline(绝对坐标),正方形中的两个用于获得变 量 x_movieclip 和 y_movieclip(相对坐标),为了获得变量,需要在文本框的属性面板中的 Var 属性中分别填入相应 的变量名,与上面例子形成循环的方式一样,在第一帧中写下面的 AS,第二帧创建为内容帧: x_timeline = _root._xmouse; y_timeline = _root._ymouse; x_movieclip = mc._xmouse; y_movieclip = mc._ymouse; 注意:场景的坐标原点为其左上角,坐标值向右向下递增,为正值(这与我们通常意义的坐标并不相同);MC 的 坐标原点是编辑 MC 时的中心,坐标象限见图 1.

—1—

Flash 小游戏开发基础

获得 MC 坐标的方法与上面说的大同小异,我们将在下面的 MC 属性简介中做介绍。 3.MC 常用属性简介
属性 _x _y _xscale _yscale _alpha _visible _width _height _rotation _currentframe _totalframes _framesloaded _name 用法 MC._x MC._y MC._xscale MC._yscale MC._alpha MC._visible MC._width MC._height MC._rotation MC._currentframe MC._totalframes MC._framesloaded MC._name 说明 返回/设置 MC 的横纵坐标值 可获得 Y 可设置 Y 取值范围 数值

返回设置 MC 的 x/y 轴缩放比例 返回/设置 MC 的透明度 返回/设置 MC 的可见性 返回/设置 MC 的宽/高值 返回/设置 MC 的角度 返回 MC 的当前帧 返回 MC 的总帧数 返回已下载帧数 返回/设置 MC 的名称

Y Y Y Y Y Y Y Y Y

Y Y Y Y Y N N N Y

数值 0-100 true;false 数值 数值 -

4.判断按键 既然是游戏,当然就要响应玩家的各种反应,除了鼠标,最直接的就是键盘了。 响应键盘无非是判断玩家按下了 哪一个键或者组合键,要实现这些其实很简单,我们既可以通过按钮或 MC 的事件来响应按键,也可以通过帧上的 动作来响应,举例说明: (1)按钮的 keyPress 方法: 先说按钮,按钮除了响应鼠标的一些动作(如:rollOver,release...)之外还有几个是响应固定按键的(如 Enter,Left,Home,PageDown...),下面我们就来制作一个。建立一个按钮,拖到场景中,捆绑下面的 AS: on (keyPress "") { trace("按下了 Left 键"); } 这样当我们在测试的环境下按下左方向键后,output 窗口就会显示出"按下了 Left 键"。下面说说怎样使 MC 响应按键更复杂的按键。 (2)MC 响应单个按键: onClipEvent (keyDown) { if (Key.isDown(72)) { trace("按下了 H 键");

—2—

Flash 小游戏开发基础

} } 这样在测试的环境下按下 H 键,output 窗口就会显示出"按下了 H 键",其中 72 是 H 键的 keyCode 值(其他按 键的 keyCode 值将在附录中给出),如果不知道某个键的 keyCode 值也没关系,Flash 为我们提供了 getCode 函数, 将上面 AS 中的 72 替换成 Key.getCode("H")会得到同样的效果。 (3)MC 响应组合键: onClipEvent (keyDown) { if (Key.isDown(72) && Key.isDown(17)) { trace("您按下的组合键是 Ctrl+H"); } } 在测试的环境中按下 Ctrl+H 键,output 窗口就会显示出"您按下的组合键是 Ctrl+H" (4)利用帧上的动作响应按键: 新建一个 flash 文件,利用上面讲过的:在第一帧写 AS,第二帧创建内容帧的方法,使影片形成循环以便随时进 行判断,然后在第一帧中写入下面的几组代码,分别进行试验;如果你使用的是 MX,也可以不建立第二帧,而是用试 验代码代替 _root.onEnterFrame=function(){...}中的"..."来达到同样的效果: //① trace(Key.getCode()); //② if (Key.isDown(72)) { trace("按下了 H 键"); } //③ if (Key.isDown(72) && Key.isDown(17)) { trace("按下了 Ctrl+H 组合键"); } //④ if (Key.isDown(17)) { if (Key.isDown(72)) { temp = "+H"; } if (Key.isDown(71)) { temp = "+G"; } trace("按下了 Ctrl"+temp+"键"); } 注:对于 MC 的(2)(3)两种情况,可以将 keyDown 事件改为 enterFrame 事件,其中(2)还可以替换为 keyUp 事 件. 附:键码值表
字母和数字键的键码值(keyCode) 按键 A B C D 键码 65 66 67 68 按键 J K L M 键码 74 75 76 77 按键 S T U V 键码 83 84 85 86 按键 1 2 3 4 键码 49 50 51 52

—3—

Flash 小游戏开发基础

E F G H I

69 70 71 72 73

N O P Q R

78 79 80 81 82

W X Y Z 0

87 88 89 90 48

5 6 7 8 9

53 54 55 56 57

数字键盘上的键的键码值(keyCode) 按键 0 1 2 3 4 5 6 7 键码 96 97 98 99 100 101 102 103 / 按键 8 9 * + Enter . 键码 104 105 106 107 108 109 110 111 按键 F1 F2 F3 F4 F5 F6

功能键键码值(keyCode) 键码 112 113 114 115 116 117 按键 F7 F8 F9 F10 F11 F12 键码 118 119 120 121 122 123

控制键键码值(keyCode) 按键 BackSpace Tab Clear Enter Shift Control Alt Cape Lock 键码 8 9 12 13 16 17 18 20 按键 Esc Spacebar Page Up Page Down End Home Left Arrow Up Arrow 键码 27 32 33 34 35 36 37 38 按键 Right Arrow Down Arrow Insert Delete Num Lock ;: =+ ,< 键码 39 40 45 46 144 186 187 188 按键 -_ .> /? `~ [{ \| ]} '" 键码 189 190 191 192 219 220 221 222

5.检测碰撞(hitTest) 目前我们见到的射击游戏或打老鼠之类的游戏很多都利用了 hitTest,hitTest 既可以检测 MC 与 MC 的碰撞, 也可以检测鼠标与 MC 的碰撞: hitTest 的语法如下: (1)myMovieClip.hitTest(x,y,shapeFlag) 这用来检测鼠标的碰撞,x 和 y 分别代表鼠标的横纵坐标,shapeFlag 用来规定检测以 MovieClip 的最大边界 为限或以 MovieClip 的实际边界为限. (2)myMovieClip.hitTest(target) 检测 MC 之间的碰撞,应用起来十分简单。 6.MC 的复制与卸载 MC 的复制,顾名思义就是产生出一个与目标相同的 MC(除了 name 和 depth 以外),语法 为:duplicateMovieClip(target,newname,depth) target:被复制目标的名称; newname:复制出的 MC 的名称; depth:复制出的 MC 的深度.
—4—

Flash 小游戏开发基础

需要注意,复制出来的新 MC 的 name 最好不要相同,也不要与被复制的 MC 的相同,因为这样会给控制带来不 可预期的麻烦;另外 depth 也是一个相当重要的参数,如果新复制出的 MC 与前面某个复制的 MC 的 depth 属性相 同(即位于通一深度),那么先前被复制的 MC 将被新复制的 MC 替换掉(不管他们是否属于同一被复制目标),这个特 性经常被我用来制作鼠标跟随的效果,即炫又简单,你试试:) 再来说说 MC 的卸载,大家对这个 MC 的复制的"双胞胎兄弟"的重视程度好像远不如他的"兄长",因为我经常 在论坛中看到类似于"为什么复制出的 MC 在跳到其他帧,甚至到其他场景后依然存在?"的问题,其实解决方法很 简单,就是 MC 的卸载: removeMovieClip(target); 只要将要被卸载的 MC 的 name 替换掉语句中的 target 就可以成功的完成卸载任务。 7.获取影片运行时间 getTimer(); 这个函数用以返回自影片开始播放时起已经过的毫秒数,虽然是个很简单的函数,但用利用率却很高,尤其是 在一些需要计时的游戏中。 需要说明的是:毫秒与秒的计算公式为 1 毫秒=1/1000 秒;函数以影片第一次播放的开始时刻为 0,不受任何其 他因素影响,也就是说如果你想从头开始计时,那么只有重起 player,或者定义一个变量来存放 getTimer 的值,然后 用 getTimer 与变量做减法运算以便得到新的运行时间,看下面的例子(例 5). 8.颜色的设置 说到颜色必须先说说什么是对象,对象就是预先定义好的用来访问某些特定类型的信息的集合,大多数预定义 对象都有自己的方法(被指派给一个对象的函数被称为这个对象的一个方法),你可以通过这些方法得到不同类型 的返回值或执行某个动作. 预定义对象包括普通对象和顶级对象,普通对象在使用前需要创建(我们将要提到的 Color 对象就属于这一 类),而顶级对象则可以直接调用(入下面要说的 Math 对象) 下面我们详细介绍一下 Color 对象,它包含四种方法: getRGB():返回由最后一次 setRGB 调用设置的数值; getTransform():返回由最后一次 setTransform 调用设置的转换值; setRGB(0xRRGGBB):指定 Color 对象实例的 RGB 颜色, 调用此方法会覆盖由 setTransform 方法设置的 任何以前的设置; setTransform(colorTransformObject):设置 Color 对象实例的颜色转换信息 colorTransformObject 参数是 通过 new Object 构造函数创建的通用对象它具有指定颜色的红、绿、蓝和 alpha(透明度)成分百分比和偏移量 数值的参数,颜色转换对象的参数与"高级效果"对话框中的设置相对应,定义如下: ra 是红色成分的百分比(-100 到 100) rb 是红色成分的偏移量(-255 到 255) ga 是绿色成分的百分比(-100 到 100) gb 是绿色成分的偏移量(-255 到 255) ba 是蓝色成分的百分比(-100 到 100) bb 是蓝色成分的偏移量(-255 到 255) aa 是 alpha 的百分比(-100 到 100) ab 是 alpha 的偏移量(-255 到 255) myColorTransform = new Object(); myColorTransform.ra = 50; myColorTransform.rb = 244; myColorTransform.ga = 40; myColorTransform.gb = 112; myColorTransform.ba = 12; myColorTransform.bb = 90;

—5—

Flash 小游戏开发基础

myColorTransform.aa = 40; myColorTransform.ab = 70; 也可使用以下语法来创建 colorTransformObject 参数: myColorTransform = {ra:'50',rb:'244',ga:'40',gb:'112',ba:'12',bb:'90',aa:'40',ab:'70'} 下面的例子展示了为一个目标电影创建一个新的 Color 对象,使用 Object 构造器创建一个颜色改变对象以及 使用 setTransform 方法将这个颜色改变对象传递给一个 Color 对象的过程: //为目标 MC 创建一个名为 myColord 的对象 myColor=new Color(MC); //使用普通对象 Object 对象创建一个名为 myColorTransform 的颜色改变对象 myColorTransform=new Object; //为 myColorTransform 设置值 myColorTransform={ra:'50',rb:'244',ga:'40',gb:'112',ba:'12',bb:'90',aa:'40',ab:'70'}; //将颜色改变对象和为 MC 创建的颜色对象关联起来 myColor.setTransform(myColorTransform);. 9.三角函数的运用 三角函数属于 Flash 中的顶级对象----Math,一提到这个名词很多人是不是会感到"恐惧",但在游戏的制作中 它可是必不可少的。 这里我们利用 Math 的 atan 方法来制作一个永远指向鼠标的指针(例 6),其他的三角函数以及数学函数的用法 和注意事项请参考附录中的数学函数表. 新建一个 MC,画一个长度为 70 的水平指向右侧的箭头(箭头根部放在中心点上),回到场景,Ctrl+J 修改影片的大小 为 200*200,将指针从库中拖入场景,命名为"pointer",修改坐标为 100*100,在主 timeline 的第一帧中写如下 AS: x = _xmouse-100; y = _ymouse-100; //将坐标中心移到场景的中心 tan = Math.atan(y/x)*180/Math.PI; //注意要使用弧度表示的角度值 if (x>=0 && y>=0) { r = Math.round(tan); } else if (x>=0 && y<0) { r = Math.round(360+tan); } else { r = Math.round(180+tan); } //判断各种不同的情况,通过运算使 r 值在 0-360 之间 pointer._rotation = r; //将 r 值付给_rotation 放置一个用来显示 r 值的文本框属性为 Dynamic Text,获取变量(Var)为"r",第二帧建立内容帧,Ctrl+Enter 测 试。 附:
数学函数表(Math) 方法 abs 描 述 计算并返回由参数 x 指定的数字的绝 对值. 以弧度为单位计算并返回参数 x 中指 定的数字的反余弦值. 语法 Math.abs(x) 说 明

acos

Math.acos(x)

-1.0<=x<=1.0

—6—

Flash 小游戏开发基础

asin

以弧度为单位计算并返回参数 x 中指 定的数字的反正弦值. 计算并返回参数 x 中指定的数字的反 正切值. 以弧度为单位计算并返回 y/x 的反正

Math.asin(x)

-1.0<=x<=1.0

atan

Math.atan(x)

返回值介于负二分之 pi 与正二分之 pi 之间.

atan2

切值.返回值表示相对直角三角形对角 的角,其中 x 是临边边长,而 y 是对边 边长. 返回指定数字或表达式的上限值.数字

Math.atan2(y,x)

x/y 分别指定点的 x 坐标和 y 坐标

ceil

的上限值是大于等于该数字的最接近 的整数. 返回由参数 x 指定的角的余弦值(介

Math.ceil(x)

cos

于 -1.0 与 1.0 之间的值).必须以弧 度为单位指定角度 x. 返回 e 的 x 次方的值,其中 e 为自

Math.cos(x)

x 为弧度,换算公式为:1 弧度=角度*180/Math.PI

exp

然对数的底 (e),x 为参数 x 中指定的 Math.exp(x) 指数. 返回参数 x 中指定的数字或表达式的

常数 Math.E 可以提供 e 的值.

floor

下限值.下限值是小于等于指定数字或 Math.floor(x) 表达式的最接近的整数.

表达式:Math.floor(12.5)将返回值:12

log max min pow random

返回参数 x 的自然对数. 返回两个数中最大者 返回两个数中最小者 计算 x 的 y 次幂 返回 n,其中 0 <= n < 1 将参数 x 的值向上或向下舍入为最接 近的整数并返回值 计算并返回以弧度为单位指定的角度

Math.log(x) Math.max(x,y) Math.min(x,y) Math.pow(x) Math.random()

x>0

获得 a-b 之间的随机整数的公式为: Math.floor(Math.random()*(b-a+1)+a)

round

Math.round(x)

sin sqrt tan

的正弦值 计算并返回指定数字的平方根 计算并返回指定角度的正切值

Math.sin(x) Math.sqrt(x) Math.tan(x)

换算公式参见 cos x>=0 换算公式参见 cos

以上我们向大家介绍了 Flash 游戏制作中最常用的一些 ActionScript,掌握了这些基本控制方法,就可以制 作出很多有意思的 Flash 游戏,同时在制作的过程中你还会发现更多的技巧,欢迎投稿和大家一起交流。

FLASH 游戏制作基础:响应键盘的四种方法
响应键盘的方法作为 AS 中的一个重要组成部分,在如今已经越来越广泛的使用,尤其是在 FLASH 游戏制作中,如果缺少了 响应键盘的方法,那是不可能的,而响应键盘的方法主要的四种,分别是: 1、利用按钮进行检测 2、利用 KEY 对象

—7—

Flash 小游戏开发基础 3、利用键盘侦听的方法 4、利用影片剪辑的 keyUp 和 keyDown 事件来实现响应键盘 只有熟练掌握了这些方法,然后加以变通的话,就会得到很多意想不到的效果,下面我就结合理论和自己的想法简要的介绍一 下。 第一种响应键盘的方法:利用按钮进行检测来实现响应键盘 在按钮的 on 事件处理函数中不但可以对鼠标事件作出响应,而且可以对键盘事件作出响应。 如在按钮的动作面板中加入如下 所示的代码,在敲击键盘上的 X 键时输出窗口中将提示:X is pressed 在按钮上加上:

on (keyPress "x") { trace("X is pressed"); } 但是要注意的是:检测键盘上的字母键时,字母都应为小写。如果要检测键盘中的特殊键, Flash 中有一些专门的代码来表
示它们,下面列出了一些常用的功能键的表示代码: 如要检测键盘上的键,可以使用下面的 ActionScript:

on (keyPress "") { trace("Left is pressed"); }
另外,你可以在一个按钮中加入若干个 on 函数,也可以在一个 on 函数中结合多种事件,这使 您可以为按钮定义自己熟悉常 用的快捷键,如下所示:

on (release, keyPress "") { _root.myMC.prevFrame(); } on (release, keyPress "") { _root.myMC.nextFrame(); }
上面的第一个语句实现单击按钮或按键盘上的左方向键,控制影片剪辑 myMC 回退 1 帧,而上面的第二个语句实现单击按钮 或按键盘上的右方向键,控制影片剪辑 myMC 前进 1 帧。 第二种响应键盘的方法:利用 Key 对象来实现响应键盘的操作 利用按钮检测按键动作很有效,但是并不利于检测持续按下的键,所以不适合于制作某些通过键盘控制的游戏。 这时,您就需要用到 Key 对象。Key 对象包含在动作面板的“对象”/“影片”目录下面,它由 Flash 内置的一系列方法、常 量和函数构成。使用 Key 对象可以检测某个键是否被按下,如要检测左方向键是否被按下,可以使用如下 ActionScript:

if (Key.isDown(Key.LEFT)) { trace("The left arrow is down"); }
函数 Key.isDown 返回一个布尔值,当该数中的参数对应的键被按下时返回 true,否则返回 false。常量 Key.LEFT 代表键盘上 的左方向键。当左方向键被按下时,该函数返回 true。 Key 对象中的常量代表了键盘上相应的键,下面列出了一些基本的常量: 一些功能键的表示: Key.BACKSPACE Key.ENTER Key.PGDN Key.CAPSLOCK Key.ESCAPE Key.RIGHT Key.CONTROL Key.HOME Key.SHIFT Key.DELETEKEY Key.INSERT Key.SPACE Key.DOWN Key.LEFT Key.TAB Key.END Key.PGUP Key.UP 以上是键盘上的功能键,那么如何表示键盘上的字母键呢? Key 对象提供了一个函数 Key.getCode 来实现这一功能,如下所示:

—8—

Flash 小游戏开发基础

if (Key.isDown(Key.getCode("x"))) { trace("X is pressed"); }
上面脚本的意思就是,利用 Key.getCode 函数来告诉系统你是否按下了 x 键,如果按下了 x 键以后,函数 Key.isDown 则会返 回 true,在输出窗口就会输出 X is pressed。 第三种响应键盘的方法:利用键盘侦听的方法来实现响应键盘(个人习惯用这种方法) 假设在影片剪辑的 onClipEvent(enterFrame)事件处理函数中检测按键动作,而影片剪辑所在的时间轴较长,或计算机运算速 度较慢,就有可能出现这种情况:即当在键盘上按下某个键时还未来得及处理 onClipEvent(enterFrame)函数,那么按键动作将被 忽略,这样的话,很多你想要的效果就会无法实现了。 另外,还有一个需要解决的问题就是,在某些游戏(如射击)中,我们需要按一次键就执行一次动作(发射一发子弹),即使长时 间按住某个键不放也只能算作一次按键,而 Key 对象并不能区别是长时间按住同一个键还是快速地多次按键。 所以如果要解决这个问题,就需要用到键盘侦听的方法。你可以使用 “侦听器(listener)”来侦听键盘上的按键动作。 要使用侦听器之前,首先需要创建它,你可以使用如下所示的命令来告诉计算机你需要侦听某个事件:

Key.addListener(_root);
Key.addListener 命令将 主时间轴 或 某个影片剪辑 作为它的参数,当侦听的事件发生时,可以用这个参数指定的对象来响 应该事件。 上面的代码指定主时间轴来响应该事件。要让主时间轴对该事件作出响应,还需要设置一个相应的事件处理函数,否则设置侦 听器就没有什么意义了。 键盘侦听的事件处理函数有两个:onKeyUp 和 onKeyDown,如下所示:

Key.addListener(_root); _root.onKeyUp = function() { trace(Key.getAscii()); }; //代码的意思是,当按下一个键并释放后,输出窗口将输出你按下的那个键的 Ascii 码
当然,你也可以使用影片剪辑作为侦听键盘的对象,只需要使用影片剪辑的路径代替_root 作为 Key.addListener 命令的参数 就可以了。 比如下面代码:

Key.addListener(_root.mc); _root.mc.onKeyUp = function() { trace(Key.getAscii()); };
代码的意思是,当按下一个键并释放后,输出窗口将输出你按下的那个键的 Ascii 码,意思差不多,但是键盘侦听对象不同, 一个是影片 mc,一个是主时间轴。 第四种响应键盘的方法:利用影片剪辑的 keyUp 和 keyDown 事件来实现响应键盘 最后一种方法很容易被忽视,但是也有一定的应用价值,最重要的是把概念弄清楚。 影片剪辑包含两个与键盘相关的事件 keyUp 和 keyDown,使用它们也可以实现对按键事件的响应

—9—

Flash 小游戏开发基础 例如下面的代码:

onClipEvent (keyDown) { trace(Key.getAscii()); } //当按下键盘上的一个键的时候,输出窗口将输出按下的这个键的 Ascii 码值。
函数 Key.getAscii 表示返回与按键相对应的 ASCII 码,其中 ASCII 码是一个整数,键盘上的每个字符对应一个 ASCII 码,如 字母 A 对应的 ASCII 码为 65,B 对应的 ASCII 码为 66,a 对应的 ASCII 码为 97, b 对应的 ASCII 码为 98,+ 对应的 ASCII 码为 43 等。需要注意的是:只有字符键才有 ASCII 码,键盘上的功能键是没有 ASCII 码的。 如果我想在输出窗口中输出与按键相对应的字符,那怎么办? 这时候,你可以使用 String 对象的 fromCharCode 函数将 ASCII 码转换成字符,如将上例的代码改成如下所示:

onClipEvent (keyDown) { trace(String.fromCharCode(Key.getAscii())); }; //意思就是说,当按下键盘的一个键,输出按下的这个键相对应的字符,当然除了功能键。

关于 String 对象的详细解释,大家可以查看动作面板的“对象”/“核心”目录下面。

Flash 游戏制作--空战
Flash 游戏制作--空战 射击类游戏一直是 Flash 游戏制作中的一个热点,大多数 Flash 射击游戏都是都是纵版的,也就是游戏 背景的前进方向是垂直的,这样的游戏已经司空见惯了。所以这次我们来制作一个横版的射击游戏,游戏 背景和飞机的运动方向都是水平的。 游戏运行后的主界面如图 1 所示:

图1 游戏说明:

—10—

Flash 小游戏开发基础

此游戏玩家是以第一视角的模式来进行的,所谓第一视角就是游戏的界面相当于玩家的双眼,通过这样的 形式,可以使游戏达到一种非常逼真的效果,仿佛您已经置身于激烈的游戏之中了。游戏中玩家可以使用 鼠标控制屏幕中的瞄准镜,瞄准并射击从左边随机出现的敌机,飞机会以各种路线在空中飞行以避开你的 射击,如果敌机被射中后,就会从空中跌落下来,相应的玩家会得一分,在游戏规定的 100 秒内,尽量击 落更多的敌机。 制作步骤: 一:游戏中相应元件的制作 1. 既然是空战游戏, 自然少不了飞机, 所以首先来制作游戏中的敌机。 在影片中新建一个 Graphic 元件, , 命名为 gPlane,进入元件的编辑状态后,可以从外部导入一张飞机的图片,然后将其分离,稍稍加工一下 即可。或者使用 Flash 提供的强大的绘图工具自己绘制一架飞机,如图 2 所示:

图2 有了飞机,还需要一个飞行员飞机才可以工作,所以再建一个 Graphic 元件,命名为 gMan,进入元件编辑 状态后,使用椭圆绘图工具绘制一个简单的人头即可,如图 3 所示:

图3 接下来就需要将飞机和飞行员组合到一起了,因为游戏中需要使用 Action 动作脚本对飞机进行控制,所以 需要将最终的组合体制作成 Movie clip 元件,所以再新建一个 Movie clip 元件,进入元件的编辑状态后, 将元件 gMan 和 Gplane 分别拖到编辑区,使用鼠标调整其相对位置,如图 4 所示:

图4 这样,一架逼真的战斗机就制作完成了。 2. 飞机飞行动画的制作: 游戏中飞机是从游戏窗口左边随机出现的, 但是飞机的飞行路线是事先确定好的, 我们可以在制作过程中按照实际需要制作一些飞机沿一定路线飞行的 Motion 动画,使用 Guide Line 引导 线可以很方便的实现,然后在游戏中分别调用即可,本游戏预先制作了三中不同的飞行路线,这里以其中 一种举例说明,其它的制作方法完全类似。 新建一个 Movie clip 元件,命名为 mPlane1,进入元件的编辑状态后,在图层 layer1 的上面插入一个引 导层,在引导层上使用铅笔工具随意绘制一条曲线,然后将图层延续到第 120 桢,如图 5 所示:

—11—

Flash 小游戏开发基础

图5 然后将元件 mPlane 拖到图层 layer1 的第 1 关键桢,放置到曲线的左边的开始端点,飞机会自动吸附到 此端点,接着在属性面板中设置飞机的 Instance name 为 airplane。在第 120 桢插入一个关键祯,同样 的将飞机拖到曲线的右边的端点,也会自动吸附上去,最后,在第 1 祯到第 120 祯的任意祯上单击鼠标右 键,选取 Creat Motion Tween 命令即可,这样就创建了飞机从曲线的左端点沿曲线运动到右端点的运动 效果。最后还需要添加一个图层 Action,用来设置 Action 动作脚本,在第 1 桢添加如下 as: var planeDepth=_root.pDepth; 在最后一桢(120 祯)添加如下 as: _root.numPlane--; this.removeMovieClip(); 按照同样的方法分别制作元件 mPlane2 和 mPlane3,和 mPlane1 的唯一不同点就是引导层的曲线不一 样。 3.制作瞄准镜:游戏中玩家可以控制的唯一对象就是瞄准镜,可以用它瞄准并射击敌机,新建一个 Movie clip 元件,命名为 mPointer,在编辑区中使用椭圆工具绘制一个正圆,然后在正圆中绘制四条方向不同的 直线即可,如图 6 所示:

图6 4.云彩的制作:既然是空战,天空中当然少不了白云,并且适当的在游戏中加入白云这样的对象,可以使 游戏更生动和逼真,游戏中的白云是使用 Action 动作脚本随机复制并进行控制的,所以这里我们新建一个 Movie clip 元件,命名为 mCloud,进入元件编辑状态后,使用铅笔工具的 Ink 绘制模式,绘制一个弯曲的 闭合区域,并将图层延续到第 5 祯,如图 7 所示:

图7 接下来需要添加复制和控制白云的 Action 动作脚本, 新建一个图层, 分别在第 1,3,5 三祯插入三个关键祯, 给第一祯添加如下 AS: this._x = 575;

—12—

Flash 小游戏开发基础

this._y = 30+random(300); speed = 2+random(5); 给第 3 祯添加如下 AS: this._x -= speed; 给第 5 祯添加如下 AS: if (this._x<-35) else { gotoAndPlay (_currentframe-2); } 5.飞机被击落的效果:游戏中飞机如果被击落,如果简单的来做,只需要设置飞机消失即可,不过为了增 强游戏的观赏性,我们这里专门来设计以下飞机被击落的效果,而且会带有爆炸的声音。 新建一个 Movie clip 元件,命名为 mDown,进入元件的编辑状态后,首先添加三个图层分别为 down, planedown 和 explord,在图层 explord 的第一祯绘制一个如图 8 所示的多角形,并填充上适当的颜色:

图8 然后在第 3 祯插入一个关键祯,在属性面板上设置此多角形的 Alpha 透明度值为 15%,最后建立第 1 到第 3 祯的 Motion 运动过渡,这样就实现了飞机被击中的瞬间爆炸的效果。 接下来制作飞机下落的效果。在图层 planedown 的第 2 祯插入一个关键祯,将元件 Mplane 拖进编辑区, 使用旋转工具将飞机旋转 90 度,使飞机头冲下,然后在第 10 祯插入一个关键祯,将飞机向下移动一段直 线距离,并适当降低飞机的 Alpha 透明度值,最后建立第 2 祯到第 10 祯的 Motion 运动过渡效果,这样 飞机被击中后下落并消失的效果也有了。 不过如果飞机在下落过程中, 能有冒烟的效果就更完美了。 所以我们在图层 down 的第 4 祯插入一个关键 祯,然后使用椭圆工具绘制个竖直的扁椭圆,并填充上黑色,在第 10 祯插入关键祯,调整椭园的形状并设 置降低其透明度,同样建立一个 Motion 运动过渡效果。 然后插入一个图层 sound,用来设置飞机下落的声音效果,从外部导入一个爆炸的音效,然后选中图层 sound,从属性面板的 sound 下拉列表中选择所导如的身影,最后将此层也延续到第 10 祯,时间线如图 9 所示:

图9 最后还要添加一些 Action 动作脚本对其加以控制。新建一个图层 ACTION,在第 1,2,和 10 祯分别插入一 个关键祯,然后给第一祯添加如下 AS: this._x = _root.expX; this._y = _root.expY; 给第 2 祯添加如下 AS: this._x=_root.expX; this._y=_root.expY;

—13—

Flash 小游戏开发基础

给第 10 祯添加如下 As: this.removeMovieClip(); 6.制作记时器:游戏是有一定时间控制的,所以还需要添加一个记时器,使用动态文本可以方便的实现, 新建一个 Movie clip 元件,命名为 mTime,在元件编辑状态下,使用文本工具绘制一个矩形文本框,然后 在属性面板中设置其为 Dynamic 动态文本,这样就可以用 Action 对其中的内容加以控制了,设置其变量 名为 rTime,然后在文本框前面输入提示信息,如图 10 所示:

图 10 然后新建一个层,在第一祯添加如下 AS: now = new Date(); //新建一个 Date 对象 startTime = now.getTime(); //设置开始时间为系统时间 playTime = _root.playTime; rTime = playTime; 在第三祯添加如下 AS: now = new Date(); currentTime = now.getTime(); rTime = playTime-int((currentTime-startTime)/1000); if (!rTime) { _root.gotoAndPlay("reStart"); stop (); } //显示并控制记时器中的时间 在第 5 祯添加如下 AS: gotoAndPlay (_currentframe-2); 到此为止,游戏中需要的元件大部分准备好了,下面就可以开始布置主场景了。 二:布置主场景 1.首先将默认图层 layer1 重命名为 background,使用矩形工具绘制一个和舞台一样大小的矩形,并填充 上天蓝色,将图层延续到第 50 祯。 2. 新建两个图层分别为 start 和 gun,在 start 图层上用来设置游戏的开始界面, 使用文本工具输入游戏的 名称,并将瞄准器放置到图层 gun 中,并在属性面板中设置瞄准器的 Instance name 为 pointer,如图 11 所示:

—14—

Flash 小游戏开发基础

图 11 3.在图层 gun 的第 22 祯插入关键祯,输入游戏时间已到的消息,如图 12 所示;

图 12 4.新建一个图层命名为 score&time,用来放置记分器和记时器,将记时器 mTime 放到舞台下面靠右的 位置,然后在下面靠左的位置绘制一个动态文本框,设置其变量名为 score,用来记录游戏的得分,如图 13 所示:

图 13 三:给游戏添加 Action 动作脚本 最后的游戏就是添加 Action 动作脚本了。 新建一个图层,命名为 ACTION,设置第 2 祯的祯标签为 start, 设置第 9 祯的祯标签为 dup, 设置第 15 祯的祯标签为 gotoDup, 设置第 22 祯的祯标签为 reStart. 在第一祯添加如下 AS: Mouse.hide();

—15—

Flash 小游戏开发基础

startDrag("/pointer", true); //游戏开始前,首先隐藏鼠标,然后使瞄准器变为可拖动状态 sShoot = new Sound(); sShoot.attachSound("sShoot"); //新建一个 sound 声音对象,然后从外部导入射击的音效 Sshoot,使用 attachsound 方//法将此声音绑 定 sExp = new Sound(); sExp.attachSound("sExp"); ////新建一个 sound 声音对象,然后从外部导入射击的音效 Sexp,使用 attachsound 方//法将此声音绑 定 stop(); 在第 2 祯添加如下 AS: score = 0; //设置初始得分为 0 playTime = 100; //设置游戏时间为 100 秒 var expX; var expY; //定义两变量,代表飞机的坐标 cDepth = 100; pDepth = 0; numPlane = 0; numCloud = 0; //定义变量,分别代表飞机和云的深度和数量 _root.attachMovie("mP", "pointer", 300); startDrag("/pointer", true); 在第 9 祯添加如下 AS: if (Math.random()<0.2 && numCloud<5) { numCloud++; _root.attachMovie("mCloud", "c"+cDepth, cDepth); cDepth = (++cDepth)%100+100; } //复制白云 if (Math.random()<0.3 && numPlane<7) { _root.attachMovie("mPlane"+(1+random(3)), "P"+pDepth, pDepth); numPlane++; with (eval("/p"+pDepth)) { _x = -20-random(120); _y = 150+random(60); } pDepth = (++pDepth)%100; } //复制飞机,并使用随机函数设置飞机出现的坐标 在第 15 祯添加如下 AS: gotoAndPlay("Dup"); //返回到祯 Dup 复制飞机

—16—

Flash 小游戏开发基础

在第 22 祯添加如下 AS: _root.pointer.removeMovieClip(); //游戏结束后,从游戏中删除瞄准器 在第 50 祯添加如下 AS: Mouse.show(); //显示鼠标 for (i=0; i<100; i++) { removeMovieClip ("/c"+(100+i)); removeMovieClip ("/p"+i); } stop (); //删除游戏中所有复制出来的飞机和白云 最后的时间线如图 14 所示:

图 14 到这里,一款精彩的空战射击游戏就制作完成了,您可以按照相似的制作方法,制作一款比较传统的纵版 射击游戏。此实例其实是设计空战类射击游戏的通用思路,其它飞行射击游戏其实是在此基础上扩展成的, 所以还可以进一步丰富游戏的功能,加强游戏的可玩性。

Flash 飞行游戏制作全解
Flash 一直是大家喜欢的交互多媒体开发工具,Flash 游戏则以简单、耐玩,而深受用户喜爱。看似复杂多变的 Flash 游戏,其制作 并不难。本文以一款传统的飞行游戏制作为例,说明其制作全过程,相信在你阅读完本文后,也可以通过自己的想象,制作出心仪 的游戏来。

一、飞行游戏制作思路分析
这是一款相对传统的飞行游戏。它使用上、下、左、右键控制飞机的运行方向,Shift 键发射子弹,空格键发射导弹。游戏中 共有两种敌机,一号敌机的飞行方向是由下而下,二号敌机是由左至右,两种敌机的飞行轨迹都是弧线的、随机的。 在游戏中我们添加了几组数据,以增加游戏的刺激性。例如,装备库的设计,它可以随机添加一些装备,以供主控飞机使用。这其 中包括有子弹的速度、导弹的个数、飞机数量,以及主控飞机的飞行速度。装备库的设计,会大大增加游戏的娱乐性。 另外,在 BOSS 敌机的设计中,我们使用了利用弧度换算角度的公式,使 BOSS 敌机可以发射一种子弹,跟踪主控飞机的坐标。 相信在这些设计中,会让大家品尝到不同的数学公式,在游戏制作中的妙用。 注:本文全部源程序及素材下载地址为 http://www.itbook.com.cn/hdb/fj_game.rar。 二、游戏界面设计

1.制作开始界面
每一个游戏都有一个开始界面,供游戏者选择,我们在第 1 帧中制作游戏的开始界面。启动 Flash MX 2004,请在第 1 帧中加 入 stop()代码,然后制作一个 start 按钮,当按钮点击时跳转到下一场景。如图 2 所示。按钮的内容如下:

—17—

Flash 小游戏开发基础 on(press){ gotoAndPlay("Scene 2",1) } 2.制作星空 按下 Shift+F2 组合键,打开“场景”面板,点击“+”按钮新增加一个场景,进入场景 2,开始游戏的制作。 将“图层 1”更名为 scene 以制作星空。其实,这些星空都是用圆形绘图工具绘制上去的,它们的大小只有一个或是两个像素, 我们可以使用复制,然后再对齐的方式,使它们布满场景。 全选这些亮点,按 F8 键将其转换成影片剪辑,将这个影片剪辑复制 3 次,然后放置在一个影片剪辑中,让它们并排向下循环移动 即可。

3.变量设置
新建一个图层,命名为 fenshu,使用文本输入工具,在屏幕下方输入:“现在分数:”、“子弹速度”、“子弹类型:”、 “导弹数量:”、“飞机速度:”、“飞机数量:”等文字内容。 新建一个图层,命名为 score,在工具箱中点击“文本工具”按钮,然后在“属性”面板中更改其为“动态文本”,在“现在 分数:”的后面拖出一个输入框,在“属性”面板中将“变量”更改为 score。 使用相同的方法,新建 shot_speed 图层,在“子弹速度:”后制作一个动态文本框,变量名称为 shot_speed。新建一个 shot_sty 图层,在“子弹类型:”后制作一个变量名为 shotsty_txt 的动态文本框。新建一个 plane_speed 图层,在“飞机速度:”后制作 一个 plane_speed 的动态文本框。 新建 missilenum 图层,使用绘图工具绘制作如图 5 所示的图形,选取这些图形按下 F8 键将其转换成影片剪辑,命名为 missilenum_mc,在“属性”面板“实例名称”框中输入“missile_num”。 进入 missilenum_mc 影片剪辑,在第 3、4、5、6 帧处按 F6 建立关键帧,在第 6 帧处加入 stop()代码,然后将第 1 帧中的导弹全 部删去,第 2 帧保留一个,第 3 帧保留 2 个,以此类推。 回到场景,新建一个 plane_num 图层,取实例名为“planenum_mc”,依照上一步的方法制作。 回到场景,在第 1 帧中加入如下代码,新建一个 info 图层文件夹,将上面的这些图层放置其中: score=0 shot_speed=10 shotsty_txt="单弹道" missilenum=6 plane_speed=10 planenum=4 shot_sty=1 missile_text=6 代码说明: 这里主要是为这些变量赋值,score 等于分数,初始值为 0,shot_speed 等于子弹速度,初始值为 10;shotsyt_txt 等于子弹 类型,开始时它为单弹道;missilenum 表示导弹数量,初始值为 6;plane_speed 表示飞机速度,初始值为 10;planenum 表示飞 机数量,初始值为 4;子弹类型的变量等于 1;导弹类型的变量等于 6。

三、主机制作
1.主机结构
在场景中新建一个 plane 图层,使用绘图工具绘制一个飞机。 选中飞机按 F8 键将其转换成影片剪辑,名称为 plane_mc,双击进入该影片剪辑,新建一个图层,绘制一个矩形,如图 8 所示,按 F8 键将其转换成影片剪辑,取实例名称为 plane_hit,再将透明度降为 0。因为 Flash 的碰撞测试是以矩形为准的,所以,我们绘 制矩形影片剪辑,用来碰撞测试。 回到场景,为飞机影片剪辑取实例名称为 plane_mc,按 F8 键转换成影片剪辑,双击进入影 片剪辑开始制作,新建一个图层,在第 30 帧建立关键帧,绘制一个渐淡的红色圆球,将其转换成影片剪辑,名称为 plane_bo。如

—18—

Flash 小游戏开发基础 图 9 所示。 在 plane_bo 影片剪辑中,第 5 帧制作它被放大,第 10 帧缩小变黄,第 20 帧渐渐消失。新建一个图层,导入音乐

文件 fx13431_bomb8.mp3,放置在第 1 帧。双击空白区域回到上一级影片剪辑, 新建 8 个图层,分别复制 plane_bo 影片剪辑,放置在第 30 帧以后的位置,隔两帧放置一个。等于是让 8 个爆炸的圆球依次播 放,模仿爆炸效果。新建一个图层,在第 1 帧加入代码: plane_mc._y=550 plane_mc._x=0 _root.command_bl=false _root.hittest_bl=false _root.shot_bl=false 代码说明: 在第 1 帧,我们让主控飞机的 Y 坐标等于 550,X 坐标等于 0,让代表可以被控制的 command_bl 变量为假,表示在这 1 帧时, 主控飞机不能被控制,hittest_bl 敌机的热区检测为假,也就是主控飞机不能被击爆,shot_bl 子弹可以发射的变量为假。 在第 2 帧加入代码: plane_mc._y-=10 plane_mc._alpha=30 代码说明: 主控飞机的 Y 坐标等于 Y 坐标减去 10,透明度等于 30。 在第 3 帧加入代码: if(plane_mc._y<=0){ gotoAndPlay(4) }else{ gotoAndPlay(2) } 代码说明: 当主控飞机的坐标小于等于 0 时,开始播放第 4 帧,如果不然,将播放第 2 帧,实际上等于让飞机以 10 个坐标的速度递减。 在第 4 帧加入代码: _root.command_bl=true _root.hittest_bl=false _root.shot_bl=true _root.shot_bl=true _root.shot_sty=1 _root.shot_speed=10 _root.plane_speed=10 _root.missile_num.gotoAndPlay(1) 代码说明: 在前 3 帧中,实际是一个让主控飞机飞入场景的动画,而现在,为一些初始变量赋值。 在第 30 帧加入代码: stop() plane_mc._alpha=100 _root.command_bl=true _root.hittest_bl=true 代码说明: 在这一帧,我们设置透明度为 100,主机可以被控制,碰撞测试也可以开始。 在第 31 帧加入代码: _root.command_bl=false _root.hittest_bl=false

—19—

Flash 小游戏开发基础 _root.shot_bl=false 代码说明: 如果主控飞机被击爆,那么这个影片剪辑应该开始播放了,主机不能被控制,碰撞测试和子弹都不能发射。 在第 65 帧,也就是最后 1 帧加入代码: if(_root.planenum_mc._currentframe<2){ stop() } if(_root.planenum_mc._currentframe!=1){ _root.planenum_mc.gotoAndStop(_root.planenum_mc._currentframe-1) gotoAndPlay(1) } 代码说明: 当根目录下的 planenum_mc 影片剪辑的当前帧小于 2 时,本影片剪辑将不再循环播放。如果 planenum_mc 影片剪辑的当前帧不 等于 1 时,那么代表主控飞机个数的 planenum_mc 影片剪辑将后退 1 帧。本影片剪辑将重新开始播放。也就是说,planenum_mc 影 片剪辑一共有 4 帧,在正常情况下,本影片剪辑应该也只播放 4 次,除非有其他的外界程序干扰。

2.主机飞行控制
回到场景中,为主控飞机的影片剪辑添加实例名称为 plane,在第 1 帧加入代码如下: plane.onEnterFrame=function(){ if(command_bl){ if(Key.isDown(Key.LEFT) && plane._x>30){ plane._x-=plane_speed } if(Key.isDown(Key.RIGHT) && plane._x<620){ plane._x+=plane_speed } if(Key.isDown(Key.UP) && plane._y>30){ plane._y-=plane_speed } if(Key.isDown(Key.DOWN) && plane._y<420){ plane._y+=plane_speed } } 代码说明: 当 plane 影片剪辑开始播放时,每播放 1 帧执行一次。 如果 command_bl 变量为真时,也就是我们刚才设置的主控飞行开关为真时;当按键中的 LEFT 键按下,而且 plane 影片剪辑的 X 坐标大于 30 时,plane 的 X 坐标等于它的 X 坐标减去 plane_speed 变量,也就是飞机开始向左移动,其他代码效果相同。

3.子弹发射方法
回到场景中,新建一个 shot 图层,在场景的外面,使用绘图工具绘制一个子弹的形状,如图 10 所示,选中它并按 F8 键转换 成影片剪辑,名称为 shot,输入实例名称为 shot。 双击进入影片剪辑,在第 2 帧建立关键帧,放置 2 个这样的子弹在中心位 置。在第 3 帧放置 4 个这样的子弹在中心位置。第 1 帧加入 stop()代码,让影片剪辑在开始停止播放。 回到场景中,给 shot 对象加入如下代码(注意是给对象加代码,而不是帧),方法是鼠标右键选择子弹对象,选择“动作”命 令,然后输入代码。 onClipEvent(enterFrame){ this._y-=10+random(_root.shot_speed)

—20—

Flash 小游戏开发基础 } 代码说明: 当影片剪辑开始播放时,它的 Y 坐标等于它的 Y 坐标减去 10 加上 shot_speed 的随机数。 在场景的第 1 帧,我们刚才主控飞机加控制代码的地方,在第 1 行加上 n=0,在其他按键代码的后面,添加如下代码: if(Key.isDown(Key.SHIFT) && _root.shot_bl){ if(n<50){ shot.duplicateMovieClip("shot"+n,n+100) _root["shot"+n].gotoAndStop(shot_sty) _root["shot"+n]._x=_root.plane._x _root["shot"+n]._y=_root.plane._y-10 n++ }else if(n>=50){ n=0 } } 代码说明: 当按下 Shift 键时,且 shot_bl 子弹控制开关为真时;当 n 小于 50 时,shot 影片剪辑开始复制,一共复制 50 个,图层深度 为 N+100;复制品跳转到 shot_sty 变量所指的那一帧;复制品的 X 坐标等于主控飞机的 X 坐标;复制品的 Y 坐标等于主控飞机的 Y 坐标减 10;N 递增;当 N 大于等于 50 时,N 等于 0。 这段代码实际上就是一个子弹的发射过程,当我们按下 Shift 键时,影片剪辑就会不断地进行复制,而起始坐标永远都是飞机 的坐标,影片剪辑本身的代码中,使它不停的向上运动,就形成了完整的子弹发射过程。

4.导弹发射方法
在场景中新建一个图层,命名为 missile,使用绘图工具绘制一个导弹,如图 11 所示,转换成影片剪辑,取实例名为 missile, 进入影片剪辑开始编辑工作。 要大一些。 选中该图层,按 F8 键转换成影片剪辑,在第 40、70 帧建立关键帧,在第 40 帧把爆炸效果缩放到特别大,大到你喜欢的程度, 然后建立 Motion 运动。 新建一个图层,导入音乐文件 fx13443_explomed.mp3 放在第 1 帧,在第 1 帧加入如下代码: stop() this._x=5000 this._y=5000 代码说明: 在第 1 帧停止播放,影片剪辑的 X 坐标和 Y 坐标等于 5000。 回到场景中,在主控飞机的代码中,加入如下代码: if(Key.isDown(Key.SPACE) && _root.missile._currentframe==1 && shot_bl){ if(missile_text>1){ missile.play() missile._x=plane._x missile._y=plane._y missile_text-missile_num.gotoAndStop(missile_text) } } 代码说明: 在影片剪辑中,再次选取导弹按 F8 转换成影片剪辑,在第 15 帧建立关键帧,将导弹的坐标放置 在 X:0,Y:-175 的位置上,从第 1 帧建立动画,新建一个图层,在第 15 帧绘制一个爆炸的圆形渐变图,类似飞机爆炸的那种,但

—21—

Flash 小游戏开发基础 当按下空格键时,且 missile 影片剪辑的当前帧等于 1,当 shot_bl 子弹开关为开时;当 missile_text 变量大于 1 时;导弹 影片剪辑开始播放;导弹影片剪辑的坐标等于主控飞机的坐标; Missile_num 也就是我们最初制作的导弹数量的影片剪辑跳转到 missile_text 变量的位置。

四、制作装备彩蛋
回到场景中,新建一个图层,命名为 brand,使用绘图工具绘制如图 12 所示的内容。转换成影片剪辑。 把这个图形放置 在 Y:1000,然后进入影片剪辑编辑,选取文字内容,按 F8 键转换成影片剪辑,命名为 brand_mc,取实例名为 brand_mc。 进入 brand_mc 影片剪辑,在第 1 帧输入内容“子弹加速”,在第 2、3、4、5 帧分别输入内容“子弹样式”、“飞机加速”、 “增加飞机”、“增加导弹”。在第 1 帧加入 gotoAndStop(random(5)+1) 代码,让影片剪辑直接跳转到相应的帧。 回到场景中,选取这个装备图标,为对象加入代码,记得吗?在子弹制作中,我们已经给对象加过代码了: onClipEvent(enterFrame){ this._y+=5 if(this._y>=3000){ this._y=-1000 this._visible=1 } if(this._y<=-100){ this.brand_mc.gotoAndPlay(1) this._x=random(650) } if(this.hitTest(_root.plane)){ this._visible=0 this._y+=200 if(this.brand_mc._currentframe==1){ _root.shot_speed=_root.shot_speed+10 } if(this.brand_mc._currentframe==2 && _root.shot_sty<4){ _root.shot_sty+=1 if(_root.shot_sty==2){ _root.shotsty_txt="双弹道" }else if(_root.shot_sty==3){ _root.shotsty_txt="四弹道" } } if(this.brand_mc._currentframe==3){ _root.plane_speed+=1 } if(this.brand_mc._currentframe==4 && _root.planenum_mc._currentframe<5){ _root.planenum_mc.gotoAndStop(_root.planenum_mc._currentframe+1) } if(this.brand_mc._currentframe==4 && _root.planenum_mc._currentframe==4){ _root.score+=2000 } if(this.brand_mc._currentframe==5 && _root.missile_num._currentframe<6){ _root.missile_num.gotoAndStop(_root.missile_num._currentframe+1) }

—22—

Flash 小游戏开发基础 } } 代码说明: 当影片剪辑开始播放时,它的坐标等于它的坐标加上 5。当它的坐标大于等于 3000 时,它的坐标等于负 1000,它的显示参数 为可视。当它的坐标等于负 100 时,它影片剪辑中的 brand_mc 也就是刚才制作的文字影片剪辑开始播放第 1 帧,实际上也就是跳 转到任意一帧,它的 X 坐标等于 650 的随机数,等于是屏幕的任意位置。 当它碰撞到主控飞机时,它的显示为假,也就是说它变得不可见,同时它的坐标加上 200。当它的 brand_mc 影片剪辑的当前 帧等于 1 时,shot_speed 子弹速度等于再加上 10。 当它的 brand_mc 影片剪辑的当前帧等于 2 而且子弹样式小于 4 时,子弹样式等于再加上 1,如果子弹样式等于 2,那么 shotsyt_txt 动态文本就显示双弹道,如果等于 3 就显示四弹道。如果它的 brand_mc 影片剪辑的当前帧等于 3,那么 plane_speed 飞机速度就等于再加上 1,如果它的 brand_mc 影片剪辑的当前帧等于 4 而且 planenum_mc 的当前帧小于 5,那么 planenum_mc 影片 剪辑的当前帧等于再加上 1 帧,这样就等于增加了一个主控飞机。 如果它的 brand_mc 影片剪辑的当前帧等于 4 而且 planenum_mc 的当前帧等于 4, 也就是说主控飞机已经满了, 那么就加上 2000 分。如果它的 brand_mc 影片剪辑的当前帧等于 5 而且 missile_num 导弹数量的当前帧小于 6,那么就增加一个导弹。

五、制作敌机
1.一号敌机制作方法
新建一个图层,命名为 enemy_a,绘制一个如图 13 所示的敌机,选中该敌机按 F8 键,转换成影片剪辑,名称为 enemya_mc, 实例名也是 enemya_mc,双击进入影片剪辑。 removeMovieClip(_parent._parent) _root.score+=100 再次新建一个图层,在第 2 帧放入 fx13431_bomb8.mp3 音乐文件,记得要使用 stream 数据流的方式,双击空白区域回到场景。 在场景中选中该影片剪辑,放置在场景以外的左上角,再次按 F8 键转换成影片剪辑,名称为 enemya_eft,实例名为 enemy_a, 进入影片剪辑,在图层 1 上加入一个引导图层,使用绘图工具绘制一条曲线,如图 14 所示。 将两个图层都延缓到第 60 帧,将 第 1 帧的敌机放置在引导线的起始,在最后 1 帧将敌机放置到引导线的结尾,建立 Motion 动画,在最后 1 帧加入 removeMovieClip(_parent)代码,删去上一级影片剪辑。这也就是说,无论敌机是被击爆的,还是飞行结束,它都将消失,所不同 的就是加不加分而已。 在第 1 帧加入代码 stop(),让影片停止播放,新建一个图层,在新图层的第 2 帧 制作一个爆炸的效果,在最后帧加入如下代码,这等于删去上一级影片剪辑,而分数再加上 100。

2.一号敌机的复制方法
回到场景,选中敌机按 F8 键转换成影片剪辑,名称为 enemya,实例名称为 enemy_a,选取后再次按 F8 键转换成影片剪辑,名 称为 enemy_a,实例名称为 enemya。双击进入影片剪辑。 在第 10 帧按 F5 键,新建一个图层,在第 1 帧,加入代码: enemya_i=0 enemya_max=10 enemya._visible=0 代码说明: Enemya_i 变量等于 0,enemya_max 变量等于 10,而敌机为不显示。 在图层 2 的第 2 帧加入代码: if(enemya_i<ENEMYA_MAX){< p> enemya.duplicateMovieClip("enemya"+enemya_i,enemya_i) this["enemya"+enemya_i]._x=random(650) this["enemya"+enemya_i]._y=enemya._y-random(200)+100 enemya_i++ }

—23—

Flash 小游戏开发基础 if(enemya_i>=enemya_max){ enemya_i=0 } 代码说明: 当 enemya_i 变量小于 enemya_max 时,Enemya 影片剪辑开始复制,复制品的 X 坐标等于 650 的随机数,复制品的 Y 坐标等于 敌机的 Y 坐标减去 200 的随机数再加上 100;Enemya_i 变量递增;当 enemya_i 变量大于等于 enemya_max 变量时,它的值为 0。 在第 10 帧加入代码 gotoAndPlay(2),这样就可以完成复制,让每 10 帧,就复制一个敌机。

3.一号敌机碰撞测试
右键点击敌机,选择“动作命令”,为对象加入如下代码: onClipEvent(enterFrame){ if(this.hitTest(_root.plane.plane_mc.plane_hit)){ this.enemy_a.enemya_mc.play() this.enemy_a.enemya_mc._x=this.enemy_a.enemya_mc._x this.enemy_a.enemya_mc._y=this.enemy_a.enemya_mc._y _root.plane.play() } if(this.hitTest(_root.missile)){ this.enemy_a.enemya_mc.play() this.enemy_a.enemya_mc._x=this.enemy_a.enemya_mc._x this.enemy_a.enemya_mc._y=this.enemy_a.enemya_mc._y } for (j = 1; j<50; j++) { if (this.hitTest(_root["shot"+j])) { this.enemy_a.enemya_mc.play() this.enemy_a.enemya_mc._x=this.enemy_a.enemya_mc._x this.enemy_a.enemya_mc._y=this.enemy_a.enemya_mc._y } } } 代码说明: 当敌机影片剪辑开始播放时执行;当敌机碰撞到主控飞机时,enemy_a 影片剪辑中的 enemya_mc 影片剪辑开始播放,也就是爆 炸动画。此时它将不再移动,主控飞机也将爆炸。当它碰撞到导弹时,它的爆炸动画开始播放,它的坐标也将不会再运动了。当 j=1,而且 j 小于 50 时,j 递增,这句实际上是每帧执行 50 次的一个代码,也就是子弹的碰撞测试,因为子弹是使用的复制品, 实例名称有 50 个,所以,以下代码有点变化,当它碰撞到“"shot"+j”这个数组时,也就表示它碰撞到 50 个子弹中任意的一个时, 它的爆炸动画开始播放。

4.二号敌机制作方法
二号敌机与一号敌机制作方法基本相同, 依照相同的方法, 我们制作一个 enemy_b 的影片剪辑, 绘制的敌机如图 15 所示。 照与一号敌机相同的制作步骤制作,区别仅仅是引导线,如图 16 所示。它将从左侧按弧线飞行到右上角。 帧加入代码 stop(),因为这个敌机在一开始的时候,并不会出现,等到分数值到了一定程度,才会出现。 回到场景中,我们在主控飞机的代码中,加入如下代码: if(score>=10000){ enemyb.play() } 依 二号敌机的碰撞代

码也与一号敌机相类似,可以参考一号敌机,也可以对照源程序。在场景中,二号敌机的实例名称为 enemyb。在二号敌机的第 1

—24—

Flash 小游戏开发基础 if(score>=20000){ gotoAndStop(2) } if(_root.planenum_mc._currentframe<2){ gotoAndStop(3) } 代码说明: 当分数大于等于 10000 时,二号敌机开始播放,当分数大于等于 100000,场景跳转到第 2 帧,当飞机数量的影片剪辑当前帧 小于 2 时,场景跳转到第 3 帧。

5.BOSS 敌机子弹制作
现在开始制作 BOSS 敌机了,先来制作一些准备工作,导入 f8f158.mp3 音乐文件。在“库”面板中,右键选取该音乐文件,选 择“链接”命令,在出现的对话框中选择“为动作脚本导出”选项,在输入框中输入 sound2,将这个音乐文件输出。 在主控飞机的代码中,第 1 行,加入如下代码: mysound=new Sound() mysound.attachSound("sound2") mysound.start(0,10000) 代码说明: Mysound 是新的音乐对象,这个音乐对象将绑定 sound2 音乐文件,而且它开始播放 10000 遍。 新建一个图层,名称为 foeshot。绘制一个椭圆形的渐变在场景中,这其实就是敌机的子弹。它的坐标是 X:0,Y:0。如图 17 所示。 双击进入影片剪辑,将坐标调整为 0,再次转换成影片剪辑,在第 125 帧建立关键帧,将其的坐标调整为 X:800,Y:0, 在第 1 帧建立动画,在最后 1 帧加入 removeMovieClip(this)代码,让它删除自己。 双击空白区域,回到上一级影片剪辑,为子弹效果起实例名称为 foeshot,新建一个图层,在第 1 帧加入如下代码,变量 foe_i 等于 0,foe_max 等于 10,而子弹的显示参数为 0。影片剪辑停止播放。 foe_i=0 foe_max=10 foeshot._visible=0 stop() 在第 2 帧加入如下代码: if(foe_i<FOE_MAX){< p> foeshot.duplicateMovieClip("foeshot"+foe_i,foe_i) this["foeshot"+foe_i]._x=_root.boss.boss_mc._x+_root.boss.boss_mc._width/2 this["foeshot"+foe_i]._y=_root.boss.boss_mc._y+_root.boss.boss_mc._height this["foeshot"+foe_i]._rotation=(180/Math.PI)*Math.atan2((_root.plane._y-this["foeshot"+foe_i]._y),(_root.plane._ x-this["foeshot"+foe_i]._x)) foe_i++ } if(foe_i>=foe_max){ foe_i=0 } 代码说明: 当 foe_i 小于 foe_max 时,子弹开始复制,这些复制品的 X 坐标等于 BOSS 飞机中的 BOSS 飞机影片剪辑的宽度除以 2,复制品 的 Y 坐标等于 BOSS 飞机的高度,而复制品旋转的角度,套用一个弧度换角度的几何公式,正好跟随着主控飞机的坐标,foe_i 递 增。当 foe_i 大于等于 foe_max 时,它等于 0。 给子弹的对象加入如下代码:

—25—

Flash 小游戏开发基础 onClipEvent(enterFrame){ if(this.hitTest(_root.plane.plane_mc.plane_hit)){ this.gotoAndStop(125) _root.plane.play() } if(this.hitTest(_root.missile)){ this.gotoAndStop(125) } } 代码说明: 当影片开始播放时执行,如果子弹碰撞到主控飞机,那么它将直接跳转到第 125 帧,如果它碰撞到导弹就删去自己。

6.BOSS 敌机碰撞测试
回到场景中,绘制一个敌机,如图 18 所示。转换成影片剪辑 BOSS,实例名相同,在影片剪辑中尽量把它缩放的大一些,然后 选取按 F8 转换成影片剪辑,命名为 boss_mc,实例名相同。 在 boss_mc 影片剪辑,制作 BOSS 主机的爆炸动画,可以同一号敌机的爆炸差不多,在第 1 帧加入 stop()代码,在第 2 帧加入 _root.foe.gotoAndStop(1)代码,双击回到上一级影片剪辑,制作一段动画,让它循环左右移动,在开始移动的这一帧加入 _root.foe.play()代码,让子弹程序开始播放。 回到场景中,在第 2 帧加入如下代码: _root.bosslife=5000 _root.boss.onEnterFrame=function(){ for(i=0;i<50;i++){ if(_root.boss.boss_mc.hitTest(_root["shot"+i])){ _root.bosslife-_root["shot"+i].removeMovieClip() } } if(bosslife<=0){ _root.boss.stop() _root.boss.boss_mc.boss_eft.play() } if(_root.boss.boss_mc.hitTest(_root.missile)){ _root.bosslife-} } 代码说明: Bosslife 变量等于 5000;当影片开始播放时执行代码;i 等于 0 时,i 小于 50 时,i 递增;当 BOSS 主机碰撞到主控飞机的子 弹时,Bosslife 开始递减,也就是 BOSS 主机的生命开始递减;而子弹将被删去;当 bosslife 的值小于等于 0 时,BOSS 影片剪辑 停止播放,也就不再移动,而 BOSS 主机的爆炸动画将开始播放。当 BOSS 主机碰撞到导弹时,它的生命也将递减。 在场景中第 3 帧加入 stop()、stopAllSounds()代码,停止所有音乐,使用文字输入工具输入 GAME OVER 字样,再制作一个按 钮,按钮内容为: On(press){ gotoAndPlay("Scene 1",1) } 让游戏回到开始界面。

—26—

Flash 小游戏开发基础 至此,该游戏基本制作完成, 虽然它看起来只像是一个雏形, 但却已经具备了一个小型游戏的全部功能。 通过这个游戏的制作, 你可能已经能够感受到,制作大型游戏,无非就是在这样的代码基础上,增加更多的内容和场景,以及人物,声音,动画,效果等。

Flash 游戏制作--迷宮
迷宫是一种很古老的智力游戏,记得小时候玩的迷宫游戏大都是印在报纸上的,然后拿跟笔在报纸上划来划去的找出口,一旦出口 被找到了,那么这个游戏的生命也就结束了,谁也不愿意重复玩一张迷宫地图,不过我们下面将要开始的 Flash 迷宫游戏就不同了, 每此玩之前都会动态的创建迷宫,保证可以玩到不同的迷宫。 (本例的源文件请点击这里下载) 所有 热点网络 热点下载 热点网络学院 版权所有= 此游戏的主界面如图 1 所示:

图1 游戏玩法: 从图 1 显示的游戏主界面中可以看到,此款游戏在外观上和传统的迷宫游戏非常相似,而且在玩法上也是一模一样,游戏中玩 家用键盘方向键控制左上角的绿色主角,在迷宫中寻找到达右下角红色出口的通路,只要成功的到达出口,游戏胜利,可以开始玩 下一局,每局和每局的迷宫地图都不相同,地图由游戏动态生成。 游戏制作思路: 如果想顺利的实现此游戏,首先需要考虑下面几点: 1.主角的控制:能够很好的对主角进行控制,是增强游戏可玩性的关键,所以考虑使用键盘方向键来控制主角的上下左右的移 动,使用 Flash Action 动作脚本提供的 OnClipevent 事件,可以轻易的使用键盘对游戏中的对象进行控制。 2.迷宫的生成:这个问题是实现此游戏最关键的部分,在本例我们使用功能强大的 Action 动作脚本中的 Array 数组对象来控制 迷宫的动态生成,可以保证每次游戏的地图完全不同,不过除了使用 AS 生成地图外,也可以使用比较传统的办法,那就是事先绘 制好一些迷宫地图,分配到不同的关键桢中,然后通过 Random 随机函数随机跳到某一桢,这样也达到了随机显示地图的目的。不 过这样做工作量比较大,而且缺乏一定的动态性,既然 Flash 为我们提供了强大的 AS,为什么不加以利用,提高工作效率呢,所以 本例我们使用 AS 控制`地图的随机生成。 3.在迷宫中判断碰壁和到达终点:如果主角在运动中碰到了迷宫的墙壁,则不能继续前进,需要改变运动方向,所以在游戏 中很好的对是否碰壁进行判断也是很重要的一方面。 不过这个问题实现起来也不难, 使用 Hittest 碰撞测试函数可以很好的解决这个 问题,而判断是否到达终点的解决办法也一样,只不过碰撞的对象是终点的红色小球。 制作步骤: 在初步规划了游戏设计思路,考虑了游戏中要解决的问题的解决方法后,就可以着手制作游戏了。

—27—

Flash 小游戏开发基础 1.制作游戏主角:游戏主角是我们要控制的对象,所以首先来制作主角,因为游戏中需要使用键盘对主角进行控制,所以主角 应该制作成 MC,这里新建一个 MC,命名为 man,进入 man 的编辑状态后,在第 1 桢使用矩形工具和直线工具绘制一个简单的圆脸, 如图 2 所示:

图 2 所有 热点网络 热点下载 热点网络学院 版权所有= 图 2 是主角在游戏中的状态,主角到达终点时候,会显示一张笑脸,所以在第 2 桢插入一个关键桢,使用矩形工具和铅笔工具 绘制一个简单的笑脸,如图 3 所示:

图3 2.制作迷宫出口:游戏中迷宫的出口是由一个小球标识的,只要主角到达小球所在位置,则可判断游戏胜利,游戏中需要判断 主角是否和小球发生碰撞,所以小球也需要制作成 MC,新建一个 MC,命名为 exit,进入 exit 的编辑状态后,只需绘制一个有填充色 的正圆即可,如图 4 所示:

图4 3.制作重玩按钮:游戏中当然少不了开始,重玩一类的控制按钮,这里只需要一个重玩按钮即可,游戏启动后会自动进入开 始状态。新建一个 Button,命名为 tryagain,进入 tryagain 的编辑状态后,可以按照自己的喜好绘制各种按钮,本例中重玩按钮的 Up 祯和 Down 桢如图 5 所示,Over 祯如图 6 所示:

图5

—28—

Flash 小游戏开发基础

图6 4.制作迷宫墙壁:游戏中迷宫是由 AS 控制生成的,不需要人为的干预,所以只需要制作墙壁的基本部分,由程序控制将其拼 接成完整的迷宫。这里可以制作两个 MC,分别为水平墙壁和垂直墙壁,使用矩形工具绘制成园角矩形即可,如图 7 所示:

图7 游戏的基本组件已经制作完了,非常的简单,剩下的工作就可以交给 Action 去处理了,在使用 Action 控制游戏之前,还需要 布置主场景。 布置主场景: 回到主场景中,设置影片舞台大小为 540px*400px,影片背景色为桔红色,然后将默认图层 layer1 重命名为 tryagain,在第 7 桢 插入一个关键祯,将组件 tryagain 放置到舞台靠右下的位置,还可以在按钮上添加一些提示信息,如”找到出口拉”,如图 8 所示:

图8 新建一个图层,重命名为 exit,在第 5 桢插入一个关键祯,然后从库中将出口小球 exit 拖到舞台上任意位置,并在属性面板中设 置其 Instance Name 为 exit,如图 9 所示:

—29—

Flash 小游戏开发基础 图9 再新建一个图层,重命名为 start&man,此图层放置游戏开始时构造迷宫地图的提示信息以及游戏的主角,在第 1 关键桢输入如图 10 所示的游戏开始提示信息:

图 10 然后在第 5 祯插入一个空白关键祯,将主角 man 拖到舞台的任意位置,并在属性面板中设置其 Instance Name 为 man,如图 11 所示,并将此图层延续到第 7 祯:

图 11 添加 Action: 主场景布置好后,最后的任务就是添加 Action 控制代码了,新建一个图层,重命名为 actions,在第 4 桢插入一个关键祯,并添 加如下 AS: MazeH = 12; MazeW = 12; //定义变量 MazeH 和 MazeW,分别代表迷宫地图的高度和宽度,高度以垂直墙壁为单位,//高度以水平墙壁为单位,分别为 12 个 TotalCells = MazeH*MazeW; //定义变量 TotalCells,其值为迷宫宽度和高度的乘积,代表了迷宫所能容纳的墙壁 //总数 Maze = new Array(); //定义一个数组 Maze for (i=0; i Room = new Array(); Cell = new Array(); //定义两个新数组 Room 和 Cell Cell.push(true, true, true, true); Cell.push(int(i/MazeW));

—30—

Flash 小游戏开发基础 Cell.push(i%MazeW); //使用数组对象的 Push 方法将参数值加到数组中,其中 i/MazeW 为 I 和 Mazew 相除且取//整数部分,I%MazeW 取两者相除的余数部 分 Room.push(Cell); Maze.push(Room); }//最后将数组 Cell 和 Room 分别加到数组 Room 和 Maze 中,作为数组中最后一个元素 while (true) { roomNum = random(Maze.length); cellNum = random(Maze[roomNum].length); wallNum = random(4);所有 热点网络 热点下载 热点网络学院 版权所有= //分别取三个随机数,roomNum 取数组 Maze 长度内的随机数,用来表示迷宫内的房间号,cellNum 取数组 Room 长度内的随机数, 因为 roomNum 是数组 Maze 的最大长度,所以数组 Maze 的第 roomNum 号元素就是其最后一个元素,也即数组 Room。最后一个 变量取 4 以内的随机数,代表房间内不同的四堵墙。 上面的几个数组 Maze,Room,Cell 之间其实有一个包含与被包含的关系,因为 Cell 被加入到 Room 中,而 Room 又被加入到了 Maze 中,所以 Maze 是最外层的数组,其包含了数组 Room 而数组 Room 又包含了 Cell,这样其实就建立了一个三维数组,Maze 代表了整个的迷宫,其元素 Room 代表了迷宫中的房间,而 room 中的元素 cell 则代表了房间里的墙壁,这样层层嵌套,有利于实 现下面的撞墙判断脚本。 if (Maze[roomNum][cellNum][wallNum] == false) { continue;//如果迷宫中的第 roomNum 个房间里的第 cellNum 堵墙的值为 faulse,则继续进行判断,直到值为 true } //判断 Maze 数组中编号为[roomNum][cellNum][wallNum]的元素值是否为假,如果为 //假,进行下一步循环 x = Maze[roomNum][cellNum][4]; y = Maze[roomNum][cellNum][5]; //分别设置 x,y 为第 roomNum 号房间的第 cellNum 堵墙的第 4 个和第 5 个元素 if (wallNum == 0 and x == mazeW-1) { continue; } else if (wallNum == 1 and y == mazeH-1) { continue; } else if (wallNum == 2 and x == 0) { continue; } else if (wallNum == 3 and y == 0) { continue; } //对变量进行判断,然后执行相应的操作 oppsCell = new Array(); //定义新数组 oppsCell if (wallNum == 0) { oppsCell = fun_findcell(x+1, y); } else if (wallNum == 1) { oppsCell = fun_findcell(x, y+1); } else if (wallNum == 2) { oppsCell = fun_findcell(x-1, y); } else if (wallNum == 3) { oppsCell = fun_findcell(x, y-1);

—31—

Flash 小游戏开发基础 } // 根据墙壁编号的不同,分别调用参数不同的函数,fun_findcell 为自定义函数 if (oppsCell[0] == roomNum) { continue; } if (wallNum == 0) { oppsWall = 2; } else if (wallNum == 1) { oppsWall = 3; } else if (wallNum == 2) { oppsWall = 0; } else if (wallNum == 3) { oppsWall = 1; } // 打开单元格中的一堵墙 Maze[roomNum][cellNum][wallNum] = false; Maze[oppsCell[0]][oppsCell[1]][oppsWall] = false; Maze[roomNum] = Maze[roomNum].concat(Maze[oppsCell[0]]); Maze.splice(oppsCell[0], 1); //用四个墙壁将空间封闭 if (Maze.length == 1) { break; } } function fun_findcell (a, b) { reCell = new Array(); for (i=0; i for (j=0; j if (Maze[i][j][4] == a && Maze[i][j][5] == b) { reCell.push(i, j); return reCell; } } } } //自定义函数 fun_findcell,用来寻找没有封闭的单元格 在第 5 祯添加如下 AS; Maze=Maze[0]; cellW=30; wn=0; //定义三个变量 for (i=0; i cellX = Maze[i][4]; cellY = Maze[i][5]; for (j=0; j 4; j++) { if (Maze[i][j] == true) {

—32—

Flash 小游戏开发基础 _root.attachMovie("w"+j, "ww"+wn, wn); eval("ww"+wn)._x = 105+cellW*cellX; eval("ww"+wn)._y = 35+cellW*cellY; wn++; } } } //控制游戏主角在迷宫中运动,并对路线进行判断 man._x=105; man._y=35; //设置游戏主角的坐标 man.gotoAndStop(1); //主角处于游戏进行状态 exit._x=105+11*cellW; exit._y=35+11*cellW; //设置迷宫出口坐标 manX = 0; manY = 0; 在第 6 祯和第 7 祯都添加 AS; stop();,用以停止游戏进行,以便让玩家选择,同时设置第 7 祯的祯标签为 playagain,接下来给重 玩按钮设置 AS; on (release) { for(i=0;i<WN;I++){ removeMovieClip("ww"+i); } gotoAndPlay (1); } //将游戏中复制出的迷宫墙壁全部清除掉,然后回到游戏开始重新构造迷宫地图 最后的时间轴如图 12 所式:所有

图 12 到此为止,迷宫游戏就制作完成了,可以看到,游戏中使用的对象非常少,主要功能全部由 AS 来实现,这也是用 Flash 制作 游戏和一般动画很大的不同。

—33—

Flash 小游戏开发基础

Flash 游戏制作规划与流程漫谈
对于大多数的 Flash 学习者来说,制作 Flash 游戏一直是一项很吸引人,也很有趣的技术,甚至许多闪客都以制作精彩的 Flash 游戏 作为主要的目标。不过往往由于急于求成,制作资料不足,数据获得不易,使许多朋友难以顺利进行 Flash 游戏设计。即使自己下 定决心,也是进展缓慢,乃至最终放弃。所有这一切都不是因为制作者的技术水平的问题,而是在于游戏制作前的前期设计与规划 没有做好造成的,所以这里我们主要来谈一下 Flash 游戏制作流程与规划这个方面,希望能对大家的游戏制作有一定的启发作用。 构思 不管大家学习 Flash 已有多才多长时间,现在大家心里想的都是同一件事,就是做出精彩的、能让玩家一玩就不想停下来的游 戏。但是要想让玩家可以在游戏中玩得尽兴,说起来简单,真正做起来并不轻松。因为要制作一个好的 Flash 游戏必须要考虑到许 多方面的因素。 在着手制作一个游戏前,你必须先要有一个大概的游戏规划或者方案,要做到心中有数,而不能边做边想。就算最后完成了, 这中间浪费的时间和精力也会让人不堪忍受。虽然制作游戏的最终目的是取悦游戏的玩家,通过他们的肯定来得到一定的成就感, 这也是激励游戏制作者继续不断创作的重要因素。 要想让游戏的制作过程轻轻松松,关键就在于不要让工作的内容太过繁琐或困难重重,要想使整个制作过程变的轻松,关键是 要先制定一个完善的工作流程,安排好工作进度和分工,这样做起来就会事半功倍,不过在制定任何工作计划之前,一定要在心里 有个明确的构思,以及对于游戏的整体设想。充满想象力的幻想,的确有助于你的创作,但是有系统的构思,要绝对优于漫无边际 的空想。 游戏的目的 制作一个游戏的目的有很多,有的纯粹是娱乐,有的则是想吸引更多的访问者来浏览自己的网站,还有很多时候是出于商业上 的目的,设计一个游戏来进行比赛,甚至把通过游戏的关卡当作是奖励的奖品。 所以在进行游戏的制作之前,必须先确定游戏的目的,这样才能够根据游戏的目的来设计符合需求的作品。 游戏的种类 凡是玩过 PC 游戏或者 TV 游戏的朋友一定非常清楚,游戏可以分成许多不同的种类,各个种类的游戏在制作过程中所需要的 技术也都截然不同,所以在一开始构思游戏的时候,决定游戏的种类是最重要的一个工作,在 Flash 可实现的游戏范围内,基本上 可以将游戏分成以下几种类型: 动作类游戏(Actions) 凡是在游戏的过程中必须依靠玩家的反应来控制游戏中角色的游戏都可以被称做”动作类游戏”。在目前的 flash 游戏中,这种 游戏是最常见的一种,也是最受大家欢迎的一种,至于游戏的操作方法,即可以使用鼠标,也可以使用键盘。此类游戏的典型代表 是著名的动作游戏”小小作品二号—过关斩将”和”碰碰拳打”,分别如图 1 和图 2 所示:

图1

—34—

Flash 小游戏开发基础

图2 益智类游戏(Puzzle) 此类游戏也是 Flash 比较擅长的游戏,相对于动作游戏的快节奏,益智类游戏的特点就是玩起来速度慢,比较幽雅,主要来培 养玩家在某方面的智力和反应能力,此类游戏的代表非常多,比如牌类游戏,拼图类游戏,棋类游戏等等,总而言之,那种玩起来 主要靠玩家动脑筋的游戏都可以被称为益智类游戏。图 3,图 4,图 5 分别为牌类游戏,拼图类游戏,棋类游戏的典型代表:

图3

—35—

Flash 小游戏开发基础

图4

图5 角色扮演类游戏(RPG) 所谓角色扮演类游戏就是由玩家扮演游戏中的主角,按照游戏中的剧情来进行游戏,游戏过程中会有一些解谜或者和敌人战斗 的情节,这类游戏在技术上不算难,但是因为游戏规模非常大,所以在制作上也会相当的复杂。图 6 为一个典型的角色扮演类游戏:

—36—

Flash 小游戏开发基础

图6 射击类游戏(Shotting) 射击类游戏在 Flash 游戏中占有绝对的数量优势,因为这类游戏的内部机制大家都比较了解,平时接触的也较多,所以做起来 可能稍微容易一点,图 7 为一个典型的射击类游戏:

游戏的规划与制作流程 在决定好将要制作的游戏的目标与类型后,接下来是不是可以立即开始制作游戏了呢?这里的回答是不可以!当然如果你一 定要坚持立即开是制作,也不是不可以,只不过要事先提醒大家的是:如果你在制作游戏前还没有一个完整的规划,或者没有一个 严谨的制作流程,那么必定将浪费你非常多的时间和精力,很有可能游戏还没制作完成,你就已经感到筋疲力尽了。所以制作前认 真制定一个制作游戏流程和规划是十分必要的。

—37—

Flash 小游戏开发基础 其实像 Flash 游戏这样的制作规划或者流程并没有你想象中的那么难,大致上只需要设想好游戏中会发生的所有情况,如果是 RPG 游戏需要设计好游戏中的所有可能情节,并针对这些情况安排好对应的处理方法,那么制作游戏就变成了一件很有系统的工 作了。例如下面的流程图:







上图表现了游戏”掷摋子”的流程图,只要对计算机有一定了解的朋友,对上面的流程图一定不会感到很陌生的,如果是对程序 设计有研究的朋友,对它就再也熟悉不过了,即使是在此之前没有接触过流程图的朋友,只要稍微用心看一下,也不难理解其中包 含的意思。 由上面的流程图就可以清楚的了解需要制作的内容已及可能发生的情况。在游戏中,一开始玩家要确定所押的金额,接着会随 机出现玩家和电脑各自的点数,然后游戏对点数进行判断,最后就可以判断出谁胜谁负了。如果玩家胜利了,就会增加金额,相反 则要扣除金额,接着显示目前玩家的金额,再询问玩家是否结束游戏,如果不结束,则再选择要押的金额,进行下一轮游戏。 所以,如果有了比较完整的流程图,肯定会使游戏的制作工作更加清晰和顺利 素材的收集和准备

—38—

Flash 小游戏开发基础 游戏流程图设计出来后,就需要着手收集和准备游戏中要用到的各种素材了,包括图片,声音等,俗话说,巧妇难为无米之炊, 所以要完成一个比较成功的 flash 游戏,必须拥有足够丰富的游戏内容和漂亮的游戏画面,所以在进行下一步具体的制作工作前, 需要好好准备游戏素材。 图形图象的准备 这里的图形一方面指 flash 中应用很广的矢量图,另一方面也指一些外部的位图文件,两者可以进行互补,这是游戏中最基本 的素材。虽然 flash 提供了丰富的绘图和造型的工具,如贝塞耳曲线工具,可以在 flash 中完成绝大多数的图形绘制工作,但是 flash 中只能绘制矢量图形,如果需要用到一些位图或者用 flash 很难绘制的图形时,就需要使用外部的素材了。 取得这些素材一般有下面几种方法: 1.自己动手制作:可以使用一些专业的图形设计软件来制作自己需要的素材,比如 Photoshop,Painter,Coreldraw 等都是很不错 的选择,另外可能需要一些 3D 的造型,这时候象 3D Studio Max,Poser,Moho 和 Bryce 等都是很方便的工具,完全可以利用这些工 具为 flash 服务。

图8 2.多媒体光盘:现在的多媒体光盘种类越来越丰富,盘上的各类资源也愈来愈多,完全可以利用手上现有的各类光盘来寻找 自己需要的素材,而且现在也有好多专门的素材光盘,素材数量非常丰富,完全可以满足我们的制作需要。

图9 3.网络资源:在互联系网空前发展的今天,我们可以充分利用网络上大量的免费资源来寻找我们需要的素材,现在网上有非常 丰富的各类素材,包括图形,图象和声音等,我们完全可以足不出户就得到我们需要的素材。

—39—

Flash 小游戏开发基础 音乐及音效 音乐在 flash 游戏中是非常重要的一种元素,大家都希望自己的游戏能够有声有色,绚丽多彩,给游戏加入适当的音效,可以 为整个游戏增色不少,前面的图形图象我们已经知道如何去获取了,那么如何找到我们需要的音效呢,下面就是一些常用的经验和 技巧: 1.网上搜集 网上有很多精彩的音效提供下载,但是这种方法的搜索面积过大大,不好找重点,而且还要受网落速度的限制。不过这里可以 给大家一个小建议:最好找那么可以打包下载音效的网站,全部下载回来,然后自己整理和建立自己的本地音效库,这样在以后的 制作中就可以很便捷的找到自己需要的音效。 2.音乐歌曲 就是从平常听的音乐里找音效,如果要找快节奏的鼓点最好多搜集一些 Disco 的舞曲,风格最好是 Techno,house。这些风格的 鼓点很强烈,慢一点的可以选择 Hip-Hop 的说唱音乐。好多韩国音乐和港台音乐的电子音效都很不错。不能忽视的是一些动漫片的 音乐,也有很多值得提取的部分。 3.故事片影碟。 这是最佳的音效来源,如今杜比音效已经很普及了,更为流行的是 AC-3 解码的 DVD 音效,可以使用一些流行的播放软件例 如超级解霸来提取影片中的音效。 4.游戏 这是我发现的一个最为捷径的音效来源,一般游戏安装后都会有专门的目录存放游戏中的音乐,比如游戏“生化危机”完全安装 后,会有一个 Sound 文件夹,打开看看吧,里面存放了几百种不同的音效,而且都是循环音效,是不是很方便啊。

飞机游戏的制作
飞机游戏是最简单的 Flash 游戏类型。飞机虽小,五脏俱全,它涵盖了 Flash 游戏制作的方方面面——判定、enterframe 控制 MC 行 为、按键检测、加载删除 MC、关卡设计等等。 下面我就来引导大家制作一款飞机游戏把! 本教程基于 FlashMX 2004 英文版 若您是一位初学者,对 Flash 的基本概念还不太清楚,请看 对 Flash 游戏初学者说的话 ,它将引导你学习 Flash。

1 编辑一个 mc
Flash 游戏中大部分物体都是 mc( MovieClip 电影剪辑)。譬如,主角、主角的子弹、敌人一般都是 mc。我们对 mc 有很多控制权, 譬如移动他、控制他播放、设置事件等等。 下面我们将制作一个 mc。 首先,绘制一个矩形,用 F8 将他变成一个 mc,名称叫 MC-主角 ,注册点选择中心。

点击确定之后,矩形就变成了一个 mc,同时库(F11)中出现了一个新的项 MC-主角。

—40—

Flash 小游戏开发基础 注册点是 mc 的重要属性,它是 mc 的中心,mc 的很多操作都是相对于注册点的。 重要区别:使用变形工具(Q)编辑的是动画的注册点,而非 mc 自己注册点。mc 注册点必须编辑 mc 本体才行。 双击场景上的那个 mc,或者双击库中 MC-主角 那一项, 都可以编辑 MC-主角。编辑的时候会看到一个 * 号,这就是 MC 的注册 点了。你不能挪动注册点,只能挪动 MC 内部的图形。

为了精确确定注册点的位置,有下面一些工具可以帮助大家定位: View -> Grid ( 视图-> 网格) View -> Snapping ( 视图->自动吸附 ) 对齐工具 ( Ctrl + K ) 场景上所有的 mc 都是库 mc 的实例。所以,一旦库 mc 改变,所有对应的实例都会改变;而每个实例有自己的属性,譬如实例名称、 位置、旋转等。下面我将说明这一点。 若正在编辑场景上的 mc,双击画面空白处,即可退回到主场景下。也可以在下图所示的编辑路径中跳回上级的层次。下图表明, 目前正在编辑 Scene1 中的 MC-主角。

做做看看: 从库中再拖一个 MC-主角到场景上,这样,场景上就有了两个方块 mc。你可以用变形工具(Q)在外部编辑任意一个方块;但是若是 你双击到 mc 内部,编辑这个 mc 本身,那么这两个 mc 以及库中 mc 都会改变。 在主场景下,选中一个 MC-主角 的实例,打开属性面板(Ctrl + F3) 设置实例名( InstanceName) 为 主角。

—41—

Flash 小游戏开发基础

下面我们用 enterframe

控制主角的移动。

在主事件轴上加一个图层叫 as。选中这个图层,打开 as 面板( F9 )输入如下 as: //主角的 enterframe 函数 主角.onEnterFrame = function (){ _x += 5; //每帧 x 增加 5 _y += 3; //y 增加 3 }

注意大小写和下划线。执行看看,主角自动向右下移动了。注意,主场景的注册点是左上角,坐标为(0,0);y 轴正方向向下,x 轴 正方向向右。 所以,_y 增大主角会往下移动。 每个 mc 都可以有自己的 enterframe 函数。系统每帧都会依次调用所有 mc 的 enterframe,然后才刷新画面。 enterframe 是控制游戏的基本手段之一,本教程就是使用它来控制整个游戏的。

为了更直观的理解坐标,我们把当前主角的坐标输出出来。 在主角的 enterframe 代码中加上一句 trace( this._x + " " + this._y ) this 表示函数的主人,也就是主角拉。 这样 as 层的代码就变成这样: //主角的 enterframe 函数 主角.onEnterFrame = function (){ _x += 5; //每帧 x 增加 5 _y += 3; //y 增加 3 trace( this._x + "," + this._y ); } 执行看看,会跳出一个小窗口,不停的报出主角的当前坐标。 trace 是 Flash 最常用的调试工具。 点击主场景空白处,打开属性窗口(Ctrl + F3)即可编辑主场景的属性。我们可以编辑场景的大小、fps(Frame per Second 秒间 帧数)以及背景颜色。 双击这个位置也会跳出如图的面板:

—42—

Flash 小游戏开发基础

fps 表示一个 swf 播放时一秒钟绘制多少帧画面。上图为 Flash 默认设置,12 fps,即一秒钟播放 12 帧。 每帧,mc 自己的时间轴会前进一格,同时系统会让所有设置了 enterframe 的 mc 调用自己的 enterframe 函数。 所以 fps 越高,动作越是连贯流畅。譬如上面的例子中,角色每帧水平移动 5 像素,一秒移动 12 x 5 = 60 像素。若是提高到 30 fps 而速度不变,把代码改为每帧 2 像素,画面就更为流畅了。 当然,若是只加大 fps 而代码不变,就只是快进效果。 Flash 游戏一般采用 30 fps;PC 上的商业游戏则要求 60 fps。当游戏由于运算量过大跑不动的时候,流畅的底线要求是 24 fps。

用 Flash 制作互动的小人
实现其实是很简单的,下面我们一步一步来制作这个实例效果。 1、打开 Flash,新建一个场景,按“Ctrl + F8”新建一个 Clip,命名为“Symbol 5”,类型为“Button”,用椭圆工 具在此 Clip 的场景中绘制一个圆,并用填充工具填充一个渐变颜色,如图所示。

2、按“Ctrl + F8”新建一个 Clip,命名为“Symbol 1”,类型为“Movie Clip”,将上一步所制作的“Symbol 5”拖到此 Clip 的场景中,并在“Symbol 5”Clip 的 Action 面板上面增加如下语句:

on (press) { this.startDrag(); } //当鼠标点击的时候,拖动 Clip

—43—

Flash 小游戏开发基础

on (release, releaseOutside) { //当放开鼠标的时候,停止拖动 Clip this.stopDrag(); }
3、按“Ctrl + F8”新建一个 Clip,命名为“Symbol 4”,类型为“Movie Clip”,用直线工具在此 Clip 的场景中 绘制一小段直线。 4、按“Ctrl + F8”新建一个 Clip,命名为“Symbol 1 copy”,类型为“Movie Clip”,将第一步中制作的“Symbol 5”拖到此 Clip 的场景中,并在“Symbol 5”Clip 的 Action 面板上面增加如下语句:

on (press) { this.startDrag(); drag = 1; } on (release, releaseOutside) { this.stopDrag(); drag = 0; }
5、在“Symbol 1 copy”Clip 中,用鼠标右键单击时间轴上面的图层,选取插入一个新的图层,将第三步所制 作的“Symbol 4”拖到新插入图层的场景里面,选取场景中的“Symbol 4”,在属性面板上面设置实例名为“link”。 6、在“Symbol 1 copy”Clip 中,用鼠标右键单击时间轴上面的图层,再选取插入一个新的图层,在此图层的 第一帧的 Action 面板上面插入如下语句:

nx = parent._x+sx; //取得场景中表示头的那个小球的位置。 ny = parent._y+sy; if (i<1) { i = Math.ceil(Math.random()*179); //取得一个随机的整数。 } if (i>180) {

—44—

Flash 小游戏开发基础

i = 1; //大于 180,则重新置为 1 } else { i++; } x = ((_root.inertion-1)*_x+nx)/_root.inertion+_root.s[i]*_root.force; //计算取得小球所要改变位置的值 y = ((_root.inertion-1)*_y+ny)/_root.inertion; dx = x-_x; dy = y-_y; if (drag>0) { parent._x = parent._x-dx/_root.elast; //改变球的位置 parent._y = parent._y-dy/_root.elast; if (parent.parent) { //改变代表头部的小球的位置 parent.parent._x = parent.parent._x-dx/_root.elast/_root.elast/_root.elast; parent.parent._y = parent.parent._y-dy/_root.elast/_root.elast/_root.elast; } } else { _x = x; _y = y; } dx = parent._x-_x; //重新取得值,在下一帧中使用 dy = _y-parent._y; link._xscale = dx*10; //改变球之间的直线的长度

—45—

Flash 小游戏开发基础

link._yscale = dy*10;
在新插入图层的第二帧上面单击鼠标右键,选取插入空白关键帧,此时图层之间的位置应该如图所示,在第 二帧的 Action 面板上面插入一段 ActioScript 代码,这段代码跟跟上一帧是一样的,需要两帧是因为要不断播放, 不断的改变球之间的位置。

7、回到影片的主场景中,用“Ctrl + L”打开图库,从图库中拖一个“Symbol 1”Clip 的实例到场景中,并在其的属 性面板上面设置实例名为“sparent”。从图库中拖五个“Symbol 1 copy”Clip 的实例到场景中,并分别在它们的属性 面板上面设置实例名为“i1”、“i21”、“i22”、“i3”、“i2”,此时场景中应该如图所示。

8、选取主场景中时间轴上面的第一帧,在其 Action 面板上面增加如下语句:

elast = 1.5; //分别初始化几个值 inertion = 10; force = 1; i1.parent = sparent; i1.sx = 30; i1.sy = 80; i2.parent = sparent; i2.sx = 0;

—46—

Flash 小游戏开发基础

i2.sy = 70; i3.parent = sparent; i3.sx = -30; i3.sy = 80; i21.parent = i2; i21.sx = 20; i21.sy = 60; i22.parent = i2; i22.sx = -20; i22.sy = 60; s = new Array(); //初始化两个数组 c = new Array(); for (i=0; i<180; i++) { s[i] = Math.sin(i*Math.PI/90); //将数学中的 Sin 值保存到数组中 } for (i=0; i<180; i++) { c[i] = Math.cos(i*Math.PI/90); //将数学中的 Cos 值保存到数组中 }
至此,实例就制作完成了,按“Ctrl + Enter”就可以看到实例的效果。

常见的飞机发射子弹的控制
只随便画了方块表示飞机,小矩形条表示子弹 space(空格键)发射子弹. 主要代码:
—47—

Flash 小游戏开发基础

var i = 0;//初始变量 fly.time = getTimer();//获取时间 fly.onEnterFrame = function() { if (Key.isDown(Key.SPACE) and getTimer()-this.time>200) { //按下空格或者两次按键的时间差>200 this.time = getTimer(); bullet(); } }; function bullet() { B = this.attachMovie("bullet", "bullet"+i, i++);//调库中的子弹 B._x = fly._x; B._y = fly._y+20;//设置子弹的初始位置 B.onEnterFrame = function() { this._y -= 10;//子弹逐桢移动距离 10 if (this._y<0) { this.removeMovieClip();//如果子弹超出屏幕,就删除 } }; }

一个完全使用 AS2 编制的飞机游戏之制作详解
作者自己的水平应该是很高的了,但从游戏的模式上而言,这个游戏并没有太多的创新,仍旧是无限循制, 不过想法上已经相当完整了,有这样一个很好的开发习惯,想做大的东东,就不会无从下手了。 作者写此文章的主要目的是在于介绍给大家如何真正用面向对象的 AS2 来写游戏, 所以,从这个角度而言,这篇文章还是相当优秀的,尤其是在国内这方面资料比较馈乏的时候, 这种文章可谓雪中送碳的佳举,我翻译一下,一方面是自己有提高,另一个方面,也算是给闪吧增点辉,给广大 的 FLASHER 做点贡献吧~~~~ (第一次翻国外的东东,所以有什么不地道的地方,敬请高手斧正,英文原文附在第三帖中了. 对了,要是作者本人给你发邮件说想找 EmilMatthew 收中文版的版权费时,你们就说不认识我啊,呵呵~~~:) ) 这篇文档是我第一个用 OOP(面向对象的编程)方法写的 AS2 游戏。 这个一个标准的空间打击敌人的游戏,有三架敌机和一架游戏者的喷火镭射机。 起初只会有一关,但是设计上可以使得增加关数的可能性变得非常方便。 游戏中会有基本的分数以及生命值。 和别的正在挣扎着实行在 FLASH MX2004 中的新的 ACTIONSCRIPT2.0 语法的人一样, 这篇文档也是为了我个人学习的好处。 我会遵照一个合理的传统的 OOP 设计的结构。 非常感谢并尊重来自 http://www.1coinplay.com 的 Squize 让我使用他的小精灵纸(?)来做为这个例子。 1 要求文档。 2 使用事件。 3 类的表格。 4 交互的表格。
—48—

Flash 小游戏开发基础

5 试验最初的代码。 6 迭代(Iteration) 7 测试。 8 发布。 ************************************************************************************* 要求: Spaceship: 上下左右移动。 通过空格键来发射镭射。 Enemy: 在一个随机的高度从右移到左。 有三个实例。 当它从左移出屏幕时,重新回到右侧。 BackGround: 从左移到右。 前景要比背景移动的快(视差(PARALLAX)) Laser: 当空格键按下时火焰从飞船中喷出。 Game: 如果射到敌人,游戏者得到分数。 如果飞船撞到敌机,则会损失生命值。 如果游戏者得到了胜利的分数,那个他(她)就赢了,游戏重新开始。 如果损失生命数超过三,游戏结束,游戏者失败。 2 使用的事件: 使用的事件是用图表来代表(设计的)要求。它们展示了在游戏中会发生的不同的事件,或者是所有会发生的不 同的动作。 这就是你所有所要做的。仅仅是把它们在一张纸上完整的实现(NUT ?), 这张表格能很好的给最终将使用的类及方法一个好的提示。 当你做完这些以后,该是你搞定你会要使用什么类以及这些类需要什么什么属性及方法. 类的表格: 类的表格展示了类之间的关系。 在我们下面的这张表格里:飞船,敌人,镭射及背景类都包含在进了游戏类. 这意味着那些类的实体被在游戏类中声明了。 这被叫做取合或者是“有一层”关系而区别于被描述为“是一种”关系的继承。? 游戏类被取聚合进了我的 Flash 文件里。 类的描述: 宇宙飞船类 属性或方法 类型 描述 speed Number x 变量的增量 moveShip() method 用按键来移动飞船 setShipX(x) setter _x 变量获取值的方法 getShipX() getter 返回_x 值 setShipY(y) setter _y 变量获取值的方法 getShipY() getter 返回_y 值

—49—

Flash 小游戏开发基础

敌机类 属性或方法 类型 描述 enSpeed Number x 变量的增量 moveEn() method 随机的移动敌机 setEnX(x) setter _x 变量获取值的方法 getEnX() getter 返回_x 值 setEnY(y) setter _y 变量获取值的方法 getEnY() getter 返回_y 值 镭射子弹类 属性或方法 类型 描述 fire() method start 当空格键按下时移动 setLaserX(x) setter _x 变量获取值的方法 getLaserX() getter 返回_x 值 setLaserY(y) setter _y 变量获取值的方法 getLaserY() getter 返回_y 值 背景类 属性或方法 类型 描述 scroll() method 从右移到左 setBackX(x) setter _x 变量获取值的方法 getBackX() getter 返回_x 值 setBackY(y) setter _y 变量获取值的方法 getBackY() getter 返回_y 值 游戏类 属性或方法 类型 描述 score Number 游戏者的得分 lives Number 游戏者的生命数 checkCollisions() method 碰撞检测 CheckLives(lives) method 如果生命值为 0 就停止游戏。 checkScore() method 检测并展示分数 交互的表格 交互表格述了通过方法传递的信息来符合我们一开始所提出的要求。 我现在对这项计划是否有效没有任何概念,因为我不知道 Flash 是否能处理组合。 游戏类包含着其它类并且是游戏的管理者。 但是我并不清楚是否能在一个类中控制一个继承于 MovieClip 类的子类(的实例). 那好,这里就是这计划,让我们看一下它是否能起作用。 计划不是被放在混凝土里的。如果它们无效,你可以把它们扔掉,或者是修改,甚至从草稿重新开始。 最重要的事情是过程。 通过过程来明确问题并呈现给我们处理问题的方法。这就像给电影的情节串连图版. 你草拟出它,呈现出脚本的想法同时也瞄准了观众的需求。 一旦你把这个都搞定了,你就把它扔在了一边并用本能进行着导演。 你知道故事的背景因为你浏览了情节串连图版的过程。这里也是如此: 上面是我画的一个份交互的表格。 我甚至做了一些改变并意识到一些在类表格中里所遗漏的内容。 就像那个 moveship 方法需要一个方向(左,右,上,下)并且我能过一个变量 dir 来传递按了哪个键。 dir 可以是 string 类(“left”)或者是一个字母(1,2,3,4).这并不重要。

—50—

Flash 小游戏开发基础

测试优先: 我新建了一个新的 Flash 文件并创建了一个 spaceship_mc(mc),把它连接到库里的 ship_mc 并把“Spaceship”放 进连接(link)AS2 CLASS 选项中。 然后在交互面板中我写下了下面的代码:
//连接 spaceship_mc attachMovie("ship_mc", "myShip", getNextHighestDepth()); //声明变量 var enArray:Array; // 现在是空的 var bulletArray:Array; // 空的 var myGame = new Game(myShip , enArray , bulletArray); //游戏循环 _root.onEnterFrame = function(){ myGame.moveShip("right"); }

Then I wrote minimal code so that the classes would just compile 然后我写下最少量的代码以致能让它刚好编译
class Game{ //游戏类,控制整个游戏并包含其它类的实例。 // 声明变量 var ship:Spaceship; var enemyArray:Array; var laserArray:Array; (译者注:上面最好用 Private 加以标明,否则就没有封装的意义了) // 构造函数 function Game(_ship:Spaceship, _enArray:Array, _bullArray:Array){ ship = _ship; enemyArray = _enArray; laserArray = _bullArray; } (译者注:这个函数最好在头前加 Public 在尾部加:void,这样子就比较正规了。) }

然后在 Spaceship.as 文件里我这样写:
class Spaceship extends MovieClip{ }

然后编译,但是没有错误。 但是那里应该有些错误因为 moveShip 方法还没有出现?嗯??(译者注:我倒) 在调试中什么也没有出现。 相当讨厌的出错检查。。。噢,好吧。。。 现在我必须写 Game.moveShip 方法了。。。我会写下它并测试。。。 我写下了 moveShip 方法并意识到我必须再写一个可以检测哪个键被按下了并传回一个 Sring 类的 dir 变量的 chekcKey 方法用以检测按键。 // Game 类 // 检测按键的方法:

—51—

Flash 小游戏开发基础 function checkKey():String{ if(Key.isDown(Key.RIGHT)){ dir = "right"; } if(Key.isDown(Key.LEFT)){ dir = "left"; } if(Key.isDown(Key.UP)){ dir = "up"; } if(Key.isDown(Key.DOWN)){ dir = "down"; } return dir; } // moveship 方法 // 1. 检查按键 // 2. 分配变量 dir 就是在每按下键一次,把 dir 传给 spaceship.move 方法 function moveShip(dir:String){ ship.move(dir); }

编译后并得到了错误。。。 " 行 38: 没有'move'方法." 太棒了,开始得到错误了,(译者注,我再倒),那正是所期待着的要发生的事。 现在写下 ship.move 方法来清除错误。。。 那就是“测试优先”的想法(作者这样写:主要是这里做的是个小东东,而且主要目的 在于尝试 AS2 编程,至于诸位自己做项目的时候,用什么模式,还请自己拿捏准哟.) 把方法在一系列的测试中实施直到它们出了问题,然后编写方法直到它符合要求接着移向下一个方法。 我使得飞船移动,这里就是我如何做的。。。
class Game{ //声明变量 var ship:Spaceship; var enemyArray:Array; var laserArray:Array; var dir:String; // ==== 构造函数 ============== function Game(_ship:Spaceship, _enArray:Array, _bullArray:Array){ ship = _ship; enemyArray = _enArray; laserArray = _bullArray; } // ==== 检查按键的方法 ======= function checkKey():String{ if(Key.isDown(Key.RIGHT)){ dir = "right";

—52—

Flash 小游戏开发基础 } else if(Key.isDown(Key.LEFT)){ dir = "left"; } else if(Key.isDown(Key.UP)){ dir = "up"; } else if(Key.isDown(Key.DOWN)){ dir = "down"; } else dir="stop"; //下面这个起作用了 //trace(dir + " - in game.checkey"); return dir; }

// // // //

=== 移动飞船的方法 ===== 1.检查按键 2.分配给变量 dir 相应的方向 3 把变量 dir 的值传进 spaceship.move 方法中

function moveShip(dir:String){ ship.move(checkKey()); } } //game 类结束

在宇宙飞船类中:
class Spaceship extends MovieClip{ var dir:String; function move(_dir:String){ dir = _dir; if(dir=="left") _x -= 20; if(dir=="right")_x += 20; if(dir=="up") _y -= 20; if(dir=="down") _y += 20; if(dir=="stop"){ _x +=0; _y +=0; } } } //Spaceship 类结束

我在把变量 dir 传进 ship.move 方法时没有遇到任何麻烦,然后我尝试试着直接使用 checkKey 方法,因为它总是 返回 dir,当然,这个起效了。 然后我不得不加一个 stop 在其中...无论何时当键按起的时候,飞船的运动有一些可笑,这样的状态一直持继着, 直到我在后来能把运动变得平缓为止... 但是我知道我的设计起效了。 我仅仅要作是只是把宇宙飞船(SPACESHIP)的实例传给游戏类的构造函数中。 然后,哈哈,presto(类例于芝麻开门之类的话)...接下来是什么呢?嗯,或许是发射镭射子弹吧。。。好的, 让我们走。

—53—

Flash 小游戏开发基础

发射雷射子弹 这个花了我两天的时间,我几乎不能相信。我持续着错误的子弹发射。。。这里是我发射镭射子弹方法的第一次 尝试。 // 在 game 类中: // ====== 发射镭射子弹 ========
function fireLaser_old(){ if(Key.isDown(Key.SPACE)){ // set start pt of laser laserArray[bulletNum]._y = ship.getY(); laserArray[bulletNum]._x = ship.getX(); // if space bar pressed set flag hasFired = true; bulletNum++; if(bulletNum >=5){ bulletNum = 0; } } }

上面的代码已相当接近我最后结束时的状态,最实际的问题是在于 movelaser 方法。 噢哈哈,我把镭射子弹发射放在了我的 FLA 中的 EnterFrame 循环中了...大大的错误... 这必须放在 FLA 文件的 onKeyDown 事件中。这就是目前为止的状况
://在 fla 文件的 actions 面板中 attachMovie("ship_mc", "myShip", getNextHighestDepth()); var enArray = new Array(3); var bulletArray = new Array(5); //连接 bullet 数组 for(var i =0;i < 5;i++){ attachMovie("laser_mc", "laser"+i, 100 + i); bulletArray[i] = _root["laser"+i]; } // 声明并初始化游戏类的实体 // 把飞船, 敌机数组和子弹数组传进去 var myGame = new Game(myShip , enArray , bulletArray); // ======= 获取键值============ // someListener = new Object(); someListener.onKeyDown = function () { myGame.fireLaser(); }; Key.addListener(someListener); // 游戏循环 _root.onEnterFrame = function(){ myGame.checkKey(); myGame.moveShip(dir); myGame.moveLaser(); }

—54—

Flash 小游戏开发基础

这样好了一些,但是仍旧没有得到正确的子弹发射。。。它要比空格键延迟两个键后才发射。 嗯,好吧,这是我这次使用的 moveLaser 方法:
// ========= move laser ==========// function moveLaser_old(){ if(hasFired==true){ laserArray[bulletNum]._x += 30; } if(laserArray[bulletNum]._x > Stage.width) { laserArray[bulletNum]._x = -10; hasFired = false; } } // ============== //

下面是最终(也就是现在)使用的镭射子弹发射方法。 它的运作很简单,得到飞机的位置并传递给子弹。 然后子弹数目开始增加,当数字大于 5 的时候,它被重新初始化到 0。
// ========= FIRE LASER ====== // function fireLaser(){ if(Key.isDown(Key.SPACE)){ // set start point laserArray[bulletNum]._y = ship.getY(); laserArray[bulletNum]._x = ship.getX(); // increment the bullet number ++bulletNum; // if more than 5 bullets , start again at 0 if (bulletNum>5) { bulletNum = 0; } } }

下面是最终移动子弹的方法,同样是非常的单简。 这个过程遍历所有的子弹,如果有子弹可以提供,就移动它。它仍旧不是很完美,但现在还能凑和着用。
// ======= MOVE LASER ======= // function moveLaser(){ var bulleti = 0; while (bulleti<6) { laserArray[bulleti]._x += 30; bulleti++; } } // ============= //

下面是到目前为止所创建的游戏类:
class Game{ // ========= 声明变量 var ship:Spaceship; var enemyArray:Array;

—55—

Flash 小游戏开发基础 var laserArray:Array; var dir:String; var bulletNum:Number = 0; // ==== 构造函数============== function Game(_ship:Spaceship, _enArray:Array, _bullArray:Array){ ship = _ship; enemyArray = _enArray; laserArray = _bullArray; } // ==== 检测键被按下的方法 ======= function checkKey():String{ if(Key.isDown(Key.RIGHT)){ dir = "right"; } else if(Key.isDown(Key.LEFT)){ dir = "left"; } else if(Key.isDown(Key.UP)){ dir = "up"; } else if(Key.isDown(Key.DOWN)){ dir = "down"; } else dir="stop"; return dir; }

// // // //

=== 移动飞船的方法 ===== 1.检查按键 2.分配给变量 dir 相应的方向 3 把变量 dir 的值传进 spaceship.move 方法中

function moveShip(dir:String){ ship.move(checkKey()); } // ========= 发射子弹 ====== // function fireLaser(){ if(Key.isDown(Key.SPACE)){ // 设置起始位置 laserArray[bulletNum]._y = ship.getY(); laserArray[bulletNum]._x = ship.getX(); // 增加子弹数目 ++bulletNum; // 如果大于 5,重新将数目开始于 0 if (bulletNum>5) { bulletNum = 0; }

—56—

Flash 小游戏开发基础 } } // ======= 移动子弹 ======= // function moveLaser(){ var bulleti = 0; while (bulleti<6) { laserArray[bulleti]._x += 30; bulleti++; } } // ============= // } // ------ 游戏类结束 ------- //

下面是 Spaceship 类和它所使用的 getX 和 getY 方法:
class Spaceship extends MovieClip{ var dir:String; // ===== 移动 ========= function move(_dir:String){ dir = _dir; if(dir=="left") _x -= 20; if(dir=="right")_x += 20; if(dir=="up") _y -= 20; if(dir=="down") _y += 20; if(dir=="stop"){ _x +=0; _y +=0; } } // ====== 得到 X 值 ==== function getX():Number{ return _x; } // ======= 得到 Y 值 ===== function getY():Number{ return _y; } } // ====Spaceship 类结束

这里是 Laser 类:
class Laser extends MovieClip{ // ======= 构造函数 ========= // function Laser(x:Number, y:Number){ _x = x; _y = y; } }

—57—

Flash 小游戏开发基础

在 FLASH MX2004 中做好你的敌人 MC, 然后在链接对话框中, 在标识文本框内写下“baddie”,在 AS2 类文本框中 写下“Enemy”。 现在在你的 FLA 的交互面板中写下下面的脚本,把敌人 MC 连接到场景中,并把它们放进 enemyArray 数组中: (译者注:看来,AS2 的 ARRAY 还是和 AS1 一样(还有 JAVASCRIPT),什么东东都能放啊,这里用的相当的妙。)
// ------ 连接到 ENEMY 数组 --------- // for(var j=0;j<3;j++){ attachMovie("baddie", "baddie"+j, 200+j); enArray[j] = _root["baddie"+j]; enArray[j]._x = 50*j; enArray[j]._y = 100; }

这就是到目前为止在我们的 Enemy 类中写的东西:
class Enemy extends MovieClip{ // 把实现的代码写在这里 } // ------- enemy 类结束

移动 Enemy 类 没有,所以我们需要些什么呢 ? 来些变量如何. 让我们回到先前的类表中去看一下我们在文档里能设计些什么. 好的,我们需要速度,所以我把它放进去,并且我们需要一个移动的方法 噢,还有一些我在设计里忘记的东西,一个 reset()方法,使敌机从场景的左边移出时或者它们被刺击中时重新回 到场景的右边. 我们可以在构造函数里设定初始的速度,这就是我到目前为止所完成的内容:
class Enemy extends MovieClip{ // 声明属性 private var speed:Number; // ======= 构造函数 function Enemy(){ speed = 20; } // ===== 移动 function moveEnemy(){ if(_x<=-30){// 当移出场景左边时 reset(); } else{ _x -= speed; } } // ====== 重设 function reset() { _x = Stage.width+50; _y = Math.random()*380 + 10; speed = Math.random()* 10 + 10;

—58—

Flash 小游戏开发基础 } } // ----- enemy 类结束

通过编译测试它. 啊哈! 凑效了.敌机以在 X 方向上以 10-20 像素/帧的速度开始始动. 噢,然后我们会把我们的机子放进 game 类中,所以把下面的代码放进 Game 类中.
// 在 Game 类中 // 移动敌人 function moveBaddies(){ for(var i=0;i<3;i++){ enemyArray[i].moveEnemy(); } }

并且再度确认你有 movebaddies 方法在你的 flash 文件中的 Enterframe 循环中,这使得你的 ACTION 面板里的代 码十分的整齐和干净.
// 循环 _root.onEnterFrame = function(){ myGame.checkKey(); myGame.moveShip(dir); myGame.moveLaser(); myGame.moveBaddies(); }

碰撞检测 我不是很清楚我将要如何实现它,或许是在游戏类中。 并且要做一些循环...
//在 game 类中 // 碰撞检测 function collision(){ for(var j = 0; j<6;j++){ for(var k=0;k<3;k++){ if(laserArray[j].hitTest(enemyArray[k])){ trace("enemy hit, no. " + k ); } } } }

并把这里的方法放进我们的 FLA 文件中的 ENTERFRAME 事件中去 :
// 循环: _root.onEnterFrame = function(){ myGame.checkKey(); myGame.moveShip(dir); myGame.moveLaser(); myGame.moveBaddies(); myGame.collision(); }

—59—

Flash 小游戏开发基础

制造爆炸效果,当子弹击中敌机的时候,我们想看到爆炸(那是当然的)。 在你的 FLASH MX 2004 的文件里做一个爆炸的 MC。 我只是聚集了一些烟和雾的图像放在每一帧里,并在最后加一个空白帧,还有一个 stop()。 我把这个 MC 取名叫做“Splode_mc”并且在链接对话框中把它的链接名子叫做"Splode". 所以在磁碰撞的方法里,我应该连接上 splode 这个 MC,重设敌机,然后我们把分数给加上。
// 在 game 类中 // 碰撞检测 function collision(){ for(var j = 0; j<6;j++){ for(var k=0;k<3;k++){ if(laserArray[j].hitTest(enemyArray[k])){ // 爆炸效果 _root.attachMovie("splode", "splode", 301); // 使爆炸作用于敌机的位置 _root.splode._x = enemyArray[k]._x; _root.splode._y = enemyArray[k]._y; // 把敌机重设在场景的右边 enemyArray[k].reset(); break; } } } }

碰撞检测之敌机碰飞船. 现在让我们审视一下敌机我和我们的宇宙飞船之间的碰撞。 我重复利用了 sploe_mc,改变了它的颜色及 x,y 方向的拉伸值, 我们也能够把一个声音的效果加在每一次击中的判定中。 但是我还是把那件是交给你们吧
。// 碰撞检测 function collision(){ for(var j = 0; j<6;j++){ for(var k=0;k<3;k++){ //检查子弹击中敌机 if(laserArray[j].hitTest(enemyArray[k])){ // // 爆炸效果 _root.attachMovie("splode", "splode", 301); // 使爆炸作用于敌机的位置 _root.splode._x = enemyArray[k]._x; _root.splode._y = enemyArray[k]._y; // 把敌机重设在场景的右边 enemyArray[k].reset(); }// end if // 检查敌机击中飞船 if(enemyArray[k].hitTest(ship)){ _root.attachMovie("splode", "splode", 301);

—60—

Flash 小游戏开发基础 // 使得爆炸符合飞机的坐标 _root.splode._x = ship._x; _root.splode._y = ship._y; // 改变颜色 var my_color:Color = new Color(_root.splode); my_color.setRGB(0xff0000); // 改变大小 _root.splode._xscale = _root.splode._yscale = 400; } } } }

分数以及身命值: 剩下的是什么呢? 分数以生命值.我或许应该做一些文本框,在改变发生的时候去改变它们的 TEXT 属性。 所以在我们的 FLASH MX 2004 文件中制做两个文本框,把它们分别取名叫做 score_txt 和 lives_txt. 然后给游戏类增加两个变量,score 和 lives 并在在我们的构造函数中初始化它们。
// 在 Game 类中 //声明变量 var score:Number; var lives:Number; // ==== 构造函数 ============== function Game(_ship:Spaceship, _enArray:Array, _bullArray:Array){ ship = _ship; enemyArray = _enArray; laserArray = _bullArray; //初始化子弹及生命值 score = 0; lives = 10; }

现在让我们把 score 及 lives 变量设置给 textfields
// 在 Game 类中 // 碰撞检测 function collision(){ for(var j = 0; j<6;j++){ for(var k=0;k<3;k++){ //检查子弹击中敌机 if(laserArray[j].hitTest(enemyArray[k])){ // 增加分数值并呈现它 score += 10; _root.score_txt.text = " Score: " + score; // 爆炸效果 _root.attachMovie("splode", "splode", 301); // 使爆炸作用于敌机的位置 _root.splode._x = enemyArray[k]._x;

—61—

Flash 小游戏开发基础 _root.splode._y = enemyArray[k]._y; // 把敌机重设在场景的右边 enemyArray[k].reset(); }// end if // 检查敌机击中飞船 if(enemyArray[k].hitTest(ship)){ // 重设敌机,减小生命值 // 显示生命值 enemyArray[k].reset(); lives -= 1 ; _root.lives_txt.text = " Lives : " + lives; _root.attachMovie("splode", "splode", 301); // 使得爆炸符合飞机的坐标 _root.splode._x = ship._x; _root.splode._y = ship._y; // 改变颜色 var my_color:Color = new Color(_root.splode); my_color.setRGB(0xff0000); // 改变大小 _root.splode._xscale = _root.splode._yscale = 400; } } } }

在上面的代码中在敌机击中飞船的时候我不得不重设敌机,由于碰撞会持续几帧,所以生命数会持续的减少。 把 enemyArray[k].reset() 一行注释掉你会看到生命数持续的减少。 上面所做的是一个相当简单的过程: 1 碰撞检测。 2 变量值的增加或减少。 3 呈现变化的变量值. 这在技术方面对我们而言语是一个有些份量的跳跃,我想,我会把它放在那里一会儿让我们消化消化。 下一步我们将会做一个检查分数的方法用以来检查分数及生命数是否出界,如果是,就结束游戏。 但在呢,让我们体息。下面的注意事项和第一部分一样... 接下来要进入第三部分,在那里,我们将会整理出一个呈现分数的方法并制作一个水平方面移动的背景. 现在我们必须来检查我们的生命数并且当然相应的做出处理。 检查生命数: 在你的 FLA 文档中 创建两个新帧,并把第一帧的代码放进第二帧 f 去。 In your fla, make 2 new frames and put the code that was on frame 1 onto frame 2. 添加一个 stop();写在代码的开头部分,分别添加在第一帧和第三帧。 在第一帧中,加一个标题,一些说明及一个按纽。 在按纽上写下如下的代码:
on(release){ _root.gotoAndStop(2); }

—62—

Flash 小游戏开发基础

在第三帧中加一个动态的文本框来呈现游戏中的结果,并把实例名命名为"result_txt" 添加一个重新开始的按纽,并给按纽写上如下的代码,好让它返回第二帧。
on(release){ _root.gotoAndStop(2); }

重新回到我们的游戏类中的代码并添加这个方法用以检查剩下多少生命以及处理结果:
// 在 Game 类中 // ============检查生命值=============== // function checkLives() { if (lives<=0) { // 擦屏 // 重新移动 mc 对象 ship.removeMovieClip(); for(var i=0;i<enemyArray.length;i++){ enemyArray[i].removeMovieClip(); } // 设定文本框的文字量示位置 _root.result_txt.autoSize = "left"; // 展示分数(Good) _root.result_txt.text = "You have scored "+score+" . Congratulations."; // 跳转至结果的图像面. _root.gotoAndStop(3); } }

移动背景 我们此刻有两个选择。 我们可以只在我们的 FLASH 里做一个移动的背景动画或者是 做一个 Background 类并把移动的方式写在其中. 好吧,我决定做一个 Background 类并把移动的方式写在其中. 首先我做了 4 个 mc,大小上两倍于舞台的宽度,高度与舞台一致。 我的做成了 1400*400 大小,我准备在我的背景中使用视差. 最近的背景会比较远的被放置在后面的背移动的快. 我把这些 MC 命名分别为 sky,far,mid,和 fore. 这里就是 BackGround 类了。
class Background { // ----- 初始化背景 --- // function initBack() { _root.attachMovie("sky", "sky", 1); _root.attachMovie("far", "far", 2); _root.attachMovie("mid", "mid", 3); _root.attachMovie("fore", "fore", 4); } // ========== 移动背景 ==== // function moveBack(){

—63—

Flash 小游戏开发基础 // sky 移动 if(_root.sky._x <= -Stage.width){ _root.sky._x = 0; } _root.sky._x -= 2; // far 前景移动 if(_root.far._x <= -Stage.width){ _root.far._x = 0; } _root.far._x -= 4; // mid 移动 if(_root.mid._x <= -Stage.width){ _root.mid._x = 0; } _root.mid._x -= 6; // fore 移动 if(_root.fore._x <= -Stage.width){ _root.fore._x = 0; } _root.fore._x -= 8; } // // ===擦除背景 === // function cleanBack(){ _root.sky.removeMovieClip(); _root.far.removeMovieClip(); _root.mid.removeMovieClip(); _root.fore.removeMovieClip(); } }

注意到我有三个方法: initBack() - 在这里我把背景剪辑加载到了时间轴上 moveBack() -用不同的速度来移动背景对象 cleanBack() - 当生命数为 0 时,移除所有的背景对象。 在 Game 类中增加 back 变量,并改变构造函数把背景对象实体给传进去
.// 在 Game 中 // 声明变量 var back:Background; //...构造函数 function Game(_ship:Spaceship, _enArray:Array, _bullArray:Array,_back:Background) { ship = _ship; enemyArray = _enArray; laserArray = _bullArray; back = _back; score = 0;

—64—

Flash 小游戏开发基础 lives = 10; }

现在我们需要来初始化我们的背景。 在 game 类中,在 initGame 方法中,初始化背景:
// 在 Game 中 // --- 初始化 ----------- // function initGame(){ back.initBack(); }

然后移动它:
//在 Game 中 // == 移动背景 ===== // function moveBackground(){ back.moveBack(); } //在我们的 fla 中 // 游戏循时 _root.onEnterFrame = function(){ myGame.checkKey(); myGame.moveShip(dir); myGame.moveLaser(); myGame.moveBaddies(); myGame.collision(); myGame.checkLives(); myGame.moveBackground(); }

固定我们的分数并呈现. 现在所有都做的很好,但是我们看不现展示出的分数及生命脉数。 那是因为我们的文本框是在 root 层(level),而背景则是在 1-4 层,所以 root 层被覆盖了。 所以我们现在要做是增加一个动态检测,并把它们放在一个更高的层次上。 把这一等增加在游戏类中我们声明变量的地方: var myformat:TextFormat; 这将会使得我们在后面去风格化我们的文本框,并且在 initGame(初始化游戏)的方法中添加动态文本框:
// 在 Game 类中 // --- 初始化----------- // function initGame(){ back.initBack(); // 创建一个文本框并设置好格式 _root.createTextField("score_txt",501,20,10,100,50); myformat = new TextFormat(); myformat.color = 0xff0000; myformat.size =20; _root.score_txt.text = "Score : " + score; _root.score_txt.setTextFormat(myformat); //初始化显示生命值的文本框 _root.createTextField("lives_txt", 502, 600,10, 100, 30);

—65—

Flash 小游戏开发基础 _root.lives_txt.text = "Lives : " + lives; _root.lives_txt.setTextFormat(myformat); }

删除我们放在场景中的广西文本框并进行子弹和敌机以及敌机和主机间的碰撞检测。
// 在 Game 类中 // 碰撞检测 ... // 子弹击中敌机 score += 10; _root.score_txt.text = " Score: " + score; _root.score_txt.setTextFormat(myformat); // ... // 敌机击中宇宙飞船 lives -= 1; _root.lives_txt.text = " Lives : "+lives; _root.lives_txt.setTextFormat(myformat); // ...

擦除 当游戏结束的时候,我们仍旧需要把场景从游戏场景中移出。 所以我做了一个新的方法来做这项工作:
// 在 Background 类中 // ===擦除背景=== // function cleanBack(){ _root.sky.removeMovieClip(); _root.far.removeMovieClip(); _root.mid.removeMovieClip(); _root.fore.removeMovieClip(); }

现在把这一行 checkLives()方法添加进 Game 类中:
// 在 Game 类中 // 在 CheckLives 的方法里 if(lives<=0){ // ... back.cleanBack(); // ... }

还剩下要做: 这个游戏还远没有完成。 对于我来说这是编程的一次练习并且我忽略了很多游戏性方面的因素, 视觉上审还将美角度的效果以及别的一些 东西。 这就是能被添加的东西: 声间---子弹射击,碰撞。 更多的关数,更大和更坏的敌人(译著注:作者在这里"更坏"用的是 badder~~~~) 一张最高成绩表单 把按纽的代码写进游戏类中 难道没有一些别的什么东西吗?就凭你的想象了.

—66—


更多相关文档:

Flash游戏开发教材

Flash游戏开发教材_学科竞赛_高中教育_教育专区。flash开发校本教材牌头中学校本教材 Flash 小游戏开发基础 主编:李琦 牌头中学校本教材审定委员会牌头中学 . 选修课...

Flash游戏开发教程

Flash游戏开发教程_IT/计算机_专业资料。Flash游戏开发教程 Flash 游戏开发教程最近累,虽然有很多朋友都在等勇者 2,但我实在没心情开发。 闲着也是闲着,开一贴给...

FLASH小游戏开发教程:游戏制作前的准备

FLASH小游戏开发教程:游戏制作前的准备_IT/计算机_专业资料。Flash游戏制作的教程FLASH 游戏这东西吧,总入不了大流。国内拿 FLASH 做美术方面的应用比较多,而传统...

Flash游戏开发教程

Flash 游戏开发教程 Flash 游戏开发教程:第一节作者:周云(cloudy1982) 来源:闪吧 闲着也是闲着,开一贴给刚刚踏上 FLASH 游戏开发的爱好者们写点东西。 FLASH ...

基于flash小学课本游戏开发读书报告

Flash游戏开发(五) 56页 免费 Flash游戏开发(二) 58页 免费如要投诉违规内容,请到百度文库投诉中心;如要提出功能问题或意见建议,请点击此处进行反馈。 ...

Flash小游戏开发教室基础篇

就变成了没多少职业程序员来开发 FLASH 游戏, 学校也不会培养学生深入学 习开发 FLASH,搞这块的人少,人少交流讨论的也少,正正规规的教材也少,当然优秀作品 更...

Flash游戏开发教程

flash 游戏开发文档flash 游戏开发文档隐藏>> Flash 游戏开发教程:第一节 游戏开发教程:作者:周云(cloudy1982) 来源:闪吧 闲着也是闲着,开一贴给刚刚踏上 FLASH...

【Flash入门必备】Flash开发AS代码之游戏制作过程例子

Flash入门必备】Flash开发AS代码之游戏制作过程例子_IT/计算机_专业资料。【Flash...As3 游戏制作 郑重声明这不是什么教程, 说教对我来说还太遥远, 本人只是个...

Flash游戏开发教程:第1节

Flash 游戏开发教程:第一节 游戏开发教程: 闲着也是闲着,开一贴给刚刚踏上 FLASH 游戏开发的爱好者们写点东西。 FLASH 游戏这东西吧,总入不了大流。国内拿 ...

Flash游戏开发实例系列

Flash游戏开发(二) 58页 免费 Flash游戏开发(四) 57页 免费 Flash游戏开发教程3 21页 免费 Flash游戏开发教程:第3... 5页 免费 Flash游戏开发教程:第4......
更多相关标签:
flash游戏开发 | 实战flash游戏开发 | flash as3游戏开发 | flash 游戏开发教程 | flash游戏开发工具 | flash网页游戏开发 | flash游戏开发学习 | flash游戏开发书籍 |
网站地图

文档资料共享网 nexoncn.com copyright ©right 2010-2020。
文档资料共享网内容来自网络,如有侵犯请联系客服。email:zhit325@126.com