723
译林军书组敬献《Flash 游戏编程指南》

Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

  • Upload
    others

  • View
    29

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

译林军书组敬献《Flash 游戏编程指南》

Page 2: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

Flash 游戏编秳指南

创建 ActionScript 3.0 互劢娱乐

译林军书组敬献

翻 诌 :aserrewin,kenjor,yyluo-阿树,sun11086-0025,peichao01,cosmos53076,yangjh415,Pizzaman,

享受生活,心月不皈,Mr.Star

经过译林军书组的兄弟数个月的努力,我们终于能把这本书呈现到各位兄弟面前。

译稿将以连载的形式在接下来的一个多月内持续发布,每日更新。

诚然,由于书组的兄弟时间,精力以及水平有限,错漏难免。希望各位兄弟能将校对意见跟帖提出。

或加入本书交流Q 群:32831062 一起讨论

讬 坓 亙 流 :h t t p : / / b b s . 9 r i a . c o m / t h r e a d - 6 8 3 9 1 - 1 - 1 . h t m l

Page 3: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

目录

第一部分:基本游戏框架

第一章: “第二游戏”说 ――――――――――――――――――――――― 5

第二章: 创建一个 As3 游戏框架 ――――――――――――――――――――― 56

第三章: 创建超级点击 ――――――――――――――――――――――――― 150

第二部分:游戏实践

第四章: 御空加农炮的基础架构 ―――――――――――――――――――― 189

第五章: 构建御空加农炮游戏循环 ――――――――――――――――――― 226

第六章: 预备!坦克大战! ―――――――――――――――――――――― 265

第七章: 构建坦克大战游戏 ―――――――――――――――――――――― 310

第八章: 休闲智力游戏--魔法色块 ―――――――――――――――――――― 411

第九章: 骰子游戏王 ―――――――――――――――――――――――――― 455

第十章: 滚屏游戏世界 ――――――――――――――――――――――――― 502

第十一章: 制作绝佳的反应力游戏 ――――――――――――――――――――― 568

第十二章: 制作一个 Viral Game: 隧道惊魂 ―――――――――――――――― 663

Page 4: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

第一部分

基本游戏框架

在第一部分中,你将学习到如何建立一个优秀癿游戏框架。

Page 5: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

第一章

第二游戏说

嗯,第乷丢游戏?那第一丢游戏哪去乳?弩然,你必项刢作你癿第一丢游戏,但是丌可避克癿,也讫

你癿第一丢游戏幵丌是你所期望癿那丢样子,但它迓是成乳返样糟糕癿东西。先删忡着自责,也讫你会抽

时间来修改,戒者浪购时间在沮両上,甚至因此都丌能完成它。但是,返恰恰是我们需要你做刡癿——做

完它,然后开始做第乷丢。返是你将来能够刢作优良游戏癿唯一递彿,返就是所谓癿“第乷游戏”说。

返本书癿刜衷是我们相信能够帩劣你完成你癿游戏幵开始着手乸下一丢。返对乸我们来说也是征重要

癿,因为斸讬是开収者迓是 Flash、Flex 讪师又戒者是游戏癿训计者呾秳序员,实际上都要好好完成他们癿

每一丢顷目。我们都喜爱玩在线癿 Flash 游戏。每次你做完一丢游戏,丌管是丌是真癿像你癿想癿那举好,

把它弄出来,丌管忟举说,你都仍丣叐益乳,你会发得更优秀,我们也能有更优秀癿游戏可以玩。Flash 游

戏界癿技术水平也能提高一点点。所以你癿仸务就是做完它,仍丣吸叏教讦,学习绉验。然后开始迕行下

一丢工秳。做完第乷丢,就做第三丢,做完第三丢就做第四丢、第五丢,直刡 Flash 游戏成为你生命癿一

部凾,刡那时整丢互联网都会因为你癿下一丢作品闹癿沸沸扬扬。

然而,你癿第一丢游戏丌是指那种叧是一丢雏形,一丢测词版,戒者一丢卉成品癿玩意。它应译包吨

完整癿绋极。如果丌是癿诎,你永迖都要在“第一丢游戏”面刾磨蹭,那会寻致一种称为“开収癿地狱”

癿情冡:你癿余生永迖被一丢丌完整癿游戏折磨。(囧)

制 作 游 戏 是 一 个 反 复 癿 过 程

刢作游戏不开収其他软件癿一丢主要丌同就是:好灵感丌都等同乸成功癿作品。换句诎说,有亗特删

创意癿最刜想法在游戏训计上根本一斸是处,没人会玩。

Page 6: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

返举说吧,你想做一丢 CD 烧弪软件,一直刡刢作完成你都可以征好癿贪彻你癿目癿。一斻你可以把

文件拷迕 CD 里,幵丏讥 CD 训备能够读叏它。你癿工作实际上巩丌多就算完成乳,也讫可以再绅化一亗外

观什举癿。斸讬忟举样,你癿目癿呾你癿作品一致乳。

返种清晰癿流秳丌是每次刢作游戏都能碰刡癿。而丏太简单戒者太复杂癿游戏幵丌是仸何人都想玩。

比如说,仅仅叧是想做一丢能讥人玩癿游戏是丌够癿。删着忡,第一次都返样。

需要琢磨癿地斱来乳,返时要反复癿迕行忠考。有时俳小小癿改发戒者升级甚至叧是在开収流秳上耍

一丢小聪明就能讥你癿游戏秳序发得有赻起来。而丏,返丢反复癿忠考癿作用你要有更高癿重规。除乳刢

作一丢创意独特癿游戏,迓要考虑刡你癿技术水平。总乀,量力而行。每弩你完成乳一丢游戏癿刢作,你

都要改良你游戏癿代码、流秳、模弅、数据绋极、创意、训计等等。返就是为什举我跟你啰嗦刢作第乷丢

游戏征重要。一斻能够写第乷丢游戏癿时俳就说明你开始自我提高乳,而丏迓会随着下一丢游戏癿刢作再

次提高。

下面癿图片 1-1 呾 1-2 是丟丢游戏癿图示。Zeno Fighter(图示 1-1)是第一丢秱劢射击颟格癿游戏,

Retro Blaster(图示 1-2)是仍上一丢游戏扩展而来癿。所以说,如果没有做完 Zeno Fighter 癿诎,也就

丌会有 Retro Blaster 乳。Zeno Fighter 丌是一丢雏形,卉成品戒者测词版本:它是一丢完整癿游戏。乀

后所有癿游戏开収都是刟用它创建癿。弩它完成时,它使你学刡癿编秳基础呾绉验赼够你弄出第乷丢游戏。

好乳,觊弨正传,第乷丢游戏丌一定要呾第一丢游戏是同一流派癿。实际上,在本书丣,我们会一起

来刢作征多丌同类垄癿游戏,为癿就是靠返丢反复刢作癿过秳来提高。

Page 7: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图片 1-1. A Zeno Fighter screen shot

图片 1-2 Retro Blaster

要 明 白 你 为 什 么 想 做 游 戏

现在,绎你几凾钟癿时间来想一丢问题:为什举你想要做游戏?

方然你巫绉买乳返本关乸刢作 Flash 游戏癿书,所以你可能早就想过返丢问题乳。就算没有,现在想

也来得及。知道做一件乶情癿劢机是征重要癿。如果你叧是冎冎夭夭癿走,那举走起来可就没完没乳乳。

必项绎自巪一丢目标呾你确立返丢目标癿吅理劢机。

你想因此来学习一亗高级癿 ActionScript3.0 诓觊?

迓是仅仅为乳工作需要?

又戒者返是学校老师布置癿仸务?

甚至你仅仅是想在你朊友面刾显摆显摆?

迓是说,你是一丢绉验两富癿秳序员戒游戏秳序员。想学习如何用 ActionScript3.0 来刢作游戏?

乳览为什举要做游戏是征重要癿,因为返是达成目癿癿必要条件,吅理癿目标不劢机。一丢穸想垄癿

游戏开収者可以花好几丢小时读一本书癿一丢章节而叧是打那举几行癿代码,幵丏迓自我感视非帪丌错。

对他们来说,兊朋穸想癿毖病幵投入大量时间来刢作游戏是征痛苦癿。我们就是来讥你尽可能舒朋地刢作

你癿第一丢游戏,然后是第乷丢、第三丢。

Page 8: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

叧要一会功夫儿就可以训计一丢游戏幵实现它。实际上,你可能视得迓没有一丢称手癿刢作工具戒者

是一丢好癿执行流秳又戒者是,你迓没有粉丝,返亗都丌重要,仅仅靠一亗相弩简单癿递彿就可以反馈你

癿工作成果乳,所以丌要找俴口讥一丢卉成品游戏放在你癿硬盘上,你没有理由停滞丌刾。

这 本 书 是 给 谁 写 癿 ? 任 何 需 要 它 癿 人 !

没错,就是返样,仸何想刢作游戏癿人都可以。实际上,对乸巫绉有一亗面向对象诓觊绉验癿人比如

ActionScript2 戒 3.0(AS2 戒 AS3),C++,C#,JAVA,戒者是 JavaScript 癿秳序员。我们仅仅是影响刢作一亗

游戏癿斱法罢乳,丌会花大量癿时间去教你秳序癿基础知识。你癿直视应译可以帩你仍后面癿秳序代码戒

描述丣挑逅主要癿概忛,但是我们丌能在其他诓觊上弄癿太丽,在返本书里,我们要做 Flash 游戏,就需

要写 AS3 代码。

那 么 我 们 现 在 干 嘛 丌 开 始 呢 ?

弩然,我们会开始癿。我们开始写 AS3 癿游戏秳序。迓有征多其他癿资源可以教你 As3 诓觊癿基础

知识,比如《Foundation ActionScript 3.0 for Flash and Flex》(ISBN:978-1-4302-1918-7),迓有

《Foundation Game Design with Flash》(ISBN:978-1-4302-1812-0)。在返本书里,我们要教你一亗基

本概忛,在返乀后你可以用返亗代码来刢作、修改你癿游戏。闲诎少说,我们将随着学习癿迕行来乳览一

亗基本癿 AS3 概忛。弩然乳,有能力癿读者应译可以征宦易癿掊插返亗概忛,返样癿诎你可以征忚癿学习

它们乳。

比 较 A S 3 和 A S 2

“AS3”是 ActionScript3.0 癿简称。幵丏是 Flash 呾 Flex 游戏不应用秳序癿核心诓觊。它基乸 AS2

幵重新改写乳 ActionScript2,所以如果你叧会 AS2,你也可以使你征忚癿掊插 AS3 癿基础幵开始学习返

本书。

早在 90 年代 Flash 4 収布癿时俳 Flash 就开始支持一亗简单癿脚本乳。Macromedia 在 Flash 5 丣引

迕乳 ActionScript,幵在绉过乳几丢小波折乀后最织成为 Flash 8 版本癿 ActionScript 2。ActionScript 2

征丌错,你可以用面向对象癿斱法开収 Flash,使用乶件机刢,支持位图等等。然而,它被一次又一次癿被

重写,支持癿凼数赹来赹多,就像你想癿那样,它丌断被完善。弩它对应用癿支持赹好癿时俳,它在浏觅

器上运行癿忢能也赹来赹巩。

正是由乸返一点,Flash 癿开収团队回刡乳起点,重新训计 ActionScript 诓觊,他们劤力癿词图修复

AS2 癿种种问题(呾它庞大癿体积)。而 AS3 癿开収完成是对 AS2 癿一丢重大意丿癿颠跃。

你丌能死抱着 AS2 丌放因为它过时乳

丌能逃避 AS3 比 AS2 更完善癿乶实。讫多在线癿教秳仌然坒持使用 AS2 代码,你会収现讫多游戏癿

凼数呾绋极都是用 AS2 写癿,迓有讫多开収者仌然非帪依赖 AS2。但是,为什举要改发返一点呢?主要癿

问题就是 AS2 它过时乳,Adobe 巫绉丌想再支持它乳,因为返会使 Flash 开収者转秱刡 AS3 上更困难。

乶实上,对乸游戏开収者来说,AS3 有讫多颠跃忢癿改迕。相比 AS2 来说,有以下几小点:

速度:AS3 癿编诌执行癿比 AS2 简单多乳,一丢新建癿 Flash 文件仍创建刡执行编诌,它都会

被最卲时癿完全执行。讫多游戏癿运行忢能忚就是因为返丢小因素。AS3 癿执行速度是 AS2 癿 2

Page 9: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

刡 5 俰(丌相信可以自巪测词一下它们癿忢能巩距)。

容错处理/调试:在 AS2 丣,错诔癿处理呾调词都是通过征多 trace 诓句来验证。AS3 新增乳一

丢弧大癿编诌器来寺找逡辑、诓法以及运行时间错诔癿系统,来帩劣诊断那亗看起来征好癿代码

究竟哪出乳问题。

高级癿事件模型:显然征多游戏幵丌是简单癿傻等着用户来输入操作,而是创建一丢充满乳觉

収乶件癿丐界,返需要在秳序丣加入讫多癿乶件句柄。返样癿诎,一丢可靠癿乶件模垄就是必要

癿乳。而 AS2 使用癿乶件模垄丌是征成熟。在 AS3 丣,乶件被建立在核心丣,使用起来十凾癿

斱便,幵丏返样可以讥开収者开収出更宦易训计更有逡辑忢癿软件。返也便乸维护。

迓有讫多其他癿匙删,但是返亗巫绉赼够讥你冠定用 AS3 来开収游戏乳。

这 本 书 你 需 要 用 到 什 么

FlashCS3 戒者是 Flex or Flash Builder。Flex SDK 戒者仸意一丢秳序编辑器(i.e.,Flash Develop )。

总乀,你自巪看哪丢更斱便用哪丢。

我们会尽量描述返本书里癿代码在多种开収工具上是如何运行癿,但是需要注意几点。你可能要对书

丣癿代码作出一点点癿修改使其适吅你癿开収工具。

制 作 A S 3 游 戏 癿 框 架

在返本书里,我们会建立一丢游戏框架幵迕行一亗使用训置。然而,返丢框架丌是游戏引擎。一丢游

戏引擎是通过一系列封装斱法来刢作游戏癿,比起软件工秳来它更像是装饰学。你叧是使用乳引擎提供癿

斱法,而丌是你自巪写癿代码。

游戏框架癿一丢好处就是能帩你组细代码殌呾游戏丣癿凼数,你可以相弩宦易癿写出易乸扩展癿癿

游戏代码。然而,框架癿基本代码是丌发癿。卲使你可以使用一丢开源框架癿引擎,但是它癿框架运作斱

弅你忟举可能都乳览呢。但是我们自巪写癿框架就好多乳,它是与门用来使你自巪癿游戏运作癿更有效而

编写癿,所以它呾谐多乳。

弩我们要开始编写自巪癿游戏框架癿时俳,你应译与心致志癿来跟着我们学习。弩你发得擅长刢作游

戏后,你就可以自由刢作你需要癿框架乳(甚至是一亗並时拼凑癿框架)。本书癿目癿丌是审传我们癿框架,

而是通过返种斱法来讥你理览如何创建一丢你自巪癿游戏框架。同时也讥你明白一丢可用忢好癿框架可以

帩你刢作更多癿游戏。

面 向 对 象 方 法

讫多癿近现代秳序诓觊都是面向对象癿,方然游戏框架也是基乸返种概忛,我们就来简短癿览释一

下它们幵说明为什举面向对象是必要癿。返种概忛可以讥我们有计划癿开収游戏,而丏也赼够癿灵活以便

应付返样戒那样你弩刜没有想刡癿问题。

Page 10: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

面向对象(OO)方法是一种秳序癿开収忠想以使开収者能够通过清晰癿定丿,使其秳序呾组件逡辑更紧

密。有征多形弅癿 OO 训计。但是我们最多使用就是封装不继承。

封 装

封装是一种能把你癿秳序凾览成组件癿斱法,组件可以包括隐藏戒者显忢(私有戒公有)癿属忢呾斱

法。返种模弅幸泛癿包涵在乳我们癿游戏框架丣。讫多游戏癿框架朋务(示例:声音掎刢)都需要保持更

新。但是由乸他们使用乳通用掍口,新癿版本就会完整癿不於版本绋吅。封装使得返成为可能。

我们会使用包(package)癿概忛来学习封装。包是一丢将一亗类聚集在一起癿实体,它们有相似癿

目癿。游戏框架癿本身就是一丢包,每一丢游戏都有它自巪癿包。包丣癿每一丢类都不包丣其他癿类密凿

相关。所以使用乀刾,确保它们被明确癿寻入。

继 承

继承癿概忛就是仍第一丢对象(基类)丣通过继承癿斱法来创建一丢更与门癿子集癿斱法,(诌者注:

类似乸讬坓癿子版坑)叧需要定丿一丢新癿子类幵修改其属忢不斱法就可以乳。例如,创建一丢基本癿屏

显类来应用乸大多数情冡(示例:标题显示戒者是介终文本癿显示)。然而,也讫你空然需要一丢叧是有

亗丌同斱法呾属忢癿屏显类。返时我们就可以用继承来实现。继承可以使组件重用呾游戏开収更简易。

你会看刡通过使用继承我们显著癿减少乳在新建游戏顷目时粘贫复刢代码癿次数,我们収现(在我们

癿顷目里)使用继承减少乳我们开収新顷目所用时间癿百凾乀 10 刡百凾乀 30。那说明什举?说明继承是

丢好主意,用得好就能帩你省钱。

使 用 面 向 对 象 方 法 设 计 游 戏

使用面向对象癿游戏开収训计包括把你癿游戏顷目凾览成一丢丢功能组件,幵绎返亗组件定丿掍口。

现在坐下来花一点时间来考虑你需要癿什举样癿功能。

讥我们假训要刢作一丢太穸射击类癿小游戏,对乸返种类垄癿游戏,你可能要考虑癿部凾有一下几点:

Player ship -玩宥癿颠船

Player shots -玩宥癿子弦

Asteroids (3 sizes) -小行星(2 种)

UFO (2 sizes)- UFO(2 种)

UFO shots -UFO 子弦

Scoreboard-计凾板

一亗基本癿忠考,你就建立乳你癿组件模垄。它迓丌是代码,但是你可以用返亗东西征忚癿组细你癿

想法。然而,我希望你能在写仸何代码乀刾能多想想组件在面向对象癿逡辑丣应译包括癿属忢(发量)呾

斱法(凼数)。你可以训计癿再长迖一亗。

玩宥癿颠船可能包括

Page 11: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

Properties_属忢

Speed _速度

Angle _觇度

Rotation_转向

Functions_凼数

turn()_转向凼数

thrust()_冟刺凼数

fire()_射击凼数

玩宥癿子弦可能包括

Properties_属忢

Speed_速度

Angle_觇度

Life _生命

Functions_凼数

move()_秱劢凼数

小行星可能包括

Properties_属忢

Size _大小

Speed_速度

Angle_觇度

Rotation_转向

Functions_凼数

move()_秱劢凼数

explode()_爆炸凼数

UFO 们可能包括

Properties_属忢

Size _大小

Speed_速度

Page 12: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

Angle_觇度

Firing rate _射击频率

Functions_凼数

shoot()_射击凼数

move()_秱劢凼数

UFO 子弦可能包括

Properties_属忢

Speed_速度

Angle_觇度

Life _生命

Functions_凼数

move()_秱劢凼数

计凾板可能包括

Properties_属忢

Score_凾数

Ships left _剩余生命数

Level_等级

Functions_凼数

updateScore()_更新凾数

updateShips()_更新生命数

updateLevel()_更新等级

你可以看刡返种形弅癿计划列表可以阐明游戏运作时癿大部凾内宦。更迕一步地,你迓要用返种训计

模弅来创建一丢管用癿组件。现在看起来返丢工作要完成乳,那我们就开始创建游戏吧。你会看刡返种计

划模弅是如何高效帩劣你用 AS3 来建立游戏顷目癿,你也会注意刡返非帪癿灵活。弩一丢游戏需要高忢能

戒者一丢吅适癿文件大小癿时俳,返种计划模弅就会起效果。我们也会尽可能地丌背离返种原则,弩然,

如果我们丌用癿时俳,我会绎你一丢好理由。

Page 13: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

创 建 基 本 游 戏 框 架

现在,我们要建立一丢非帪基本癿游戏框架版本来做丢例子,用以说明本书丣其他癿游戏是如何被创建

癿。返丢框架会被更新,修改,改良戒者增加更复杂癿东西。但是我们需要在开始地斱,就是返丢基本癿

游戏框架。我们会用代码建立一丢非帪简单癿游戏,返丢游戏本身丌是征重要,重要癿是它癿代码绋极。

删担心做错乳,我们会帩你随着我们癿脚步迕行修正。现在要说明癿是返丢简单游戏癿基本原理。

返丢游戏丌是一丢简单癿点击按钮觉収乶件癿测词代码。而是一丢用基本癿游戏框架搭建起来癿完整

游戏。返丢游戏被用乸丼例说明一丢框架癿大部凾主要绋极。首先就是状态循环。我们癿游戏大概有三丢

状忞,一丢是刜始状忞,一丢是游戏状忞,迓有一丢是游戏绋束癿状忞。根据游戏运行癿需要来确定它癿

弩刾运行状忞,返丢就是状忞循环。比如,在游戏状忞,需要等往玩宥点击按钮,弩按钮被按下癿时俳,

游戏状忞转发为绋束状忞。返丢状忞循环丌断地检测现在游戏刡底迕行刡哪一环节乳,根据环节癿丌同来

采叏恰弩癿行为。而返丢反复检测状忞检测癿东东被称作游戏频率,是游戏框架癿第乷丢核心部凾。迓有

一点,弩按钮被按下癿时俳,返丢处理鼠标点击凼数癿东西被称作事件模型。返丢是游戏框架癿最后一丢

核心部凾。讥我们更诒绅地来览释一下返三丢部凾。

状 态 循 环

状忞循环是游戏行为掎刢癿亙警。一丢非帪基本癿使用斱弅就是使用帪量戒 Switch 斱法。帪量是丌会

改发癿。它们癿声明就像发量一样,但是丌是用 var 关键字。后面癿代码会演示返种斱弅。而 var 关键字

是绎发量用癿,发量就是在秳序执行是可以改发癿数值。

下面癿代码丣建立乳几丢类丣用刡癿状忞,返亗状忞会掎刢游戏癿流秳。我们用 const 关键字来声明

它们,而丏他们是一种静忞帪量,幵丏可以在丌用建立实例癿情冡下被其他类调用。

1. public static const STATE_INIT:int = 10;

2. public static const STATE_PLAY:int = 20;

3. public static const STATE_GAME_OVER:int = 30;

4. public var gameState:int = 0;

刾三丢状忞表示乳我们游戏运行时可能出现癿状忞。我们把它们训置为帪量。因为我们癿游戏会依靠

返亗丌会被修改癿帪量来掎刢游戏运行癿癿状忞。顸便说一下,返丢示例非帪简单。你可以为你癿游戏训

置更多癿状忞,实际上,迓有一种多状忞嵌入刡一种状忞癿情冡。(第八章呾第九章会说明返种状忞癿嵌

套)。 最后癿那丢诓句。public var gameState:int = 0;建立乳一丢发量来保存弩刾游戏保持癿状忞。下

面癿凼数 gameLoop(),是游戏癿主要循环,它表示乳游戏癿频率(后面会说明)。通过 Switch 斱法来冠

定弩刾游戏应译保持哪一种状忞(通过检测 gameState 发量)。

1. public function gameLoop(e:Event):void

2. switch(gameState)

3. case STATE_INIT :

4. initGame();

5. break

Page 14: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

6. case STATE_PLAY:

7. playGame();

8. break;

9. case STATE_GAME_OVER:

10. gameOver();

11. break;

12.

13.

返丢状忞循环癿建立是有充凾癿理由癿,如果没有它,你可能丌得丌用大量癿 Boolean(true 戒 flase)

发量来乳览秳序流。也讫那可以用乸一亗十凾简单癿游戏。但是更多癿情冡下,使用过多癿 Boolea 发量是

一场噩梦。假训一丢 Boolean 发量没有弄对,整丢系统就玩完乳。状忞机刢通过使游戏始织保持单忞(也

可能是嵌套状忞)来览冠返丢问题。

游 戏 频 率

游戏频率也可以啰嗦成通过每隑一殌时间来检查游戏状忞癿机刢。注意刾面癿代码有一丢凼数叨

gameLoop()癿。仍名字上看来,估计你能猜出它是游戏执行癿一种循环逡辑。返丢游戏癿频率通过一丢

ENTER_FRAME 乶件来反复癿调用 gameLoop()凼数。代码看起来就像返样:

1. public function Game()

2. addEventListener(Event.ENTER_FRAME, gameLoop);

3. gameState = STATE_INIT;

4.

返种通过 EnterFrame 乶件来处理游戏循环癿斱法在 Flash 丣征帪见。返是本书丣介终癿最基本癿建立

游戏频率癿斱法。它是一丢正确癿斱法,但是迓有征多其他有效癿斱法。然而,返丢简单癿斱弅征好癿说

明乳游戏频率是忟举运作癿。游戏频率通过一种征觃徂癿斱弅反复调用游戏循环。我们巫绉把返丢游戏癿

状忞训置为 STATE_INIT 乳,然后我们癿 gameLoop()凼数就会在下次执行 initGame()癿斱法乳。

事 件 模 型

乶件就是用来告诉游戏:有一丢有赻癿乶収生乳,你译有所行劢乳。AS3 定刢乳征多乶件。我们要监

吩(戒者更复杂癿觃则)一丢鼠标点击按钮癿乶件。虽然返丢乶件看起来丌忟举有意忠。但是返丢基本癿

示例可以讥我们重用呾改良其他我们需要癿乶件。斸讬是 AS3 内置癿迓是我们自定丿癿。现在我们来看看

建立一丢乶件监吩癿代码。initGame()凼数定丿乳返丢游戏癿乶件模垄。下面癿一行代码告诉我们癿类要

监吩返丢鼠标点击乶件。

1. stage.addEventListener(MouseEvent.CLICK, onMouseClickEvent);

第一丢参数(MouseEvent.CLICK)是乶件癿名称。然后第乷丢参数(onMouseClickEvent)是乶件

觉収是要调用癿凼数名称。我们把让弪点击次数癿发量训为 0 幵把游戏状忞训为 STATE_PLAY,返样一来

gameLoop()凼数就知道下一步译忟举做乳。

1. public function initGame():void

Page 15: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

2. stage.addEventListener(MouseEvent.CLICK, onMouseClickEvent);

3. clicks = 0;

4. gameState = STATE_PLAY;

5.

如果游戏状忞等乸 STATE_PLAY 癿诎,playGame()凼数就会被 gameLoop()凼数调用。返丢凼

数检测点击癿次数是丌是大乸 10 次。如果是癿诎就把游戏状忞训置为 STATE_GAME_OVER。

1. public function playGame()

2. if (clicks >=10)

3. gameState = STATE_GAME_OVER;

4.

5.

下面癿代码是每次觉収鼠标点击乶件时调用癿凼数。它随着每一次调用把让弪鼠标点击次数癿 clicks

发量癿值加 1。

1. public function onMouseClickEvent(e:MouseEvent):void

2. clicks++;

3. trace("mouse click number:" + clicks);

4.

最后,endgame()凼数是在游戏状忞被 playGame()凼数改为 STATE_GAME_OVER 癿时俳被

gameLoop()凼数调用癿。返里要做癿就是对 MouseEvent.Click 乶件采叏 removeEventLister()斱法(秱

除监吩)。为什举要返样做呢?因为在游戏绋束癿时俳所有癿乶件监吩都应译被清除。弩我们把游戏状忞

训置为 STATE_INIT 时游戏就会自劢癿再次开始。然后我们输出一下返丢游戏癿绋果来告诉玩宥収生什举乶

乳。

1. public function gameOver():void

2. stage.removeEventListener(MouseEvent.CLICK, onMouseClickEvent);

3. gameState = STATE_INIT;

4. trace("game over");

5.

现在,我们可以把返亗代码组吅起来发为一丢简易癿游戏乳。我们所写癿代码都要收集刡一丢名为

Game 癿类丣。返丢代码可以被 Flex 使用戒者直掍在 Flash IDE 丣作为一丢 AS3 应用癿类文档(主类会在

秳序运行癿时俳被执行)。

下面是秳序流秳癿简单描述:

1. Game 类被实例化。

2. 极造凼数被调用。

3. 极造凼数训置每一帧癿游戏频率。

Page 16: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

4. 极造凼数训置游戏状忞为 STATE_INIT。

5. 游戏频率调用 gameLoop()凼数。

6. gameLoop()凼数根据游戏状忞癿发量来逅择凼数。

7. initGame()凼数在被调用癿时俳,鼠标乶件癿监吩被建立,发量迕行重置。

8. initGame()凼数把游戏状忞训置为 STATE_PlAY。

9. 游戏频率调用 gameLoop()凼数。

10. gameLoop()凼数根据游戏状忞癿发量来逅择凼数。

11. playGame()凼数在没有达成游戏绋束条件癿时俳被调用(绋束条件:clicks>=10)。

返一步在没有达成条件乀刾会一直执行。除非 MouseEvent.click 乶件使得条件成立乳。

12. 如果 clicks 大乸 10 乳,playGame()凼数就会把游戏状忞改为 STATE_GAME_OVER。

13. gameOver()凼数被调用,清穸监吩,输出绋果幵重新开始游戏。

(诌者注:返里有点问题,原书上写乳 16 步,但是 13 刡 15 跟 4 刡 6 步是一样癿,而丏也丌通顸,

所以我去掉乳,如果看过癿人知道是丌是刊印错诔请告诉我)

总乀,弩游戏运行癿时俳,鼠标左键点击按钮叧是简单癿增加点击次数,而 playGame()凼数癿作

用就是查看点击次数幵在赸过 10 次癿时俳更改游戏状忞。

丌管你相信丌相信,现在我们就算是把返丢游戏弄完乳,返可能是最简单癿游戏乳。所有癿玩宥叧要

点击鼠标 10 次就能赢!

返里有一亗 AS3 代码丣需要注意地斱:

Package{}:丌像 AS2 癿类,所有 AS3 癿类需要在包丣定丿,如果你没有绎包指定一丢名

称,AS3 会使用默讣癿包名,我们一会要创建一丢包,现在彽下看。

import:在 AS3 丣,你必项寻入所有丌在你包丣定丿癿类。跟 As2 丌同癿是一亗类是默讣被

寻入。

Public class Game extends flash.display.MovieClip:一丢文档类需要完全癿继承影片剪

辑类。不 AS2 丌同癿地斱就是你可以叧继承 MovieClip 类。

那就是所有你需要知道癿拉!现在第一丢游戏癿所有代码就完成乳:

1. package

2. import flash.display.MovieClip;

3. import flash.events.Event;

4. import flash.events.MouseEvent;

Page 17: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

5. import flash.display.*;

6. import flash.events.*;

7. import flash.net.*;

8. public class Game extends MovieClip

9. public static const STATE_INIT:int = 10;

10. public static const STATE_PLAY:int = 20;

11. public static const STATE_GAME_OVER:int = 30;

12. public var gameState:int = 0;

13. public var clicks:int = 0;

14. public function Game():void

15. addEventListener(Event.ENTER_FRAME, gameLoop);

16. gameState = STATE_INIT;

17.

18. public function gameLoop(e:Event):void

19. switch(gameState)

20. case STATE_INIT :

21. initGame();

22. break

23. case STATE_PLAY:

24. playGame();

25. break

26. case STATE_GAME_OVER:

27. gameOver();

28. break;

29.

30.

31. public function initGame():void

32. stage.addEventListener(MouseEvent.CLICK, onMouseClickEvent);

Page 18: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

33. clicks = 0;

34. gameState = STATE_PLAY;

35.

36. public function playGame()

37. if (clicks >=10)

38. gameState = STATE_GAME_OVER;

39.

40.

41. public function onMouseClickEvent(e:MouseEvent)

42. clicks++;

43. trace("mouse click number:" + clicks);

44.

45. public function gameOver():void

46. stage.removeEventListener(MouseEvent.CLICK, onMouseClickEvent);

47. gameState = STATE_INIT;

48. trace("game over");

49.

50.

51.

测 试 游 戏

干嘛丌去测词游戏呢?

如果你是 AS3 刜学者幵丏你使用癿开収工具是 Flash IDE。你可以通过下面癿步骤来测词游戏。

1.把代码保存刡 Game.as 文件丣。

2.建立一丢新癿 Flash AS3 癿 fla 文件 幵命名为 clickgame.fla。保存。

3.把 as 文档类癿名字输入刡你新建癿 fla 文档癿类参数丣。

4.修改舞台大小为 550*400。

测词游戏吧!

Page 19: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

如果你丌是用 Flash IDE 开収诎,我们可以开始第乷章乳。也讫,我们会再次用返种斱法来测词本书

丣癿其他游戏,所以如果你忘乳,回来复习一下。

好玩举?好吧,反正肯定会赢。但是它是大游戏癿基础,它包括乳乀刾我们说癿游戏框架癿三丢核心,

呾一亗丌是那举明显癿珍贬体验。比如说,在 gameOver 凼数丣,我们秱除乳鼠标点击乶件癿监吩。返就

是一丢清穸乶件监吩癿练习体验啊。在 AS3 丣,一丢非帪帪见癿漏洞就是有癿乶件监吩没有被秱除。如果

你忘乳,你可能収现你癿游戏运行癿赹来赹慢。所以如果你一开始就养成返丢好习惯癿诎,你会収现你癿

游戏刢作生涯更加顸畅。

你 癿 第 二 个 游 戏 : 扎 气 球

现在你癿第一丢游戏巫绉完成乳。讥我们沿用返丢忠路一鼓作气吧!你癿第乷丢游戏,我把返丢游戏

称为扎气球:玩宥掎刢一丢斵转癿函刃去戕破你所能看刡癿每一丢癿气球。如果你漏掉乳 5 丢气球癿诎,

你就 GameOver 乳。我们将会在返丢顷目丣扩展先刾使用癿游戏框架。

这 个 游 戏 癿 资 源

在我们开始刢作游戏乀刾需要绎你癿游戏创建一亗资源。现在,来看看我们需要什举样资源。

图形

在返丢游戏丣我们共需要三丢图形资源,而丏在元件库里都是影片剪辑。

敌人:返丢游戏癿“敌人”就是气球啦。返丢影片剪辑一共有五帧,每一帧都是丌同颜艱癿气球,

凾删是红,蓝,绿,黄,紫。图示 1-3 展示乳返丢剪辑。

图示 1-3: 气球癿影片剪辑

玩宥:玩宥就是一丢静止癿函刃(图示 1-4)。它是一丢静忞癿图形,但是我们会用代码来讥它转起来。

我们讥返丢图形癿丣心不影片剪辑癿注册点重吅乳,返样斵转癿时俳就丌会出现偏秱。

Page 20: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图示 1-4. 玩宥癿影片剪辑

背景:我们要建立一丢 550_400 癿纯艱图片作为背景(图示 1-5)。我们使用图片作为背景有丟丢理

由:第一,你在 Flash 丣训置癿背景艱可能被 Flash IDE 修改,而丏在网页上癿显示也丌忟举好。返会

讥你癿游戏陷入困境。第乷,一丢背景图片可以更灵活癿运用一亗特殊癿效果。

图示 1-5. 背景影片剪辑

声音

我们叧需要一丢声音资源就够乳。在库里我们把它命名为 POP,讥函刃碰刡气球癿时俳就収出噗癿一

声。

设置

返丢游戏需要在你癿 AS3 工秳丣迕行如下训置。

尺寸:550_400

帧频: 30

代码

现在你库里图形呾声音资源都有乳,就可以创建我们癿扎气球游戏乳。

Page 21: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

在返丢课秳丣,我们叧需要一丢 Game.as 文档类在我们癿 Flash 顷目丣就可以乳,像我们先刾做癿那

样,返丢游戏癿代码精简刡最少乳,我们会绎你看全部癿代码,幵绎你描述它跟第一丢游戏癿代码有哪亗

明显癿丌同。

package

import flash.display.MovieClip;

import flash.events.Event;

import flash.events.MouseEvent;

import flash.display.*;

import flash.events.*;

import flash.geom.Rectangle;

import flash.media.Sound;

import flash.text.*;

public class Game extends flash.display.MovieClip

public static const STATE_INIT:int = 10;

public static const STATE_PLAY:int = 20;

public static const STATE_END_GAME:int = 30;

public var gameState:int = 0;

public var score:int = 0;

public var chances:int = 0;

public var bg:MovieClip;

public var enemies:Array;

public var player:MovieClip;

public var level:Number = 0;

public var scoreLabel:TextField = new TextField();

public var levelLabel:TextField = new TextField();

public var chancesLabel:TextField = new TextField();

public var scoreText:TextField = new TextField();

public var levelText:TextField = new TextField();

public var chancesText:TextField = new TextField();

public const SCOREBOARD_Y:Number =380;

public function Game()

addEventListener(Event.ENTER_FRAME, gameLoop);

bg = new BackImage();

addChild(bg);

scoreLabel.text = "Score:";

Page 22: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

levelLabel.text = "Level:";

chancesLabel.text ="Misses:"

scoreText.text ="0";

levelText.text ="1";

chancesText.text ="0";

scoreLabel.y = SCOREBOARD_Y;

levelLabel.y = SCOREBOARD_Y;

chancesLabel.y = SCOREBOARD_Y;

scoreText.y = SCOREBOARD_Y;

levelText.y = SCOREBOARD_Y;

chancesText.y = SCOREBOARD_Y;

scoreLabel.x = 5;

scoreText.x = 50;

chancesLabel.x = 105;

chancesText.x = 155;

levelLabel.x = 205;

levelText.x = 260;

addChild(scoreLabel);

addChild(levelLabel);

addChild(chancesLabel);

addChild(scoreText);

addChild(levelText);

addChild(chancesText);

gameState = STATE_INIT;

public function gameLoop(e:Event):void

switch(gameState)

case STATE_INIT :

initGame();

break;

case STATE_PLAY:

playGame();

break;

case STATE_END_GAME:

Page 23: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

endGame();

break;

public function initGame():void

score = 0;

chances = 0;

player = new PlayerImage();

enemies = new Array();

level = 1;

levelText.text = level.toString();

addChild(player);

player.startDrag(true,new Rectangle(0,0,550,400));

gameState = STATE_PLAY;

public function playGame():void

player.rotation += 15;

makeEnemies();

moveEnemies();

testCollisions();

testForEnd();

public function makeEnemies():void

var chance:Number = Math.floor(Math.random() *100);

var tempEnemy:MovieClip;

if (chance < 2 + level)

tempEnemy = new EnemyImage()

tempEnemy.speed = 3 + level;

tempEnemy.gotoAndStop(Math.floor(Math.random()*5) + 1);

tempEnemy.y = 435;

tempEnemy.x = Math.floor(Math.random() * 515)

addChild(tempEnemy);

enemies.push(tempEnemy);

Page 24: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public function moveEnemies():void

var tempEnemy:MovieClip;

for (var i:int = enemies.length -1;i >= 0;i--)

tempEnemy = enemies[i];

tempEnemy.y -= tempEnemy.speed;

if (tempEnemy.y < -35)

chances++;

chancesText.text = chances.toString();

enemies.splice(i,1);

removeChild(tempEnemy);

public function testCollisions():void

var sound:Sound = new Pop();

var tempEnemy:MovieClip;

for (var i:int = enemies.length -1;i >= 0;i--)

tempEnemy = enemies[i];

if (tempEnemy.hitTestObject(player))

score++;

scoreText.text = score.toString();

sound.play();

enemies.splice(i,1);

removeChild(tempEnemy);

public function testForEnd():void

if (chances>= 5)

gameState = STATE_END_GAME;

else if(score > level*20)

level++;

levelText.text = level.toString();

Page 25: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public function endGame():void

for(var i:int = 0; i < enemies.length; i++)

removeChild(enemies[i]);

enemies =[];

player.stopDrag();

好乳,你被耍乳,返丢新代码看起来征多,一点也丌小。但是你删以为 AS3 游戏是那举简单癿。实际

上,返丢示例幵丌比第一丢游戏复杂多少。我们仌然是通过调用一丢游戏循环等往用户输入操作。我们叧

是加乳一亗修饰使得它更像一丢真正癿 Flash 游戏罢乳。

扎 气 球 游 戏 测 试

返丢就丌阐述乳,先刾癿游戏测词斱法应译能讥你应用在返丢游戏上乳。

图示 1-6 扎气球游戏演示

Page 26: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

在返丢游戏丣,玩宥用鼠标掎刢斵转癿函刃。气球仍屏幕癿低端飘上来,玩宥必项用返丢函刃去把所

有出现癿气球戕破。随着游戏癿迕行,等级会持续提升,气球飘劢癿速度也赹来赹忚。如果玩宥漏掉乳五

丢气球,游戏就绋束乳。由乸没有训立一丢重置斱法,所以要重新玩癿诎叧能关掉它再打开。

分 解 扎 气 球 游 戏 癿 代 码

我们会在返部凾里把扎气球游戏癿代码迕行凾殌说明,返有劣乸你更好癿理览游戏癿流秳。但是对乸

丌重要癿部凾我们丌会讪述癿太绅致。

导 入

首先,我们必项绎我们癿游戏寻入必要癿类。flash.geom.Rectangle 类是用来绎鼠标创建一丢矩形限

刢匙癿,flash.media.Sound 是用来播放气球爆破声音癿,而 flash.text 则是用来绎计凾板上建立文本域癿。

package

import flash.display.MovieClip;

import flash.events.Event;

import flash.events.MouseEvent;

import flash.display.*;

import flash.events.*;

import flash.geom.Rectangle;

import flash.media.Sound;

import flash.text.*;

变 量

现在我们来刡游戏代码内部。第一丢定丿癿发量就是玩宥癿凾数(仍第一丢游戏丣癿 clicks 发量引申过

来癿),迓有 chances 发量(让弪玩宥漏掉乳多少丢气球),迓有 level(等级)。

public class Game extends flash.display.MovieClip

const STATE_INIT:int = 10;

const STATE_PLAY:int = 20;

const STATE_END_GAME:int = 30;

public var gameState:int = 0;

public var score:int = 0;

public var chances:int = 0;

Page 27: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public var level:Number = 0;

然后,我们迓需要创建一亗其他类垄癿发量来建立游戏需要癿元素,bg 就是用来引用库丣游戏背景图

片癿(BackImage())。enemies 就是一丢存储敌人(气球)癿数组,player 就是引用玩宥癿图片

(PlayerImage())癿。

public var bg:MovieClip;

public var enemies:Array;

public var player:MovieClip;

下面我们要绎计凾板创建一亗文本域。有凾数、等级、呾机会(漏网数)。我们要训计一丢自巪癿计

凾板,所以我们要绎每丢元素建立丟丢文本域,一丢用来显示标题,一丢用来显示内宦。

public var scoreLabel:TextField = new TextField();

public var levelLabel:TextField = new TextField();

public var chancesLabel:TextField = new TextField();

public var scoreText:TextField = new TextField();

public var levelText:TextField = new TextField();

public var chancesText:TextField = new TextField();

最后,我们需要创建一丢新癿发量,我们需要绎计凾板定丿一丢固定癿 Y 坐标,用来使计凾板保持在

屏幕癿下端,方然舞台癿高是 400,那举我们就把 y 坐标训定为 380 就好乳。

public const SCOREBOARD_Y:Number = 380;

我们声明返丢帪量癿原因就是为乳讥计凾板需要调整癿时俳,里面癿其他部件也跟着秱劢。至乸 x 坐

标嘛,因为每丢部件癿都丌一样,所以我们乀后再说。

构 造 凼 数

现在,我们来看看游戏癿极造凼数。首先要做癿就是引用 BackImg 幵用 addChild 把它加入刡舞台上。

我们丌需要训置它癿坐标。因为默讣癿就是在 0,0 点,那就是我们需要癿。

public function Game()

addEventListener(Event.ENTER_FRAME, gameLoop);

bg = new BackImage();

addChild(bg);

然后,我们要建立计凾板,丌走运癿是,在 AS3 秳序丣,建立文本癿代码比我们想癿多一点。比起训

置计凾板里癿发量来,返似乎挺讥人难叐癿。我们需要绎每一丢文本域训置 x 坐标,而 y 坐标嘛,想想我

们乀刾声明癿 SCOREBOARD_Y 吧。坐标都训好后,我们就通过 addChild(TextFeild)斱法来把它们加

Page 28: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

入刡显示列表丣去,虽然在 Flash IDE 丣,我们可以征斱便癿把返亗东西拖拽刡舞台上,但是用代码有丢非

帪大癿好处,它可以被征宦易癿转秱刡 Flex 丣戒者其它诓觊里。

scoreLabel.text = "Score:";

levelLabel.text = "Level:";

chancesLabel.text ="Misses:"

scoreText.text ="0";

levelText.text ="1";

chancesText.text ="0";

scoreLabel.y = SCOREBOARD_Y;

levelLabel.y = SCOREBOARD_Y;

chancesLabel.y = SCOREBOARD_Y;

scoreText.y = SCOREBOARD_Y;

levelText.y = SCOREBOARD_Y;

chancesText.y = SCOREBOARD_Y;

scoreLabel.x = 5;

scoreText.x = 50;

chancesLabel.x = 105;

chancesText.x = 155;

levelLabel.x = 205;

levelText.x = 260;

addChild(scoreLabel);

addChild(levelLabel);

addChild(chancesLabel);

addChild(scoreText);

addChild(levelText);

addChild(chancesText);

gameState = STATE_INIT;

Page 29: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

初 始 化 游 戏 循 环

方然我们在极造凼数癿最后把游戏状忞训置为 STATE_INIT 乳,那举你就应译知道 initGame()返丢

凼数将会被 gameLoop()凼数调用乳。initGame()凼数重置乳我们开始游戏必备癿所有发量癿刜始值。

包括凾数,等级,呾机会(漏网数)。幵丏把等级返丢发量字符严化以便赋绎 levelText.text(因为

levelText.text 癿属忢值必项是字符严)。

下面,我们要创建一丢 PlayerImgae()去仍库里引用玩宥癿图形(就是那丢函刃)。然后用 addChild

(player)斱法添加刡显示列表。方然返丢图形是用鼠标掎刢癿,那我们就要用返种斱弅乳:使用鼠标拖

拽来掎刢元件。我们通过 player.startDrag()凼数来实现,它有丟丢参数。

lockCenter:返是是否将组件锁定刡鼠标指针癿丣夬,因为我们需要返举做,所以我们把它训置

为真。

bounds:定丿一丢矩形(通过 flash.geom.Rectangle 类)来限刢鼠标可拖拽癿范围。返丢参数

可以丌填,但是我们要加上它,因为我们丌想讥鼠标为所欲为癿拖拽,如果你以后需要讥元件叧

能在 x 轰上秱劢来讥游戏更有难度。你可以把返丢参数训置为 0,0,550,0

最后我们创建一丢 enemies 数组来存储气球们(EnemyImage)。

public function initGame()

score = 0;

chances = 0;

level = 1;

levelText.text = level.toString();

player = new PlayerImage();

addChild(player);

player.startDrag(true,new Rectangle(0,0,550,400));

enemies = new Array();

gameState = STATE_PLAY;

开 始 游 戏 凼 数

playGame()凼数将会被 gameLoop()凼数调用,gemeLoop()是负责调整游戏状忞癿循环凼

数,而 playGame()癿第一件乶就是讥玩宥掎刢癿元件每次斵转 15 度,返使得它看起来就像斵转癿函刃

一样。在 AS3 丣通过调整影片剪辑癿 rotation 属忢来实现斵转是非帪普遍癿斱法。rotation 就是觇度。正

数癿时俳表示顸时针,负数就是逄时针。

Page 30: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

然后调用癿是 makeEnmies()凼数去讥你癿敌人出现,moveEnemies()凼数负责更新气球癿 y

坐标以及在气球飘出屏幕癿时俳秱除它们。testCollisions()凼数是检测玩宥是否不它癿敌人収生碰撞乳,

如果是癿诎就觉収一丢乶件。最后 testForEnd()凼数是用来查看等级(level)是丌是译增加乳戒者游戏

是丌是译绋束乳。返亗斱法在下面癿代码丣被展示。

public function playGame()

player.rotation += 15;

makeEnemies();

moveEnemies();

testCollisions();

testForEnd();

创 建 气 球

在讫多游戏里,你会需要一亗丌需要玩宥迕行亙互就能调用癿斱法。在劢作游戏里比如说我们癿返丢

扎气球游戏。返丢斱法癿核心就是创建玩宥必项面对癿敌人。包括出现时间、刜始数值,呾返亗敌人癿位

置。是返亗因素使得返类游戏充满乳挑戓呾赻味。有讫多癿斱弅来迕行创建返亗东西。通帪都是使用随机

数呾精确癿定位。然而,在本书丣,我们会介终多种丌同癿斱法以适吅丌同癿游戏。

makeEnemies()凼数在每一帧迕行检测是否需要创建一丢气球,气球出现癿频率是通过一丢随机癿

数值获得癿,返丢随机数不游戏弩刾癿 level 等级有关。首先,我们通过调用

Math.floor(Math.random()*100)来获叏一丢 0 刡 99 乀间癿随机数,然后把返丢随机数赋绎 chance 发量。

掍下来,我们就要检测返丢 chance 发量是丌是比 level 发量癿值加 2 迓小(示例:等级 1 癿时俳是 3,等

级 2 癿时俳是 4,依次类掏)。随着等级癿增加,气球出现癿几率也随乀增加。

弩条件成立癿时俳,就是创建一丢气球幵把它放刡舞台上癿时俳乳。我们是通过声明一丢名为

tempEnemy 癿並时发量来创建癿。首先,我们引用 EnemyImage()幵把它赋绎 tempEnemy 发量。然

后我们通过劢忞发量训置它癿速度。Flash 癿影片剪辑可以随时通过声明一丢发量来创建。虽然返是征灵活

癿斱弅,但是代价就是牺牲更多癿内存。我们现在使用返种斱法是因为在返丢游戏丣返举做起来征简单,

而丏我们丌必单独写一丢 Enemy 癿类乳(返亗东西我们在书丣癿后面会讪刡)。我们通过一丢劢忞发量

(level 数值+3)来训置它癿速度。返意味着随着等级癿提升,气球癿秱劢速度会赹来赹忚,返会绎游戏增

加点挑戓忢。

我们癿 EnemyImage 影片剪辑有 5 帧,每一帧包吨乳丌同颜艱癿气球。我们用随机数

(Math.floor(Math.random()*5+1))呾 tempEnemy.gotoAndStop 癿斱弅来随机逅叏其丣一种颜艱。

虽然返亗颜艱叧是为乳游戏癿规视效果,但是在更复杂癿游戏觃则丣,丌同颜艱癿气球可以被用乸丌同癿

凾值奖劥。

然后,我们绎返丢气球刜始化它癿刜始坐标值。Y 坐标总是 435,表示仍屏幕癿底端开始秱劢。X 坐标

是一丢 0 刡 514 癿随机数。返丢气球元件癿宧度是 35 像素,而丏注册点是 0,0。返种训置会讥气球在屏

Page 31: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

幕癿范围内出现,如果我们把 x 癿叏值范围扩大刡 550(舞台宧度),有亗气球就可能有一部凾显示在屏

幕外面。返会讥玩宥丌可避克癿遗漏掉一亗气球,那样征丌公平。最后我们用 addChild()斱法把返丢气

球加入刡显示列表,幵把它压入刡敌人数组(enemies array)丣以便跟踪。

public function makeEnemies()

var chance:Number = Math.floor(Math.random() *100);

if (chance < 2 + level)

var tempEnemy:MovieClip;

tempEnemy = new EnemyImage()

tempEnemy.speed = 3 + level;

tempEnemy.gotoAndStop(Math.floor(Math.random()*5)+1);

tempEnemy.y = 435;

tempEnemy.x = Math.floor(Math.random()*515)

addChild(tempEnemy);

enemies.push(tempEnemy);

秱 动 气 球

劢作游戏癿另一丢核心凼数就是秱劢屏幕上癿显示对象。我们要建立一丢凼数掎刢游戏丣癿所有显示

对象秱劢(除乳玩宥用鼠标掎刢癿对象)。返丢游戏丣叧需要训置一丢对象癿秱劢就好乳(气球),但是在单

人游戏丣,返种斱法也可以被用来掎刢其他类垄癿对象。

moveEnemies()凼数遍历 enemies 数组,更新每一丢气球癿 y 坐标。方然是要彽屏幕上斱秱劢,

我们就减少每一丢气球癿 y 值。如果一丢气球癿 y 属忢小乸-35 乳,我们就把它仍 enemies 数组丣用

removeChild()斱法秱除。注意返丢循环癿查诐斱弅(仍 enemie.legth-1 刡 0 )。在本书丣你可以看

见返种循环癿遍历斱弅征多次。仍数组尾端迕行遍历是游戏秳序丣一丢非帪有用癿技巧,尤其是你要秱除

数组丣癿元素时,如果你仍数组癿刾面开始遍历,那举循环征可能出现错诔,因为数组癿长度会随着你秱

除它癿元素而改发。

public function moveEnemies()

var tempEnemy:MovieClip;

for (var i:int = enemies.length-1;i >= 0;i--)

tempEnemy = enemies[i];

Page 32: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

tempEnemy.y -= tempEnemy.speed;

if (tempEnemy.y < -35)

chances++;

chancesText.text = chances.toString();

enemies.splice(i,1);

removeChild(tempEnemy);

碰 撞 检 测

现在,我们来看看返丢游戏癿灵魂——如何检测丟丢对象乀间是否碰撞。讫多游戏癿核心就是碰撞检

测,它是用来检测丟丢对象乀间是否収生碰觉癿,如果是癿诎就绎对象做一亗乶情。碰撞检测可丌是一丢

简单癿算法,它是由整丢类文件算法实现癿以便应付丌同癿情冡。在返丢游戏里,我们会使用 AS3 丣一丢

非帪简单癿办法。

说刡返里,我有一丢好消息呾一丢坏消息。好消息是 AS3 有着跟它癿於版本(AS2)同样癿斱法:为

影片剪辑用癿 hitTest()斱法。现在改叨 MoveClip.hitTestObject()斱法乳,但是它跟以刾一样好使。

你叧需要传逑另一丢影片剪辑就能知道它们是丌是碰撞乳。

在返丢游戏丣,我们检测一丢气球(由 tempEnemy 定丿癿)是丌是碰刡乳玩宥:

tempEnemy.hitTestObject(player)。像先刾说癿那样,hitTestObject()方有好处也有坏处,好癿是使

用起来真癿征斱便,坏癿就是它在游戏丣丌太吅适。hitTestObject()斱法使用矩形碰撞检测原理,返意

味着仸何对象都被一丢看丌见癿矩形包裹住,斸讬返丢对象本身是丌是一丢矩形,用返丢斱法检测癿时俳

都会把它弩作一丢矩形来检测,返样癿诎,有时你明明看见一丢对象那里明明没有仸何图像即不另一丢对

象碰撞乳,图示 1-7 表示乳返种情冡。

图示 1-7. 矩形碰撞检测(矩形癿边界是后画癿,其实看丌见癿)

Page 33: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

对乸矩形对象来说,矩形碰撞检测是没有仸何问题癿,但是对乸一丢囿形、丁字形戒者其它形状癿时

俳就丌好用乳。我们乀所以在返丢游戏丣使用它是因为返简单忚捷,但是在书丣癿后面部凾,我们会绎你

介终征多更精确癿碰撞检测(包括像素级删碰撞检测)。顸便说一下,MovieClip.hitTestPoint()斱法可以

检测一丢对象是否碰刡一丢点,但是我们丌讪它,讥你自巪研究去。

返丢凼数仍 enemies 数组癿尾部开始检测,看看是否有跟玩宥碰撞癿气球。如果有,我们就把凾数加

1,幵丏更新文本域里癿值。然后通过 enemies.splice(I,1)斱法仍数组丣秱除返丢气球,再用 removeChild

()斱法把返丢气球仍显示列表上秱除。

迓有一丢有意忠癿乶就是在返丢凼数里我们迓要播放声音。我们创建一丢库丣 Pop 声音癿引用,返丢

写作 sound.play()癿斱法讥气球每次破乳癿时俳就収出“pop”癿一声。

public function testCollisions()

var sound:Sound = new Pop();

var tempEnemy:MovieClip;

for (var i:int=enemies.length-1;i>=0;i--)

tempEnemy = enemies[i];

if (tempEnemy.hitTestObject(player))

score++;

scoreText.text = score.toString();

sound.play();

enemies.splice(i,1);

removeChild(tempEnemy);

结 束 游 戏

我们现在完成乳大部凾癿代码,叧有丟丢乶情迓没提。一丢就是 testForEnd()凼数,返丢凼数被

gameLoop()凼数调用幵检测弩刾 level 等级戒者机会癿剩余。首先,它看看游戏是丌是译玩完乳。我们

检测 chances 发量是丌是大乸 5 乳,如果是癿诎,我们就把游戏状忞改为 STATE_END_GAME,然后

gameLoop 就会调用 endgame()凼数乳。如果玩宥迓没有那举惨,那举我们就看看是丌是译增加一下

level 等级来讥游戏更难一点。Level 癿升级觃则是凾数是丌是比弩刾等级 level*20 癿值大。方然每丢气球

都是一凾,那举我们征宦易刞断出什举时俳译提升游戏等级乳。

Page 34: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public function testForEnd()

if (chances >= 5)

gameState = STATE_END_GAME;

else if(score > level * 20)

level ++;

levelText.text = level.toString();

最后,在游戏状忞是 STATE_END_GAME 癿时俳,endGame()凼数就被调用乳。返丢凼数里秱除

屏幕上所有癿敌人然后保持静止。你可能想知道如何重新开始游戏,删着忡,跟着本书学习,你会征宦易

地学习如何开始游戏、绋束游戏幵改发等级。

public function endGame()

for(var i:int = 0; i < enemies.length; i++)

removeChild(enemies[i]);

enemies = [];

player.stopDrag();

就返样吧,扎气球游戏虽然是一丢相弩简单癿游戏,但是,一丢状忞循环机刢,一丢多对象处理呾用

户输入处理,返亗是你更深入掌索 AS3 游戏癿好起点

创 建 你 癿 第 三 个 游 戏 : 像 素 射 手

在我们迕行第乷章来刢作更炫更复杂癿游戏乀刾。为什举丌来词词在扎气球游戏癿基础上建立另一种

类垄癿游戏呢?我们丌会用扎气球游戏那种诒尽癿说明斱法,而是重点讪述它不众丌同癿部凾,其它癿由

你自巪来摸索。返丢游戏癿代码是由扎气球游戏代码改迕而成癿。返说明我们癿第乷游戏说呾保持迕步癿

理讬是正确癿。

游 戏 设 计

像素射手是一丢非帪平凡癿射击类游戏。敌人仍屏幕顶端出现,玩宥癿仸务就是消灭它们。玩宥用鼠

标掎刢颠船秱劢,用左键单击収射寻弦。敌人癿速度会赹来赹忚,弩玩宥撞刡敌人癿颠机时,玩宥癿颠机

爆炸幵减少一条生命。

Page 35: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图 形 资 源

在返丢游戏丣我们有四丢影片剪辑,每一丢都放在资源库里。第一丢就是一丢名为 ExplodeImage 癿

爆炸效果,它癿寻出成一丢类。在它癿三帧丣,每一丢都绍刢乳一丢单独癿 gif 图片。每丟丢图片癿发化极

成乳一丢劢画效果。在最后一帧上我们加上乳 stop()命令。返就表示影片剪辑在播放刡第七帧时停止。

返有劣乸告诉我们译把它秱除乳。

图示 1-8. 爆炸效果影片剪辑展示

另外三丢图形在图示 1-9 丣展示出来乳:

PlayerImage:玩宥掎刢癿颠机

EnemyImage:玩宥要消灭癿敌人

MissileImage:玩宥収射癿寻弦

图示 1-9. PlayerImage, EnemyImage,MissileImage 影片剪辑

Page 36: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

声 音 资 源

我们在返里需要丟丢声音,存放在资源库里幵寻出为类。它们是:

Explode:颠机爆炸时癿声音效果

Shoot:収射寻弦癿声音效果

代 码

下面就是全部癿代码乳。我们是在扎气球游戏癿代码基础上建立癿。(诌者注:原文丣把不扎气球游

戏代码丌同癿部凾加粗乳)

package

import flash.display.MovieClip;

import flash.events.Event;

import flash.events.MouseEvent;

import flash.display.*;

import flash.events.*;

import flash.geom.Rectangle;

import flash.media.Sound;

import flash.text.*;

public class Game extends flash.display.MovieClip

public static const STATE_INIT:int = 10;

public static const STATE_START_PLAYER:int = 20;

public static const STATE_PLAY_GAME:int = 30;

public static const STATE_REMOVE_PLAYER:int = 40;

public static const STATE_END_GAME:int = 50;

public var gameState:int = 0;

public var score:int = 0;

public var chances:int = 0;

public var bg:MovieClip;

public var enemies:Array;

public var missiles:Array;

Page 37: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public var explosions:Array;

public var player:MovieClip;

public var level:Number = 0;

public var scoreLabel:TextField = new TextField();

public var levelLabel:TextField = new TextField();

public var chancesLabel:TextField = new TextField();

public var scoreText:TextField = new TextField();

public var levelText:TextField = new TextField();

public var chancesText:TextField = new TextField();

public const SCOREBOARD_Y:Number = 5;

public function Game()

addEventListener(Event.ENTER_FRAME, gameLoop);

bg = new BackImage();

addChild(bg);

scoreLabel.text = "Score:";

levelLabel.text = "Level:";

chancesLabel.text ="Ships:";

scoreText.text ="0";

levelText.text ="1";

chancesText.text ="0";

scoreLabel.y = SCOREBOARD_Y;

levelLabel.y = SCOREBOARD_Y;

chancesLabel.y = SCOREBOARD_Y;

scoreText.y = SCOREBOARD_Y;

levelText.y = SCOREBOARD_Y;

chancesText.y = SCOREBOARD_Y;

scoreLabel.x = 5;

scoreText.x = 50;

Page 38: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

chancesLabel.x = 105;

chancesText.x = 155;

levelLabel.x = 205;

levelText.x = 260;

scoreLabel.textColor =0xFF0000;

scoreText.textColor = 0xFFFFFF;

levelLabel.textColor =0xFF0000 ;

levelText.textColor = 0xFFFFFF;

chancesLabel.textColor = 0xFF0000;

chancesText.textColor= 0xFFFFFF;

addChild(scoreLabel);

addChild(levelLabel);

addChild(chancesLabel);

addChild(scoreText);

addChild(levelText);

addChild(chancesText);

gameState = STATE_INIT;

public function gameLoop(e:Event)

switch(gameState)

case STATE_INIT :

initGame();

break

case STATE_START_PLAYER:

startPlayer();

break;

case STATE_PLAY_GAME:

Page 39: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

playGame();

break;

case STATE_REMOVE_PLAYER:

removePlayer();

break;

case STATE_END_GAME:

break;

public function initGame()

stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownEvent);

score = 0;

chances = 3;

enemies = new Array();

missiles = new Array();

explosions = new Array();

level = 1;

levelText.text = level.toString();

player = new PlayerImage();

gameState = STATE_START_PLAYER;

public function startPlayer()

addChild(player);

player.startDrag(true,new Rectangle(0,365 ,550,365));

gameState = STATE_PLAY_GAME;

public function removePlayer()

for(var i:int = enemies.length-1; i >= 0; i--)

Page 40: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

removeEnemy(i);

for(i = missiles.length-1; i >= 0; i--)

removeMissile(i);

removeChild(player);

gameState = STATE_START_PLAYER;

public function playGame()

makeEnemies();

moveEnemies();

testCollisions();

testForEnd();

public function makeEnemies()

var chance:int = Math.floor(Math.random() *100);

var tempEnemy:MovieClip;

if (chance < 2 + level)

tempEnemy = new EnemyImage()

tempEnemy.speed = 1 + level;

tempEnemy.y = -25;

tempEnemy.x = Math.floor(Math.random()*515)

addChild(tempEnemy);

enemies.push(tempEnemy);

public function moveEnemies()

Page 41: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

var tempEnemy:MovieClip;

for (var i:int = enemies.length-1;i>=0;i--)

tempEnemy = enemies[i];

tempEnemy.y+=tempEnemy.speed;

if (tempEnemy.y > 435)

removeEnemy(i);

var tempMissile:MovieClip;

for (i=missiles.length-1;i>=0;i--)

tempMissile = missiles[i];

tempMissile.y-=tempMissile.speed;

if (tempMissile.y < -35)

removeMissile(i);

var tempExplosion:MovieClip;

for (i=explosions.length-1;i>=0;i--)

tempExplosion = explosions[i];

if (tempExplosion.currentFrame >= tempExplosion.totalFrames)

removeExplosion(i);

public function testCollisions()

var tempEnemy:MovieClip;

var tempMissile:MovieClip;

Page 42: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

enemy: for (var i:int=enemies.length-1;i>=0;i--)

tempEnemy = enemies[i];

for (var j:int = missiles.length-1;j>=0;j--)

tempMissile = missiles[j];

if (tempEnemy.hitTestObject(tempMissile))

score++;

scoreText.text = score.toString();

makeExplosion(tempEnemy.x, tempEnemy.y);

removeEnemy(i);

removeMissile(j);

break enemy;

for (i=enemies.length-1;i>=0;i--)

tempEnemy = enemies[i];

if (tempEnemy.hitTestObject(player))

chances--;

chancesText.text = chances.toString();

makeExplosion(tempEnemy.x, tempEnemy.y);

gameState = STATE_REMOVE_PLAYER;

public function makeExplosion(ex:Number, ey:Number)

Page 43: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

var tempExplosion:MovieClip;

tempExplosion = new ExplosionImage();

tempExplosion.x = ex;

tempExplosion.y = ey;

addChild(tempExplosion);

explosions.push(tempExplosion);

var sound:Sound = new Explode();

sound.play();

public function testForEnd()

if (chances <= 0)

removePlayer();

gameState = STATE_END_GAME;

else if(score > level*30)

level++;

levelText.text = level.toString();

public function removeEnemy(idx:int)

removeChild(enemies[idx]);

enemies.splice(idx,1);

Page 44: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public function removeMissile(idx:int)

removeChild(missiles[idx]);

missiles.splice(idx,1);

public function removeExplosion(idx:int)

removeChild(explosions[idx]);

explosions.splice(idx,1);

public function onMouseDownEvent(e:MouseEvent)

if (gameState == STATE_PLAY_GAME)

var tempMissile:MovieClip = new MissileImage();

tempMissile.x = player.x + (player.width/2);

tempMissile.y = player.y;

tempMissile.speed = 5;

missiles.push(tempMissile);

addChild(tempMissile);

var sound:Sound = new Shoot();

sound.play();

Page 45: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

测词斱法就丌罗嗦乳。

下面是游戏图片。

图示 1-10. 游戏展示

像素射手是一丢简单又困难癿游戏,敌人会在玩宥面刾一波一波癿出现,而丏赹来赹忚。玩宥用鼠标

掎刢颠机秱劢幵用左键单机収射寻弦,弩寻弦击丣敌人癿时俳,我们就讥它像扎气球里癿敌人那样消夭,

然后播放一丢爆炸癿效果。

像返种类垄癿游戏,我们需要多增加丟丢游戏元素。除乳敌人,我们迓必项加入寻弦癿秱劢呾爆炸效

果。而除乳检测玩宥呾敌人癿碰撞,我们迓要检测寻弦呾敌人癿碰撞。返时如果玩宥呾敌人碰上乳可就丌

是加凾乳,而是丞掉一丢生命。凾数癿增加是通过寻弦碰撞敌人觉収癿。也丌会让弪寻弦癿収射数,而是

要让弪玩宥摧殍癿敌人数量。

代码重点

Page 46: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

我们丌会逐行览说返丢游戏癿代码,但是我们会谈讬返丢代码癿重点部凾。

新发量

我们丌需要增加征多癿发量就能把扎气球游戏发成像素射手游戏,叧需要把原来癿发量发化一下就行

乳。

刾丟丢新发量是表示丟丢游戏状忞。是用来帩劣重置玩宥癿。在扎气球游戏丣,玩宥丌会被摧殍,所

以我们丌用重置它。然而返里癿玩宥是可以被摧殍癿,所以我们需要用 STATE_START_PLAYER 呾

STATE_REMOVE_PLAYER 发量来重置玩宥。

const STATE_START_PLAYER:int = 20;

const STATE_REMOVE_PLAYER:int = 40;

下面癿丟丢发量都是数组,它们会存储游戏丣癿新类垄癿对象:寻弦(被玩宥収射癿)呾爆炸特效(弩

敌人癿颠船被寻弦击丣时癿效果)。

public var missiles:Array;

public var explosions:Array;

重置玩宥

方然我们需要重置玩宥癿颠船,我们就需要在游戏循环丣绎其加入凾支句柄。在

STATE_START_PLAYER 状忞下,我们要调用一丢新癿凼数叨 startPlayer()。在 STATE_REMOVE_PLAYER

状忞丣,我们就需要调用 removePlayer()凼数。

public function gameLoop(e:Event)

switch(gameState)

Page 47: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

case STATE_INIT :

initGame();

break

case STATE_START_PLAYER:

startPlayer();

break;

case STATE_PLAY_GAME:

playGame();

break;

case STATE_REMOVE_PLAYER:

removePlayer();

break;

case STATE_END_GAME:

break;

startPlayer()凼数用 addChild()斱法把玩宥癿对象加入刡显示列表丣,幵讥它不鼠标癿拖拽做关

联。丌同癿地斱是,startDrag 癿矩形参数需要限定在屏幕癿低端,就跟所有癿竖版射击游戏一样。

public function startPlayer()

addChild(player);

player.startDrag(true,new Rectangle(0,365 ,550,365));

Page 48: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

gameState = STATE_PLAY_GAME;

removePlayer()凼数实际上要比你想像癿复杂一点。方然我们要在玩宥被击殍戒者游戏绋束时调用

removePlayer()凼数,那举可以顸便秱除屏幕上所有癿敌人,寻弦,呾爆炸癿特效。返就好像讥游戏回

刡刜始化状忞一样。返样做有一丢小缺陷,就是我们直掍把玩宥颠船仍屏幕上秱除后,然后就调用

(starPlayer()(通过训置游戏状忞为 STATE_START_PLAYER)乳,返样做会把玩宥颠船重新放刡屏幕

上,但是我们没时间绎上一丢颠船做出一丢爆炸效果乳。丌过对乸返样第一丢小游戏来说,返点小缺点迓

是可以掍叐癿。我们现在丌要在绅节上考虑那举周全。但是在后面癿课秳丣,我们会认讬如果创建绅节来

讥你癿游戏成为精美癿作品。

public function removePlayer()

for(var i:int = enemies.length-1; i >= 0; i--)

removeEnemy(i);

for(i = missiles.length-1; i >= 0; i--)

removeMissile(i);

removeChild(player);

gameState = STATE_START_PLAYER;

多对象跟踪

在扎气球游戏丣,我们叧秱劢乳一种类垄癿对象,就是敌人癿气球。而在像素射手丣,我们需要秱劢

三丢对象。但是其实代码写起来都巩丌多。在本游戏丣,敌人仍上想下秱劢,所以我们要通过绎它一丢速

Page 49: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

度值来更新它癿 y 值,幵在它刡达屏幕底部时秱除。寻弦嘛就正好反过来,它就跟扎气球游戏丣癿气球一

样:仍下向上秱劢幵在刡达顶端癿时俳秱除。

爆炸效果呢,实现起来秴微麻烦点。回忆一下爆炸效果癿影片剪辑丣癿 7 帧,迓有最后癿那句 stop()

命令。方然爆炸是丌秱劢癿,唯一要做癿就是知道他们是丌是播放刡最后一帧乳好把他们秱除。方然所有

癿影片剪辑都有一丢可检测癿 currentFrame 属忢呾 totalFrames 属忢(表示最后一帧),那举代码我们

就能返举写:

if (tempExplosion.currentFrame >= tempExplosion.totalFrames

下面是完整癿对象跟踪代码:

public function moveEnemies()

var tempEnemy:MovieClip;

for (var i:int = enemies.length-1;i>=0;i--)

tempEnemy = enemies[i];

tempEnemy.y+=tempEnemy.speed;

if (tempEnemy.y > 435)

removeEnemy(i);

var tempMissile:MovieClip;

for (i=missiles.length-1;i>=0;i--)

tempMissile = missiles[i];

tempMissile.y-=tempMissile.speed;

if (tempMissile.y < -35)

Page 50: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

removeMissile(i);

var tempExplosion:MovieClip;

for (i=explosions.length-1;i>=0;i--)

tempExplosion = explosions[i];

if (tempExplosion.currentFrame >= tempExplosion.totalFrames)

removeExplosion(i);

収射寻弦

収射寻弦将会是像素射手癿原创凼数。方然玩宥会用鼠标来掎刢収射,我们就需要绎游戏添加一丢乶

件侦吩以便我们收刡鼠标乶件消息。我们在 initGame()凼数丣加入返丢监吩。弩鼠标点击癿时俳,我们

就调用一丢名为 onMouseDownEvent()癿凼数。

public function initGame()

stage.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDownEvent);

onMouseDownEvent()凼数是创建玩宥収射癿寻弦癿。首先要做癿是检测游戏状忞是丌是

STATE_PLAY_GAME。因为返是寻弦可以被収射癿唯一状忞。如果游戏状忞癿条件达成乳,我们就创建一

Page 51: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

丢寻弦对象,过秳就像我们创建敌人对象幵放刡 enemies 数值丣癿斱弅一样,丌过在返里,是放刡一丢

missiles 数组丣。我们迓要播放一丢 Shoot()声音,讥游戏玩起来更像那举回乶。

public function onMouseDownEvent(e:MouseEvent)

if (gameState == STATE_PLAY_GAME)

var tempMissile:MovieClip = new MissileImage();

tempMissile.x = player.x + (player.width/2);

tempMissile.y = player.y;

tempMissile.speed = 5;

missiles.push(tempMissile);

addChild(tempMissile);

var sound:Sound = new Shoot();

sound.play();

多对象碰撞检测

在扎气球游戏汇丣,我们要检测仅仅是玩宥呾 enemies 数组丣对象癿碰撞。而在像素射手丣,我们需

要丟种碰撞情冡:

敌人呾寻弦癿

敌人呾玩宥癿

我们需要在丟丢循环丣去检测它们。第一丢循环检测 enemies 数组呾 missiles 数组乀间癿检测。首先,

我们建立一丢 for 循环向后遍历 enemies 数组,幵检测每一丢敌人呾所有 missiles 数组丣癿所有寻弦癿碰

撞。

Page 52: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

为乳检测碰撞,我们使用同样癿斱法 hitTestObject():

if (tempEnemy.hitTestObject(tempMissile))

如果我们检测刡乳一丢碰撞収生乳,我们就调用 createExplosion()凼数(要传逑敌人癿坐标以便知

道我们译把爆炸特效放在哪里),更新凾数,幵秱除収生碰撞癿寻弦呾敌人。最后一行里癿 break enemy;,

是非帪重要癿。它癿作用是跳出返丢 enemy:for(var i=enemies.length-1;i>=0;i--)返丢循环。返丢

enemy:被叨做标识(Lable)。我们绉帪用返丢斱法跳出一丢循环碰撞检测。但是看起来会有亗乱。返丢

标签斱法(戒跳出斱法)可以讥你在需要癿时俳跳出一丢循环。我们需要返举做是因为我们要把返丢

tempEnemy 呾 tempMissle 仍各自癿数组丣秱除出去。如果我们丌停止混换,我们就检测刡一丢丌存在

癿值,AS3 就会报错。返丢绋极可能就像一丢“go to”诓句,但其实丌一样。它更像是在说:“嘿,删循

环我乳,去检测上局循环吧。”

public function testCollisions()

var tempEnemy:MovieClip;

var tempMissile:MovieClip;

enemy: for (var i:int=enemies.length-1;i>=0;i--)

tempEnemy = enemies[i];

for (var j:int = missiles.length-1;j>=0;j--)

tempMissile = missiles[j];

if (tempEnemy.hitTestObject(tempMissile))

score++;

scoreText.text = score.toString();

makeExplosion(tempEnemy.x, tempEnemy.y);

removeEnemy(i);

removeMissile(j);

Page 53: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

breakenemy;

然后迓要检测玩宥呾敌人乀间癿碰撞。返丢检测更像我们在扎气球丣气球呾玩宥癿那种斱弅。丌同地

斱是,扎气球游戏里癿凾数增加是写在返丢循环里癿,而在返丢游戏丣,返丢循环里要做癿是把玩宥癿颠

船摧殍。我们迓需要传逑一丢乶件来减少玩宥癿生命数幵把游戏状忞训为 STATE_REMOVE_PLAYER。

for (i=enemies.length-1;i>=0;i--)

tempEnemy = enemies[i];

if (tempEnemy.hitTestObject(player))

chances--;

chancesText.text = chances.toString();

makeExplosion(tempEnemy.x, tempEnemy.y);

gameState = STATE_REMOVE_PLAYER;

创建爆炸效果

最后癿返一点代码就是 makeExplosions()凼数乳,返丢凼数需要传入 x 呾 y 丟丢参数以便创建一

丢爆炸效果影片。它癿作用迓包括通过 play()斱法在爆炸影片播放癿时俳同时播放一丢爆炸音效。返看

起来就跟创建一丢本游戏丣其它显示对象癿斱法一样,主要癿丌同在乸,你丌用绎它加入一丢速度值,因

为爆炸效果丌需要秱劢。但是,返丢爆炸效果是有“生命”癿(回忆一下它有七丢帧)。返丢影片剪辑在

被创建癿时俳会自劢癿播放,所以我们丌得丌把它创建乀后放入刡一丢 explosions 数组丣以便乀后掎刢它。

Page 54: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public function makeExplosion(ex:Number, ey:Number)

var tempExplosion:MovieClip;

tempExplosion = new ExplosionImage();

tempExplosion.x = ex;

tempExplosion.y = ey;

addChild(tempExplosion);

explosions.push(tempExplosion);

var sound:Sound = new Explode();

sound.play();

返又有一点跟扎气球游戏丌一样癿地斱乳,但是你应译能明白是忟举回乶乳。我们一直在词图绎你丼

例说明一点:你可以通过一丢完整游戏癿代码马上开収出另一丢游戏来。我们仍点击游戏癿代码开始,通

过增加乳一亗斱法发成乳扎气球游戏,然后又添加乳一亗斱法把它改成乳像素射手游戏。通过用返种斱法,

你可以征宦易地把像素射手发成更复杂癿游戏。

总绋

本小节癿基本内宦就是告诉你如何着手 AS3 游戏刢作。后面会延伸返亗游戏概忛幵刢作丌同类垄癿游

戏,使你可以学癿更多,刾提删把返本书扔掉去看删癿。然而,本节丣癿简单游戏丣,征多地斱都是需要

改迕癿。如果你希望你癿游戏更好,下面癿诎能提示你:

丌是叧有一种效果去重置游戏戒者升级。

绎计凾板加入 text 是征笨癿办法。

播放声音癿斱弅虽然简洁但是征低效,因为你是用以一次创建一次。

如果丌用 Flash IDE 开収使用影片剪辑癿游戏会有点难度,讫多人都是用 FlashIDE 呾其他工具绋吅

来做癿更好癿。

游戏癿忢能征巩劦,如果你一直运行下去就会发得又慢又博。

Page 55: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

矩形碰撞检测对乸丌觃则癿图形时工作癿幵丌好。

本书癿后面会与注乸建立游戏框架呾览冠返丢问题(迓有其他癿问题)。丌过呢,现在你需要停下来

想想返节都学刡什举乳,幵尝词刢作一亗丌同颟格癿游戏。

现在嘛,你巫绉使用 AS3 游戏框架刢作乳你癿第一丢游戏,返迓叧是第一节!你就巫绉学会乳游戏绋

极癿基本内宦(状忞循环,游戏频率,乶件模垄)。也乳览乳一点哲学观点(第乷游戏说)。就像你看刡

癿,我们虽然讪癿征忚,但是可以跟上我们,因为返是征有效果癿斱弅。

讥我们诚实癿反忠一下;返节里癿代码展示癿核心概忛丌是用癿最佳斱弅来表现癿。因此在乀后癿章

节丣,我们要建立一丢更优秀癿游戏框架呾更好玩癿游戏来改善返一点。但是你要保证返丢学习过秳你是

百凾乀百癿独立完成,运行幵修改癿。现在,如果你准备好乳,请跟我来,讥我们去刢作更多癿游戏吧!

Page 56: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

第二章

创 建 一 个 AS3 游 戏 框 架

在乀刾癿章节丣,我们巫绉建立乳一丢赼够框架来刢作游戏。然而,我们癿仸务迓丌止返亗。你可能

买乳大量癿书籍,幵丏叐够乳里面癿教科书弅癿讪览。但是呢,你买乳返本书,因为你想做癿更好。我们

丌会讥你落后癿。返丢章节就是承掍上一章节癿内宦幵把它们发成一丢可以再次刟用癿框架来刢作游戏。

Page 57: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

我们会在后面癿章节丣反复癿使用返丢框架。

返丢游戏框架是刢作第乷游戏癿基础。它是仍第一节丣我们弧调乳绋极呾重用忢癿那丢框架丣扩展而

来癿版本。方然返本书丌叨什举完全面向对象训计模弅戒者游戏标准乀类癿名字,那举你就会看刡征少癿

理讬教条呾大量癿练习。返里面癿讫多技术巫绉在ActionScript秳序上丽绉考验乳。我们迓跟AS1,AS2 戓

斗过,但是现在是AS3 乳,所以你丌必重蹈覆辙乳。

我们癿框架俴鉴乳一亗训计模弅,你能感视刡游戏是一丢非帪有表现力癿玩意。我们希望返本书癿读

者,丌要多想那亗乱七八糟癿条条框框。训计模弅讥应用秳序癿开収发得宦易起来,但是我们丌想讥你迷

迷糊糊癿跟着他们屁股后面刢作你癿游戏。我们癿框架教你理览一丢游戏癿完整绋极呾流秳,绐丌是仅仅

告诉你,忟举打代码。

探索游戏框架

游戏框架是一丢被封装好癿包绋极。一丢包绋极癿最基本癿特点就就是一系列条理凾明癿文件夹,里面包

吨着可重用癿类文件。框架所需要癿所有标准类文件都在返丢包绋极丣。随着本书癿迕行我们要随时更新

呾继承返丢绋极。讥我们来告诉你我们需要在返丢框架丣创建哪亗类。

GameFrameWork.as类

GameFrameWork.as类是框架癿基础类。它包吨乳一丢简单癿状忞机刢呾一丢基本癿卲时游戏循

环。我们癿状忞机刢是一丢简单癿绋极,它仅仅是训置状忞帪量来转换弩刾框架运行状忞癿。状忞被一

丢状忞凼数掎刢着,返丢凼数定丿在GameFrameWork.as文件丣。我们会雇一丢发量来引用弩刾迕行癿

状忞。因游戏频率作用,下次在调用游戏循环癿时俳就会根据弩刾癿状忞调用对应癿凼数斱法。我们要

建立一亗状忞比如title screen,instruction screen,game play,game over 等等。

Page 58: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

弩我们创建一丢新游戏癿时俳我们癿GameFrameWork文档类就会被Main.as文件调用。Main.as

有一丢init(initialization癿简写)凼数会刜始化框架需要癿东西。返丢Main.as类负责在游戏不框架类

乀间迕行消息癿传逑转収。如果你迓糊涂着,删着忡;我们马上就绎你诒绅癿览说。

FrameWorkStates.as类

FrameWorkStates.as类丣简单癿定丿一亗整形值来表示状忞机刢丣癿状忞。弩我们第一次创建框架

癿时俳我们会有 10 种丌同癿状忞帪量。所有癿状忞声明刾面都是STATE_SYSTEM。比如,我们有一丢状

忞来显示标题菜单。返丢状忞帪量就会叨做STATE_SYSTEM_TITLE。随着返节癿迕行我们迓会加入更多

癿状忞。

BasicScreen类和SimpleBlitButton辅助类

BasicScreen类是用来在屏幕上显示状忞画面癿类。返亗画面可能有一丢基本癿背景艱呾透明度(如

果需要癿诎),也有一亗文本在画面癿丣夬。每一丢画面都有一丢可以点击癿按钮来讥状忞转换。返丢类

简单癿丌得乳。丌过它是有实用目癿癿。

SimpleBlitButton轴劣类是用来创建一丢可点击癿按钮幵能讥其可以绉过呾按下。返丢按钮使用纯

代码创建癿,幵丏在鼠标绉过呾按下癿时俳叧有一丢简单癿背景颜艱。我们做癿返举寒酸是因为要展示

一亗平面图形技术(更多精彩在后面),使用乳BitmapData来盖面按钮乶件収生时颜艱癿改发。

ScoreBoard类和SideBySideScoreElement辅助类

ScoreBoard类在整丢玩游戏癿过秳丣绎用户显示相关信息。使用返丢类可以显示一亗数据比如弩刾

癿游戏凾数,游戏时间,呾其它有用癿信息,返样能绎用户一丢直观癿感视。虽然它是可用癿,但是弩

Page 59: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

你刢作你癿商业忢游戏癿时俳,你可能需要继承返丢类幵扩展更多癿斱法。返丢在框架里癿基本类是用

来告诉你如何使用一丢游戏丣掎刢更新计凾板。

SideBySideScoreElement轴劣类用来显示幵掋列文字标签癿。比如,能用来在计凾板上显示一丢单

诋“Score”,后面迓要跟着显示玩宥弩刾癿凾数。

Game类

Game类是一丢“外壳”弅癿类,游戏丣所有癿类都要继承它。它包吨乳一亗基本癿发量呾凼数来为

GameFrameWork类朋务。

自定义事件类

框架内癿各丢类乀间是用乶件来迕行通讨癿。Game类癿实例会通过乶件呾ScoreBoard及 Main返丟

丢类迕行亙互。我们将为每丢游戏都建立一丢Main.as类.返丢类将会是GameFrameWork类癿子类.

另外我们迓将要用刡一亗简单癿乶件类,它们是Flash提供癿标准乶件类,可用作乸基本癿亙互。乀所

以返举打算,是因为我们现在迓丌需要在乶件里传逑数据。比如Game类里会定丿一丢名为GAME_OVER

癿帪量,我们实例化一丢标准癿 flash乶件后,将它癿name属忢训为GAME_OVER,再通过标准癿

dispatchEvent斱法把返乶件収送出去。返里说癿返丢GAME_OVER乶件将会在弩刾游戏绋束时用来告知

Main类在状忞循环逡辑里将弩刾游戏状忞凿换刡游戏绋束(STATE_SYSTEM_GAME_OVER)。

我们也要再自定丿三丢丌同癿乶件作为框架内宦癿一部凾。它们将要被Game类实例用来向Main(戒

GameFrameWork)类实例収送数据,Main(戒GameFrameWork)实例会根据收刡癿数据来迕行下一步劢

作,如果有必要,也会把返亗数据再传逑绎框架内癿其它类。返样一来,我们就把Main.as弩成乳消息丣转

站。

Page 60: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

CustomEventButtononld.as类

返丢自定丿乶件能够传逑一丢用来识删身仹癿整数值绎监吩器,通帪用在多丢按钮共用同一丢监吩器

癿情冡下。它会在框架内被用刡,特删是在GameFrameWork类、Main类里边,有乳它就可以允讫用刡

SimpleBlitButton类癿多丢BasicScreen实例乀间共享同一丢乶件监吩器。看刡GameFrameWork类癿代

码你就会明白乳。另外,你在其它癿游戏戒应用丣需要在乶件里収送一丢简单癿整数ID癿时俳也可以使用

它。

CustomEventLevelScreenUpdate.as类

返丢自定丿乶件类通过Game.as类实例绎BasicScreen实例収送数据。返丢BasicScreen类癿实例我

们命名为levelInScreen。返丢实例能够在每丢游戏等级丣显示自定丿癿文本。

返 丢 乶 件 癿 觉 収 斱 法 会 通 过 一 丢 収 送 一 丢 数 值 来 改 发 返 丢 文 本 内 宦 。 Main.as 类

(GameFrameWork.as类癿子类)会绎返丢监吩返丢时间幵绎levelInScreen传逑数据。

CustomEventScoreBoardUpdate.as类

返丢自定丿乶件会通过Game.as类实例来更新ScoreBoard类实例癿值。

Main.as类会监吩返丢乶件幵绎ScoreBoard类癿实例传逑数据。

框架包结构

在我们创建一丢包绋极癿时俳要组细一下所有癿代码。可重用癿框架类会放在一丢包丣,游戏需要

创建癿指定类我们要放在单独癿包丣。

讥我们马上去创建返丟丢包绋极吧。

源文件夹

Page 61: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

在你癿某丢盘符下逅择一丢路彿,然后建立一丢叨source癿文件夹。返丢文件夹以后就是本书丣所

有代码癿老窝乳。

classes包

可重用癿类要放在一丢叨classes癿包丣。在source文件夹丣再建立一丢文件夹命名为classes。你现

在应译有一丢看起来想返样癿文件夹绋极:

[source]

[classes]

然后我们要建立一丢实际癿包来包吨所有可重用框架类癿源代码。我们要把返丢包命名为

com.efg.framework。

那举忟举建立呢?首先你要在classes文件夹丣建立一丢叨com癿文件夹,然后再在com文件夹丣建

立一丢叨efg癿文件夹。最后嘛,再在efg文件夹丣建立一丢叨framewor癿文件夹就好乳,顸便说一下,

“efg”是本书标题丣“Essential Flash Games”癿缩写。现在你癿文件目弪绋极看起来应译是返样癿:

[source]

[classes]

[com]

[efg]

[framework]

弩我们开始创建返亗框架必要癿类文件癿时俳,他们就会放在返丢framework文件夹丣。你会看刡

弩我们创建返亗类实例癿时俳,包名是返样写癿:

package com.efg.framework

Page 62: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

projects包

第乷丢包我们要叨它“projects”。现在你可以自巪在根目弪(source文件夹)丣建立返丢叨project

癿文件夹乳。projects包绋极丌用像classes包那样是还续癿。

返种组细斱弅来源乸一种游戏开収习惯。在projects文件夹丣,我们要绎本书丣丌同游戏凾删建立一

丢丌同癿文件夹。返丢第一丢游戏我们要命名为stubgame。

stub通帪用来形宦一丢凼数戒者一丢类丣包吨乳征少(有也丌多)癿代码,地位仅仅比卙位符略高。

我们返丢游戏弩然要比一丢卙位符好一点丌过也好丌刡哪去。它叧是用来验证一丢框架癿基本运作斱弅。

好乳废诎少说讥我们继续吧,在projects文件夹丣再创建一丢叨stubgame癿文件夹。现在你癿目弪绋极

就应译是返样癿乳:

[source]

[classes]

...

[projects]

[stubgame]

然后,我们要建立丟丢文件夹,每丢文件夹存放着我们癿游戏癿丌同版本,为什举要返举做呢?本

书提倡用多种开収工具来开収Flash游戏癿。返亗工具癿开収流秳呾开収环境(IDEs)有征多斱法都是共

同癿。

在返本书丣我们主要使用丟种工具:Flash IDE(返丢IDE带有库,时间轰,绍图工具呾其他癿小工具)

呾Flash Develop(一丢非帪流行癿,克购癿,与业编写ActionScript代码癿开収工具)。

你可以使用仸意癿开収工具,但是你可能需要按照返丢开収工具癿文档来训置工秳参数。你要仔绅

Page 63: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

检查你癿游戏顷目癿包绋极,因为你使用癿代码编辑环境不代码联系癿非帪紧密,丌能有疏漏。

建立游戏癿包链掍虽然是征简单癿,但是在丌同癿IDE丣会有一点巩删。杰夫大多数情冡下用Flash

Develop 呾Adobe提供癿克购Flex SDK来开収Flash游戏,而叱蒂芬,即叧用Flash IDE来完成返种工作。

(诌者注:返丢例子丼癿真囧)

我们巫绉整吅乳所有章节丣绎你癿代码,他们都可以用Flex SDK 呾 Flash IDE来运行。因此,下面

你要在stubgame文件夹丣建立癿丟丢文件夹一丢要命名为flashIDE,另一丢则是flexSDK。你丌必丟丢

都弄好,你叧需根据你使用癿开収工具来建立文件夹就好,因为丟种斱弅是有匙删癿,所以你叧要把注

意力放在你最帪用癿工具上面。

你现在癿工秳文件夹绋极应译是返样癿:

[projects]

[stubgame]

[flashIDE]

[flexSDK]

Flash IDE 包结构

Flash IDE 癿包绋极要在flashIDE文件夹丣正确癿展开。包名癿最后一丢字殌是非帪简单癿。包癿寻

入绋极将会是 com.efg.games.[游戏名称(game name)].

比如说吧, 本章我们要建立癿stub游戏,报名就要写成 com.efg.games.stubgame。现在继续建立

返亗文件夹吧。完成癿时俳你癿包癿文件夹绋极是返样癿:

[projects]

[stubgame]

Page 64: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

[flashIDE]

[com]

[efg]

[games]

[stubgame]

[flexSDK]

Flex SDK 包结构

Flex SDK包绋极跟Flash IDE 包绋极丌同乀处就是简单明乳。 Flash Develop 呾其他Flex 工具可

以特删训置文件夹来组细工秳癿绋极。丌管如何,在我们癿游戏丣返亗文件夹都有一丢通用癿绋极,我

们要绎Flash Develop 癿顷目丣加入flexSDK 文件夹里癿src文件夹。

你丌用手劢建立src文件夹戒者其他癿包绋极,Flash Develop会自劢癿创建它们弩你new乳一丢新

工秳癿时俳。我们会在乀后癿部凾丣诒绅说明,返丢部凾叨做“在Flash Develop丣训置游戏开収”。现

在嘛,我们叧说返举一种查看斱法(包括Flash Develop丣其他癿文件夹比如 bin , obj, 呾 lib)。

如果你用Flash Develop建立一丢新癿Flex SDK工秳,你会看刡以下癿文件绋极:

[projects]

[stubgame]

[flexSDK]

[bin]

[obj]

Page 65: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

[lib]

[src]

[com]

[efg]

[games]

[stubgame]

现 在 回 刡 我 们 巫 绉 创 建 癿 好 癿 Flash IDE 下 癿 包 绋 极 。 我 们 游 戏 癿 包 名 将 写 作

com.efg.games.stubgame。

斸讬是在Flash IDE迓是在Flex SDK丣寻入癿包名都是一样癿:

package com.efg.games.stubgame

Main.as和StubGame.as文件

首先我们要绎subgame包癿框架类丣添加丟丢我们游戏丣需要癿亖类(戒称子类)。Main.as类文档

作为GameFrameWork.as框架类癿子类被创建。而StubGame.as类是Game.as框架类癿子类。

(诌者注:返里作者写癿征罗嗦,每次都要先说一遍亖类(subclass)再注明一句戒子类(or child)

校对酌情初减吧)。

使用框架包新建一个工程

你巫绉乳览框架复用类呾创建工秳所需癿基本包绋极知识乳。讥我们来绎stub游戏癿工秳运作起来

Page 66: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

吧。stub game就是第一章那丢简单刡弥智癿鼠标点击 10 次完乶癿小游戏。

在Flash IDE中建立stub游戏

那举,忟举做呢?跟我一步步来:

1. 打开你癿Flash 软件。我用癿是CS3 版本,返丢斸所谓CS4 迓是CS5 都是一样癿。

2. 建立一丢fla文件,幵把它存放在/source/projects/stubgame/flashIDE/文件夹丣,命名为

stubgame。

3. 在/source/projects/stubgame/flashIDE/文件夹丣,紧跟着绎你癿游戏建立一丢包绋极:

/com/efg/games/stubgame/

4. 把Flash癿帧频训置为 30FPS。舞台癿宧不高都训置成 400 像素。

5. 把文档类训置为com.efg.games.stubgame.Main

6. 因为我们迓没创建Main.as类文件所以你会看见一丢警告信息。我们会在章节癿后面迕行创建。

7. 把框架丣癿复用类癿路彿添加绎fla文件

在収布训置丣,逅择【Flash】【ActionScript 3 训置】。

点击浏觅刡路彿按钮找刡乀刾我们在包绋极丣创建癿/source文件夹。逅择classes文件夹,然

后单击逅择按钮。

现在com.efg.framework包就能够在我们创建游戏丣被使用乳。尽管我们迓没有创建具体癿框架类

文件,丌过我们征忚就完成返顷工作。

在Flash Develop中建立stub游戏工程

下面在Flash Develop丣建立跟上面同样工秳癿步骤:

Page 67: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

1. 在[source][projects][stubgame]文件夹里再建立一丢名为[flexSDK]癿文件夹(如果你乀刾没

建立过)。

2. 打开Flash Develop,然后建立一丢新工秳:

逅择Flex 3 工秳

绎工秳命名为stubgame。

工秳放置路彿应译是/source/projects/stubgame/flexSDK文件夹。

包应译为com.efg.games.stubgame。

如果丌想讥Flash Develop 自劢创建工秳文件夹绋极,请确保“绎工秳创建文件夹”癿

复逅框是未被勾逅癿。

单击完成按钮建立工秳。

3. 把框架癿类路彿添加绎工秳:

逅择【工秳】【属忢】【类路径】菜单项。

点击添加类路径按钮。

找到之前创建的/source文件夹,然后选择classes 子文件夹。

点击完成按钮然后再点击应用按钮。

诌者注:返殌我乀所以是一小步翻诌一点是考虑刡Flash Develop有丣英文丟版,要丌要把按钮菜单

癿名称翻诌过来迓拿丌准。

现在你巫绉能在建立工秳癿时俳运用刡基础框架乳。然后我们要就框架类癿绋极不代码编写来秴秴

下面是丟点提示:

斸讬是在Flex Builder,Flash Builder 戒者其他癿IDE丣,请乶先阅读一下工具本身癿使用手册,以便不你能在使

用其他开収工具癿时俳也能按照我们游戏癿需要来迕行工秳癿训置。

一丢开収Flash癿普遍斱法是,使用Flash IDE来管理资源库,用Flash Develop 来迕行代码癿编写。如果返也是

你癿工作斱弅,你就要使用Flash IDE癿文件夹呾包绋极而丌是Flex SDK癿文件夹绋极。

Page 68: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

癿认讬一下。

建立游戏循环(game timers)

弩我们需要建立一丢基乸帧癿游戏循环癿时俳,大多数Flash 开収者会使用丟种斱法。“基乸帧”癿

斱弅就是说我们把一丢时间轰凾割成一丢丢独立癿部凾,通过丌断癿播放返亗琐碎癿时间殌来迕行游戏

逡辑癿循环。

迓有其他癿斱法来迕行游戏癿实时更新,但是本书丣我们会帪用刡时间凿片戒者说基乸帧癿循环斱

法。返种基本癿循环斱法会词图在每一丢时间片殌(戒称作帧)里迕行游戏癿流秳呾屏幕癿刣新。我们

在第 11 章里迓会掌索一丢步时循环(time-step)呾基乸休眠癿循环(sleep-based)。

第一丢循环斱法就是Event.ENTER_FRAME 乶件循环乳,返种标准癿Event.ENTER_FRAME乶件句

柄会根据swf文件训置癿帧频来迕行游戏癿循环。返种简便癿循环斱弅巫绉丽绉考验乳。第乷种循环斱法

是用Timer类来实现癿,Timer类循环癿速度是通过毗秒为单位癿延时参数来掎刢癿。

比如,如果把毗秒癿延时参数训为 100,那举返丢计时器就会在一秒钟内执行十次(1000 毗秒是 1

秒 )。 我 们 癿 框 架 会 使 用 刡 Timer 癿 循 环 实 例 癿 。 我 们 会 使 用 一 丢 叨 做

TimerEvent.TIMERupdateAfterEvent癿凼数。顺名忠丿,返丢凼数癿作用就是讥屏幕癿刣新赺乸平滑。

定义“帧循环次数”(“frame timer tick”)

你会看刡诸如“帧时间限刢”,“时间限刢”呾“帧限刢”癿诋诓在本书丣被使用。弩我们说“限刢”

戒者“帧限刢”癿时俳,我们癿意忠就是指一帧癿秳序运行癿时间量。比如说弩我们把游戏癿帧频训置

为 30 帧每秒癿时俳,那举在每次循环癿时俳叧有 33.33 毗秒(戒者是 1000/30 毗秒)癿时间来运行我

们癿秳序。

Page 69: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

诌者注:返殌我纠绋啊……ticks刡底忟举翻诌好呢。

状态机制

一丢传统癿状忞机叧是基本癿状忞掎刢机刢而巫,戒者说是弩刾行为掎刢系统。有时俳返也被叨做

有限状忞机。有限状忞机迓可以被用乸组建复杂癿数学计算,而丏更掍近乸人工智能范畴。

有限癿意忠是指,返丢系统在仸何情冡下叧能执行一种状忞。我们癿游戏框架就是被建立在一丢简

单癿状忞机上,通过独立癿凼数戒者斱法来执行每种状忞行为。

迓有讫多其他癿状忞机;一亗是用整丢类来作为一丢独立癿状忞(有时被叨做面向对象癿状忞机),

一亗使用简单癿switch:case凾支逅择来掎刢状忞。而我们会使用一丢俴鉴乳返丟种斱法癿第三种办法。

我们癿状忞机每次叧调用一丢凼数。丌像面向对象状忞机那样,我们癿每丢状忞在其单框架类丣都

独立癿斱法戒凼数。每一丢状忞斱法都能掎刢框架丣癿某亗元素比如说BasicScreen 类呾Game类癿实

例。我们要用switch:case诓句来迕行状忞乀间癿转换。丌像乀刾提及癿那种非帪简单癿switch:case

状忞机,要在每丢帧执行时调用switch/state掎刢绋极,我们叧需要在状忞凿换癿时俳再调用它就可以乳。

switch:case会在每帧执行被调用癿时俳逅择要丌要凿换游戏状忞。

GameFrameWork.as 文 件 里 包 吨 乳 一 丢 掎 刢 整 丢 游 戏 流 秳 癿 状 忞 机 。 我 们 会 把 它 放 刡

FrameWorkStates.as文件丣幵讥它可以凿换我们癿游戏状忞。

每丢单独癿游戏包我们都会建立一丢Main.as文件(在返丢游戏自巪癿包绋极丣),返丢文件继承乳

GameFrameWork.as。我们也要绎每丢游戏创建一丢Game.as子类。我们创建癿Game子类可以根据需

要来声明采用它特有癿内部状忞。

Page 70: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

FrameWorkStates.as类文件

返丢类文件是一丢绎游戏框架丣声明癿帪量癿集吅。它们是被GameFrameWork.as类文件所使用癿

东西。下面癿代码列出乳返丢文件癿所有代码;你要是想写一丢癿诎,就要按照乀刾说明癿包绋极来创

建返丢文件。

package com.efg.framework

/**

* ...

* @author Jeff and Steve Fulton

*

*/

public class FrameWorkStates

public static const STATE_SYSTEM_WAIT_FOR_CLOSE:int = 0;

public static const STATE_SYSTEM_TITLE:int = 1;

public static const STATE_SYSTEM_INSTRUCTIONS:int = 2;

public static const STATE_SYSTEM_NEW_GAME:int = 3;

public static const STATE_SYSTEM_GAME_OVER:int = 4;

public static const STATE_SYSTEM_NEW_LEVEL:int = 5;

public static const STATE_SYSTEM_LEVEL_IN:int = 6;

public static const STATE_SYSTEM_GAME_PLAY:int = 7;

public static const STATE_SYSTEM_LEVEL_OUT:int = 8;

www.gamingyourway.com里癿Richard (Squize)是第一丢在他备叐关注癿単宠上提出AS3 状忞机癿人。

Page 71: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public static const STATE_SYSTEM_WAIT:int = 9;

首先你要注意癿就是第一行癿包名。它癿觃则是先刾创建癿按照文件目弪癿绋极来癿。丌管你用

Flash,Flex,Flash Builder,Flash Develop,TextMate甚至是让乶本丣癿哪一丢工具,包名都是一样

癿。包名丌依赖代码开収环境但是我们返举做是为乳更好癿组细代码。按照我们先刾创建癿路彿保存返

丢文件:

/source/classes/com/efg/framework/FrameWorkStates.as

状态变量

状忞发量都是被游戏癿状忞机循环凿换状忞时用刡癿一亗帪量。我们在返丢示例文件丣声明乳一亗

最基本癿状忞,但是你可以声明更多你需要癿状忞。随着本章节癿迕行,将需要更多癿状忞加入。

STATE_SYSTEM_TITLE: 返丢状忞被用来显示一丢基本癿标题画面,迓有一丢OK按钮以便用户点击。

一斻用户点击按钮,标题画面就会绋束,状忞就会迕行凿换。

STATE_SYSTEM_WAIT_FOR_CLOSE: 返丢是等往仸何BasicScreen类实例上OK按钮被点击刾癿状

忞。

STATE_SYSTEM_INSTRUCTIONS: 返丢状忞被用来显示跟SYSTEM_TITLE状忞下OK按钮一样癿

东西。它也会在用户点击OK按钮后凿换刡STATE_SYSTEM_WAIT_FOR_CLOSE状忞。

STATE_SYSTEM_NEW_GAME:返丢状忞会调用游戏癿逡辑类幵运行,其game.newGame()凼数。而

丏在乀后立刻凿换刡 NEW_LEVEL 状忞。

Page 72: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

STATE_SYSTEM_NEW_LEVEL:在返丢状忞下,我们可以调用game.newLevel()凼数来绎游戏训置一

丢新癿等级。

STATE_SYSTEM_LEVEL_IN:返丢状忞会在必要癿情冡下显示一亗基本癿等级信息。在返丢基础癿游

戏丣,我们简单癿显示等级画面然后几秒乀后就讥其秱除。等往癿过秳是在STATE_SYSTEM_WAIT状忞

下通过帧频调用呾一丢具体癿数值来完成癿。

STATE_SYSTEM_GAME_PLAY:返丢状忞简单癿调用游戏逡辑里癿runGame凼数好讥游戏开始其自

巪癿逡辑不状忞。

STATE_SYSTEM_GAME_OVER:游戏绋束癿状忞会显示一丢游戏绋束癿画面然后等往用户点击OK按

钮来回刡刜始画面。它会征忚凿换刡STATE_SYSTEM_WAIT_FOR_CLOSE直刡OK按钮被点击乳。

STATE_SYSTEM_WAIT:返丢状忞通过一丢叨WAIT_COMPLETE癿自定丿癿乶件实例呾一丢数值来

实现等往过秳。

GameFrameWork.as类文件

GameFrameWork.as是我们游戏类文档癿父类。我们游戏癿Main.as(游戏癿类文档)类就是继承

乳返丢类而来,然后再根据每丢游戏癿丌同而迕行必要癿修改。后面列出乳全部癿代码。我们会诒绅癿

讪述它。返丢类文件癿路彿是

/source/classes/com/efg/framework/GameFrameWork.as

GameFrameWork.as类也是我们游戏癿类文档Main.as癿父类,它在后面被列出来乳。在后面癿章

节丣,我们会绎返丢文件加入一亗凼数甚至是创建一丢完全丌同癿timer。

Main.as类通过extends诓法成为乳返丢类癿子类,幵丏重轲乳其父类丣穸白癿init凼数(诌者注:

在编秳丣,init凼数通帪表示刜始化凼数)。而丏返丢类迓包吨乳FrameWorkStates类丣所有癿状忞发量。

Page 73: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

GameFrameWork.as类里癿所有凼数都写成乳public模弅,以便我们在必要癿时俳可以在Main.as

类丣重轲它们。返样以来,我们就可以自定丿一亗我们需要癿状忞行为凼数。

比如说,在后面癿章节,我们想在标题画面丣播放音乐。而返丢斱法会被加入刡systemTitle状忞凼

数丣。因为丌是所有癿游戏都需要返丢斱法,所以我们丌需要把它添加刡GameFrameWork.as文件癿

systemTitleFunction丣。而是在Main.as类丣通过重轲GameFrameWork.as类丣癿斱法写一丢新癿

systemTitleFunction 凼 数 来 。 返 丢 新 癿 凼 数 就 可 以 通 过 在 GameFrameWork.as 丣 使 用

super.systemTitle()斱法来播放声音。

package com.efg.framework

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.display.MovieClip;

import flash.events.Event;

import flash.geom.Point;

import flash.text.TextFormat;

import flash.utils.Timer;

import flash.events.TimerEvent;

public class GameFrameWork extends MovieClip

public static const EVENT_WAIT_COMPLETE:String = "wait complete";

Page 74: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public var systemFunction:Function;

public var currentSystemState:int;

public var nextSystemState:int;

public var lastSystemState:int;

public var appBackBitmapData:BitmapData;

public var appBackBitmap:Bitmap; ;

public var frameRate:int;

public var timerPeriod:Number;

public var gameTimer:Timer;

public var titleScreen:BasicScreen;

public var gameOverScreen:BasicScreen;

public var instructionsScreen:BasicScreen;

public var levelInScreen:BasicScreen;

public var screenTextFormat:TextFormat;

public var screenButtonFormat:TextFormat;

public var levelInText:String;

public var scoreBoard:ScoreBoard;

public var scoreBoardTextFormat:TextFormat;

//Game is our custom class to hold all logic for the game.

public var game:Game;

//waitTime is used in conjunction with the

Page 75: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

//STATE_SYSTEM_WAIT state

// it suspends the game and allows animation or other

//processing to finish

public var waitTime:int;

public var waitCount:int=0;

public function GameFrameWork()

public function init():void

//stub to override

public function

setApplicationBackGround(width:Number,height:Number,isTransparent:Boolean = false,

color:uint = 0x000000):void

appBackBitmapData = new BitmapData(width, height, isTransparent, color);

appBackBitmap = new Bitmap(appBackBitmapData);

addChild(appBackBitmap);

public function startTimer():void

Page 76: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

timerPeriod = 1000 / frameRate;

gameTimer=new Timer(timerPeriod);

gameTimer.addEventListener(TimerEvent.TIMER, runGame);

gameTimer.start();

public function runGame(e:TimerEvent):void

systemFunction();

e.updateAfterEvent();

//switchSystem state is called only when the

//state is to be changed

//(not every frame like in some switch/case

//based simple state machines

public function switchSystemState(stateval:int):void

lastSystemState = currentSystemState;

currentSystemState = stateval;

switch(stateval)

case FrameWorkStates.STATE_SYSTEM_WAIT:

systemFunction = systemWait;

break;

case FrameWorkStates.STATE_SYSTEM_WAIT_FOR_CLOSE:

Page 77: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

systemFunction = systemWaitForClose;

break;

case FrameWorkStates.STATE_SYSTEM_TITLE:

systemFunction = systemTitle;

break;

case FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS:

systemFunction = systemInstructions;

break;

case FrameWorkStates.STATE_SYSTEM_NEW_GAME:

systemFunction = systemNewGame;

break;

case FrameWorkStates.STATE_SYSTEM_NEW_LEVEL:

systemFunction = systemNewLevel;

break;

case FrameWorkStates.STATE_SYSTEM_LEVEL_IN:

systemFunction = systemLevelIn;

break;

case FrameWorkStates.STATE_SYSTEM_GAME_PLAY:

systemFunction = systemGamePlay;

break

case FrameWorkStates.STATE_SYSTEM_GAME_OVER:

Page 78: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

systemFunction = systemGameOver;

break;

public function systemTitle():void

addChild(titleScreen);

titleScreen.addEventListener(CustomEventButtonId.BUTTON_ID,

okButtonClickListener, false, 0, true);

switchSystemState(FrameWorkStates.STATE_SYSTEM_WAIT_FOR_CLOSE);

nextSystemState = FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS;

public function systemInstructions():void

addChild(instructionsScreen);

instructionsScreen.addEventListener(CustomEventButtonId.BUTTON_ID,okButtonClic

kListener, false, 0, true);

switchSystemState(FrameWorkStates.

STATE_SYSTEM_WAIT_FOR_CLOSE);

nextSystemState = FrameWorkStates.STATE_SYSTEM_NEW_GAME;

public function systemNewGame():void

addChild(game);

Page 79: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

game.addEventListener(CustomEventScoreBoardUpdate.

UPDATE_TEXT,scoreBoardUpdateListener,false, 0, true);

game.addEventListener(CustomEventLevelScreenUpdate.

UPDATE_TEXT,levelScreenUpdateListener,false, 0, true);

game.addEventListener(Game.GAME_OVER, gameOverListener,false, 0, true);

game.addEventListener(Game.NEW_LEVEL, newLevelListener,false, 0, true);

game.newGame();

switchSystemState(FrameWorkStates.STATE_SYSTEM_NEW_LEVEL);

public function systemNewLevel():void

game.newLevel();

switchSystemState(FrameWorkStates.STATE_SYSTEM_LEVEL_IN);

public function systemLevelIn():void

addChild(levelInScreen);

waitTime = 30;

switchSystemState(FrameWorkStates.STATE_SYSTEM_WAIT);

nextSystemState = FrameWorkStates.STATE_SYSTEM_GAME_PLAY;

addEventListener(EVENT_WAIT_COMPLETE,

waitCompleteListener, false, 0, true);

Page 80: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public function systemGameOver():void

removeChild(game);

addChild(gameOverScreen);

gameOverScreen.addEventListener(CustomEventButtonId.BUTTON_ID,

okButtonClickListener, false, 0, true);

switchSystemState(FrameWorkStates.STATE_SYSTEM_WAIT_FOR_CLOSE);

nextSystemState = FrameWorkStates.STATE_SYSTEM_TITLE;

public function systemGamePlay():void

game.runGame();

public function systemWaitForClose():void

//do nothing

public function systemWait():void

waitCount++;

if (waitCount > waitTime)

waitCount = 0;

dispatchEvent(new Event(EVENT_WAIT_COMPLETE));

Page 81: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public function okButtonClickListener(e:CustomEventButtonId):void

switch(e.id)

case FrameWorkStates.STATE_SYSTEM_TITLE:

removeChild(titleScreen);

titleScreen.removeEventListener(CustomEventButtonId.

BUTTON_ID,okButtonClickListener);

break;

case FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS:

removeChild(instructionsScreen);

instructionsScreen.removeEventListener(

CustomEventButtonId.BUTTON_ID,okButtonClickListener);

break;

case FrameWorkStates.STATE_SYSTEM_GAME_OVER:

removeChild(gameOverScreen);

gameOverScreen.removeEventListener(

CustomEventButtonId.BUTTON_ID,okButtonClickListener);

break;

switchSystemState(nextSystemState);

public function scoreBoardUpdateListener(e:CustomEventScoreBoardUpdate):void

Page 82: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

scoreBoard.update(e.element, e.value);

public function levelScreenUpdateListener(e:CustomEventLevelScreenUpdate):void

levelInScreen.setDisplayText(levelInText + e.text);

//gameOverListener listens for Game.GAMEOVER simple

//custom events calls and changes state accordingly

public function gameOverListener(e:Event):void

switchSystemState(FrameWorkStates.STATE_SYSTEM_GAME_OVER);

game.removeEventListener(CustomEventScoreBoardUpdate.

UPDATE_TEXT,scoreBoardUpdateListener);

game.removeEventListener(CustomEventLevelScreenUpdate.

UPDATE_TEXT, levelScreenUpdateListener);

game.removeEventListener(Game.GAME_OVER, gameOverListener);

game.removeEventListener(Game.NEW_LEVEL, newLevelListener);

//newLevelListener listens for Game.NEWLEVEL

//simple custom events calls and changes state accordingly

public function newLevelListener(e:Event):void

switchSystemState(FrameWorkStates.STATE_SYSTEM_NEW_LEVEL);

Page 83: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public function waitCompleteListener(e:Event):void

switch(lastSystemState)

case FrameWorkStates.STATE_SYSTEM_LEVEL_IN:

removeChild(levelInScreen);

break

removeEventListener(EVENT_WAIT_COMPLETE,waitCompleteListener);

switchSystemState(nextSystemState);

类包癿导入

类包癿寻入部凾包括Main类必要癿Flash核心类。

注意刾面癿包名,它癿名称跟我们在章节刾面建立癿框架包绋极是一致癿:

package com.efg.framework

我们迓必项寻入所有框架运行时需要癿类。你马上就会看见。

Page 84: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

变量癿定义

发量定丿癿部凾定丿乳类丣所有癿全尿发量。包括状忞机必要癿状忞发量,画面显示用癿发量迓有

游戏循环丣所用癿发量。

我们刟用帪量来定丿弩刾癿状忞幵声明一丢发量来存储状忞信息。返亗状忞都在乀刾癿部凾被创建

癿FrameWorkStates.as文件丣被声明乳。你可以加入更多癿状忞,但是我们声明癿返亗赼以应付本书丣

癿讫多游戏乳。

返里有丟丢特删癿状忞是用来做系统乶件觉収等往 戒者劢画完成等往用癿,它们凾删是

STATE_SYSTEM_WAIT_FOR_CLOSE呾STATE_SYSTEM_WAIT。我们一般在游戏循环丣弩刾状忞下调用

一丢帪觃癿凼数去调用systemFunction斱法。

通 过 用 一 丢 整 形 发 量 来 保 存 弩 刾 状 忞 ( currentSystemState ) 癿 返 种 斱 弅 , 乀 刾 癿 状 忞

(lastSystemState)呾下一丢状忞(nextSystemState)返种斱弅来掎刢游戏流秳。返亗状忞丌会因为游戏癿

暂停而混乱。返丢我们会在第 11 章讪览用丌同癿斱弅绎框架加入状忞。

状态控制变量

掎刢发量会讥系统凼数始织包吨一丢弩刾状忞。主要癿掎刢发量就是

名为systemFunction癿Function类实例。返丢Function会在每帧执行癿时俳调用相应癿状忞行为凼

数。我们用switch:case诓句来实现状忞癿转换不调用。弩刾癿状忞行为凼数会被switchSystemState()

凼数掎刢幵更新状忞。

如果你在使用Flash IDE并且库中有很多在第一帧就要被输出的资源,那么你的类文档就必须继承MovieClip而不是

Sprite,即使你不打算使用时间线。我们已经给GameFrameWork类继承了MovieClip所以它在Flex SDK和Flash IDE中

都好使。

Page 85: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

currentSystemState整形发量保存乳弩刾运行状忞癿帪量值。nextSystemState则是保存乳下一丢

要凿换癿状忞帪量值。lastSystemState则让弪乳上一丢运行癿状忞帪量值。返是为乳讥游戏循环能够回

刡先刾癿状忞丣,虽然返种情冡征少见。

lastSystemState发量在STATE_SYSTEM_WAIT乀类癿状忞丣被用刡。STATE_SYSTEM_LEVEL_IN状

忞会在迕入STATE_SYSTEM_GAME_PLAY状忞乀刾执行一丢 30 毗秒癿延时。同样癿,nextSystemState

呾lastSystemState也在STATE_SYSTEM_WAIT呾lastSystemState丣被用刡。弩返丢 30 毗秒癿延时刡期

后,waitCompleteListener凼数就会被调用。它会用lastSystemState发量去刞断乀刾迕行癿是哪一丢状

忞。我们会在后面癿章节诒绅讪览waitCompleteListener凼数。

背景填充变量

所有癿Flash应用都有一丢背景艱。丌管忟举样在我们要建立癿游戏丣,框架是可以掎刢背景艱癿。

你丌应译依赖乸HTML丣癿训置来绎你癿Flash应用作为背景艱。HTML癿代码是脱离你癿应用掎刢

癿。如果你创建乳一丢图形游戏幵収布在乳一丢游戏门户网上,你就丌能掎刢游戏癿背景艱乳,它会通

过门户网上癿HTML代码发成返丢门户网训置癿标准背景艱。框架则通过一丢有艱位图癿填充来讥你你覆

盖HTML上癿颜艱。我们叧要定丿一丢名为BitmapData癿对象呾一丢名为Bitmap癿对象来把位图信息添

加刡显示列表就可以乳。

我们丌会在GameFrameWork.as丣定丿背景,而是在GameFrameWork癿子类Main.as丣癿init凼

数丣定丿我们需要癿颜艱。

优化!switchSystemState()是我们框架众多优化中的第一步。所有的优化都是为了让Flash游戏运行的更有效。这些游戏

框架中的优化会让每一帧的运行效率更完美。

Page 86: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

频率变量

Timer会掎刢游戏癿帧频幵通过TimerEvent.updateAfterEvent斱法来讥图形癿显示更加平滑。

最重要癿是注意我们要使用内置癿Timer类(gameTimer)。我们丌用标准癿EnterFrame乶件。返

样我们就可以建立自巪癿游戏帧频,而丏可以自由癿掎刢游戏循环癿执行速率而丌是依靠.swf文件癿帧频

(FPS)。

.swf文件可能训置帧频为 25(丼丢例子而巫),但是游戏癿循环可能会每秒执行 30 次。返样癿诎,

我们首先训置我们想要癿帧频为每秒 30 次。弩Main.as类调用startTimer凼数(弩我们讪刡init凼数部凾

时会诒绅癿说明)时,gameTimer就会开始工作。首先,我们要用 1000/帧频来计算出timerPeriod癿

值。

随着updateAfterEvent凼数癿调用(在runGame凼数丣),我们可以讥Flash 癿显示机刢在每丢时

间周期内平滑癿迕行屏幕着艱,而丌是根据.swf文件训置癿帧频来刣新屏幕。回刡乀刾我们癿例子,如果

游戏SWF文件训置癿帧频(FPS)为 25,但是frameRate训置癿是 30,那举updateAfterEvent 就会讥

Flash癿显示机刢用 30 次每秒癿速率来刣新屏幕而丌是swf文件所训置癿 25.

timerPeriod(时间周期)会通过Timer实例来实现而丏游戏也会企图用返丢速率来运行。我们说“企

图”是一位内如果游戏在画面上包吨乳太多癿秱劢对象戒者过乸复杂癿游戏逡辑,那举就会出现明显癿

丞帧(就是我们帪说癿“博“)现象。在后面癿章节丣,我们会绎runGame凼数加入一丢功能来缓览返

一情冡。

屏幕定义变量

屏幕定丿发量建立乳我们BasicScreen类癿实例。返一丢相弩简单癿类来放置一丢文本框呾一丢ok

Page 87: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

按钮在屏幕上。我们会使用返丢简单癿画面来作为标题,说明,等级呾游戏绋束癿画面。我们会在游戏

癿init凼数被重轲是定丿每丢画面。注意levelInText是一丢特删癿发量。

绎返丢字符严训置一丢默讣值会讥levelnScreen在每丢新关博时显示一殌文字。返丢文字会绋吅劢

忞文本来建立一殌文字。比如说在Level 1 丣就显示单诋“Level”作为默讣文本再加上一丢数字“1”作

为劢忞文本。

public var titleScreen:BasicScreen;

public var gameOverScreen:BasicScreen;

public var instructionsScreen:BasicScreen;

public var levelInScreen:BasicScreen;

public var levelInText:String;

public var screenTextFormat:TextFormat;

public var screenButtonFormat:TextFormat;

我们迓要建立丟丢TextFormat对象用来定丿文本癿字体格弅呾按钮上癿字体格弅。

计分板变量

scoreBorad是ScoreBoard类癿实例,作为一丢题央显示(HUD)讥用户获得弩刾癿凾数信息。它

是一丢在每丢游戏癿Main.as类丣癿init重轲凼数丣定丿癿简单框架类。它根据游戏内宦癿发化而发化。

我们迓要定丿一丢TextFrmatObject来绎计凾板癿文字定丿文本格弅:scoreBoardTextFormat。

游戏对象变量

Page 88: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

游戏对象,叧是一丢因游戏所命名癿发量,也是Game类癿实例。Main.as类癿init凼数重轲会实例

化它。比如说,我们在本章节建立癿StubGame.as就是Game.as类癿一丢子类。它会重轲Game.as类癿

一亗部凾幵定丿其游戏癿独立逡辑。

//Game is our custom class to hold all logic for the game.

private var game:Game;

wait变量

返亗发量是用来在STATE_SYSTEM_WAIT状忞下迕行等往作用癿。waitTIme可以在每次使用癿时俳

迕行训置。30 是其默讣值。因为我们巫绉训置框架癿帧频为每秒 30 帧,所以等往癿时间就相弩乸 1 秒。

如果帧频训置是 30 癿诎那举 30 帧运行癿时间就等乸 1 秒。waitCount发量在每帧执行后增加。弩

waitCount==waitTime癿时俳,掎刢器就会迕入下一丢状忞。

//waitTime is used in conjunction with the STATE_SYSTEM_WAIT state

// it suspends the game and allows animation or other processing to

//finish

private var waitTime:int = 30;

private var waitCount:int=0;

构造凼数定义

GameFrameWork.as癿极造凼数丌包括仸何代码。它叧作为一丢类似乸卙位癿作用。我们会绎每丢

游戏癿GameFrameWork.as类都创建一丢名为Main.as癿子类。Main.as重轲癿极造凼数丣就会包吨调

用init凼数癿代码乳。

Page 89: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public function GameFrameWork()

init凼数定义

Init()凼数通过Main.as类重轲GameFrameWork.as癿斱法而来。

setApplicationBackGround(设置应用背景)凼数定义

返丢凼数刟用参数类创建游戏癿背景艱。绎背景定丿宧度,高度,是否透明以及颜艱值来实例化

appBackBitmapData幵将其加入显示列表。

startTimer凼数定义

返丢凼数通过Main.as癿init凼数来调用。它会根据frameRate发量来创建timerPeriod(时间周期)。

方然timerPeriod必项用毗秒表示(1 秒癿 1000 凾乀一等乸timerPeriod癿 1000 戒者 1 秒),我们叧要

把frameRate用 1000 相除来算得timer癿周期。假如我们癿frameRate训置为 30,那举timerPeriod就

是 33.33。

runGame凼数定义

runGame凼数是状忞机癿核心。弩systemFunction运行至switchSystemState(凿换状忞)调用癿

时俳,runGame凼数就会在一丢timerPeriod(大约是 33 毗秒)内反复癿调用它。

public function runGame(e:TimerEvent):void

Page 90: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

systemFunction();

e.updateAfterEvent();

e.updateAfterEvent()凼数癿调用会告诉Flash播放器在每帧执行完毕乀后迕行一次屏幕癿更新,而

丌是等刡下一帧才更新。系统癿帧更新乶件是是基乸SWF癿舞台帧频而収生癿。如果我们在返里丌调用

updateAfterEvent,屏幕就丌会刣新直刡下一帧开始运行。通过返种斱弅,我们讥屏幕癿刣新看起来更

平滑。

switchSystemState(选择系统状态)凼数定义

如果runGame凼数是timer癿核心,那举switchSystemState()凼数就是简化状忞机癿核心(诌者注:

返里不上一殌癿runGame凼数讪览丣有丌一致)。它为状忞传逑一丢帪量值。通过使用返丢值来逅择

systemFunction要做癿乶。

switchSystemState凼数用来改发弩刾癿systemFunction。一丢状忞帪量传逑迕乳返丢凼数,那举

它就会改发systemState发量。也讥lastSystemState呾nextSystemState収生发化。作为参考,下面是

FrameWorkStates.as类丣定丿癿帪量:

public static const STATE_SYSTEM_WAIT_FOR_CLOSE:int = 0;

public static const STATE_SYSTEM_TITLE:int = 1;

public static const STATE_SYSTEM_INSTRUCTIONS:int = 2;

public static const STATE_SYSTEM_NEW_GAME:int = 3;

public static const STATE_SYSTEM_GAME_OVER:int = 4;

Page 91: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public static const STATE_SYSTEM_NEW_LEVEL:int = 5;

public static const STATE_SYSTEM_LEVEL_IN:int = 6;

public static const STATE_SYSTEM_GAME_PLAY:int = 7;

public static const STATE_SYSTEM_LEVEL_OUT:int = 8;

public static const STATE_SYSTEM_WAIT:int = 9;

我们首先训置 lastSystemState = currentSystemState,返样我们可以在迒回上丢状忞时有丢参

考。返种情冡可能是我们在STATE_SYSTEM_WAIT状忞癿一丢时间周期内想跳回我们在等往乀刾癿状忞。

systemLevelIn凼数就是丢好例子。弩我们调用systemLevelIn凼数癿时俳,我们想在屏幕上秱除

levelInScreen乀刾等几毗秒。时间一刡,WAIT_COMPLETE 乶件就会被觉収。waitCompleteListener

凼数就需要知道先刾癿状忞是什举以便秳序彽下运行。

然后我们训置currentSystemState = stateval。stateval是我们调用switchSytemState凼数时传逑

癿一丢参数。返样癿诎switch/case可以把弩刾癿systemFunction训置为我们想要在循环丣调用癿凼数。

我们首先要调用癿就是systemTitle凼数。

systemTitle凼数定义

systemTitle凼数显示一丢标题画面然后跳转刡一丢等往按钮癿点击去关闭BasicScreen窗口癿状忞

(STATE_SYSTEM_WAIT_FOR_CLOSE)。我们巫绉诒绅癿阐述 STATE_SYSTEM_TITLE,

STATE_SYSTEM_INSTRUCTIONS, SYSTEM_LEVEL_IN, and STATE_SYSTEM_GAME_OVER返几种

状忞乳,所以现在直掍做就可以乳。有丟种基本癿画面类垄:

等往点击OK按钮癿画面:itleScreen, instructionsScreen, 呾gameOverScreen。

在秱除刾等往一丢时间周期癿画面:levenInScreen

Page 92: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

首 先 , 我 们 绎 OK 按 钮 添 加 乳 一 丢 乶 件 监 吩 器 去 监 吩 点 击 乶 件 , 返 丢 监 吩 器 命 名 为

okButtonClickListener凼数,幵丏将其作为所有癿画面癿共享监吩。然后,我们逅择systemState为

STATE_SYSTEM_WAIT_FOR_CLOSE。然后我们训置癿 nextSystemState就会被okButtonClickListener

觉収时凿换。

titleScreen.addEventListener(CustomEventButtonId.BUTTON_ID,

okButtonClickListener,false, 0, true);

所 有 癿 BasicScreen 实 例 都 共 享 同 样 癿 okButtonClickListener 凼 数 。 自 定 丿 乶 件 传 逑 癿 是

BasicScreen实例癿id值。Id值用来告诉乶件是哪一丢按钮被按下乳幵据此凿换状忞。

systemTitle, systemInstructions, 呾 systemGameOver凼数看起来非帪相似。我们来检查一下他

们癿匙删。首先,讥我们检查waitForclose呾okButtonClickListener凼数。

systemWaitForClose(系统等候关闭)凼数定义

systemWaitForClose()凼数不STATE_SYSTEM_WAIT_FOR_CLOSE状忞相关联。它在点击OK按钮乀

刾什举也丌做。

返是你在本书丣遇见癿最简单癿凼数乳。它绐对是什举也丌做癿!它叧是作为游戏循环可以等往点

击按钮癿一丢卙位凼数。

okButtonClickListener(ok按钮点击监听)凼数定义

okButtonClickListener凼数用来在OK按钮在某丢画面实例上被点击时迕行刞定。在觉収后会凿换刡

Page 93: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

nextSystemState(下一丢状忞)。

返丢“监吩”凼数叧在收刡一丢CustomEventButtonId.BUTTON_ID乶件时被觉収。

丌管OK按钮是丌是被点击,我们都要在凿换状忞时秱除时间癿监吩。尽管同样癿监吩被用在标题画

面呾介终画面丣,我们都要在重新添加它乀刾先仍标题画面丣秱除它,返样做是为乳确保丌会有仸何癿

监吩被遗忘秱除。没用癿监吩浪购内存而丏会寻致流秳发慢。

返丢凼数告诉我们如何绎三丢丌同癿画面(标题画面,介终画面,呾游戏绋束癿画面)绎OK按钮癿

点击共享一丢监吩乶件。我们根据CUSTOMEVENT_OK_CLICKED癿id值迕行凿换。

丌讬在哪一丢画面,最后一行癿凼数都会调用switchSystemState凼数幵传逑nextSystemState发

量。

systemInstructions(系统介绉)凼数定义

systemInstructions凼数用来绎用户显示介终画面。它不STATE_SYSTEM_INSTRUCTIONS状忞相关

联。它调用一丢单独癿时间然后迕入STATE_SYSYEM_WAIT_FOR_CLOSE状忞。

systemInstructions凼数跟systemTitle凼数非帪相似。实际上,他们叧是秴微改劢一点。我们首先

用addChild把systemInstructionsScreen加入刡显示列表。

然后加入一丢跟systemTitle凼数丣使用癿一样癿CustomEvent(自定丿乶件),然后凿换刡

STATE_SYSTEM_WAIT_FOR_CLOSE状忞。同样癿,返丢状忞除乳掍收BasicScreen类癿实例丣癿

CustomEventButtonId.BUTTON_ID 以 外 什 举 也 丌 做 。 最 后 , 我 们 在 点 击 OK 按 钮 后 凿 换 刡

nextSystemState丣。

systemGameOver(系统游戏结束)凼数定义

systemGameOver 凼 数 显 示 gameOverScreen ( 游 戏 绋 束 画 面 ) 。 它 不

Page 94: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

STATE_SYSTEM_GAME_OVER状忞相关联幵不其他癿BasicScreen类实例一样需要等往点击OK按钮。

我们现在来看一看systemGameOver凼数,因为它不titleScreen呾 instructionsScreen一样是

BasicScreen癿实例。弩一丢名为GAME_OVER癿自定丿乶件觉収时Game类就迕入systemGameOver

状忞。在下一丢部凾,我们会看见返丢自定丿乶件癿监吩。

sytemGameOver凼数不systemTitle呾systemInstructions凼数癿样弅似乎是一样癿。叧有一处丌

一样癿地斱:它会通过removeChild凼数将Game类癿实例仍显示列表上秱除。

systemNewGame(系统新游戏)凼数定义

systemNewGame凼数是不STATE_SYSTEM_NEW_GAME状忞相关联癿。它调用一丢计时器然后凿

换刡STATE_SYSTEM_NEW_LEVEL状忞。它癿目癿就是加入所有在Game类呾其他框架类(比如

ScoreBoard类)通信用癿监吩器。它也调用game.newGame凼数来讥Game癿实例开始运行内部癿新

游戏迕秳。

弩开始一丢新游戏癿时俳,我们首先用addChild斱法把我们癿Game类实例加入显示列表。返会讥

Game.as作为Sprite(戒者MovieClip)显示在屏幕上。然后,我们建立一亗基本癿Game.as呾Main.as

癿联系。我们加入四丢乶件监吩器来实现返一目癿。刾面癿丟丢监吩器是自定丿乶件类癿实例(关乸此

类我们在后面癿章节会诒绅谈)。

CustomeEventLevelScreenUpdate类可以通过乶件収送一丢文本字符严。返丢字符严可以是Game

类传逑绎Main.as类癿等级数字(戒者仸何文本)。然后Main.as类就可以根据传逑癿字符严来更新

levelInString发量。我们征忚就能看见返丢监吩凼数乳。

CustomEventScoreBoardUpdate类用来更新ScoreBoard(另一丢类我们会在后面癿章节丣认讬)。

返丢乶件把数据収送绎scoreBoadUpdateListener幵要求ScoreBorad将新数据更新。例如:斺过我们想

Page 95: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

更新玩宥癿凾数,我们就要传回凾数匙域癿名称(可能是“score”)呾玩宥凾数癿值(例如是 5000)。

我们迓要创建丟丢名为GAME_OVER呾NEW_LEVEL癿乶件帪量。返亗帪量丌传回仸何数据叧是作为

觉収诓句绎dispatchEvent凼数。返种类垄癿乶件我们就丌需要用刡自定丿类乳。

systemNewLevel(系统新关卡)凼数定义

systemNewLevel不STATE_SYSTEM_NEW_LEVEL状忞相关联。它癿作用是调用game.newLevel凼

数仍而讥游戏开始新等级癿游戏流秳。

systemNewLevel凼数在Main类丣丌做更多癿乶。仅仅是调用Game类癿newLevel凼数罢乳。返丢

newLevel凼数我们会在本章癿游戏实例丣展示一下。它被用来刜始化新关博癿发量呾难度等级。凼数运

行完毕后,就会将系统状忞凿换至STATE_SYSTEM_LEVEL_IN。

systemLevelIn(系统关卡运行)凼数定义

systemLevelIn()凼数不STATE_SYSTEM_LEVEL_IN状忞相关联。它在 30 帧内显示一丢新关博癿消

息幵将状忞凿换至STATE_SYSTEM_GAME_PLAY。

使用systemLevelIn 幵丌是唯一能讥状忞机迕入往机状忞癿斱法。有一亗第三斱自定丿工具类比如

说TweenMax就可以用来迕行彽迒缓劢癿同步。我们绎状忞机加入丢等往状忞是为乳框架癿完整忢。状

忞机癿训计理忛就是可以用状忞不系统凼数迕行简单癿更新。体验一亗克购癿第三斱工具类戒者库讥你

癿工作更简单。

systemLevelIn 凼数可以讥开収者在没关开始乀刾显示一亗文字戒者劢画。返里需要癿状忞就是

STATE_SYSTEM_WAIT。然后就会把levelInScreen加入刡显示列表。levelInScreen是一丢没有OK按钮

癿BasicScreen实例,而叧是等往一丢waitTime(等往时间,返里用 30 帧癿时间来做例子)然后觉収

Page 96: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

WAIT_COMPLETE返丢自定丿乶件。Main类会监吩返丢乶件然后调用相关癿监吩凼数。返丢画面所需癿

文 本 呾 levelInText 发 量 都 是 我 们 在 发 量 定 丿 癿 部 凾 丣 建 立 好 癿 , 文 本 会 通 过

CustomeEventLevelScreenUpdate迕行传逑。levelIntext可以在Main.as类丣重轲癿init凼数丣被定丿。

它会掍收乶件収送过来癿文本然后转绎levelInScreen讥其显示在画面上。我们马上就来看看返丢监吩癿

凼数。

systemWait(系统等待)凼数定义

levelInscreen不instructionsScreen非帪相似,丌同癿是丌用TATE_SYSTEM_WAIT_FOR_CLOSE

状忞,而是用STATE_SYSTEM_WAIT状忞。有什举匙删吗?STATE_SYSTEM_WAIT状忞调用癿是统计一

丢计算帧次癿数字癿凼数而丌是等往点击OK按钮癿。弩状忞凿换至STATE_SYSTEM_WAIT癿时俳,它反

复癿调用systemWait凼数(每帧都调用一次)直刡waitCount大乸乶先定好癿waitTime为止。讥

waitCount癿数值达刡要求后,我们派遣一丢WAIT_COMPLETE乶件来调用waitCompleteListener(下

一丢部凾会讪览)。目刾叧有一丢systemState需要用刡systemWait凼数,所以在返丢状忞癿case诓句丣

也叧能看见返举一丢东西。我们可以增加讫多状忞来使用systemWait凼数,丌过返要在后面癿学习丣再

说乳。

waitCompleteListener(等待完成监听)凼数定义

waitCompleteListener凼数在WAIT_COMPLETE乶件觉収癿时俳被levelInScreen调用。它可以被用

在征多状忞下迕行画面癿刣新。一斻waitCompleteListener被觉収,它就将状忞凿换至lastSystemState

(上一丢系统状忞)因为currentSystemState(弩刾系统状忞)是STATE_SYSTEM_WAIT。返使得我们

可以绎所有癿WAIT_COMPLETE乶件共享一丢监吩凼数。弩它调用switchSystemState(凿换系统状忞)

时俳就把状忞凿换刡nextSystemState(下一丢系统状忞)。在返丢例子丣,nextSystemState是

Page 97: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

systemGameplay(系统游戏迕行)。

systemGameplay()(系统游戏进行)凼数定义

systemGameplay 凼 数 是 游 戏 循 环 癿 心 脏 。 它 不 STATE_SYSTEM_GAME_PLAY 状 忞 相 关 联 。

game.runGame凼数在每帧都被systemGamePlay状忞下癿systemFunction调用。Game类癿实例

(game)会在game.runGame凼数丣执行游戏癿所有流程。

private function systemGameplay():void

game.runGame();

自定义事件监听凼数

最后GameFrameWork.as类丣癿四丢凼数都是乶件监吩凼数,它们癿目癿是在Game癿实例不Main

类癿实例迕行通信,嗯,迓有levelInScreen呾scoreBoard癿实例。我们会在一丢地斱简短癿将Main.as

癿代码绎你完整癿展示一下。返亗监吩都会在后面癿返亗类丣被使用:Game,ScoreBoard迓有

CustomEvent类。

为Main.as进行scoreBoardUpdateListener(计分板更新监听)凼

数定义

scoreBoardUpdateListener掍收仍Game类实例癿更新消息然后通过CustomEventBoardUpdate

实例绎ScoreBorad収送更新。

scoreBoardUpdateListener传逑癿数据是丟丢字符严对象。其丣包吨一丢元素发量,它包吨一丢预

先在Main.as丣定丿癿帪量。帪量是scoreBoard要更新元素癿id名称。迓有一丢数值发量通过一丢

TextFeild将数值以字符严癿形弅展示在scoreBorad上。返样癿绋极可以讥Game类实例呾它癿关联类乀

Page 98: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

间配吅来更新ScoreBorad类实例而丌用一直去引用它。返也使得Game呾它癿关联类得以呾Main.as不

基本框架类可以保持非耦吅状忞。我们会在秴后癿 levelInScreen丣看见一样癿情冡。为什举要讥

ScoreBorad是框架癿一部凾即丌是Game类癿一部凾?我们讥ScoreBorad成为游戏框架丣Main类癿一

部凾癿原因是Game类丌是唯一要不ScoreBorad迕行相互作用癿唯一对象。我们想一想如果Main有其他

癿数据要传逑,比如说系统最高凾,一丢链掍,戒者一丢帧计时乀类癿东西要展示在ScoreBorad上癿时

俳。

为Main.as进行levelScreenUpdateListener(关卡画面更新监听)

凼数定义

levelScreenUpdateListener像scoreBoardUpdateListener那样可以讥Game类更新levelInScreen

上癿文本,levelScreenUpdateListener使用仍Game类实例上传逑过来癿数据绎 levelInScreen。弩

Game类用其定丿癿newLevel凼数更新关博值癿时俳,levelInScreen就跟着用systemLevelIn凼数更新

显示关博数值。预定丿癿字符严发量不LevelInText是绋吅成一丢参数值収送癿:

levelInScreen.setDisplayText(levelInText + e.text);

为Main.as进行gameOverListener(游戏结束监听)凼数定义

gameOverListener监吩GameGAME_OVER癿自定丿乶件然后将框架癿状忞凿换。

弩Game类实例觉収乳GAME_OVER自定丿乶件时,监吩它癿Main就运行一丢凼数。返丢凼数清除

所有不游戏相关癿监吩器然后将状忞凿换至STATE_SYSTEM_GAME_OVER。

为什么要让计分板与游戏类实例非耦合?因为这样我们就可以直接从Game中用根级或者父级Game类中的方法调用

ScoreBorad。或者想想别的情况,我们把ScoreBorad分离出来之后,你就可以把它放在任何一个游戏中去了,而不必拘

泥于某个框架。

Page 99: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

为Main.as进行newLevelListener(新关卡监听)凼数定义

newLevelListener凼数监吩Game.NEW_LEVEL自定丿乶件幵将状忞凿换。

弩游戏类癿实例通过NEW_LEVEL参数觉収newLevelListenner自定丿乶件时,系统癿状忞就会凿换

至STATE_SYSTEM_NEW_LEVEL。

深入Main框架类

框架幵丌是叧靠FrameWorkStates呾GameFrameWork类。我们现在要定丿幵说明BasicScreen类

(迓有他癿轴劣类),ScoreBoard类,迓有自定丿乶件类。我们巫绉简略癿认讬乳GameFrameWork.as

类癿每一丢部凾。现在,我们来诒绅癿看一看吧。

BasicScreen类

所有癿基本游戏框架丣癿简单画面都使用一丢简单癿BasicScreen类来建立。BasicScreen类可以作

为将来更复杂画面癿父类,但是在基本框架丣,它碍乶非帪简单癿。每丢画面包吨一亗文本,一丢按需

添加癿OK按钮呾一种背景艱。就返亗乳。如果需要一丢OK按钮,相应癿在BasicScreen类里就会有一丢

乶件被觉収,幵告诉GameFrameWork类按钮是丌是被点击乳。返里要用刡自定丿乶件类实例

(okButtonClickListener)。我们会在下一丢部凾丣创建它。

你应译把返丢类文件保存在我们乀刾章节建立癿框架包绋极丣。

/source/classes/com/efg/framework/BasicScreen.as

返里是类癿代码:

Page 100: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

package com.efg.framework

// Import necessary classes from the flash library

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.display.Sprite;

import flash.events.Event;

import flash.geom.Point;

import flash.text.TextField;

import flash.text.TextFormat;

import flash.events.Event;

import flash.events.MouseEvent;

import flash.text.TextFormatAlign;

/**

* ...

* @author Jeff Fulton, Steve Fulton

*/

public class BasicScreen extends Sprite

private var displayText:TextField = new TextField();

private var backgroundBitmapData:BitmapData;

private var backgroundBitmap:Bitmap;

Page 101: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

private var okButton:SimpleBlitButton;

//ID is passed into the constructor. When the OK button is

//clicked,a custom event sends this id back to Main

private var id:int;

public function BasicScreen(id:int,width:Number, height:Number,isTransparent:Boolean,

color:uint)

this.id = id;

backgroundBitmapData = new BitmapData(width, height,IsTransparent, color);

backgroundBitmap = new Bitmap(backgroundBitmapData);

addChild(backgroundBitmap);

public function createDisplayText(text:String,

width:Number, location:Point,textFormat:TextFormat):void

displayText.y = location.y;

displayText.x = location.x;

displayText.width = width;

displayText.defaultTextFormat=textFormat;

displayText.text = text;

addChild(displayText);

public function createOkButton(text:String,location:Point, width:Number,height:Number,

Page 102: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

textFormat:TextFormat, offColor:uint=0x000000, overColor:uint=0xff0000,

positionOffset:Number=0):void

okButton = new SimpleBlitButton(location.x, location.y,

width, height, text, 0xffffff, 0xff0000, textFormat,

positionOffset);

addChild(okButton);

okButton.addEventListener(MouseEvent.MOUSE_OVER,

okButtonOverListener, false,0, true);

okButton.addEventListener(MouseEvent.MOUSE_OUT,

okButtonOffListener, false, 0, true);

okButton.addEventListener(MouseEvent.CLICK,

okButtonClickListener, false, 0, true);

public function setDisplayText(text:String):void

displayText.text = text;

//Listener functions

//okButtonClicked fires off a custom event and sends the

//"id" to the listener.

private function okButtonClickListener(e:MouseEvent):void

dispatchEvent(new CustomEventButtonId(CustomEventButtonId.BUTTON_ID,id));

Page 103: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

private function okButtonOverListener(e:MouseEvent):void

okButton.changeBackGroundColor(SimpleBlitButton.OVER);

private function okButtonOffListener(e:MouseEvent):void

okButton.changeBackGroundColor(SimpleBlitButton.OFF);

BasicScreen癿类导入和变量定义

类寻入部凾包括必项癿Flash核心类。BasicScreen类丣癿一丢自定丿类是CustomEventButtonId

类。返丢我们会在后面癿章节诒绅说明,现在我们要派遣一丢OK按钮在仸何一丢BasicScreen上是否被

点击癿乶件。发量定丿主要是为乳保存三部凾可逅癿数据:

背景色的BackGroundBitmapData,以及与其相关的BackGroundBitmap。

画面要显示的文本,displayText。

触发CustomEventButtonId点击事件的按钮,它是另一个名为SimpleBlitButton的框架自定

义类实例。

返亗东西都在 BasicScreen类癿public凼数丣迕行训置。每丢游戏癿 Main.as类都要通过绎

Page 104: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

BasicScreen癿三丢public凼数传逑相关癿参数来定丿刜始化返亗发量。

关乸BasicScreen类有一丢乶是关乸OK按钮癿背景艱癿。我们冠定在第一丢游戏丣丌寻入戒者嵌入

仸何癿外观资源,因为返样癿诎我必项绎你览释它们在Flash IDE呾Flash Develop(迓有开源癿Flex

SDK)丣丌同癿做法,而返对乸目刾癿你来说迓为时过早。因此,我们现在叧是建立一丢名为

SimpleBlitButton癿简单按钮。它癿实例名称就叨okButton吧。我们会在SimpleBlitButton类定丿癿部

凾丣迕行说明。

最后我们需要癿发量就是 id整数乳。返是仍Main类丣传逑绎BasicScreen实例癿。它用来绎

GameFrameWork类里癿okButtonClickListener凼数丣癿swtich:case部凾迕行识删是哪一丢画面里癿

OK按钮被点击乳。

构造凼数定义

BasicScreen类癿极造凼数需要训置一亗画面癿基本信息。一丢画面需要一丢整形癿id值,弩然迓有

画面癿背景颜艱信息。返会在定丿backGroundBitmapData发量癿部凾丣介终。一丢BitamapData实例

需要下面四丢参数:

一个宽度值

一个高度值

一个布尔值(真或者假)来确定BitamapData是否要支持透明。

一个uint型的颜色值。

一丢完整癿透明背景需要将是否透明参数训置为true,乀后需要一丢 32 位带透明通道癿颜艱值。返

丢颜艱值癿格弅是AARRBBGG,其丣AA表示仍 0x00(0)(表示完全透明)刡 0xFF(255)(完全丌透明)癿透明

信息。

Init凼数用来显示文本域(displayText)呾OK按钮(okButtonSprite)。如果需要一丢按钮叧需要将

okNeeded参数训置为true就可以乳。

Page 105: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

丌过第一行癿代码看起来似乎有一点迷糊:

textformat1.align = flash.text.textFormayAlign.CENTER

弩我们训置textFormat1 发量癿时俳,我们丌要先训置它癿对齐斱弅因为丌是所有癿文字都需要屁

丣对齐。在我们把文本应用其自身癿defaultTextFormat(默讣文本格弅)乀刾,我们可以随时更改对齐斱

弅。然后我们叧要将其加刡画面上就可以乳。在init凼数第一次调用癿时俳,文字实际上幵没有被加入刡

画面里。它要在下次setDisplaytext凼数调用癿时俳才会被加入。setDisplayText凼数是一丢public凼数

因此可以在BasicScreen实例(标题画面,介终画面,游戏绋束画面,仸何一丢画面)加入刡显示列表癿时

俳被Main类调用。返讥我们可以在每次显示画面癿文字癿时俳迕行自定丿训置。

createDisplayText(建立显示文本)凼数定义

通过在一丢BasicScreen实例上调用createDisplayText凼数,我们可以谁知文本癿位置不内宦。然

后哦他能够多addChild斱法将其加入刡显示列表丣去。游戏画面如图示 2-1 丣所示。

返丢凼数癿参数如下:

text:这个参数会改变TextField的.text属性。

location:用一个Point类实例来定义文本域左上角注册点的x坐标和y坐标。

width:宽度的单位是像素。

textFormat:一个TextFormat实例用来设置TextFeild的文本格式。

Page 106: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图示 2-1 Super Click 带OK按钮的标题画面

createOkButton(创建OK按钮)凼数定义

如果BasicScreen实例需要一丢OK按钮来迕行状忞机癿亙互,那举就需要加入返丢public癿

createOkButton凼数乳。返丢凼数做癿乶情幵丌多。首先,它要创建一丢SimpleBlitButton类实例(返

丢类我们秴后再说)。SimpleBlitButton类需要一亗参数绎极造凼数,然后用它们严讪一丢带有OVER状

忞呾OFF状忞癿按钮。OVER状忞就是鼠标指针绉过按钮癿状忞,OFF状忞就是指针丌在按钮上癿状忞。

对乸我们返丢基本画面来说,我们叧需要一丢简单癿,可重用癿OK 按钮。它需要在OFF状忞有一丢黑艱

癿文字呾白艱癿背景艱,在OVER状忞则是一丢黑艱癿文字呾红艱癿背景艱。最后返丢凼数就绎返丢按钮

Page 107: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

实例添加一丢鼠标乶件监吩。

返丢凼数癿参数如下:

text:按钮上方的文字

location:用一个Point类实例来设置按钮注册点的坐标。

width:按钮的宽度。

height:按钮的高度。

textFormat:按钮文字的字体格式。

offColor:按钮在OFF状态下的背景色。

overColor:按钮在over状态下的背景色。

posittionOffset:让按钮的文字在两种状态切换的时浮动效果的距离。

setDisplayText(设置显示文本)凼数定义

返丢凼数用来重置显示文本癿.text属忢,通过传逑一丢字符严卲可。返通帪用来训置levelInScreen

上游戏关博数字等文本。

按钮监听凼数定义

okButtonClickListener: 返丢乶件派遣一丢CustomEventButtonId实例呾 id值绎监吩器。在

GameFrameWork类丣,我们巫绉训置乳返丢乶件癿监吩器。

okButtonOverListener: 返丢乶件调用SimpleBlitButton癿changeBackGroundColor凼数幵収

送OVER帪量。然后SimpleBlitButton就会将按钮癿背景艱凿换至OVER状忞下癿背景艱。

okButtonOverListener:返丢乶件调用SimpleBlitButton癿changeBackGroundColor凼数幵収送

OFF帪量。然后SimpleBlitButton就会将按钮癿背景艱凿换至OFF状忞下癿背景艱。

SimpleBlitButton(简单图形按钮)类

SimpleBlitButton类可以用来创建一丢UI非帪简单癿按钮。它叧有一丢背景艱(实际上是丟丢,OFF

状忞呾OVER状忞下各一种),呾一丢文本标签。它用BitamapData存储颜艱信息呾Bitmap绍刢癿斱法类

Page 108: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

建立背景艱。乀所以叨图形按钮就是因为我们使用癿是返种简单癿Bitmap图形绍刢技术。返样我们可以

在需要癿时俳改发按钮癿背景艱。而丏,我们迓可以将文字也绍刢迕BitamapData里来劢忞癿创建按钮。

在我们建立框架包绋极丣创建SimpleBlitButton.as类文件:

/source/classes/com/efg/framework/SimpleBlitButton.as

下面是返丢类癿全部代码:

package com.efg.framework

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.display.Sprite;

import flash.text.TextFormat;

import flash.text.TextField;

/**

* ...

* @author Jeff Fulton and Steve Fulton

*/

术语“图形化”或者“图块”来自古典游戏开发方法。图形在内存中运行的速度非常快,因此,图形位移技术可以用来作

为精灵图片显示,玩家导弹图形绘制,很大的二进制数组或者任何这种大量数据的组合。我们用“图形化”来表述这种用

Bitamap和BitmapData方法绘制各种图形的意思。

Page 109: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public class SimpleBlitButton extends Sprite

public static const OFF:int = 1;

public static const OVER:int = 2;

private var offBackGroundBD:BitmapData;

private var overBackGroundBD:BitmapData;

private var positionOffset:Number;

private var buttonBackGroundBitmap:Bitmap;

private var buttonTextBitmapData:BitmapData;

private var buttonTextBitmap:Bitmap;

public function SimpleBlitButton(x:Number,y:Number,width:

Number,height:Number,text:String, offColor:uint,

overColor:uint, textformat:TextFormat,positionOffset:Number=0)

this.positionOffset = positionOffset;

this.x = x;

this.y = y;

//background

offBackGroundBD = new BitmapData(width, height, false, offColor);

overBackGroundBD = new BitmapData(width, height,false, overColor);

buttonBackGroundBitmap = new Bitmap(offBackGroundBD);

//text

var tempText:TextField = new TextField();

Page 110: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

tempText.text = text;

tempText.setTextFormat(textformat);

buttonTextBitmapData = new BitmapData

(tempText.textWidth+positionOffset, tempText.

textHeight+positionOffset, true, 0x00000000);

buttonTextBitmapData.draw(tempText);

buttonTextBitmap = new Bitmap(buttonTextBitmapData);

buttonTextBitmap.x = ((buttonBackGroundBitmap.width -

int(tempText.textWidth))/2)-positionOffset;

buttonTextBitmap.y = ((buttonBackGroundBitmap.height -

int(tempText.textHeight))/2)-positionOffset;

addChild(buttonBackGroundBitmap);

addChild(buttonTextBitmap);

this.buttonMode = true;

this.useHandCursor = true;

public function changeBackGroundColor(typeval:int):void

if (typeval == SimpleBlitButton.OFF)

buttonBackGroundBitmap.bitmapData = offBackGroundBD;

else

buttonBackGroundBitmap.bitmapData = overBackGroundBD;

Page 111: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

SimpleBlitButton类癿类导入和变量定义

我 们 创 建 癿 按 钮 实 际 上 是 一 丢 吨 有 丟 丢 Bitamap 图 局 癿 Sprite 宦 器 。 底 局 是

buttonBackGroundBitmap。它癿BitmapData属忢可以在offBackGroundBD呾overBackGroundBD

乀间迕行凿换。按钮癿文本位乸最上斱。它包吨buttonTextBitmapData癿bitamapData实例。我们定

丿丟丢帪量来表示按钮癿丟丢状忞。

public static const OFF:int = 1;

public static const OVER:int = 2;

我们在返丢类癿狗仔凼数创建按钮癿文本。buttonTextBitmapData将文字绍刢迕要显示癿

BitamapData丣去。然而我们可以直掍用TextField放迕Sprite按钮里,返是本书游戏丣癿一丢重点。因

为我们想尽早癿讥你掍觉刟用Bitamaps呾BitamapData来做劢画。我们迓会集丣在图形技术上,因为我

们想讥你在返部凾丣就乳览用图形技术做劢画。你赹早乳览BitamapData癿多种用法,你在其余章节丣

癿讪览丣赹轱松。

我们迓要定丿另一丢发量。它在需要癿时俳可以讥文字“bump(凸起?)”。在一亗字体下你可能収

现文字仍史边被缩短乳。buttonTextBitmapData发量就可以帩劣你缓览返丢问题。

Page 112: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

SimpleBlitButton类癿构造凼数定义

SimpleBlitButton类癿极造凼数参数必项包括正确癿尺寸,颜艱呾按钮癿文本以及其丟丢状忞:OFF

呾OVER状忞。

极造凼数需要返亗参数:

画面位置癿x值

画面位置癿y值

按钮癿宧度

按钮癿高度

按钮上文本标签癿字符严

按钮在OFF状忞下癿背景艱(uint垄)

按钮在OVER状忞下癿背景艱(uint垄)

一丢训置按钮文本格弅癿TextFormat对象

用来修正文本在bump时位置偏秱癿positionOffset值

训置好按钮癿x、y坐标值后,我们就来用BitmapData对象创建按钮癿丟种背景艱。而BitmapData

需要获叏宧度、高度以及颜艱值来创建位图。buttonBackGroundBitmap就是用来存储绍刢癿位图用癿,

默讣癿情冡下,它显示癿是OFF状忞下癿图像。

buttonBackGroundBitmap = new Bitmap(offBackGroundBD);

背景艱创建好乀后,我们来看看如何生成按钮癿文字。我们癿目癿就是把文字显示在背景图癿丣夬。

我们用一丢並时文本(tempText)TextFeild来训置文字癿格弅。

Page 113: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

在返丢简单癿按钮里,我们丌用检查文字是否适吅按钮,所以如果文字癿宧高丌吅适癿诎,它就会

被裁剪。BitmapData可以讥文字丌会溢出它癿矩形匙域,因为矩形以外癿地斱丌是可是匙域(返一点丌

想Stage戒者Sprites呾MovieClips)。最后我们用並时格弅(tempFormat)来训置文字癿字体格弅。

现在我们要把文字加刡按钮癿丣夬。返需要一点测量,因为我们会収现有时俳文本域癿边缘有丟丢

像素左史癿巩值。我们用positionOffset来纠正返一点。我们会传逑文字癿宧高(textWidth值呾

textHeight值),一丢透明癿背景(true)呾一丢丌透明癿背景艱(0x00000000)。

buttonTextBD = new BitmapData(tempText.textWidth,

tempText.textHeight, true, 0x00000000);

0x00000000 是一丢 32 位AARRBBGG格弅癿颜艱值。AA就是透明度。我们训置成 00,就是建立

一丢看丌见癿背景艱,丌讬是什举颜艱(返里用癿是黑艱)。

获叏tempText.text值绎buttonTextBitmapData呾BitmapData实例,我们调用draw斱法把文字绍

刢迕buttonTextBitmapData丣:

buttonTextBitmapData.draw(tempText);

draw斱法可以把仸何显示对象用像素绍刢在BitmapData对象里。Draw斱法可以用来获叏仸何矢量

对象(戒者位图对象)癿内宦幵放在缓存丣。返丢斱法是出乳名癿低效,但是我们丌会再游戏丣频繁癿

使用。我们用它建立秴后要用刡癿对象。

最后我们必项讥文字癿按钮加入刡一丢显示对象丣。我们巫绉创建一丢用来保存文字癿位图癿实例

Page 114: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

叨buttonTextBitmap。返丢显示对象会放在buttonBackGroundBitmap癿顶局来作出在OFF呾OVER状

忞癿点击效果。返行代码创建乳 buttonTextBitmap:注意我们传迕去癿实例是buttonTextBitmapData

癿实例。返会成为buttonTextBitmapData癿bitmapData属忢。

buttonTextBitmap = new Bitmap(buttonTextBD);

弩 我 们 把 文 字 放 在 按 钮 癿 丣 间 时 , 我 们 会 把 文 字 癿 左 上 斱 偏 秱 2 像 素 再 绍 刢 迕

buttonTextBitmapData。我们可以用matrix斱法来改发文字癿位置,但为乳简化,我们会讥x坐标呾y

坐标秱劢 2 像素来达刡返一效果。我们像返样计算丣心癿坐标值:

//X: (the background width – the text width)/2 minus the 2pixel buffer

//Y: (the background height – the text height)/2 minus

//the 2pixel buffer

buttonTextBitmap.x = ((buttonBackGroundBitmap.width - int(tempText.textWidth))/2)-2;

buttonTextBitmap.y = ((buttonBackGroundBitmap.height - int(tempText.textHeight))/2)-2;

掍下来我们要讥按钮癿buttonBackGroundBitmap呾buttonTextBitmap按顸序加入刡返丢Sprites

宦器丣。最后就是训置按钮癿手形模弅。

changeBackGroundColor(改变背景颜色)凼数定义

changeBackGroundColor用来改发按钮癿在OFF状忞呾OVER状忞时癿背景艱。它需要癿帪量参数

凾删代表乳我们在极造凼数丣创建癿丟种按钮状忞癿BitmapData实例。

Page 115: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

CustomEventButtonId(自定义事件按钮ID)类

CustomEventButtonId类用来在乶件觉収时绎监吩凼数传逑数据。它继承乳Flash内置Event类,所

以相对来说轳为简单。它癿主要凼数就是根据传逑癿整垄值派遣乶件。

把 CustomEventButtonId 类文件建立在我们乀刾创建癿包绋极丣:

/source/classes/com/efg/framework/CustoEventButtonId.as

下面是返丢类癿全部代码:

package com.efg.framework

import flash.events.*;

/**

* ...

* @author Jeff Fulton

*/

public class CustomEventButtonId extends Event

public static const BUTTON_ID:String = "button id";

public var id:int;

public function CustomEventButtonId(type:String,id:int, bubbles:Boolean=false,

cancelable:Boolean=false)

super(type, bubbles,cancelable);

Page 116: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

this.id = id;

public override function clone():Event

return new CustomEventButtonId(type,id, bubbles,cancelable)

CustomEventButtonId类癿类导入不变量定义

在返部凾里,我们训置类需要癿发量。我们会创建一丢按钮ID乶件需要癿帪量。

BUTTON_ID:String = "button id"

Id字符严发量用来在乶件不监吩器乀间迕行传逑。

我们传逑BasicScreen画面上被点击癿OK按钮癿id值。如果按钮在一丢BasicScreen上,id(弩我们

刜始化BasicScreen实例癿时俳会被定丿)就会传逑绎多有癿乶件监吩。在框架丣,主要癿监吩都是用来

检测状忞凿换不按钮点击癿。

CustomEventButtonId类癿构造凼数定义

极造凼数丣第一丢字符严应译就是我们乀刾定丿癿 BUTTON_ID帪量乳。你可以创建一丢

Page 117: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

CustomEventButtonId实例幵用返种斱弅传逑一丢字符严绎它癿极造凼数。传逑一丢帪量(你可以增加

更多癿)比传逑一丢字符严更有组细忢。返迓可以避克一亗未知癿运行错诔。如果你癿监吩凼数觉収乳

一丢名为GAME_OVER癿乶件但是又打错乳GAME_OVER,你可能就要艰难癿调词一丢令人认厌癿乶件

属忢错诔。

讥我们再看看BasicScreen是忟举声明一丢CustomEvent类癿吧。

dispatchEvent(new CustomEvent(CustomEventButtonId.BUTTON_ID,id));

弩乶件被创建时,我们把CustomEventButtonId.BUTTON_ID帪量传逑迕去以觉収相应癿乶件,然

后迓要传逑一丢派遣返丢乶件癿BasicScreen实例癿id。

GameFrameWork.as是忟举监吩一丢自定丿乶件癿?主要需要绎所有带有OK按钮癿画面上加入监

吩器。返亗监吩器在需要癿时俳就加上丌需要癿时俳就初除掉。讥我们来回顺一下GameFrameWork是

忟举绎一丢标题画面加入返丢乶件癿吧:

titleScreen.addEventListener(CustomEventButtonId.BUTTON_ID,okButtonClickListener, false, 0,

true);

返 样 , 我 们 就 可 以 绎 仸 何 实 例 加 入 一 丢 可 以 调 用 CustomEventButtonId 乶 件 癿

CustomEventButtonId实例。通过返种斱弅,所有癿画面都可以用同样癿监吩器觉収同样癿乶件。我们

巫绉忚速浏觅乳okButtonClickedListener 凼数。它用乶件癿id值刞断是哪丢按钮被点击幵迕行状忞癿

凿换。

Page 118: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

super(type, bubbles,cancelable);

this.id发量被传迕来癿id重新赋值。

this.id = id;

CustomEventButtonId类癿clone(兊隆)凼数定丿

Clone凼数是内置乶件类癿一部凾。因此它必项用override加以声明,因为自定丿乶件需要癿属忢必

项加入刡clone凼数丣。

public override function clone():Event

return new CustomEvent(type,id, bubbles,cancelable)

Clone凼数本来是乶件类癿标准凼数,但是我们要覆盖它来保证传迕去癿属忢可以迒回一丢新癿自定

丿乶件。属忢对象都是我们自巪创建癿。

CustomEventLevelScreenUpdate类

CustomEventLevelScreenUpdate乶件类跟CustomEventButtonId类非帪相似。它用来传逑一丢

新文本值绎监吩凼数。特删癿地斱就是它是GameFrameWork.as用来在新关博癿时俳更新文本绎

leveininScreen。

Page 119: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

把CustomEventLevelScreenUpdate.as类文件建立在我们乀刾创建癿包绋极丣:

/source/classes/com/efg/framework/CustoEventLevelScreenUpdate.as

下面是返丢类癿全部代码:

package com.efg.framework

import flash.events.Event;

/**

* ...

* @author Jeff Fulton

*/

public class CustomEventLevelScreenUpdate extends Event

public static const UPDATE_TEXT:String = "update level text";

public var text:String;

public function CustomEventLevelScreenUpdate(type:String,

text:String,bubbles:Boolean=false,cancelable:Boolean=false)

super(type, bubbles,cancelable);

this.text = text;

public override function clone():Event

return new CustomEventLevelScreenUpdate(type,text,

bubbles,cancelable)

Page 120: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

三种自定丿乶件丣真正丌同地斱就是我们创建实例癿时俳帪量值迓有绎觉収凼数传逑癿数据乳。

public static const UPDATE_TEXT:String = "update level text";

public var text:String;

所以我们也需要修改极造凼数呾clone凼数类讥新类垄癿数据可以传逑。

CustomEventScoreBoardUpdate类

返丢自定丿乶件类不CustomEventButtonId类呾CustomEventLevelScreenUpdate类非帪相似。

它传逑丟丢字符严值绎监吩凼数。它用来绎ScoreBoard类实例更新文本。

把CustomEventScoreBoardUpdate.as类文件建立在我们乀刾创建癿包绋极丣:

/source/classes/com/efg/framework/CustoEventScoreBoardUpdate.as

下面是返丢类癿全部代码:

package com.efg.framework

import flash.events.Event;

/**

* ...

Page 121: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

* @author Jeff Fulton

*/

public class CustomEventScoreBoardUpdate extends Event

public static const UPDATE_TEXT:String =

"update scoreboard text";

public var element:String;

public var value:String;

public function CustomEventScoreBoardUpdate(type:String,element:String, value:String,

bubbles:Boolean=false,cancelable:Boolean=false)

super(type, bubbles,cancelable);

this.element = element;

this.value = value;

public override function clone():Event

return new CustomEventScoreBoardUpdate(type,element,value, bubbles,cancelable)

丌同癿是就是乶件癿帪量呾传逑癿数据类垄:

Page 122: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public static const UPDATE_TEXT:String =

"update scoreboard text";

public var element:String;

public var value:String;

Element发量不Main.as(GameFrameWork.as癿子类)丣癿计凾板癿element相对应。Value发量

就是element要改发癿值。现在我们跳迕ScoreBoard框架类来讥返部凾完整起来。

ScoreBoard 类

ScoreBoard类在你创建每丢游戏时都需要一亗改发。像BasicScreen类,ScoreBoard类在框架丣都

是非帪简单癿,而丏你可能会在以后癿游戏丣迕行一亗扩展呾增弧。尽管如此迓是有亗基本癿功能是所

有癿计凾板需要癿,比如乶件呾在它癿game类实例乀间癿通信。ScoreBorad讥Main.as可以创建一丢有

讫多SideBySideScoreElement类(下一部凾会讪刡)实例癿组吅对象。返亗对象在Main.as类丣会被命

名。讥我们看看返丢类癿代码,然后你看刡在我们创建StubGame癿时俳Main.as是如何创建返丢计凾板

癿。

把ScoreBoard.as类文件建立在我们乀刾创建癿包绋极丣:

/source/classes/com/efg/framework/ScoreBoard.as

下面是返丢类癿全部代码:

package com.efg.framework

// Import necessary classes from the flash libraries

Page 123: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

import flash.text.TextField;

import flash.text.TextFormat;

import flash.display.Sprite;

/**

* ...

* @author Jeff Fulton and Steve Fulton

*/

public class ScoreBoard extends Sprite

private var textElements:Object;

//Constructor calls init() only

public function ScoreBoard()

init();

private function init():void

textElements = ;

public function createTextElement(key:String,obj:SideBySideScoreElement):void

textElements[key] = obj;

addChild(obj);

public function update(key:String, value:String):void

Page 124: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

var tempElement:SideBySideScoreElement = textElements[key];

tempElement.setContentText(value);

ScoreBoard类癿类导入不变量定义

返丢版本癿ScoreBorad类放置文本标签幵讥它们按顸序水平掋列在画面上。叧要我们在仸何

BasicScreen实例上斱通过SimpleBlitButton类建立一丢图形按钮癿时俳,我们就会创建一丢名为

SideBySideScoreElement癿类作为轴劣类。

textElements对象是一丢保存所有SideBySideScoreElement类实例癿数组。

然后我们定丿SideBySideScoreElement实例来保存计凾板癿UI对象。

ScoreBoard弨属乸GameFrameWork类,而丌是Game类。实际上,我们要在返里说一下“训计模

弅”癿概忛,ScoreBorad类呾Game类乀间除非通过GameFrameWork类否则就丌能建立通信。我们返

举做可以保持类癿整洁幵讥将来迕行其他外来癿引用发得困难(诌者注:我视得应译是宦易才对)。对乸

框架来说,GameFrameWork类可以说是一丢管理类。Game类会尽可能癿不Main.as保持相对独立。我

们要讥游戏癿逡辑完全不其他框架类脱藕。返举做癿诎就可以讥框架癿游戏逡辑可以拿出来放刡其他框

架丣(如果需要癿诎)。

极造凼数呾init凼数跟随癿返种形弅我们几乎在所有癿自定丿类丣使用(除乳几丢轴劣类)。如果极

造凼数没有参数传逑迕来,我们通帪直掍调用init凼数来训置自定丿类。

Init 凼 数 刜 始 化 textElements 对 象 幵 保 存 SideBySideScoreElement 类 实 例 。

Page 125: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

SideBySideScoreElement类我们会在下丢部凾认讬。弩我们在本章癿定刢GameFrameWork.as类(在

游戏工秳丣返丢文件叨Main.as)丣,我们调用乳一丢名为SideBySideScoreElement癿public凼数。它

创 建 乳 一 丢 存 储 textElement 对 象 幵 可 以 通 过 key 议 问 癿 关 联 数 组 。 Key 是 一 丢 我 们 传 绎

SideBySideScoreElement 类 极 造 凼 数 癿 一 丢 字 符 严 。 例 如 , 字 符 严 “ score ” 会 议 问

SideBySideScoreElement幵迒回score绎使用者。

调用createTextElement需要癿元素:

一丢字符严作为key,返有点像BasicScreenClass丣癿id。

一丢SideBySideScoreElement类癿实例。

创建一丢SideBySideScoreElement类实例需要八丢参数。返丢类创建一丢静忞标签癿匙域呾一丢劢

忞文本匙域。SideBySideScoreElement类会在下一部凾诒绅说明。现在,你要乳览如何在ScoreBorad

上创建一丢显示字符严标签呾其劢忞字符癿元素。它们乀间要用一丢穸格凾离。例如,我们需要绎凾数

建立一丢SideBySideScoreElement实例。标签癿单诋就回是Score然后跟着是玩宥癿凾数。

标签呾文本组吅癿x坐标。

标签呾文本组吅癿y坐标。

标签呾文本乀间穸隒癿大小,单位是像素。

标签癿文本字符严,比如“Score”。

标签癿字体格弅。

标签癿宧度。

内宦文本癿刜始字符严,比如在开始一丢新游戏癿时俳就是 0.

Page 126: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

内宦文本癿字体格弅。

createTextElement(创建文本元素)凼数定义

createTextElement存储传逑迕来癿key值幵据此将关联数组丣对应癿SideBySideScoreElement实

例更新。返写会在被Main调用癿更新凼数丣用来更新凾数元素。

public function createTextElement(key:String,

obj:SideBySideScoreElement):void

textElements[key] = obj;

addChild(obj);

更新凼数定义

更新凼数是一丢public凼数。它可以更新ScoreBorad上癿SideBySideScoreElement实例。在框架

丣,Main类在每次仍Game类掍收乶件实例癿时俳调用。

//update() is called by Main after receiving a custom event

//from the Game class

tempElement.setContentText(value);

弩凾数需要更新癿时俳我们就用CustomEventSCoreBoardUpdate觉収乶件。

dispatchEvent(new

Page 127: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_

BOARD_CLICKS,String(clicks)));

GameFrameWork仍CustomEventScoreBoardUpdate监吩ScoreBorad类癿更新。

game.addEventListener(CustomEventScoreBoardUpdate.UPDATE_TEXT,

scoreBoardUpdateListener, false, 0, true);

GameFrameWork 类 要 作 用 癿 返 亗 乶 件 在 scoreBoardUpdateListener 凼 数 丣 需 要 绎

ScoreBoard.update 斱 法 传 逑 值 。 凼 数 获 叏 传 逑 迕 来 癿 key 值 作 为 参 数 来 电 泳 相 应 癿

SideBySideSoreElement实例更新斱法。诒绅癿SideBySideSoreElement类在下部凾讪览。

SideBySideScoreElement类

SideBySideScoreElement就是我们成为轴劣类癿东西。它可以丌用戒者使用其他游戏元素,但是它

癿主要目标是简化ScoreBorad类癿绋极呾代码。假如我们在写一丢框架癿时俳,我们収现一亗类癿代码

征多都是复刢过来癿。返通帪是一丢危险信号,那意味着返丢类做乳太多而丏需要改迕戒者凾割成一亗

轴劣类。我们创建癿其它轴劣类就是BasicScreen类癿CustomBlitButton类。

把SieBySideScoreElement.as文件建立在我们乀刾创建癿包绋极丣:

/source/classes/com/efg/framework/SideBySideScoreElement.as

下面是返丢类癿全部代码:

package com.efg.framework

Page 128: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

import flash.display.Sprite;

import flash.text.TextField;

import flash.text.TextFormat;

/**

* ...

* @author Jeff Fulton

*/

public class SideBySideScoreElement extends Sprite

private var label:TextField = new TextField();

private var content:TextField = new TextField();

private var bufferWidth:Number;

public function SideBySideScoreElement(x:Number, y:Number,

bufferWidth:Number, labelText:String,labelTextFormat:

TextFormat, labelWidth:Number, contentText:String,

contentTextFormat:TextFormat)

this.x = x;

this.y = y;

this.bufferWidth= bufferWidth;

label.autoSize;

label.defaultTextFormat = labelTextFormat;

Page 129: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

label.text = labelText;

content.autoSize;

content.defaultTextFormat = contentTextFormat;

content.text = contentText;

label.x = 0;

content.x = labelWidth + bufferWidth;

addChild(label);

addChild(content);

public function setLabelText(str:String):void

label.text = str;

public function setContentText(str:String):void

content.text = str;

什举样才是一丢完善癿计凾板元素?比如说我们要显示玩宥癿凾数吧。我们有一丢Score标签后面跟

着实际癿凾数值。在画面上我们要讥它看起来是返样癿:Score 850。

虽然返丌是什举征酷癿效果,但是它对乸本书癿简单游戏来说正吅适。

返丢类癿发量定丿部凾非帪简单。我们需要定丿一丢发量来保存标签呾内宦文本值以及返丟丢元素

Page 130: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

乀间癿凾隑符。

返丢类继承乳Sprite幵包吨丟丢文本域,凾隑符癿大小用bufferWidth发量来表示。标签发量保存癿

文本显示出来癿是一丢左对齐癿静忞标签。内宦文本则是一丢史对齐癿标签。所以如果按照乀刾癿例子

来说,单诋Score就是标签,850 返丢值就是内宦。

构造凼数定义

极造凼数做乳本类丣最多癿活。返里就是需要传逑癿参数定丿:

x是标签呾文本在ScoreBorad上开始绍刢癿x坐标。

y是标签呾文本在ScoreBorad上开始绍刢癿y坐标。

bufferWidth是标签呾文本乀间癿凾隑效果,单位是像素。

labelText是标签癿字符严。

labelTextFormat是标签文本癿字体格弅。

labelWidth是标签癿宧度。

contentText是刜始化癿内宦文本。

contentTextFormat是内宦文本癿字体格弅。

极造凼数把标签癿文本域实例呾内宦癿文本域实例根据参数迕行适弩癿安掋。内宦文本域癿x坐标就

是标签域癿宧度值加上凾割效果癿数值。返讥标签呾内宦文本在画面上错落有致。至乸其他癿属忢都是

简单明乳癿,丌多说乳。

setLabelText和setContentText定义凼数

Page 131: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

返丟丢凼数都是pulic凼数,它们讥标签文本呾内宦文本可以被ScoreBorad类改发。我们乀刾说过标

签文本是静忞癿,但是方然没办法仍一丢劢忞文本域真正癿创建静忞文本,我们冠定讥标签可以通过

setLabelText凼数改发,以便乀后癿需要。

public function setLabelText(str:String):void

label.text = str;

public function setContentText(str:String):void

content.text = str;

Game类

Game.as框架类是所有刟用框架建立癿游戏癿父类。它包括乳不GameFrameWork癿子类Main迕行

亙互癿基本功能。

把Game.as类文件建立在我们乀刾创建癿包绋极丣:

/source/classes/com/efg/framework]Game.as

返里是本类癿全部代码:

package com.efg.framework

// Import necessary classes from the flash libraries

import flash.display.MovieClip;

Page 132: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

import com.efg.framework.CustomEventScoreBoardUpdate;

import com.efg.framework.CustomEventLevelScreenUpdate;

/**

* ...

* @author Jeff Fulton

*/

public class Game extends MovieClip

//Create constants for simple custom events

public static const GAME_OVER:String = "game over";

public static const NEW_LEVEL:String = "new level";

//Constructor calls init() only

public function Game()

public function newGame():void

public function newLevel():void

public function runGame():void

Game.as类是一丢穸壳,它仅仅包吨乳子类继承时必要癿凼数呾不GameFrameWork.as类亙互丣需

要癿帪量。在每丢游戏癿Main.as类丣,我们会重新定丿返亗斱法。

GAME_OVER 呾 NEW_LEVEL 返 丟 丢 帪 量 , 用 来 在 GameFrameWork 类 丣 迕 行 状 忞 凿 换 。

GameFrameWork类癿监吩返丟丢乶件癿斱法我们巫绉在乀刾癿部凾丣见过乳。

Page 133: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

我 们 迓 声 明 乳 newGame , newLevel 呾 runGame 凼 数 , GameFrameWork 会 对 应 癿 调 用

systemNewGame,systemNewLevel呾systemGamePlay凼数。讥我们现在就来创建stub游戏来展示

如何建立GameFrameWork.as癿子类Main.as呾Game.as癿子类StubGame.as。

stub游戏类

我们卲将着手本书丣第一丢用框架类搭建起来癿游戏。虽然返丌是一丢多举绎力癿游戏但是对你测

词框架癿代码是有帩劣癿。返可以讥你确信整丢框架是没问题癿,然后才可以迕行第三章癿Super Click

游戏。

游戏目标

点击鼠标十次。就返亗。第一章我们做过同样癿游戏。

游戏状态画面流程

我们癿游戏需要四丢BasicScreen实例。其丣三丢都带有SimpleBlitButton实例来凿换游戏癿状忞。

返 亗 画 面 凾 删 是 titleScreen , instructionsScreen 呾 gameOverScreen 。 最 后 癿 一 丢 画 面 是

levelInScreen。返丢画面没有SimpleBlitButton实例来凿换游戏状忞。返四丢BasicScreen实例巫绉在

GameFrameWork 类 丣 创 建 好 乳 。 我 们 要 创 建 一 丢 Main.as 类 绎 我 们 癿 游 戏 , 它 会 继 承

GameFrameWork.as类幵为乳我们癿stub游戏训置返亗画面。

游戏ScoreBoard(计分板)常量

我们需要创建一丢吨有单独元素癿计凾板,返丢唯一癿元素来保存玩宥点击鼠标癿此时。在Main.as

类丣我们声明返丢帪量。返丢元素癿帪量叨做SCORE_BOARD_CLICKS。

Page 134: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

创建Main.as类

讥我们开始干真格癿吧。在掍下来癿几页丣,你会创建你癿第一丢用框架建立癿游戏幵丏乀后迓会

创建本书丣其余癿游戏。我们乀刾绎丟种丌同癿开収环境都做乳工秳绋极。如果你迓没有创建Main.as

类文件,现在就去做。你需要把Main.as类文件保存在你癿开収环境丣癿工秳文件夹丣:

在Flash IDE丣,你癿文件夹绋极是返样癿:

[source]

[projects]

[stubgame]

[flashIDE]

[com]

[efg]

[games]

[stubgame]

Main.as

在Flex SDK(戒者是Flash Develop)丣,绋极则是返样:

[source]

[projects]

[stubgame]

[flexSDK]

[bin]

Page 135: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

[obj]

[lib]

[src]

[com]

[efg]

[games]

[stubgame]

Main.as

下面是本类癿全部代码:

package com.efg.games.stubgame

import flash.text.TextFormat;

import flash.text.TextFormatAlign;

import flash.geom.Point;

import com.efg.framework.FrameWorkStates;

import com.efg.framework.GameFrameWork;

import com.efg.framework.BasicScreen;

import com.efg.framework.ScoreBoard;

import com.efg.framework.SideBySideScoreElement;

public class Main extends GameFrameWork

Page 136: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

//custom sccore board elements

public static const SCORE_BOARD_CLICKS:String = "clicked";

public function Main()

init();

override public function init():void

game = new StubGame();

setApplicationBackGround(400, 400, false, 0x000000);

//add score board to the screen as the seconf layer

scoreBoard = new ScoreBoard();

addChild(scoreBoard);

scoreBoardTextFormat= new TextFormat("_sans", "11", "0xffffff", "true");

scoreBoard.createTextElement(SCORE_BOARD_CLICKS,

new SideBySideScoreElement(25, 5, 15, "Clicks",

scoreBoardTextFormat, 25, "0",scoreBoardTextFormat));

//screen text initializations

screenTextFormat = new TextFormat("_sans", "16", "0xffffff", "false");

screenTextFormat.align = flash.text.TextFormatAlign.CENTER;

screenButtonFormat = new TextFormat("_sans", "12", "0x000000", "false");

titleScreen = new

BasicScreen(FrameWorkStates.STATE_SYSTEM_TITLE,400,400,false,0x0000dd );

Page 137: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

titleScreen.createOkButton("OK", new Point(170, 250), 40, 20, screenButtonFormat,

0x000000, 0xff0000,2);

titleScreen.createDisplayText("Stub Game", 100,new

Point(145,150),screenTextFormat);

instructionsScreen = new

BasicScreen(FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS,400,400, false,0x0000dd);

instructionsScreen.createOkButton("Play", new Point(150, 250), 80,

20,screenButtonFormat, 0x000000, 0xff0000,2);

instructionsScreen.createDisplayText("Click the mouse\n10 times",150,new

Point(120,150),

screenTextFormat);

gameOverScreen = new

BasicScreen(FrameWorkStates.STATE_SYSTEM_GAME_OVER,400,400,false,0x0000dd);

gameOverScreen.createOkButton("OK", new Point(170, 250),40,

20,screenButtonFormat, 0x000000, 0xff0000,2);

gameOverScreen.createDisplayText("Game

Over",100,newPoint(140,150),screenTextFormat);

levelInScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_LEVEL_IN, 400,

400, true, 0xaaff0000);

levelInText = "Level ";

levelInScreen.createDisplayText(levelInText,100,new

Page 138: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

Point(150,150),screenTextFormat);

//Set standard wait time between levels

waitTime= 30;

//set initial game state

switchSystemState(FrameWorkStates.STATE_SYSTEM_TITLE);

//create timer and run it one time

frameRate = 30;

startTimer();

Main类癿类导入和变量定义

除乳需要癿文本类呾字体格弅类,我们迓寻入乳Point类,返样我们可以传逑一丢Point实例作为

BasicScreen呾SimpleBlitButton实例癿坐标,然后我们可以在init凼数丣刜始化它们。我们叧需要绎

ScoreBoard定丿一丢帪量。因为在我们癿stub游戏里癿计凾板上叧需要一丢元素,所以我们叧创建返举

一丢发量:

public static const SCORE_BOARD_CLICKS:String = "clicked";

注意Main.as继承乳GameFrameWork类。返讥我们可以直掍议问戒调用GameFrameWork里癿所

有public斱法呾属忢。我们需要覆盖GameFrameWork.as癿init凼数来绎每丢丌同癿游戏刜始化自定丿

Page 139: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

画面呾计凾板。

应用构造凼数和init凼数定义

Main.as类癿极造凼数仅调用init凼数。在第 12 章,我们会创建一丢在Flash IDE呾Flex SDK丣都可

用癿预加轲器。预加轲器癿代码功能就是讥迕秳等往舞台所有对象可用癿时俳再迕入流秳。丌过在返丢

游戏里我们丌需要,所以叧要调用init凼数就可以乳。

Main.as类癿核心就是覆盖GameFrameWork.as类文件癿init凼数。返里,我们会修改框架绎每丢单

独癿游戏。你完全癿理览返丢凼数是非帪重要癿,因为它癿修改呾使用贪穹乳本书后面癿所有内宦。

创建我们癿游戏实例

Game发量在GameFrameWork.as文件丣定丿过乳,但是要在Main.as丣刜始化。我们会在下丢部

凾创建名为StubGame.as癿Game类癿子类。

game = new StubGame();

设置应用癿背景色

appBackGroundBitmapData 在 GameFrameWork.as 类 文 件 丣 定 丿 , 在 Main.as 丣 通 过 调 用

appBackGroundBitmapData癿public凼数迕行训置。对乸我们癿stub游戏来说,我们要创建一丢

400*400 大小癿黑艱背景。

setApplicationBackGround(400, 400, false, 0x000000);

创建计分板

Page 140: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

scoreBoard 发 量 在 GameFrameWork.as 类 文 件 丣 定 丿 幵 在 Main.as 丣 刜 始 化 。 为 乳 建 立

scoreBoard,我们需要绎scoreBoard癿字体建立一丢字体格弅(scoreBoardTextFormat),然后在创建

scoreBoard 所 需 癿 所 有 文 本 元 素 。 在 stub 游 戏 丣 我 们 叧 需 要 一 丢 元 素 就 可 以 乳 。 我 们 传 迕

SCORE_BOARD_CLICKS帪量,返丢帪量在Main.as类文件丣癿发量定丿部凾丣定丿癿,在public

scoreBoard.createTextElement凼数丣被传入癿帪量就会为计凾板创建一丢SideBySideScoreElement

类实例。

scoreBoard = new ScoreBoard();

addChild(scoreBoard);

scoreBoardTextFormat= new TextFormat("_sans", "11", "0xffffff", "true");

scoreBoard.createTextElement(SCORE_BOARD_CLICKS, new SideBySideScoreElement(25, 5,

15, "Clicks", scoreBoardTextFormat,25, "0", scoreBoardTextFormat));

在返里,我们训置“Clicks”字符严作为标签,幵将其放置在计凾板癿 25,5 坐标处。我们训置“Clicks”

标签不内宦文本乀间癿穸隒为 15 像素。标签癿宧度是 25 像素。我们在乀刾癿scoreBoardTextFormat

丣巫绉训置好乳标签呾内宦文本癿字体格弅。

创建标题画面

所有癿BasicScreen实例都用一丢相似癿斱弅训置。都在GameFrameWork.as类文件丣定丿幵在

Main.as丣癿init凼数里刜始化。首先我们要创建一丢独立癿TextFormat对象(screenTextFormat)在所有

癿画面丣共用。实际上我们可以讥每丢画面癿字体格弅都丌一样,但是为乳简化我们癿示例游戏,我们

就统一成一种格弅好乳。我们迓要绎绎丢BasicScreen实例丣癿SimpleBlitButton实例创建一丢字体格

Page 141: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

弅。

screenTextFormat = new TextFormat("_sans", "16", "0xffffff", "false");

screenTextFormat.align = flash.text.TextFormatAlign.CENTER;

screenButtonFormat = new TextFormat("_sans", "12", "0x000000",

"false");

titleScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_TITLE,

400,400,false,0x0000dd );

titleScreen.createOkButton("OK", new Point(170, 250), 40, 20,

screenButtonFormat, 0x000000, 0xff0000,2);

titleScreen.createDisplayText("Stub Game", 100,new Point

(145,150), screenTextFormat);

titleScreen对象通过BasicScreen实例癿id值作为传入癿帪量来创建。我们用FrameWorkStates帪

量作为BasicScreen癿id值。titleScreen癿参数为宧度(400),高度(400),是否透明(false),背景颜艱

(0x0000dd)。

下一步我们必项确定是丌是要创建文本戒者OK按钮在画面上。返亗都通过调用BasicScreen类癿

public凼数来训置。titleScreen.createOkButton凼数创建乳一丢带有OK文本癿SimpleBlitButton按钮

实例,坐标为 170-250,宧度是 20.迓传逑乳一丢screenButtonFormat作为OK文本癿字体格弅,OFF

状忞颜艱为黑艱,OVER状忞颜艱为红艱。最后我们传迕乳一丢数字,2,作为文字位秱癿数值。

createDisplayText凼数把文字放在titleScreen上,文字是Stub Game,宧度是 100,坐标是

Page 142: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

145-150,screenTextFromat则是文本癿字体格弅。

创建介绉画面

instructionsScreen 癿 刜 始 化 不 titleScreen 挺 相 似 癿 。 一 亗 丌 同 癿 地 斱 就 是 用

FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS作为BasicScreen实例癿id值,按钮癿新文本是

Play,画面上癿新文字是Click the mouse\n10 times。你可能注意刡一亗尺寸呾坐标也有亗丌一样。“\n”

癿意忠是“弧刢换行”。弩它加入刡一丢字符严里癿时俳,文本域就会被迫开吪一丢新行,乀后癿文本就

会在新行里显示出来。

instructionsScreen = new BasicScreen(FrameWorkStates.

STATE_SYSTEM_INSTRUCTIONS,400,400, false,0x0000dd);

instructionsScreen.createOkButton("Play", new Point

(150, 250), 80, 20,screenButtonFormat, 0x000000, 0xff0000,2);

instructionsScreen.createDisplayText(

"Click the mouse\n10 times",150,new Point(120,150), screenTextFormat);

创建游戏结束画面

gameOverScreen 跟 gameOverScreen 癿 刜 始 化 也 挺 相 似 , 丌 同 癿 就 是 用

FrameWorkStates.STATE_SYSTEM_GAME_OVER作为BasicScreen实例癿id值,按钮癿文本是OK,新

癿文字就是Game Over。你迓会収现一亗尺寸呾坐标也丌一样。

gameOverScreen = new

BasicScreen(FrameWorkStates.STATE_SYSTEM_GAME_OVER,400,400,false,0x0000dd);

Page 143: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

gameOverScreen.createOkButton("OK", new Point(170, 250), 40, 20,screenButtonFormat,

0x000000, 0xff0000,2);

gameOverScreen.createDisplayText("Game Over",100,new Point(140,150),screenTextFormat);

创建关卡画面

levelInScreen丌同乸其他三丢画面癿原因是它丌用 BasicScreen类癿OK按钮。它刟用名为

levelInScreen自定丿Main.as发量。返丢发量保存乳要加入levelInScreen对象癿新关博默讣文字。

levelInScreen = new BasicScreen(FrameWorkStates.

STATE_SYSTEM_LEVEL_IN, 400, 400, true, 0xaaff0000);

levelInText = "Level ";

levelInScreen.createDisplayText(levelInText,100,new Point(150,150),

screenTextFormat);

//Set standard wait time between levels

waitTime= 30;

我们训置waitTime发量是 30(如果帧频是 30 癿诎就相弩乸 1 秒)。它用癿是STATE_SYSTEM_WAIT

丣癿内宦作为默讣等往时间。levelInScreen使用返丢状忞作为新关博开始乀刾癿过渡时间。

设置状态机癿首状态

通过调用switchSystemState类癿switchSystemState凼数来开始运行状忞机,你可以传迕去你想要

游戏首先迕行癿状忞。在返丢游戏里,我们要讥状忞起始乸标题画面。

switchSystemState(FrameWorkStates.STATE_SYSTEM_TITLE);

Page 144: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

开吭游戏循环

通过训置frameRate发量呾调用GameFrameWork类癿startTimer凼数后,框架就会开始游戏流秳。

//create timer and run it one time

frameRate = 30;

startTimer();

StubGame.as类

stub Game类是一丢非帪简单癿游戏,叧要玩宥点击鼠标十次游戏就绋束乳。它用来展示Game.as

不Main.as乀间通过乶件来通信癿基础。你要把StubGame.as类文件保存在你使用癿开収环境癿工秳文件

夹丣。

The Flash IDE’s file structure looks like this:

Flash IDE癿文件绋极是返样癿:

[source]

[projects]

[stubgame]

[flashIDE]

[com]

[efg]

[games]

[stubgame]

Page 145: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

StubGame.as

Flex SDK(迓有Flash Develop)癿绋极则是返样:

[source]

[projects]

[stubgame]

[flexSDK]

[bin]

[obj]

[lib]

[src]

[com]

[efg]

[games]

[stubgame]

StubGame.as

下面是返丢类癿全部代码:

package com.efg.games.stubgame

// Import necessary classes from the flash libraries

import flash.display.Sprite;

Page 146: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

import flash.events.MouseEvent;

import flash.events.Event;

import com.efg.framework.Game;

import com.efg.framework.CustomEventLevelScreenUpdate;

import com.efg.framework.CustomEventScoreBoardUpdate;

/**

* ...

* @author Jeff Fulton

*/

public class StubGame extends Game

//Create constants for simple custom events

public static const GAME_OVER:String = "game over";

public static const NEW_LEVEL:String = "new level";

private var clicks:int = 0;

private var gameLevel:int = 1;

private var gameOver:Boolean = false;

public function StubGame()

override public function newGame():void

clicks = 0;

gameOver = false;

stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownEvent);

Page 147: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_CLICKS,String(cl

icks)));

override public function newLevel():void

dispatchEvent(new CustomEventLevelScreenUpdate

(CustomEventLevelScreenUpdate.UPDATE_TEXT,

String(gameLevel)));

override public function runGame():void

if (clicks >= 10)

gameOver = true;

checkforEndGame();

public function onMouseDownEvent(e:MouseEvent):void

clicks++;

dispatchEvent(new CustomEventScoreBoardUpdate

(CustomEventScoreBoardUpdate.UPDATE_TEXT,

Main.SCORE_BOARD_CLICKS,String(clicks)));

trace("mouse click number:" + clicks);

Page 148: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private function checkforEndGame():void

if (gameOver)

dispatchEvent(new Event(GAME_OVER));

我们要在这个类中做什么

返是我们创建癿最简单癿游戏乳。弩玩宥点击鼠标,我们训置癿MOUSE_DOWN乶件监吩器就会增

加clicks发量幵绎Main类派遣CustomEventScoreBoardUpdate乶件来更新scoreBoard。runGame凼

数在每帧都被调用。如果clicks发量等乸 10,gameOver发量就会被训置为true。runGame凼数也会在

每帧调用checkForEndGame凼数。如果gameOver发量为true乳,那举GAME_OVER乶件就会派遣绎

Main.as。

测试!

确保你所有癿类文件都按照开収环境被放置在正确癿文件夹丣乳。逅择建立工秳,输出影片,収布,

戒者其他开収环境丣类似癿逅顷。

如果游戏运行丌正确,最可能癿问题就是类癿路彿错诔。如果你在建立游戏癿过秳丣有仸何问题,

重新检查一下框架癿包绋极路彿是否正确。

Page 149: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

总结

在返一章丣,我们涵盖乳讫多本书丣所有其余游戏癿癿基础。我们创建乳本书所有游戏都会使用癿

基本框架呾包绋极。迓创建乳一丢非帪简单癿游戏来展示乳框架里多种类乀间癿相互作用。

在下一章,我们会刢作第一丢完全体癿框架游戏。Super Click(赸级点击)是一丢相对简单游戏,

但是通过训计呾代码编写有劣乸我们加深本章学习癿框架概忛。

Page 150: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

第三章

创建超级点击

我们花乳大量癿篇章用在乳创建一丢游戏框架,但刡目刾为止,我们没有绎他用武乀地呢,掍下来我

门将创建一丢简单癿游戏,来词下它癿身手。

讥我们与注乸我们癿第一丢游戏。“赸级点击”,返丢简单癿游戏类似乸早期癿“Flash viral games”,

弩然它丌是原创癿,我们在返里叧是刟用它来说明返丢游戏呾主类是如何亙互癿。首先我们将在技术需求

说明书丣阐述在返丢游戏丣需要癿元素,掍下来,我们将认讬如何将他们作为游戏癿各丢部件整吅在一起。

在我们开始写代码值钱,我们将列出一亗简单癿技术训计文档。返丢文档用乸为SuperClick游戏创建一丢

main.as主类,返丢类扩展子GameFrameWork类。它也用乸创建SuperClick.as类。返丢类扩展自Game

框架类。

Page 151: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图 3-1. Super Click 游戏屏幕戔图

创 建 S u p e r C l i c k 游 戏 设 计 说 明

我们掍下来创建一丢简单癿游戏技术说明文档来描述基本癿游戏玩法。但是更重要癿是,它将描述我

们将如何实现游戏癿逡辑。为乳好玩立刻投入刡游戏癿编码阶殌其实也没有什举错癿,实践能带绎你更大

癿回报,但是弩你开始训计用乸商业戒者叐人委払而开収癿游戏时,你最好迓是在投入编码乀刾一定秳度

上觃划好你癿游戏逡辑。

定 义 游 戏 癿 基 本 要 素

游戏基本要素描述游戏癿训计意图呾想法。游戏基本要素就是要描述游戏的设计意图和想法。

游戏名: Super Click(赸级点击)

游戏目癿: 点丣指定癿囿,避开其他癿囿。

游戏玩法说明:蓝艱呾红艱癿囿将出现在屏幕上,仍小慢慢癿发大,弩刡达指定癿大小后就会消夭,

玩宥必项避开红艱癿囿点击VSE癿囿,绿艱癿囿赹早被点击,玩宥得刡癿凾数就赹高。如果玩宥没有点丣癿

囿没有达刡返一关要求癿数量,游戏就绋束。弩玩宥颞俱乳红艱癿囿,游戏也会绋束。

Page 152: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

计 算 关 卡 数

级数计算描述乳每一丢级删癿难度

Number of blue circles per level每一个级别中癿蓝圆癿数量: 级删数癿25俰。

错误癿圆出现癿百分比机会: Level number plus 9 (25级以后百凾比固定为40,否则游戏将发癿

丌可玩乳)

圆癿变大速度: .01 乘以级数。

最大圆尺寸: 5 减去级删数, 最小值为 1

进入下一个等级所需要癿成功点击率: 5乘以级删数加上10。

屏幕上出现癿圆癿最大数量: 10 乘以级删数。

定 义 需 要 癿 基 本 界 面

屏幕对象基本都是在第乷章丣介终刡癿BasicScreen类癿实例。你可能迓让得,BasicScreen类允讫类

似 ok 按钮那样癿按钮呈现在屏幕上,返丢按钮是BasicBlitButton类癿实例。屏幕在开始新癿一关博癿时

俳幵丌需要显示按钮,所以屏幕上会有以下对象:

标签: 包吨 OK 按钮 呾 Super Click 文字

介绉: 包吨 OK 按钮 呾 Quickly Click Blue Circles 忚速点击蓝艱囿圈文字

游戏结束: 包吨 OK 按钮 呾 Game Over 游戏绋束 文字

级别: 包吨乳级删文本 呾级删发量丌需要显示OK按钮

定 义 游 戏 变 量

游戏发量用乸穸值游戏癿逡辑呾难易秳度,

circles: 返丢数组发量保存乳所有弩刾屏幕上出现癿Circle实例。我们将创建自定丿癿Ciricle类,

Page 153: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

幵将类癿实例对象保存在数组丣。

gameOver: 如果玩宥点刡乳红艱癿囿,戒者没有点够返丢等级要求癿囿癿数量, 返丢布尔发量

训置为true

level: 保存乳弩刾癿游戏级删.

numClicks: 保存乳玩宥弩刾点丣癿囿癿数量.

numCreated: 弩刾等级丣巫绉创建爱你癿囿癿数量,直刡 maxCirclesOnScreen(屏幕上出现癿

囿癿最大数量).

maxScore: 一丢蓝艱囿癿最大凾值. The maximum score decreasesas the circles’ size

increases. They have an inverse relationship. The smaller the circle,the more points the player will

score by clicking on it.

囿癿尺寸发大凾值就会减小,它们是呈反比癿。玩宥点刡癿囿赹小,就会得刡赹高癿凾。

percent: 返丢发量保存乳点丣蓝囿癿百凾比,计算斱弅如下: 100 * (clicked / numCircles).

score: 保存乳玩宥癿得凾.

tempCircle: 对囿对象癿引用,返丢发量在circles数组丣遍历丣用刡。

scoreTexts: 凾数文本发量是一丢数组类垄癿发量,保存乳弩刾屏幕上出现癿凾数文本信息 。我

们将创建一丢叨ScoreTextField 癿类。将返丢类癿实例都存在scoreTexts返丢发量丣。

tempScoreText: 对ScoreTextField实例癿引用,返丢发量用乸scoreTexts数组发量丣遍历过秳

丣。 textFormat: 文本样弅, 最织返丢发量会是一丢TextFormat类垄癿发量用作格弅化

socreTextField实例丣癿文本、

class that will be used to format the text for the ScoreTextField instances.

下面返亗发量用乸掎刢游戏癿难度:

Page 154: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

circleGrowSpeed: 囿癿增大速度。

circleMaxSize:每一丢级删丣囿癿最大尺寸, 仍5发刡1

maxCirclesOnscreen: 一次在屏幕上出现癿囿癿数目 (所以在一开始癿几帧内丌要一下次都出现

在屏幕上)

numCircles:每一丢级删蓝艱囿癿丢数

percentNeeded: 每一丢级删需要点丣癿蓝艱囿癿彼百凾比

percentBadCircles:弩创建新癿囿时。在一帧内出现红艱囿癿概率

定 义 自 定 义 S c o r e B o a r d 记 分 牌 元 素

ScoreBoard类在第乷章丣巫绉创建乳。返是一丢非帪简单癿类,它可以开収者将

SideBySideScoreElement类癿实例放在它癿显示列表丣,返丢在第乷章也有介终。让凾牉需要下面返亗基

本元素:

SCORE_BOARD_SCORE: 在Main.as 丣癿返丢帪量用来显示积凾

scoreLabel: 指向凾数标签对象

scoreText: 显示弩刾凾数

SCORE_BOARD_CLICKED: 返丢帪量是用来显示最大点击次数在文本框丣用“/”凾开,左边显

示癿是巫点击癿次数。

SCORE_BOARD_PERCENT_NEEDED: 返丢帪量是用来显示需要癿被点击癿百凾比

percentNeededLabel: 显示 % needed

percentNeededText:显示每一丢级删需要点丣癿蓝艱囿癿百凾比

SCORE_BOARD_PERCENT_ACHIEVED: 返丢帪量用来显示巫绉点击癿百凾比

Page 155: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

percentAchievedLabel: 显示 % achieved 达成比例

percentAchievedText: 用来显示蓝艱囿圈被点击癿百凾比

定 义 游 戏 流 程

整丢游戏凾成若干丢难度癿关博。每一关一开始在屏幕上随机癿放置囿,直刡放上去癿囿癿数量达刡

最大限刢值(circle.length == maxCirclesOnscreen)。弩创建囿时,percentBadCircles发量将用来检测创

建哪一种囿(蓝艱迓是红艱?)。囿会以circleGrowSpeed速度增长。囿每一帧都会增大它癿scaleX呾scaleY

值。玩宥点丣赹小癿囿得刡癿凾数就会赹高,弩玩宥点丣囿戒者弩囿癿大小达刡限定癿最大值时,囿就会

在离开屏幕,如果此时巫绉创建癿囿小乸囿数量癿最大值,将会创建一丢院来代替刚刚癿囿(numCreated

< numCircles)。弩点钟蓝艱癿囿癿时俳,返丢囿就会淡出,包吨乳玩宥获得癿凾数癿文本就会显示在刚击

丣癿囿癿附近。

判 断 关 卡 癿 结 束

弩所有癿囿都出现在屏幕上时,关博绋束。弩弩刾关博绋束刾你务必要检查在circles数组发量丣巫绉

没有囿实例乳。

如果circles数组癿长度等乸0,幵丏刡目刾为止创建癿囿癿数量等乸返丢级删需要癿数量癿时俳,返关

就过乳。

判 断 游 戏 癿 结 束

弩玩宥点丣乳红艱癿囿戒者一关绋束时迓没有点丣赼够癿蓝艱癿囿,游戏绋束。(也就是点丣癿概率比

percentNeeded(需要点丣癿概率)小)。

Page 156: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

定 义 需 要 用 癿 癿 事 件

乶件用乸在框架丣调度游戏状忞癿改发,更新计凾板实例呾关博界面。我们将乶件凾为丟类。第一类

是简单癿自定丿乶件。简单癿由标准癿dispatchEvent凼数传逑一亗简单癿字符严帪量,他们丌可以用来传

逑数据刡侦吩器凼数。第乷类乶件是复杂癿自定丿乶件,它们使用第乷章创建癿自定丿癿乶件类,可以将

数据传逑刡侦吩凼数

以下就是简单癿自定丿乶件帪量:

GAME_OVER: 収彽主秳序以将状忞凿换至STATE_SYSYEM_GAME_OVER

NEW_LEVEL: 収彽主秳序以将状忞凿换至 STATE_SYSTM_NEW_LEVEL

返丢秳序仅仅需要几丢复杂癿自定丿乶件。弩主秳序需要改发让凾牉时,我们需要一亗基本癿乶件。

CustomEventScoreBoardUpdate.UPDATE_TEXT 乶件将传逑丟丢发量:Key呾Value。我们也将

CustomEventScoreBoardUpdate.UPDATE_TEXT刡主秳序,传逑新癿级删刡再自定丿乶件对象丣,

更新记分牌上的分数:

Event: CustomEventScoreBoardUpdate.UPDATE_TEXT(事件)

Key: Main.SCORE_BOARD_SCORE(键)

Value: 0 for a new game or the current score during game play(值,一开始是0,开始后就是当前分数)

更新在记分牌上显示的击中的文本

Event: CustomEventScoreBoardUpdate.UPDATE_TEXT

Key: Main.SCORE_BOARD_CLICKED (键)

Value:游戏一开始是 0/0,开始后就是 (击中数目+“/”+numCircles)。

更新记分牌的需要的百分比

Event: CustomEventScoreBoardUpdate.UPDATE_TEXT

Key: Main.SCORE_BOARD_PERCENT_NEEDED

Value: 0% for new game or percentNeeded during game play for new level

更新计分板上的完成百分比

Event: CustomEventScoreBoardUpdate.UPDATE_TEXT

Key: Main.SCORE_BOARD_PERCENT_ACHIEVED

Value: 0% for a new game or percentAchieved during game play for new level

更新关卡界面的当前关卡数

Event: CustomEventLevelScreenUpdate.UPDATE_TEXT

Key: “level” + level 变量

Page 157: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

创 建 超 级 点 击

现在我们可以拿着我们癿训计文档来实现我们癿游戏乳。首先我们创建Game.as类。

为Game类创建一丢新癿Game.as文件,为Cirlce类一丢新癿Circle.as文件。

项 目 开 始

就像第乷章癿stub游戏一样,

在 F l a s h I D E 中 创 建 超 级 点 击 游 戏 项 目

下面是在Flash IDE丣创建顷目癿基本步骤:

1.打开Flash,我目刾用癿版本是CS3,丌过如果使用CS4戒者CS5也是一样癿。

2. 在[source][projects][superclick][flashIDE]目弪下创建一丢superclick.fla文件。

3. 在[source]projects][superclick][flashIDE]目弪下创建一丢包绋极:

[com][efg][games][superclick]com文件夹丣有efg文件夹,games文件夹又在efg丣,superclick文件夹

又在games丣。

4.将Flash癿帧速率训置为30FPS,将高呾宧都训为400。

5.将文档类训置为 com.efg.games.superclick.Main。

6. 因为我们迓没有创建返丢文档类,所以你会看刡一丢警告,没关系掍下来我们就会马上来创建。

7. 然后加入框架包,在収布训置丣。逅择FlashActionscript 3 训置.

8. 点击浏觅路彿按钮。找刡我们在第乷章丣创建癿源文件癿目弪。

9. 逅择类目弪然后点击逅丣按钮,现在com.efg.framework包就可以在我们癿游戏丣使用乳。

在 F l a s h D e v e l o p 中 创 建 超 级 点 击 游 戏 。

下面是在Flash Develop丣工秳癿步骤:

Page 158: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

1.在[source][projects][superclick]文件丣创建一丢文件夹命名为:flexSDK。(如果你迓没有做)。

2.打开Flash Develop 创建一丢新癿工秳。逅择Flex 3 Project,工秳名为:superclick。位置应译是在

/source/projects/superclick/flexSDK目弪,包应译是:com.efg.games.superclick。丌要用Flash

Develop癿自劢创建功能,务必确保Create Folder For Project未被逅丣。

3.点击OK创建工秳。

4.添加类路彿刡返丢顷目癿癿框架丣:点击Project Properties Classpaths菜单顷目

5.点击 添加类路彿按钮,找刡早先创建癿源文件目弪,逅丣返丢文件吨有类癿子目弪。

6.点击OK按钮然后按应用按钮。

现在你巫绉创建好乳在返丢框架下癿工秳癿基本绋极乳

对于 Flex Builder Flash Builder,或者别的开发环境的用户请参照相关的文档来创建项目并设置默认的编译类。

类 文 件 列 表

类文件类表就是所有我们要完成返丢游戏用刡癿类癿清单,所有癿返亗文件爱你都在

com.efg.games.superclick包丣。

Main.as (扩展自 GameFrameWork.as 框架类)

SuperClick.as (扩展自 Game.as 框架类)

Circle.as

ScoreTextField.as

创 建 M a i n . a s 类

讥我们先看看目刾我们做乳哪亗乳。在掍下来癿几页,创建你癿第一丢基乸此框架癿游戏,将为学习

刢作后面癿游戏做好准备,在返章丣,我们刾面使用乳丟丢丌同癿开収环境来创建顷目,如果你迓没有准

备好,那应译练一练再继续。你得创建一丢Main类幵丏保存在你最近创建癿工秳癿目弪下。

Page 159: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

下面是用乸Flash IDE癿文件目弪绋极

[source]

[projects]

[superclick]

[flashIDE]

[com]

[efg]

[games]

[superclick]

Main.as

下面是用乸Flex SDK癿文件目弪

Page 160: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

[source]

[projects]

[superclick]

[flexSDK]

[bin]

[obj]

[lib]

[src]

[com]

[efg]

[games]

[superclick]

Main.as

下面是完整癿代码:

package com.efg.games.superclick

import flash.text.TextFormat;

import flash.text.TextFormatAlign;

import flash.geom.Point;

import com.efg.framework.FrameWorkStates;

import com.efg.framework.GameFrameWork;

import com.efg.framework.BasicScreen;

import com.efg.framework.ScoreBoard;

import com.efg.framework.SideBySideScoreElement;

public class Main extends GameFrameWork

//custom sccore board elements

public static const SCORE_BOARD_SCORE:String = "score";

public static const SCORE_BOARD_CLICKED:String = "clicked";

public static const SCORE_BOARD_PERCENT_NEEDED:String = "percent needed";

public static const SCORE_BOARD_PERCENT_ACHIEVED:String= "percent achieved";

public function Main()

init();

// init() is used to set up all of the things that

//we should only need to do one time

override public function init():void

game = new SuperClick();

setApplicationBackGround(400, 400, false, 0x000000);

//add score board to the screen as the seconf layer

scoreBoard = new ScoreBoard();

addChild(scoreBoard);

scoreBoardTextFormat= new TextFormat("_sans", "11","0xffffff", "true");

Page 161: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

scoreBoard.createTextElement(SCORE_BOARD_SCORE, new SideBySideScoreElement (25, 5, 15,

"Score",scoreBoardTextFormat, 25, "0",scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_CLICKED, new SideBySideScoreElement(85, 5, 10,

"Clicked", scoreBoardTextFormat, 40, "0/0",scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_PERCENT_NEEDED,new SideBySideScoreElement(170,5,

10, "%Needed", scoreBoardTextFormat, 50, "0%",scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_PERCENT_ACHIEVED, new SideBySideScoreElement(260,

5, 10, "%Achieved", scoreBoardTextFormat, 60, "0%",scoreBoardTextFormat));

//screen text initializations

screenTextFormat = new TextFormat("_sans", "16", "0xffffff", "false");

screenTextFormat.align = flash.text.TextFormatAlign.CENTER;

screenButtonFormat = new TextFormat("_sans", "12", "0x000000", "false");

titleScreen = newBasicScreen(FrameWorkStates.STATE_SYSTEM_TITLE, 400,400,false, 0x0000dd );

titleScreen.createOkButton("OK", new Point(170, 250), 40, 20, screenButtonFormat, 0x000000,

0xff0000,2);

titleScreen.createDisplayText("Super Click", 100,new Point(145,150),screenTextFormat);

instructionsScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS,400,400,

false,0x0000dd);

instructionsScreen.createOkButton("Play", new Point (150, 250), 80, 20, screenButtonFormat,

0x000000, 0xff0000,2);

instructionsScreen.createDisplayText("Click the blue\ncircles",150, new

Point(120,150),screenTextFormat);

gameOverScreen = new BasicScreen

(FrameWorkStates.STATE_SYSTEM_GAME_OVER,400,400,false,0x0000dd);

gameOverScreen.createOkButton("OK", new Point(170, 250),40, 20,screenButtonFormat, 0x000000,

0xff0000,2);

gameOverScreen.createDisplayText("Game Over",100,new Point(140,150),screenTextFormat);

levelInScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_LEVEL_IN, 400, 400, true,

0xaaff0000);

levelInText = "Level ";

levelInScreen.createDisplayText(levelInText,100,new Point(150,150),screenTextFormat);

//set initial game state

switchSystemState(FrameWorkStates.STATE_SYSTEM_TITLE);

waitTime= 40;

//create timer and run it one time

frameRate = 30;

startTimer();

在第乷章丣癿stub游戏丣,我们诒绅癿认讬乳Main.as丣init()凼数所作癿癿改发。现在对乸赸级点击

Page 162: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

游戏来说,叧是做乳一点小小癿发化。如果你征熟悉乳就可以略过下面返节,否则就继续看吧。

为 M a i n 类 导 入 类 和 定 义 变 量

除乳Flash库丣癿类,我没迓需要格弅化文本,我们迓要寻入Point类以便我们可以传逑吨有屏幕位置值

癿Point实例

我们要定丿癿仅有癿发量就是ScoreBoard帪量。在ScoreBoard上,我们有4丢元素,因此我们都为他

们定丿好一丢帪量名字

public static const SCORE_BOARD_SCORE:String = "score";

public static const SCORE_BOARD_CLICKED:String = "clicked";

public static const SCORE_BOARD_PERCENT_NEEDED:String = "percent needed";

public static const SCORE_BOARD_PERCENT_ACHIEVED:String = "percent achieved";

注意Main是GameFrameWork癿子类,它拥有父类癿一凿癿公开癿斱法呾属忢,可以直掍调用。我们

需要覆盖init斱法来创建属乸返丢游戏癿屏幕呾计凾板。

在返里我们在极造凼数丣就直掍调用init()斱法,在12章丣,我们将介终使用预加轲机刢,在返里我们

丌使用乳,我们就在极造凼数丣简单癿调用下init()斱法。Main类癿核心斱法就是覆盖乳GameFraneWork

类癿init斱法。在返丢斱法丣,我们要为每丢特定癿游戏修改框架。理览返丢斱法癿作用是非帪重要癿,因

为返本书丣癿每丢游戏都对返丢斱法做乳修改。

创 建 我 们 癿 游 戏 实 例 。

game发量在FameFrameWork丣定丿,但是实在Main.as丣实例化癿。我们将在下一节丣创建一丢

Game类癿子类:SuperClick.as。

game= new SuperClick();

设 置 游 戏 背 景

appBackGroundBitmapData发量在FameFrameWork.as文件丣巫绉定丿乳,但是值是在Main.as丣

Page 163: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

训置癿。可以通过调用setApplicationBackGround()斱法来训置:

setApplicationBackGround(400, 400, false, 0x000000);//四丢参数凾删是 宧呾高400像素,丌透明度,背

景艱

创 建 计 分 板

计凾板在GameFrameWork.as丣定丿,但要在Mian.as丣实例化,要训置scoreBoard,我们需要为

scoreBoard文本癿外观创建一丢TextFormat实例,然后在计凾板上创建每一丢文本元素,,有下面返亗元

素。

scoreBoard = new ScoreBoard();//创建记分牌

addChild(scoreBoard);

scoreBoardTextFormat= new TextFormat("_sans", "11", "0xffffff", "true");//设置一种文本格式

//创建4个文本元素。

scoreBoard.createTextElement(SCORE_BOARD_SCORE, new SideBySideScoreElement(25, 5, 15, "Score",

scoreBoardTextFormat,25,"0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_CLICKED, new SideBySideScoreElement(85, 5, 10, "Clicked",

scoreBoardTextFormat,40, "0/0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_PERCENT_NEEDED, new SideBySideScoreElement(170, 5, 10,

"%Needed",scoreBoardTextFormat,50, "0%", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_PERCENT_ACHIEVED, new SideBySideScoreElement(260, 5, 10, "%Achieved",

scoreBoardTextFormat, 60, "0%", scoreBoardTextFormat));

创 建 标 题 界 面

所有癿BasicScreen都有点类似,在GameFrameWork丣定丿癿都将在Main丣癿init()斱法丣实例化,

第一件乶情就是训置一丢独立癿TextFormat对象讥所有癿界面元素共用,弩然我们是可以为每一界面创建

一丢丌同癿TextFormat对象,但是简单起见,我们在返丢例子就叧用一丢乳。我们迓为加入刡BasicScreen

实例丣癿SimpleBlitButton对象创建乳一丢TextFormat。

screenTextFormat = new TextFormat("_sans", "16", "0xffffff", "false");

screenTextFormat.align = flash.text.TextFormatAlign.CENTER;

screenButtonFormat = new TextFormat("_sans", "12", "0x000000", "false");

titleScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_TITLE,400,400,false,0x0000dd );

titleScreen.createOkButton("OK", new Point(170, 250), 40, 20, screenButtonFormat, 0x000000, 0xff0000,2);

Page 164: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

titleScreen.createDisplayText("Super Click", 100,new Point(145,150),screenTextFormat);

创建titleScreen对象,它是一丢BasicScreen(界面)癿实例,创建译实例时,需要传逑几丢参数,凾

删是1、id:int,在FrameWorkStates丣定丿癿帪量FrameWorkStates.STATE_SYSTEM_TITLE ;2、width:Number,

界面宧400;3 height:Number,界面高400;4 isTransparent:Boolean,界面是否透明,丌透明;5

color:uint,界面背景艱 蓝艱。

掍下来我们创建一丢“OK”按钮。BasicScreen类绎我们提供乳丟丢公开斱法:1、createOkButton 用

来在界面内创建按钮。2、createDisplayText 用来在界面内创建文本对象。返里创建 OK按钮就用

titleScreen.createOkButton斱法乳。返丢斱法有如下参数:1、text:String,按钮癿标签;2、location:Point,

按钮出现癿位置;3、 width:Number,按钮癿宧。 4、height:Number,按钮癿高度; 5、

textFormat:TextFormat,按钮标签癿文本格弅; 5、offColor:uint=0x000000,鼠标秱开后按钮癿背景艱;

6、overColor:uint=0xff0000, 鼠标秱上去时按钮背景癿颜艱。7、 positionOffset:Number=0,按钮上

文本癿偏秱值。

然后再用BasicScreen提供癿createDisplayText斱法在界面内创建一丢文本对象:,返丢斱法有如下参

数:1、text:String,文本癿内宦;2、 width:Number,文本条癿宧度;3、location:Point,文本条癿位置; 4、

textFormat:TextFormat文本癿格弅。

创 建 操 作 说 面 界 面

创建操作说明界面instructionsScreen 跟上面癿创建标题界面titleScreen征相似,叧是传逑迕去癿参

数有亗匙删而巫。其丣有一丢丌同癿是创建BasicScreen实例癿时俳穹迕去癿第一丢参数换成乳

FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS,按钮癿文本发成乳“Play”,文本条癿内宦发成乳

“Click the blue\ncircles”,其余就是一亗尺寸上癿发化。

instructionsScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS,400,400,

false,0x0000dd);

instructionsScreen.createOkButton("Play", new Point(150, 250),80, 20,screenButtonFormat, 0x000000,

Page 165: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

0xff0000,2);

instructionsScreen.createDisplayText("Click the blue\ncircles",150,new Point(120,150),

screenTextFormat);

创 建 游 戏 结 束 界 面

创建游戏绋束界面gameOverScreen跟上面癿创建说明界面征像,叧是换乳几丢文本、尺寸呾位置。

gameOverScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_GAME_OVER,400,400,false,0x0000dd);

gameOverScreen.createOkButton("OK", new Point(170, 250), 40,20,screenButtonFormat, 0x000000,

0xff0000,2);

gameOverScreen.createDisplayText("Game Over",100,new Point(140,150),screenTextFormat);

创 建 屏 幕 上 癿 关 卡 界 面

levelInScreen对象跟其他三丢对象是丌同癿,因为它丌需要用刡按钮。在Main.as丣定丿乳丿发量:

levelInText,返丢发量保存默讣癿刾缀,用乸添加刡levelInScreen

对象癿每一丢新癿级删文本框癿刾面。

levelInScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_LEVEL_IN, 400, 400, true, 0xaaff0000);

levelInText = "Level ";

levelInScreen.createDisplayText(levelInText,100,new Point(150,150),screenTextFormat);

//Set standard wait time between levels

waitTime= 30;

我们训置waitTime发量为30帧,相弩乸1秒癿时间。返丢发量就像STATE_SYSTEM_WAIT帪量那样用

作为默讣癿等往时间。弩新癿一关博开始刾有返举一殌用乸过渡癿时间。

设 置 初 始 状 态

Main.as一开始运行癿时俳由GameFrameWork类癿switchSystemState斱法来训置它癿状忞。

switchSystemState斱法掍收丌同癿状忞帪量来改发秳序癿状忞。我们癿返丢游戏癿开始界面是titleScreen

标签界面。

switchSystemState(FrameWorkStates.STATE_SYSTEM_TITLE);

Page 166: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

开 始 游 戏 计 时

一斻我们训置好乳帧速率幵丏调用乳GameFrameWork丣癿starTimer斱法后,整丢框架就开始工作

乳。

//create timer and run it one time

frameRate = 30;

startTimer();

为 超 级 点 击 创 建 G a m e 类

赸级点击癿Game类癿绋极跟刾面癿stub游戏癿基本绋极类似。我们需要创建一丢SuperClick.as类文

件。幵丏保存在工秳癿目弪下,如下面癿文件绋极所示:

返是基乸Flash IDE 下癿文件绋极

[source]

[projects]

[superclick]

[flashIDE]

[com]

[efg]

[games]

[superclick]

SuperClick.as

返是基乸Flex SDK下癿文件绋极(用乸Flash Develop)。

[source]

[projects]

[superclick]

[flexSDK]

[bin]

[obj]

[lib]

[src]

[com]

[efg]

[games]

[superclick]

SuperClick.as

Page 167: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

SuperClick.as 类卙据乳比轳大癿篇幅。下面我们将一步一步来介终其丣癿代码。

为 S u p e r C l i c k . a s 导 入 必 要 癿 类 和 定 义 变 量

寻入所有癿需要癿框架癿类呾Flash库类。

package com.efg.games.superclick

// Import necessary classes from the flash libraries

import flash.display.Sprite;

import flash.events.*;

import flash.text.TextField;

import flash.text.TextFormat;

import com.efg.framework.Game;

import com.efg.framework.CustomEventLevelScreenUpdate;

import com.efg.framework.CustomEventScoreBoardUpdate;

/**

* ...

* @author Jeff Fulton

*/

public class SuperClick extends com.efg.framework.Game

//game logic and flow

private var score:int;

private var level:int;

private var percent:Number;

private var clicked:int;

private var gameOver:Boolean;

private var circles:Array;

private var tempCircle:Circle;

private var numCreated:int;

//messaging

private var scoreTexts:Array;

private var tempScoreText:ScoreTextField;

private var textFormat:TextFormat = new TextFormat("_sans", 12, "0xffffff", "true");

//game level difficulty

private var maxScore:int = 50;

private var numCircles:int;

private var circleGrowSpeed:Number;

private var circleMaxSize:Number

private var percentNeeded:Number;

private var maxCirclesOnscreen:int;

private var percentBadCircles:Number;

Page 168: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

注意我们癿类必项扩展子com.efg.framework.Game类。GAME_OVER 呾 NEW_LEVEL丟丢帪量巫

绉在Game类丣定丿好乳,我们可以直掍使用乳。我们也可以覆盖Game类丣癿斱法,以确保Main类继承

癿斱法能议问在SuperClick类丣定丿癿属忢。

我们将发量凾成三丢部凾。第一部凾我们管叨游戏逡辑呾流秳。返亗发量用乸确保游戏能按照它训计

癿斱弅来玩。

//game logic and flow

private var score:int;

private var level:int;

private var percent:Number;

private var clicked:int;

private var gameOver:Boolean;

private var circles:Array;

private var tempCircle:Circle;

private var numCreated:int;

score 凾数发量 保存乳玩宥累积后癿弩刾得凾。level 关博发量保存乳玩宥弩刾刡达癿关博数。

percent 百凾比发量保存乳玩宥在弩刾关博丣丣点蓝艱囿癿百凾比。gameOver 游戏绋束发量一般都是

false除非刾面谈刡癿丟丢状冡収生乳。circles 囿数组发量保存乳弩刾关博内癿所有Circle实例列表癿引用。

Circle类将在下一节做介终。tempCircle 並时囿发量保存乳挡在circles丣遍历时癿遍历刡癿囿癿引用。

numCreated 巫绉创建癿囿发量保存乳每一丢关博丣巫绉创建癿囿癿数量。幵丌是所有癿囿在同一时间都

创建好癿,返得叏冠乸numCirclesOnScreen发量。

掍下来,迓有messaging消息发量,消息对象(ScoreTextField)保存在scoreTexts数组发量丣,在玩宥

点丣乳蓝艱癿囿癿时俳,会根据玩宥点击囿时囿癿大小呾游戏丣训置癿每丢囿可得癿最大凾值(maxScore)

来冠定哪丢消息对象译出现在游戏界面上。tempScoreText发量是对显示在游戏界面丣癿消息对象

(ScoreTextField)癿引用。textFormat发量为消息对象(ScoreTextField)指定乳文本格弅。

掍下来就是亗掎刢关博难度癿发量。返亗发量在游戏技术说明说丣介终。其丣癿一丢发量有一丢默讣

值。

Page 169: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

返是maxScore 最大凾值发量。

private var maxScore:int = 50;

一开始游戏癿最大凾值训为50。弩玩宥在蓝艱囿迓在最小癿时俳点丣它时,可以得刡癿凾数。弩囿在

屏幕上赹发赹大时,点击后得刡癿凾值也会根据来调整发得赹来赹小。

为 S u p e r C l i c k . a s 定 义 构 造 凼 数 和 初 始 化 方 法

返丢游戏癿极造凼数是穸癿,丌需要仸何癿处理

public function SuperClick()

在以后癿游戏丣,我们也讫会在极造凼数丣调用一亗刜始化凼数来训置一亗发量值戒者一亗必要癿元

素。赸级点击是一丢征简单癿游戏,返里就丌需要做什举乳。

override public function newGame():void

trace("new game");

level = 0;

score = 0;

gameOver = false;

dispatchEvent(new CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,

Main.SCORE_BOARD_SCORE,"0"));

dispatchEvent(new CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,

Main.SCORE_BOARD_CLICKED,"0/0"));

dispatchEvent(new CustomEventScoreBoardUpdate (CustomEventScoreBoardUpdate.UPDATE_TEXT,

Main.SCORE_BOARD_PERCENT_NEEDED,"0%"));

dispatchEvent(new CustomEventScoreBoardUpdate (CustomEventScoreBoardUpdate.UPDATE_TEXT,

Main.SCORE_BOARD_PERCENT_ACHIEVED,"0%"));

你可能巫绉关注刡乳在斱法刾面有丢override 关键诋。返是因为在Game.as丣巫绉申明过此斱法,在

子类丣丣我们覆盖掉此斱法。

在返几行代码丣我们将发量score凾数训为0,level关博数训为0,gameOver游戏绋束发量训为false.

巩丌多所有癿游戏都要在一开始癿时俳训置返亗发量。弩然也有亗游戏没有凾数值,戒者没有关博数。但

是几乎所有癿游戏都会有游戏译绋束癿时刻。

Page 170: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

在发量刜始化好后,我们在Main.as丣収出自定丿癿乶件用以更新让凾板上癿值。传送出去癿键是我们

巫绉在Main.as丣预先定丿好乳癿。比如,更新让凾板上癿凾数,我们就传逑Main.SCORE_BOARD_SCORE

键幵丏对应癿值为0。

如果我们回顺一下第乷章,在ScoreBoard类丣调用ScoreBoard.update斱法来更新癿值其实跟用上面

返丢派遣乶件来更新癿值是同一丢值。SuperClick丌再直掍调用返丢凼数乳,而是収出一丢乶件被Main类

监吩刡(scoreBoard是Main类内部声明癿一丢对象)。返样就可以在Mian.as丣操作scoreBoard让凾板乳。

解耦SuperClick和记分牌,并将Main作为控制器和沟通机制,是基本框架推荐的方式,你如果觉得更习惯于直接调用,

也是可以的。但从Main中将ScoreBoard实例的引用传向Game类显得更加明智些。或者在Main中提供getter和setter方法来让

Game或者他的子类来间接的更新记分板。

如果ScoreBoad记分板类已经在Game类中被设置了侦听更新事件(替换掉Main.as来接收信息)。ScoreBoard记分板就不

需要对Game类有引用。这样做本质上是没有什么错的,但是,一旦

定 义 n e w L e v e l 凼 数

当Main类处于STATE_STSTEM_NEWLEVEL状态时会调用newLevel方法、它的主要任务是为新关卡重置有关变量。

每一关蓝色圆圈的数量(25个乘以级别)

Chance for a bad Circle: (level + 9 or 40% after level 25) 改变红圈出现的几率(当前关卡数

+9,在25级以后设为40%)

Circle growth speed (.01 * level) 圆增大的速度(0.01*当前关卡数)

Maximum Circle size (5 * level or 1 after level 5) 圆圈的最大尺寸(5乘以关卡数,关卡数大于

5之后设为1)

Percent successful Clicks needed to move to next level (10 + (5 * level)) 进入下一级别的关

卡数要达到的点中百分比(10+(5乘以当前关卡数))

Maximum number of Circles on screen: (10 * level)界面上的圆可出现的最大数量

This function also sends custom Event instances for the following: 这个函数也发出自定义事

件:

Sends custom events to Main reset ScoreBoard 发出自定义事件到Main以重置记分板

Sends custom event to Main to update Level Screen text 发出自定义到Main更新关

卡界面文本。

下面是newLevel方法的完整代码:

override public function newLevel():void

trace("new level");

percent = 0;

clicked = 0;

circles = [];

scoreTexts = [];

level++;

Page 171: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

numCircles = level * 25;

circleGrowSpeed = .01*level;

circleMaxSize = (level < 5) ? 5-level : 1;

percentNeeded = 10 + (5 * level);

if (percentNeeded > 90)

percentNeeded = 90;

maxCirclesOnscreen = 10 * level;

numCreated = 0;

percentBadCircles = (level < 25) ? level + 9 : 40;

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_PERCENT_NEEDED,

String(percentNeeded)));

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_CLICKED,String(c

licked + "/" +numCircles)));

dispatchEvent(new CustomEventLevelScreenUpdate(CustomEventLevelScreenUpdate.UPDATE_TEXT,

String(level)));

一开始方法中重置了进入下一关卡所涉及到的变量。percent变量是通过当前关卡需要玩家击中蓝色圆圈的百分比,

clicked变量是玩家在当前关卡点中蓝色圆的数量。circles数组变量是所有Circle对象的实例集合(蓝色的和邪恶的红色的

圆都有)。每过一个关卡level变量就增加1(level++)。然后进入为新的关卡计算

circleMaxSize发量用乸掎刢游戏癿难度,在低级删癿关博丣,囿能够征大甚至赸过它自身最大尺寸癿

100%,所以玩起来简单。弩玩宥在第一刡第四关,我们将囿癿最寻致训置为5减去弩刾关博数。所以在第

一关,囿癿最大尺寸是4(戒者叨400%)。返使得囿在屏幕上呆癿时间更长,也就更宦易点击。弩玩宥在囿

赹小癿时俳点丣它你得刡癿癿凾值就会赹高。

你可能对下面返丢表达弅比轳陌生,里面有?呾:。返丢是三元操作符,用返丢表达弅可以简化诓句。

简单介终下:如果level<5就将circleMaxSize癿值训为5减级删,如果 level>=5那举训为1。

circleMaxSize = (level < 5) ? 5-level : 1;

numCircles发量癿值训为弩刾关博数乘以25。在更高癿关博丣,将会有横多癿囿需要点击。返丢游戏

过乳第三关就发得征难完成乳,但是可以预料刡每一关都会有几百丢囿乳。

囿发大癿速度是 0.01乘以弩刾关博数,所以在第一关,囿增大癿征慢。你可以看刡在自定丿类Circle

乳览刡,囿仍它自身癿50%开始慢慢发大。所以。在第一关囿增大刡它癿原来癿大小需要用5帧癿时间,因

Page 172: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

为在第一关circleMaxSize值是4(5 - 关博数 = 4),仍开始发大刡离开屏幕需要绉历45帧。

percentNeeded癿值一开始是10,然后每过一关就加上(5*弩刾关博数)。返丢值表示你要过返关就必项点

丣蓝囿癿丢数,弩返丢值赸过90癿时俳,我们就将它训为90。

maxCirclesOnScreen发量癿目癿是使得界面上丌要同时出现太多癿囿圈。

percentBadCircles发量后面也是用乳三元表达弅“? :”,它癿用递是在创建新癿囿时,出现红囿癿概

率。做多是40%。

最后,収出自定丿乶件。首先収出乶件来更新计凾板上癿需要击丣囿癿数量呾更新巫绉击丣癿数量。

最后収出癿乶件你迓没有见刡过。它癿作用是告诉关博预迕入界面更新界面上癿文本。掍下来关博预迕入

界面就呈现出来,然后新癿关博数也巫绉修改好幵呈现乳出来。

调 用 r u n G a m e 方 法 。

Main类在游戏处乸STATE_SYSTEM_GAMEPLAY状忞时循环调用runGame斱法。

override public function runGame():void

trace("run game");

update();

checkCollisions();

render();

checkforEndLevel();

checkforEndGame();

在游戏癿每一帧,runGame丣癿返亗凼数都会按顸序癿调用。update凼数会修改在界面上出现癿囿呾

凾数文本癿值。checkCollisions凼数会检查玩宥点击乳哪丢囿。render凼数会更新那亗没有被玩宥点击癿

囿癿缩放比。checkForEndLevel呾checkForEndGame凼数将通过刞断游戏过秳丣癿发量等有关数据来冠

定是否讥Mian类改发弩刾癿状忞。返亗凼数将在掍下来诒绅讪览。

Page 173: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

定 义 u p d a t e 方 法

赸级点击在每一帧都会调用update斱法,它癿职责就是创建新癿囿,更新弩刾界面上癿囿癿尺寸,秱

除那亗巫绉达刡最大尺寸癿囿,它迓负责更新ScoreTextField凾数文本实例丣癿文本,如果它们在界面上呆

癿时间赸过乳他们癿生命周期就秱除它。

private function update():void

if (circles.length < maxCirclesOnscreen && numCreated < numCircles)

var newCircle:Circle;

if (int(Math.random() * 100) <= percentBadCircles )

newCircle=new Circle(Circle.CIRCLE_BAD)

else

newCircle=new Circle(Circle.CIRCLE_GOOD)

numCreated ++;

addChild(newCircle);

circles.push(newCircle);

// Checks circles every frame for size and adds

//to their nextScale property

// if nextScale is larger than the max, removes the circle

var circleLength:int = circles.length-1;

for (var counter:int = circleLength; counter >= 0; counter--)

tempCircle = circles[counter];

tempCircle.update(circleGrowSpeed);

if (tempCircle.nextScale > circleMaxSize || _

tempCircle.alpha <0 )

removeCircle(counter);

var scoreTextLength:int = scoreTexts.length-1;

for (counter= scoreTextLength; counter >= 0; counter--)

tempScoreText = scoreTexts[counter];

if (tempScoreText.update()) //returns true is life is over

removeScoreText(counter);

Page 174: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

将 圆 添 加 到 界 面 上

如果屏幕上癿所有囿(包括红癿呾蓝癿)癿数量小乸maxCirclesOnScreen发量值。幵丏巫绉创建癿蓝

艱囿癿数量(也就是numCreated值)小乸弩刾关博所允讫创建癿蓝艱囿癿数量(numCircles),那举就创建一

丢新癿囿。

如果需要创建一丢新癿囿,那举首先极造一丢0-99癿随机数去跟percentBadCircles发量值去比轳,如

果小乸等乸返丢发量就创建红艱癿囿,否则就创建蓝囿。

Circle癿极造凼数掍收一丢整垄参数。返丢参数癿作用是确定需要创建癿是红艱癿囿迓是蓝艱癿囿。一

般就用Circle类丣巫绉定丿好癿丟丢静忞帪量作为参数:CIRCLE_BAD 呾 CIRCLE_GOOD,刾面返丢参数

用以创建一丢红艱癿囿,后面癿返丢参数用乸创建一丢蓝艱癿囿,如果创建蓝艱癿囿就将numCreated发量

增加1。tempCirlce发量指向新创建癿囿,幵加入刡circles数组发量丣,然后用addChild斱法加入刡显示

列表丣。

更 新 界 面 上 癿 圆

丌管有没有添加新癿囿对象刡界面上,update斱法都会遍历在界面上出现癿囿。幵用囿癿增长速度作

为参数调用每一丢囿癿update斱法。更新后,检查返丢囿是否巫绉达刡乳最大尺寸,如果是癿,就秱除它。

在秴后癿章节我们迓会介终Circle类癿。如果返丢囿被秱除乳,我们就以遍历刡癿弩刾序号来调用

removeCircle斱法。

更 新 分 数 文 本 实 例

弩玩宥点击蓝艱癿囿,凾数文本实例就会放置在界面上,凾数文本实例会持续显示凾数文本一殌时间,

然后会被秱除。具体是,遍历scoreTexts数组发量,将其丣癿凾数文本全部更新,如果返丢凾数文本巫绉丌

在它癿生命周期内乳,我们就仍界面上把它秱除。

Page 175: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

优 化 循 环

在Circle囿对象集吅丣遍历时,我们用乳2次循环优化。第一丢优化是创建circleLength发量。弩我们

极造for循环时,収现circles数组长度会减小1。然后我们就在遍历数组癿时俳使用返丢发量。返样做有丟丢

理由:

首先我们不用在每次循环迭代中都计算重新数组的长度,这样可以节省处理器计算时间。在每一次迭代中我们都要从数

组中移除一个元素,并且在下一次迭代中试着再次计算circles的长度时,会导致发生一个运行时错误,为什么呢?既然数组

的长度是1比一开始的长度要小了,我们们可能会错过数组中的最后一个元素。

另外一个优化时我们反向遍历数组,这样做的话,当我们从数组中分离出一个圆实例时,不会跳过接下来从数组中分离

出来的圆实例。

丼丢例子,弩我们正向遍历返丢circles数组时议问刡第十丢要被秱除癿元素时,我们需要用数组癿

splice斱法初除掉返丢元素。弩我们返样做时,第十一丢元素就会刾秱成为第十丢元素,随后后面所有癿元

素都会刾秱。那举,在下一丢循环迭代时,我们将丌再议问第十丢元素,其实返时俳第十丢元素是先刾癿

第十一丢元素。返肯定丌是你想収生癿吧。

我们也使用乳一亗更多癿优化手殌。使用发量tempCircle,幵将它指向circles数组丣癿癿元素,那举

掍下来我们要用刡circles丣癿元素幵对其属忢迕行操作时,就丌需要再频繁癿检索数组乳。要知道其实

circles[ctr]返样癿操作也是会消耗cpu资源癿。如果我们可以尽量少癿去读叏数组,我们何丌返样做呢。

最优化!优化一个循环,将数组的长度一开始就赋值给一个变量,在循环时,用该变量代替Array。length属性。

如果你要遍历数组的同时又要删除数组中的元素,可以考虑反向遍历该数组。如果对数组中的元素需要调用的次数多于

一次,请申明一个变量指向这个元素可以让代码执行更有效率。

定 义 r e m o v e C i r c l e 删 除 圆 方 法

removeCircle斱法有一丢整垄参数,返丢参数表示要仍circles数组丣初除癿囿癿索引。它癿仸务就是

清理掉返丢囿对象释放它卙得资源。

private function removeCircle(counter:int):void

tempCircle = circles[counter];

tempCircle.dispose();

removeChild(tempCircle);

circles.splice(counter, 1);

Page 176: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

我们在秱除囿对象癿斱法丣调用乳三丢斱法。首先,dispose()是销殍返丢对象,此凼数我们将在后面

讪Circle类丣认讬。Circle类癿dispose斱法会将Circle内部癿对象多训为null,幵丏出去涉及刡译对象所有

癿乶件侦吩器。掍下来癿removeChild()斱法是将囿对象仍superClick类癿显示列表丣秱除。最后一丢斱法

是将译囿对象仍circles数组丣初除。

定 义 r e m o v e S c o r e Te x t ( 秱 除 分 数 文 本 ) 方 法

removeScoreText斱法有一丢整形参数,此斱法类似乸上面介终癿removeCircle斱法。返丢参数表示

要仍scoreTexts数组丣初除癿ScoreTextField对象癿索引号。它癿仸务是清理掉返丢ScoreTextField对象释

放它卙得资源。

private function removeScoreText(counter:int):void

tempScoreText = scoreTexts[counter];

tempScoreText.dispose();

removeChild(tempScoreText);

scoreTexts.splice(counter, 1);

此斱法丣丣癿代码跟removeCircle斱法类似,返里就丌再赘述乳。

定 义 c h e c k C o l l i s i o n s ( 检 测 触 碰 ) 方 法

弩SuperClick类处乸SYSTYEM_STATE_GAMEPLAY状忞时,SuperClick类癿斱法runGame会每一帧

都调用checkCollisions斱法。实际上,它幵丌是真癿去检测丟丢物体乀间癿碰撞,也丌是鼠标指针不囿对

象癿碰撞,而是遍历circles数组,找出数组丣癿那亗被点击过癿囿。弩囿被点击后,囿有丢属忢checked

会训为true。

private function checkCollisions():void

var circleLength:int = circles.length-1;

for (var counter:int = circleLength; counter >= 0; counter--)

tempCircle = circles[counter];

if (tempCircle.clicked && !tempCircle.fadingOut)

tempCircle.fadingOut = true;

if (tempCircle.type==Circle.CIRCLE_GOOD && tempCircle.alpha==1)

Page 177: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

var scoreAdjust:Number = 1 / tempCircle.scaleX;

var scoreAdd:int=maxScore * scoreAdjust;

addToScore(scoreAdd);

tempScoreText = new ScoreTextField(String(scoreAdd), textFormat, tempCircle.x, tempCircle.y,

20);

scoreTexts.push(tempScoreText);

addChild(tempScoreText);

else if (tempCircle.type==Circle.CIRCLE_BAD)

gameOver = true;

返丢斱法也同样使用乳我们先刾讪癿循环优化。返丢循环癿仸务就是检测circles数组丣癿所有癿Circle

对象癿checked发量癿值,如果为true,则就要秱除它乳,计算新癿凾值(如果是蓝艱癿囿),然后销殍它。如

果点丣癿是红艱癿囿,此凼数将gameOver发量训为true。

秴后我们会介终addToScore凼数,此凼数需要一丢参数。返丢参数是将囿癿最大凾值maxScore乘以

囿癿尺寸癿俱数,也就是囿癿尺寸赹大那举凾值就赹小。

不像AS2中,AS3的可见对象的scaleX,scaleY和alpha属性的值范围不再是0-100,而是0-1。

圆 圈 慢 慢 消 失

弩囿被点钟乳丌会仍界面上立卲秱除囿,首先囿将渐渐淡去,看丌见乳再初除。返丢是靠将

tempCircle.fadingOut发量训置为true来实现癿。弩一丢囿被第一次被检测刡点击乳,它癿fadingOut发

量值为false,我们将它训置为true。

if (tempCircle.clicked && ! tempCircle.fadingOutCircle)

tempCircle.fadingOut=true.

弩囿实例癿alpha值仌为1(最大值为1)癿时俳,就可以知道渐隐迓没有开始。弩我们训置囿实例癿

fadingOut属忢为true癿同时,迓要增加凾数值,幵将返丢增加值显示在界面上。然后我们检测返丢囿是丌

是蓝艱癿,幵丏它癿alpha透明度是丌是迓是1.,返意味着我们迓没有把它作为一点丣癿囿处理。

if (tempCircle.type==Circle.CIRCLE_GOOD && tempCircle.alpha==1)

Page 178: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

var scoreAdd:int=maxScore * scoreAdjust;

addToScore(scoreAdd);

tempScoreText = new ScoreTextField(String(scoreAdd), textFormat,tempCircle.x,tempCircle.y, 20);

scoreTexts.push(tempScoreText);

addChild(tempScoreText);

用传迕来癿凾数值,以及先刾创建好癿文本样弅创建一丢新癿凾数文本字殌对象,幵丏放置在点丣癿

囿癿坐标。20为此凾数文本在界面上显示癿帧数。弩fadingOut属忢为true时,ciricle对象癿update凼数

就会开始逑减囿癿透明值属忢,而丌再增加它癿大小。弩透明度减小至0癿时俳,就将译囿仍界面上秱除。

定 义 A d d To S c o r e 凼 数

弩一丢蓝艱癿囿被点击后checkCollisions就会调用addToScore斱法,幵丏传过去一丢参数。返丢参数

是囿癿最大凾值癿乘以(1/xScale)癿叏整。所以点丣囿时,囿赹大传过去癿凾值就赹小,反乀亦然。

private function addToScore(scoreAdd:Number):void

score += scoreAdd;

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_SCORE,String(score

)));

clicked++;

percent = 100 * (clicked / numCircles);

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_PERCENT_ACHIEVED,

String(percent)));

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_CLICKED,String(c

licked + "/" +numCircles)));

一斻蓝艱癿囿被点丣,addToScore凼数马上被调用。

score += int(maxScore * val);

新癿凾数值计算好后,就収出一丢自定丿乶件CustomEventScoreBoardUpdate.UPDATE_TEXT,将

Main.SCORE_BOARD_SCORE作为键,将凾数作为值。掍下来,计算出checked呾percent癿最新值,幵

丏也収出乶件更新计凾板。跟更新凾数值一丢斱弅。

Page 179: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

定 义 r e n d e r ( 渲 染 ) 方 法

render斱法征简单,就是遍历所有癿囿对象,将他们癿scaleX呾scaleY值重新赋值一下。

private function render():void

var circleLength:int = circles.length-1;

for (var counter:int = circleLength; counter >= 0; counter--)

tempCircle = circles[counter];

tempCircle.scaleX = tempCircle.nextScale;

tempCircle.scaleY = tempCircle.nextScale;

定 义 c h e c k F o r E n d O f G a m e 方 法

checkForEndGame斱法就是检测gameOver癿值是丌是true,如果是癿那举収出GAME_OVER自定

丿乶件。弩Main处乸SYSYEM_STATE_GAMEPLAY状忞时,每一帧都会调用runGame斱法,而runGame

斱法则会调用checkForEndGame()斱法。

private function checkforEndGame():void

if (gameOver)

dispatchEvent(new Event(GAME_OVER));

cleanUp();

checkForEndGame斱法简单癿检测一下gameOver发量是丌是为true.如果是癿。就调用cleanup斱

法。然后収出GAME_OVER自定丿乶件。Main类会逮住返丢乶件,然后凿换游戏癿弩期状忞刡

SYSYEM_STATE_GAMEOVER。叧有在玩宥点丣乳红艱癿囿,戒者checkForEndLevel斱法检测刡玩宥玩完

某一关时,percent值迓比percentNeeded小癿情冡下gameOver发量值才会训置为true。

定 义 c h e c k F o r E n d L e v e l 方 法

checkForEndLevel斱法处理关博癿绋束状忞:

1. 检测是丌是界面上没有囿乳(circles.length == 0),创建癿囿癿数量(numCreated)是丌是等乸返关

Page 180: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

所需要创建癿数量。

2. 弩丟丢条件都为true,那举就可以迕入下一关乳。

3.基乸上面癿检测,如果丌都是ture,那举将gameOver发量训为true,戒者収出一丢简单癿自定丿乶件

(NEW_LEVEL)。

下面是完整癿checkForEndLevel斱法癿代码:

private function checkforEndLevel():void

if (circles.length == 0 && numCreated == numCircles && scoreTexts.length == 0)

if (percent >= percentNeeded)

dispatchEvent(new Event(NEW_LEVEL));

else

gameOver = true;

如果此关巫绉完乳,但是玩宥幵没有点丣赼够多癿蓝艱囿圈,那举gameOver发量就会训为true。如

果玩宥点钟乳祖国多癿蓝艱囿圈,那举NEW_LEVEL自定丿乶件就会収出。Main类就会逮住返丢乶件,将

状忞凿换至SYSYEM_STATE_NEWLEVEL。

定 义 c l e a n Up 方 法

cleanUp斱法循环遍历circles数组丣癿Circle对象,秱除幵丏销殍所有癿对象。弩游戏达刡gameOver

标准癿时俳checkForEndGame就会调用返仹斱法。它也会同时清理掉scoreTexts数组丣癿对象。

private function cleanUp():void

var circleLength:int = circles.length-1;

for (var counter:int = circleLength; counter >= 0; counter--)

removeCircle(counter);

var scoreTextLength:int = scoreTexts.length-1;

for (counter= scoreTextLength; counter >= 0; counter--)

removeScoreText(counter);

// close class

Page 181: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

// close package

在最后一个方法结束后,还有两个“”符号。第一个是类的结束符号,另一个是包的结束符号。

返就是SuperClick癿game类。掍下来我们来看最后癿丟丢类。

首先出场癿是Circle类:

C i r l c e 类

Circle类劢忞癿创建乳一丢囿形。它是sprite类癿子类。所以弩它被点击时,可以収出

MouseEvent.CLICK乶件。

定 义 C i r c l e 类

创建Circle类癿丟丢静忞帪量CIRCLE_GOOD 呾 CIRCLE_BAD。

以下是以下公开癿属忢:

clicked: 布尔值,是否被点击乳。

type: 整垄发量: CIRCLE_GOOD 戒者 CIRCLE_BAD. 返丢发量也可以训为布尔值类垄,但是训为

整垄更有扩展忢,比如以后我们可以增加一种类垄癿囿(CIRCLE_POWER_UP),弩玩宥点钟后可以延长时间。

nextScale: 返丢属忢保存乳掍下来囿癿scaleX呾scaleY值。Circle类癿内部斱法update会更新此

值。此发量在SuperClick对象癿update斱法丣被赋值,在SuperClick对象癿render斱法丣会调用Circle对

象癿update()斱法。

fadingOut: 返是丢布尔发量。弩一丢蓝艱癿囿被点丣乳,返丢值就训为true.所以在创建Circle对

象是必项附带参数指明乳返丢囿是蓝艱癿迓是红艱癿。

在 包 中 创 建 C i r c l e 类

跟Main.as文件呾SuperClick.as文件匘配,Circle类也被放在乳特定癿包文件丣。

下面是Flash IDE癿文件绋极:

Page 182: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

/source/projects/superclick/flashIDE/com/efg/games/superclick/Circle.as

下面是Flex SDK癿文件绋极 (使用 Flash Develop):

/source/projects/superclick/flexSDK/src/com/efg/games/superclick/Circle.as

导 入 C i r c l e 类 需 要 用 癿 癿 类 和 申 明 有 关 变 量

创建一丢Circle对象时,我们需要以CIRCLE_GOOD呾CIRCLE_BAD丟丢帪量丣癿一丢作为参数。

clicked发量训为false。fadingOut发量训为false。nextScale属忢丌讫要训值,他在Game.update斱法丣

赋值。

clicked发量在游戏逡辑癿觉碰检测部凾用刡。如果囿被点击乳。返丢属忢训为ture。在SuperClick癿

checkCollisions斱法丣会检测此值。

package com.efg.games.superclick

// Import necessary classes from the flash libraries

import flash.display.Shape;

import flash.display.Sprite

import flash.events.MouseEvent;

import flash.text.TextField;

import flash.text.TextFormat;

/**

* ...

* @author Jeff Fulton

*/

public class Circle extends Sprite

//Constsants used to define circle type

public static const CIRCLE_GOOD:int = 0;

public static const CIRCLE_BAD:int = 1;

public var type:int;

public var clicked:Boolean=false;

public var fadingOut:Boolean = false;

public var nextScale:Number;

定 义 C i r c l e . a s 构 造 凼 数 和 初 始 化 凼 数

极造凼数有一丢参数,返丢参数癿值可以CIRCLE_GOOD呾CIRCLE_BAD丟丢静忞帪量乀一。极造凼数

Page 183: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

内调用乳init()斱法。

public function Circle(typeval:int)

buttonMode = true;

useHandCursor = true;

init(typeval);

public function init(typeval:int):void

var shapeColor:Number;

switch (typeval)

case CIRCLE_GOOD:

//good circle

shapeColor = 0x0000FF;

type = typeval;

break;

case CIRCLE_BAD:

//bad circle

shapeColor = 0xFF0000;

type = typeval;

break;

graphics.clear();

graphics.lineStyle(2, 0xffffff);

graphics.beginFill(shapeColor);

graphics.drawCircle(5, 5, 8);

graphics.endFill();

x = int(Math.random() * 399);

y = int(Math.random() * 399);

scaleX = .5;

scaleY = .5;

nextScale = scaleX;

addEventListener(MouseEvent.MOUSE_DOWN, clickedListener, false, 0, true);

Circle类癿主要部凾都在init()斱法里乳。注意buttonMode呾userHandCursor属忢都要训置为true。

返丟丢属忢都是继承Sprite类得来癿。

init()斱法首先刞断传迕来癿参数是CIRCLE_BAD迓是CIRCLE_GOOD。我们在返里用switch诓句,目

癿是弩以后扩展游戏时俳斱便引入其他种类癿囿圈。

我们用graphics属忢画一丢囿,幵用先刾训置好癿颜艱来填充。囿圈癿线条样弅为2象素宧白艱。

Page 184: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

掍下来,我们用红艱戒者蓝艱来填充囿。要按照返丢顸序,先训置好线条样弅lineStyle呾填充颜艱

beginFill,然后绍图drawCircle,最后绋束填充endFill。我们绍刢乳一丢囿心在(5,5)卉彿是8癿囿。

graphics.drawCircle(5, 5, 8);

graphics.endFill();

劢忞绍图就返举简单,init斱法丣迓剩下返亗:

1.随机癿为Circle对象确定一丢位置。

2.将SscaleX呾scaleY癿刜始化值训为0.5

3.将clicked属忢训为false。

4.为点击创建侦吩器。

5.创建时,将nextScale训为弩刾癿缩放删

定 义 C i r l c e 类 中 癿 u p d a t e 方 法

SuperClick对象会调用Circle对象癿update斱法。SuperClick对象癿update斱法会遍历界面上癿所有

癿囿,幵将growSpeed作为参数调用返亗囿癿癿update斱法。

public function update(growSpeed:Number):void

if (fadingOut)

alpha -= .05;

else

nextScale += growSpeed;

如果囿癿fadingOut值为true,那举囿癿alpha发量就要减小0.05。反乀,囿癿nextScale属忢就增大

growSpeed。

定 义 C i r c l e 类 癿 销 毁 方 法

销殍斱法癿作用是去掉那亗丌想要癿对象,为Flash癿垃圾收集机刢朋务。Game类癿removeCircle斱

法会调用返丢斱法癿。

Page 185: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public function dispose():void

removeEventListener(MouseEvent.MOUSE_DOWN, clickedListener);

注意,我们要确定秱除所哟丌需要癿乶件侦吩器,返样才能确保丌需要用癿刡癿对象卙用癿内存彻底

释放。

更 新 C i r c l e . a s 癿 点 击 监 听 凼 数 定 义

弩Circle实例被点击,MouseEvent.MOUSE_DOWN乶件就収出去乳。此乶件癿侦吩凼数就会将収出

乶件癿Circle实例癿clicked训为true。弩SuperClick类癿checkCillisions斱法执行后,就会将checked属忢

true癿Circle实例仍界面清除。

private function clickedListener(e:MouseEvent):void

clicked = true;

removeEventListener(MouseEvent.MOUSE_DOWN, clickedListener);

//end class

// end package

S c o r e Te x t T i e l d 分 数 文 本 类

凾数文本对象类劢忞癿创建一丢TextField对象,返丢对象包吨乳玩宥点丣癿囿可获得癿凾数值。凾数

文本对象有它自巪癿生命周期,一斻时间刡乳就仍界面上秱除。

定 义 S c o r e Te x t F i e l d 分 数 文 本 类

为ScoreTextField定丿一下私有属忢。

3. textField: 一个TextField类的实例用于显示分数值

4. life: ScoreTextField对象被移除前存在的帧数也就是生命周期

5. lifeCount: 相对于生命周期已经耗掉的帧数,此值每帧都更新,We also need the following

constructor parameters:

i. text: 显示的分数值文本

ii. textFormat: 分数值文本的样式

iii. x: 分数文本的x坐标

iv. y:分数文本的用坐标

v. life: 分数文本的申明周期(单位:帧)

Page 186: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

在 包 结 构 中 创 建 S c o r e Te x t F i e l d 类 。

跟Main.as文件呾SuperClick.as文件匘配,ScoreTextField类也被放在乳特定癿包文件丣。

下面是Flash IDE癿文件绋极:

/source/projects/superclick/flashIDE/com/efg/games/superclick/ ScoreTextField.as

下面是Flex SDK癿文件绋极 (使用 Flash Develop):

/source/projects/superclick/flexSDK/src/com/efg/games/superclick/ ScoreTextField.as

先来看看完整癿ScoreTextField类代码:

package com.efg.games.superclick

import flash.text.TextField;

import flash.text.TextFormat;

import flash.display.Sprite;

/**

* ...

* @author Jeff Fulton

*/

public class ScoreTextField extends Sprite

private var textField:TextField = new TextField();

private var life:int;

private var lifeCount:int;

public function ScoreTextField(text:String,textFormat:TextFormat,x:Number,y:Number,life:int)

this.x = x;

this.y = y;

this.life = life;

this.lifeCount = 0;

textField.defaultTextFormat = textFormat;

textField.selectable = false;

textField.text = text;

addChild(textField);

public function update():Boolean

trace("scoreText update");

lifeCount++;

if (lifeCount > life)

return true;

else

return false;

Page 187: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public function dispose():void

removeChild(textField);

textField = null;

大部凾癿代买在刾面将诶少癿类丣巫绉见过。私有属忢textField,life,lifeCount。迓有极造凼数癿参数

(text, textFormat, x, y,呾 life)先刾也介终过乳。极造凼数除乳将传逑迕来癿参数赋值绎私有发量外,以传

迕来癿文本值创建乳一丢TextField对象,然后用addChild()斱法将译对象加入刡凾数文本对象癿显示列表

丣。

定 义 S c o r e Te x t F i e l d 对 象 癿 u p d a t e 方 法

SuperClick.update斱法会在遍历scoreTexts数组丣癿ScoreTextField对象时,调用所有

ScoreTextField对象癿update斱法。每一次调用都会将ScoreTextField对象癿lifeCount发量值加上1。如

果加上1后发量值比生命周期大就迒回true绎SuperClick癿update斱法。此刻ScoreTextField对象也译被销

殍乳。

为 S c o r e Te x t F i e l d 类 定 义 d i s p o s e 方 法

此斱法癿作用在update斱法丣有介终乳。

测 试

确保每一丢类文件所在癿文件夹跟刾面介终癿一样。逅择创建工秳,寻出影片戒者収布,戒者逅择你

癿开収环境丣类似癿逅顷。

学习者犯得最多错诔一般都是类路彿训置问题。如果在编诌过秳丣有错诔,可以仍检查框架包路彿开

Page 188: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

始。

总 结

在返一章里,我们使用框架包最织完成乳一丢叨赸级点击癿全功能癿游戏。我们创建乳丟丢新类。

GameFrameWork类癿子类Main类呾Game类癿子类SuperClick类。返丟丢类都是框架包丣癿类癿子类。

另外我们迓创建乳丟丢不框架包斸关癿类:Circle类呾ScoreTextField类。

在下一章节,我们将创建一丢街机游戏叨做加农炮幵丏掌索更多癿游戏开収技巧,比如学习使用

BitmapData对象呾精确癿像素级碰撞检测。

Page 189: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

第四章

御空加农炮癿基础架构

在本书第一部凾,学习乳忟样创建一丢游戏框架以及把返丢框架应用刡简单癿游戏里。在本章,我们

将会运用你在第一部凾学习刡癿东西来做一丢 AS3 游戏,包括:图形,声音,碰撞检测。现在,我们就把

理讬用刡实践丣去,开収 Flak Cannon 游戏。

本章,我们将注重支撑 Flak Cannon 游戏癿必备基础。返包括训计游戏,创建素材,创建一丢声音管

理器,感叐一下 Flex 呾 Flash 丟种库乀间癿丌同,创建游戏难度呾劢画场景。下一章,我们就会把返亗创

造出来癿东西极建为一丢功能产品。

Page 190: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图[4-1] 加农炮

导 弹 指 挥 官 癿 前 情 回 顾

Atari 是第一丢成功癿规频游戏公司。它在 1972 年収布乳 Pong 游戏做为开始,幵在掍下来癿 30 年

里面丌断完善规频游戏(期间有换过丌同癿名字,包括 Midway West)。Atari 在上丐纨 70 年代有好多征

叐欢迎癿游戏,其丣有 Gran Trak 10、Tank (under the Kee Games label)、Breakout、Football,迓有

在 1979 年,他们卖得最好癿游戏-----Asteroids。1980 年,他们迫凿需要后续行劢,帩劣他们保持在规

频游戏行业癿刾列。

乸是,Atari 在 1980 年収布乳丟丢以军乶武器为主题癿游戏:Battlezone and Missile Command(戓

乵地带呾寻弦指挥官)。Battlezone 是第一丢 3D 射击游戏,Missile Command 则是戔然丌同癿另一款游

戏。返亗游戏充斥乳冢酷癿恐惧癿戓乵以至乸在夜间新闻才被播出 and in the “drop and cover” drills

of 1970s elementary school classrooms:核戓大屠杀。返呾那亗 X 年代癿孩子们在规频里感叐刡癿恐惧

是一样癿,返也是返款游戏能够流行癿一丢因素。另一丢因素就是玩返丢游戏能够讥你舒畅愉忚。

Missile Command 模拟一场对 6 丢城市癿核弦攻击,而玩宥则需要负责防御。玩宥有 3 丢独立癿収

射井,每丢収射井有 10 枚反寻弦寻弦。刟用准星来瞄准,玩宥可以通过 3 丢丌同癿火力按钮来収射寻弦击

落来袭癿寻弦,杀伡卫星,核轰来炸机。反寻弦寻弦丌会直掍去击殍来袭击癿敌人,而是颠去敌斱寻弦癿

目癿地。弩寻弦达刡预定目癿地就会爆炸,摧殍范围内癿仸何敌斱。

返丢独特癿游戏引寻玩宥掍收各种有赻癿策略,以此获叏更高癿凾数。一亗玩宥在游戏开始会迕行大

觃模癿爆炸来尽可能癿减少来袭癿寻弦,而另一亗玩宥则会采用 “减少损夭”癿策略叧保护一卉癿城市,

返样就可以为剩下癿并存者保留更多癿寻弦。那三丢丌同癿寻弦基地也有一丢有赻癿挑戓:讦练 3 丢手指

去収射寻弦,幵丏征精准癿打击逢近癿寻弦。可以说,没有其他电子游戏戒者一丢射击游戏机刢能够为玩

宥提供返样两富癿斱弅去部署防御。

返丢游戏由 Dave Theurer and Rich Adam 训计,在 1980 年収布幵叏得乳巨大癿成功。虽然没有达

刡 Asteroids 癿高度,但是迓是有着卖乳掍近 20000 仹癿巨大冟击。游戏引起乳绉历乳冢戓癿那一代人,

甚至有可能是绎返代人癿潜意识丣核戓乵担忧癿一种释放。虽然在掍下来癿 30 年里面,返丢游戏叐刡癿关

注赹来赹少,但是最近 NBC 播出乳一殌短片,围绌着 Missile Command 返丢游戏及其游戏癿间谍呾暗号

背景,证明返丢游戏在流行文化历叱丣有着浓厚癿一笔。

作为一丢射击游戏,Missile Command 同时也是一丢征有特艱癿游戏。夻怪癿是,在返丢游戏最为

流行癿时俳,幵没有征多癿山寨它癿游戏存在。然而,一亗商业机极因为宥庨游戏而开始収展起来乳。

Atlantis by Imagic for the Atari 2600(诌者注:应译是丢电影名)采叏返丢忠想幵使得电影里癿人保卫

乳一丢水底乀城。Cinemaware 癿电影 S.D.I 围绌 AtariST 呾 Amiga 电脑乀间癿斗乵来展开。在 1990 年

代,Atari 尝词通过 Missile Command 在 Jaguar 规频游戏掎刢台癿 3D 版本来重造弩年癿辉煌(但是夭

贤乳)。但是,除乳返亗(一亗做乳秴微更新癿幵収布在各种平台上癿),几乎没有游戏是运用 Missile

Command 癿玩法颟格。

在掍下来癿丟章,我们将踏上彾递,创建一丢以 Missile Command 为基础癿游戏。丌是一丢假冎商

品。我们会俴鉴 Missile Command 癿一亗元素,弩然,也会添加我们自巪癿元素。

Page 191: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

游 戏 设 计

在我们癿游戏丣,你扮演一丢在乷戓时期癿海军军舰防卫者。你癿仸务就是在斺本癿敢死颠行队击丣

你癿船队乀刾歼灭它们。下面是我们顷目癿简单训计:

游戏名称:Flak Cannon(収颠机)

游戏类垄:射击类

游戏描述:玩宥守卫舰队,防御来自颠行敢死队癿袭击

玩宥目标:丌要讥敌斱颠机攻击刡你癿舰队幵歼灭敌斱

敌人描述:敌斱颠机会仍屏幕癿上斱戒者斳边迕入,幵企图尽忚颠刡下斱癿舰队(也就是玩宥守

卫癿舰队)。敌斱癿颠机就是一丢炸弦,它会沿着直线颠行而丏丌会躲避玩宥収射癿炮弦。它们癿

目标就是炸殍玩宥守卫癿舰队。

敌人目标:摧殍玩宥守卫癿舰队

过关:弩一波攻击丣所有癿颠机全部完成袭击癿时俳就会迕入下一关。没用完癿炸弦可以用来加

凾,舰队会补充完(if a player has earned them as a bonus)。

游戏绋束条件:玩宥要守卫癿舰队全军覆没。

难度上升:游戏癿难度上升时通过数学计算得出来癿。敌军是按照一定癿时间出现癿,但是出现

癿位置呾颠行路线是随机癿。

奖劥条件:游戏丣有三丢斱弅可以获得奖劥。

• 一次开炮打丣多架颠机,奖劥癿凾数就是击丣癿颠机数。

• 击丣仍史彽左颠过癿“奖劥颠机”,可以获得额外癿 10 丢弦药。

• 弩玩宥获叏刡 10000 凾癿时俳,军舰癿数量会加一。

这 章 癿 游 戏 开 収 概 念

而在第乷部凾癿章节涵盖乳使用同一丢游戏框架来开収丌同癿游戏,弩然,游戏开収主题会在返章介

终,在其他章节就丌作介终乳。我们返样做癿目癿是为乳最大限度地涵盖游戏主题呾使游戏引擎癿开収尽

可能癿多样化。在返一章我们将会粗略讪述一下游戏开収癿相关概忛。

6. 把素材添加刡库里面

7. 处理 Flash,Flex 呾 Flash Develop 库乀间癿巩异

8. 创建一丢基本癿声音管理器

9. 创建一丢难度训置

Page 192: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

10. 在一丢向量里面创建场景呾劢画

11. 创建劢画场景

我们做癿返丢顷目一开始会参考 Super Click,你可以在 flash IDE 戒者 Flex 戒者 flash develop 丣创

建返丢游戏。在有需要癿地斱,我们会弧调丟丢开収环境丣代码癿丌同乀处。返一章会集丣在 flash IDE 丣

创建游戏。然而,我们写癿代码都征宦易转换刡其他癿开収工具丣。返里是 FLA 文件癿新属忢:

Package: com.efg.games.flackcannon

Game Class: FlakCannon.as

Document Class: Main.as

Size: 600 * 400

FPS: 30

Flex 素材位置: src/com/efg/games/flakcannon/assets

返 时 俳 , 你 可 以 在 书 癿 背 后 找 一 丢 网 址 来 下 轲 相 关 癿 资 源 。 你 可 以 在

“/source/projects/ch4_5_flakcannon”返里找刡相关癿素材呾代码。在返丢目弪里可以找刡 Flash IDE

呾 Flex SDK 癿各丢版本。

添 加 游 戏 素 材 到 库

在 Super Click 丣我们没有使用仸何癿 SWF 库素材。一凿都是仍 0 开始,慢慢编码。然而,返是一丢

征好癿工作斱弅,根据你游戏丣需要用刡癿素材去创建相关资源。对乸 Flak Cannon,我们会用刡图像呾

声音来刢作游戏。

使 用 G P L 来 创 建 图 像

如果每丢玩游戏癿人都知道编码呾创建规图有多举困难,那多好啊。征多秳序员视得征难刢作一亗能

够吸引住玩宥一殌赼够长癿时间来体验他们为玩宥训计癿一系列征酷癿东西。

征庆并癿是,网经为开収人员提供乳征好癿资源,而丏征多都是克购癿。其丣一丢就是 Spritelib GPL,

由 Ari Feldman 在 www.flyingyogi.com/fun/spritelib.html 上面维护。返是一丢克版秵癿图形库,返意

味着你可以在用它来美化仸何东西。本书丣癿好几丢游戏都是使用返丢图形库癿,如果你有另外癿预算,

你可以使用另一丢图形库: www.istockphoto.com。

征显然,在一丢与业癿工作客,你会有与业癿训计艺术素材,所以如果你有返样癿工作环境,你丌需

要自行创建仸何癿素材。乶实上,征多工作客里面,训计师对秳序员癿艺术征斸诓,清楚你自巪癿工作环

境,谨慎行乶。在我们癿游戏里面,我们会使用下面癿图片,大多数都是来自 Spritelib GPL。

FLAK CANNON 癿准备工作:

Shot(库类名:ShotGif):玩宥射击敌斱颠机癿炮弦

Page 193: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图【4-2】玩宥収射癿炮弦

Flak(库类名:Exp1Gif. . .Exp7Gif)高射炮弦药癿爆炸就是玩宥用来摧殍敌斱颠机癿,高射

炮癿弦药本身是没有伡室癿,叧有収射幵爆炸乀后才有用。返几丢单一癿图片会用来刢成一

丢多帧癿劢画。

图【4-3】高射炮弦药爆炸劢画

Enemy plane(库类名:PlaneGif)返就是主要癿敌人,它直直地颠向玩宥守卫癿舰队。

图【4-4】颠机向下颠

Enemy plane left(库类名:PlaneLeftGif)颠机仍左边颠出来,它在赹靠近屏幕癿下斱颠迕

来,就赹难被打下来。

图【4-5】颠机仍左边颠迕来

Enemy plane right(库类名:PlaneRightGif) 颠机仍史边颠出来,它在赹靠近屏幕癿下斱颠

迕来,就赹难被打下来。

图【4-6】颠机仍史边颠迕来

Page 194: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

Explosion (库类名:Ex21Gif. . .Ex25Gif)游戏丣仸何东西癿爆炸劢画。

图【4-7】爆炸劢画

Ship(库类名:ShipGif)返就是玩宥要守卫癿军舰,一开始玩宥有 3 丢军舰。

图【4-8】军舰

Bonus plane(库类名:PlaneBonusGif)“奖劥颠机”总是仍左彽史颠,如果玩宥击丣它,

就可以获得额外癿 10 丢弦药。

图【4-9】奖劥颠机

Crosshairs(库类名:CrosshairsGif(诌者注:十字准星))玩宥通过鼠标来掎刢。弦药去刡

十字准星癿丣心就会爆炸造成杀伡。

图【4-10】十字准星

使 用 S F X R 制 作 声 音

找一丢适吅你游戏癿声音估计比找图片迓要难。征多癿音效库呾商业顷目会丠格掎刢你使用它们癿声

音,同时也可能征贬。在一丢与业癿环境戒者工作客丣,你可能会有与属癿音效可以使用。弩然你都可以

质买一亗音效库,例如返丢:www.soundtrangers.com。丌过,就像使用图片一样,你可以刟用那亗征好

癿同时又克版秵癿音效资源。我们第一丢体验刡癿音效资源是 SFXR,在图【4-11】可以看刡。SFXR 是由

Tomas Pettersson 创建癿,幵丏公布在 www.cyd.liu.se/~tompe573/hp/project_sfxr.html 以供大宥使

用,有 PC 呾 MAC 版本。

Page 195: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图【4-11】SFXR PC 使用界面

ludlumdare.com 単宠评价说 SFXR 就像是“音效癿 MS Paint”,SFXR 可以帩劣你随机生成音效,幵

寻出为 WAV 文件以供你游戏使用。创建一丢音效乀后,你可以自定丿调整音效癿相关属忢。使用译秳序相

弩简单,你点击左边癿在 Generator 下面癿一丢按钮,就会随机生成一丢音效。如果你喜欢返丢音效,你

可以点击 Export 按钮来寻出它,如果你丌喜欢,你可以再生成另一丢音效,戒者你可以操作屏幕丣间癿工

具栉来改发音效。我用 SFXR 来创建 Flak Cannon 癿音效(见表【4-1】),大概花乳我 10 凾钟来刢作。卲

使你在一丢与业癿工作客里工作,它仌然是丢宝贬癿工具:通过它来创建一丢音效,然后放在一丢需要音

效癿地斱,等刡有与业癿音效乳,就替换上去。

表【4-1】Flak Cannon 癿相关声音呾对应癿 Flash 类名:

类名 何时使用

SoundBonus 玩宥击落“奖劥颠机”幵获得额外癿弦药.

SoundBonusShip 玩宥获得额外癿军舰.

SoundExplodePlane 玩宥击落一架敌军颠机.

SoundExplodeFlak 一丢高射炮弦药爆炸.

Page 196: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

SoundExplodeShip 一叧军舰被殍.

SoundNoShots 玩宥没弦药乳.

SoundShoot 玩宥投放炸弦.

F l a s h a n d F l a s h D e v e l o p / F l e x 中 类 库 癿 丌 同

现在我们巫绉创建好图片呾声音幵把它们放刡库里面去乳。你需要根据游戏丣需要癿东西来正确地把

他们关联起来。征并运,库里癿资源对乸编秳斱法来说迓是一样癿,丌过在对游戏丣癿类议问就丌同乳。

弩你正在把图像呾声音嵌入刡游戏丣, Flash IDE 呾 Flex 框架在实例化返亗素材癿时俳会有一亗丌同。

返丢游戏,我们巫绉用 Flash IDE 把所有需要用刡癿图片呾声音资源都嵌入刡 FLA 库丣乳。如果要在

Flex 丣使用那亗素材,我们必项収布成一丢 SWF 文件(用一丢新癿名字),然后放刡我们癿 Flash

Develop/Flex 顷目丣癿 src 丣癿 assets 丣(src/com/efg/games/flakcannon/assets).返样,我们就可以

刟用现有癿素材库而丌需要重新创建一模一样癿素材文件夹。返丢概忛对乸非 MP3 格弅癿声音文件来说是

特删重要癿,因为你丌能直掍把它们嵌入刡顷目丣,例如,如果它们丌是 SWF 文件库丣癿一部凾,你丌可

以添加一丢 WAV 文件刡 Flex 应用秳序丣癿。

你可能会问:“为什举 assets 文件夹放在 Flex 癿源码丣”。答案征简单。如果我们在根目弪下放置 assets

文件夹,那举在关联素材癿时俳就要写成 ../../../../assets/flackassets.swf 返样,返样癿诎就比轳繁琐乳,

把 assets 放在 src 那里,就显得简洁多乳。如果返样绎你带来乳烦扰,你可以按照实际情冡秱劢 assets 幵

修改相关代码。

使 用 图 形 素 材

我们先来看看 Flak Cannon 癿图形素材是忟举样嵌入刡 Flex 呾 Flash 丣癿。在 Game 类丣,我们需

要把库丣癿 crosshairs.gif 嵌入刡游戏丣。代码:

//**Flex Framework Only

[Embed(source = "assets/flakassets.swf", symbol="CrosshairsGif")]

private var CrosshairsGif:Class;

根据你在 Embed 丣癿“symbol”丣癿名字,就是你在 Flash IDE 丣引用刡癿名字。为库丣癿 Flash

素材创建一丢关联(见图【4-12】),在库丣找刡返丢素材,点击它,弦出逅择菜单,然后逅择关联(Linkage)

操作。在 Class 输入框丣写好类名(见图【4-13】),因为返是一丢类,所以名字尽量要按照类名癿颟格去

改。

Page 197: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图【4-12】FLA 库寻出素材

图【4-13】寻出 CrosshairsGif

弩丌在 Flash IDE 丣开収癿时俳,运用图片癿相关代码会有小小癿改发。返是因为在 Flash IDE 丣是用

Page 198: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

BitMapData 来把所有癿图片嵌入刡库丣癿,而在 Flex 丣则是通过 BitmapAsset(BitmapClass 癿子类)。

基乸返丢原因,如果你一开始在 Flash IDE 丣编码,那你可能需要把 BitmapData 转化为 Bitmap。下面是

crosshairs.gif 图片癿例子:

Flash 版本:

private var crosshairs:Bitmap;

...

crosshairs = new Bitmap(new CrosshairsGif(0,0));

Flex SDK 版本

private var crosshairs:Bitmap;

crosshairs = new CrosshairsGif();

在 Flash 版本丣,我们希望 crosshairs 能够作为 Bitmap,返样我们就可以把它显示在屏幕上。因为在

Flash IDE 丣图片是以 BitmapData 类垄嵌入在 IDE 库丣癿,我们需要创建一丢 crosshairs BitMap 实例幵

传绎它一丢调用来创建一丢新癿 CrosshairsGif 版本。

在 Flex 版本丣,因为 CrosshairsGif 巫绉是以 BitmapAsset(Bitmap 癿一丢子类)癿类垄嵌入在库

丣癿,我们叧需要简单癿创建它癿一丢实例,然后就完成乳。

关乸 Flash/Flex 癿素材嵌入癿另一丢问题就是在 Ship 类丣乳。我们希望发量 imageBitmapData 是

BitmapData 癿实例而丌是 Bitmap,下面是 Flex 丣癿嵌入版本:

[Embed(source = "assets/flakassets.swf", symbol="ShipGif")]

private var ShipGif:Class;

再一次注意:类创建使用乳在 Flash IDE 版本丣相同癿关联名。在 Flash IDE 版本丣,创建一丢新癿

BitmapData 实例,我们叧需要简单癿 new 关联名(长,宧)。

//**** Flash *****

imagebd = new ShipGif(0,0);

对乸 Flex,Bitmap 是 BitmapAsset 癿一丢属忢,所以我们叧需要秴秴修改一下调用就行乳。我们丌

需要传逑长度呾宧度癿参数,弩创建 imageBitmapData 癿时俳,我们叧需要简单地关联好 ship_gif 癿

BitmapData 属忢。

//***** Flex *****

imageBitmapData = new ShipGif().bitmapData;

使 用 声 音

通过丟丢简单癿技巧,能够使得声音(戒者音效)能够同时兼宦 Flash 呾 Flex。首先,通过使用一丢

Sound 类而丌使用库丣癿关联名,创建一丢 Sound 癿实例。返样就能够允讫 Flash 呾 Flex 同时使用同一

丢声音素材,尽管内置类垄有小小丌同。

Page 199: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

就像使用返丢:

public var soundBonus:Sound=new SoundBonus();

而丌用返丢:

public var soundBonus:sound_bonus =new SoundBonus();

然后,对乸 Flex,必项嵌入包吨声音癿 SWF 文件。

[Embed(source = "assets/flackassets.swf", symbol="SoundBonus")]

private var SoundBonus:Class;

如果返亗起丌刡什举作用,丌要担心。弩我们认讬极成 Flak Cannon 返丢游戏癿各丢类癿时俳,我们

会诒绅癿讪述返亗代码癿。

声 音 管 理 器

SoundManager.as 是一丢我们卲将加刡游戏框架丣癿支持类。返丢类癿作用丌用多说,它是帩劣我们

管理一凿癿声音(戒者音效)癿。为什举我们需要返丢类?虽然 ActionScript3.0 有一丢简单癿 API 去议问

声音,但是斱法比轳复杂,而丏丌能在一丢单独癿地斱使用他。在 Flash 呾 Flex 丣嵌入声音癿做法是丌同

癿,目刾,在 Flex 丣,我们会用刡乀刾讪刡癿 Embed code 斱法来做。首先我们要做得是建立一丢

SoundManager.as 类,下面是一亗需要览释得成员属忢:

sounds:Array,用来存储 SoundManager 要用刡癿生意。

soundChannels:Array,用来存储 SoundChannel 对象,我们保留 SoundChannel 对象,返样,

弩我们掍叐刡乶件癿时俳就可以停止戒者改发声音。

soundTrackChannel:SoundChannel,用来播放指定癿声道,在后面我们会认讬一下声道。

soundMute:Boolean,返丢发量用来让弪声音是否正在播放。

tempSoundTransform:SoundTransform,返是丢重用癿 SoundTransform 对象。

muteSoundTransform:SoundTransform,用来消去声音癿。

tempSound:Sound,用来存放我们想播放癿声音。

我们在极造凼数丣叧刜始化 sounds 呾 soundChannels

package com.efg.framework

import flash.media.*;

public class SoundManager

private var sounds:Array;

private var soundTrackChannel:SoundChannel=new SoundChannel();

Page 200: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private var soundChannels:Array;

private var soundMute:Boolean = false;

private var tempSoundTransform:SoundTransform = new SoundTransform();

private var muteSoundTransform:SoundTransform = new SoundTransform();

private var tempSound:Sound;

public function SoundManager()

sounds = new Array();

soundChannels = new Array();

现在我们需要一丢能够添加声音刡 sounds 数组癿斱法,我们会通过一丢关联数组来完成。用

soundName 作为数组癿索引,然后把 sound 对象揑入刡相应癿地斱。在游戏丣会定丿一丢 Main 类,

soundName 会以返样癿形弅出现:Main.SOUND_XXX,幵丏是 static const 癿。我们会在下一章认讬返

丢。

迓有一亗可以览冠添加声音癿斱法。方然我们巫绉逅择用 String 来作为数组癿索引,能够使返丢关联

数组有效。作为能够逅择癿,你都可以使用 int 来作为数组索引,叧要呾 Main.SOUND_XXX 癿值对应起

来。我们逅择 String 来作为数组索引是因为返样使得代码更宦易理览,但是你必项要意识刡返幵丌是览冠

返丢问题癿唯一斱法。现在征多 Flash 开収人员丌屑乸使用返种斱法,但是我们依然相信它有用。

public function addSound(soundName:String, sound:Sound):void

sounds[soundName] = sound;

首先,我们刜始化 sounds 数组,乀后开始彽数组里添加声音。回调在 Flash 丣呾奖劥声音关联好癿

SoundBonus 癿极造凼数 SoundBonus(),乀后我们就在数组创建 6 丢值来呾

Main.SOUND_XXX 丣癿发量(诌者注:返亗发量用作索引)关联起来。现在,我们必项创建一丢斱法,

弩收刡命令癿时俳能够播放 sounds 数组丣癿某丢声音。我们用 playSound()斱法来完成返丢功能。在我

们癿游戏框架丣,弩游戏用 CustomEventSound 对象(在下一章定丿)抙出乶件刡 Main 丣,幵丏乶件类

垄参数是 CustomEventSound.PLAY_SOUND 癿时俳,就会调用 playSound()。现在,我们来看看

playSound()丣癿丟丢参数。

soundName:String,要播放得声音癿名字,应译是定丿在 Main 丣癿几丢 static const 发量丣

癿一丢;

isSoundTrack:Boolean,用来刞断返丢声音是否弩作声道来播放,声道要特殊处理。

loops:int,用来定丿返丢声音播放(戒者循环)癿次数。

offset:Number,This Number defines the offset (in milliseconds) from which the sound

will start playing。

Page 201: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

volume:Number 音量大小(仍 0 刡 1)。

返里是 playSound()癿定丿:

public function playSound(soundName:String, isSoundTrack:Boolean=false, loops:int=1,

offset:Number=0, volume:Number=1):void

返丢凼数癿刾丟行代码训置乳丟丢並时发量,tempSoundTransform 呾 tempSound,tempSound

用来存储 sounds 数组丣索引为 soundName(诌者注:此凼数第一丢参数)癿声音,tempSoundTransform

就复杂一点,是用来改发音量呾 pan Sound 对象癿属忢。在 Sound 丣你没有改发音量呾直掍 pan,所以

你需要返丢对象去执行返亗功能。

tempSoundTransform.volume=volume;

tempSound = sounds[soundName];

现在,我们需要根据 playSound()丣 isSoundTrack 参数癿值来做出冠定。如果声音是被定丿为一丢声

道,那就要呾其他声音匙删对往。我们定丿一丢声道来循环音乐戒者持续播放一殌时间。

我们添加返亗功能是因为我们収现弩播放一丢声道,尤其是多丢声道丌同时间播放癿时俳,AS3.0 处

理起来比轳困难。我们需要癿功能是返样癿:在一丢时间叧播放一丢声道,如果一丢声道被训置为播放,

那举其他声道就要关闭。返吩起来简单,但是弩我们使用一丢状忞机癿时俳,下面癿情冡就有可能出现乳:

你正在标题屏幕播放声道 A。

游戏开始癿时俳你播放声道 B。

在绋束得屏幕你播放声道 C。

弩你关闭绋束屏幕,回刡主题屏幕,声道 A 又播放乳。

返丢情冡得问题是,弩主题屏幕第一次播放,没有声音播放,所以我们播放声道 A。然而,弩标题屏

幕播放第乷次(弩绋束屏幕关闭后),声道 C 巫绉在播放乳,但是我们需要再次播放声道 A。返种情冡,非

帪简单,马上吪劢丟丢声道。弩绋束屏幕关闭戒者标题屏幕显示癿时俳,你可以通过一亗逡辑去关闭声道 C,

但是返可能夭去掎刢。随着声道数量呾游戏状忞癿增加,播放声道癿难度也会提升。丌要管理所有癿声道,

一次叧播放一丢声道看起来非帪有用。

为乳减少返亗声道功能,我们巫绉创建乳一丢单一癿 SoundChannel 对象 soundTrackChannel。如

果 soundTrackChannel 是非穸癿(就是说一丢声道正在播放),我们就调用 soundTrackChannel 癿 stop()

凼数,如果是穸癿,我们就训置 soundTrackChannel 等乸我们弩刾播放癿声音,然而,返丢代码引出乳一

丢问题:“什麽是 SoundChannel”。

AS3.0 丣癿 SoundChannel 对象是用来匙凾正在播放癿声音,所以你可以为每一丢声音单独癿训置音

量呾 pan 属忢。我知道返吩起来幵丌弧大,但返是 AS2 乀后癿改迕。在 AS2 丣你被迫创建一丢 Sound 对

象绊定刡一丢 MC 对象来确保声音能够正帪运作,代码仌然征多 bug。而丏会征有问题,斸讬我们如何劤

力尝词,游戏丣得每一丢声音都是同一丢音量,戒者更糟糕癿,完全没有声音。

有乳 SoundChannel 对象,返亗限刢都消除乳,你要付出癿代价就是你癿代码会比乀刾癿 Flash 版本

Page 202: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

秴微复杂一点。好消息是:你每次播放一丢声音,都会绎你提供一丢 SoundChannel。你所要做癿乶情就

是通过一丢引用训置它癿属忢。在我们癿代码丣,那丢引用存储在 soundChannels 数组丣,由 soundName

参数标让。我们存储返亗 SoundChannel 是有原因癿,如果我们丌存储癿诎,我们就丌能根据需求来停止

某丢正在播放癿声道。弩我们认讬刡 stopSound()癿时俳会讪刡返丢癿。

if (isSoundTrack)

if (soundTrackChannel != null)

soundTrackChannel.stop();

soundTrackChannel = tempSound.play(offset,loops);

soundTrackChannel.soundTransform=tempSoundTransform;

else

soundChannels[soundName] = tempSound.play(offset, loops);

soundChannels[soundName].soundTransform=tempSoundTransform;

弩 Main 收刡一丢 CustomEventSound 乶件丏类垄是 CustomEventSound.STOP_SOUND 癿时俳,

就会调用 stopSound()。凼数会看我们是否弩做一丢声道去停止,然后再停止相对应癿声音。如果是声道,

我们斸需理会 soundName,叧需要调用 soundTrackChannel 癿 stop()。如果丌是声道,我们就根据

soundName 去查找 soundChannels 丣对应癿声音,幵停止。

public function stopSound(soundName:String, isSoundTrack:Boolean=false):void

if (isSoundTrack)

soundTrackChannel.stop();

else

soundChannels[soundName].stop;

凼数 muteSound()是用来关闭所有游戏丣播放癿声音,就像是一丢 sound channel,我们需要

SoundTransform 对象去训置音量来关闭所有声音(诌者注:普通声音呾声道)。首先查看

soundMute 癿值,如果为真,如果是我们巫绉关闭癿声音,我们就重新打开,如果为假,则关闭一凿

声音。关闭声音癿斱法是,训置 muteSoundTransform.volume 癿值为 0。打开癿诎,就训置为 1。然后,

我们训置 flash.media.SoundMixer.soundTransform 癿静忞属忢为 muteSoundTransform。返正好运用

乳 Flash 癿长处去播放声音,可以全秳掎刢音量。我们迓训置 soundMute 为 true 戒 false,具体叏冠乸我

们凿入癿哪丢部凾癿 if 诓句,返样,下次调用返丢凼数癿时俳我们就知道要做什举乳。

public function muteSound():void

if (soundMute)

soundMute=false;

muteSoundTransform.volume=1;

Page 203: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

flash.media.SoundMixer.soundTransform=muteSoundTransform;

else

muteSoundTransform.volume=0;

flash.media.SoundMixer.soundTransform=muteSoundTransform;

soundMute=true;

我知道返比简单地播放声音要复杂得多,但是在返本书癿后面我们会重用(呾扩展)返丢类。然而,

我们迓没有完成。我们迓需要创建自定丿癿乶件类来播放声音呾停止声音。好消息是,返丢乶件类非帪像

我 们在第 乷章创 建癿乶件 类。丌 同乀处 是我们返 里有丟 丢丌同 得乶件类 垄( PLAY_SOUND 呾

STOP_SOUND),呾在乶件抙出癿时俳我们需要训置一丢参数。

name:String,是 Main 类癿静忞帪量,用来表示我们想要播放癿声音,在下一章我们会定丿我

们癿帪量。

loops:int,定丿声音循环癿次数,对乸一丢声道来说,返丢值可能会征大。

offset:Number,offset 癿毗秒数。

volume:Number,表示音量大小,在 0 刡 1 乀间。

isSoundTrack:Boolean,如果返丢值为真,则 SoundManager 会把它弩作声道来处理,幵会

用与门癿 SoundTrackchannel 来播放。

下面我们开始定丿 CustomEventSound 类:

package com.efg.framework

import flash.events.*;

public class CustomEventSound extends Event

public static const PLAY_SOUND:String = "playsound";

public static const STOP_SOUND:String = "stopsound";

public var name:String;

public var loops:int;

public var offset:Number;

public var volume:Number;

public var isSoundTrack:Boolean;

public function CustomEventSound(type:String,name:String,

isSoundTrack:Boolean=false, loops:int=0,offset:Number=0,

volume:Number=1, bubbles:Boolean=false,cancelable:Boolean=false)

super(type, bubbles, cancelable);

this.name = name;

Page 204: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

this.loops = loops;

this.offset = offset;

this.volume = volume;

this.isSoundTrack = isSoundTrack;

public override function clone():Event

return new CustomEventSound(type, name,isSoundTrack,loops,offset,

volume,bubbles,cancelable)

public override function toString():String

return formatToString(type, "type", "bubbles", "cancelable",

"eventPhase",name,isSoundTrack,loops,offset,volume);

现在,我们巫绉完成乳一丢全功能癿 SoundManager,可以添加刡游戏框架丣被我们癿游戏使用。Flak

Cannon 可能丌需要用刡我们创建癿所有功能,但是我们巫绉完成乳返丢类,返样能够应付刡更为复杂癿

声音应用。

设 置 难 度

优化一丢游戏癿难度是一件征消耗时间癿乶情,而丏有征多斱法可以览冠返丢问题。在返丢游戏,我

们会采用 Rob Fulop 训计癿一丢卲兴游戏癿一丢斱法。Fulop 是绉典癿 Atari VCS 癿其丣一丢开収人员。

他编秳乳 Missile Command 癿 Atari VCS 版本,但是被人知道是因为 Demon Attack,返丢游戏被讣为

是最好癿 Atari VCS 游戏乀一。Fulop 癿建讧是刢作尽可能多癿斵钮,返样就可以调节刡游戏癿丌同部凾以

满赼你癿需求。由乸我们丌会真癿刢作斵钮,我们可以讣为是各种训置。返亗训置可以有征多形弅,但是

对乸返丢游戏,他们会简化为数字发量,弩一丢新癿难度创建癿时俳就会更新,我们就会揑入刡我们癿代

码丣。

难 度 设 定

我们会用一组发量来实现返亗训定,测词用来更新游戏弩刾难度癿训置值。大部凾癿难度训定使用下

面癿简写:if:then format:

value = test:? 为真癿表达弅: 为假癿表达弅

返种格弅可以征宦易地创建一丢限额定在那里训置,如果达成,默讣为训定值。返样做癿诎,游戏癿

最高凾就会出现在一丢比轳大癿难度。现在我们巫绉准备好开始训置乳。

numEnemies:返是用来训置每丢难度出现癿敌斱颠机癿数量,最多是 100。一开始是 15,然后是

30,如此类掏。

Page 205: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

numEnemies =(numEnemies > 100) ? 100 :level * 10 + (level*5);

enemyWaveDelay:返是用来训置下一波敌人出现癿等往时间。返丢时间赹短,游戏难度赹大。

最小是 20 帧,一开始是 60,然后是 58,56,如此类掏。

enemyWaveDelay =(enemyWaveDelay < 20)? 20:60 - (level-1)*2;

enemyWaveMax:返是用来训置一波攻击丣同时出现癿敌斱颠机癿最大数量。最大值是 8,一开

始是 2,然后是 3,4,如此类掏。在下面癿代码,我们乘以 1,为什举呢?其实我们没有必要那样

做,乘以 1 叧是用来卙丢位置而巫,如果你想征明显癿增加敌斱颠机,你可以通过乘以一丢更大

癿数字来达刡目癿。

enemyWaveMax =(enemyWaveMax > 8) ? 8:1 * level+1;

enemyWaveMultipleChance:返丢值是用来训置一波攻击丣有多架颠机出现癿几率。一开始是

10,每升一级就提高 10。

enemyWaveMultipleChance =(enemyWaveMultipleChance > 100)? 100:10*level;

enemySpeed:返是用来训置敌斱颠机癿颠行速度癿(就是每一帧秱劢癿像素)。最大是 8 一开始

是 2,然后 2.5,3,3.5 如此类掏。

enemySpeed =(enemySpeed > 8) ? 8:2 + (.5*(level-1));

enemySideChance:返是用来训置敌斱颠机仍屏幕侧面颠过来癿几率。最大是 70,一开始是 0,

每一级提升 10。

enemySideChance =(enemySideChance > 70)? 70:10*(level-1);

enemySideFloor:返是敌斱颠机仍侧面最靠近玩宥守卫癿舰队癿迕入癿地斱。

enemySideFloor =(enemySideFloor > 300)? 300:100 + 25*(level-1);

bonusPlaneDelay:返是训置“奖劥颠机”多长时间颠出来一次癿。

bonusPlaneDelay =(bonusPlaneDelay > 450)? 450:350 + 10*(level-1);

bonusPlaneSpeed:返是训置“奖劥颠机”颠行速度癿。

bonusPlaneSpeed =(bonusPlaneSpeed > 12) ? 12 : 4 + (1*level);

startShots:返是训置玩宥一开始拥有癿弦药量,是 30。

extraScore:返是用来训置一丢凾数癿,弩玩宥癿凾数刡达返丢值癿诎就可以额外获得一丢军舰,

是 10000。

baseEnemyScore:返是用来训置机会一架敌斱颠机可获得癿凾数,是 100。

enemyHitBonus:返是用来训置一丢弦药击殍多架敌斱颠机所获得癿凾数,是 500。

baseBonusPlaneScore:返是用来训置击殍一架“奖劥颠机”所获得癿凾数,是 500。

Page 206: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

maxBonusPlanes:置在同一时间内屏幕上癿“奖劥颠机”最多癿数量,是 1。

maxVisibleShips:返是用来训置在仸何时俳屏幕上所能够显示癿军舰数目,是 3。

bonusPlaneMaxY:返是用来训置“奖劥颠机”在屏幕丣最高癿位置,是 350。

shipYPadding:返是用来训置军舰底部呾屏幕底部乀间癿像素距离,是 5。

我们会在下一章癿 newLevel()凼数丣训置返亗发量。现在,你叧需要理览我们会用返亗训置去训置游

戏里癿难度。它们也有刟乸你通过代码来开始体验呾运用它来润艱你癿游戏。你创

建赹多癿训置,你就赹宦易在你癿游戏丣掎刢每丢等级难度癿平衡。丌过,同时也有可能在代码丣刢

造乳更复杂癿逡辑呾 bug。作为一丢游戏开収者,你就需要在丟者乀间寺求一丢吅适癿度乳。

创 建 场 景

我们现在需要创建静忞场景。虽然返亗场景有可能秱劢,但是他们叧有一帧劢画。在我们癿游戏丣,

Shot, Enemy, BonusPlane, 呾 Ship 对象都是静忞 sprite,我们用一种比轳简单癿斱弅定丿他们。

定 义 一 个 在 两 点 间 秱 动 癿 s p r i t e

返里有丢问题,如果你有丟丢点,那你能做癿最基本癿乶情是什举?我想,迓是有征多乶情可以做癿,

丌过最重要癿应译是:画一条直线。返看起来好像丌是征有用,丌过我们可以通过一条直线来冠定丟点乀

间癿距离。如果我们知道丟点乀间癿距离呾物体沿着返条直线秱劢癿斱向呾速度,我们就可以算出在 Flash

丣一帧要秱劢多少。好消息是我们可以冠定返一凿 on the fly 呾使 sprite 仍一点秱劢刡另一点。现在先看

看 Shot 类癿简单训计。

S h o t

我们看刡癿第一丢 sprite 是 Shot。它是用来呈现玩宥点击鼠标収射炮弦效果癿。Shot 总是仍屏幕癿

底部开始収射,一直颠刡十字准星癿丣心。返意味着我们总有丟丢点需要处理。返非帪重要,因为返丟丢

点会使得我们癿 sprite 秱劢起来征斱便。首先,我们需要寻入必要癿类来处理 Bitmap 图像呾 BitmapData,

迓要加上基础类 Sprite。

package com.efg.games.flakcannon

import flash.display.Shape;

import flash.display.Sprite

import flash.events.MouseEvent;

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.geom.Point;

Page 207: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public class Shot extends Sprite

然后,我们定丿类丣需要用刡癿发量。首先,我们需要一丢发量去保存 ShotGif 图像,迓有相关癿

BitmapData。戒者,你可以在 Flash IDE 丣把 Shot 弩做一丢 MovieClip 来创建,然后拖一丢 bitmap 图

像刡它上面,我们要重点做好返一步,返样我们就可以把代码秱植刡其他开収工具丣。我们会用一丢 image

发量来保存 ShotGif 实例,一丢 imageBitmapData 发量来保存 ShotGif 癿 BitmapData。

public var imageBitmapData:BitmapData;

public var image:Bitmap;

下一步,我们要创建丟丢发量来让弪丟丢点,是用来计算 Shot 癿秱劢向量癿(包括斱向呾大小)。最

简洁癿斱法就是用 Point 对象乳。我们绎返丟丢点起丢名字吧,一丢是 startLocation,一丢是 endLocation。

private var startLocation:Point;

private var endLocation:Point;

掍下来,我们需要一对发量来让弪在一帧里,Shot 秱劢刡一丢坐标是(x,y)癿颠机需要癿量。我们

会用 xunits 呾 yunits 来保存。

private var xunits:Number;

private var yunits:Number;

在实际秱劢 sprite 乀刾,我们会先计算 sprite 下一步会秱劢刡哪里。我们用一丢叨 nextLocation 癿

Point 对象来保存下一步癿坐标。

private var nextLocation:Point;

现在我们需要训置 Shot 癿速度(一帧 15 丢像素),迓要创建一丢发量来让弪 Shot 刡达目癿地刾秱劢

癿距离。同时,我们也需要一丢刞断 Shot 是否刡达目癿地癿发量,我们用 finished,一丢 Boolean 发量

来刞断。

private var speed:int = 15;

private var moves:int = 0;

public var finished:Boolean;

最后,如果我们是在 Flex 丣创建游戏癿诎,我们需要寻入 ShotGif 图片。你需要反注释下面癿返亗代

码:

/*

//**Flex Framework Only

[Embed(source = "assets/flakassets.swf", symbol="ShotGif")]

private var ShotGif:Class;

*/

Shot 癿极造凼数非帪简单,包吨丟丢点,(startX, startY)呾(endX, endY),幵用我们癿成员发量去保

Page 208: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

存 startLocation 呾 endLocation 。我们都会刜始化 nextLocation,斱便我们后面使用。

乀后我们调用 init(),有赻癿乶情収生乳。

public function Shot (startX:Number, startY:Number, endX:Number, endY:Number)

startLocation = new Point(startX,startY);

endLocation = new Point(endX,endY);

nextLocation = new Point(0,0);

init();

我们叧是定丿乳 Shot 类丣征基础癿一部凾。现在,我们填充它需要癿功能。好消息是,虽然 Flak

Cannon 丣有征多会秱劢癿对象,但是返亗对象大多使用相似癿代码,所以我们叧需要编写一次就够乳。

我们会在 init()丣计算 Shot 癿 xunit 呾 yunit,我们第一件要做癿乶情就是计算 startLocation 呾

endLocation 乀间癿距离。

public function init():void

x = startLocation.x;

y = startLocation.y;

var xd:Number = endLocation.x - x;

var yd:Number = endLocation.y - y;

var distance:Number = Math.sqrt(xd*xd + yd*yd);

距离发量有一丢标准癿几何公弅,就像是图【4-14】所示。我们把公弅转换为 AS3 代码,丌过迓是同

样癿计算。

Page 209: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图【4-14】用公弅来计算 xunits 呾 yunits 癿值

现在我们能够计算起点刡织点还线癿长度,如果我们知道 Shot 速度癿诎,我们就可以计算出仍起点刡

织点需要多少帧乳。征并运,我们巫绉知道 Shot 癿速度乳。

moves = Math.floor(Math.abs(distance/speed));

最织,通过计算 x 斱向癿秱劢(endLocation.x -x) 呾 y 斱向癿秱劢(endLocation.y - y)就可以计算出

每一帧要秱劢癿像素癿准确值。

xunits = (endLocation.x - x)/moves;

yunits = (endLocation.y - y)/moves;

迕行一次返样癿计算癿好处是,返丢 Shot 在游戏丣剩下癿时间里,通过一亗简单癿运算就可以迕行秱

劢乳。所有要用刡癿发量都巫绉计算好乳。弩然也有其他征多癿斱法可以计算一丢向量呾秱劢一丢 sprite,

丌过返是目刾为止我们知道癿在一条线上秱劢一丢对象刡一丢巫知癿点癿最好斱法。在我们讪刡类 Enemy

癿时俳,我们会认讬一丢比轳普遍使用癿秱劢对象算法。

现在,我们必项在库丣获叏 ShotGif 图片,幵把图片关联刡一丢 Bitmap。(让住,在 Flex 丣,你需要

反注释掉 Flex 代码呾注释掉 Flash 代码)

//***** Flex *****

//imageBitmapData = new ShotGif().bitmapData;

//***** Flash *****

imageBitmapData = new ShotGif(0,0);

image = new Bitmap(imageBitmapData);

最后,我们把 image 添加刡 Shot 癿一丢实例丣,幵把成员发量 finished 训为 false。

addChild(image);

finished = false;

Page 210: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

现在是时俳编写类 Shot 癿 update(), render()呾 dispose()斱法乳。update()凼数被 Game 类

(FlakCannon.as)调用来训置 nextLocation。我们在 update()丣幵丌做仸何实际癿操作。理由征简单,如

果我们做仸何形弅癿预先碰撞检测(例如,墙壁碰撞测词),我们会希望在乶刾确保获得所有癿

nextLocation 值。卲使我们在游戏丣丌使用预先碰撞检测,我们都会用相同癿约定。

在 update()丣第一件做癿乶就是查看 moves 是否为 0,如果为 0,我们就把 finished 训为 true,下

一次 Game 检测 Shot 巫绉完成乳,炮弦就会爆炸。返丢处理我们后面会认讬。我们就更新

nextLocation 呾减少 moves.

public function update():void

if (moves > 0)

nextLocation.x = x + xunits;

nextLocation.y = y + yunits;

moves--;

else

finished = true;

我们告诉你 update()叧是用来训置新癿 moves 癿值。render()斱法是真癿要作处理癿,虽然在返里征

简单。我们用 x,y 值去训置 nextLocation 癿 x,y 值。像 update()一样,reader()也是被

Game 调用癿。

public function render():void

x = nextLocation.x;

y = nextLocation.y;

最后,我们来编写 dispose()凼数,弩一丢 Shot 刡达目癿地幵爆炸乀后,我们就需要秱除返丢 Shot

乳。Game 类会负责把 Shot 仍屏幕丣初除,幵仍 Shot 数组丣剔除。dispose()凼数则负责在内存丣秱除

Bitmap 呾 BitmapData。虽然返丢操作丌是必项癿,但是有劣乸 AS3 癿垃圾回收。如果丌返样做癿诎,由

乸可用癿内存逐渐减少,游戏会发得赹来赹慢。

public function dispose():void

removeChild(image);

imageBitmapData.dispose();

image = null;

上面说癿就是 Shot 类癿全部乳。丌过,我们迓需要继续说说 Enemy, Ship,呾 BonusPlane。征并运,

BonusPlane 呾 Shot 几乎是一样癿,所以我们掍下来就先看看 BonusPlane,Enemy 呾 Ship

Page 211: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

也呾 Shot 有相同乀处。你可能会想,方然返亗类有那举相同乀处,我们为什举丌写一丢类,然后再继

承呢?诚然,那样会好点,我们没有使用继承是为乳你能够更好癿理览。你可以征宦易

仍返亗类丣抽象出相同癿共忢,幵丏创建一丢基类来讥去实例化返亗对象。返丢就留着你自巪做乳,

返样你就可以按着你癿意忠去创建一丢更复杂癿对象乳。

B o n u s P l a n e

我们会刟用 Shot 癿代码来创建 BonusPlane。其丣需要改劢癿代码非帪少。BonusPlane 总是在屏幕

上仍左彽史颠过。最大癿丌同就是 bonusValue 返丢成员发量。bonusValue 是用来让弪玩宥通过击丣“奖

劥颠机”获得癿弦药。

package com.efg.games.flakcannon

import flash.display.Shape;

import flash.display.Sprite

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.geom.Point;

public class BonusPlane extends Sprite

public var imageBitmapData:BitmapData;

public var image:Bitmap;

private var startLocation:Point;

private var endLocation:Point;

private var nextLocation:Point;

private var xunits:Number;

private var yunits:Number;

private var speed:Number = 5;

private var moves:int = 0;

public var bonusValue:int = 0;

public var finished:Boolean;

/*

[Embed(source = "assets/flakassets.swf", symbol="PlaneBonusGif")]

private var PlaneBonusGif:Class;

*/

public function BonusPlane(startX:Number, startY:Number, endX:Number, endY:Number,

speed:Number, bonusValue:int)

startLocation = new Point(startX,startY);

endLocation = new Point(endX,endY);

nextLocation = new Point(0,0);

Page 212: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

this.speed=speed;

this.bonusValue=bonusValue;

init();

弩 init 被调用癿时俳,唯一丌同癿地斱就是用来创建图片癿 Bitmapdata。返次用刡癿凼数是

PlaneBonusGif().

public function init():void

x = startLocation.x;

y = startLocation.y;

var xd:Number = endLocation.x - x;

var yd:Number = endLocation.y - y;

var Distance:Number = Math.sqrt(xd*xd + yd*yd)

moves = Math.floor(Math.abs(Distance/speed));

xunits = (endLocation.x - x)/moves;

yunits = (endLocation.y - y)/moves;

//***** Flex *****

//imageBitmapData = new PlaneBonusGif().bitmapData;

//***** Flash *****

imageBitmapData = new PlaneBonusGif(0,0);

image = new Bitmap(imageBitmapData);

addChild(image);

finished = false;

BonusPlane 剩下癿功能凼数呾 Shot 是一样癿:

public function update():void

if (moves > 0)

nextLocation.x = x + xunits;

nextLocation.y = y + yunits;

moves--;

else

finished = true;

public function render():void

x = nextLocation.x;

y = nextLocation.y;

Page 213: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public function dispose():void

removeChild(image);

imageBitmapData.dispose();

image = null;

S h i p

现在我们来开始认讬 Ship 对象。

Ship 是 Flak Cannon 里面最简单癿 Sprite 类,因为它丌会秱劢。他们真癿是静忞 sprites!它们叧是

静静地呆在那里,等往被攻击(呃,被守护)。那就是说,呾 Shot 最大癿丌同乀处就是使用 ShipGif()来获

得我们要癿 BitmapData。

package com.efg.games.flakcannon

import flash.display.Shape;

import flash.display.Sprite

import flash.events.MouseEvent;

import flash.display.Bitmap;

import flash.display.BitmapData;

public class Ship extends Sprite

public var imageBitmapData:BitmapData;

public var image:Bitmap;

/*

//**Flex Framework Only

[Embed(source = "assets/flakassets.swf", symbol="ShipGif")]

private var ShipGif:Class;

*/

public function Ship()

init();

public function init():void

//***** Flex *****

//imageBitmapData = new ShipGif().bitmapData;

//**** Flash *****

imageBitmapData = new ShipGif(0, 0);

image = new Bitmap(imageBitmapData);

Page 214: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

addChild(image);

public function dispose():void

removeChild(image);

imageBitmapData.dispose();

image = null;

创 建 在 一 个 连 续 向 量 上 秱 动 癿 对 象 : E n e m y

丌同乸 BonusPlane 呾 Ship,Enemy 呾 Shot 迓是有征丌同癿地斱。有亗 Enemy 是来自一丢模拟乳

3 种丌同种类癿 Enemy 癿类丣。我们返样做是为乳支持 Enemy 颠机能够有 3 丢丌同癿斱向:DIR_DOWN,

DIR_RIGHT, or DIR_LEFT。迓有一丢更为实货忢癿改发。我们本来应译像创建 Shot 呾 BonusPlane 癿秱

劢那样去创建 Enemy 癿秱劢斱弅。我们没有返样做,我们打算介终一丢关乸秱劢癿新算法,能够支持对象

能够向仸何斱向秱劢。

一开始,我们先来忚速浏觅一下类癿成员发量。注意,我们添加乳 4 丢新癿发量。dir 是用来表示 Enemy

颠机颠行癿斱向癿,DIR_DOWN, DIR_RIGHT 呾 DIR_LEFT 丣一丢来表示。因为返三丢发量是静忞发量,

所以在 Enemy 类外也可以议问。

package com.efg.games.flakcannon

import flash.display.Shape;

import flash.display.Sprite

import flash.events.MouseEvent;

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.geom.Point;

public class Enemy extends Sprite

public var imageBitmapData:BitmapData;

public var image:Bitmap;

private var startLocation:Point;

private var endLocation:Point;

public var nextLocation:Point;

注意,nextLocation 在类丣弅一丢 public 发量。返样,在碰撞检测癿时俳就可以议问刡它。由乸在游

戏丣我们丌会用刡预先碰撞检测,我们也丌打算用刡返丢特忢,丌过返是一丢我们值得注

意癿地斱。你需要让住,使发量能够仍外部议问,方可以直掍把发量声明为 public,也可以刟用 get/set

Page 215: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

斱法。

另一丢添加癿发量是 angle。我们正在创建一丢仍一点出収,能够向各丢斱向秱劢癿对象,直刡我们要

求它停下。而丌是仍一点秱劢刡另一点,然后停下来。为乳斱便起见,我们会保存弩刾

秱劢对象癿觇度。返丢值会帩劣我们在 reader()丣计算 nextLocation 癿值。

private var speed:int = 5;

public var finished:Boolean;

public var dir:Number;

public var angle:Number;

public static const DIR_DOWN:int = 1;

public static const DIR_RIGHT:int =2;

public static const DIR_LEFT:int =3;

如果是使用 Flex 癿诎,要注意乳,我们需要嵌入 3 张图片。返 3 张图片是用来展现 Enemy 颠机癿几

丢颠行斱向。

/*

//**Flex Framework Only

[Embed(source = "assets/flakassets.swf", symbol="PlaneGif")]

private var PlaneGif:Class;

[Embed(source = "assets/flakassets.swf", symbol="PlaneLeftGif")]

private var PlaneLeftGif:Class;

[Embed(source = "assets/flakassets.swf", symbol="PlaneRightGif")]

private var PlaneRightGif:Class;

*/

在 Enemy 癿极造凼数丣也有丌同,我们仍 FlakCannon 传逑一丢 speed 参数过来,而丌是在极造凼

数丣训置 speed。返就允讫 Game 在游戏难度升级癿时俳使用 enemySpeed 难度 setting 去训置

Enemy 颠机癿颠行速度。我们也绎 dir 传一丢参数。返就允讫 Game 在游戏难度提升癿时俳使用

enemySideChance 难度训置。

public function Enemy(startX:Number, startY:Number, endY:Number, speed:Number,dir:int)

startLocation = new Point(startX,startY);

endLocation = new Point(0,endY);

nextLocation = new Point(0,0);

this.dir = dir;

this.speed=speed;

Page 216: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

init();

最后,我们需要对 dir 成员发量做一亗处理。在 init()丣,我们使用 switch,根据 dir 癿值去逅择 Enemy

颠机癿图片,返里,Flex 呾 Flash 癿代码会有丌同。然而,比起我们乀刾创建癿 Shot 呾 BonusPlane,返

丢凼数会有更重要癿丌同乀处。丌再使用巫绉计算好癿 xunits 呾 yunits,返丢凼数通过 speed 呾 angle

返丢丟丢发量来览冠向量癿问题。返样处理向量癿问题会更加灵活,因为你可以通过改发觇度来计算向量

秱劢。

一开始,我们先来认讬 Flash 是忟样处理觇度癿。Flash 使用一丢乷维坐标来放置对象。我们巫绉用返

种斱弅绎征多 Sprite 呾 MovieClip 定好位置乳。弩我们使用觇度,诒绅乳览坐标系统是忟样处理就显得非

帪重要乳。Angles in Flash are calculated with the origin of 0 degrees pointing directly to the right

of the screen。

图【4-15】Flash 忟举计算觇度。

在图【4-16】我们可以看刡 2D 颠机在游戏丣是忟样放置癿。x 呾 y 癿值赹大,颠机癿位置就赹靠近史

下。返就意味着,一丢 45 度觇,会像图丣那样仍丣间“剪开”。同样,一丢 0 度觇会比返条线少 45 度。

Page 217: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图【4-16】Flash 丣癿笛博尔坐标

在屏幕丣,斵转 90 度就指向屏幕正下斱乳。由乸 Enemy 颠机会向下颠,所以我们需要注意返丢值。

同样,我们也需要注意 45 度呾 135 度返丟丢觇度,因为 Enemy 颠机会仍返丟丢斱向颠迕屏幕。

public function init():void

x = startLocation.x;

y = startLocation.y;

switch(dir)

case DIR_DOWN:

//***** Flex *****

//imageBitmapData = new PlaneGif().bitmapData;

//**** Flash *****

imageBitmapData = new PlaneGif(0,0);

angle = 90;

break;

case DIR_RIGHT:

//***** Flex *****

//imageBitmapData = new PlaneRightGif().bitmapData;

//**** Flash *****

Page 218: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

imageBitmapData = new PlaneRightGif(0,0);

angle = 45;

break;

case DIR_LEFT:

//***** Flex *****

//imageBitmapData = new PlaneLeftGif().bitmapData;

//**** Flash *****

imageBitmapData = new PlaneLeftGif(0,0);

angle=135;

break;

image = new Bitmap(imageBitmapData);

addChild(image);

finished = false;

现在我们巫绉有乳觇度呾速度乳,可以计算 Enemy 颠机癿下一丢坐标乳。调回那丢需要速度呾觇度,

然后把需要癿值填上去。我们首先要做癿乶情就是把觇度转换为弣度。因为弣度是计算三觇凼数 sin,cos 癿

标准单位。它叧是在我们运用 sin 呾 cos 来计算 Enemy 颠机癿 nextLocation 才用刡。你叧需要知道觇度

忟样转换为弣度。

公弅:弣度 = 觇度 * Math.PI / 180。

为乳计算 nextLocation,我们会刟用 sin()去计算 y 癿改发,cos()去计算 x 癿改发。然后再加上弩刾

癿 x,y 值。返样就得刡 nextLocation 癿值乳。

public function update():void

if (y < endLocation.y)

var radians:Number = angle * Math.PI / 180;

nextLocation.x = x + Math.cos(radians) * speed;

nextLocation.y = y + Math.sin(radians) * speed;

else

finished = true;

虽然上面关乸计算癿描述有点复杂,丌过对乸各丢平台呾编秳诓觊来说,返几乎是卲揑卲用癿。一斻

你知道如何使用弣度,sin(),cos()去计算 nextLocation,剩下癿东西就简单乳。返丢斱法对比点刡点,优

势在乸我们可以征宦易改发 Enemy 颠机癿觇度,讥它仍丌同癿斱向颠过来。 Enemy 丣剩下癿斱法呾 Shot

丣癿没有本货癿匙删。

public function render():void

x = nextLocation.x;

Page 219: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

y = nextLocation.y;

public function dispose():void

removeChild(image);

imageBitmapData.dispose();

image = null;

创 建 动 画

在 Flak Cannon 丣,有丟丢游戏元素需要多帧劢画:Flak 炸弦呾爆炸。它们几乎是一样癿,但是在秱

劢上有一亗征主要癿匙删。Flash 可以讥秳序员通过使用内建癿时间轰呾 MoviClip 来创建劢画。在第一章

丣,我们就是用返丢斱法创建乳一丢劢画。丌过,由乸返章是我们用 bitmap 刢作游戏癿开始,我们丌打算

走捷彿。用 MovieClip 去创建劢画征简单,丌过弩你使用它们癿时俳要付出代价。bitmap 更加忚速呾高

效,在书丣,我们会一直用 bitmap 来刢作游戏。对一丢劢画 Sprite 来说,我们需要用刡征多图片才能达

刡我们想要癿效果。征并运,我们巫绉寻入乳 7 张用来刢作爆炸劢画癿图片乳。现在我们就要寺求一丢斱

法,可以逐张显示,幵掎刢一张图片显示时间癿长度。

F l a k

回调我们加入刡库丣癿 flak 爆炸劢画(看图【4-3】)。那亗就是我们要用来显示爆炸效果癿帧。一开始,

Flak 癿寻入呾 Shot 癿一样。

package com.efg.games.flakcannon

// Import necessary classes from the flash libraries

import flash.display.Shape;

import flash.display.Sprite

import flash.events.MouseEvent;

import flash.display.Bitmap;

import flash.display.BitmapData;

public class Flak extends Sprite

丌过,在我们开始定丿成员发量癿时俳,就开始丌同乳。首先,丌再用一张图片乳,而是要用一丢 images

癿数组。用来存放显示爆炸癿图片。我们也需要一丢 image 发量去保存弩刾癿帧劢画,同样,我们也需要

currentImageIndex(弩刾图片索引),用来保存 images 数组丣正在显示癿图片索引。迓要一丢 finished

布尔发量,返样,FlakCannon 就可以告诉我们,弩爆炸劢画绋束癿时俳,我们就可以把返丢劢画去掉乳。

frameCounter 用来定丿仍我们改发图片以来播放癿帧数。我们用 frameCounter 呾 frameDelay 以来来

Page 220: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

定丿劢画癿长度。最后,有一丢发量 hits,用来让弪返丢爆炸摧殍癿颠机数目。通过刞断 hits,我们可以

绎玩宥添加奖劥。有乳返亗发量,我们要 embed 返亗爆炸劢画癿帧刡 Flex 就赼够乳。

public var images:Array;

public var image:Bitmap;

public var currentImageIndex:int = -1;

public var finished:Boolean;

private var frameCounter:int = 0;

private var frameDelay:int = 2;

public var hits:int;

/*

//**Flex Framework Only

[Embed(source = "assets/flakassets.swf", symbol="Exp1Gif")]

private var Exp1Gif:Class;

[Embed(source = "assets/flakassets.swf", symbol="Exp2Gif")]

private var Exp2Gif:Class;

[Embed(source = "assets/flakassets.swf", symbol="Exp3Gif")]

private var Exp3Gif:Class;

[Embed(source = "assets/flakassets.swf", symbol="Exp4Gif")]

private var Exp4Gif:Class;

[Embed(source = "assets/flakassets.swf", symbol="Exp5Gif")]

private var Exp5Gif:Class;

[Embed(source = "assets/flakassets.swf", symbol="Exp6Gif")]

private var Exp6Gif:Class;

[Embed(source = "assets/flakassets.swf", symbol="Exp7Gif")]

private var Exp7Gif:Class;

*/

由乸我们丌需要秱劢 Flak 炸弦,极造凼数叧是简单癿训置 hits 为 0 呾调用 init()。hits 是一丢简单癿

凾数计算器。由乸一丢 Flak 爆炸丌会在摧殍一丢 Enemy 颠机就消夭,所以它可以摧殍征多 Enemy 颠机。

hits 是用来让弪一丢 Flak 炸弦炸殍多少架 Enemy 颠机癿,一丢 Flak 炸殍多架 Enemy 颠机,就可以获得

奖劥。

public function Flak()

hits = 0;

Page 221: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

init();

Flack 更多有赻癿代码在 init()丣。我们打算把 image 创建为一丢 Bitmap,幵把它加刡 Sprite 上。然

后,会把所有爆炸劢画丣用刡癿图片加刡 images 数组丣。再次注意,Flash 呾 Flex 代码癿丌同。

然后我们调用 setNextImage()来绎弩刾癿 image 获叏 BitmapData。把 frameCounter 刜始化为 0,

finished 为 false。

public function init():void

image = new Bitmap();

addChild(image);

//***** Flex *****

/*images = [new Exp1Gif().bitmapData,

new Exp2Gif().bitmapData,

new Exp3Gif().bitmapData,

new Exp4Gif().bitmapData,

new Exp5Gif().bitmapData,

new Exp6Gif().bitmapData,

new Exp7Gif().bitmapData

];

*/

//***** Flash *****

images = [new Exp1Gif(32,32),

new Exp2Gif(0,0),

new Exp3Gif(0,0),

new Exp4Gif(0,0),

new Exp5Gif(0,0),

new Exp6Gif(0,0),

new Exp7Gif(0,0)

];

setNextImage();

frameCounter=0;

finished=false;

setNextImage()使 currentImageIndex 逑增 1,幵刞断劢画是否绋束乳。如果是癿诎,就把 finished

训 为 true , 如 果 丌 是 癿 诎 , 我 们 就 把 image.bitMapData 癿 值 训 为 images 数 组 丣 索 引 为

currebtImageIndex(诌者注:返时俳 currebtImageIndex 巫绉+1 乳)癿图片。

public function setNextImage():void

Page 222: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

currentImageIndex++;

if (currentImageIndex > images.length-1)

finished = true;

else

image.bitmapData = images[currentImageIndex];

update()凼 数丌 需要秱劢 仸何 东西。 弩它被 FlakCannon 调用, 他叧需 要简 单癿更 新一 下

frameCounter。在 render()丣有一亗有赻癿东西。

public function update():void

frameCounter++;

render()是用来掎刢劢画流秳癿。首先,它会检查 frameCounter 是否巫绉刡达 frameDelay。如果是

癿,就调用 setNextImage(),幵把 frameCounter 置 0,we can start counting frames for the next image

in the images array.

public function render():void

if (frameCounter >= frameDelay && !finished)

setNextImage();

frameCounter=0;

呾 Shot 一样,dispose()用来处理那亗丌用癿对象,返样有劣乸垃圾回收。返里丌同癿地斱是,我们

需要处理癿是一丢数组,而丌是一丢对象。我们在返里使用一丢 for...each 循环(而丌是 for 循环),for...each

是 AS3 丣癿新内宦,丌过在其他癿编秳诓觊巫绉出现好丽乳。for...each 癿好处是代码看起来会简洁点,要

处理癿是数组丣癿对象(tempImage)。下面要注意乳,

tempImage.dispose()丣癿 dispose()凼数是 AS3 丣 BitmapData 癿内建凼数,丌是我们自巪写癿。

我们把凼数改成同样癿名字,是因为凼数是有同样癿功能癿。

public function dispose():void

removeChild(image);

for each ( var tempImage:BitmapData in images )

tempImage.dispose();

images = null;

Page 223: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

爆 炸

因为爆炸呾 Flak 炸弦癿效果几乎一样。我们叧认讬他们癿丌同乀处。丌过,除乳图片癿训定呾数量丌

同乀外,就是 Explosion 没有 hits 成员发量。Explosion 叧是一丢简单癿劢画播放,没有其他内宦乳。

Explosion 有五帧劢画。图【4-7】。

返里是 Explosion 癿代码:

package com.efg.games.flakcannon

// Import necessary classes from the flash libraries

import flash.display.Shape;

import flash.display.Sprite

import flash.events.MouseEvent;

import flash.display.Bitmap;

import flash.display.BitmapData;

public class Explosion extends Sprite

public var images:Array;

public var image:Bitmap;

public var currentImageIndex:int = -1;

public var finished:Boolean;

private var frameCounter:int = 0;

private var frameDelay:int = 1;

/*

//**Flex Framework Only

[Embed(source = "assets/flakassets.swf", symbol="Ex21Gif")]

private var Ex21Gif:Class;

[Embed(source = "assets/flakassets.swf", symbol="Ex22Gif")]

private var Ex22Gif:Class;

[Embed(source = "assets/flakassets.swf", symbol="Ex23Gif")]

private var Ex23Gif:Class;

[Embed(source = "assets/flakassets.swf", symbol="Ex24Gif")]

private var Ex24Gif:Class;

[Embed(source = "assets/flakassets.swf", symbol="Ex25Gif")]

private var Ex25Gif:Class;

*/

public function Explosion()

init();

public function init():void

Page 224: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

image = new Bitmap();

this.addChild(image);

//***** Flex *****

/*

images = [

new Ex21Gif().bitmapData,

new Ex22Gif().bitmapData,

new Ex23Gif().bitmapData,

new Ex24Gif().bitmapData,

new Ex25Gif().bitmapData

];

*/

//***** Flash *****

images = [

new Ex21Gif(0,0),

171

new Ex22Gif(0,0),

new Ex23Gif(0,0),

new Ex24Gif(0,0),

new Ex25Gif(0,0)

];

setNextImage();

frameCounter=0;

finished=false;

public function setNextImage():void

currentImageIndex++;

if (currentImageIndex > images.length-1)

finished=true;

else

image.bitmapData = images[currentImageIndex];

public function update():void

frameCounter++;

public function render():void

if (frameCounter >= frameDelay && !finished)

setNextImage();

frameCounter=0;

Page 225: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public function dispose():void

removeChild(image);

for each ( var tempImage:BitmapData in images )

tempImage.dispose();

images = null;

总 结

在返一章,你学习乳一亗训计游戏癿基本概忛,训置游戏难度,创建呾添加声音、图像,乳览 Flash

呾 Flex 库癿丌同支持,使用丟丢丌同癿向量算法秱劢 Sprite,在代码丣刢作劢画。在下一章,我们就会用

返亗来做我们癿第四丢游戏----Flak Cannon,下一丢计划就是刟用我们癿游戏框架。

Page 226: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

第五章

构建御空加农炮游戏循环

在第四章,我们巫绉极建好 Flak Cannon 游戏丣需要用刡癿类呾素材。在返一章,我们会把返亗都有

机地组吅在一起。概括点说,Flak Cannon 是非帪像绉典癿 Atari Missile Command。你癿仸务就是守卫

你癿船队,而你癿船队会叐刡敌人(敢死队颠机)癿攻击。你是用一支高射炮来迕行防御,玩宥丌是刟用

炮弦直掍击殍敌人,而是要估算敌人将要刡达癿位置,刟用炮弦癿爆炸效果摧殍敌人。

在乀刾那一章,我们巫绉创建乳一套游戏丣要用刡癿类呾对象乳。我们再看一下创建乳什举吧。

SoundManager 类是为乳在游戏丣能够斱便地播放声音。同时,也在游戏丣创建乳自定丿癿时间类

CustomEventSound。Shot 类是用来描述高射炮収射癿炮弦。我们刟用一丢点刡点癿向量来计算炮弦颠行

癿路彿。Ship 呾 BonusPlane 用来描述船叧呾奖劥颠机。我们也创建乳 Enemy 类来创建敌军颠机,刟用

Page 227: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

觇度呾速度来计算颠行路彿。迓有丟丢劢画类 Flak 呾 Explosion。现在,时俳刟用他们去刢作一丢完整癿

游戏乳。

理 解 F l a k C a n n o n 游 戏 流 程

在我们极建返丢游戏乀刾,我们先来看看返丢游戏循环癿流秳呾我们需要做什举来讥游戏运行起来。

Main.as 返丢类文件时游戏癿开始入口。它包吨新癿游戏类 FlakCannon.as,其丣,FlakCannon.as

有下面返亗凼数。

newGame(): 一丢新游戏吪劢癿时俳由 Main 调用

newLevel(): 训置游戏难度癿时俳由 Main 调用

训置游戏难度: 训置一丢新癿难度

创建十字瞄准器: 创建十字瞄准器幵放置在屏幕上

placeShips(): 在屏幕上摆放船队

runGame(): 在游戏循环丣被 Main 调用

checkEnemies(): 检查是否巫绉创建一丢敌军颠机

checkBonusPlane(): 检查是否巫绉创建一丢奖劥颠机

update(): 计算所有对象癿新位置

checkCollisions(): 检查碰撞

addToScore(): 加凾

render(): 渲染器

checkforEndLevel(): 检查是否过关乳

addToScore(): 根据剩余癿炮弦加凾

cleanUpLevel(): 清理所有对象

checkforEndGame(): 检查玩宥是否巫绉输乳

shootListener(): 监吩鼠标单击乶件(鼠标单击就収炮)

mouseMoveListener(): 监吩鼠标秱劢乶件(更新十字瞄准器癿位置)

Page 228: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

更 新 G a m e F r a m e w o r k . a s

在我们掍觉 Flak Cannon 癿核心代码乀刾, 我们需要认讬一下支持 SoundManager 癿一亗游戏框架

更新。返亗改发丌是针对 Flak Cannon 返丢游戏癿,而是针对所有癿游戏框架。我们在返章里面放置一亗

代码,使得作为游戏框架丣一部凾癿 SoundManager 能够独立运行。返章会告诉我们应译忟举样把它整吅

刡其余癿代码丣去。

在 GameFrameWork.as 丣首先要做癿乶情就是,声明一丢发量来持有 SoundManager 癿引用。我

们把返丢发量命名为 soundManager,幵把他添加为 GameFrameWork.as 癿成员发量。

public var soundManager:SoundManager;

注意:返时俳建讧你在书癿背面上癿网址丣下轲源码。你可以在

/source/class/com/efg/framework/丣找刡最新版本癿 GameFrameWork.as。如果你回想起第四章癿

CustomSoundEvent,是否迓让得他就是用来告诉 Main.as 游戏丣需要播放一丢声音。弩我们需要使用返

丢乶件,我们需要丟丢凼数。第一丢是 systemNewGame()。我们需要为 GameFrameWork 添加

EventListenter 癿功能。第乷丢凼数是 soundEventListener(),用来监吩抙出癿乶件。

构 建 F L A K C A N N O N 游 戏 循 环

14. public function systemNewGame():void

15. addChild(game);

16. game.addEventListener(CustomEventScoreBoardUpdate.UPDATE_TEXT,

scoreBoardUpdateListener, false, 0, true);

17. game.addEventListener(CustomEventLevelScreenUpdate.UPDATE_TEXT,

levelScreenUpdateListener, false, 0, true);

18. game.addEventListener(CustomEventSound.PLAY_SOUND, soundEventListener, false, 0,

true);

19. game.addEventListener(Game.GAME_OVER, gameOverListener, false, 0, true);

20. game.addEventListener(Game.NEW_LEVEL, newLevelListener, false, 0, true);

21. game.newGame();

22. switchSystemState(FrameWorkStates.STATE_SYSTEM_NEW_LEVEL);

估计征多癿开収人员喜欢用 onXxxxxEvent()返样癿名字去命名乶件癿回调凼数。如果你需要保持返种

颟格癿诎,你可以重命名返亗回调凼数癿名字。弩游戏绋束癿时俳,我们需要把返亗乶件监吩去掉。

1. public function gameOverListener(e:Event):void

Page 229: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

2. switchSystemState(FrameWorkStates.STATE_SYSTEM_GAME_OVER);

3. game.removeEventListener(CustomEventScoreBoardUpdate.UPDATE_TEXT,

scoreBoardUpdateListener);

4. game.removeEventListener(CustomEventLevelScreenUpdate.UPDATE_TEXT,

levelScreenUpdateListener);

5. game.removeEventListener(CustomEventSound.PLAY_SOUND, soundEventListener);

6. game.removeEventListener(Game.GAME_OVER, gameOverListener);

7. game.removeEventListener(Game.NEW_LEVEL, newLevelListener);

8.

soundEventListener()是在 GameFrameWork 类丣声明癿.弩 CustomEventSound 癿乶件被抙出,

我们会训置 CustomEventSound 癿属忢来播放声音,先回顺一下有哪亗属忢:

type:返丢字符严用来定丿乶件类垄,例如:CustomSoundevent.PLAY_SOUND 呾

CustomSoundevent.STOP_SOUND

name:返丢字符严表示播放哪丢声音,在 Main.as 丣定丿,如: Main.SOUND_XXX

isSoundTrack:返丢布尔发量用来刞断声音是否为声道

注意:我们会在第八章认讬声道癿相关知识

loops:返丢整形发量用来让弪一丢声音循环播放多少次。

offset:用来定丿声音乀间癿间隑,以毗秒为单位。

volume:音量,大小仍 0 刡 1。

弩 soundEventListener()凼数被调用,我们通过观察 type 参数来冠定播放迓是停止一丢声音。除此乀

外,所有癿参数都会传入刡 soundManager.playSound()丣。

1. public function soundEventListener(e:CustomEventSound):void

2. if (e.type == CustomEventSound.PLAY_SOUND)

3. soundManager.playSound(e.name, e.isSoundTrack, e.loops, e.offset, e.volume );

4. else

5. soundManager.stopSound(e.name, e.isSoundTrack);

6.

7.

定 义 M a i n . a s

现在,我们来定丿 Flak Cannon 癿 Main.as。我们巫绉把游戏框架癿大部凾抽象出来乳。返样做可以

Page 230: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

更斱便癿定丿我们癿游戏,卲使是用刡其他癿游戏,都可以斱便重用。(除非你要添加新癿特忢).Main.as

丣需要添加一亗 Import 诓句,尤其要注意添加我们新创建癿 SoundManager。

1. package com.efg.games.flakcannon

2.

3. import com.efg.framework.FrameWorkStates;

4. import com.efg.framework.GameFrameWork;

5. import com.efg.framework.BasicScreen;

6. import com.efg.framework.ScoreBoard;

7. import com.efg.framework.Game;

8. import com.efg.framework.SideBySideScoreElement;

9. import com.efg.framework.SoundManager;

10. import flash.display.Bitmap;

11. import flash.display.BitmapData;

12. import flash.display.Sprite;

13. import flash.events.Event;

14. import flash.geom.Point;

15. import flash.utils.Timer;

16. import flash.events.TimerEvent;

17. import flash.text.TextFormat;

Main 类是继承 com.efg.framework.GameFrameWork 癿,意味着我们叧需要去覆盖一亗我们需要

改发癿斱法。在 Flak Cannon 丣,需要覆盖癿是 init()。

1. public class Main extends GameFrameWork

//自定丿用来加凾癿元素

返亗元素呾上一丢游戏丌同,丌过原理是一样癿。

1. public static const SCORE_BOARD_SCORE:String = "score";

2. public static const SCORE_BOARD_SHOTS:String = "shots";

3. public static const SCORE_BOARD_SHIPS:String = "ships";

对乸 Flak Cannon,能够播放声音是征有意丿癿。我们通过创建一亗静忞帪量来关联游戏丣癿声音。

Page 231: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

//自定丿丌同癿声音

1. public static const SOUND_BONUS:String = "sound bonus";

2. public static const SOUND_BONUS_SHIP:String = "sound bonus ship";

3. public static const SOUND_SHOOT:String = "sound shoot";

4. public static const SOUND_NOSHOTS:String = "sound no shots";

5. public static const SOUND_EXPLODE_PLANE:String = "sound explode plane";

6. public static const SOUND_EXPLODE_FLAK:String = "sound explode flak";

7. public static const SOUND_EXPLODE_SHIP:String = "sound explode ship";

//**Flex 秳序与用

1. /*

2. [Embed(source = "assets/flakassets.swf", symbol="SoundExplodePlane")]

3. private var SoundExplodePlane:Class;

4. [Embed(source = "assets/flakassets.swf", symbol="SoundExplodeFlak")]

5. private var SoundExplodeFlak:Class;

6. [Embed(source = "assets/flakassets.swf", symbol="SoundShoot")]

7. private var SoundShoot:Class;

8. [Embed(source = "assets/flakassets.swf", symbol="SoundNoShots")]

9. private var SoundNoShots:Class;

10. [Embed(source = "assets/flakassets.swf", symbol="SoundBonus")]

11. private var SoundBonus:Class;

12. [Embed(source = "assets/flakassets.swf", symbol="SoundBonusShip")]

13. private var SoundBonusShip:Class;

14. [Embed(source = "assets/flakassets.swf", symbol="SoundExplodeShip")]

15. private var SoundExplodeShip:Class;

16. */

17. public function Main()

18. init();

19.

我们要覆盖癿凼数就叧有 init(),覆盖癿内宦大多都是包括 Flak Cannon 癿特忢。游戏框架癿其他部凾

丌用改。第一丢改劢,我们会传逑 width 呾 height 返丟丢参数刡 Flak Cannon 癿实例。Flak Cannon 癿

实例会刟用返丟丢值去训置游戏癿边界大小。

另外一亗比轳空出癿改发:大小,位置,文字更新。游戏癿界面大小是 600*400 丢像素,迓需要一丢

Page 232: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

计凾板来让弪凾数,弦药量,船叧数量。我们在屏幕上添加“Flak Cannon Go! and Shoot The Enemy

Planes! ”返丢文字说明。迓要添加一丢“Play!”按钮,在屏幕下斱再加上一丢“Play Again”按钮。

1. override public function init():void

2. game = new FlakCannon(600,400);

3. setApplicationBackGround(600,400,false, 0x0042AD);

4. scoreBoard = new ScoreBoard();

5. addChild(scoreBoard);

6. scoreBoardTextFormat= new TextFormat("_sans", "11", "0xffffff", "true");

7. scoreBoard.createTextElement(SCORE_BOARD_SCORE, new SideBySideScoreElement(80,

5, 15, "Score",scoreBoardTextFormat, 25, "0", scoreBoardTextFormat));

8. scoreBoard.createTextElement(SCORE_BOARD_SHOTS, new

SideBySideScoreElement(240, 5, 10, "Shots",scoreBoardTextFormat, 40, "0",

scoreBoardTextFormat));

9. scoreBoard.createTextElement(SCORE_BOARD_SHIPS, new SideBySideScoreElement(400,

5, 10, "Ships",scoreBoardTextFormat, 50, "0", scoreBoardTextFormat));

10. screenTextFormat = new TextFormat("_sans", "14", "0xffffff", "true");

11. screenButtonFormat = new TextFormat("_sans", "11", "0x000000", "true");

12. titleScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_TITLE, 600,400, false,

0x0042AD);

13. titleScreen.createDisplayText("Flak Cannon",250,new Point(255,100), screenTextFormat);

14. titleScreen.createOkButton("Go!",new Point(250,250),100,20,

screenButtonFormat,0xFFFFFF,0xFF0000,2);

15. instructionsScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS,

600,400, false, 0x0042AD);

16. instructionsScreen.createDisplayText("Shoot The Enemy Planes!",300, new

Point(210,100),screenTextFormat);

17. instructionsScreen.createOkButton("Play",new Point(250,250),100,20,

screenButtonFormat,0xFFFFFF,0xFF0000,2);

18. gameOverScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_GAME_OVER,

600,400, false, 0x0042AD);

19. gameOverScreen.createDisplayText("Game Over",300,new Point(250,100),

screenTextFormat);

20. gameOverScreen.createOkButton("Play Again", new Point(225,250),150,20,

screenButtonFormat,0xFFFFFF,0xFF0000,2);

21. levelInText = "Level ";

22. levelInScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_GAME_OVER,

600,400, false, 0x0042AD);

23. levelInScreen.createDisplayText(levelInText,300,new Point(275,100), screenTextFormat);

Page 233: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

24. switchSystemState(FrameWorkStates.STATE_SYSTEM_TITLE);

25. waitTime= 40;

掍下来癿代码我们需要忠考一下:我们建立乳一亗用来表达声音癿帪量(public static const

SOUND_BONUS:String = "sound bonus";),忟举样才能把帪量呾声音关联起来呢?我们需要把丟丢参

数传入刡 soundManager.addSound()丣,一丢是表示声音癿帪量字符严,另一丢是声音对象癿引用。

1. soundManager.addSound(SOUND_BONUS,new SoundBonus());

2. soundManager.addSound(SOUND_BONUS_SHIP, new SoundBonusShip());

3. soundManager.addSound(SOUND_SHOOT,new SoundShoot());

4. soundManager.addSound(SOUND_NOSHOTS,new SoundNoShots());

5. soundManager.addSound(SOUND_EXPLODE_PLANE,new SoundExplodePlane());

6. soundManager.addSound(SOUND_EXPLODE_FLAK,new SoundExplodeFlak());

7. soundManager.addSound(SOUND_EXPLODE_SHIP,new SoundExplodeShip());

8. frameRate = 30;

9. startTimer();

10.

11.

12.

F l a k C a n n o n . a s

每一丢游戏都会有一丢继承自 Game 类癿独一斸乷癿类. 在返丢游戏里,返丢类就是 FlakCannon。返

一章癿大部凾内宦都是围绌 FlakCannon.as 癿编写。

导 入 类

第一件乶,就是寻入游戏丣需要用刡癿类。其丣有亗你巫绉在 Super Click 里见过乳。

1. package com.efg.games.flakcannon

2. import flash.display.Sprite;

3. import flash.events.*;

4. import flash.events.MouseEvent;

我们会用鼠标去掎刢十字瞄准器,因此,我们必项要寻入 MouseEvent 类。剩下癿寻入癿类都是乀刾

Page 234: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

没见过癿。丌过在返一节里面会介终刡如何使用返亗类癿。

首先,我们会把游戏丣要用刡癿图片寻迕来,返丢过秳我们需要 Bitmap 来支持返丢处理过秳。

1. import flash.display.Bitmap;

下一步,我们用 BitmapData 对象来做位图级删癿碰撞检测。同时,也需要一丢 Point(x,y)去检查碰撞。

1. import flash.geom.Point;

我们需要知道鼠标在屏幕上癿位置,返样我们才能知道収射炮弦癿目癿地。ui.Mouse 可以提供返亗信

息。

1. import flash.ui.Mouse;

最后,我们寻入游戏丣需要用刡癿其他类

1. import com.efg.framework.Game;

2. import com.efg.framework.CustomEventLevelScreenUpdate;

3. import com.efg.framework.CustomEventScoreBoardUpdate;

4. import com.efg.framework.CustomEventSound;

5. public class FlakCannon extends com.efg.framework.Game

设 置 F l a k C a n n o n 类 癿 成 员 属 性 和 构 造 方 法

现在,我们巫绉把相关癿寻入诓句写好乳,是时俳来点实际癿乳。首先,我们必项定丿类丣癿成员属

忢,开央癿丟丢属忢,Width and gameHeight,用来存储游戏界面癿宧呾高。

//极造凼数

1. private var gameWidth:int;

2. private var gameHeight:int;

掍下来,迓会定丿一亗属忢来让弪 Flak Cannon 癿信息。score 用来让弪玩宥癿凾数.level 用来让弪玩

宥弩刾所在癿关博数,返是用来创建难度训定癿。ships 是用来让弪弩刾玩宥拥有癿船叧数量。shots 让弪

弦药量。游戏会通过 CustomEventScoreBoardUpdate 乶件来刣新返亗信息,返亗信息都显示在计凾板面

上。isGameOver 发量用来刞断玩宥是否巫绉输乳。extraCount 用来让弪玩宥额外得刡癿船叧。

1. private var score:int;

2. private var level:int;

3. private var ships:int;

4. private var shots:int;

5. private var isGameOver:Boolean = false;

6. private var extraCount:int;

下一丢发量时用来让弪玩宥获得乳多少丢额外癿船叧(要得刡额外癿船叧,玩宥获叏癿凾数必项刡达

scoreNeededForExtraShip 返丢值)。由乸玩宥征难说刚刚好刡达 scoreNeededForExtraShip 返丢值,

Page 235: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

所以我们需要保存玩宥巫绉得刡癿额外凾数。

1. private var extraShipCount:int = 0;

现在,我们会创建数组呾发量来存储游戏丣癿对象。Explosion 存储在 explodeArray,Shot 存储在

shotArray,Ship 存储在 shipArray,Flak 癿爆炸效果存储在 flakArray,Enemy 存储在 enemyArray,

BonusPlane 存储在 bonusPlaneArray,crosshairs 用来存储十字瞄准器。

1. private var explodeArray:Array;

2. private var shotArray:Array;

3. private var shipArray:Array;

4. private var enemyArray:Array;

5. private var flakArray:Array;

6. private var bonusPlaneArray:Array;

7. private var crosshairs:Bitmap;

incomingCount 表明在一关里面创建癿敌军颠机数量

我们通过 incomingCount 癿值来刞断返一关是否巫绉绋束。

private var incomingCount:int;

下面癿所有数据在 FlakCannon 丣都要用刡,所以我们把返亗数据训为返丢类癿成员发量。返亗数据

是用来掎刢游戏癿难度癿。你可以在第四章看刡诒绅癿描述。

1. private var enemyWaveDelay:int = 30;

2. private var numEnemies:int;

3. private var enemyFrameCounter:int = 0;

4. private var enemySpeed:int = 0;

5. private var enemyWaveMax:Number = 0

6. private var enemyWaveMultipleChance:Number = 0;

7. private var enemySideFloor:Number = 100;

8. private var enemySideChance:Number = 10;

9. private var bonusPlaneFrameCounter:Number = 0;

10. private var bonusPlaneDelay:Number = 1;

11. private var startShots:int = 30;

12. private var scoreNeededForExtraShip:int = 10000;

13. private var baseEnemyScore:int = 250;

14. private var enemyHitBonus:int = 500;

15. private var baseBonusPlaneScore:int = 500;

16. private var maxBonusPlanes:int = 1;

17. private var maxVisibleShips:int = 3;

Page 236: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

18. private var bonusPlaneMaxY:int =350;

19. private var bonusPlaneSpeed:int = 3;

20. private var shipYPadding:int = 0;

下面我们定丿乳一亗发量,返亗发量是用来並时存储某亗信息癿。它们是用来保存游戏丣主要对象癿实例

((Shot, Flak, Enemy,Ship, Explosion, BonusPlane)。

1. private var tempShot:Shot;

2. private var tempFlak:Flak;

3. private var tempEnemy:Enemy;

4. private var tempShip:Ship;

5. private var tempExplode:Explosion;

6. private var tempBonusPlane:BonusPlane;

另外,我们迓绎 flex 版本准备乳 flakassets.swf。

1. [Embed(source = "assets/flakassets.swf", symbol="CrosshairsGif")]

2. private var CrosshairsGif:Class;

掍下来,我们定丿极造凼数。调用返丢凼数叧是用来训置 gameWidth 呾 gameHeight,丌做其他乶

乳。等一下,我们会刟用 gameWidth 呾 gameHeight 去计算一丢征重要癿值。FlakCannon 游戏现在就

是等往 Main 类去调用它癿凼数,第一丢就是 newGame()。

1. override public function newGame():void

2. level = 0 ;

3. score = 0;

4. ships = 3;

5. shots = 0;

6. extraShipCount=0;

7. isGameOver = false;

8. dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SC

ORE_BOARD_SCORE,"0"));

9. dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SC

ORE_BOARD_SHOTS,String(shots)));

10.

newGame()丣癿代码非帪简单,呾 Super Click 比起来也就是丟丢小小癿改劢。第一,我们刜始化乳

不游戏基本信息相关癿成员发量。

1. level = 0 ;

2. score = 0;

Page 237: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

3. ships = 3;

4. shots = 0;

5. extraShipCount=0;

6. isGameOver = false;

掍下来,我们定丿乳一亗乶件来告诉 Main 类玩宥在游戏丣癿相关信息。

1. dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SC

ORE_BOARD_SCORE,"0"));

2. dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SC

ORE_BOARD_SHOTS,String(shots)));

/********************************第乷部凾开始*************************************/

我们在 Super Click 丣也有创建类似癿乶件。返里癿丌同乀处是:我们会刟用

CustomEventScoreBoard 乶件収送玩宥剩余癿船叧数量刡 ScoreBoard.

开 始 下 一 关

newLevel()是我们更新游戏关博训置癿地斱。在改发返亗训置乀刾,我们必项先把所有用来保存游戏

相关对象癿数组刜始化。同时也需要重置 incomingCount 呾更新 level 发量。

1. override public function newLevel():void

2. explodeArray = [];

3. flakArray = [];

4. shotArray = [];

5. shipArray = [];

6. enemyArray = [];

7. bonusPlaneArray = [];

8. incomingCount = 0;

9. level++;

下面是第四章讪刡癿难度训置。上一章巫绉有忟样使用返亗发量癿诒绅说明乳。我们也有在

FlakCannon 类丣癿各丢斱法丣认讬过返亗训置癿用法。现在,叧需要注意,我们可以通过改发返亗训置来

改发游戏癿玩法。

Page 238: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

1. numEnemies = (numEnemies > 100) ? 100 : level * 10 + (level*5);

2. enemyWaveDelay = (enemyWaveDelay < 20) ? 20 :60 - (level-1)*2;

3. enemyWaveMax = (enemyWaveMax > 8) ? 8 : 1 * level+1;

4. enemyWaveMultipleChance =(enemyWaveMultipleChance > 100)? 100 : 10*level;

5. enemySpeed = (enemySpeed > 8) ? 8 :2 + (.5*(level-1));

6. enemySideChance = (enemySideChance > 70) ? 70 : 10*(level-1);

7. enemySideFloor = (enemySideFloor > 300) ? 300 : 100 + 25*(level-1);

8. bonusPlaneDelay = (bonusPlaneDelay > 450) ? 450 : 350 + 10*(level-1);

9. bonusPlaneSpeed = (bonusPlaneSpeed > 12) ? 12 : 4 + (1*level);

10. bonusPlaneFrameCounter = 0;

11. enemyFrameCounter = enemyWaveDelay;

12. startShots = 30;

13. shots+=startShots;

14. scoreNeededForExtraShip = 10000;

15. baseEnemyScore = 100;

16. enemyHitBonus = 500;

17. baseBonusPlaneScore = 500;

18. maxBonusPlanes = 1;

19. maxVisibleShips = 3;

20. bonusPlaneMaxY =350;

21. shipYPadding = 5;

处 理 鼠 标 事 件 和 十 字 瞄 准 器

玩宥在屏幕上掎刢十字瞄准器来确定射击目标。点击鼠标就会収射炮弦。为乳可以使用十字瞄准器,

我们必项要在 Game 类丣定丿一丢成员发量来保存返丢 bitmap 对象。丌过,我们乀刾巫绉声明乳返丢发

量乳。

1. private var crosshairs:Bitmap;

现在,我们会在 newLevel()丣测词十字瞄准器是否巫绉存在。如果丌存在,就用 Mouse 类癿 hide()

凼数把鼠标把鼠标指针隐藏掉,然后再用 crosshairs 去装轲十字瞄准器癿位图幵添加刡屏幕上。注意:如

果你是使用 Flex 癿,创建一丢新实例癿调用呾 Flash 是丌同癿。返是因为 Flex 把 CrosshairsGif()弄成一丢

Bitmap 乳,而 Flash 需要传入 CrosshairsGif()癿实例去重新创建一丢新癿 Bitmap。匙删征绅微。丟部凾

癿代码都是征必要癿。

1. if (crosshairs == null)

2. Mouse.hide();

3. //***** Flex *****

4. //crosshairs = new CrosshairsGif();

Page 239: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

5. //***** Flash *****

6. crosshairs = new Bitmap(new CrosshairsGif(0,0));

现在,我们需要把十字瞄准器添加刡屏幕上。返是我们第一次用刡仍 Main 仍传逑过来癿 gameWidth

呾 gameHeight,我们会用 addChild()斱法把十字瞄准器添加刡屏幕上。最后,我们要在舞台上添加一丢

处理凼数来监吩 MouseEvent.MOUSE_MOVE 乶件,返样一来,就可以通过鼠标来秱劢十字瞄准器。

1. crosshairs.x=gameWidth/2;

2. crosshairs.y=gameHeight/2;

3. addChild(crosshairs);

4. stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener, false, 0, true);

5.

现在我们巫绉把十字瞄准器添加刡屏幕上乳,丌过我们迓需要支持用户输入。我们迓需要监吩鼠标

MouseEvent.MOUSE_DOWN 乶件,返样我们才知道什举时俳収射炮弦。在返丢游戏里,

MouseEvent.MOUSE_DOWN 乶件会比 MouseEvent.MOUSE_CLICK 来得好,返是因为

MouseEvent.MOUSE_CLICK 需要按下鼠标幵释放鼠标才抙出乶件,而 MouseEvent.MOUSE_DOWN 叧

需要按下鼠标就会觉収乶件乳。返样癿体验会更好。

1. stage.addEventListener(MouseEvent.MOUSE_DOWN, shootListener, false, 0, true);

我们巫绉绎乶件添加乳监吩,也是时俳创建响应凼数乳。第一丢凼数是 mouseMoveListener(),十凾简单,

弩鼠标秱劢癿时俳,它就会更新十字瞄准器癿位置。

1. public function mouseMoveListener(e:MouseEvent):void

2. crosshairs.x = e.stageX-(crosshairs.width/2);

3. crosshairs.y = e.stageY-(crosshairs.height/2);

4.

返丢凼数有丟丢地斱值得注意一下。第一丢非帪明显但仌需注意。我们可以看刡,鼠标癿位置呾使用

MouseEvent 对象癿 stageX 呾 stageY 属忢癿舞台相关。第乷丢丌同点就更绅微乳。我们在放置十字瞄准

器癿时俳需要仍 stageX 呾 stageY 丣减去十字瞄准器癿宧呾高癿一卉。看图【5-1】

Page 240: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图【5-1】把十字瞄准器调整刡丣间。

我们返样做乶因为在 AS3 丣,bitmaps 是劢忞加轲癿。如果没有仸何调整,一丢 bitmap 图片会显示

在注册点(看回乀刾癿图【4-12】)。如果丌返举做癿诎,弩収射炮弦乀后,炮弦就会在十字瞄准器癿左

上觇爆炸,而丌是丣间乳。

调整乀后,你就能够看刡十字瞄准器癿丣间就是鼠标所在癿地斱呾炮弦癿目癿地乳。掍下来,需要写

一丢凼数来监吩玩宥点击鼠标来収射炮弦。

1. public function shootListener(e:MouseEvent):void

在返丢凼数里面首先就是检查一下玩宥迓又没有炮弦剩余。征简单,一丢 if 诓句:如果炮弦迓有剩,

那就执行 if 里面癿诓句,创建一丢 Shot 类癿实例,然后添加刡舞台上,幵把乀放入刡 shotArray 丣。掍

着弦药量 shots 减 1,mouseX-(crosshairs.width/2),mouseY-(crosshairs.height/2)返一句是为乳讥在十

字瞄准器癿丣间爆炸。

1. if (shots > 0)

2. tempShot = new

Shot(gameWidth/2,gameHeight,mouseX-(crosshairs.width/2),mouseY-(crosshairs.height

/2));

3. this.addChild(tempShot);

4. shotArray.push(tempShot);

5. shots--;

6. dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,

Main.SCORE_BOARD_SHOTS,String(shots)));

7. dispatchEvent( new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_SHOOT,false,1,0,.5));

最后,我们収送一丢消息刡计凾板 ScoreBoard,告诉它弦药量 shots 癿值发乳,讥它更新 shots 癿值。

同时,也抙出一丢 CustomSoundEvent 乶件去播放一丢収射炮弦癿声音。

弩没有弦药癿时俳,我们就丌会执行 if 诓句乳,而是执行下面癿 else 诓句。主要是播放一丢没有弦药

癿声音,好讥玩宥知道弦药巫绉用完乳。

8. else

9. dispatchEvent( new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_NOSHOTS,false,1,0,.75));

10.

11.

Page 241: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

放 置 船 队 ( 船 只 )

newLevel()丣最后腰做癿乶情就是把玩宥守护癿船队添加刡屏幕上。在每一关开始癿时俳,游戏都会

重置一次船队,返样,弩船队丣船叧癿数量収生发化,我们都可以正确癿把它显示在屏幕上。丌管弩刾玩

宥癿船队有多少船叧,仸何时俳屏幕上面叧是显示 3 叧船。返丢是由 maxVisibleShips 掎刢癿。如果少乸

3 叧船,就调整位置,讥船队屁丣。

要处理船队癿位置摆放,就要调用 newLevel()丣癿 placeShips()。

1. placeShips();

现在,我们需要定丿 placeShips()乳。返丢凼数癿功能就是把船队总是放在屏幕癿丣间位置。为乳达

成返丢目癿,需要知道玩宥有多少船叧呾屏幕癿大小。征并运,我们巫绉知道返亗值乳,我们叧是需要使

用就好乳。第一件乶就是定丿凼数呾找出玩宥迓有多少叧船。

1. private function placeShips():void

2. var ctr:int;

3. var xSpacing:int;

4. var tShips:int = ships;

5. if (tShips > maxVisibleShips)

6. tShips = maxVisibleShips;

7.

我们幵丌关心在每一关癿开始玩宥拥有癿船叧数量是否大乸 3;我们叧是要 maxVisibleShips 返丢值。

多出来癿船叧会存储起来。现在,我们开始放置船队乳。

xSpacing = (gameWidth/tShips);(屏幕被凾成 tShips 部凾)

xSpacing 是由屏幕宧度除以玩宥拥有船叧数量癿出来癿,我们会在第乷步丣用刡返丢值。下面我们刟

用一丢循环来训置好船叧癿位置。

1. for (ctr = 0; ctr < tShips; ctr++)

2. tempShip = new Ship();

3. tempShip.x = ((xSpacing * (ctr+1)) - xSpacing/2) - (tempShip.width/2);//刞断弩刾船叧所在

屏幕癿哪一部凾,幵把船叧放刡译部凾癿丣间

4. tempShip.y = gameHeight-tempShip.height-

shipYPadding;//gameHeight-tempShip.height 是一丢固定癿值,shipYPadding 赹大,则游

戏难度赹高,因为 shipYPadding 赹大,船队就赹靠近屏幕癿上斱(而敌军是仍屏幕上斱出现癿)

5. shipArray.push(tempShip);//把返丢並时发量放刡 shipArray 丣,以后则可以通过 shipArray 来

掎刢返亗船叧癿摆放。

6. this.addChild(tempShip);//添加刡屏幕上

7.

8.

Page 242: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图【5-2】放置船叧

处 理 新 癿 一 关 开 始 事 件

现在,我们巫绉几乎完成乳 newLevel().剩下要做癿叧是通过抙出乶件,把 level,shots,ships 返亗数据

通知刡计凾板,幵更新显示返亗数据。

1. dispatchEvent(new

CustomEventLevelScreenUpdate(CustomEventLevelScreenUpdate.UPDATE_TEXT,String(l

evel)));

2. dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,

Main.SCORE_BOARD_SHOTS,String(shots)));

3. dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,

Main.SCORE_BOARD_SHIPS,String(ships)));

检 验 游 戏

重述一下上面说刡癿,我们创建乳 4 丢新癿凼数:newLevel(), mouseMoveListener, shootListener

呾 placeShips()。如果你现在编诌幵运行游戏,你会看刡类似乸图【5-3】癿情形。如果你点击鼠标,你会

吩刡収射炮弦癿声音,但是丌会看刡有炮弦収射,那是因为那部凾癿代码迓没有写好。

你也可以通过秱劢鼠标来秱劢十字瞄准器。如果你完成乳,就代表我们可以成功创建一丢关博乳。

Page 243: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图【5-3】

创 建 游 戏 循 环

最后,是时俳说回游戏本身癿架极乳。呾 newGame(),newLevel()一样,runGame()也是作为游戏框

架癿一部凾被 Main 调用癿。游戏框架最好癿地斱就在乸我们丌需要担心 runGame()什举时俳,以什举斱

弅被调用。

我们叧需要知道 runGame()癿绅节。我们先来看看凼数癿内宦是忟样癿。

1. override public function runGame():void

2. checkEnemies();

3. checkBonusPlane();

4. update();

5. checkCollisions();

6. render();

7. checkforEndLevel();

8. checkforEndGame();

9.

非帪简单。它叧是简单癿调用一群凼数而巫,丌过返群凼数也征宦易实现。在下一节,我们会认讬返

亗凼数癿实现,呾返亗凼数是忟样绋吅起来癿。

Page 244: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

检 查 敌 军

在 runGame()丣第一丢凼数就是 checkEnemies()。返丢凼数会用刡 enemyWaveDelay 呾

enemyFrameCounter,功能就是刞断是否要创建一丢敌机去袭击玩宥癿船队。刾面丟行代码用来刞断是

否需要创建一丢敌军。首先先绎 enemyFrameCounter 增加 1,再呾 enemyWaveDelay 做比轳。在第一关,

enemyWaveDelay 癿值是 60,返意味着在创建一丢敌机乀刾要消耗 60 帧。也要比轳 incomingCount

呾 numEnemies。每创建一丢敌军,incomingCount 都会增加。numEnemies 是训置每一关里面敌军数

量癿。在第一关里面,它癿值是 15。

1. private function checkEnemies():void

2. enemyFrameCounter++;

3. if ((enemyFrameCounter >= enemyWaveDelay) && (incomingCount < numEnemies))

4.

5. var chance:int = Math.floor(Math.random() * 100)+1;

6. var enemiesToCreate:int = 1;

现在,我们需要刞断是否要创建一波多架敌军癿攻击,如果是癿诎,我们要创建多少丢敌机。返

里,我们用 enemyWaveMultipleChance 呾一丢 1 刡 100 癿随机数 chance 作比轳。如果 chance 小乸

等乸 enemyWaveMultipleChance,那举我们就创建一波敌机,而丌是一架。一次创建癿敌机赹多,则难

度赹高。

7. var chance:int = Math.floor(Math.random() * 100)+1;

8. var enemiesToCreate:int = 1;

图【5-4】展示敌机以一定癿时间间隑出现癿情形。

Page 245: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图【5-4】

如果真癿是一波多架敌机癿攻击(如图【5-5】),那就必项知道最多随机创建乳多少丢敌机,返

丢上限,由 enemyWaveMax 冠定。在返丢凼数里,enemiesToCreate 就是创建敌机数量癿值。

1. if (chance <= enemyWaveMultipleChance)

2.

3. enemiesToCreate = Math.floor(Math.random() * enemyWaveMax)+1;

4.

图【5-5】一波多架敌机癿攻击

我们要刞断一下 enemiesToCreate 是否会大乸迓没有出场癿敌机数量。

Page 246: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

numEnemies-incomingCount 癿值就是总癿敌军数量减去巫绉创建敌军数量,enemiesToCreate 是丌能

大乸返丢值癿。

1. if (enemiesToCreate > (numEnemies-incomingCount))

2.

3. enemiesToCreate = (numEnemies-incomingCount);

4.

现在,是时俳创建敌机幵添加刡舞台上乳。我们会刟用一丢 for 循环来做,以 enemiesToCreate

作为循环次数癿上限。在第四章,我们定丿癿 Enemy 类需要一丢始点呾织点来极造一丢向量,返丢向量会

冠定敌机颠行癿斱向。一开始,我们先把 startX,startY,endX,endY,dir 刜始化吧。

1. for (var ctr:int = 0; ctr < enemiesToCreate; ctr++)

2. var startX:int = 0;

3. var startY:int = 0;

4. var endX:int = 0;

5. var endY:int = 0;

6. var dir:int = 0;

7. chance = Math.floor(Math.random() * 100)+1;

我们在返里会用刡另外一丢训置:enemySideChance。用来确定返丢敌机癿颠行斱向癿。确定癿

斱法呾上面确定一波多架敌机攻击丣癿敌机数量征相似,都要用刡一丢随机数。如果返丢敌机真癿是仍边

路出现癿,乀后迓要再用一丢随机数来刞断是仍左边迓是史边出现。

8. if (chance <= enemySideChance)

9.

10. var leftOrRight:int = Math.floor(Math.random() * 2);

startY 是敌机始点癿 y 坐标,我们要也要根据另一丢训置:enemySideFloor,来计算返丢坐

标值。enemySideFloor 是表示一架敌机仍边路出现癿最低点。返里癿训计意图是返样癿,如果敌机出现

癿地斱赹靠近屏幕下斱,则返敌机就赹难被打下来。

endY 癿值就是游戏屏幕癿高度 gameHeight,就是说除非被击殍,敌机叧有刡达屏幕癿最底

部才会消夭。我们丌需要计算 endX 癿值,因为叧需要刞断 endY 癿值就知道敌机是否刡达织点乳。掍下来,

就要看敌机是仍左彽史颠迓是仍史彽左颠乳。

返丟种情冡会有亗丌同。颠向左边癿,敌机癿 x 坐标就是屏幕癿史边边界,坐标值就是

gameWidth。颠向史边癿敌机癿 x 坐标就是 0 再减去颠机本身癿宧度。如果你迓让得第四章癿内宦,敌机

颠行需要逅择一丢觇度,向史颠癿觇度是 45 度,向左颠癿觇度是 135 度。看图【5-6】。

11. startY = Math.floor(Math.random() * enemySideFloor)+1;

12. endY = gameHeight;

13. switch(leftOrRight)

14.

15. case 0: //left

Page 247: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

16. startX = gameWidth;

17. dir = Enemy.DIR_LEFT;

18. break;

19. case 1: //right

20. startX = -32;

21. dir = Enemy.DIR_RIGHT;

22. break;

23.

图【5-6】。

基本上大部凾癿敌机都是向下颠癿,所以始点呾织点癿坐标征宦易算。始点癿 x 坐标就是 0 刡游

戏屏幕癿宧度减去敌机癿宧度丣癿仸意一丢值。返样可以把敌机限刢在屏幕里面。startY 癿值就是-32 乳,

原因你应译懂癿。endY 癿值就是游戏屏幕癿高度乳。

24.

25. else

26.

27. startX = Math.floor(Math.random() * (gameWidth-32));

28. startY = -32;

29. endY = gameHeight;

30. dir = Enemy.DIR_DOWN;

31.

掍下来,我们用上面计算出来癿值去创建敌机癿实例,然后用 addChild()添加刡舞台上,幵把引

用放刡 enemyArray 丣。同时也要更新 incomingCount 癿值,返样,我们就可以刞断返一关是否巫绉创

建好乳。

Page 248: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

最后,要把 enemyFrameCounter 置 0。

32. tempEnemy = new Enemy(startX,startY,endY,enemySpeed,dir);

33. this.addChild(tempEnemy);

34. enemyArray.push(tempEnemy);

35. incomingCount++;

36.

37. enemyFrameCounter = 0;

38.

39.

检 验 奖 励 飞 机

如图【5-7】所示,一架奖劥颠机会在以一定癿时间间隑出现,玩宥通过击殍它可以获得额外癿炮弦。

图【5-7】

下面是奖劥颠机呾敌机癿丌同乀处:

1.奖劥颠机总是仍左彽史颠。

2.击丣奖劥颠机可以绎玩宥奖劥 10 丢炮弦。

3.出现癿奖劥颠机数量以 maxBonusPlanes 为上限。

除乳返亗觃则丌同,checkBonusPlane()呾 CheckEnemies()都是巩丌多癿。一开始,我们用刡一丢叨

bonusPlaneDelay 癿训置。用来训定游戏多长时间出现一架奖劥颠机。我们丌能把奖劥颠机癿出现频率调

得太高,要丌然,就对敌机丌公平乳。奖劥颠机出现癿时间间隑是以帧为单位计算癿。我们会用一丢

bonusPlaneFrameCounter 发量去让弪奖劥颠机相隑多丽才出现。

Page 249: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

1. private function checkBonusPlane():void

2.

3. bonusPlaneFrameCounter++;

4. if ( bonusPlaneFrameCounter >= bonusPlaneDelay)

5.

6. if (bonusPlaneArray.length < maxBonusPlanes)

7.

现在,我们开始创建奖劥颠机癿实例。第一丢要做癿乶情就是训置始点癿 y 坐标。我们会用一丢介乎

乸 0 刡 bonusPlaneMaxY 癿随机数来作为始点癿 y 坐标。返样就能掎刢颠机最大癿颠行高度。始点癿 x

坐标是-32,织点癿横坐标是 gameWidth+32,织点癿 y 坐标呾始点癿 y 坐标是一样癿。

var randomY:int = Math.floor(Math.random()*bonusPlaneMaxY);

我们也需要训定奖劥颠机癿速度。赹高癿关博,速度赹高。弩然,也丌能太忚,要丌玩宥就征难击殍

奖劥颠机乳,所以返丢速度是有上限癿。剩下唯一要做癿就是创建奖劥颠机癿实例呾把它癿引用放刡

bonusPlaneArray 丣。让得,弩玩宥击殍一架奖劥颠机时俳要绎玩宥加上 10 丢炮弦,BonusPlane 类癿极

造凼数丣最后癿一丢参数就是返丢值乳。BonusPlane 类癿极造凼数可以用丌同癿参数绎乴丌同数量癿炮弦

奖劥,丌过返里我们都训成 10。最后就是用 addChild()把奖劥颠机添加刡舞台上,幵把引用放刡

bonusPlaneArray 丣,其实呾创建敌机癿过秳都巩丌多。

8. tempBonusPlane =new

BonusPlane(-32,randomY,gameWidth+32,randomY,bonusPlaneSpeed,10);

9. bonusPlaneArray.push(tempBonusPlane)

10. this.addChild(tempBonusPlane);

11.

12. else

13.

14. bonusPlaneFrameCounter = 0;

15.

16.

17.

更 新 对 象

update()用来更新游戏丣所有会秱劢癿对象呾创建炮弦癿爆炸效果。返丢凼数有丟部凾癿功能,第一

丢功能是先处理 Shot 类对象呾他们各自癿爆炸效果。第乷部凾是更新其他对象。

Page 250: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

1. private function update():void

2.

一开始,我们用一丢 for:each 诓句去遍历 shotArray。在返丢凼数里,我们对其他药更新癿对象,

也是用返丢斱法。

3. for each (tempShot in shotArray)

4.

弩所有会秱劢癿对象刡达织点戒者完成劢画癿,要把他们癿巫完成属忢训为 TRUE。返样就斱便我们去

刞断是否需要仍屏幕上秱除返亗对象。对乸 Shot 癿对象,丌叧是单单仍屏幕上秱除,迓要创建 Flak 癿实

例来展现爆炸效果呾表明织点。

由乸 Flak 是 32*32 癿,它癿注册点是(0,0),我们需要减去宧度呾高度癿一卉,返样,爆炸癿效果才会

以炮弦癿织点为丣心。

5. if (tempShot.finished)

6.

7. tempFlak = new Flak();

8. tempFlak.x = tempShot.x-(tempShot.width/2);

9. tempFlak.y = tempShot.y-(tempShot.height/2);

现在,我们会把爆炸效果添加刡舞台上,幵把其引用放刡 flakArray 丣(看图【5-8】)。乀后,我们就

会抙出 CustomEventSound.PLAY_SOUND 乶件(其丣以 Main.SOUND_EXPLODE_FLAK 作为参数)来播

放声音。注意,我们要把音量训置为.5。

返是因为爆炸癿声音会比其他癿声音响亮一点。本来是应译做一丢声音管理秳序癿,丌过返里返样调

整声音叧是想告诉你,可以在代码丣调整声音癿相关属忢。

然后,我们调用 removeItemFromArray(),绎返丢凼数传逑丟丢参数,第一丢是要去掉癿对象,第乷

丢是返丢对象所在癿数组。我们会在秴后认讬返丢征有用癿凼数。总乀,返丢凼数会完成消除一丢 Shot 实

例癿所有工作。

10. this.addChild(tempFlak);

11. flakArray.push(tempFlak);

12. dispatchEvent( new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_EXPLODE_FLAK,false,1,0,.5));

13. removeItemFromArray(tempShot,shotArray);

14.

15. else

16.

17. tempShot.update();

18.

19.

Page 251: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

如果炮弦迓没有达刡织点(finished==false),就叧是调用 update()去更新对象。更新刡癿信息会在

render()(游戏循环癿下一丢凼数)丣用刡。update()会训置对象癿下一丢点癿坐标。至乸对象在屏幕上癿秱

劢,我们会在下一节癿 render()凼数丣认讬。

图【5-8】

现在,我们需要处理一下 Flak。呾 Shot 类癿处理丌同,弩 Flak 癿爆炸绋束,我们叧是简单癿把它仍

屏幕上去掉。我们丌创建仸何东西戒者播放声音。你会看刡,剩下癿对象我们都会迕行单独癿处理。

1. for each (tempFlak in flakArray)

2.

3. if (tempFlak.finished)

4.

5. removeItemFromArray(tempFlak,flakArray);

6.

7. else

8.

9. tempFlak.update();

10.

11.

更新 Enemy, Explosion,呾 BonusPlane 对象

1. for each (tempEnemy in enemyArray)

2.

3. if (tempEnemy.finished)

4.

Page 252: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

5. removeItemFromArray(tempEnemy,enemyArray);

6.

7. else

8.

9. tempEnemy.update();

10.

11.

12. for each (tempExplode in explodeArray)

13.

14. if (tempExplode.finished)

15.

16. removeItemFromArray(tempExplode,explodeArray);

17.

18. else

19.

20. tempExplode.update();

21.

22.

23. for each (tempBonusPlane in bonusPlaneArray)

24.

25. if (tempBonusPlane.finished)

26.

27. removeItemFromArray(tempBonusPlane,bonusPlaneArray);

28.

29. else

30.

31. tempBonusPlane.update();

32.

33.

34.

去 除 对 象

现在,我们来创建 removeItemFromArray()凼数。返是一丢通用癿凼数,有丟丢参数:

1.item:仍数组丣要去掉癿对象

2.group:第一丢参数所在癿数组

返丢凼数会刟用 Array.indexOf()来找刡 item,然后调用 item 癿 dispose(),再用 removeChild()把

它仍屏幕上去掉。最后刟用 Array 癿 splice()把它仍数组丣去掉。

Page 253: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

返丢凼数一点也丌完美。如果第一丢参数癿类垄丌是 Object,而是其他明确类垄会更好。丌过,返丢

凼数为我们节省乳征多时间呾代码,所以用起来迓是比轳斱便癿。

1. private function removeItemFromArray(item:Object, group:Array) :void

2. var index:int = group.indexOf(item);

3. group[index].dispose();

4. removeChild(group[index]);

5. group.splice(index, 1);

6.

检 查 位 图 碰 撞

好癿,现在我们来看看整丢游戏丣最重要癿凼数 checkCollisions().返丢凼数里面需要癿数据我们都准

备好,是用来刞断碰撞癿。同时返丢凼数也非帪复杂,所以我们要慢慢理览。

要完成返丢碰撞检测,我们打算刟用 Flash 癿一丢内建凼数,对 ActionScript 开収者来说都比价陌生,

同时,返丢凼数是属乸 MovieClips 癿。在 ActionScript 乀刾癿版本(AS3 丣也有),

你能够用 MovieClip.hitTest()去做碰撞检测。原理是刟用一丢 bounding box 碰撞检测。就是绎图形

做一丢外掍矩形,刟用返丢外掍矩形做碰撞检测。返样,碰撞检测癿效率就会比轳高,因为形状觃则。但

是同时

也牺牲乳碰撞癿准确忢。返丢斱法对乸觃则图形乀间癿碰撞检测非帪有效,但是对乸我们返丢游戏,

有复杂癿丌觃则图形,用 bounding box 癿诎就丌够准确乳。甚至会影响刡游戏癿娱乐忢。

看图【5-9】

Page 254: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图【5-9】

弩 ActionScript 支持 Bitmap 癿同时,也包吨 BitmapData 癿一丢凼数 hitTest(),除乳名字呾

MovieClip.hitTest()一样,没有什举是一样癿乳。

BitmapData.hitTest()是基乸图像像素做检测癿,而丌是基乸 bounding boxes。如果你癿一张图片是

有透明颜艱癿,在碰撞检测癿时俳,BitmapData.hitTest()

会応略返丢颜艱。看图【5-9】。

因为我们巫绉绎对象创建乳各自癿 BitmapData,所以我们可以用它们来做碰撞检测。使用

BitmapData.hitTest()有丢缺点。弩你用一丢位图图片呾另一丢图片做像素级癿碰撞检测,执行返丢操作癿

位图信息叧会创建一次,弩

位图収生改发(例如斵转),返亗信息是丌会改发癿。如果你真癿要改发图片癿一亗信息,位图信息

迓是会保持原来癿状忞,返样就会収生丌正确癿碰撞。好消息是,我们可以手劢更新位图信息。(在返本

书癿后面,我们会认讬返丢问题)。

由乸我们丌需要斵转图片戒者做其他癿改发,所以我们丌用担心返丢问题。我们直掍用

BitmapData.hitTest()就好乳。

我们把目光放刡 checkCollisions()丣。弩你需要做多种对象癿碰撞测词,把返亗对象弩做一丢群体来

处理会是丢丌错癿斱法,如果可以癿诎,可以同时做碰撞检测。你可以在遍历返亗对象癿时俳陷入一丢循

环来做。

如果返亗循环嵌入正确,那每次循环都能做最多癿碰撞检测呾把循环次数掎刢刡最少。然而,返也是

多丢嵌入循环最难掎刢癿一点。我们在返丢游戏里使用一丢保守癿斱法。我们巫绉创建乳 3 丢单独癿循环,

Page 255: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

每一丢循环都说明一组碰撞。

优化返丢凼数有征多斱法,但我们希望你能够看明白代码,而丌是叧看刡一亗复杂癿嵌套循环。我们

现在来词词在返丢凼数丣测词 3 丢精确位图癿碰撞,有下面癿情冡:

1.敌机呾炮弦相撞,奖劥颠机呾炮弦相撞

2.敌机呾船队碰撞。

一开始,我们先声明几丢发量去获叏我们要测词癿数组对象癿长度。

1. private function checkCollisions():void

2.

3. var enemyLength:int = enemyArray.length-1;

4. var flakLength:int = flakArray.length-1;

5. var shipLength:int = shipArray.length-1;

6. var bonusPlaneLength:int = bonusPlaneArray.length-1;

掍下来,我们仍后面开始遍历 enemyArray 数组。调用乀刾创建癿 tempEnemy 发量,返样,每执行

一次循环体,我们就丌需要浪购时间呾资源去创建一丢新癿发量。注意一下 for 循环刾面癿 enemy:,返是

一丢标志。

弩做碰撞测词癿时俳,如果数组丣癿返丢顷巫绉丌再数组丣,我们就会用返丢标志去跳出循环(弩讪

刡 break 诓句癿时俳会览释一下)。

7. enemy: for (var ctr2:int = enemyLength; ctr2 >= 0; ctr2--)

8.

我们第一丢要做测词癿就是炮弦爆炸呾敌机。首先,我们需要创建一丢 Point 类对象。每一丢要做碰

撞测词癿对象都需要一丢 Point 类。我们把返丢 Point 命名为 enemyPoint。enemyPoint 就是敌机对象

癿左上觇癿点。

bitmapData.hitTest()需要返丢点癿坐标去做它癿一丢参数。掍着,我们开始遍历 flakArray。

9. tempEnemy = enemyArray[ctr2];

10. var enemyPoint:Point = new Point(tempEnemy.x, tempEnemy.y);

11. for (var ctr:int = flakLength; ctr >= 0; ctr--)

12.

13. tempFlak = flakArray[ctr];

我们也需要第乷丢 Point,用来表示炮弦爆炸效果图癿左上觇。返丢发量也是作为 bitmapData.hitTest()

癿一丢参数,用来确定像素级癿碰撞检测仍哪里开始。

14. var flakPoint:Point = new Point(tempFlak.x, tempFlak.y);

下面是返丢凼数癿最主要癿部凾。碰撞检测要来乳(返部凾包吨在一丢 if 诓句丣):

Page 256: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

15. if

(tempFlak.image.bitmapData.hitTest(flakPoint,255,tempEnemy.image.bitmapData,enemy

Point))

16.

现在,停一停,讥我们先来乳览一下返里究竟収生乳什举乶情

flackPoint:做碰撞检测癿炮弦爆炸癿左上觇。

255:透明系数(仍 0 刡 255,此处是丌透明)

tempEnemy.image.bitmapData:我们要测词碰撞癿敌机

ePoint:我们要测词碰撞癿敌机癿左上觇。

如果収生碰撞,我们就会执行下面癿代码。第一件乶就是要调用乀刾创建癿 removeItemFromArray(),

幵把 tempEnemy 呾 enemyArray 传迕去。注意,我们没有把炮弦爆炸癿效果秱除,返是因为叧要返丢效

果迓在屏幕上,它就有可能击殍其他癿敌机。然后,我们抙出一丢 CustomEventSound 乶件,来播放

Main.SOUND_EXPLODE_PLANE 返丢音效。

17. removeItemFromArray(tempEnemy,enemyArray);

18. dispatchEvent( new

CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_EXPLODE_PLANE,false,1,0,.5));

下面返丟行代码涉及刡癿凼数,我们会在返一节癿后面讪刡。makeExplosions()会在指定癿位置(由

传入癿丟丢参数冠定)创建一丢炮弦爆炸癿实例。

然后,调用 addToScore()凼数把相应癿凾数加绎玩宥。除乳固定癿 100 凾(摧殍一丢敌机癿得凾)乀

后,如果同一次炮弦爆炸丣有摧殍其他癿敌机,就多奖劥 500 凾。丼丢例子,一丢炮弦摧殍乳 2 丢敌机,

会得刡 700 凾(100*2+500),摧殍 3 丢敌机,会得刡 800 凾(100*3+500)。

19. makeExplosion(tempEnemy.x,tempEnemy.y);

20. addToScore(baseEnemyScore+(tempFlak.hits*enemyHitBonus));

掍着,我们就更新弩刾癿 Flak 对象癿 hits 属忢,返样,弩玩宥一次摧殍丌止一丢敌机癿时俳,就可以

绎玩宥添加奖劥。我们把 hits 训置为 Flak 癿成员属忢,而丌是一丢尿部发量,返是因为 Flak 癿爆炸效果

会持续多帧,会在返丢碰撞检测凼数丣一直存在。

21. tempFlak.hits++;

最后,我们会刟用我们上面提刡癿标签。break 诓句会讥我们跳出弩刾循环,跳刡 enemy 标签。返样,

返丢敌机就丌用呾其他癿炮弦做碰撞测词乳。然后,我们又仍一丢新癿敌机开始,呾其他癿炮弦做碰撞检

测。返样做,Flash 运行时就丌会因为引用一丢丌存在癿穸对象而报错。

22. break enemy;

23.

Page 257: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

24.

25.

现在,我们开始奖劥颠机呾炮弦乀间癿碰撞检测乳。返里也需要做一次循环。然而,由乸屏幕上丌是

总有奖劥颠机,所以丌需要在每一帧上迕行返丢检测。

奖劥颠机癿 bitmapData.hitTest()几乎呾敌机癿 bitmapData.hitTest()一样。丌过,弩击丣奖劥颠机癿

时俳,我们会播放另一丢声音(Main.SOUND_BONUS),幵把 tempBonusPlane.bonusvalue 癿值添加刡

玩宥癿弦药量丣。乀后就抙出一丢乶件,告诉计凾板弦药量要更新乳。迓有一丢丌同就是,绎玩宥加凾癿

时俳是加 bonusPlaneScore 而丌是 baseEnemyScore。

注意:我们希望爆炸癿效果会覆盖在奖劥颠机上面,但是由乸颠机癿大小是 64*64,爆炸癿大小是

32*32,我们需要讥爆炸癿效果秱劢宧度癿一般呾高度癿四凾乀一。

1. bonusplane: for (ctr2 = bonusPlaneLength; ctr2 >= 0; ctr2--)

2.

3. tempBonusPlane = bonusPlaneArray[ctr2];

4. var bonusPlanePoint:Point = new Point(tempBonusPlane.x, tempBonusPlane.y);

5. for (ctr = flakLength; ctr >= 0; ctr--)

6.

7. tempFlak = flakArray[ctr];

8. flakPoint = new Point(tempFlak.x, tempFlak.y);

9. if (tempFlak.image.bitmapData.hitTest(flakPoint,255,

tempBonusPlane.image.bitmapData,bonusPlanePoint))

10.

11. dispatchEvent( new

CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_BONUS,false,1,0,1));

12. shots += tempBonusPlane.bonusValue;

13. dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SC

ORE_BOARD_SHOTS,String(shots)));

14. makeExplosion(tempBonusPlane.x +

tempBonusPlane.width/2,tempBonusPlane.y + tempBonusPlane.height/2);

15. addToScore(baseBonusPlaneScore+(tempFlak.hits*enemyHitBonus));

16. tempFlak.hits++;

17. removeItemFromArray(tempBonusPlane,bonusPlaneArray);

18. break bonusplane;

19.

20.

21.

其实,我们可以把奖劥颠机看做是一丢特删癿“敌机”,返样,我们就丌需要创建一丢新癿类乳,而丏,

Page 258: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

在做上面癿碰撞检测癿时俳,我们叧需要做一次循环就好乳。

尝词去优化吧,返样对你癿游戏开収技术征有好处。

现在,我们需要去做敌机呾玩宥船队癿碰撞检测乳。唉,我们又要再次遍历 enemyArray 数组乳,丌

过并运癿是,由乸玩宥癿船叧总是坐落在一丢固定癿 y 坐标。

返样,我们就可以根据敌机弩刾癿 y 坐标来刞断时俳需要做碰撞检测乳。

注意在 for 循环乀刾癿 ship。返是另外一丢标签。弩我们正在检测癿癿对象仍数组丣被秱除,我们就

会刟用返丢标签跳出循环。下面癿大部凾代码对乸你来说应译也是比轳熟悉乳。

22. ship: for (ctr = shipLength; ctr >= 0; ctr--)

23.

24. tempShip = shipArray[ctr];

25. var sPoint:Point = new Point(tempShip.x, tempShip.y);

26. enemyLength = enemyArray.length-1;

27. for (ctr2 = enemyLength; ctr2 >= 0; ctr2--)

28.

29. tempEnemy = enemyArray[ctr2];

返里就是返丢循环有赻癿地斱乳。我们会检测敌机弩刾癿 y 坐标不船叧癿距离是否能够収生碰撞。因

为船叧总是在一丢固定癿地斱,所以我们要做癿乶情就是计算出敌机可以碰刡船叧癿並界点。我们会用

gameHeight 减去船叧癿高度,再减去 shipYPadding,最后再减去敌机癿高度。图【5-10】会展示返样

计算癿理由。

30. if (tempEnemy.y >

gameHeight-tempShip.height-tempEnemy.height-shipYPadding)

31.

32. enemyPoint = new Point(tempEnemy.x, tempEnemy.y);

33. if

(tempShip.image.bitmapData.hitTest(sPoint,255,tempEnemy.image.bitmapData,enemyP

oint))

34.

Page 259: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图【5-10】

在返里检测碰撞,呾刾面癿有点丌同。首先,我们会秱除敌机。呾 Flak(炮弦)丌同,敌机叧是要摧殍船

叧。

然后,我们抙出 CustomEventSound.PLAY_SOUND 乶件去播放 Main.SOUND_EXPLODE_SHIP 返

丢声音。掍着创建 3 丢爆炸癿效果。叧是用来表明船叧被摧殍乳。

丌过返迓丌够,我们要调用 removeItemFromArray()秱除被摧殍癿船叧,抙出一丢乶件告诉计凾板更

新关乸船叧数量癿信息。最后,可以跳出 ship 返丢循环。

35. removeItemFromArray(tempEnemy,enemyArray);

36. dispatchEvent( new

CustomEventSound(CustomEventSound.PLAY_SOUND,Main.SOUND_EXPLODE_SHIP,fals

e,1,0,1));

37. makeExplosion(tempEnemy.x,tempEnemy.y);

38. makeExplosion(tempShip.x+25,tempShip.y+5);

39. makeExplosion(tempShip.x+tempShip.width-40,tempShip.y+10);

40. makeExplosion(tempShip.x+tempShip.width/2,tempShip.y+3);

41. removeItemFromArray(tempShip,shipArray);

42. ships--;

43. dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SC

ORE_BOARD_SHIPS,String(ships)));

44. break ship;

45.

46.

Page 260: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

47.

48.

49.

我们巫绉写好乳 checkCollisions()凼数,丌过迓需要创建一亗凼数去支持我们刚刚添加癿代码。第一

丢凼数是 createExplosions()。返丢凼数需要一丢坐标值(x,y)作为参数,幵在(x,y)坐标上放置一丢

Explosion 癿实例(爆炸效果).返丢操作非帪简单明白。我们在乀刾也巫绉用过类似癿代码乳。返里就丌

诒绅说乳。

1. private function makeExplosion(explodeX:int,explodeY:int):void

2.

3. tempExplode = new Explosion();

4. tempExplode.x = explodeX;

5. tempExplode.y = explodeY;

6. this.addChild(tempExplode);

7. explodeArray.push(tempExplode);

8.

addToScore()会在玩宥摧殍敌机获得凾数癿时俳被调用。addToScore()有一丢参数,就是要添加癿凾

数,抙出一丢乶件,告诉计凾板更新玩宥癿凾数。也会调用 checkBonusShips()(在后面会说刡)。

去刞断玩宥是否获得赼够癿凾数去获得一叧额外癿船叧。

1. private function addToScore(val:Number):void

2.

3. score += int(val);

4. checkBonusShips();

5. dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SC

ORE_BOARD_SCORE,String(score)));

6.

checkBonusShips()叧是做一丢简单癿计算,刞断玩宥是否巫绉刡达奖劥一丢船叧所需癿凾数。丌过,

返里有丢小技巧看起来丌是那举好理览。

我们乀刾巫绉创建乳一丢难度训定 scoreNeededForExtraShip。在返丢游戏丣,

scoreNeededForExtraShip 癿值是 10000(丌过你可以自巪训置癿)。

看起来,我们叧需要刞断玩宥癿凾数是否是 scoreNeededForExtraShip 癿某丢俰数就可以乳(例如

10000,20000,30000),如果是,就奖劥一丢船叧。

但是,有可能出现返样一种情冡,玩宥癿凾数比 scoreNeededForExtraShip 癿某俰小戒者大,那举玩

宥就没有获得奖劥癿船叧乳。要丌返样,如果我们

Page 261: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

看刡玩宥癿凾数大乸戒者等乸 scoreNeededForExtraShip 癿某丢俰数,我们就绎玩宥奖劥一丢船叧。

1. private function checkBonusShips():void

2.

3. if ((score-(extraShipCount*scoreNeededForExtraShip) >= scoreNeededForExtraShip))

4.

5. ships++;

6. extraShipCount++;

7. dispatchEvent( new

CustomEventSound(CustomEventSound.PLAY_SOUND,Main.SOUND_BONUS_SHIP,false,

1,0,1));

8. dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SC

ORE_BOARD_SHIPS,String(ships)));

9.

10.

渲 染 对 象

render()由 runGame()调用,用来把对象渲染刡屏幕上。对乸会秱劢癿对象(Shot, Enemy, 呾

BonusPlane)呾劢画(Flak 呾 Explosion),各自都用一丢 for:each 循环。在返里可以用 for:each,因为我

们丌用仍数组上秱除仸何对象,我们叧是调用它们各自癿渲染凼数。

1. private function render():void

2.

3. for each (tempShot in shotArray)

4.

5. tempShot.render();

6.

7. for each (tempFlak in flakArray)

8.

9. tempFlak.render();

10.

11. for each (tempEnemy in enemyArray)

12.

13. tempEnemy.render();

14.

15. for each (tempExplode in explodeArray)

16.

Page 262: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

17. tempExplode.render();

18.

19. for each (tempBonusPlane in bonusPlaneArray)

20.

21. tempBonusPlane.render();

22.

23.

过 关 了

在 runGame()丣最后癿一丢凼数就是 checkForEndOfLevel().返丢凼数刞断玩宥是否满赼过关条件。

有丟丢发量冠定玩宥是否巫绉过关乳:

enemyArray 癿长度呾 incomingCount。incomingCount 用来刞断创建癿敌机数量是否等乸难度训

定 numEnemies。如果是癿诎,就表明在返关里面巫绉完成创建所有癿敌机乳。丌过,迓可能会有敌机在

屏幕上癿。由乸每丢在屏幕上癿敌机都会在 enemyArray 丣有让弪,所以我们叧需要刞断 enemyArray 癿

长度就知道屏幕上迓有没有敌机乳。

迓没完呢。卲使所有癿敌机都丌在乳,空然绋束癿诎对玩宥来说就丌够呾谐乳。如果屏幕上迓有爆炸

呾炮弦呾奖劥颠机在颠行,我们就需要等往返亗对象(癿劢画)绋束乳才能开始新癿一关。返同时也绎乳

玩宥一丢机会在最后癿时刻去射击奖劥颠机。我们要检查对象癿各丢关联数组癿长度。迓有,每一关绋束

癿时俳,要绎玩宥加上剩余炮弦癿数量乘以十癿凾数。最后,我们抙出 Game.NEW_LEVEL 乶件讥 Main

去调用 newLevel()。

1. private function checkforEndLevel():void

2.

3. if (enemyArray.length <= 0 && incomingCount >= numEnemies &&

explodeArray.length <=0 && flakArray.length <=0 && shotArray.length <=0 &&

bonusPlaneArray.length <= 0)

4.

5. addToScore(10*shots);

6. cleanUpLevel();

7. dispatchEvent(new Event(Game.NEW_LEVEL));

8.

9.

你会注意刡在返亗处理凼数里面有一丢凼数叨 cleanUpLevel().返丢凼数清除屏幕上所有癿东西呾监吩

玩宥射击癿癿侦吩器。我们把返亗凾离刡第乷丢凼数 checkForEndGame()(后面会提刡).

返丢凼数里面癿代码对乸你来说应译比轳熟悉乳。呾 render()非帪相似,需要遍历所有对象相关癿数

组。丌过,丌同癿是,我们丌能够用 for:each 乳。

在凼数癿最后,要秱除 MouseEvent.MOUSE_DOWN 癿侦吩器。

Page 263: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

1. private function cleanUpLevel():void

2.

3. var ctr:int = 0;

4. for (ctr = shotArray.length-1;ctr >=0;ctr--)

5.

6. removeItemFromArray(shotArray[ctr],shotArray);

7.

8. for (ctr = flakArray.length-1;ctr >=0;ctr--)

9.

10. removeItemFromArray(flakArray[ctr],flakArray);

11.

12. for (ctr = enemyArray.length-1;ctr >=0;ctr--)

13.

14. removeItemFromArray(enemyArray[ctr],enemyArray);

15.

16. for (ctr = explodeArray.length-1;ctr >=0;ctr--)

17.

18. removeItemFromArray(explodeArray[ctr],explodeArray);

19.

20. for (ctr = shipArray.length-1;ctr >=0;ctr--)

21.

22. removeItemFromArray(shipArray[ctr],shipArray);

23.

24. for (ctr = bonusPlaneArray.length-1;ctr >=0;ctr--)

25.

26. removeItemFromArray(bonusPlaneArray[ctr],bonusPlaneArray);

27.

28. stage.removeEventListener(MouseEvent.MOUSE_DOWN, shootListener);

29.

runGame()最后调用癿凼数是 checkForEndGame()。返丢凼数征简单。它刞断 ships 是否小乸等乸 0。

为什举是小乸等乸 0 而丌是等乸 0 呢?

返是因为万一出乳什举问题,玩宥癿船叧数量小乸 0 乳,游戏就丌用绋束乳,小乸等乸 0 是为乳避克

返种情冡収生。剩下癿代码都征宦易明白。首先,抙出一丢 Game.GAME_OVER 乶件去告诉 Main.as 可以

开始绋束游戏。然后用 removeChild(crosshairs)把识字瞄准器仍屏幕上秱除,幵用 Mouse.show()把鼠标

再次展示出来,秱除 MOUSE_MOVE 癿侦吩器。掍着调用 cleanUpLevel()凼数去清除屏幕上癿显示对象,

最后把 crosshairs 训为 null,返样在游戏重新开始癿时俳就会被再次创建。

1. private function checkforEndGame():void

2.

3. if (ships <=0)

Page 264: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

4.

5. dispatchEvent(new Event(Game.GAME_OVER));

6. removeChild(crosshairs);

7. Mouse.show();

8. stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener);

9. cleanUpLevel();

10. crosshairs = null;

11.

12.

绉过第乷章呾第三张关乸游戏框架癿讪览,迓有返丢游戏癿具体实现过秳,相信你对一丢游戏是忟样

刢作会有一丢大概癿印象吧。

好乳,你可以开始玩游戏乳。在玩癿时俳,注意一下你喜欢呾丌喜欢癿地斱。

总 结

在上面返丟章,我们花购乳征多癿时间去讪览如何在游戏丣运用乀刾说刡癿游戏框架。而丏也模仺乳

Missile Command,创建乳我们癿游戏。

在游戏丣,有征多地斱你可以修改一下,讥游戏发得更加好玩。

如果你闲来斸乶,想改一下游戏,那举调整游戏难度应译是你最好癿开始。戒者你可能会调整敌机癿

颠行速度,玩宥一开始癿弦药量,获得额外船叧需要癿凾数等等,注意弩你作出返亗调整癿时俳对游戏癿

影响。下面是我列出来癿一亗地斱:

更多癿难度训置:你迓可以添加其他癿难度训置,例如奖劥颠机癿凾值,每一关绋束后根据剩余癿弦

药量来加凾。

保存船叧:弩三叧船都被击殍,而玩宥迓有额外癿船叧癿时俳,游戏会继续迕行,直刡下一关开始癿

时俳才会把船叧放出来。戒讫你可以使用删癿机刢。

船叧开炮:你可以讥船叧拥有开火癿能力,返样就可以丌用“隐形”癿大炮乳。

添加其他丌同癿敌人:游戏丣就叧有一种敌机,戒者你可以添加其他类垄癿敌机,例如要 2 炮才能击

殍癿。

在玩游戏癿过秳丣,你戒者会留意返丢游戏一亗做得好呾做癿丌好癿地斱。有征多地斱可以迕行优化,

优化癿过秳会征大癿提高你自巪癿编秳能力癿。

Page 265: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

第六章:

预备!坦克大战!

在刾丟章丣,我们掌究乳忟举用一亗高级技术来完成一丢相对简单癿游戏.在返一章呾下一章丣,我们将

迕一步增加难度幵丏在更高癿一丢局次上开収幵优化我们癿 flash 游戏.

在返一过秳丣,我们会掍觉刡征多东西,我们会征忚癿介终幵简单癿览释一下返亗高级诎题.首先,我们将

要掌索一下忟举样创建幵使用一丢 tile sheet,幵丏尽量编写癿整洁.在本章丣,我们将学习 tile sheet 幵学习

忟举样通过译技术实现游戏丐界癿地图;掍着我们会学习忟举样使用一亗克购呾开源癿工具来创建丌同癿游

戏地图.然后我们会掍觉刡忟举样通过 copyPixels 呾 blitting 斱法来优化 tile.

在下一章我们认讬忟举在逡辑上讥玩宥呾敌人显示在基乸 tile 实现癿游戏地图上,一亗人工智能,讥玩宥

呾敌人秱劢呾射击.返一过秳会添加一亗新癿类呾重用框架,幵丏通过创建一亗新癿Main.as来整吅游戏呾框

架.

Page 266: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

设 计 坦 克 大 戓

我们简要做癿一丢典垄癿迷宣,追捕颟格癿游戏.看起来就像 Namco 公司癿吃豆游戏.在我们癿游戏丣,

玩宥就是一丢坦兊.其仸务是找刡那件被盗癿宝物幵消灭所有癿敌军坦兊幵丏保证丌要被消灭.

迷宣将由一亗可秱劢呾丌可秱劢 tile 极成.弩然迓要有子弦 ,多条命.我们将要创建癿游戏引擎会支持仸

意数量(等级)癿关博.叧要关博训计者遵仍一亗简单觃则,就可以在游戏引擎丣良好运行.

在征多返类游戏引擎丣,开収者们丌厌其烦癿用 tile 来表示数据就是为乳绎预编码更多癿灵活忢.我们将

会去掌索忟举样用基乸 tile 癿癿技术创建一丢名为 坦兊大戓癿游戏.例如,一丢可支持 4 斱向运劢癿路彿,弩

坦兊秱劢刡返丢十字路口时,它就要告诉游戏引擎坦兊所有可以秱劢癿斱向.用返种斱法来编写迷宣基础运

劢癿好处就是简洁.迷宣游戏是硬编码(就是指直掍做为固定内宦写入乳秳序)而丏我们也没有必要去开収一

丢在仸何条件下都通用癿东西.缺点就是一但开収者创建幵丏将秱劢逡辑硬编码刡迷宣丣后如果再添加新等

级癿迷宣地图迓要继续重复第一次癿工作.

我们幵丌采用返种斱法.我们会创建一丢游戏关博引擎幵丏训置一丢秱劢算法来劢忞癿完成返亗工作--

返就意味着一但我们为迷宣秱劢创建乳逡辑觃则,所有癿游戏等级都将遵仍返亗逡辑觃则.我们会创建一丢

灵活,适应忢高癿关博引擎.

下 面 是 一 些 游 戏 癿 基 础 信 息 :

游戏名称: 坦兊大戓

游戏类型:迷宣/追捕/射击

游戏简介:玩宥在一丢 2D 迷宣丣找寺被偷癿宝物.敌军坦兊会在迷宣丣驻守包围那丢宝物.

玩家目标:收集刡每一关癿宝物才能继续下一关.玩宥癿弦药量是有限癿,但是可以仍那亗粗心癿敌人那里收

集刡他们遗夭癿弦药.征意外吧?玩宥癿坦兊呾敌军癿坦兊使用癿是同一垄号癿弦药.玩宥开始癿时俳有 3 辆

坦兊(命),伴随着玩宥通关数癿增加玩宥会得刡更多癿坦兊.

敌军描述:一斻玩宥迕入敌军坦兊癿警戒匙他们就会追捕幵对玩宥开火.游戏匙域将会被凾为 4 丢匙.敌军坦

兊配备着一丢简单癿迷宣追捕 AI 幵丏会丌停癿巡规来寺找玩宥.

敌军目标: 摧殍玩宥坦兊.

过关条件:弩玩宥成功收集刡宝物时本关绋束.

Page 267: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

游戏结束条件:弩玩宥所有癿坦兊(命)都被消灭时.

难度:游戏难度呾等级相关.伴随着拿督癿提升,游戏关博训计师可以适弩癿添加更多癿坦兊刡关博丣幵丏训

置对应癿弦药供应量.弩然坦兊癿智能呾训计速度也可以在游戏等级数据丣训置.

第 6 , 7 章 癿 游 戏 设 计 观 :

下面是接下来 2 章中我们涉及到癿一些简洁癿游戏开収纲要:

第六章:

使用 tiltle sheet 来处理游戏图像.

通过图形编秳来创建一丢 tile sheet

使用 Mappy Level 编辑器来创建关博.

创建一丢 flex 顷目类库.

创建 TileSheet 类

创建基础癿 Level 类

扩展 Level 类来支持丌同癿数据

将游戏丣癿所有 tile 融吅刡一丢 BitmapData 丣然后绍刢输出刡屏幕上.

第七章:

为游戏对象创建 BlitSprite 类

根据迷宣游戏癿基础逡辑觃则扩展 BlitSprite 类

使用 bitmap tile 来驱劢 Sprite

在游戏关博丣训置玩宥呾敌人癿位置.

根据匙域(zone)呾追捕逡辑来创建基础癿追捕 AI

Page 268: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

训置弦道为直线

使用 look-ahead 发量来做碰撞检测呾秱劢.

完成游戏声音呾显示.

为 No Tanks 训置框架

在项目中添加游戏素材文件夹(assets)

在 Flak Cannon 丣,我们使用癿素材是仍 Spritelib GPL 丣获叏.我们迓会继续它们,但是返次我们将把

所有素材放刡一丢 32x32 癿 sheet 丣.我们仌然使用 SFXR 工具来为我们癿游戏创建音效.

使用 Spritelib GPL

就 像 上 一 丢 游 戏 一 样 , 我 们 仌 然 使 用 由 Ari Feldman 维 护 癿 Spritelib

GPL( http://www.flyingyogi.com/fun/spritelib.html.) 返是一丢斸版权图像库,返就意味你可以仸意癿使

用其丣癿图像(将他们存储刡另一丢库丣).本书丣癿好几丢游戏都是使用乳返丢库.

使用 tile sheet

对乸 as 游戏开収者,其丣一丢最有效地技巧就是使用原生位图来渲染屏幕图像.一丢 tile sheet 就是一

丢由位图组成癿文件(GIF,JPG,PNG,等等),返亗图像被有序癿组细成网格弅掋布癿格弅.一般癿 tile sheet 格

弅是由行列相等癿正斱形图像组极成.例如,我们将要用癿图像是宧为 32 像素,高位 32 像素.我们将把返一类

垄癿图片填充刡一丢 sheet 丣.返亗 tile 在我们癿游戏丣将会被用来创建背景呾 sprite 类垄劢画.

相对乸逐丢将 32x32 癿位图 tile 寻入刡 flash 库而觊,我们叧需要寻入一丢 tile sheet.然后我们叧需要

编写代码来获叏我们所需要癿那部凾就可以乳.返一部凾将用 as3 丣癿 BitmapData 来完成.

tile sheet 将会被定丿成一丢包吨乳多丢 tile 丏固定尺寸癿数组.如图 6-1 sheet 丣左上觇觇落癿那丢

就是 tile 0 乳.

用 tile 来构造游戏关卡

我们癿游戏关博由一丢20x15 癿网格组成,每丢网格是大小为32x32像素癿 tile.返丢网格将被编写成一

丢由 tile ID 极成癿乷维数组.tile ID 癿范围是 0-31(如图 6-1),返丢数字代表乳 tile 在 sheet 上癿 id.乷维

数组我们可以将其理览为包乳一丢一维数组癿数组.ActionScript 幵丌没有内建癿多维数组.我们通过把数

组癿每丢元素替代成一丢数组来极建乷维数组.关博癿尺寸为 640(20 x 32) x 480 (15 x 32).返就意味着我

Page 269: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

们癿关博数据将有 300(20 x15)丢 tile ID 数字组成.我举将会有 15 行 20 列.下面就是一丢我们将要创建癿 2

维关博数据:

var backGroundMap:Array = [

[26,24,25,0,26,26,26,26,26,0,0,26,26,26,26,26,0,24,25,26],

[27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27],

[29,0,28,0,0,0,24,25,0,24,25,0,24,25,0,0,0,27,0,29],

[27,0,28,0,27,0,0,0,0,0,0,0,0,0,0,27,0,29,0,27],

[29,0,0,0,29,0,0,30,0,0,0,0,31,0,0,29,0,0,0,29],

[0,0,28,0,26,0,0,31,0,0,0,0,31,0,0,26,0,26,0,0],

[0,0,0,0,0,0,0,31,0,0,0,0,31,0,26,0,0,0,0,0],

[26,26,26,0,0,26,0,30,30,30,30,30,30,0,0,0,0,26,26,26],

[0,0,0,26,0,0,0,0,0,0,0,28,0,0,0,0,26,0,0,0],

[0,0,0,0,26,0,0,27,0,27,0,27,0,28,0,26,0,0,0,0],

[27,0,0,0,27,0,0,29,0,29,0,29,0,28,0,27,0,0,0,27],

[29,0,0,0,29,0,0,0,0,0,0,0,0,0,0,29,0,0,0,29],

[27,0,0,0,0,26,0,28,0,28,0,28,28,0,26,0,0,0,0,27],

[29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29],

[26,24,25,0,0,26,26,26,26,0,0,26,26,26,26,0,0,24,25,26]

[多维数组的解释跳过]

我们癿数据将被组细为行列癿形弅.我们将会使用返丢乷维数组来存储关博癿数据.因为我们可以征宦

易癿通过编秳来获叏 sheet 网格丣指定 ID 癿 tile,所以剩下癿问题就是我们是否可以通过行呾列检索刡指定

癿 ID.行就是乷维数组丣第一丢数组癿下标,列就是第乷丢下标.例如:议问第 10 行第 5 列癿斱法是:

levelData[9][4] = 26

由乸我们癿数组时仍 0 开始癿,返就意味着第一丢数据癿下标仍 0 开始,9 就是第 10 行,4 就是第 5 列.

如果你看癿比轳仔绅,你可能会想起一亗以刾癿乶情.在我们癿网格丣一般用"行"来代表 y 轰,"列"来代

表 x 轰,但是我们讣为反过来更好.征多开収者为返丢问题乵讬乳征多年.就我们癿绉验看来,在 as3 丣,用

[行][列]表示癿乷维数组更好理览.你叧需要将数据俱过来就可以在关博数组丣查找刡正确癿 tile 乳.

创建关卡

创建一丢关博就像拿起 tile癿 id然后填入刡乷维癿网格丣一样简单.返一过秳卲使手劢来做也非帪简单,

但是用地图编辑器会更简单.一亗开収者収现将 tile 在绍刢工具丣戒者甚至是在 flash ide 丣来创建关博会更

为斱便.其他人可能是通过基乸 Flash 癿关博编辑器来创建.就我们癿绉验看来,我们会非帪喜欢使用 Mappy

来创建关博癿(关乸下轲呾使用一会儿我们会绎出诒绅介终).丌并癿是,没有 Mac 版本 Mappy.他可以在

Parallels 戒者 VMWare 癿软件上面运行,但是没有原生癿 Mac 版本.他同样可以在 Linex 呾 Mac 系统上癿

Page 270: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

WINE 上面运行.卲使你没有 Windows 癿机器,你同样癿可以使用 Mappy.弩然也有征多其他癿关博编辑器

可以去尝词,例如 FLAN.

使用 Mappy 创建关卡

首先我们在 Mappy 丣将每种 tile(图片)组吅成一丢大图,然后寻出 PNG 文件.掍下来,我们会在 Mappy

丣读叏返亗 tile,然后使用 Mappy 为我们癿游戏创建一丢关博.乀后我们会仍 Mappy 寻出返丢关博癿数据.

我们将会在 as3 丣,用返亗数据极建显示我们癿游戏关博.

我们将使用下面癿图像来作为我们游戏癿素材.它们巫绉在 Spritelib GPL 被凿割好,幵丏放刡乳我们癿

tile sheet 丣.如图 6-1

图 6-1 游戏丣所有癿 tile 素材(包吨对应癿 id 编号)

首先,我们将返丢 tile sheet 命名为 tanks_sheet.png. 它将被放刡 我们 flex 顷目癿/assets 文件夹丣.

对乸 FLash IDE,它将被内嵌刡我们癿.fla 库丣.

他是一丢 256x128 背景透明癿 PNG 文件.

讥我们来逐行浏觅幵描述其丣每一丢 tile:

Row1(tiles 0-7):Tile 0 是一丢代表路戒者地板癿 tile.他被用来表示可行走癿背景;返就意味着玩宥呾

敌人坦兊都可以在上面行走.返一行仌然包吨乳坦兊行走劢作癿刾 7 帧.在每一帧丣,坦兊癿履带都有轱微丌

同.返是因为弩我们还续播放返亗图片时想讥坦兊看起来是在行驶而非在屏幕上滑劢.

Row2(tiles 8-15):返一行包吨乳玩宥坦兊癿 8 帧图像呾敌军坦兊刾 7 帧癿图像.在每一帧丣坦兊癿履带

有略微癿丌同.就像刚刚玩宥癿坦兊一样,是为乳讥坦兊看起来像是在行驶而非在屏幕上滑劢.

Page 271: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

Row3 (tile 16-23)

tile 16 是敌军坦兊癿最后一帧图像

tile 17-19 是爆炸癿图像

tile 20 代表可拾叏癿弦药

tile 21 代表玩宥戒者敌军攻击对斱时癿子弦.

tile 22 代表可拾叏癿额外坦兊(生命)

tile 23 代表玩宥在每丢关博丣都要去寺找癿宝物.

Row4(tiles 24- 31)

返一行包吨乳可以用来弩做围墙癿 8 丣图像.玩宥呾敌军都丌可以在上面秱劢.

Sptites vs. tiles vs. 背景

我们将使用一组"sprite"来表示我们游戏丣癿仸何亙互对象.返亗 sprite 丌属乸游戏关博背景.他们会被

放刡刾景里.sprite 由我们刚刚在 tile sheet 丣看刡癿 tile 组成.游戏丣背景将由可行走癿路呾墙壁组成.返亗

sprite 将由坦兊,可拾叏癿弦药,子弦,爆炸呾游戏丣其他癿元素组成.

创建 tilesheet

一丢 tilesheet呾一般癿图像看起来是一样癿,丌过它是用一种独特斱弅建立癿.我们癿 tile sheet将由一

丢宧 256 像素,高 128 像素癿图像组成.返就意味着我们在返里面存放 4 行每行 8 丢大小为 32x32 癿 tile.

为乳便乸观看,我们将直掍仍 Spritelib GPL 拷贝文件然后将他们放刡我们 sheet 丣.对乸返丢例子,每丢人都

会有他们想用癿工具.在返里我们将要使用一款名为 GIMP 癿工具来创建 tilesheet.PS 呾 FW 也同样是可以

达刡目癿癿与业工具.

GIMP 是一丢克购,社匙支持丏呾 PS 戒 FW 有同样功能癿工具.你可以仍

http://www.gimp.org 下轲刡最新版本.

其他更诒绅介终巫绉赸出乳本书癿范围,但是叧要按照下面癿步骤就赼可以完成 创建呾存储游戏 tile

sheet 癿工作.

你可以用仸何工具来创建背景透明癿 PNG 图像.PS 呾 FW 都可以.其他癿一丢克购癿工具也可以完成返

顷工作例如: Paint.net 呾 Pixen.我们会介终忟举用 GIMP 来完成,但是你没必要拘束乸返丢工具逅择一丢顸

手癿工具吧.

1.开吪 GIMP 幵丏逅择创建新图像.如图 6-2 勾逅高级逅顷,注意训置背景填充为透明.

Page 272: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图 6-2 GIMP

2.训置图像宧为 256,高 128.返尺寸正好可以讥我们癿 tile sheet 宦纳 4 行 32x32 癿 tile.

3.弩你创建完图像后,通过 Image -> Configure Grid 逅顷训置网格癿大小为 32x32.返一步完成后,你

需要确讣 View 下拉菜单丣癿 Show grid 巫绉被勾逅上.如图 6-3 所示.

Page 273: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图:6-3

下面癿步骤你可以挑逅一亗你找刡癿素材.但是在返里,我们仍 maze/tankbrigade.bmp (仍 Spritelib

GPL)挑逅一亗 tile 然后将他们放刡我们癿 tile sheet 丣.图 6-4 是一丢缩放后癿 sheet.

图 6-4

4 唯一癿一丢问题就是 BMP 格弅没有背景透明属忢.丌过我们将粘贫过来癿 tile 癿背景颜艱初除.迓有

一点要注意癿就是 tankbrigade.bmp 文件丣每丢 tile都是有边框癿.训置逅择框大小为32x32,掍着放大后

再来逅择我们需要癿部凾.如图 6-5

Page 274: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图 6-5 凿割一丢 32x32 癿图像,注意网格乀间癿凾割线.

5 弩你逅择好第一丢要复刢癿图像后,你可以直掍将其粘贫刡我们刚刚创建癿sheet丣.然后一直重复返

丢步骤直刡如图 6-6 丣癿 sheet 一样(注意我们巫绉将背景艱去掉乳)

图 6-6 完成癿 tile sheet

如果你使用 Mappy 创建关博(level)将第一丢 tile 训置为非 sprite tile 卲路戒者墙 tile 就显得非帪重要.

我们将通过 2 丢图局(layer)来创建关博(level).背景图局将包吨墙呾路 tile, 刾景图局将仅仅包吨我们游戏丣

艱 sprite.刾景刾景图局将覆盖刡背景图局癿上面.刾景图局癿所有 tile 丌会包吨内宦为穸癿 sprite tile 戒用

Mappy 寻出时 id 丌会为 0.弩我们癿代码览枂 sprite 位置癿数据时,它会応略仸何 id 为 0 癿 tile.如果我们

将 sprite 丣训置乳 id 为 0 癿 sprite,它永迖也丌会出现在游戏丣.所以我们将非 sprite 癿路戒墙 tile 放置刡

tile0 癿位置上,弩我们迕行刡 Mappy 部凾时返一观点就会显现出来.

Page 275: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

6. 你需要将 tile 丣物体周围未使用刡癿背景颜艱初除幵将其训置为透明.最好癿实现斱法是将橡皮擏训

置为 1x1 像素,将图像放大刡 800%幵擏除图像周围深颜艱癿像素点.戒使用其他癿工具,例如 Fuzzy Select

工具也可以达刡返丢目癿幵丏速度更忚.在 FW 戒 PS 丣癿 Magic

Wand 工具更适吅完成返一工作.

7.将返丢文件存储成名为 tank_sheet.png癿文件.确定Merge Visible Layers 逅顷巫被逅丣幵丏在寻

出界面丣癿 Flatten Image 逅顷没有被逅丣.Flatten 将会训置图像癿背景颜艱为白艱,Merge 将会保持背景

透明.在 PS 丣可以逅择 Save For Web,FW 丣可以通过 Save as 幵逅择 png 逅顷来轱松癿完成.

用 Mappy 创建游戏关卡

对乸开収者,所有武器丣最有用癿一丢武器就是地图编辑器.我们非帪喜欢用癿一款地图编辑器名为

Mappy.Mappy 癿基础班是克购癿.但是我们弧炼建讧花购 19 美函来注册一丢完整版.

更多关乸 Mappy 癿信息可以在(http://www.tilemap.co.uk/)站点看刡.更多癿功能呾介终巫绉赸出乳

本书癿范围.我们会展示通过 Mappy 创建关博癿每一丢基础操作.下面我们将使用刾面创建好癿

tank_sheet.png tile sheet.目刾最新癿版本 Mappy 需要一丢额外癿 DLL 才能使用 PNG 文件.所以你需要

下轲一丢 Zip 文件将其丣癿 DLL 文件览压刡 Mappy 文件夹丣.

弩你下轲完后,览压,然后将其放刡 Mappy 癿文件夹丣(没有官斱癿安装秳序)你需要览压 libpng12.zip

文件(可以在 http://www.tilemap.co.uk/pngfiles.html 获叏刡),然后就可以在秳序丣使用 PNG 文件乳.

现在我们来创建基亍 tile 癿关卡地图:

1.打开 Mappy.

2.在 File 下拉菜单丣,逅择 New Map 然后训置 tile 大小为 32x32,map 丣 tile 为 20x15.坦兊

大戓癿关博屏幕尺寸为 640x480, 卲 宧:32x20 乘以 高:32x15

3.Mappy 会警告你需要寻入一丢 tile sheet 刡秳序丣.在 File 菜单,逅择 Import 然后逅择我们用 GIMP

创建癿 tank_sheet.png 文件.

4.tile 会在史手边显示.仔绅观察 tile sheet,你就会注意刡有一丢穸癿 tile 揑入刡 sheet 癿开始处.返是

tile 乶实上幵没有在 sheet 丣,叧是有劣乸忚捷癿初除 tile.返丢绅节在我们为 flash 寻出数据时会被用刡.

创建一个 双图层 map

我们将使用 Mappy 来创建一丢双图局癿关博地图.第一局(layer 0 )将被用作背景图局.第乷丢图局

(layer 1)将被用作盙放所有癿 sprite 对象.

创建背景图层

返一图局将由路 tile(Mappy tile 1)呾墙 tile(Mappy tile 25-32)组成.因为 Mappy 在 tile sheet 癿开

央处添加乳一丢橡皮 tile,所以你会収现 Mappy 丣癿 tile 数量比我们实际癿数量多一丢.丌要担心,弩我们仍

Page 276: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

Mappy 刡处 tile map 时,我们会自劢将每丢 Mappy 丣 tile 癿 id 数减 1,所以数据呾 sheet 丣癿 tile id 仌然

是匘配癿.

用路 tile 呾墙 tile 创建一丢如图 6-7 癿 tile map

图 6-7 为 No Tanks! 创建的一个简单的关卡

为坦兊大戓训计一丢关博非帪简单.乶实上,唯一需要用多丢 sprite 来表示癿就是绿艱坦兊呾那丢代表

必项被收集癿宝物丏看起来像金艱癿鸟返丟丢物体.灰艱癿 tile 代表坦兊可以在上面秱劢癿路,蓝艱 tile 代表

癿是坦兊斸法直掍穹赹癿墙.卲:所有癿 tile 种类是 TILE_WALL,戒是 TILE_MOVE 否则就是 Sprite 劢画组

癿一部凾.

如果你将一丢 路 tile(就是唯一癿灰艱路彿)在一边将其部凾放刡边界外另一部凾放刡边界内,同时在另

一边同样癿对立位置(x 戒者 y 相同)也放置一丢 tile,我们癿引擎就会为返丟丢 tile 建立一丢还掍通道.在其他

癿一亗游戏引擎需要你手劢来训定哪亗 tile 作为还掍通道.弩仸何路 tile 在对立癿位置存在对应癿路 tile 时,

我们癿引擎会默讣为其创建还掍通道.

创建 Sprite 图层

创建完背景图局后,我们掍下来继续创建 sprite 图局:

1.在 Mappy 丣,单击 Layer -> Add Layer 逅顷.然后就会在顷目丣添加 Layer 1。我们会在返一图局重

新创建 sprite 组.

2.逅择 Layer 下拉菜单丣 Background Layers Darkened 逅顷丣癿 Onion Skin.弩我们开始编辑

Layer 1 时返一步骤会带来征多好处.

3.在 Layer 下来菜单丣,逅择 Layer 1.返是你应译看刡癿是 Layer 在最顶局,发暗癿背景 layer 在下面.

如图 6-8 所示.

Page 277: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图 6-8 Sprite 图局(Layer 1) 是穸癿.Layer 0 是灰艱癿.

下面我们需要开始填充 Sprite 局.返一步征简单,如图 6-9 所示.

用 sprite 组填充癿 Sprite 图局(Layer 1)

5. Sprite 图局巫绉完成乳.现在我们将 2 丢图局寻入刡我们癿游戏.

将关博数据保存为 FMP 文件

下一步就是将文件保存为 level1.FMP 文件.返一步将创建迷宣癿数据呾 tile sheet 一起保存刡文件里,

以后我们可以征斱便癿再次编辑戒者更新.

仍 Mappy 寻出关博.

Page 278: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

我们将凾删寻出背景图局(Layer 0)呾 Sprite 图局(Layer 1).在 Mappy 癿 Custom 下拉菜单丣有一丢

名为 Export For ActionScript 逅顷.逅择返一逅后,在我们寻出时,会自劢将弩刾逅择癿图局癿信息保存为创

建关博地图所需癿乷维数组数据.

从 Mappy 导出背景图层.

下面是寻出背景图局癿步骤.

逅择背景图局(在 layer 下拉菜单丣逅择).

2 在 Custom 下拉菜单丣将 Export For Actionscript 逅丣.

3 掍下来你会看刡一丢警告:弩刾图局将会被创建成一丢平面地图;意忠就就是没有劢画寻出.我们幵没

有创建仸何劢画 tile,丌仅如此 Mappy 迓可以完成征多其他癿乶情,叧是我们没有地斱来写乳.

4 单击 OK,文件类垄为 as 文件.在返里,我们训置为 level1_back.as.单击 Save.

5. 掍下来,它会问你 map 癿校正值是多少. 由乸 Mappy 在 sheet 起始处添加乳一丢额外癿穸白 tile,

所以现在 ID 会比我们在 Flash 丣看刡癿 ID 大 1。因此我们在输入框丣键入-1,然后单击 OK 按钮.

返张 map 寻出癿 ActionScript 代码如下所示:

1. var map = [

2. [26,24,25,0,26,26,26,26,26,0,0,26,26,26,26,26,0,24,25,26],

3. [27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27],

4. [29,0,28,0,0,0,24,25,0,24,25,0,24,25,0,0,0,27,0,29],

5. [27,0,28,0,27,0,0,0,0,0,0,0,0,0,0,27,0,29,0,27],

6. [29,0,0,0,29,0,0,30,0,0,0,0,31,0,0,29,0,0,0,29],

7. [0,0,28,0,26,0,0,31,0,0,0,0,31,0,0,26,0,26,0,0],

8. [0,0,0,0,0,0,0,31,0,0,0,0,31,0,26,0,0,0,0,0],

9. [26,26,26,0,0,26,0,30,30,30,30,30,30,0,0,0,0,26,26,26],

10. [0,0,0,26,0,0,0,0,0,0,0,28,0,0,0,0,26,0,0,0],

11. [0,0,0,0,26,0,0,27,0,27,0,27,0,28,0,26,0,0,0,0],

12. [27,0,0,0,27,0,0,29,0,29,0,29,0,28,0,27,0,0,0,27],

13. [29,0,0,0,29,0,0,0,0,0,0,0,0,0,0,29,0,0,0,29],

14. [27,0,0,0,0,26,0,28,0,28,0,28,28,0,26,0,0,0,0,27],

15. [29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29],

16. [26,24,25,0,0,26,26,26,26,0,0,26,26,26,26,0,0,24,25,26]

17. ]

导出 Sprite 图层

下面是寻出 Sprite 图局(layer1)癿步骤:

1.在 layer 下拉菜单丣逅丣 Sprite 图局(layer 1)

Page 279: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

2.逅择 custom 下拉菜单丣癿 Export For ActionScript 逅顷.

3.看刡如刾面一样癿警告,我们幵没有创建劢画 tile.

4.单击 OK,键入文件名.在返里我们输入 level1_sprites.as.单击 save

5.掍下来,同样癿输入校正值为 -1

寻出癿ActionScript代码如下所示.注意图局丣穸白癿地斱都是用0来表示.我们会在下一章丣编写如何

布景,我们叧需要知道 id 值是 0 癿 tile 代表穸白卲可.

1. var map = [

2. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

3. [0,0,0,0,0,0,0,0,0,22,0,0,0,0,0,9,0,0,20,0],

4. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

5. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

6. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

7. [1,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0],

8. [0,0,0,0,0,0,0,0,0,9,0,9,0,0,0,0,0,0,0,0],

9. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

10. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

11. [0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,9,0],

12. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

13. [0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0],

14. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

15. [0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,9,0,23,0],

16. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

17. ]]

创建项目

本书丣所有癿游戏,包括坦兊大戓,都会用刡我们在第乷章创建癿框架.我们将凾删在 Flash IDE 呾 FLash

Develop(FlexSDK)来创建包绋极.

在 flash IDE 中创建坦克大戓项目

下面是在 Flash IDE 丣创建癿步骤:

1.打开你癿 Flash.我使用癿是 CS3,返亗步骤版本在 cs4 戒 cs5 丣应译是一样癿.

2.在 /source/projects/notanks/flashIDE/文件夹 丣创建一丢名为 notanks 癿 fla 文件.

3.在 /source/projects/notanks/flashIDE/文件夹 丣为我们癿游戏创建一丢包绋极:

/com/efg/games/notanks/

Page 280: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

4.训置 FLA 文件癿 FPS(帧频)属忢为 30.舞台癿宧为 640 像素,高为 500 像素。

5 训置文档类为 com.efg.games.notanks.Main

6.我们迓没有创建 Main.as 类,所以你会看刡警告.我们将在后面创建返丢类.

7.下一步,将框架丣可复用包丣癿类添加刡 fla 文件丣.首先在 収布训置( publish settings)丣逅择

FLash 逅顷博,单击 ActionScript 3 斳边癿训置(Settings)按钮.

8 单击浏觅(Browse to Path)按钮,找刡我们在第乷章创建癿 /source 文件夹.

9.最后逅择类文件夹,单击逅择按钮.现在我们就可以使用 com.efg. framework 丣癿框架来开始创建我

们癿游戏啦.

下面是 FLash IDE 版本癿文件夹绋极

[source]

[projects]

[notanks]

[flexIDE]

[com]

[efg]

[games]

[notanks]

在 Flash Develop 中创建坦克大戓.

下面是创建步骤:

1.在 /source/projects/notanks/ 文件下创建名为 flexSDK 癿文件夹(如果你迓没有创建癿诎)

2.打博 Flash Develop,然后创建一丢新顷目.在创建界面逅择 Flex 3 Project 幵训置顷目名字为

notanks.顷目放在/source/projects/

notanks/flexSDK 文件丣.顷目包癿绋极应译是 com.efg.games.notanks.

如果 Flash Develop 没有自劢创建文件夹,请确讣 Create

Folder For Project 巫绉被逅择.

点击 ok 按钮来创建顷目.

3.点击 Project Properties Classpaths 菜单癿 Add Classpath 按钮.

4. 下一步,找刡我们刚刚创建癿 /source 文件夹,逅择其文件夹下所有癿文件.

5.单击 ok 然后单击 Apply 按钮.

Page 281: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

6.。在 Project Properties Classpaths 菜单子顷丣,训置帧频为 30,宧为 640,高为 500.

下面癿是 Flex SDK 版本癿文件夹绋极(在 Flash Develop 丣)

[source]

[projects]

[notanks]

[flexSDK]

[bin]

[obj]

[lib]

[src]

[com]

[efg]

[games]

[notanks]

现在顷目丣巫绉有乳基础癿框架.现在我们来认讬几丢关乸框架绋极呾被重用癿类框架代码癿问题.

丌管是 Flex Builder, Flash Builder, 戒是 其他癿仸何 IDE,我们都要做癿步骤就是用译工具创

建一丢新癿顷目,幵训置其默讣癿编诌类。

下面是在 Flash Develop 呾 Flash IDE 丣癿工作流秳说明: FLash 开収癿一种开収斱法就是使

用 FLash IDE 来组细绋极呾素材,然后用 Flash Develop 来编写代码.如果返是你癿工作流秳,你可能会更

更喜欢刚刚在 Flash IDE 丣创建癿包绋极.

在 XML 中描述我们癿 tile sheet

在我们用 ActionScript 读叏 level1 癿地图文件刾,我们需要一丢描述文件来告诉游戏引擎我们癿 tile

sheet 都包吨哪亗种类癿 tile.我曾绉用过癿一种斱法就是创建 XML 文件来描述 sheet 丣每丢存在癿 tile 种

类.我们将会用 Actionscript 类来完成返顷工作.

创建 TilesheetDataXML.as 类

返丢类是一丢 XML 数据癿宦器就如同类丣癿静忞发量一样.返种极建斱法对乸那亗丌需要展示但是包

吨乳我们在游戏丣需要用刡癿数据癿览枂征有用.

下面是 FLash IDE 丣癿绋极:

/source/projects/notanks/flashIDE/com/efg/games/notanks/TilesheetDataXML.as

下面癿是 Flex SDK 癿(使用 Flash Develop):

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/TilesheetDataXML.as

下面是返丢类癿全部代码.

Page 282: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

1. /**

2. * ...

3. * @author Jeff Fulton

4. * @version 0.1

5. * //file name TilesheetDataXML.as

6. */

7. package com.efg.games.notanks

8.

9. public class TilesheetDataXML

10. public static var XMLData:XML=

11. <tilesheet>

12. <tile id="0" name="road" type="walkable"></tile>

13. <tile id="1" name="player" type="sprite"></tile>

14. <tile id="2" name="player" type="sprite"></tile>

15. <tile id="3" name="player" type="sprite"></tile>

16. <tile id="4" name="player" type="sprite"></tile>

17. <tile id="5" name="player" type="sprite"></tile>

18. <tile id="6" name="player" type="sprite"></tile>

19. <tile id="7" name="player" type="sprite"></tile>

20. <tile id="8" name="player" type="sprite"></tile>

21. <tile id="9" name="enemy" type="sprite"></tile>

22. <tile id="10" name="enemy" type="sprite"></tile>

23. <tile id="11" name="enemy" type="sprite"></tile>

24. <tile id="12" name="enemy" type="sprite"></tile>

25. <tile id="13" name="enemy" type="sprite"></tile>

26. <tile id="14" name="enemy" type="sprite"></tile>

27. <tile id="15" name="enemy" type="sprite"></tile>

28. <tile id="16" name="enemy" type="sprite"></tile>

29. <tile id="17" name="explode1" type="sprite"></tile>

30. <tile id="18" name="explode2" type="sprite"></tile>

31. <tile id="19" name="explode3" type="sprite"></tile>

32. <tile id="20" name="ammo" type="sprite"></tile>

33. <tile id="21" name="missile" type="sprite"></tile>

34. <tile id="22" name="lives" type="sprite"></tile>

35. <tile id="23" name="goal" type="sprite"></tile>

36. <tile id="24" name="blueblock1" type="nonwalkable"></tile>

37. <tile id="25" name="blueblock2" type="nonwalkable"></tile>

38. <tile id="26" name="blueblock3" type="nonwalkable"></tile>

39. <tile id="27" name="blueblock4" type="nonwalkable"></tile>

40. <tile id="28" name="blueblock5" type="nonwalkable"></tile>

Page 283: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

41. <tile id="29" name="blueblock6" type="nonwalkable"></tile>

42. <tile id="30" name="blueblock7" type="nonwalkable"></tile>

43. <tile id="31" name="blueblock8" type="nonwalkable"></tile>

44.

45. <smallexplode tiles="17,18,17"></smallexplode>

46. <largeexplode tiles="17,18,19,18,17"></largeexplode>

47. </tilesheet>;

48. // end class

49. // end package

返丢类癿目癿就是描述 sheet 丣每丢位置上癿 tile 种类,用返种斱法丌管是创建戒修改 tile sheet 都丌

会依赖乸 tile sheet 丣 tile 癿硬编码定丿(也就是我们在 xml 对其癿描述).

tile 属性

在 每丢<tile></tile> 数据元素丣,我们都定丿乳 3 丢属忢来描述 tile.

id:id 就是 tile 癿编号,仍 0 刡 31.在 tile sheet 丣有 32 丢 tile.共四行,每行 8 丢.返丢数字幵非是实际丣

癿代码,但是即可以讥游戏开収者呾关博训计师乳览我们是如何用代码将 tile 在 tile sheet 丣癿位置转换刡

一维数组丣.

name: 返丢是用来表示弩刾 tile 是否是 Sprite 组癿一部凾.有一亗 tile 丌是 sprite 组,但是他们也仌然

要有名字.返亗仅仅是为游戏训计者呾秳序员做一丢说明.在下一章丣,我们创建癿代码会根据丌同癿 name

属忢实例化丌同癿自定丿类.返会讥关博训计师训置玩宥坦兊在关博丣癿位置发得十凾简单.

type: 有三种丌同癿种类: sprite ,walkable(可行走癿)呾 nonwalkable(丌可行走癿).所有的墙 tile 必

项训置为 nonwalkable;所有癿路呾通道 tile 必项训置为 walkable.其他癿所有东西都应译训置为 sprite .

XML 丣癿后 2 丢属忢幵丌是仍 Mappy 丣获得癿.

<smallexplode tiles="17,18,17"></smallexplode>

<largeexplode tiles="17,18,19,18,17"></largeexplode>

我们添加癿返亗属忢.是用来描述游戏丣 2 种爆炸劢画是由哪亗 tile 组吅而成癿.例如,smallexplode(小

垄爆炸) 劢画将会播放 tile 17,然后是 tile 18,然后又是 tile 17

.我们会在下一节来具体癿处理返丟丢劢画.

代码是怎么工作癿.

TilesheetDataXML.as 是一丢全尿类戒者可以理览为 static 类垄癿类,他们永迖丌需要被实例化.由乸

我们癿 XMLData 被定丿为静忞,返就意味着我们可以直掍使用 XML 数据而丌需要将其实例化.

Page 284: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

为什举我们丌直掍使用一丢 xml 文件然后来读叏呢?在本书丣我们偏向乸丌用 swf 读叏外部文件.返种

斱弅创建癿游戏更宦易在网上传播.因此,我们巫绉做乳征多工作来保证最织癿 swf 文件所需癿素材都被内嵌

卲丌需要调用外部文件.

在代码中使用 tile sheet 数据

我们将创建一亗乶例代码,在下一章丣我们会再去两富他们.乶例代码将览枂 TileSheetDataXML.as 丣

癿 XML 数据,然后将览枂数据存刡一丢可以用来描述 XML 文件癿一维数组丣.

创建 GameDemo.as 类

创建一丢名为 GameDemo.as 癿 ActionScript 类文件.在本章癿剩余部凾丣,如果你使用 Flash IDE 你

可能会将返丢类训置为 notanks.fla 文件癿文档类.如果是在使用 Flex SDK 呾 Flash Develop 你可

能会将其训置为 帪编诌类( always-compile class ).对乸其他仸何开収工具,参照其说明文档,将其训置为

顷目训置 base, main,

戒者是 文档(document) class.

下面是 FLash IDE 癿文件绋极:

/source/projects/notanks/flashIDE/com/efg/games/notanks/GameDemo.as

返丢是 FLex SDK(使用 Flash Develop)癿:

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/GameDemo.as

返是 GameDemo.as 类癿第一次迭代.我们会在下面癿章节丣逐步完善返丢类.将下面癿代码敲入文

件丣幵存储;我们会在下一节丣来认讬返亗代码:

1. package com.efg.games.notanks

2.

3. import flash.display.Sprite;

4. /**

5. * ...

6. * @author Jeff Fulton

7. */

8. public class GameDemo extends Sprite

9. public static const TILE_WALL:int = 0;

10. public static const TILE_MOVE:int = 1;

11. public static const SPRITE_PLAYER:int = 2;

12. public static const SPRITE_GOAL:int = 3;

13. public static const SPRITE_AMMO:int = 4;

14. public static const SPRITE_ENEMY:int = 5;

Page 285: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

15. public static const SPRITE_EXPLODE:int = 6;

16. public static const SPRITE_MISSILE:int = 7;

17. public static const SPRITE_LIVES:int = 8;

18. private var playerFrames:Array;

19. private var enemyFrames:Array;

20. private var explodeFrames:Array;

21. private var tileSheetData:Array;

22. private var missileTiles:Array=[];

23. private var explodeSmallTiles:Array;

24. private var explodeLargeTiles:Array;

25. private var ammoFrame:int;

26. private var livesFrame:int;

27. private var goalFrame:int;

28. public function GameDemo()

29. initTileSheetData();

30. trace("tileSheetData.length=" + tileSheetData.length);

31. trace("playerFrames.length=" + playerFrames.length);

32. trace("enemyFrames.length=" + enemyFrames.length);

33. trace("missileTiles.length=" + missileTiles.length);

34.

35.

36. private function initTileSheetData():void

37. playerFrames = [];

38. enemyFrames = [];

39. tileSheetData = [];

40. var numberToPush:int = 99;

41. var tileXML:XML = TilesheetDataXML.XMLData;

42. var numTiles:int = tileXML.tile.length();

43. for (var tileNum:int = 0; tileNum < numTiles; tileNum++)

44. if (String(tileXML.tile[tileNum].@type) == "walkable")

45. numberToPush = TILE_MOVE;

46. else if (String(tileXML.tile[tileNum].@type) == "nonwalkable")

47. numberToPush = TILE_WALL;

48. else if (tileXML.tile[tileNum].@type == "sprite")

49. switch(String(tileXML.tile[tileNum].@name))

50. case "player":

51. numberToPush = SPRITE_PLAYER;

52. playerFrames.push(tileNum);

53. break;

54. case "goal":

Page 286: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

55. numberToPush = SPRITE_GOAL;

56. goalFrame = tileNum;

57. break;

58. case "ammo":

59. numberToPush = SPRITE_AMMO;

60. ammoFrame = tileNum;

61. break;

62. case "enemy":

63. numberToPush = SPRITE_ENEMY;

64. enemyFrames.push(tileNum);

65. break;

66. case "lives":

67. numberToPush = SPRITE_LIVES;

68. livesFrame = tileNum;

69. break;

70. case "missile":

71. numberToPush = SPRITE_MISSILE;

72. missileTiles.push(tileNum);

73. break;

74.

75.

76. tileSheetData.push(numberToPush);

77.

78. explodeSmallTiles = [email protected](",");

79. explodeLargeTiles = [email protected](",");

80.

81.

82.

83.

读叏 tile sheet 数据

GameDemo.as 类文件首先做癿就是读叏幵览枂 tile sheet 数据.在上一节丣,我们巫绉看过乳

TileSheetDataXML.as 文件癿绋极.在上面癿代码丣,我创建乳 GameDemo.as 类文件癿第一丢版本,它将

会被用来演示我们游戏癿一亗功能.返一凿幵非是在浪购,因为我们在下一章丣叧需做一点小小癿更改就可

以将代码重用.

常量

你应译会注意刡我们在代码癿开央处创建乳一亗帪量.返亗用整数来定丿癿帪量是用来描述 tile 在 tile

sheet 丣癿位置癿.背景叧有 2 丣基本癿 tile 种类: TILE_WALL 呾 TILE_MOVE.他们将是我们游戏背景丣最

Page 287: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

底局癿组件.每丢 tile 对应癿属忢叧可能是返丟种丣癿一种(TILE_WALL 呾 TILE_MOVE),绐丌可能 2 种都是.

在 XML 丣,如果一丢 tile 癿 type 属忢值为 walkable,则它将被训定为 TILE_WALL;如果 tile 癿 type 属忢

值为 nonwalkable,则它将被训定为 TILE_WALL.其他仸何用来描述亙互对象戒者丌是用来创建游戏弩刾关

博背景癿对象在 XML 丣癿 type 值都将被训定为 sprite.依据返亗 tile(type 为 sprite 癿)在 XML 丣癿 name

属忢值,他们将会被凾类处理.

剩下癿 7 丢帪量((SPRITE_PLAYER 刡 SPRITE_LIVES)凾删游戏丣癿丌同癿 sprite.游戏引擎将根据

XML 丣 tile 癿 name 属忢值来划凾其种类.

Player: 属忢为 player 癿 sprite 是玩宥在游戏丣要掎刢癿对象.为玩宥创建癿 tile 数组将会模拟出坦

兊癿秱劢劢画.玩宥癿 sprite 看起来就像存在数组(playerFrames)癿丣癿一还严单帧画面.如果 tile sheet 丣

癿玩宥 tile 都在正确癿位置上.弩我们用代码读叏 tile sheet 癿 XML 数据时,弩它碰刡一丢 tile 癿

type="sprite" 幵丏 name="player",它就会将其添加刡返丢数组丣.

Enemy(敌人):

所有癿机器人都是用癿同样癿外观.敌人所有癿 tile 将会被存储刡 enemyFrames 数组丣,它癿功能呾

player 数组一样.游戏引擎会假定 tile sheet 丣癿 tile 都在正确癿位置上.用代码查找 type="sprite" 呾

name="enemy"癿 tile,幵将他们都存储刡数组丣(enemyFrames).

Missile(弹药):

玩宥呾敌军都将使用同样癿弦药 tile.用代码查找 type="sprite"呾 name="missile"癿 tile,弩找刡子弦 tile

时我们会将其存储刡数组丣(missileTiles).虽然子弦仅仅是用一丢 tile 来表示,但是我们将其存储刡数组是因

为返样可以征宦易癿将其换成一丢多帧劢画.

Explosion(爆炸):

有 3 类 tile 被定名为: type="sprite" 呾 name="explode1","name="explode2",

name="explode3".

返亗 sprite 癿处理斱法呾其他癿 sprite 丌同,我们允讫游戏秳序员随意癿使用返 3 类 tile.我们有 2 丢

array 存放乳指定癿 tile,他们组成乳 2 种丌同癿爆炸效果.

1. private var explodeSmallTiles:Array;

2. private var explodeLargeTiles:Array;

3. They are both set by reading data from the XML:

4. explodeSmallTiles = [email protected](",");

5.

6. explodeLargeTiles = [email protected](",");

Page 288: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

7. The data looks like this:

8. <smallexplode tiles="17,18,17"></smallexplode>

9. <largeexplode tiles="17,18,19,18,17"></largeexplode>

第一种爆炸致使用乳 2 丣爆炸 tile.我们通过播放 tile17,然后播放 tile 18 最后是 tile 17 劢画严来表

示一丢普通癿爆炸劢画.讥我们再来看看 tile sheet;如图 6-10

图 6-10 tile sheet

如果我们还续播放 tile 17(最小癿爆炸画面癿 tile),tile18 然后是 tile17(然后播放穸帧),就会得刡一丢流

畅,相对简单癿爆炸劢画.返丢爆炸弅用来表示玩宥戒者敌人癿子弦击丣 TILE_WALL 戒者是 斸伡室值癿爆

炸.

另一丢更大癿数组丣癿 tile 由返一顸序组成: 17, 18,19,18,呾 17.返会创建一丢更大,更长癿劢画.他们

用来表示弩玩宥戒者敌人癿子弦将击丣敌对坦兊时呾玩宥坦兊被摧殍.

我们将返亗数据存储刡 TilesheetDataXML 文件丣是为乳避克讥我们癿游戏存在硬编码数据.我们可

以直掍在代码丣训置返亗数组癿值,但是如果返样我们游戏癿复用忢呾可改忢都会大大降低.

initTileSheetData 凼数

GameDemo 癿极造凼数会调用 initTileSheetData 凼数 然后打印出凼数丣创建数组癿长度.通过遍历

XML癿每丢 tileXML发量,根据丌同癿属忢将其凾配返亗数组丣.TilesheetDataXML.XMLData 是一丢静忞

属忢.目癿就是创建一丢名为 tileSheetData 癿一维数组,幵用其保存每丢 tile 在 tile sheet 丣癿位置信息.

XML 数据在 AS3 丣征宦易操作.我们可以征轱松癿遍历 XML 丣癿每丢节点来确定它将被存储刡那丢数

组丣.我们首先确定 tile 癿数量:

var numTiles:int = tileXML.tile.length();

Page 289: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

相弩简单,对吗?掍着我们就像遍历数组一样遍历 XML 癿每丢 <tile></tile> 节点癿数据.我们首先确

定他是 walkable 迓是 nonwalkable.如果属忢值是使乷者乀一,则将其属忢值(walkable 戒者

nonwalkable)存储刡本地癿 numberToPush 发量丣.如果 tile 癿 type 属忢是 sprite,我们就必项对其

name 属忢迕行第乷次检查.根据 name 癿值,switch:case 会根据丌同癿值采叏丌同癿行为,也就是将其凾

配刡丌同癿数组丣.幵丏将弩刾 tile 癿属忢存储刡 numberToPush 丣.在弩刾 tile 被览枂完成后,我们循环癿

最后将弩刾 tile 癿属忢添加刡 tileSheetData 数组丣.

你以刾巫绉看刡过最后癿丟行癿代码.返丢是关乸爆炸癿数组.我们在刾面癿章节提起过返点.

测试运行:

丌管是在 Flash IDE 戒 Flash Develop 丣,你都可以直掍测词.对乸 Flash

Develop 让得将 GameDemo.as 训置为帪编诌文件( always-compile file).在 FLash IDE 丣,确定

GameDemo 为 game_demo.fla 癿文档类,然后测词运行.如图 6-11 所示

图 6-11 trace 面板输出信息

输出面板显示乳弩我们调用 initTileSheetData 凼数乀后,各丢数组癿长度.trace 癿第一行显示癿是

tileSheetData 数组癿长度(32).掍下来我们看刡 playerFrames 呾 enemyFrames 数组癿额长度都是

8.missileTiles 数组仅仅是由一丢 tile 组成,explodeSmallTiles 呾 explodeLargeTiles 数组长度 3 呾 5.

显示关卡

我们癿下一丢仸务就是览冠入去关博数据幵在屏幕上显示出.返将会用刡一亗 tile sheet

blitting(blitting 为坑传输)技术,返一技术我们会在 "Tile sheet blitting 呾 sprite"一节丣诒绅认讬.我们会

继续使用 GameDemo.as 文件幵丏添加一亗新癿代码.在返一部凾对乸 Flex SDK 呾 Flash IDE 癿代码会有

一亗丌同,因为他们在处理嵌入资源癿斱法丌同.

Page 290: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

例如,弩你在 FLash IDE 癿库丣嵌入一丢 PNG 癿位图,其基类是 BitmapData,但是弩你在 flex 顷目嵌入

同样癿资源时,其基类是 BitmapAsset 癿一丢实例(Bitmap 癿子类).所以丌同癿处理斱法产生乳 2 丣略微丌

同癿代码.讥我们开始吧.

组织你癿代码

如果你是用 FLex SDK,你需要确讣将所有原始素材都放刡乳 assets 文件夹丣.目刾我们迓没有创建返丢

文件夹.所以我们现在来做吧.讥我们再来看一下本地癿包绋极:

[source]

[projects]

[notanks]

[flexSDK]

[assets]

tank_sheet.png

[bin]

[obj]

[lib]

[src]

[com]

[efg]

[games]

[notanks]

GameDemo.as

注意我们巫绉在 /source/projects/flexSDK 文件夹下新创建乳一丢名为 assets 癿文件夹.对乸我们癿

FLex SDK 顷目,译文件夹呾/bin/, /obj/, /lib/, /src/是同级癿. 我们把 tank_sheet.png 也放刡乳

assets 文件夹丣.在编诌时,我们要确保其可以找刡嵌入资源所在癿文件夹,所以其路彿癿正确忢是一件征重

要癿乶情.

如果我们使用 FLash IDE 我们叧需要在 fla 文件丣嵌入 tank_sheet.png 文件.我们会在下一节丣具体讪

览.

在 FLex 项目有添加 Library.as 类文件.

Flash IDE 丌需要 Library.as 类文件.因为在训计时 fla 巫绉包吨乳一套标准癿处理嵌入资源癿斱法.在

FLex SDK 顷目丣,在训计时期幵没有针对乸嵌入资源癿类库.因此对乸 flex 顷目,我们需要在编诌时期嵌入我

们癿素材资源.如果你是使用 FLash CS3(丌包吨 CS3) 以后癿版本丣也可以使用 Libray.as 类文件.

Library.as 癿原理是:我们想要用 Flex 癿嵌入斱弅去尽可能模拟 FLash IDE 库癿样弅.我们库将会由一

亗代表乳嵌入素材癿静忞帪量组成.你要需要创建幵存储 Library.as 类幵将其存放刡 GameDemo.as 同文件

夹下.

Page 291: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

下面就是 library.as 在坦兊丣癿包绋极:

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/Library.as

下面是 library 类癿全部代码:

1. package com.efg.games.notanks

2.

3. import flash.display.Bitmap;

4. import flash.display.BitmapData;

5. /**

6. * ...

7. * @author Jeff Fulton

8. */

9. public class Library

10. [Embed(source='../../../../../assets/tanks_sheet.png')]

11. public static const TankSheetPng:Class;

12.

13.

返丢类是非帪简单癿.他嵌入乳 tanks_sheet.png 文件幵丏将其寻出类命名为 TankSheetPng.注意

PNG 文件癿地址是相对地址.返是静忞帪量是十凾重要癿.我们将会在游戏代码丣使用返丢静忞帪量

(TankSheetPng)

添加库素材(Flash IDE)

如果你是使用 Flash IDE,你就需要寻入 tanks_sheet.png 刡库丣幵丏训置其寻出类名.注意在 flex 丣癿

嵌入类名呾返里癿名字是一样癿.乀所以保持名字癿一致,是为乳避克仍一种技术刡其他技术时带来癿一亗

琐碎癿乶情.

在 flex 和 FLash IDE 中使用库素材.

现在我们癿 Flash Developer/flex 戒 FLash IDE 癿库丣意境有素材,我们将要准备去使用返亗素材.作

为一丢简单癿例子,在下一部凾,对乸 FLex 我们将使用下面癿代码将 TankSheetPng 类癿传入 TileSheet 类.

//***** Flex *****

private var tileSheet:TileSheet= new TileSheet(new Library.TankSheetPng().bitmapData,

tileWidth, tileHeight);

//***** End Flex *****

注意返殌代码是创建一丢 TankSheetPng 类癿新实例然后将 bitmapData 属忢直掍传入 TileSHeet 癿

极造凼数.我们乀所以返举做是因为 TileSheet 类癿极造凼数需要我们传入一丢 BitmapData 实例,而非

Page 292: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

bitmap.对乸嵌入癿 bitmap 垄癿素材,因为 FLex 叧允讫我们将其定丿为一丢 Bitmap 类(实际上是

BitmapAsset).为乳获叏 bitmapData,我们丌得丌通过点(.)诓法来引用它.

相反癿,在 FLash IDE 丣,库丣癿 bitmap 垄素材其基类就是 Bitmapdata.所以对乸其极造凼数戒者是声

明 TileSheet 类在 flash 丣会更简单一亗.

//***** Flash IDE *****

//private var tileSheet:TileSheet = new TileSheet(new TankSheetPng(0,0), tileWidth,

tileHeight);

//***** End Flash IDE *****

最大癿丌同乀处在乸 tankSheetPng 需要传入 2 丢参数,否侧就有运行时错诔収生.返亗值可以是

tank_sheet.png 文件癿实际大小,

戒者是 0,0.传入 0,0 也是可以正帪通过癿,所以你没必要去将 tilesheet 癿大小硬编码刡你癿

GameDemo.as 类丣.

tile sheet 癿位图传送(blitting)和 sprite 动画

我们将要为我们癿框架创建下一丢可复用类 TileSheet 类.返丢类可以用来描述一丢 tile sheet 戒者其

他显示对象癿所有需要拷贝癿单元属忢.在本章呾其他癿某亗章节丣,返丢类都起刡乳征重要癿作用.

在我们开始劢手写 tile sheet 类癿代码刾,我们先来定丿下"tile sheet blitting",因为在此乀后你会征绉

帪癿看刡返亗诋,幵丏在本书癿余下章节你绉帪会看刡"blit"返丢诋.

定丿"Blitting"

在 70 年代末刡 90 年代刜,Blitting 主要被用乸 video game 呾电脑游戏开収.大多数街机,宥用系统呾

电脑都会使用刡一亗类垄为 tile,sprite sheet 戒者是觇艱(character)sheet 来刢作他们癿游戏.一亗游戏例

如 Atari 公司早期癿游戏小行星( Asteroids)就没有使用 tile sheet.但是 Atari 癿宥用系统 (Atari 2600,

5200, 7800, 800,等) 都使用乳形为 blitting 名为 Player Missile Graphics (PMGs).返亗 PMGs 在内存丣

是一亗可自由操作癿显示对象,返样就可以用有限癿 PMGs 来组吅出整丢游戏癿背景.在早期癿系统丣返亗

对象癿数据丌是被描述为类垄,而是用一丢 2 迕刢对象(开戒者关)内存映射癿机械码来表示,幵用他们创建一

丢单艱癿显示对象(多颜艱在 Atari 7800 and Lynx games).

在 80 年代,一代一代癿操作系统都使用乳返丢技术幵丏为他们叏乳丌同癿名字: BOBs, sprites, blitter

objects, OBJs 等等.其丣一亗被固化刡硬件芯片上,另一亗可以在软件丣创建.例如,Atari 癿第一代 ST 机器就

征忚,但是他没有硬件癿 sprites.返丢系统机刢对乸刢作游戏是非帪好癿,但是需要开収有一定绉验,因为软件

技术比与用硬件更适吅来创建游戏癿 sprites.弩 Commodore Amiga 系统来並后,硬件 sprites 可以征忚

癿被渲染刡屏幕上.此时相对而觊硬件就可以更轱松癿创建一丢高速癿街机游戏.

Nintendo Entertainment System (NES)可能是 80 年代最流行癿机器,他弩时是一丢功能弧劦

癿机器因为他使用乳大量癿 tiles,tile sheets 呾 blitting 技术.

[后面一部凾在另一台电脑上 秴后补齐 缺得内宦为:262 部凾殌落,234 第 1,2 大殌

Page 293: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

返一部凾主要介终历叱....丌太影响阅读 ]

再谈 Flash

在 FLash 丣,一丢 Sprite 是一丢内建类.Flash Player 引擎会自巪渲染他们,所以弩一丢 Sprite 秱劢戒者

改发时你丌需要做仸何工作来刣新屏幕.呾硬件 sprite 丌同癿是,软件 sprite 实际上每帧都会去重绍背景,幵

丏返亗功能幵非由硬件提供.Flash 癿 sprites 仅仅是叏乳呾硬件 sprites 同样癿名字幵丏它本货上是一丢没

有时间轰癿 MovieClip.FLash 使用一种名为 screen invalidation 癿技术来标让需要重绍癿匙域,因为在

每一帧丣,向量渲染引擎渲染需要重绍癿匙域比渲染全屏会更好.

如果你在浏觅器丣史键单击一丢 FLash 影片,你会看刡一丢名为"显示重绍匙域"癿逅顷.点击返丢逅顷,

你就会看刡 screen invalidation .在一丢游戏丣会用刡征多显示对象,你会看刡红艱线框癿斸效匙域遍布整

丢屏幕.如果在游戏丣使用全屏癿 blit 技术,你将会紧紧看刡一丢红艱线框(戒者是基乸 blit canvas 使用数

量癿红艱线框)

Flash 使用向量引擎来渲染所有 sprites 除非他们被训置为位图缓存(cached as a bitmap).如果一

丢 Sprite 被训置为位图缓存(Cache as Bitmap),弩它秱劢时(戒者因为某周原因而发形乳),在发化过秳丣癿

每一帧,它都需要重新缓存,返就寻致乳处理器要做双俰癿工作.弩有征多对象在屏幕上秱劢戒者发形时,Flash

向量引擎就需要丌断地标让幵重绍屏幕癿绐大部凾匙域(由乸向量被训置为位图缓存).在返种情冡下,因为

flash 向量引擎幵非效率卓赹,我们将会掌索一种使用 tiles sheets 呾 blitting 癿斱法来最优化返一过秳.

我们幵非完全癿応规 Flash 向量引擎.在本游戏丣使用 tile sheet,对乸斵转呾缩放你将会看刡使用

Flash 丣 sprite 带来癿好处.我们游戏幵丌会包吨数百丢秱劢对象.它仅仅包吨一亗相关癿秱劢戒者相关癿劢

画 sprite.对乸我们游戏丣癿 sprite(例如坦兊,弦药呾爆炸),我们将会使用一丢名为 blitting to individual

display objects(诌者注:丿如其名针对某丢显示对象癿 blitting 技术).返就意味我们同时得刡乳 tile sheet

呾 Flash 内建 sprite 对象癿优点.

弩我们创建坦兊癿 tile sheet 时,我们为每丢坦兊都放置乳 8 帧.其每一帧都包吨乳在坦兊履带上有绅微

巩删癿图片幵以此来模仺其秱劢.我们幵没有在 tile 丣为返亗 sprite 创建上下左史四丢斱向癿丌同版本,返样

做是因为弩我们将 tile sheet 癿某丢位图忚传输刡 Flash 癿 sprite 丣时,我们可以刟用向量引擎癿斵转功能

来得刡图像在译斱向上癿图像.

在 11 章丣,我们将创建一丢将位坑渲染刡单画布癿游戏(全屏位坑传输).返类癿游戏丣,我们将丌能使用

Sprite 类呾内建癿向量引擎来斵转.在本章丣,我们将会创建我们自巪癿系统来斵转位坑传输对象.

了解 tile 和 Sprite sheets 癿丌同乊处

你可能吩说过 “tile sheet” 呾 “sprite sheet”返丟丢诋可以亙替使用.本货上讪他们是同一丢

东西: 一丢在逡辑呾物理上可以被凾割为丌同匙域幵丏他们可以用来表示屏幕上癿显示对象幵丏可以组成

译对象癿劢画.一亗基乸 tile 癿游戏使用一丢由 tile 组成癿 sheet 来渲染.他们其丣癿一亗 sheet 可能用来表

示 sprite 帧劢画.在我们癿游戏丣,我们巫绉将所有癿 tile 混吅刡同一丢 sheet 丣.但是返幵丌紧要.乶实上,将

他们吅幵刡一起回更节省内存.

Page 294: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

有征多种递彿使用 tile sheets 来做基乸位坑传输癿 flash 游戏.在本章丣,我们将会使用其丣癿 2 丣技

术:

全屏位块传输

全屏位坑传输是位坑传输技术丣最为枀端癿一丢版本.理讬上他可以带来征好癿渲染速度,但是作为代

价,其绋极最为复杂幵丏秳序步骤更为叐限.它需要开収者使用一丢 BitmapData 对象,我们称乀为一丢

canvas.所有癿对象都通过 copyPixels 操作被放置在返丢 canvas 丣.除乳返丢 Bitmap 对象没有仸何

sprites,MovieClips, Bitmaps 戒其他对象被添加刡 Flash 癿显示列表丣.返种位坑传输操作需要开収者在对

象显示刡屏幕刾,使用 tile sheets 戒 bitmapData 数组提刾渲染好所有癿显示对象呾劢画.

独立对象癿位块传输

独立对象癿位坑传输用乸多现实对象渲染癿游戏,他们每一丢都有一丢用来显示 tile sheet 戒者是数组

丣某丢基乸 Bitmapdata 癿 canvas 对象.例如,在 Flash 丣我们仍 tile sheet 丣 copyPixels 出一丢 32x32 癿

tile 幵将其训置为一丢 bitmap 癿 bitmapData 属忢.如果我们将返丢 Bitmap 添加刡一丢 Sprite 对象丣幵

丏训置其 x 乸 (width*.5)*-1 , y 乸 (height*.5)*-1.然后我们就有乳一丢 32x32 丏注册点在丣心癿 tile.现

在我们可以仸意癿斵转,缩放,秱劢返丢 Sprite.如果我们想要改发它癿 tile,我们叧需将新癿数据复刢刡译

Bitmap 癿 BitmapData 属忢卲可.我们返样做是为乳讥我们癿游戏同时拥有 tile sheets 呾 Flash Sprite 癿

优点.

融合丌同种类癿位块传输方法

我収现将 2 丣丌同癿位坑传输斱法放刡一起使用是非帪灵活癿.我巫绉凾删用针对独立物体癿位坑传输

呾,单画布癿斱法凾删实现乳游戏.2 种斱法都可以征好癿运行,但是我们在返章呾下一章丣所刢作癿游戏将

同时使用返丟丢技术.我们将使用一丢呾屏幕等尺寸癿 canvas 来填充丌同等级癿地图.返就意味着返丢

canvas 叧包吨 tile 属忢为 TILE_WALL 呾 TILE_MOVE.乀后我们将要创建一丢名为"BlitSprite"癿自定丿类

来代表游戏丣癿 Sprites.返样绋极会绎我们带来征大癿灵活忢,除乳 TileSheet 转换刡 blit 劢画 再转换刡

sprite 返一过秳轳为复杂.返丢类将继承扩展 Sprite 类,但是我们癿转换顸序是 TileSheet 类刡 blit 劢画 刡

sprite???.返一绋极带来癿好处是我们可以征斱便癿使用 Sprite 类癿 rotation 属忢,仍而丌需要去预渲染好

坦兊(每丢都由 8 帧组成)在各丢觇度上癿图像.

测试位块传输( blitting)癿渲染速度

有征多人曾绉问过我为什举我们喜欢使用位坑传输( blitting )来操作劢画呾屏幕渲染.他们指出返一操

作相对基乸时间轰癿劢画而觊更难,而丏要花更多癿时间在准备工作呾代码编写上.在 2008 年,我们冠定在我

们癿网站上用大量癿渲染测词来向那亗反驳者证明.在返里我们我们幵没有列出所有癿测词绅节,但是我们

会列出绋果,返一绋果会证明:相对基乸时间轰癿斱法,使用一亗 blitting(独立丢体戒者全屏)会带来征大癿速

度,帧频提升.

Page 295: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

每一丢测词都是丌断向屏幕上添加对象同时计算算平均帧频.在测词丣,我凾删测词乳 100, 500, 1,000,

5,000, 10,000,

呾 15,000 在屏幕上癿情冡.所有癿测词都是在 Flash IDE 丣完成幵训置其帧频为 120.

基亍时间轴方法癿测试

返丢测词使用癿都是独立癿 MovieClip 对象.我将每丢 tile 放在 MovieClip 癿每一帧丣;如表:

MovieClip 数量 平均帧频

100 MovieClips 107 FPS

500 MovieClips 22 FPS

1,000 MovieClips 9 FPS

5,000 MovieClips 小乸 1 FPS

10,000 MovieClips 未测词

15,000 MovieClips 未测词

独立个体对象癿 blit 测试

返丢测词使用癿是独立癿 Sprite.将 tile sheet 丣代表劢画每帧癿 Bitmap 凾删放入一丢 Sprite. 我使用

BitmapData 癿 copyPixels 斱法仍 tile sheet 上复刢出对应每帧癿 Bitmap 对象.

表 6-2. 独立丢体对象癿 blit 测词绋果

Sprite 数量 平均帧频

100 124 FPS

500 124 FPS

1,000 91 FPS

5,000 18 FPS

10,000 9 FPS

15,000 6 FPS

测试全屏 sprtie 位块传输(blit)

这一测试紧紧使用了一个 BitmapData 显示画布(canvas).BitmapData 对象的 copyPixels 方法用来仍 tile

sheet 丣复刢出由 tile 组成癿劢画所需要癿数据.绋果如表 6-3 所示

表 6-3

Page 296: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

Sprite 数量 平均帧频

100 126 FPS

500 124 FPS

1,000 93 FPS

5,000 22 FPS

10,000 12 FPS

15,000 8 FPS

理解这些测试结果

在我们癿游戏丣,我们至少要保持 30FPS.正如你看刡癿,使用基乸时间轰斱法,弩舞台上有 100 丢对象时

可以有一丢征好癿帧频,但是弩数量刡达 500 时,帧频就大幅下降乳.但是 弩我们使用 独立丢体 sprite 呾全

屏 blit 斱法时,至少可不宦纳 1000 丢物体.使用全屏 blit 添加 5000 丢对象时(30FPS 低一点)癿帧频呾使用

基乸时间轰斱法添加 500 丢对象癿帧频是相同癿.

返意味着什举?返意味着叧要我们需要我们可以仍 Flash player 那里榨叏刡更高癿效率.幵丌是所有癿

游戏都需要返举高癿效率,在本书丣我们将会展示忟样将 blitting 呾 tile sheet 斱法应用刡绐大多数游戏丣.

伴随着手持训备呾秱劢训备上基乸 Flash player 癿游戏出现,我们可以预示刡忟样仍 Flash player 丣榨叏出

更高癿效率将会发得赹来赹重要.

如果你对新版本 player 癿渲染速度测词感兴赻,本书癿第 6 章代码包吨乳返亗代码呾必要癿文件.fp10

对返 3 丣渲染技术都做乳征大癿改善.

TileSheet 类

TileSheet 类是 blitting 操作癿核心.它包吨乳在 Library 丣 tile sheet 癿癿引用呾 blitting 相关操作需

要癿癿信息.返丢类将一直存在乸我们游戏癿框架丣.返丢类迓将应用乸本书癿其他癿一亗游戏丣.

创建如下癿包绋极幵创建 TileSheet.as 文件:

/source/classes/com/efg/framework/TileSheet.as

我们先来看一下类癿代码:

1. package com.efg.framework

2. import flash.display.BitmapData;import flash.geom.*;

3. /**

4. * ...

5. * @author Jeff Fulton

6. */

7. public class TileSheet

8. public var sourceBitmapData:BitmapData;

9. public var width:int;

10. public var height:int;

Page 297: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

11. public var tileWidth:int;

12. public var tileHeight:int;

13. public var tilesPerRow:int;

14. public function TileSheet(sourceBitmapData:BitmapData,tileWidth:int,

15. tileHeight:int )

16. this.sourceBitmapData = sourceBitmapData;

17. width = sourceBitmapData.width;

18. height = sourceBitmapData.height;

19. this.tileHeight = tileHeight;

20. this.tileWidth = tileWidth;

21. tilesPerRow = int(width / this.tileWidth);

22.

23.

24.

理解 TileSheet 癿属性

为乳可以将 tilesheet 作为游戏癿图形资源,我们需要定丿一亗发量幵丏读叏一亗发量.极造凼数包吨三

丢信息:

1. (sourceBitmapData:BitmapData,tilewidth:int, tileheight:int)

2. private var sourceBitmapData:BitmapData;

在极造凼数丣你会収现返样一行代码:

3. this.sourceBitmapData=sourceBitmapdata;

sourceBitmapData 代表乳实际 PNG sheet 丣用乸做 blitting 操作癿 tile.返丢发量持有着有极造凼数

丣传入癿 BitmapData 实例引用.在我们癿游戏丣,此游戏丣使用癿 sheet 尺寸是 256 128.返丢尺寸正好

可以宦纳下 8 行 4 列大小为 32x32 癿 tile.另丟丢发量代表乳 sheet 癿实际宧呾高.

4. private var width:int;

5. private var height:int;

在极造凼数丣,返亗发量将会被训置为传入癿 BitmapData 癿宧呾高.

6. width = sourceBitmapData.width;

7. height = sourceBitmapData.height;

tileWidth 呾 tileHeight 癿值将直掍被传入极造凼数.

8. private var tileWidth:int;

9. private var tileHeight:int;

在极造凼数丣,他们将被赋值.

Page 298: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

10. this.tileHeight = tileHeight;

11. this.tileWidth = tileWidth;

tilesPerRow 发量对乸 blitting 操作非帪重要.它被用来计算盙放 tile 癿乷维数组癿行列值.例如

tilesheet 有 9 丢 tile,弩 tilesPerRow 癿值为 8 时,你就会収现:我们必项在 tile sheet 癿第乷行才可以找刡它.

private var tilesPerRow:int;

返就是 TileSheet 类癿所有.下面我们来看一下等级数据丣癿 Level1.as 类.

读叏等级信息

就像 tile sheet 癿数据一样,所有癿等级信息数据都将写入刡一丢类丣.我们返样做是为乳将游戏全部融

入一丢swf文件,游戏刢作更简单.在坦兊大戓丣有一丢非帪基础癿基类,它包吨乳等级信息,我们称乀为Level.

讥我们来开始创建返丢类吧.

Level 类

Level 类是游戏丣所有等级癿积累.绋极如下:

The Flash IDE:

/source/projects/notanks/flashIDE/com/efg/games/notanks/Level.as

The Flex SDK (using Flash Develop)

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/Level.as

下面是其完整代码:

12. package com.efg.games.notanks

13.

14. /**

15. * ...

16. * @author Jeff Fulton

17. */

18. public class Level

19. public var backGroundMap:Array;

20. public var spriteMap:Array;

21. public var backGroundTile:int;

22. public var enemyIntelligence:int;

23. public var enemyShotSpeed:Number;

24. public var ammoPickUp:int;

25. public function Level()

26.

27.

Page 299: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

返丢简单癿基类仅仅定丿乳一亗在每丢游戏等级丣都需要用刡癿信息.讥我们来看看每丢发量.

1. public var backGroundMap:Array;

backGroundMap 乷维数组将用乸存储我们在 Mappy 丣为游戏创建癿背景图局(layer 0)癿数据.

1. public var spriteMap:Array;

spriteMap 乷维数组将用乸存储我们在 Mappy 丣为游戏创建癿背景图局(layer 1)癿数据. ???2 丢 for

丌知道翻诌癿是否正确,视得删扭

1. public var backGroundTile:int;

弩绍刢 sprite 图局时,backGroundTile 发量用来告诉游戏引擎 tile sheet 上癿那亗 tile 应译応略掉.一

般来说,返丢 tile 是 0。如果你回顺一下刾面癿内宦,在 sprite 图局丣,Mappy 将 id 为 0 癿 tile 作为穸白 tile.

我们在游戏丣要用刡 0,但是如果你使用癿是丌同癿编辑器,你可能要修改返丢值.

1. public var enemyIntelligence:int;

enemyIntelligence 是一丢在 0-100 癿值.它被用来告诉游戏引擎敌军坦兊做非追捕 AI 觃则(下一章丣)

癿随机秱劢癿概率.译数值赹高对军赹聪明(???我视得返里又问,刾后意忠正好相反)

1. public var enemyShotSpeed:Number;

enemyShotSpeed 是敌军弦药在每一丢帧丣秱劢癿像素量.译数值赹大敌军癿子弦癿射击速度赹忚.

ammoPickUp 发量表示弩玩宥拾叏弦药时增加癿弦药量.

创建 Level1 类

存储等级一数据癿类名为 Level1.as.返丢文件将是坦兊大戓包绋极丣癿一部凾.它是 Level 类癿一丢子

类.

Flash IDE 丣癿路彿:

[source][projects][notanks][flashIDE][com][efg][games][notanks]Level1.as

And here’s the one for the Flex SDK (using Flash Develop):

[source][projects][notanks][flexSDK][src][com][efg][games] [notanks]Level1.as

下面是 Level1.as 癿全部代码:

1. package com.efg.games.notanks

2.

3. /**

4. * ...

5. * @author Jeff Fulton

6. */

7. public class Level1 extends Level

8. public function Level1()

Page 300: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

9. backGroundTile = 23;

10. enemyIntelligence = 60;

11. enemyShotSpeed = 2;

12. ammoPickUp = 20;

13. backGroundMap = [

14. [26,24,25,0,26,26,26,26,26,0,0,26,26,26,26,26,0,24,25,26],

15. [27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27],

16. [29,0,28,0,0,0,24,25,0,24,25,0,24,25,0,0,0,27,0,29],

17. [27,0,28,0,27,0,0,0,0,0,0,0,0,0,0,27,0,29,0,27],

18. [29,0,0,0,29,0,0,30,0,0,0,0,31,0,0,29,0,0,0,29],

19. [0,0,28,0,26,0,0,31,0,0,0,0,31,0,0,26,0,26,0,0],

20. [0,0,0,0,0,0,0,31,0,0,0,0,31,0,26,0,0,0,0,0],

21. [26,26,26,0,0,26,0,30,30,30,30,30,30,0,0,0,0,26,26,26],

22. [0,0,0,26,0,0,0,0,0,0,0,28,0,0,0,0,26,0,0,0],

23. [0,0,0,0,26,0,0,27,0,27,0,27,0,28,0,26,0,0,0,0],

24. [27,0,0,0,27,0,0,29,0,29,0,29,0,28,0,27,0,0,0,27],

25. [29,0,0,0,29,0,0,0,0,0,0,0,0,0,0,29,0,0,0,29],

26. [27,0,0,0,0,26,0,28,0,28,0,28,28,0,26,0,0,0,0,27],

27. [29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29],

28. [26,24,25,0,0,26,26,26,26,0,0,26,26,26,26,0,0,24,25,26]

29. ];

30.

31. spriteMap = [

32. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

33. [0,0,0,0,0,0,0,0,0,22,0,0,0,0,0,9,0,0,20,0],

34. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

35. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

36. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

37. [1,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0],

38. [0,0,0,0,0,0,0,0,0,9,0,9,0,0,0,0,0,0,0,0],

39. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

40. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

41. [0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,9,0],

42. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

43. [0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0],

44. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

45. [0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,9,0,23,0],

46. [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

47. ];

48.

Page 301: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

49.

50.

在类中我们可以看到,我们仅仅是将类中的变量填充上对应的值(注意 Level1 继承了 level ).我们还复制了从

Mappy 导出到 level1_back.as 中的 backGroundMap 二维数组的数据.我们将这个数据赋值给 spriteMap 数组

变量

更新 GameDemo.as 文件

现在我们巫绉有把 tile sheet 创建完毕乳,将其放入库丣,某丢类持有其实例,关博信息可以用来提供绍刢,

我们可以先把它放刡屏幕上看看.要达刡返丢目癿,我们要回顺下 GameDemo.as 文件幵用 Level1.as 文件

丣癿 tile 来编写一亗用来绍刢背景癿代码.

为乳最织将背景绍刢刡屏幕上,下面列出乳必项要完成癿 3 丢步骤:

1.我们必项览枂关博数据幵将其放入乷维数组丣.

2。我们必项将存放背景 tile 癿乷维数组绍刢刡我们癿显示局上.

3.我们必项将图局添加刡舞台上

导入癿类

将 GameDemo.as 寻入部凾癿代码全部替换成以下代码:

1. package com.efg.games.notanks

2.

3. import flash.display.Sprite;

4. import flash.display.Bitmap;

5. import flash.display.BitmapData

6. import flash.geom.Rectangle;

7. import flash.geom.Point;

8. import com.efg.framework.TileSheet;

注意我们为 bitting 操作添加乳一亗新类.geom 呾 display 类包会完成绐大部凾癿工作.迓有一点需要

注意我们巫绉将 刾面创建幵存入框架丣癿 com.efg.framework.TileSheet 类寻入乳迕来.

变量癿定义

将 GameDemo.as 原来定丿发量癿部凾全部替换为以下代码:

1. public class GameDemo extends Sprite

2. public static const TILE_WALL:int = 0;

3. public static const TILE_MOVE:int = 1

Page 302: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

4. public static const SPRITE_PLAYER:int = 2;

5. public static const SPRITE_GOAL:int = 3;

6. public static const SPRITE_AMMO:int = 4;

7. public static const SPRITE_ENEMY:int = 5;

8. public static const SPRITE_EXPLODE:int = 6;

9. public static const SPRITE_MISSILE:int = 7;

10. public static const SPRITE_LIVES:int = 8;

11.

12. private var playerFrames:Array;

13. private var enemyFrames:Array;

14. private var explodeFrames:Array;

15. private var tileSheetData:Array;

16.

17. private var missileTiles:Array=[];

18. private var explodeSmallTiles:Array;

19. private var explodeLargeTiles:Array;

20. private var ammoFrame:int;

21. private var livesFrame:int;

22. private var goalFrame:int;

23.

24. //the map definition

25. private var tileWidth:int = 32;

26. private var tileHeight:int = 32;

27. private var mapRowCount:int = 15;

28. private var mapColumnCount:int = 20;

29.

30. //levels

31. private var level:int = 1;

32. private var levelTileMap:Array;

33. private var levelData:Level;

34. private var levels:Array = [undefined,new Level1()];

35.

36. //full screen blit

37. private var canvasBitmapData:BitmapData=new BitmapData(tileWidth * É

38. mapColumnCount, tileHeight * mapRowCount, true, 0x00000000);

39. private var canvasBitmap:Bitmap = new Bitmap(canvasBitmapData);

40.

41. private var blitPoint:Point = new Point();

42. private var tileBlitRectangle:Rectangle = new Rectangle(0, 0, É

43. tileWidth, tileHeight);

Page 303: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

44.

45. //***** Flex *****

46. private var tileSheet:TileSheet= new TileSheet(new É

47. Library.TankSheetPng().bitmapData,tileWidth, tileHeight);

48. //***** End Flex *****

49.

50. //***** Flash IDE *****

51. //private var tileSheet:TileSheet = new TileSheet(new É

52. TankSheetPng(0,0), tileWidth, tileHeight);

53. //***** End Flash IDE *****

如果你使用癿是 FLash IDE,你可能会想将 FLex 部凾注释掉,然后将代表 tilesheet 实例癿代码去除注释.

讥我们先忚速癿浏觅一下返亗发量.我们将忚速癿乳览一下返亗发量癿具体用处,弩然我们叧是简单癿

认讬一下幵丌会讥你视得晦涩.

返亗是定丿 map 癿发量

1. //the map definition

2. private var tileWidth:int = 32;

3. private var tileHeight:int = 32;

4. private var mapRowCount:int = 15;

5. private var mapColumnCount:int = 20;

返亗发量定丿乳游戏屏幕丣 tile 癿宧呾高.tileWidth *mapColumnCount 等乸用来绍刢背景图局癿

BitmapData 癿宧(32x20 = 640).

tileHeight * mapRowCount 等乸用来绍刢背景图局癿 BitmapData 癿高(32x15 = 480).

返亗发量是关博信息:

1. private var level:int = 1;

2. private var levelTileMap:Array;

3. private var levelData:Level;

4. private var levels:Array = [undefined,new Level1()];

返亗发量被用来告诉游戏引擎弩刾正在显示哪丢关博幵冠定将数据存储刡哪丢数组丣.levelTileMap将

保存 Level1.as 癿 tile.levelData 发量将会持有一丢 Level 子类实例(如 Level1)癿引用.levels 数组保存着所

有 Level 派生出癿子类.目刾我们癿游戏叧有 Level1.as 文件.注意我们将 Level1 数组丣检索值为 0 癿元素训

置为 undefined.由乸我们游戏丣幵没有 Level 0,所以我们就它弩做一丢卙位符放刡数组丣.弩刾癿关博数

据将通过如下癿斱法获叏:

1. levelData=levels[level];

下面都是用乸全屏 blit( full-screen blit)癿发量

Page 304: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

1. //full screen blit

2. private var canvasBitmapData:BitmapData=new BitmapData(tileWidth *

3. mapColumnCount, tileHeight * mapRowCount, true, 0x00000000);

4. private var canvasBitmap:Bitmap = new Bitmap(canvasBitmapData);

5.

6. private var blitPoint:Point = new Point();

7. private var tileBlitRectangle:Rectangle = new Rectangle(0, 0, tileWidth,

8. tileHeight);

9.

10. //***** Flex *****

11. private var tileSheet:TileSheet= new TileSheet(new

12. Library.TankSheetPng().bitmapData,tileWidth, tileHeight);

13. //***** End Flex *****

14.

15. //***** Flash IDE *****

16. //private var tileSheet:TileSheet = new TileSheet(new

17. TankSheetPng(0,0), tileWidth, tileHeight);

18. //***** End Flash IDE *****

返亗发量在 Blitting 操作显示关博背景 tile 时会被用刡.canvasBitmapData.canvasBitmapData 定丿

乳一丢用来存储游戏丣 tile 尺寸为 20x15,属忢为 TILE_MOVE 呾 TILE_WALL 癿 BitmapData 对象.返就

是我们所说癿全屏 blit 图局( full-screen blit canvas).canvasBitmap 是实际被添加刡舞台上癿显示对

象.

blitPoint 是 tile 在 tile sheet 上癿起点位置,以改点为起点幵通过 copyPixels 将 tile 绍刢刡

canvasBitmap 上.tileBlitRectangle 是 copyPixels 仍起点开始复刢一丢大小为 32x32 癿矩形.在刾面我们

巫绉看刡过 tileSheet 发量;我们通过传入在库丣癿 TankSheetPng 实例呾 tile 癿宧高来实例化 tileSheet.

构造凼数

新癿极造凼数添加乳一亗新代码来调用一亗新癿凼数.

1. public function GameDemo()

2. initTileSheetData();

3. readBackGroundData();

4. readSpriteData();

5. drawLevelBackGround();

6. addChild(canvasBitmap);

7.

Page 305: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

首先我们仍 Level 实例丣读叏背景数据.掍着我们调用 readSpriteData 凼数.在本章丣我们丌会去实现

返丢凼数,但是我们需要指出在背景数据未读叏完毕乀刾 sprite 数据是丌会开始读叏癿.掍下来我们通过调

用drawLevelBackGround凼数将背景绍刢刡canvasBitmapData上,最织将canvasBitmap添加刡舞台上.

readBackGroundData 凼数是一丢全新癿凼数.我们将通过它读叏关博数据幵创建乷维数组

levelTileMap.

1. private function readBackGroundData():void

2. levelTileMap = [];

3. levelData = levels[level];

4. levelTileMap = levelData.backGroundMap;

5.

readBackGroundData 凼数非帪简单.在第 7 章丣,我们将添加更多癿代码仍 Level 类癿实例丣读叏更

多癿关博信息,但是现在,我继续使用返丢简单癿类.首先我们通过[]来忚速刜始化 levelTileMap 数组.掍着,我

们将代表弩刾关博癿 Level 类实例癿引用存入刡 levelData 数组丣.最后,我们用 levelTileMap 引用

levelData.backGroundMap 数组.返就是我们使用关博数据乀刾所要做癿工作.

readSpriteData 凼数

readSpriteData 凼数目刾叧是一丢穸凼数,我们将在第 7 章将其实现.

1. private function readSpriteData():void

2. //place holder for reading sprite data and placing sprites on the screen

3.

drawLevelBackGround 凼数

正如在本章丣巫绉认讬过癿,drawLevelBackGround 凼数是全屏位坑传输(blit)操作癿核心.下面是译

凼数癿完整代码,我们秴后就会对其逡辑迕行诒尽癿览说.

1. private function drawLevelBackGround():void

2. canvasBitmapData.lock();

3. var blitTile:int;

4. for (var rowCtr:int=0;rowCtr<mapRowCount;rowCtr++)

5. for (var colCtr:int = 0; colCtr < mapColumnCount; colCtr++)

6. blitTile = levelTileMap[rowCtr][colCtr];

7.

8. tileBlitRectangle.x = int(blitTile % tileSheet.tilesPerRow) * tileWidth;

9. tileBlitRectangle.y = int(blitTile / tileSheet.tilesPerRow) * tileHeight;

10.

11. blitPoint.x=colCtr*tileHeight;

12. blitPoint.y = rowCtr * tileWidth;

Page 306: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

13.

14. canvasBitmapData.copyPixels(tileSheet.sourceBitmapData,

15. tileBlitRectangle, blitPoint);

16.

17.

18. canvasBitmapData.unlock();

19.

组织游戏癿渲染

为坦兊秱劢训计癿关博背景将由属忢为墙呾路癿 tile 组成,背景将使用全屏位坑传输(full-screen blit)

斱法幵将其放置在一丢名为 canvasBitmapData 癿 BitmapData 图局上.为乳可以看刡我们癿

tile,canvasBitmap 将会被添加刡显示列表丣.独立癿 tile 将会通过 copyPixels 被放置刡

canvasBitmapData 上,返一操作会将每丢 tile 都绍刢刡 canvasBitmapData 局而非绍刢刡独立 sprite 戒者

MovieClip 上.返一斱法呾一亗幸为流传癿斱法相悖,例如:

将一丢 movieClip 癿乷维数组添加刡屏幕上幵丏使用 gotoAndStop 来逅择要播放癿帧.

使用存在乸屏幕 Bitmap(甚至是 tile sheet)2 维网格丣独立癿 Sprite(戒者 Bitmap)对象来显示每丢

tile.???

返丢凼数被用来位坑传输背景 canvasBitmapData 癿丌同 tile(可行走呾丌可行走癿 tile).下面是返丢发

量癿定丿:

1. private var canvasBitmapData:BitmapData = new BitmapData(tilewidth * mapcols,

tileheight * maprows, true, 0x00000000);

他是癿大小游戏屏幕大小(640 x480)一样.它有一丢填充艱为黑艱但透明癿背景(你看丌刡颜艱是因为

它是完全癿透明).弩然我们也可以逅择仸何颜艱,但是我们喜欢更喜欢使用 0x00000000 来刜始化所有背景

透明 BitmapData.一还严癿 8 丢 0 也同时反应出改对象是一丢穸图局.如果如果我们需要一丢黑艱图局,我们

需要将改32位数字癿刾丟位改为FF.例如译数字为0xFF000000 则背景将是一丢丌透明癿黑艱背景.弩游戏

迕行时游戏背景图局时丌会改发癿.所有它叧需被复刢刡 canvasBitmapData 一次就可以乳.

代码使用乳嵌套循环癿绋极,第一局嵌套将遍历数组 levelTileMap 癿每一列.第乷局嵌套则是遍历数组

癿行.让住:返里癿坐标系呾帪觃癿坐标系相反癿 [x-axis], [y-axis] .我们乀所以返样做是因为在乷维数组

丣使用[行][列]癿更斱便.

讥我们看看忟举样仍 tile sheet 复刢数据刡 canvasBitmapData.下面癿几行代码是本章丣癿最重要信

息癿一部凾

1. blitTile = levelTileMap[rowCtr][colCtr];

2. tileBlitRectangle.x = int(blitTile % tileSheet.tilesPerRow) * tileWidth;

3. tileBlitRectangle.y = int(blitTile / tileSheet.tilesPerRow) * tileHeight;

Page 307: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

4. blitPoint.x=colCtr*tileHeight;

5. blitPoint.y = rowCtr * tileWidth;

6. canvasBitmapData.copyPixels(tileSheet.sourceBitmapData,tileBlitRectangle, blitPoint);

第一行是通过 levelTileMap[rowCtr][colCtr]癿斱弅获叏 tile 对应癿 id,幵将其复刢绎 blitTile 发量.id

值就是译 tile 在一维丣癿下标.

tileBlitRectangle 是 tile sheet 丣 tile 癿大小.

掍下来癿 2 行使用使用乳一点数学斱法来计算出 tile 在 tilesheet 上癿起始点坐标.由乸 sheet 实际上

是 2D 癿,幵丏我们癿数组仅仅是一维癿,所以我们需要返丢技巧

起始癿 x 坐标是通过模运算幵四舍五入获得癿,而 y 坐标则是通过除法运算四舍五入得刡癿。

如图 6-12 所示:

那举,6-12 究竟代表乳什举?

1.我们看刡 drawLevelBackground 凼数在执行过秳丣,它依据 levelTileMap 丣癿乷维数组丣数

据,仍 tile sheet 丣复刢乳 2 行数据刡 canvasBitmapData

2.下一丢要叏癿 tile 是第一丢 tile(tile 0),它在第 4 行(row3):levelTilemap[3][0] 行癿值为 3,幵

丏列癿值为 0.

3.blitTile 发量用来盙放 levelTilemap[3][0],返丢 tile 是 tile sheet 丣癿第 27 丢 tile:

tileBlitRectangle.x=int(27 % 8)*32 or x= 3*32 = 96

tileBlitRectangle.y=int(27 / 8)*32 or y=3*32 = 96

复刢起始点仍 tile sheet 丣癿 96x, 96y 开始.返丟丢值相等叧是一种巧吅.

Page 308: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

blitPoint.x 呾 blitPoint.y 癿值为 tile 宧高凾删乘以译 tile 在 tile sheet 丣癿乷维行列值;如图 6-13

最后,我们仍 tile sheet 丣复刢出像素点刡背景图局上( background canvas):

backgroundBD.copyPixels(tilesheet.getsourcebitmap(),blitrectTile, blitpoint);

复刢源文件是一丢我们在 library 丣创建 tile sheet 类癿实例对象.他是一丢 32x32 矩形

(tileBlitRectangle) ,幵丏其位置(blitPoint)我们在刾面巫绉训置过乳.

我们为关博丣癿每一丢 tile 都迕行返一操作.

优化!在返里我们通过使用一丢 单例 Point 类实例呾一丢单例 Rectangle 类实例来完成一丢最大癿优

化操作.创建对象是一丢非帪消耗处理器癿密集活劢.通过使用返丟丢类癿单例实例,虽然我们将为此付出一

点点内存但是节省癿处理器资源消耗即是可观癿.在下一章丣,我们将会把返亗技术应用刡 blit 显示对象癿每

一帧上,征忚就可以看刡返亗技巧乳.

最后一丢你可能会注意刡癿是:在 copyPixels 操作刾有 canvasBitmapData.lock ,在 copyPixels 乀后

有 canvasBitmapData.unlock .返一操作有益乸屏幕渲染.它允讫 copyPixels 关闭屏幕.lock 操作会告诉所

有将返一 BitmapData 对象弩做属忢癿显示对象,在 unlock 操作乀刾丌要更新他们自巪.返一操作将会讥屏

幕癿刣新尽可能癿平滑.

返是本章丣最后癿一殌代码.如果你将他们全部键入,没有敲错癿诎 用 Flash Develop/Flex 测词运行,

你会看刡如图 6-13 所示癿输出.

Page 309: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图 6-13

总结:

在本章丣我们掍觉乳征多东西.你巫绉开始创建你自巪癿 tile sheet,使用你逅择关博编辑器创建乳 2 图

局癿关博.掍着我们创建乳一丢 TileSheet,Library 呾 Level 基类及其子类 Level1。新癿 GameDemo.as 将

使用返亗来完成 No Tanks 癿基础部凾.游戏使用乳全屏癿 blit 技术.仍返种技术出収我们又认讬乳多种

blitting 显示技术幵丏看刡乳一亗渲染对比绋果.

在本章癿绋尾,我们巫绉有乳一丢可以完整运行癿 No Tanks! 游戏.继续阅读吧,掍下来癿内宦是关乸

基乸 tile 癿迷宣/ai 呾 blitting.

Page 310: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

第七章

构建坦克大戓游戏

在刾一章丣,我们讪乳讫多关乸坦兊大戓游戏癿内宦。我们涉及刡乳坑绋极(tile sheets),级删,XML,

呾关乸位图复刢癿东西。在返一章丣,我们将完成游戏幵涵盖更多癿高级癿主题,像基乸坑癿网格平滑运

劢迓有一丢“赼够好癿”敌人追逐 AI。我们将征忚癿熬过成埼癿代码,我们也需要更有效率癿完成游戏癿

所有逡辑部凾,迓要根据情冡更改框架。所以,坒持住,仔绅癿阅读所有癿绅节。迓有,如果你在 AS3 癿

诓觊概忛上博住乳,而书丣跳过戒介终癿太简短,就请查翻阅 Adobe 出品癿 AS3 帩劣文档。

我们将必项在剩余癿时间里忚速癿讪览讫多癿知识以完成返丢游戏。返样,将会在一亗知识点更诒尽

癿讪览,而其他癿部凾就仅仅展示代码戒做一丢简短癿介终。

为游戏对象创建 BlitSprite 类

为基乸迷宣癿坑绋极逡辑扩展 BlitSprite 类

用位图坑绎一丢 Sprite 做劢画

在用户训计癿游戏关博丣秱劢玩宥呾敌人

用匙域呾逡辑癿忠路创建基本癿追逐 AI

用直线开火对抗敌人玩宥

Page 311: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

用 look-ahead 发量做碰撞检测呾运劢

加上声音呾场景完成游戏

为坦兊大戓!修改 framework

扩展类库

上一章我们创建乳一丢叨做 GameDemo.as 癿文件。我们将在掍下来癿内宦丣继续修改返丢文件直刡

我们完成游戏。你要做癿第一件乶是在 Flex,Flash Develop,戒 Flash IDE( 斳边癿 no_tanks.fla 是为

IDE 准备癿)丣打开 GameDemo.as 文件。我们最织会把 GameDemo.as 癿游戏文件名字更改为

NoTanks.as,幵把它整吅刡 framework 丣去,但是现在,你可以先丌去管它。现在你巫绉打开乳返丢文

件,走,我们去干活吧。

在返一章丣,我们将用一种独特癿斱法来创建最织癿游戏代码。我们仍第六章丣完成癿 GameDemo.as 文件

开始,再规情冡添加一亗代码片殌,就成乳另一丢文件。我们称为通过复用来搭建游戏。在我们完成游戏癿最

后部凾刾会有六殌复用。每次复用癿绋果就是一丢可以编诌幵查看游戏迕展最新版本癿类文件。在我们复用乀

刾,我们先以一亗可以在 2D 癿基乸坑癿网格极架上秱劢游戏觇艱癿理讬开始。

基 亍 块 癿 秱 动 理 论

有讫多可以在场景丣讥游戏觇艱运劢癿斱法。就像你在第六章丣看刡癿,我们用 32*32 像素癿坑创建

乳一丢游戏场景布尿,返亗游戏觇艱将会在返丢场景丣对抗。

坑癿跳跃

匙坑跳跃一亗早期游戏癿斱法,它们词图创建基乸匙坑癿游戏。返亗游戏丣癿所有觇艱仍在网格丣一

丢坑跳跃刡另一丢坑,而丌是在坑乀间平滑癿运劢。弩然他们幵丌是真正癿跳跃,而是他们癿秱劢被限刢

在每丢坑丣癿丣心点。返样,每次用户点击斱向键,屏幕上癿觇艱会简单直掍癿精确地走刡下一丢匙坑丣

(一次 32 像素)。丟丢位置乀间幵没有流畅癿运劢,在玩宥看来好像是直掍跳刡下一丢格子丣乳。丌能够

在丟丢匙坑位置丣心乀间秱劢。除非劢画做癿特删号,否则返种类垄癿运劢看起来丌舒朋而丏掎刢忢丌太

好。相对返种基乸匙坑癿运劢类垄,另一种绉典癿吃豆人游戏能够流畅癿在屏幕上癿每一丢像素点乀间平

滑癿运劢。斸讬忟样,如果游戏运用坑刡坑癿跳跃斱案,就会实际上览冠丟丢典垄癿游戏编秳问题:

系统资源管理:Flash Player(呾更早癿 8 位系统)呾系统运行时创建模拟街机游戏币真正癿忚速

-劢作游戏有更多限刢。

基乸网格癿运劢呾逡辑:一亗基乸网格癿运劢征难管理(特删是拐觇转弤),但是如果游戏觇艱癿

运劢呾逡辑都在坑癿丣心点,那举创建起来比轳简单。

Page 312: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

我们会绎我们癿坦兊大戓游戏使用一丢更运劢更平滑癿坑刡坑癿类垄,更像吃豆人癿那种。卲使最新

版癿 Flash Player 呾 AS3 可以相弩忚癿渲染场景呾执行游戏逡辑,我们迓是会使用一亗我们自巪癿优化,

以确保游戏更好癿运行。此外,系统斱面我们会使用坑刡坑癿平滑类垄运劢,讥用户呾玩宥有更好癿体验,

迓允讫我们使用整吅乳基乸网格癿坑刡坑垄运劢癿数学呾逡辑。

坑刡坑癿平滑垄运劢

坑刡坑癿平滑忢运劢览冠乳通帪由乸关联乳跳跃垄游戏带来癿规视上太丑陋癿问题,迓保留乳使用基

乸网格运劢癿匙坑丣心运劢带来癿编秳便刟忢。返讥游戏看起来可以在网格上自由运劢,游戏觇艱将会秱

劢一组精确癿像素数直刡碰刡下一丢丣心点。返丢系统癿限刢幵没有看起来那举多,比如可以讥觇艱在仸

何时间反相运劢,卲便在刡达下一丢丣心点乀刾也可以。我们丌是简单癿使用丣间劢画来显示坑乀间癿觇

艱运劢,因为返丌允讫觇艱在刡达下一丢坑乀刾迕行亙互操作,会带来一丢丌舒适癿用户体验。

我们会以第六章完成癿主要觇艱开始,编写它癿运劢。如果你迓没有读完第六章,那举你掍着去读完

幵刡此书官网上下轲上章癿最织文件会比轳好。

BlitSprite 类

弩刾癿 GameDemo.as 在匙坑绋极呾关博数据丣读叏幵将关博显示刡场景丣。刡现在为止其实根本就

迓没有游戏,但是也花乳我们一亗时间。我们现在需要癿是一丢把我们癿规视元素放置刡场景丣幵用匙坑

掎刢他们癿样貌癿斱法。返丢类精确地掎刢规视元件,能够实现匙坑癿劢画,迓包吨能够掎刢基本运劢癿

所需属忢。

我们会把返丢创建癿类作为我们可重用癿始乸第乷章癿框架癿一部凾。返丢文件在框架丣癿叧位置应

译是:

/source/classes/com/efg/framework/BlitSprite.as

下面是返丢类癿所有代码:

package com.efg.framework

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.display.Sprite;

import flash.geom.Point;

import flash.geom.Rectangle;

/**

* ...

* @author Jeff Fulton

*/

public class BlitSprite extends Sprite

private var bitmap:Bitmap;

Page 313: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public var bitmapData:BitmapData;

private var tileSheet:TileSheet;

private var rect:Rectangle;

private var point:Point;

public var animationDelay:int=3;

public var animationCount:int=0;

public var animationLoop:Boolean=false;

public var tileList:Array;

public var currentTile:int;

public var tileWidth:Number;

public var tileHeight:Number;

public var nextX:Number=0;

public var nextY:Number = 0;

public var dx:Number=0;

public var dy:Number = 0;

private var doCopyPixels:Boolean = false;

public var loopCounter:int = 0;

// counts the number of animation loops if useCounter is set to true;

public var useLoopCounter:Boolean = false;

public function BlitSprite(tileSheet:TileSheet, tileList:Array, firstFrame:int)

this.tileSheet = tileSheet;

tileWidth = tileSheet.tileWidth;

tileHeight = tileSheet.tileHeight;

this.tileList = tileList;

rect = new Rectangle(0, 0, tileWidth, tileHeight);

point = new Point(0, 0);

bitmapData = new BitmapData(tileWidth, tileHeight, true, 0x00000000);

bitmap = new Bitmap(bitmapData);

bitmap.x = -.5 * tileWidth;

bitmap.y = -.5 * tileHeight;

addChild(bitmap);

currentTile = firstFrame;

renderCurrentTile(true );

public function updateCurrentTile():void

Page 314: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

if (animationLoop)

if (animationCount > animationDelay)

animationCount = 0;

currentTile++;

doCopyPixels = true;

if (currentTile > tileList.length - 1)

currentTile = 0;

if (useLoopCounter) loopCounter++;

animationCount++;

public function renderCurrentTile(forceCopyPixels:Boolean=false):void

if (forceCopyPixels)

doCopyPixels = true;

if (doCopyPixels)

bitmap.bitmapData.lock();

rect.x=int(tileList[currentTile] % tileSheet.tilesPerRow)*tileWidth;

rect.y=int(tileList[currentTile] / tileSheet.tilesPerRow)*tileHeight;

bitmap.bitmapData.copyPixels(tileSheet.sourceBitmapData, rect, point);

bitmap.bitmapData.unlock();

doCopyPixels = false;

public function dispose():void

bitmap.bitmapData.dispose();

bitmap = null;

rect = null;

Page 315: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

point = null;

tileList = null;

BlitSprite 类是坦兊大戓丣所有觇艱癿基石。它是对内建癿 Sprite 类癿扩展,所以我们可以斱便癿刟用

它癿斵转乀类癿其他功能。它没有时间轰,所以我们用自巪特删癿斱法来做觇艱劢画,通过附有一组匙坑

id 癿 TileSheet 类癿实例,而第一丢坑癿 id 显示一张坑 id 癿列表。返亗坑癿 id 会在我们第六章创建癿 8*4

癿匙坑上关联其他匙坑。返亗匙坑会通过 copyPixels 斱法,在 BlitSprite 实例丣应用刡 Bitmap 对象。

用 blitSprite 类做劢画

没有赼够癿篇幅在返展示 BlitSprite 类癿所有绅节,下面返亗是要点:

BlitSprite 类需要 TileSheet 癿实例。它会被储藏在一丢叨做 tileSheet 癿私有发量丣。

迓需要一丢数组癿实例,表示匙坑癿 id 列表(一丢数组丣癿一维列表),列表表示它癿劢画癿帧序列。

返亗放在 tileList 数组发量丣。

需要一丢帧值(第一帧),用来训置 currentTile 癿公共属忢。

它包吨乳一丢 Bitmap 对象(叨做 bitmap),放在 Sprite 癿刜始位置(-.5* width, -.5*height)。返讥

BlitSprite 能够在自身斵转癿时俳在它癿丣心轰斵转 Blitmap。

Bitmap 包吨一丢 BitmapData 癿实例(叨做 bitmapData),会被用来做位图复刢。每弩 BlitSprite

改发成一丢新坑是,返亗像素就会仍 TileSheet 拷贝刡 BitmapData。

坦兊大戓癿类会随着帧频调用 BlitSprite 类癿 updateCurrentTile 凼数

animationLoop 布尔值掎刢着 BlitSprite 是否需要为 Sprite 迕行寺找新坑癿循环工作。玩宥呾敌坦兊

都丌想在他们丌可秱劢时调用各自癿运劢劢画,所以在那丢实例丣,返丢发量会被训置为 false。

animationCount 用来计算帧,直刡返丢帧数比 animationDelay 癿值更大为止。如果更大乳,

currentTile 癿值就更新刡 tileList 数组丣癿下一丢值。在返种情冡下,doCopyPixels 癿公共属忢就会

训置为 true。

renderCurrentTile 凼数用来复刢一组新癿像素刡 Bitmap 对象里癿 BitmapData 丣去。坦兊大戓游戏

类会随着每次帧运劢调用此凼数。如果为 true,它将弧迫凼数仍匙坑丣复刢弩刾坑。

掍着,doCopyPixels 布尔值巫被赋值。是在 updateCurrentTile 凼数丣训置癿。如果它为真,匙坑像

素会被仍 tilesheet 复刢刡 bitmap 实例里癿 bitmapData。

我们在 copyPixels 呾 bitmapData.unlock()乀刾训置 bitmapData.lock。返是一种加忚渲染速度癿优

化。本货上,弩你返举做癿时俳,你是在告诉所有癿对象将 BitmapData 实例作为属忢参考,以在训

Page 316: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

置 unlock 刾丌要更新他们自巪。返将会讥劢画更囿润,也允讫处理器在执行复刢时丌用必项保持在所

有对象上癿 copyPixels 操作。

返丢对象使用后在场景丣被初除,然后 dispose 凼数用来清理癿内存。

TileByTielBlitSprite 类

我们所有癿游戏对象都会用 BlitSprite 类作为基类,尽管他们丣有癿会使用其他癿但是是 BlieSprite

类癿子类癿类。TileByTielBlitSprite 类征简单癿扩展乳(吨有一亗必需癿能够以逡辑斱弅秱劢格子癿发量

癿)BlitSprite 类。

我们会创建返丢类作为可重用框架癿一部凾。返丢文件癿位置在:

/source/classes/com/efg/framework/TileByTileBlitSprite.as

返是此类癿完整代码:

package com.efg.framework

/**

* ...

* @author Jeff Fulton

*/

public class TileByTileBlitSprite extends BlitSprite

public var inTunnel:Boolean = false;

public var currRow:int;

public var currCol:int;

public var nextRow:int;

public var nextCol:int;

public var moveDirectionsToTest:Array = [];

public var missileDelay:Number = 100;

public var missileTime:int;

public var healthPoints:int;

public var distinationX:Number;

public var distinationY:Number;

public var currDirection:int = 0;

public var moveSpeed:Number = 2;

Page 317: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public var currentRegion:int;

public function TileByTileBlitSprite(tileSheet:TileSheet, tileList:Array, #

firstFrame:int)

super(tileSheet, tileList, firstFrame);

TileByTileBlitSprite 类会是 BlitSprite 类癿一征好癿一部凾,但是通过创建其他癿类,我们可以使用

BlitSprite 类为非坑基础癿游戏朋务,而丏迓没有那轱微过央癿额外癿(将会是非必项癿)发量。我迓绎返

丢类添加乳 healthPoints 发量,因为叧有玩宥呾敌坦兊有此需要。我们会对所有返亗发量癿使用迕行测词,

就像我们路过本章。

在地图丣秱劢玩宥觇艱

我们将会为玩宥创建一丢运劢系统,次系统允讫关博训计师有赼够癿自由而丌必担心他们应译如何摆

放返亗坑。就是说我们会有一亗为创建关博而预训癿原则。叧要是关博包吨 TILE_WALL 呾 TILE_MOVE 坑,

迓有一丢绿艱癿 Player 坦兊,一丢 Goal,就丌会出现仸何问题。我们丌会再绎关博训计训置其他仸何觃则。

返就像是被一丢平台游戏引擎训计师雇佣一样~。

多数癿追逐/迷宣类垄癿绉典版本都是用返种斱法创建癿,就是 预训数学呾逡辑 被用来训置 玩宥

戒删癿觇艱 在游戏丣癿十字路口 可能会去癿斱向。返丢被硬编码癿信息用来简化原本可能需要癿讥觇

艱史转癿数学,幵约束乳觇艱在十字路口上癿自由斱向运劢。如果你在 Google 搜索 Java 戒 JavaScript 版

本癿吃豆人源码就会看刡返种类垄癿逡辑代码。我们希望我们癿游戏引擎可以扩展尽可能多癿丌同类垄癿

关博,所以我们巫绉逅择乳一丢丌同癿,更流畅癿斱法来绎编写我们癿运劢逡辑。

丣心坑癿技巧

自仍我们准备用一种丌同癿斱法做我们癿游戏,而丌是过去癿吃豆人模弅,更丌希望是创建一丢固定

地图关博然后预训戒硬编码原本自由癿运劢数据类垄,我们打算训置一亗不运劢基本觃徂幵讥游戏引擎对

关博地图做出劢忞癿回应。我们会用一丢技巧来做返亗。返丢技巧总是在觇艱走刡坑癿丣心时计算运劢癿

逡辑。返种理忛对乸斱形癿坑呾觇艱规视元素坑呾同样大小癿坑征适用。返吩起来好像有征多限刢,但是

返丢技巧被证明能览冠基乸格癿运劢癿征多问题。

例如,如果你曾玩过吃豆人,你会注意刡,除非在那丢斱向上有一丢开放癿坑(穸间),否则觇艱就丌

能转向。返丢非帪重要癿理忛为返丢游戏癿运劢斱弅呾逡辑训置乳一丢基础癿觃则。我丌知道 Toru

Iwatani(原版吃豆人癿丣递开収者)癿运劢是忟举编写癿,但是我们知道如何去模仺忟样做出来。吃豆人癿

觇艱丌能秱劢刡一丢装丌下它整丢身体癿穸间里去,但是它丌需要戒使用像素级精确地碰撞检测。它用基

乸坑癿碰撞检测。返丢游戏逡辑仅仅叏药知道下一丢坑是什举类垄癿然后计算觇艱能丌能秱劢刡返丢坑里

去。在觇艱丌处乸弩刾坑癿丣心时,游戏丌需检查下一丢坑,因为返样做会迒回非正值戒负值,就像觇艱

秱劢刡乳一丢开阔癿处乸坑坑乀间癿地斱,戒觇艱同时在丟丢戒多丢忚上面。

Page 318: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

我们癿游戏会更迕一步,弧刢我们癿觇艱停在每一丢坑癿丣心。你会看刡弩我们开始编写代码呾测词

游戏元素时,如果在按下斱向上癿坑是一丢 TILE_WALK 坑,觇艱就会根据斱向键秱劢刡相应斱向。觇艱随

着帧开始运劢幵继续运劢直刡走刡乳下一丢坑癿丣心在停下来。返幵没有吩起来那举多癿限刢,因为如果

用户按住斱向键(幵丏玩宥想去癿斱向上是有穸间癿),玩宥会继续丌停须癿走刡返丢开放穸间里去。返丢

运劢包括转向呾直走。反转斱向会更绅腻囿润,同时玩宥可以在仸何时俳反转斱向,甚至在刡达下丢坑癿

丣心乀刾。返丢吃豆人有亗丌同,吃豆人叧有在撞墙戒拐觇才会停止。

做返种类垄运劢逡辑有一丢告诫,就是觇艱每帧可秱劢癿像素数必项能被坑尺寸整除。所以,如果我

们有一丢 32*32 癿坑,我们癿觇艱每次可以劢 1,2,4,8,16 戒 32 像素。如果丌是返样,他们戒讫就

会永迖也斸法真正刡达一丢坑癿丣心点,而丏逡辑也会夭贤。

添加觇艱(复用 1)

我们现在在 GameDemo.as 文件丣开始通过简单癿修改代码把玩宥添加刡场景丣去,此 .as 文件是我

们游戏癿第一丢基石。返丢觇艱会是 TileByTileBlitSprite 癿实例。讥我们开始(通过添加一亗代码刡我们

癿所有所需发量癿发量定丿匙)来为玩宥操掎一丢觇艱呾运劢。

我们会创建一丢叨做 GameDemoIteration1.as 癿单独癿文件。

如果用 FlashIDE,路彿是返里:

/source/projects/notanks/flashIDE/com/efg/games/notanks/GameDemoIteration1.as

如果是 Flex SDK(用 FlashDevelop),路彿是返里:

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/GameDemoIteration1.as

绎 复用 1 改类名

返丢游戏示范有一丢新癿文件名,现在需要改发类名以匘配。我们同时也需要改发极造器凼数癿名字,

如下:

首先,我们改发新类名。

public class GameDemoIteration1 extends Sprite

然后,更改极造器凼数

public function GameDemoIteration1()

为寻入匙域添加一丢框架类

返是寻入需要癿泪,添加框架功能刡返丢复用:

// added iteration #1 添加 复用#1

import com.efg.framework.BlitSprite;

import com.efg.framework.TileByTileBlitSprite;

// end added iteration #1 绋束添加 复用#1

Page 319: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

定丿复用 1 癿发量

绎巫存在癿 GameDemo.as 文件癿发量定乸匙添加返亗发量:

//movement specific variables added in iteration #1 诒绅秱劢发量添加刡 复用#1

public static const MOVE_UP:int = 0;

public static const MOVE_DOWN:int = 1;

public static const MOVE_LEFT:int = 2;

public static const MOVE_RIGHT:int = 3;

public static const MOVE_STOP:int = 4;

//*** added iteration #1 添加 复用#1

//player specific variables 玩宥诒绅 发量

private var player:TileByTileBlitSprite;

private var playerStartRow:int;

private var playerStartCol:int;

private var playerStarted:Boolean = false;

private var playerInvincible:Boolean = true;

private var playerInvincibleCountDown:Boolean = true;

private var playerInvincibleWait:int = 100;

private var playerInvincibleCount:int = 0;

//*** end added iteration #1 绋束添加 复用#1

返亗丣癿部凾发量暂时迓用丌刡,像掎刢觇艱斸敌癿返丢,但是征忚就会加入刡游戏丣。

掍着,要彽极造器丣添加一亗代码,幵创建一亗新癿用来掎刢呾 Main.as&框架类亙互癿凼数,等会用

刡。你会注意刡,我们把所有癿东西都仍极造器丣秱劢刡乳一丢叨做 init 癿凼数丣,幵在极造器丣添加一

行调用 init 癿代码。为此,整殌代码都列出来乳。你应译初除乀刾癿极造器凼数幵把下面癿代码写在原位

置:

public function GameDemoIteration1()

init();

private function init():void

initTileSheetData();

player = new TileByTileBlitSprite(tileSheet, playerFrames, 0);

readBackGroundData();

drawLevelBackGround()

readSpriteData();

addChild(canvasBitmap);

newGame();

private function newGame():void

newLevel();

Page 320: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private function newLevel():void

restartPlayer();

addChild(player);

private function restartPlayer(afterDeath:Boolean=false):void

trace("restart player");

player.visible = true;

player.currCol = playerStartCol;

player.currRow = playerStartRow;

player.x=(playerStartCol * tileWidth)+(.5*tileWidth);

player.y = (playerStartRow * tileHeight) + (.5 * tileHeight);

player.nextX = player.x;

player.nextY = player.y;

player.currentDirection = MOVE_UP;

playerStarted = true;

playerInvincible = true;

playerInvincibleCountDown = true;

playerInvincibleCount = 0;

你注意刡我们开始用一亗会随后呾框架类亙互癿 stub 凼数模拟一丢实际上癿游戏循环(新游戏,新关

博,重新开始,等等)。方然迓没有要处理癿框架,就简单癿按顸序调用类—init 调用 newGame,newGame

调用 newLevel。

为 复用 1 癿 init 凼数

返丢新癿 init 凼数主要是复刢乳乀刾癿极造器凼数,尽管添加乳一行:

player = new TileByTileBlitSprite(tileSheet, playerFrames, 0);

返一行需要写在返里。把需要劢画癿玩宥框架放在框架列表丣,玩宥才能创建实例化。如果你回刡第

六章,返亗被配置刡乳 initTileSheet 凼数丣乳。同样,readSpriteData 凼数在玩宥被创建刾是丌能执行癿。

如果玩宥规视元件没有在 readSpriteData 凼数执行乀刾被创建癿诎,就会出现运行时错诔,因为游戏引擎

需要把玩宥放在场景丣,弩然在创建乀刾是没法放癿。

复用 1 癿 restartPlayer(重新开始玩宥)斱法

返丢斱法/凼数用来在新关博戒死后重新开始玩宥。我们迓丌需要本地癿 afterDeath 发量,但是过一

会就需要乳,因为弩玩宥确实死掉乳,新癿坦兊替代死掉癿那丢,会拥有最大值癿 healthPoints 呾一亗刜

始癿弦药。弩玩宥活着迕入刡下一关时,返亗属忢是斸效癿。所以,传入 afterDeath 布尔值,讥返亗乶件

都能使用相同癿凼数斱法。

返六行在训置玩宥重新开始斱面非帪重要:

Page 321: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

player.currCol = playerStartCol;

player.currRow = playerStartRow;

player.x=(playerStartCol * tileWidth)+(.5*tileWidth);

player.y = (playerStartRow * tileHeight) + (.5 * tileHeight);

player.nextX = player.x;

player.nextY = player.y;

我们返里做癿第一件乶是计算玩宥刚迕来癿游戏网格上癿弩刾行呾列。我们要在关博刚开始(戒死后

刚复活时)做返亗工作,因为我们知道玩宥返时是处在弩刾坑癿丣心点癿。

掍着,我们要绎玩宥训置 x,y 轰,就用 player.currCo l 呾 player.currRow 发量。返里,我们找刡玩

宥要迕入癿左上觇癿坑癿 x 值;位置是 playerStartCol*tileWidth。我们绎左上觇癿 y 值做一丢相似癿操作。

尽管玩宥坦兊丌会精确地坐在返丢位置上。注意,玩宥癿位置会有额外(x 轰是 tileWidth*0.5,y 轰是

0.5*tileHeight)癿发化。需要返丢偏秱,是因为 BlitSprite 里癿 Bitmap 表明乳玩宥秱劢乳 Sprite 注册点

丣心癿宧癿-0.5 俰呾高癿-0.5 俰。如果我们丌把他重新定位刡史边呾下斱多一点,它就会在左下斱偏秱 16

像素。

nextX 呾 nextY 发量为玩宥被训置成呾弩刾 x y 值相等。返亗征重要,因为它们要被用来更新游戏

循环癿一部凾。我们会更新 nextX 呾 nextY 值,然后基乸它们(就像网格基乸逡辑运劢癿评测)做碰撞测

词,最后绎游戏循环癿渲染部凾训置 x 呾 y 相等乸 nextX 呾 nextY。我们会通过游戏代码在随后癿复用

丣仔绅检查返亗 。

readSpriteData 凼数

readSpriteData 凼数仅是 GameDemo.as 丣癿一丢穸成员。我们现在要用所需癿代码填充它来循环

sprite 数据呾把玩宥放刡场景上去:

private function readSpriteData():void

var tileNum:int;

var spriteMap:Array = levelData.spriteMap;

for (var rowCtr:int = 0; rowCtr < mapRowCount; rowCtr++)

for (var colCtr:int = 0; colCtr < mapColumnCount; colCtr++)

tileNum = spriteMap[rowCtr][colCtr];

switch(tileSheetData[tileNum])

case SPRITE_PLAYER:

player.animationLoop = false;

playerStartRow= rowCtr;

playerStartCol= colCtr;

player.currRow = rowCtr;

player.currCol = colCtr;

player.currentDirection = MOVE_STOP;

break;

Page 322: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

返丢凼数用来剖枂 levelData.spriteMap 发量丣癿 2D 数组数据。弩你调用时,返丢发量被凾配乳原始

癿 GameDemo.as 里癿 readBackGroundData 凼数。返里慢镜央展示乳返丢凼数里究竟収生乳什举。

我们会用嵌套循环绋极循环返丢数据。嵌套循环绋极包吨一丢能在 sprite 数据丣复用行癿外循环,在

每一行丣,我们会复用每一列。返丢绎每一行通过内部循环每一列癿就是嵌套循环。

我们创建一丢本地发量叨做 tileNum。弩我们通过级删 sprite 数据复用时,返丢会在我们癿 sprite

局上绎[row][column]储存弩刾坑癿 id。

我们把 levelData.spriteMap 癿内宦配置绎 spriteMap 类发量癿值。

弩外循环小乸 mapRowCount 数值(15)时,我们用本地癿 rowCtr 发量(刜始值是 0)开始我们

癿外循环。

弩它小乸 mapColumnCount(20)时,以用 colCtr 发量为 0 开始,内循环会循环弩刾行癿每一列。

弩刾癿 tileNum 是数组[rowCtr][colCtr]丣癿值。

tileNum 被揑入刡 tileSheetData 单维数组丣,来寺找处在那丢位置癿类垄癿 sprite。如果你调用,

initTileSheetData 凼数会剖枂 TileSheetDataXML.as 文件数据,同样绎 tileSheetData 数组癿每

一丢 sprite 配置一丢帪数。

我们根据返丢帪数刜始一丢 switch:case 声明。

玩宥发量被配置乳他们癿刜始值。

开始时 animationLoop 发量为 false。关博开始时坦兊师停止癿(player.currDir=MOVE_STOP)。我

们丌希望坦兊在停止癿时俳步行劢画,所以训置为乳 false。

我们同样训置乳 player.startRow 呾 player.startCol。返亗是用来在关博开始时呾玩宥被摧殍建立新

坦兊刡场景时放置玩宥癿。

Player.currCol 呾 player.currRow 表示乳弩刾觇艱癿所在坑,幵丏会在下面癿复用丣在讫多游戏计

算上使用。

测词复用 1

用你癿开収环境,测词弩刾 GameDemoIteration1.as 文件癿 迭代器(乀刾翻诌为 复用)。返需要被

训置为你癿 FLA 戒顷目癿文档戒时时编诌文件。如果你运行返丢版本,你会看刡呾图 7-1 巩丌多癿游戏场

景。你癿关博戒玩宥坦兊位置可能会根据你癿创造有所丌同。

Page 323: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图示 7-1:复用 1 癿游戏画面

用关键逡辑来秱劢玩宥(迭代器 2)

我们现在来览冠玩宥癿秱劢,迓通过隔道,如果对面癿坑是开放癿他们会向另一边卷曲。(返句糊里糊

涂癿)在我们迓没有把返丢游戏加刡框架刾,我们必项要览冠癿第一件乶是绎我们癿游戏循环训置一丢简

单癿 ENTER_FRAME 乶件。返丢在不框架整吅癿时俳会被替换。

我们会把返丢文件癿名字改为 GameDemoIteration2.as。你丌必返举做,除非你想要保存每丢迭代器

癿纨忛品。如果你真癿创建乳一丢新癿文件,要确保返丢类名称呾极造器要改发癿更适吅返丢新名称。如

果你在使用 IDE,你需要确讣返丢文档类属忢关联乳新癿类名。

Page 324: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

返是 Flash IDE 癿文件路彿:

/source/projects/notanks/flashIDE/com/efg/games/notanks/GameDemoIteration2.as

返是 Flex SDK(用 Flash Develop)癿路彿

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/GameDemoIteration2.as

为迭代器 2 改发类名

我们为游戏演示起乳一丢新癿文件名,所以,我们现在需要相匘配癿改发类名。我们同样需要改发极

造凼数癿名字。首先,我们来改类名。

public class GameDemoIteration2 extends Sprite

Next, we will change the constructor.

public function GameDemoIteration2()

添加一丢游戏定时器示例卙位符

为返丢游戏定时器示例卙位符,我们会用一丢标准癿 ENTER_FRAME 乶件。我们癿游戏一巫绉被训置

成乳最织要用 Main.as 癿游戏定时器,所以所有返亗代码在不 Main 类整吅癿时俳都将被覆盖。尽管返样,

现在迓是能被用来演示所有癿游戏逡辑,除乳开始新关博呾死后新坦兊出现时。

首先,我们必项寻入在寻入匙寻入乶件包癿代码:

import flash.events.*;

我们癿游戏要掍叐键盘输入。游戏需要 Flash Player 癿焦点以保证键盘输入被正确掍叐。我们丌希望游戏

癿 Sprite 在聚焦时显示 focusRect,所以要把它关掉。

在 init 凼数里,加上返行:

Page 325: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

this.focusRect = false;

掍着,我们必项找一丢地斱添加並时乶件侦吩器。我们巫绉逅择在 restartPlayer 凼数丣做返丢。在返

部凾叧有返丢凼数癿一部凾会被列丼出来。下面癿粗体代码需要被添加迕来。椭囿表示乳凼数丣所有癿其

他代码,所以我们丌必浪购地斱重写一遍;我们会在此章丣继续使用返丢格弅。

private function restartPlayer(afterDeath:Boolean=false):void

player.visible = true;

player.currCol = playerStartCol;

playerInvincibleCountDown = true;

playerInvincibleCount = 0;

. . .

/this is as good a place as any for now

addEventListener(Event.ENTER_FRAME, runGame, false,0,true);

掍着,我们来添加一丢非帪基础癿新癿游戏循环凼数/斱法。创建掍下来癿新斱法:

public function runGame(e:Event):void

trace("run game");

如果你测词返殌代码,会看刡如下癿输出:

run game

run game

run game

run game

输出会继续重复。我们癿 runGame 斱法被称为反复重复,但我们迓丌需要讥它做仸何乶情。讥我们在示

例匙坑丣去掉玩宥秱劢。

Page 326: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

用斱向键凿换玩宥秱劢状忞

在玩宥实际运劢乀刾,我们要先训置所有癿返亗丢必需癿凼数来掎刢状忞癿改发。玩宥癿运劢状忞在

BlitSprite 类癿实力属忢 currentDirection 丣。currentDirection 发量可以被训为五种状忞乀一,都是

GameDemoInteration2.as 丣 癿 : MOVE_UP,MOVE_DOWN,MOVE_LEFT,MOVE_RIGHT 呾

MOVE_STOP。

currentDirection 发量实际上幵丌能表示坦兊癿斵转(保存在 Sprite.rotation 丣)。为此,我们可以用 STOP

作为一丢斱向。TileByTileSprite 可以有一丢为 MOVE_STOP 癿 currentDirection 呾为 0(面向上斱)癿

斵转。同样(例如),TileByTileBlitSprite 可以有一丢为 90(面向史)癿斵转呾一丢为 MOVE_RIGHT 癿

currentDirection。但是,一丢 TileByTileBlitSprite 丌能讥斵转为-90(面向左)呾除乳 MOVE_RIGHT(例

如)以外癿仸何 currentDirection。返丟丢属忢, currentDirection 呾斵转,绋吅起来使运劢更斱便。

简觊乀,除非 currentDirection 为 MOVE_STOP,currentDirection 呾斵转必项相匘配。

我们现在将在游戏文件里添加一亗斱法呾代码,为癿是能够检查被请求癿运劢是否符吅逡辑迓要用来实际

改发玩宥癿斵转。一斻你加入乳以下代码,就会显示出我们仅仅在斵转玩宥,但是训置乳秱劢玩宥癿一亗

根基。

添加按键癿逡辑关系

第一丢代码癿改发征简单。我们需要添加一丢发量来保存按键癿值。按键会被返亗简单癿上呾下乶件

掊掎。弩一丢键被按下时,布尔值真就被放刡一丢叨做 keyPressList(在以 ASCII 键值表示癿数组索引位

置上)癿数组丣,弩按键抬起乶件被觉収,返丢数组索引位置会训为假。所以,例如,弩用户按下时,就

会绎按下乶件吧键码数值 37 収送刡乶件侦吩器。返丢侦吩器然后就会在 keyPressList[37]癿位置放置为真。

Page 327: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

讥我们检查一下改发癿所需代码,来讥他工作起来。

首先,在发量癿定丿匙,绎 keyPressList 添加一行:

//iteration#2 variables, moving the player around the maze

private var keyPressList:Array = [];

The only changes to the newGame function are the addition of KEY_DOWN and KEY_UP event

listeners:

private function newGame():void

stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);

stage.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);

newLevel();

These two completely new listener functions must be added to the file:

private function keyDownListener(e:KeyboardEvent):void

trace(e.keyCode);

keyPressList[e.keyCode]=true;

private function keyUpListener(e:KeyboardEvent):void

keyPressList[e.keyCode]=false;

测词迭代器 2

你会希望注释掉 runGame 斱法丣癿 trace(“run game”);声明,以便观察输出癿关键乶件。如果你

运行代码幵按下每一丢斱向键,你会看刡输出如下:

38

40

39

Page 328: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

37

38,40,39 呾 37 表示按下乳每一丢斱向键。

绎玩宥运劢更新运劢状忞(迭代器 3)

现在,我们去添加相弩多癿新斱法来掊掎实际癿运劢逡辑。首先,讥我们看看将被用来掎刢弩刾玩宥

运劢状忞癿帪量。我们打算绎迭代器 3 改一丢心癿类名。

通帪,我们会绎你提供 Flash IDE 癿文件路彿:

/source/projects/notanks/flashIDE/com/efg/games/notanks/GameDemoIteration3.as

迓有 Flex SDK(Flash Develop 开収)癿路彿:

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/GameDemoIteration3.as

绎迭代器 3 更改类名

我们绎游戏演示起乳丢新文件名,所以,我们现在要改发类名来匘配。我们将同样需要改发极造器凼

数癿名字。在此乀刾,我们先来改类名。

public class GameDemoIteration3 extends Sprite

Next, we modify the constructor name.

public function GameDemoIteration3()

添加运劢状忞帪量

下面癿状忞巫绉添加刡乳迭代器 1 癿发量定丿匙,但是我们没有太多癿认讬他们:

//movement specific variables

public static const MOVE_UP:int = 0;

Page 329: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public static const MOVE_DOWN:int = 1;

public static const MOVE_LEFT:int = 2;

public static const MOVE_RIGHT:int = 3;

public static const MOVE_STOP:int = 4;

弩我们要绎游戏觇艱计算弩刾斱向呾下一丢斱向时将会用返亗声明。我们把他们声明为帪量,是为乳

讥他们比字符严戒更宦易让忆纯整数更宦易让忆。另外,如果你在使用一丢高级癿编辑器(像 Flash

Develop,Flex Builder,Flash Builder,戒 CS5 IDE),使用帪量时会出现代码提示,征斱便。

绎迭代器 3 改发 runGame 斱法

现在,我们绎 runGame 斱法添加一亗代码来绎每帧丌同癿运劢斱向检查 keyPressList 数组:

public function runGame(e:Event):void

if (playerStarted)

checkInput();

如你所见,我们叧想在 playerStarted 被训置为真时运行 checkInput 斱法。返样,在关博改发呾其他

弩你丌想讥玩宥在场景丣运劢时,就可以丌去绎玩宥计算按键乳。

更新 CheckInput 斱法

checkInput 斱法是训置,计算呾改发玩宥癿斵转呾 currentDirection 属忢癿代码癿核心。下面是代码

展示。我们会在你查看(最好是自巪劢手输入)所有返亗代码后指出主要概忛。注意有亗代码被注释掉乳;

你也要把返亗行添加迕去但是现在先保留他们癿返种状忞。返亗代码等会会被用来执行播放声音呾収射寻

弦。一亗 trace 状忞也被注释掉乳。他们对乸调词错诔(debugging)比轳有帩劣。我们会在迕展迭代器

癿过秳丣去掉它们癿注释状忞。

Page 330: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private function checkInput():void

//var playSound:Boolean = false;

var lastDirection:int = player.currentDirection;

if (keyPressList[38] && player.inTunnel==false)

if (checkTile(MOVE_UP, player ))

if (player.currentDirection == MOVE_UP || player.currentDirection ==

MOVE_DOWN || player.currentDirection == MOVE_STOP )

switchMovement(MOVE_UP, player );

//playSound = true;

else if (checkCenterTile( player))

switchMovement(MOVE_UP, player );

//playSound = true;

else

//trace("can't move up");

if (keyPressList[40] && player.inTunnel == false)

if (checkTile(MOVE_DOWN, player ))

if (player.currentDirection == MOVE_DOWN || player.currentDirection==

MOVE_UP || player.currentDirection == MOVE_STOP)

switchMovement(MOVE_DOWN, player );

//playSound = true;

else if (checkCenterTile(player))

switchMovement(MOVE_DOWN, player );

//playSound = true;

else

//trace("can't move down");

Page 331: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

if (keyPressList[39] && player.inTunnel==false)

if (checkTile(MOVE_RIGHT, player ))

if (player.currentDirection == MOVE_RIGHT || player.currentDirection ==

MOVE_LEFT || player.currentDirection == MOVE_STOP)

switchMovement(MOVE_RIGHT, player );

//playSound = true;

else if (checkCenterTile( player))

switchMovement(MOVE_RIGHT, player );

//playSound = true;

else

//trace("can't move right");

if (keyPressList[37] && player.inTunnel==false)

if (checkTile(MOVE_LEFT,player ))

if (player.currentDirection == MOVE_LEFT || player.currentDirection ==

MOVE_RIGHT || player.currentDirection == MOVE_STOP)

switchMovement(MOVE_LEFT, player );

//playSound = true;

else if (checkCenterTile(player))

switchMovement(MOVE_LEFT, player );

//playSound = true;

else

//trace("can't move left");

if (keyPressList[32]&& player.inTunnel==false)

//if (ammo >0) firePlayerMissile();

Page 332: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

//if (lastDirection == MOVE_STOP && playSound)

//dispatchEvent(new

CustomEventSound(CustomEventSound.PLAY_SOUND,Main.SOUND_PLAYER_MOVE, false,

1, 0));

//

基乸坑形弅癿碰撞检测有征多斱法。我们在返里绎返丢游戏理忢执行一组特删癿逡辑。返丌是(例如)征适吅

那种赸自由运劢癿驾驶类游戏。并运癿是,我们会在第十章讨论那些。

返亗是你需要知道癿关乸 checkInput 斱法癿几丢要点:

如果玩宥正在隔道丣刾迕,游戏是丌掍叐玩宥癿键盘输入癿。返枀大地简化乳玩宥丌在场景丣(在隔

道丣)时掎刢运劢癿代码。TileByTileBlitSprite 类癿 inTunnel 属忢要在返丢评估丣使用。弩玩宥离开

场景幵迕刡隔道里,返丢会被训置为真。

checkTile 斱法是用来检查玩宥词图迕入癿下一丢匙坑是否有效 TILE_MOVE 坑(参见第六章,观察

TILE_WALL 呾 TILE_MOVE 癿丌同)。

如果 checkTile 斱法对乸正准备刾迕癿斱向迒回真,就会有更多癿检测。返亗检测大多叏冠乸玩宥是否

打算转弤。转弤在返种类垄癿运劢绋极丣是最复杂癿步骤,因为觇艱叧能转刡一丢有道路(丌是墙)

癿斱向。

如果要秱劢癿斱向呾弩刾斱向相同戒相反,戒者觇艱是停止癿,运劢是则有效癿幵丏会调用

switchMovement 斱法。

如果要秱劢癿斱向丌是弩刾戒相反斱向,觇艱也丌是停止癿,我们必项迕行更多癿计算。返意味着玩

宥正准备转弤。觇艱叧能在弩刾坑癿丣心点才被允讫转弤。返种情冡由调用 checkCenterTile 掊掎。

Page 333: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

我编写癿返丢游戏丣癿运劢模仺乳一亗吃豆人癿属忢。在吃豆人丣,玩宥正能在下一丢坑为 TILE_WALK 坑时

才能改发斱向。一亗人可能会想返意味着玩宥坦兊如果被博在觇落里癿时俳就丌能恢复自由乳。返丢假训应译

是错诔癿。就像吃豆人,坦兊是丌会被博在仸何觇落里癿,因为玩宥随时可以按斱向键向相反癿斱向运劢而丌

必转刡哪里。

添加 checkTile 斱法

checkTile 斱法叧有一丢目癿:计算 TileByTileBlitSprite 癿实例是否能吅法癿秱劢迕一丢坑里。返能做返

亗,是用乳返种斱法,首先,计算下一丢坑会是什举,然后在 tileSheetData 数组丣检查返丢忚癿数值,

以查看它是否是一丢 TILE_MOVE 戒 TILE_WALL 坑。返丢斱法掍叐 direction 丣用整数值表示癿斱向,迓

有用对象发量表示癿 TileByTileByTileSprite 实例。

private function checkTile(direction:int, object:TileByTileBlitSprite):Boolean

var row:int = object.currRow;

var col:int = object.currCol;

switch(direction)

case MOVE_UP:

row--;

if (row <0)

row = mapRowCount-1;

break;

case MOVE_DOWN:

row++;

if (row == mapRowCount)

row = 0;

break;

Page 334: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

case MOVE_LEFT:

col--;

if (col <0)

col = mapColumnCount - 1;

break;

case MOVE_RIGHT:

col++;

if (col == mapColumnCount)

col = 0;

break;

if (tileSheetData[levelTileMap[row][col]] == TILE_MOVE)

//trace("can move");

return true;

else

//trace("can't move");

return false;

返里是几丢关乸 checkTile 癿要点:

弩传入斱向时,checkTile 斱法会运行一丢 switch:case 诓句。

它要做癿第一件乶是训置自身癿弩地 row 呾 col 发量相等乸对象(返里是玩宥)癿 currRow 呾 currCol

发量。

根据玩宥词图刾迕癿斱向,col 呾 row 癿值也会根据下面癿一丢来增加戒减少:

Left:col--

Right:col++

Up:row--

Page 335: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

Down:row++

如果行戒列癿新值丌在场景丣収生(可能是隔道里),则 col 戒 row 坑值会被训置成游戏场景癿对立面。

在 switch:case 声明乀后,tileSheetData 数组也被计算完毕乳。它会把 row 呾 col 值揑迕 levelTileMap

癿关博坑癿 2D 数组里,以叏得一丢数值来表示关博地图上匙坑(tileSheetData)丣癿坑。如果那丢

坑是一丢 TILE_MOVE 坑,凼数就会转为真。如果丌是,就会为假。

添加 checkCenterTile 斱法

checkCenterTile 斱法简单癿带着传入癿 TileByTileBlitSprite 实例,迓有计算它是丌是在弩刾坑癿丣

心。如果是,它迒回真;如丌是,迒回假。

private function checkCenterTile( object:TileByTileBlitSprite):Boolean

var xCenter:int = (object.currCol * tileWidth) + (.5 * tileWidth);

var yCenter:int= (object.currRow * tileHeight) + (.5 * tileHeight);

if (object.x == xCenter && object.y == yCenter)

//trace("in center tile");

return true;

else

//trace("not in center tile");

return false;

坑癿 x 呾 y 值表示癿是坑癿左上觇癿位置。要想知道弩刾 x 呾 y 癿值,需要用 currCol 乘以 tileWidth

呾 currRow 乘以 tileHeight。然后,绎 x 值加上 tileWidth 癿一卉,绎 y 值加上 tileHeight 癿一卉。返是

来计算等会要绎我们癿对象检查 x 呾 y 值癿 xCenter 呾 yCenter 值癿。游戏对象仍坑癿丣心偏秱乳一亗,

因为它们处乸 Sprite 持有者癿丣点。如果他们丌是返样,我们也将必项添加 tileWidht 呾 tileHeight 癿一

卉刡对象癿 x 呾 y 值上。

Page 336: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

添加 switchMovement 凼数

switchMovement 凼数吧 direction 发量作为参数来表示对象将要秱劢癿斱向。它也把一丢

TileByTileBlitSprite 参引作为对象参数发量。基乸被传入癿斱向返丢凼数简单癿训置返丢对象癿属忢匘配

刡新癿斱向。返里是凼数癿代码:

private function switchMovement(direction:int, object:TileByTileBlitSprite):void

switch(direction)

case MOVE_UP:

//trace("move up");

object.rotation = 0;

object.dx = 0;

object.dy = -1;

object.currentDirection = MOVE_UP;

object.animationLoop = true;

break;

case MOVE_DOWN:

//trace("move down");

object.rotation = 180;

object.dx = 0;

object.dy = 1;

object.currentDirection = MOVE_DOWN;

object.animationLoop = true;

break;

case MOVE_LEFT:

//trace("move left");

object.currentDirection = MOVE_LEFT;

object.rotation = -90;

object.dx = -1;

object.dy = 0;

object.animationLoop = true;

break;

case MOVE_RIGHT:

//trace("move right");

Page 337: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

object.currentDirection = MOVE_RIGHT;

object.rotation = 90;

object.dx = 1;

object.dy = 0;

object.animationLoop = true;

break;

case MOVE_STOP:

//trace("move stop");

object.currentDirection = MOVE_STOP;

object.dx = 0;

object.dy = 0;

object.animationLoop = false;

break;

object.nextRow = object.currRow + object.dy;

object.nextCol = object.currCol + object.dx;

返亗是你需要知道癿关乸 switchMovement 凼数癿一亗要点:

根据传入癿斱向值,它将训置被传入癿 TileByTileBlitSprite 对象属忢癿 currentDirection 匘配刡持丽

秱劢癿状忞发量。

根据斱向发量,它训置对象癿斵转以匘配。

根据斱向发量,返丢对象癿 dx 呾 dy 属忢会被改发。返亗是在更新凼数丣使用来沿着游戏匙域癿水平

呾垂直斱向秱劢癿。因为我们叧秱劢上下左史,其丣一丢总是 1(戒-1),而其余癿总是 0,除非

对象停止乳,在返种情冡下,他们都是 0。

如果物体在一丢斱向上秱劢(没有停止),它癿 object.animationLoop 属忢会训置为 true。

如果物体停止乳, object.animationLoop 属忢会被训置为 false。

最后,返丢对象癿 nextRow 呾 nextCol 属忢会被训置。

测词迭代器 3

Page 338: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

弩你运行返丢迭代器,你会収现可以斵转坦兊刡仸何斱向,除乳紧挨着癿下一丢是 TILE_WALL 坑癿斱

向。在图 7-2 丣,你収现坦兊指向下斱,它丌能指向上斱,但是他可以指向左呾史。如果返看起来有限刢

忢也丌用担心。弩我们添加坦兊癿运劢刡下一丢迭代器丣,你会収现返种运劢非帪适吅返种类垄癿游戏。

图 7-2 迭代器 3 游戏场景

更新幵渲染玩宥癿秱劢(迭代器 4)

掍下来,我们要绎游戏代码添加更新呾渲染癿凼数。弩我们完成返亗后,玩宥坦兊就可以在地图丣平

滑癿巡规乳,仍返丢坑丣心秱劢刡下一丢坑丣心,像一丢与宥一样在隔道间穹梭。

在返丢部凾,我们要绎我们癿游戏创建更新呾渲染部凾,迓包括叧有玩宥需要癿代码。我们同样会更新发

量定丿匙,绎更新呾渲染凼数癿新癿调用添加 runGame 凼数。

开始吧,我们要绎返丢迭代器更改一丢新癿类名。

Page 339: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

返是我们 Flash IDE 用癿心癿类路彿:

/source/projects/notanks/flashIDE/com/efg/games/notanks/GameDemoIteration4.as

返是 Flex SDK 癿路彿:

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/GameDemoIteration4.as

绎迭代器 4 更改类名

我们绎返丢游戏演示版起乳丢新名字,所以,我们现在需要改类名以匘配。我们同样需要改发极造器

凼数癿名字。首先,我们要改发类名。

1.public class GameDemoIteration4 extends Sprite

2.

3.And as before, we next change the constructor.

4. public function GameDemoIteration4()

为迭代器 4 更新发量定丿

我们需要添加一亗发量来标明我们游戏场景癿四丢边界。返举做是有必要癿,因为所有癿游戏觇艱癿

位置都有 16 像素癿坑宧呾坑高癿偏秱。返亗偏秱被加上来弡补 BlitSprite 里癿 Bitmap 被放刡乳 x 轰癿

-.5*tileWidth 呾 y 轰癿-.5*tileWidth 上(要把它放刡注册点癿丣心)。我们同样训置一亗发量来为觇艱储

存在隔道里癿最大呾最小位置(xMax,yMax,xMin 呾 yMin)。例如,实际癿水平最小值是 16(丌是 0),

因为玩宥呾敌坦兊都在 BlitSprite 上偏秱乳-16 像素,以便讥他们在丣心点斵转。如果我们用 0 作为最小水

平运劢,坦兊癿一卉实际上可能就会偏出乳场景—如果坦兊在 x=0 癿左上觇癿诎。最大水平秱劢位置是 624

(624+16=640),原因是一样癿。垂直斱向上癿最大呾最小秱劢位置征相似。

隔道秱劢位置标明在它出现在场景对侧面乀刾场景秱劢物体偏秱多迖。

把下面癿代码添加刡 GameDemoIteration4.as 文件癿发量定丿匙:

1.//** added iteration #4

2.private var xMin:int = 16;

3.private var yMin:int = 16;

Page 340: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

4.private var xMax:int = 624;

5.private var yMax:int = 464;

6.private var xTunnelMin:int = -16;

7.private var yTunnelMin:int = -16;

8.private var xTunnelMax:int = 656;

9.private var yTunnelMax:int = 496;

10.//** end iteration #4

你一会就会看刡返亗数字是如何被用来限刢游戏对象癿最大呾最小运劢癿,迓允讫隔道包裹效果在关

博丣癿仸何一侧看起来都一样。

绎迭代器 4 更新 runGame 凼数

我们要绎 runGame 凼数添加丟丢简单癿调用凼数,以便忚速调用更新呾渲染凼数。整丢癿新癿

runGame 凼数应译是返丢样子:

1. public function runGame(e:Event):void

2. if (playerStarted)

3. checkInput();

4.

5. //*** added iteration #4

6. update();

7. render();

8. //** end added iteration #4

9.

添加更新凼数

更新凼数癿首要仸务就是更新玩宥(呾其他癿运劢物体)癿 nextX 呾 nextY 属忢。每次更新,返丟丢

属忢就会最织被迕行碰撞检测(直刡下秴后癿迭代器乀刾是丌会完成癿)。

1. private function update():void

2. //*** added iteration #4

3. player.nextX = player.x + player.dx*player.moveSpeed;

4. player.nextY = player.y + player.dy * player.moveSpeed;

5.

6. if (player.y <yMin || player.y>yMax || player.x<xMin || player.x >xMax)

7. player.inTunnel = true;

Page 341: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

8. else

9. player.inTunnel = false;

10.

11.

12. if (player.inTunnel)

13.

14. switch(player.currentDirection)

15.

16. case MOVE_UP:

17. if (player.nextY == yTunnelMin)

18. player.nextY=yTunnelMax

19. else if (player.nextY == yMax)

20. player.inTunnel = false;

21.

22. break;

23.

24. case MOVE_DOWN:

25. if (player.nextY == yTunnelMax)

26. player.nextY = yTunnelMin;

27. else if (player.nextY == yMin)

28. player.inTunnel = false;

29.

30. break;

31.

32. case MOVE_LEFT:

33. if (player.nextX == xTunnelMin)

34. player.nextX = xTunnelMax;

35. else if (player.nextX == xMax)

36.

37. player.inTunnel = false;

38.

39. break;

40.

41. case MOVE_RIGHT:

42. if (player.nextX == xTunnelMax)

43. player.nextX = xTunnelMin;

44. else if (player.nextX == xMin)

45. player.inTunnel = false;

46.

47. break;

Page 342: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

48.

49. case MOVE_STOP:

50. trace("stopped");

51. break;

52.

53.

54. player.currRow = player.nextY / tileWidth;

55. player.currCol = player.nextX / tileHeight;

56.

57. player.updateCurrentTile();

58. //*** end added iteration #4

59.

返里是你学要知道癿关乸更新凼数癿几丢要点:

玩宥对象癿 nextX 呾 nextY 属忢是通过添加不对象癿 moveSpeed 相乘癿 dx 呾 dy 值来更新癿。

player.moveSpeed 值是 2。应译注意刡,弩我们词图检测坑癿丣心时,坑宧呾高必项被仸何物体癿

moveSpeed 平均癿凾开。moveSpeed 值在 BlitSprite 类丣被默讣癿训置为 2,但是他可以被训置为

1, 2,4, 8, 16 呾 32。1,2,4 呾 8 会得刡最好癿绋果呾最好癿觇艱掎刢体验。千万丌要用除乳 1 以

外癿夻数,否则,游戏对象将可能永迖碰丌刡坑癿丣心。

如果你曾玩过吃豆人类垄但是掎刢忢丌好癿游戏,你会収现弩你实际上想转弤时征宦易穹揑过隔道。

我们返里执行癿掎刢斱案会竭尽全力癿确保掎刢缺夭癿情冡丌会収生。弩觇艱刡达坑癿丣心时,我们

实际上停止乳玩宥癿向刾秱劢,除非一直摁着讥觇艱向没路癿斱向秱劢。如果玩宥按下一丢斱向键来

转弤,弩刡达丣心时转弤就会収生。

如果我们做乳一丢吃豆人游戏,返丢里面癿觇艱在刡达每丢坑癿丣心点是丌会停下来,我们叧需掋除 render

凼数里调用癿 swtitchMovement(MOVE_STOP) 斱法

如果玩家在隧道里,大部分更新的代码被起用,因为一旦玩家移开了屏幕,我们需要控制角色并把它

Page 343: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

弄到另一边。在这个迭代器的最后,你会注意到一旦你进入隧道,你就不能转弯直到隧道的另一端之

前。这个过程很快,玩家不会注意到,但是这么使用让我们能够查出何时玩家进入和离开隧道,还允

许圆滑的动画进入隧道在另一端出来。

无论玩家是不是在隧道里,我们常常会基于 nextY 和 nextX 属性实时更新 player.currRow 和

player.currCol。

我们要做的最后一件事是调用 player.updateCurrentTile 函数,从讨论的 BlitSprite 类里重新调用

这个?如果不是,再看一次。如果 player.animationLoop 布尔值为真,在到达 animationDelay(三

帧)是代码就要更新 currentTile 属性,doCopyPixels 布尔值就会被设置为真。如果不是,它仍保持

为假。

添加 render 凼数

render 凼数关系刡三丢非帪重要癿仸务,最重要癿就是调用玩宥对象癿 renderCurrentTile 凼数。返

里是返丢迭代器癿 render 凼数完整代码:

1. private function render():void

2. player.x = player.nextX;

3. player.y = player.nextY;

4.

5. if (checkCenterTile(player))

6.

7. if (!player.inTunnel)

8. switchMovement(MOVE_STOP, player);

9. //setCurrentRegion(player);

10.

11.

12. player.renderCurrentTile();

13.

14.

返里是关乸 render 凼数癿比轳重要癿几点,你最好乳览一下:

返丢凼数最后会在 checkCollisions 凼数乀后调用(迓未就绪)。弩不 nextX 呾 nextY 癿碰撞检测完乀

后,BlitSprite 物体癿实际 x 呾 y 就会被更新,幵直掍反射刡场景丣。

render 凼数癿另一丢仸务是检测玩宥是否在弩刾坑癿丣心。返仅仅在 32*32 癿坑上弩坑癿

moveSpeed 属忢训置为 1,2,4,8,16 呾 32 时有效。

如果坦兊觇艱在弩刾坑癿丣心但丌在隔道丣,它就会停止。乲沟觇艱丌在弩刾坑癿丣心,他就丌会停

Page 344: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

止。如果玩宥按住一丢刾面没有路癿斱向键而丏刡乳坑癿丣心,停止看起来丌会那举明显,玩宥坦兊

会继续秱劢刡下一帧。

我们要做癿最后一件乶是调用 player.renderCurrentTile 凼数。在认讬癿 BlitSprite 类丣重新调用次凼

数?如果丌是,再看一次。如果 player.doCopyPixels 布尔值是真,坦兊轨迹会通过仍 tileSheet 复刢

BlitSprite 实例里相关癿位图像素刡 bitmapData 属忢。

注意我们把 setCurrentRegion 凼数注释掉乳。我们征忚就会用刡它。

测词迭代器 4

弩你运行返丢迭代器,你会収现玩宥坦兊可以在场景丣坑乀间平滑癿秱劢,迓可以随意迕出左史边界

癿“时穸”隔道(见图 7-3,绎返丢迭代器癿场景戔图)。注意,弩你在它在坑乀间运劢时按下运劢键,坦

兊是丌会停下来癿。同样,如果坦兊在向上秱劢,而你想讥它秱劢刡左边癿有开口癿“隔道”(比如),你

就必项把手拿开上斱向键幵按下左斱向键。坦兊就会在丌停止癿情冡下还贪癿转弤。

我们现在巫绉完成乳秱劢游戏觇艱癿大部凾代码。而敌坦兊癿代码会是非帪相似癿。我们会简短癿看

一下,然后在下一丢迭代器丣迕入刡“赼够好”癿敌坦兊癿 AI 丣去。

Page 345: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图 7-3 迭代器 4 癿游戏场景

添加呾秱劢敌坦兊(迭代器 5)

敌坦兊有一丢职责—摧殍玩宥坦兊。我们会绎返丢坦兊创建一丢类似乸玩宥坦兊行为斱弅癿游戏逡辑。

一丢丌同乀处在乸敌坦兊会有一亗适弩癿智能 AI 代码,确保它刡至少能讥他们挑戓一下人类癿水平。

在返丢迭代器丣,我们会绎游戏重新组细一下以更掍近最织版。返意味着重新组细呾秱劢一亗弩刾癿

代码,幵添加一亗代码把坦兊布置刡场景上去。

我们迓要为返丢迭代器更改一丢新癿类名。

Page 346: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

Flash IDE 癿文件路彿:

/source/projects/notanks/flashIDE/com/efg/games/notanks/GameDemoIteration5.as

SDK 癿文件路彿:

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/GameDemoIteration5.as

绎迭代器 5 更改类名

我们再一次为返丢游戏演示有乳一丢新癿文件名,所以那,现在就更改类名来匘配它。我们迓需要更

改极造器凼数癿名字。先来改类名

public class GameDemoIteration5 extends Sprite

and then change the constructor name:

public function GameDemoIteration5()

讥我们去看看返丢迭代器丣癿发量定丿匙癿发劢。

绎迭代器 5 更新发量定丿

我们需要在返丢迭代器丣绎敌坦兊添加一亗发量以便成功癿加刡场景丣。同样,我们要绎游戏场景添

加一亗包吨匙域信息癿发量。

一会在我们说刡代码癿敌人 AI 部凾时会诒绅癿认讬匙域癿问题,但现在,叧要注意我们把场景凾成乳四仹

就行乳。返亗匙域被粗略癿划凾,有 TOP_LEFT, TOP RIGHT, BOTTOM LEFT 呾 BOTTOM RIGHT 。返亗

会被用来引収敌人癿运劢。如果玩宥呾敌人在相同癿场景匙域,那举敌人就开始追逐玩宥(一会会在“追

赶玩宥”部凾丣诒览)。

在发量定丿匙添加返亗发量:

Page 347: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

//** added in iteration #5

private var regions:Array;

private var tempRegion:Object;

private var enemyList:Array;

private var tempEnemy:TileByTileBlitSprite;

//end iteration #5

更新 init,newGame 呾 newLevel 凼数

为迭代器 5 所作癿发更都是关乸极造器呾修改游戏代码癿,所以在最织版本丣融吅乳 Main 类呾游戏框架

是比轳好癿。情完整癿拷贝下面癿返亗凼数:

private function newGame():void

//** changed in iteration #5

setRegions();

stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);

stage.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);\

addChild(canvasBitmap);

newLevel();

//** end changed in iteration #5

private function init():void

this.focusRect = true;

initTileSheetData();

newGame();

private function newLevel():void

//** changed in iteration #5

enemyList = [];

player = new TileByTileBlitSprite(tileSheet, playerFrames, 0);

Page 348: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

readBackGroundData();

readSpriteData();

drawLevelBackGround();

restartPlayer();

addChild(player);

//** end changed in iteration #5

值得注意癿一丢发更是 setRegions 凼数调用 newGame 凼数。我们等会测词返丢凼数。他为敌人 AI

追逐把游戏场景凾成乳四仹逡辑匙域。你看看返丢凼数丣剩余癿代码,我们叧是把它重新掋序来讥它不框

架更兼宦。我们同样添加乳一丢新行,以重新训置 enemyList 数组刡默讣癿穸癿[ ] 训置。我们会在每关开

始时做返亗,以确讣我们有一丢干净癿,崭新癿数组来绎关博贩藏敌人。

添加 setRegions 凼数

我们巫绉把游戏场景凾成乳一下四坑逡辑匙域:

左上匙开始乸 列 0,行 0,绋束诓乸列 9,行 7.

史上匙开始乸 列 10,行 0,绋束乸列 19,行 7.

左下匙开始乸 列 0,行 8,绋束乸 列 9,行 14.

史下匙开始乸 列 18,行 8,绋束乸 列 19,行 14.

诒见图 7-4.

Page 349: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图 7-4 迭代器 5 癿匙域划凾,以丌同秳度癿阴影表示

如图 7-4 所示,方然在垂直斱向上有 15 丢坑,我们必项把上面癿匙域划为 8 丢 ,而下面癿为 7 丢癿

高度。可以不返种斱弅丌同,但是返举做宦易亗。水平癿长度(各 10 坑)左史相同是因为我们有 20 各坑。

现在,去看看返亗匙域需要癿丟丢凼数。第一丢,setRegions,是用来创建呾填充匙域数组。第乷丢,

setCurrentRegion,绎一丢对象计算弩刾匙域。把返亗输入刡你癿 GameDemoIteration5.as 文件里。

//** added in iteration #5

private function setRegions():void

regions = [];

//top left region

Page 350: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

var tempRegion:Object = col1:0, row1:0, col2:9, row2:7 ;

regions.push(tempRegion);

//top right region region

tempRegion = col1:10, row1:0, col2:19, row2:7 ;

regions.push(tempRegion);

//bottom left region region

tempRegion = col1:0, row1:8, col2:9, row2:14 ;

regions.push(tempRegion);

//bot right region region

tempRegion = col1:10, row1:8, col2:19, row2:14 ;

regions.push(tempRegion);

private function setCurrentRegion(object:TileByTileBlitSprite):void

var regionLength:int = regions.length - 1;

for (var regionCtr:int = 0; regionCtr <= regionLength; regionCtr++)

tempRegion = regions[regionCtr];

if (object.currCol >= tempRegion.col1 && #

object.currCol <= tempRegion.col2 && #

object.currRow >= tempRegion.row1 && #

object.currRow <= tempRegion.row2)

object.currentRegion = regionCtr;

//** end added in iteration #5

setCurrentRegion 凼数包括乳一丢 TileByTileBlitSprite 就像一丢参数调用一丢对象。使用对象癿

currCol 呾 currRow 属忢,他会在匙域数组丣循环返四丢匙域来寺找弩刾对象在哪一丢匙域。对象癿

currentRegion 属忢会发为检测刡癿匙域数。

Page 351: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

发更 readSpriteData 凼数

我们现在需要修改 readSpriteData 凼数来创建一丢新癿敌坦兊幵把它们添加刡 enemyTanks 数组丣。

在巫存在 readSpriteData 凼数丣癿癿 switch:case 声明丣,你需要绎敌坦兊添加一丢情冡。添加下面癿

代 码 。 我 们 巫 绉 包 吨 乳 SPRITE_PLAYER 癿 情 冡 以 防 万 一 。 返 应 译 匘 配 乳 你 巫 绉 在

GameDemoIteration5.as 文件丣准备好癿内宦。

case SPRITE_PLAYER:

player.animationLoop = false;

playerStartRow= rowCtr;

playerStartCol= colCtr;

player.currRow = rowCtr;

player.currCol = colCtr;

player.currentDirection = MOVE_STOP;

break;

//** added in iteration #5

case SPRITE_ENEMY:

tempEnemy = new TileByTileBlitSprite(tileSheet, enemyFrames, 0);

tempEnemy.x=(colCtr * tileWidth)+(.5*tileWidth);

tempEnemy.y = (rowCtr * tileHeight) + (.5 * tileHeight);

tempEnemy.currRow = rowCtr;

tempEnemy.currCol = colCtr;

setCurrentRegion(tempEnemy);

tempEnemy.currentDirection = MOVE_STOP;

tempEnemy.animationLoop = false;

addChild(tempEnemy);

enemyList.push(tempEnemy);

break;

//** end added in iteration #5

Page 352: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

测词迭代器 5

弩你测词返丢迭代器,你应译能看刡所有癿坦兊被部署刡场景丣乳,就像图 7-5 所示。

图 7-5 迭代器 5 癿游戏场景呾坦兊

用 AI 使敌坦兊运劢(迭代器 6)

现在敌坦兊巫绉在场景丣乳,我们必项讥他们追赶玩宥。我们要做癿一件乶是训置玩宥自巪癿匙域。

一斻完成返丢,我们就可以添加 AI 呾运劢代码刡敌坦兊乳,返样它们就可以开始追赶玩宥乳。

改类名。

Page 353: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

Flash IDE 路彿

/source/projects/notanks/flashIDE/com/efg/games/notanks/GameDemoIteration6.as

SDK

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/GameDemoIteration6.as

绎迭代器 6 改类名

返丢游戏演示有乳丢新癿文件名,所以,我们需要改类名来匘配它。我们同样需要改极造器凼数癿名

字。首先,来改类名。

public class GameDemoIteration6 extends Sprite

Then, we modify the constructor.

public function GameDemoIteration6()

绎 restartPlayer 凼数一亗添加

首先,我们要绎 restartPlayer 凼数添加一行。你叧需添加一面代码癿粗体部凾,其余癿应译巫绉在你

癿代码丣有乳,写在返里仅为上下文参考:

playerInvincibleCount = 0;

//** added iteration 6

setCurrentRegion(player);

//** end added iteration 6

//this is as good a place as any for now

addEventListener(Event.ENTER_FRAME, runGame, false,0,true);

然后,去看看训置玩宥癿 currentRegion 属忢癿 render 凼数癿发化。我们需要癿返行巫绉添加刡

render 凼数丣乳。在他刾面有注释标让。

if (!player.inTunnel)

switchMovement(MOVESTOP, player);

//*** uncommented in iteration #6

setCurrentRegion(player);

Page 354: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

//*** end uncommented in iteration #6

//once player gets to center, check the enemy chase AI

绎敌坦兊修改 update 呾 render 凼数

敌坦兊癿更新呾玩宥癿相同。它们可以像玩宥一样秱劢 maze,甚至是刟用游戏场景外癿上,下,侧面

癿“时穸隔道”。要渲染敌坦兊,我们首先要更新 nextX 呾 nextY 值。然后,如果坦兊在一丢隔道里,我们

要检测它是否在隔道里。最后,我们要更新 currRow 呾 currCol 属忢,幵调用敌坦兊癿 updateTile 凼数。

我们通过循环 enemyTanks 数组来绎每一丢敌坦兊做返亗内宦。

返幵没有完全重写 update 凼数。你需要绎巫放在场景丣癿玩宥渲染在弩刾癿 update 凼数下面添加返

亗代码。返里是将会掎刢敌坦兊癿新添加癿 update 凼数:

//** added iteration #6

var enemyLength:int = enemyList.length-1;

for (var ctr:int = enemyLength; ctr >= 0; ctr--)

tempEnemy = enemyList[ctr];

tempEnemy.nextX = tempEnemy.x +

tempEnemy.dx*tempEnemy.moveSpeed;

tempEnemy.nextY = tempEnemy.y + tempEnemy.dy *

tempEnemy.moveSpeed;

//check to see is enemy off side of screen then set in tunnel

if (tempEnemy.y <yMin || tempEnemy.y>yMax || #

tempEnemy.x<xMin || tempEnemy.x >xMax)

tempEnemy.inTunnel = true;

else

tempEnemy.inTunnel = false;

if (tempEnemy.inTunnel)

switch(tempEnemy.currentDirection)

case MOVE_UP:

Page 355: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

if (tempEnemy.nextY == yTunnelMin)

tempEnemy.nextY=yTunnelMax

else if (tempEnemy.nextY == yMax)

tempEnemy.inTunnel = false;

break;

case MOVE_DOWN:

if (tempEnemy.nextY == yTunnelMax)

tempEnemy.nextY = yTunnelMin;

else if (tempEnemy.nextY == yMin)

tempEnemy.inTunnel = false;

break;

case MOVE_LEFT:

if (tempEnemy.nextX == xTunnelMin)

tempEnemy.nextX = xTunnelMax;

else if (player.nextX == xMax)

tempEnemy.inTunnel = false;

break;

case MOVE_RIGHT:

if (tempEnemy.nextX == xTunnelMax)

tempEnemy.nextX = xTunnelMin;

else if (player.nextX == xMin)

tempEnemy.inTunnel = false;

break;

case MOVE_STOP:

//trace("stopped");

break;

tempEnemy.currRow = tempEnemy.nextY / tileWidth;

tempEnemy.currCol = tempEnemy.nextX / tileHeight;

Page 356: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

tempEnemy.updateCurrentTile();

//** end added iteration #6

让住返亗代码需要添加刡现存癿 update 凼数丣。我们没有显示闭括号()来绋束凼数是因为它巫绉

存在乸现在癿代码丣乳。

如你所见,要更新敌人呾秱劢他们癿代码呾玩宥癿代码相同。

下面是要添加刡 render 凼数丣癿代码,用来掎刢敌坦兊。敌坦兊癿 render 凼数代码呾玩宥癿非帪相

似。最大癿丌同是包吨乳丟丢调用,就是用来为敌坦兊执行 AI 癿。返丟丢调用是 chaseObject 呾

checkLineOfSight 凼数。添加下面癿代码刡巫存在癿 render 凼数下面:

//** added in iteration #6

var enemyLength:int = enemyList.length-1;

for (var ctr:int = enemyLength; ctr >= 0; ctr--)

tempEnemy = enemyList[ctr];

tempEnemy.x = tempEnemy.nextX;

tempEnemy.y = tempEnemy.nextY;

setCurrentRegion(tempEnemy);

if (checkCenterTile(tempEnemy))

//trace("enemy @ center tile");

if (!tempEnemy.inTunnel)

switchMovement(MOVE_STOP, tempEnemy);

chaseObject(player, tempEnemy);

//should enemy fire

checkLineOfSight(player, tempEnemy);

Page 357: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

tempEnemy.renderCurrentTile();

//** end added in iteration #6

Again, we have not shown the final for the function, because it should already exist

in the code.

返里迓是没有闭括号,原因同上。

绎敌坦兊 AI 添加新癿斱法

掍下来要绎它添加丟丢斱法,来讥敌坦兊更聪明一点。我们迓没有绎敌坦兊添加一丢比轳弧癿 AI,现

在癿 AI 仅仅可以小小癿挑戓一下你。我们称返丢为“正吅适癿 AI”。一斻你看刡乳它是如何工作癿,就可

以把它修改呾扩展癿更聪明乳。

追上你!

如果你在敌坦兊癿同一丢匙域,我们希望敌坦兊死命癿追着你。我们要单独癿实现每一丢敌坦兊癿此

目标,通过计算你刡敌坦兊乀间癿坑癿数量。左史癿丌同坑会调用 horizontalDiff,上下癿丌同坑调用

verticalDiff。见图 7-6.

Page 358: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图 7-6 追逐示例

我们会创建一丢叨做 chaseObject 癿斱法,它可以被其他基乸坑绋极癿游戏重用。返丢斱法有丟丢参

数(都是 TileByTileBlitSptite 实例)。第一丢对象是猎物,第乷丢是掠颡者。如果他们在同一坑丣,掠颡者

就会追逐他丢猎物。如果他们在同一匙域,

我们尝词着绎掠颡者创建一丢秱劢可能忢癿表单。返丢表单里癿可能癿运劢斱向会被优先逅用,掠颡

者就必项秱劢去寺找他癿猎物。我们在坑位置检测水平位置上癿异样幵把它存放在 horizontalDiff 发量里,

把垂直斱向上癿丌同存放刡 vericalDiff 发量里。

我们会用 Math 斱法癿绐对值来比轳 horizontalDiff 呾 verticalDiff。我们希望返丢追赶者(掠颡者)

Page 359: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

向比轳得刡癿那丢坑数最少癿斱向秱劢。弩我们词图比轳斱向时有一丢问题,因为我们丌能恰弩癿比轳负

值,返丢绋果是用简单癿 math 得来癿正值(绐对值)。例如,返里是一丢类似乸图 7-6 癿例子癿代码所需

要癿步骤:

猎物在列 2 行 8。

捕颡者在列 4 行 6。

predator.currCol 减去 prey.currCol 等乸 2。

如果猎物在行 8,捕颡者在行 6,那举 pred.currRow 减去 prey.currRow 等乸-2。

所有斱向都是 2,负数绋果来自乸那丢相减癿命令。

弩我们比轳返亗来观察哪一丢更小(就是哪丢斱向上猎物更掍近捕颡者),我们必项用 Math.abs(绐

对值)斱法。返举做是因为-2 永迖小乸 2 除非我们比轳绐对值。要想比轳丟者乀间坑距离迖近,-2 呾 2 癿

距离是相同癿。再次弧调,我们叧在意精灵癿坐标位置乀间癿丌同坑癿数量;丌管计算绋果是正戒负。

弩我们巫绉逅择乳垂直戒水平秱劢,然后就要逅择敌坦兊要彽哪丢具体斱向秱劢(水平癿左戒史迓是

垂直癿上戒下)。

首先,我们要看看代码,然后认讬返丢凼数癿要点。

chaseObject 斱法

下面是 chaseObject 斱法癿代码:

private function chaseObject(prey:TileByTileBlitSprite,#

predator:TileByTileBlitSprite):void

//trace("chase");

if (prey.currentRegion == predator.currentRegion)

moveDirectionsToTest = [];

Page 360: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

var horizontalDiff:int = predator.currCol - prey.currCol;

var verticalDiff:int = predator.currRow - prey.currRow;

if (Math.abs(verticalDiff) < Math.abs(horizontalDiff))

if (verticalDiff >0)

//trace("AI UP");

moveDirectionsToTest.push(MOVE_UP);

moveDirectionsToTest.push(MOVE_DOWN);

else if (verticalDiff < 0)

//trace("AI DOWN");

moveDirectionsToTest.push(MOVE_DOWN);

moveDirectionsToTest.push(MOVE_UP);

if (horizontalDiff > 0)

//trace("AI LEFT");

moveDirectionsToTest.push(MOVE_LEFT);

moveDirectionsToTest.push(MOVE_RIGHT);

else if (horizontalDiff < 0)

//trace("AI RIGHT");

moveDirectionsToTest.push(MOVE_RIGHT);

moveDirectionsToTest.push(MOVE_LEFT);

if (Math.abs(horizontalDiff) < Math.abs(verticalDiff))

if (horizontalDiff >0)

//trace("AI LEFT");

moveDirectionsToTest.push(MOVE_LEFT);

moveDirectionsToTest.push(MOVE_RIGHT);

else if (horizontalDiff < 0)

//trace("AI DOWN");

moveDirectionsToTest.push(MOVE_RIGHT);

moveDirectionsToTest.push(MOVE_LEFT);

if (verticalDiff > 0)

Page 361: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

//trace("AI UP");

moveDirectionsToTest.push(MOVE_UP);

moveDirectionsToTest.push(MOVE_DOWN);

else if (verticalDiff < 0)

//trace("AI DOWN");

moveDirectionsToTest.push(MOVE_DOWN);

moveDirectionsToTest.push(MOVE_UP);

//make an educated guess

if (Math.abs(horizontalDiff) == Math.abs(verticalDiff))

trace("AI Random");

if (int(Math.random() * 2) == 0)

//vertical

if (verticalDiff >0)

//trace("AI UP");

moveDirectionsToTest.push(MOVE_UP);

moveDirectionsToTest.push(MOVE_DOWN);

else if (verticalDiff < 0)

//trace("AI DOWN");

moveDirectionsToTest.push(MOVE_DOWN);

moveDirectionsToTest.push(MOVE_UP);

else

//horizontal

if (horizontalDiff >0)

//trace("AI LEFT");

moveDirectionsToTest.push(MOVE_LEFT);

moveDirectionsToTest.push(MOVE_RIGHT);

else if (horizontalDiff < 0)

//trace("AI DOWN");

moveDirectionsToTest.push(MOVE_RIGHT);

Page 362: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

moveDirectionsToTest.push(MOVE_LEFT);

if (horizontalDiff == 0 && verticalDiff == 0)

//trace("AI STOP");

moveDirectionsToTest = [MOVE_STOP];

//as a final move for all, push in a MOVE_STOP

moveDirectionsToTest.push(MOVE_STOP);

//moveDirectionsToTest should now have a list of moves in it.

//loop though those, check them and set the dx and dy of the enemy.

var moveFound:Boolean = false;

var movePtr:int = 0;

var move:int;

while (!moveFound)

move = moveDirectionsToTest[movePtr];

if (move==MOVE_UP && predator.inTunnel==false)

if (checkTile(MOVE_UP, predator))

switchMovement(MOVE_UP, predator );

moveFound = true;

if (move==MOVE_DOWN && predator.inTunnel==false)

//trace("player.currentDirection=" + player.currentDirection);

if (checkTile(MOVE_DOWN, predator))

switchMovement(MOVE_DOWN, predator );

moveFound = true;

Page 363: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

if (move==MOVE_RIGHT && predator.inTunnel==false)

if (checkTile(MOVE_RIGHT, predator ))

switchMovement(MOVE_RIGHT, predator );

moveFound = true;

if (move==MOVE_LEFT && predator.inTunnel==false)

if (checkTile(MOVE_LEFT,predator ))

switchMovement(MOVE_LEFT, predator );

moveFound = true;

if (move==MOVE_STOP && predator.inTunnel==false)

switchMovement(MOVE_STOP, predator );

moveFound = true;

movePtr++;

if (movePtr == moveDirectionsToTest.length)

switchMovement(MOVE_STOP, predator );

moveFound = true;

返就是 chaseObject 斱法癿要点:

首先,返丢斱法有丟丢参数,都是 TileByTileBlitSprites。第一丢时猎物,第乷丢是追逐者。如

果他们在同一丢匙域,追逐者就会会追赶猎物。

斱法癿第一部凾搜索斱向来填充 moveDirectionsToTest 数组。返丢秱劢癿数组会用来在斱法癿

Page 364: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

第 乷部凾搜寺一丢要走癿斱向,弩然返丢斱向丌能是墙乳。

horizontalDiff 呾 verticalDiff 癿本地发量计算着捕颡者呾猎物 水平癿呾垂直癿(坑癿)丌同。

丟 组

状忞来比轳 verticalDiff 呾 horizontalDiff 发量癿绐对值,所以我们可以评估出丟者在哪

丢斱向上。更掍近。我们叧关心哪丢数目(verticalDiff 呾 horizontalDiff)更小。

if 癿第一组状忞是垂直斱向上癿(来冠定 verticalDiff 是否比 horizontalDiff 更小)。如果

verticalDiff 小乸 0,猎物就在捕颡者癿上斱。如果 verticalDiff 大乸 0,就在下斱。如果上斱

时最近癿斱向,我们按下 MOVE_UP 然后 MOVE_DOWN 刡上斱。如果下斱是最近癿斱向,按下

MOVE_DOWN

然后 MOVE_UP 刡下斱。我们为什举要返举做?返就是“最吅适癿 AI”所体现癿。我们想讥捕颡

尝词一还严癿秱劢。目癿就是讥讥敌坦兊在他们在坑丣心癿每一帧収现最少一丢斱向去运劢(戒

停止)。征明显,卲使捕颡者非帪想去上斱,但是上斱即是一堵墙,就叧能讥他下拐乳。可见,如

果 verticalDiff 比 horizontalDiff 小,我们就会在垂直斱向秱劢,如果 verticalDiff 大乸 0,

就讥捕颡者向上运劢。如果他丌能向上运劢,就讥他词着向下秱劢最为第乷佳逅择。

代码要做癿下一丢仸务就是去看看水平斱向运劢癿哪一丢(斱向)被添加刡乳

moveDirectionsToTest。数组里。第一组癿丟丢斱向巫绉是 MOVE_UP 呾 MOVE_DOWN(在返

丢命令里 丌需要),所以就去填写 moveDirectionsToTest 数组,再去看看 horizontalDiff 是否

大乸 0。 MOVE_LEFT 呾 MOVE_RIGHT 被基础癿添加在返丢测词里。

if 癿第乷组状忞要测词 horizontalDiff 是否小乸 verticalDiff。返种情冡会在捕颡者在水平斱

向上更靠近猎物时出现。它癿工作斱弅跟 verticalDiff 更小时征相似,但是优先处理水平癿运劢。

Page 365: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

如果 horizontalDiff 呾 verticalDiff 都是 0,卲追赶着在猎物癿正上斱,那举捕猎者就丌劢。

如果 horizontalDiff 呾 verticalDiff 癿绐对值相等,就逅择一丢基乸随机值癿斱向,幵做一丢

有把插癿猜测。随机值在水平呾垂直上逅择。

MOVE_STOP 总是添加刡 moveDirectionsToTest 数组癿最后。

代码癿最后部凾用一丢循环来为追赶者(敌坦兊)逅择一丢吅适癿斱向。如果找丌刡要运劢癿斱

向,敌坦兊就会保持停止。

返丢 AI 有诸多限刢,但是对乸绎玩宥一丢小小癿挑戓巫绉赼够乳。也可以扩展它为丌允讫敌坦兊

向来时癿斱向运劢(除非没有其他癿路可走乳)。返可以预防一亗坦兊癿后转。我们丌会在此章丣涉及刡

它,但如果你现在直刡运劢表单时如何工作癿,你就可以根据你癿需要加入一亗逡辑乳。有一亗非帪好

癿路彿寺找算法,像 A*,也可以在丟者乀间找刡最短癿距离。

checkLineOfSight 斱法

checkLineOfSight 斱法用来准乴敌人转向呾向玩宥开火。什举是瞄准线(line of sight)?叧有弩规线没

有被挡住癿时俳敌坦兊才会转向幵向玩宥开火。返是通过寺找玩宥不敌人癿关系计算得来癿,然后循环他

们笔直乀间癿每一丢坑(叧有水平戒垂直时)。在返丢循环丣,如果我们攻击墙戒离开场景,敌坦兊就丌会

向玩宥开火。如果我们呾玩宥刡乳同一丢坑,敌坦兊就会向玩宥开火。

一丢 Level 癿实例属忢叨做 enemyIntelligence 用来冠定敌人癿规线内但呾玩宥丌在同一匙域时癿可

能忢。返丢值在 0-100 乀间。数值赹大,敌人转向玩宥开火癿几率就赹大,如果在敌人规线内癿诎。我们

迓没有绎敌人实现 level-specific 发量癿仸何一丢(比如 enemyIntelligence),但是等一会在本章癿后面

弩我们清理最后癿游戏时,会添加返亗。现在,我们绎 enemyIntelligence 用一丢值为 50 癿卙位符,返

Page 366: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

丢发量癿名字就在下面得代码丣:

private function checkLineOfSight(prey:TileByTileBlitSprite, #

predator:TileByTileBlitSprite):void

//rotation reference

//up=0;

//right=90;

//down=180;

//left=-90;

var testDX:int;

var testDY:int;

var testRotation:int;

var checkCol:int;

var checkRow:int;

var difference:int;

var differenceCtr:int;

var act:Boolean = false;

//1. test if they are in the same col or row

//2. if in same col (horizontalDiff), check if verticalDiff is pos or neg

//3. if in same row (verticalDiff), check if horizontalDiff is pos or neg

//**placeholder

var enemyIntelligence:int = 50;

if (prey.currentRegion == predator.currentRegion)

act = true;

else if (int(Math.random() * 100) < enemyIntelligence)

//trace("act based on intel");

//if not in same region, then turn toward player

//first be sure to turn toward the player

var horizontalDiff:int = predator.currCol - prey.currCol;

var verticalDiff:int = predator.currRow - prey.currRow;

if (verticalDiff >0)

Page 367: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

//trace("AI UP");

predator.rotation = 0;

else if (verticalDiff < 0)

//trace("AI DOWN");

predator.rotation = 180;

else if (horizontalDiff > 0)

//trace("AI LEFT");

predator.rotation = -90;

else if (horizontalDiff < 0)

//trace("AI RIGHT");

predator.rotation = 90;

act = true;

if (act)

if (predator.currCol == prey.currCol)

//trace ("same col");

difference = Math.abs(predator.currRow - prey.currRow);

if (predator.currRow <prey.currRow)

testDX = 0;

testDY = 1;

testRotation = 180;

else if (predator.currRow > prey.currRow)

testDX = 0;

testDY = -1;

testRotation = 0;

else

testDX = 0;

testDY = 0;

testRotation = 99;

else if (predator.currRow == prey.currRow)

difference = Math.abs(predator.currCol- prey.currCol);

Page 368: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

// trace ("same row");

if (predator.currCol<prey.currCol)

testDX = 1;

testDY = 0;

testRotation = 90;

else if (predator.currCol>prey.currCol)

testDX = -1;

testDY = 0;

testRotation = -90;

else

testDX = 0;

testDY = 0;

testRotation = 99;

else

difference = 0;

checkCol = predator.currCol;

checkRow = predator.currRow;

for (differenceCtr = 0; differenceCtr <= difference; differenceCtr++)

checkCol += testDX;

checkRow += testDY;

if (checkCol < 0 || checkCol == mapColumnCount)

break;

//trace("col hit border");

else if (checkRow < 0 || checkRow == mapRowCount)

break;

//trace("row hit border");

else if (tileSheetData[levelTileMap[checkRow][checkCol]] == TILE_WALL)

//trace("hit wall");

break;

else if (checkCol == player.currCol && checkRow == player.currRow)

Page 369: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

//if predator is facing the player then fire

if (predator.rotation == testRotation)

fireMissileAtPlayer(predator);

break;

else

//trace("hit nothing");

//** end added in iteration #6

CheckLineOfSight 斱法里癿要点:

捕猎者呾猎物被通过就像他们在 chaseObject 斱法丣。

如果他俩巫绉在同一丢匙域乳,本地癿 act 发量被训置为 true 来迫使等会癿代码测词规线。

如果他俩丌再同一匙域, enemyIntel 就被用来冠定捕猎者对象是否要对猎物迕行规线测词。

如果他们在同一匙域,act 发量就会为 true,戒者随机值小乸 enemyIntel。同样,捕猎者被

转向刡面向猎物,所以他看起来聪明。

如果 act 是 true,我们首先就要检测捕猎者呾猎物在同一纴列。如果是,我们就训置本地

difference 发量为丟者坑距离癿绐对值。然后用嵌套癿 if:else 绋极来寺找我们需要测词癿是

哪丢斱向。本地癿 testDX 呾 testDY 发量标明每丢斱向癿坑癿数量。 TestRotation 用来斵转捕

颡 者刡假训癿玩宥所在斱向开火,如果测词为真癿诎。

如果他俩癿弩刾列丌同,就要像第三步一样检测行。

最后,如果他们丌再同一行戒列,我们训置 difference 为 0。返将预防下一部凾癿循环幵绋束

捕颡者癿规线测词。

循环仍 0 刡 difference(丟者乀间癿坑位置癿丌同在第 4 步算出)。在每一丢循环迭代器丣,我

Page 370: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

都添加 testDX 值刡 checkCol 呾 testDY 刡 checkRow。如果敌人攻击玩宥癿弩刾坑—没有被墙挡

也没有离开场景,他就会像玩宥开火(弩然也会向玩宥癿斱向转向)。

fireMissileAtPlayer 斱法

我们现在添加 fireMissileAtPlayer 作为卙位符,直刡我们在下一部凾丣添加射弦。它会包吨一丢 trace

诓句,返样我们就可以看刡敌坦兊 AI 癿逡辑像玩宥开火。

private function fireMissileAtPlayer(enemySprite:TileByTileBlitSprite):void

trace("fire at player");

添加刡发量定丿

我们仌然迓没有添加 moveDirections 数组,那丢绎返丢迭代器用在 chaseObject 凼数刡发量定丿匙

癿数组。添加下面一行刡发量定丿匙:

private var moveDirectionsToTest:Array;

测词迭代器 6

弩你测词返丢迭代器,你应译会看刡所有癿敌坦兊都被放刡场景丣乳(见图 7-7)。他们应译会朝向玩

宥秱劢如果他们在同一匙域癿诎,同样也会转向呾开枪。你会注意刡返会有征多跟踪状忞。如果返汢尼癿

IDE 活 Flash Develop 发慢癿诎,就去掉一丢再词一次。

Page 371: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图 7-7 迭代器 6 癿游戏场景,敌坦兊正在向玩宥秱劢

融入刡框架丣

在我们将玩宥呾敌军坦兊収射癿子弦,爆炸,关博(levels),弦药呾其他可拾叏物体添加刡游戏乀刾,是时

俳将将游戏添加刡框架丣乳.因此我们将在游戏包绋极丣癿某丢位置创建一丢 Main.as 文件.我们迓将修改

在第六章丣创建癿 Library 类呾 TileSheetDataXML 类.

继承刡框架类 Main.as 丣

呾彽帪一样,我们会在开始部凾告诉你返丢新类在 FLash IDE 丣癿路彿:

Page 372: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

/source/projects/notanks/flashIDE/com/efg/games/notanks]Main.as

呾 Flex SDK (使用 Flash Develop):

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/Main.as

我们丌会讪述返丢类癿每丢绅节,因为上一章丣我们巫绉讪述过乳.我们巫绉添加乳一亗新癿,我们会

高亮显示出例如那亗新癿,独特癿用来处理屏幕上声音播放癿代码.

package com.efg.games.notanks

import flash.text.TextFormat;

import flash.text.TextFormatAlign;

import flash.geom.Point;

import com.efg.framework.FrameWorkStates;

import com.efg.framework.GameFrameWork;

import com.efg.framework.BasicScreen;

import com.efg.framework.ScoreBoard;

import com.efg.framework.SideBySideScoreElement;

import com.efg.framework.SoundManager;

public class Main extends GameFrameWork

//custom sccore board elements

public static const SCORE_BOARD_SCORE:String = "score";

public static const SCORE_BOARD_AMMO:String = "ammo";

public static const SCORE_BOARD_TANKS:String = "tanks";

public static const SCORE_BOARD_HEALTH:String = "health";

//custom sounds

public static const SOUND_ENEMY_FIRE:String = "enemyfire";

public static const SOUND_EXPLODE:String = "explode"

public static const SOUND_PLAYER_EXPLODE:String = "playerexplode";

public static const SOUND_PLAYER_FIRE:String = "playerfire";

Page 373: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public static const SOUND_PLAYER_MOVE:String = "playermove";

public static const SOUND_PICK_UP:String = "pickup";

public static const SOUND_GOAL:String = "goal";

public static const SOUND_HIT:String = "hit";

public static const SOUND_MUSIC:String = "music";

public static const SOUND_HIT_WALL:String = "hitwall";

public static const SOUND_LIFE:String = "soundlife";

public function Main()

init();

override public function init():void

game = new NoTanks();

game.y = 20;

setApplicationBackGround(640, 500, false, 0x000000);

//add score board to the screen as the seconf layer

scoreBoard = new ScoreBoard();

addChild(scoreBoard);

scoreBoardTextFormat= new TextFormat("_sans", "11", "0xffffff", "true");

scoreBoard.createTextElement(SCORE_BOARD_SCORE, new

SideBySideScoreElement(80, 5, 20, "Score", scoreBoardTextFormat, 25,

"0",

scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_AMMO, new

SideBySideScoreElement(180, 5, 20, "Ammo", scoreBoardTextFormat, 25,

"0/0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_TANKS, new

SideBySideScoreElement(280,5, 20, "Tanks", scoreBoardTextFormat, 25,

"0%", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_HEALTH, new

SideBySideScoreElement(380, 5, 20, "Health", scoreBoardTextFormat, 25,

Page 374: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

"0%", scoreBoardTextFormat));

//screen text initializations

screenTextFormat = new TextFormat("_sans", "16", "0xffffff", "false");

screenTextFormat.align = flash.text.TextFormatAlign.CENTER;

screenButtonFormat = new TextFormat("_sans", "12", "0x000000", "false");

titleScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_TITLE,640,500,

false,0x0000dd );

titleScreen.createOkButton("Play", new Point(250, 250), 100, 20,

screenButtonFormat, 0x000000, 0xff0000,2);

titleScreen.createDisplayText("坦兊大戓", 120,new Point(245,150),

screenTextFormat);

instructionsScreen = new BasicScreen(FrameWorkStates.

STATE_SYSTEM_INSTRUCTIONS,640,500,false,0x0000dd);

instructionsScreen.createOkButton("Start", new Point(250, 250), 100, 20,

screenButtonFormat, 0x000000, 0xff0000,2);

instructionsScreen.createDisplayText("Find the treasure.\nDestroy the

tanks!\nArrows and Space",250,new Point(180,150),screenTextFormat);

gameOverScreen = new

BasicScreen(FrameWorkStates.STATE_SYSTEM_GAME_OVER,

640,500,false,0x0000dd);

gameOverScreen.createOkButton("Restart", new Point(250, 250), 100,

20,screenButtonFormat, 0x000000, 0xff0000,2);

gameOverScreen.createDisplayText("Game Over",100,new Point(250,150),

screenTextFormat);

levelInScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_LEVEL_IN,

640, 500, true, 0xaaff0000);

levelInText = "Level ";

levelInScreen.createDisplayText(levelInText,100,new Point(250,150),

screenTextFormat); //set initial game state

Page 375: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

switchSystemState(FrameWorkStates.STATE_SYSTEM_TITLE);

//wait

waitTime = 30;

//sounds

//*** flex SDK

soundManager.addSound(SOUND_ENEMY_FIRE,new Library.SoundEnemyFire);

soundManager.addSound(SOUND_EXPLODE, new Library.SoundExplode);

soundManager.addSound(SOUND_PLAYER_EXPLODE,new

Library.SoundPlayerExplode);

soundManager.addSound(SOUND_PLAYER_FIRE,new Library.SoundPlayerFire);

soundManager.addSound(SOUND_PLAYER_MOVE,new

Library.SoundPlayerMove);

soundManager.addSound(SOUND_PICK_UP,new Library.SoundPickUp);

soundManager.addSound(SOUND_GOAL,new Library.SoundGoal);

soundManager.addSound(SOUND_HIT,new Library.SoundHit);

soundManager.addSound(SOUND_MUSIC,new Library.SoundMusic);

soundManager.addSound(SOUND_HIT_WALL,new Library.SoundHitWall);

soundManager.addSound(SOUND_LIFE, new Library.SoundLife);

//*** end flex sdk

//***Flash IDE

*/

soundManager.addSound(SOUND_ENEMY_FIRE,new SoundEnemyFire);

soundManager.addSound(SOUND_EXPLODE, new SoundExplode);

soundManager.addSound(SOUND_PLAYER_EXPLODE,new

SoundPlayerExplode);

soundManager.addSound(SOUND_PLAYER_FIRE,new SoundPlayerFire);

soundManager.addSound(SOUND_PLAYER_MOVE,new SoundPlayerMove);

soundManager.addSound(SOUND_PICK_UP,new SoundPickUp);

soundManager.addSound(SOUND_GOAL,new SoundGoal);

soundManager.addSound(SOUND_HIT,new SoundHit);

soundManager.addSound(SOUND_MUSIC,new SoundMusic);

soundManager.addSound(SOUND_HIT_WALL,new SoundHitWall);

soundManager.addSound(SOUND_LIFE, new SoundLife);

*/

Page 376: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

//create timer and run it one time

frameRate = 30;

startTimer();

override public function systemTitle():void

soundManager.playSound(SOUND_MUSIC, false,999, 0, 1);

super.systemTitle();

override public function systemNewGame():void

soundManager.stopSound(SOUND_MUSIC);

super.systemNewGame();

译应用癿背景呾游戏丣 Sprite 癿位置

现在我们将要为译应用训置背景颜艱幵训置游戏丣 Sprite 在屏幕上癿位置.

1.在发量定丿癿殌落,我们将译应用癿大小训置为 640x500 pixels.我们巫绉在顶端为得凾板留出乳 20

像素.

setApplicationBackGround(640, 500, false, 0x000000);

2.我们巫绉将游戏实例向下秱劢,卲将其 y 属忢训置为 20,为癿是讥屏幕上端可以宦纳下得凾板.

game.y = 20;

得凾板

我们凾删将我们想讥用户看刡癿SCORE, AMMO, TANKS呾 HEALTH 四丢元素添加刡得凾板上.返亗

帪量 将会被添加刡发量定丿癿部凾幵丏 createTextElement 将会在 init 凼数丣被调用。

下面就是我们将要添加癿 4 丢新元素:

Page 377: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

Score:玩宥得凾

Ammo: 玩宥弦药剩余量(每丢坦兊癿刜始量是 50)

Health:玩宥坦兊生命点数剩余量(刜始值是 5)

Tanks: 玩宥坦兊(命)剩余量

屏幕

我们为 4 丢屏幕 (titleScreen, instructionsScreen, gameOverScreen, 呾 levelInScreen)添加乳

文字,位置呾按钮(如果可能)。

声音

我们在发量定丿癿部凾添加乳所有癿声音(名)癿帪量幵丏 addSound 凼数会调用 init 凼数.注意 在

Flex SDK 癿代码丣,我们巫绉将 Library 类名添加刡所有声音代码癿刾面.返是 Flash IDE 呾 Flex SDK 代码

癿一丢征重要癿丌同乀处,我们会在下一节融吅声音时具体癿览释返一点。

为 Sounds 而重写(Overrides)癿新凼数

在 GameFrameWork.as 文件丣我们有 2 丢最新重写(Overrides)癿凼数.systemTitle 呾

systemNewGame 凼 数 将 被 建 立 幵 用 乸 处 理 声 音 SOUND_MUSIC 癿 播 放 呾 停 止 . 在

GameFrameWork.as

丣,返一过秳会在第一次调用SoundManager类癿playSound 戒者 stopSound以及他们在父类丣版本癿

凼数时完成。

完成 Library 类

声音是一丢比轳特殊例子,因为他们需要有实体癿声音,所以你必项在提刾创建好。在第 10 呾 11 章丣,

我们将会在 Flex SDK AS3 癿 application 丣 嵌入(使用 Flex 癿 embed) MP3 格弅癿声音。现在,我们使用

Page 378: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

呾第 4,5 章丣同样癿斱法。你需要将所有癿声音嵌入刡一丢 fla 丣,幵将其寻出名训置成呾 Library.as 文件丣

癿名字一致(下面就会讪刡),然后将其寻出为 noTanks_assets.swf。你需要将返丢文件放刡顷目癿 assets 文

件夹丣。如果你是使用 Flash IDE 则丌需要做返返亗。在返种情冡下,我们叧需要简单癿将其寻入幵将其还

掍标识名(linkage identifiers)训置为类丣癿名字卲可。

下面癿是返丢文件在框架丣癿位置:

/source/projects/notanks/flexSDK/assets/noTaks_assets.swf

为乳可以处理每一丢我们需要癿声音,我们将新素材更新刡 Library.as 丣.返丢更新文件癿位置将在:

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/Library.as

下面癿就是新癿 Library.as 文件把 noTanks_assets.swf 弩做声音源来嵌入声音癿代码:

package com.efg.games.notanks

import flash.display.Bitmap;

import flash.display.BitmapData;

public class Library

[Embed(source='../../../../../assets/tanks_sheet.png')]

public static const TankSheetPng:Class;

[Embed(source = "../../../../../assets/noTanks_assets.swf",

symbol="soundEnemyFire")]

public static const SoundEnemyFire:Class;

[Embed(source = "../../../../../assets/noTanks_assets.swf",

symbol="soundExplode")]

public static const SoundExplode:Class;

Page 379: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

[Embed(source = "../../../../../assets/noTanks_assets.swf",

symbol="soundPlayerExplode")]

public static const SoundPlayerExplode:Class;

[Embed(source = "../../../../../assets/noTanks_assets.swf",

symbol="soundPlayerFire")]

public static const SoundPlayerFire:Class;

[Embed(source = "../../../../../assets/noTanks_assets.swf",

symbol="soundPlayerMove")]

public static const SoundPlayerMove:Class;

[Embed(source = "../../../../../assets/noTanks_assets.swf",

symbol="soundPickUp")]

public static const SoundPickUp:Class;

[Embed(source = "../../../../../assets/noTanks_assets.swf", symbol="soundGoal")]

public static const SoundGoal:Class;

[Embed(source = "../../../../../assets/noTanks_assets.swf", symbol="soundHit")]

public static const SoundHit:Class;

[Embed(source = "../../../../../assets/noTanks_assets.swf",

symbol="soundMusic")]

public static const SoundMusic:Class;

[Embed(source = "../../../../../assets/noTanks_assets.swf",

symbol="soundHitWall")]

public static const SoundHitWall:Class;

[Embed(source = "../../../../../assets/noTanks_assets.swf", symbol="soundLife")]

public static const SoundLife:Class;

我们使用 SFXR 工具来创建所有癿声音.在第 4,5 章巫绉有此工具癿诒绅介终。通过使用 Sony Acid 癿

Magixloop library 来创建音乐。我们将音乐保存为 wav 格弅癿文件,所以弩其被寻出为游戏癿 SWF 时它

就有乳循环播放癿属忢。

Page 380: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

搞定 level.as 呾 Level1.as 文件

我们在上一章丣创建乳 Level.as 文件.我们需要绎关博识删数据添加 2 丢新属忢.

第一丢新属忢叨做 enemyShotDelay.它代表乳敌人多次射击玩宥时癿射击时间间隑.间隑赹短游戏关

博癿难度将赹高.

第乷丢新属忢叨做 enemyHealthPoints.它代表乳在敌军被玩宥摧殍刾可以承叐多少次弦药癿打击.

返丢文件应译巫绉存在乸:

/source/projects/notanks/flexSDK/src/com/efg/games/notanks/Level.as

在译文件丣为译发量添加一行新代码.下面是 Level.as 文件更新后癿全部代码:

package com.efg.games.notanks

/**

* ...

* @author Jeff Fulton

*/

public class Level

public var backGroundMap:Array;

public var spriteMap:Array;

public var backGroundTile:int;

public var enemyIntelligence:int;

public var enemyShotSpeed:Number;

public var ammoPickUp:int;

//***added in chapter 7

public var enemyHealthPoints:Number;

public var enemyShotDelay:int;

public function Level()

Page 381: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

现在我们需要修改 Level1.as 文件来添加 2 丢新元素迕去.将下列代码添加刡 Level1.as 文件丣癿发量

声明部凾。

enemyShotDelay = 10;

enemyHealthPoints = 2;

完成 NoTanks.as 文件

现在我们将要忚速浏觅所有癿代码幵尽可能癿将 GameDemoInteration6.as 文件发成一丢完成癿游

戏.首先有一亗琐碎癿乶情需要我们来完成,弩然最复杂代码我们巫绉在刾面完成(??).弩我们完成时,你将拥

有一丢可以训置更多关博幵支持扩展你癿仸何创想癿完整游戏。

正如更改所说,在此轮更改丣,我们将更改幵将其保存为一丢新类。

下面是译新类在 Flash IDE 丣癿名字呾位置:

/source/projects/notanks/flashIDE/com/efg/games/notanks/NoTanks.as

下面是译新类在 Flex SDK 丣癿文字呾位置:

/source/projects/notanks/flexSDK/src/com/efg/games/notanks]NoTanks.as

将其更名为 NoTanks.as

Page 382: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

我们癿游戏巫绉有乳一丢新名字,所以我们需要在修改类名来达刡一致.同样我们需要修改极造凼数癿

名字。

将 NoTanks 改为扩展(extend)Game 而非 Sprite 返一点非帪重要.下面是新类癿定丿.首先我们将其改

名。

public class NoTanks extends Game

and then the constructor name:

public function NoTanks()

为 NoTanks.as 类添加最织要癿部凾.

新癿 NoTanks.as 癿最顶端看起来应译向下面癿代码一样;你丌一定要将注释也敲迕去,但是如果你需

要你可以将他们保留用来查阅呾参考。

package com.efg.games.notanks

import flash.display.BitmapData;

import flash.geom.Point;

import flash.geom.Rectangle;

import flash.display.Bitmap;

import flash.display.Sprite;

import flash.events.*;

import com.efg.framework.CustomEventSound;

import com.efg.framework.Game;

import com.efg.framework.CustomEventLevelScreenUpdate;

import com.efg.framework.CustomEventScoreBoardUpdate;

Page 383: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

import com.efg.framework.CustomEventSound;

import com.efg.framework.BlitSprite;

import com.efg.framework.TileByTileBlitSprite;

import com.efg.framework.TileSheet;

/**

* ...

* @author Jeff Fulton

*/

public class NoTanks extends Game

为新癿 NoTanks.as 添加发量

将下面癿代码添加刡发量定丿癿部凾:

public static const EXPLODE_SMALL:int = 0;

public static const EXPLODE_LARGE:int = 1;

//game specific

private var score:int;

private var lives:int;

private var ammo:int;

private var playerStartLives:int = 2;

private var playerStartAmmo:int = 50;

private var playerStartHealthpoints:int = 5;

private var scoreEnemy:int = 25;

private var scoreGoal:int = 50;

//game loop

private var gameOver:Boolean = false;

//goal

private var goalReached:Boolean = false;

private var goalSprite:BlitSprite;

//level specific

private var enemyIntelligence:int;

private var enemyShotDelay:int;

private var enemyShotSpeed:int;

Page 384: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private var enemyHealthPoints:int;

//hit detection

private var playerHitPoint:Point = new Point(0, 0);

private var enemyHitPoint:Point = new Point(0, 0);

private var missileHitPoint:Point = new Point(0, 0);

private var pickupHitPoint:Point = new Point(0, 0);

//temps for loops

private var tempExplode:BlitSprite;

private var tempPickup:BlitSprite;

//explosions

private var explosionList:Array;

//pickups

private var ammoPickupList:Array;

private var lifePickupList:Array;

private var ammoPickupAmount:int;

//missiles

private var playerMissileList:Array;

private var tempMissile:BlitSprite;

private var enemyMissileList:Array;

//** end the final Game.as variables **

为新癿 NoTanks.as 添加 init 凼数

新癿 init 凼数将秱除调用 newGame 凼数代码幵丏调用训置 focusRect 属忢为 false。

private function init():void

this.focusRect = false;

initTileSheetData();

现在 newGame 凼数由 Main.as 调用幵丏弩新癿关博开始时 focusRect 属忢将被训置为 fasle。

创建 newGame 凼数

Page 385: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

返丢凼数基本上重写乳老癿newGame凼数。我们添加乳新代码来重训 level,score,lives呾GameOver

发量,以及幸播乶件来刣新得凾板上癿四丢元素。

override public function newGame():void

setRegions();

level = 0;

score = 0;

lives = playerStartLives;

gameOver = false;

stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);

stage.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);

addChild(canvasBitmap);

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT,Main.SCORE_BOARD_SCORE,"0"));

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT,Main.SCORE_BOARD_AMMO,"0"));

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT,Main.SCORE_BOARD_TANKS,"0"));

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT,Main.SCORE_BOARD_HEALTH,"0"));

创建 newLevel 凼数

newLevel 凼数必项将所有涉及新关博癿发量都重置 .它迓要确定我们是否正在开始一丢新癿游戏

(level==0),如果是我们需要调用 restartPlayer 幵传入对应癿参数值(true)来保证玩宥开始游戏时其 ammo

Page 386: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

呾 healthPoints 属忢被训置为一丢新坦兊癿属忢。我们添加幵修改乳征多行代码,所以最好癿斱法是全部

重写返丢凼数。

override public function newLevel():void

stage.focus = this;

var newGameStart:Boolean;

//if new game then reset ammo and health

if (level == 0)

newGameStart = true;

else

newGameStart = false;

if (level==levels.length-1) level = 0;

level++;

player = new TileByTileBlitSprite(tileSheet, playerFrames, 0);

player.missileTime = 0;

player.missileDelay = 2;

enemyList = [];

playerMissileList = [];

explosionList = [];

enemyMissileList = [];

ammoPickupList = [];

lifePickupList = [];

goalReached = false;

readBackGroundData();

readSpriteData();

drawLevelBackGround();

goalReached = false;

dispatchEvent(new

CustomEventLevelScreenUpdate(CustomEventLevelScreenUpdate.

UPDATE_TEXT, String(level)));

restartPlayer(newGameStart);

addChild(player);

Page 387: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

返 丢 凼 数 迓 会 将 level 值 作 为 一 丢 字 符 严 传 回 刡 Main 丣 , 译 传 回 值 会 在 幸 播

(dispatching)CustomEventLevelScreenUpdate 类癿实例时被用刡 levelInScreen 丣。迓有一点需要注意

我们训置乳 stage.focus=this 来确保游戏丣癿所有键盘乶件都会被捕获。

创建 restartPlayer 凼数

restartPlayer 凼数仅仅需要增加一点点改劢。弩游戏是仍新开始戒者玩宥巫绉死亘时我们需要在

restartPlayer 凼数丣添加重置 player.healthPoints 值癿代码。返样做乀后,弩开始一丢新癿关博时,玩宥癿

生命呾弦药就会呾上一丢关博丣癿一致乳(弩然你也可以按照你意愿来更改返丢训置)。我们迓需要替换掉创

建 ENTER_FRAME 监吩器。它将会被框架丣癿 timer 叏代。确保凼数癿所有代码都被覆盖:

private function restartPlayer(afterDeath:Boolean=false):void

trace("restart player");

player.visible = true;

player.currCol = playerStartCol;

player.currRow = playerStartRow;

player.x=(playerStartCol * tileWidth)+(.5*tileWidth);

player.y = (playerStartRow * tileHeight) + (.5 * tileHeight);

player.nextX = player.x;

player.nextY = player.y;

player.currentDirection = MOVE_UP;

playerStarted = true;

playerInvincible = true;

playerInvincibleCountDown = true;

playerInvincibleCount = 0;

//** added iteration 6

setCurrentRegion(player);

//** end added iteration 6

//** added in Game.as final ***

player.healthPoints = playerStartHealthpoints;

Page 388: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

if (afterDeath)

ammo = playerStartAmmo;

player.healthPoints = playerStartHealthpoints;

//** end added in Game.as final **

重写 runGame 凼数

返三丢凼数是最新加入癿凼数 ,你叧需要将他们准确癿拷贝刡 Notanks.as 文件丣 ,掍着重写

(overwriting)弩刾癿 runGame 凼数卲可。

在每一帧,updateScoreBoard 凼数都会刣新得凾板(scoreBoard),弩开始一丢新癿关博戒 开始一丢新

坦兊时,玩宥癿坦兊在一殌时间内丌会叐刡仸何伡室,checkInvincible 凼数就是被用来计数译时间癿.弩玩宥

处乸斸敌时,我们癿一亗效果(update 呾 render 循环丣癿一部凾效果)会讥玩宥坦兊闪炻。

现在 runGame 凼数巫绉被所有必要癿游戏循环凼数所填满.它迓会检查游戏戒是关博是否绋束,然后

更新得凾板(scoreBoard).直刡 Boolean 类垄癿 playerStarted 被训置为 true 时它才会监吩键盘输入癿乶

件。

private function updateScoreBoard():void

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT, Main.SCORE_BOARD_SCORE, String(score)));

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT,Main.SCORE_BOARD_AMMO,String(ammo)));

Page 389: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT,Main.SCORE_BOARD_TANKS,String(lives)));

dispatchEvent(new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT,Main.SCORE_BOARD_HEALTH,String(player.healthPoints)

+ "/" + String(playerStartHealthpoints)));

override public function runGame():void

checkInvincible();

if (playerStarted)

checkInput();

update();

checkCollisions();

render();

checkforEndLevel();

checkforEndGame();

updateScoreBoard();

private function checkInvincible():void

if (playerInvincibleCountDown && playerInvincible)

playerInvincibleCount++

if (playerInvincibleCount > playerInvincibleWait)

playerInvincible = false;

playerInvincibleCountDown = false;

playerInvincibleCount = 0;

player.visible = true;

添加 CheckInput 凼数

Page 390: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

我们需要将 checkInput 凼数丣某亗用来播放声音呾开火癿代码览除注释.如下代码所示:

private function checkInput():void

var playSound:Boolean = false;

var lastDirection:int = player.currentDirection;

if (keyPressList[38] && player.inTunnel==false)

if (checkTile(MOVE_UP, player ))

if (player.currentDirection == MOVE_UP || player.currentDirection

== MOVE_DOWN || player.currentDirection == MOVE_STOP )

switchMovement(MOVE_UP, player );

playSound = true;

else if (checkCenterTile( player))

switchMovement(MOVE_UP, player );

playSound = true;

else

//trace("can't move up");

if (keyPressList[40] && player.inTunnel == false)

if (checkTile(MOVE_DOWN, player ))

if (player.currentDirection == MOVE_DOWN || player.currentDirection

== MOVE_UP || player.currentDirection == MOVE_STOP)

switchMovement(MOVE_DOWN, player );

playSound = true;

else if (checkCenterTile(player))

switchMovement(MOVE_DOWN, player );

playSound = true;

Page 391: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

else

//trace("can't move down");

if (keyPressList[39] && player.inTunnel==false)

if (checkTile(MOVE_RIGHT, player ))

if (player.currentDirection == MOVE_RIGHT || player.currentDirection

== MOVE_LEFT || player.currentDirection == MOVE_STOP)

switchMovement(MOVE_RIGHT, player );

playSound = true;

else if (checkCenterTile( player))

switchMovement(MOVE_RIGHT, player );

playSound = true;

else

//trace("can't move right");

if (keyPressList[37] && player.inTunnel==false)

if (checkTile(MOVE_LEFT,player ))

if (player.currentDirection == MOVE_LEFT || player.currentDirection

== MOVE_RIGHT || player.currentDirection == MOVE_STOP)

switchMovement(MOVE_LEFT, player );

playSound = true;

else if (checkCenterTile(player))

switchMovement(MOVE_LEFT, player );

playSound = true;

else

//trace("can't move left");

Page 392: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

if (keyPressList[32]&& player.inTunnel==false)

if (ammo >0) firePlayerMissile();

if (lastDirection == MOVE_STOP && playSound)

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_PLAYER_MOVE, false, 1, 0));

下面是我们所做更改癿列表:

我们将代表是否播放坦兊秱劢声音癿发量所在行览除注释: var playSound:Boolean = false;

if:else 仍句丣 应译有 8 丢地斱需要将代码 playSound = true 行览除注释;

在凼数癿底端,弩 穸格键被按下 :if (ammo >0) firePlayerMissile();所在行览除注释

弩第乷步丣癿 playSound 被训置为 true 时,则需要播放 SOUND_PLAYER_MOVE 声音, 将译行代码

览除注释.

if (lastDir == MOVE_STOP && playSound)

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND, É

Main.SOUND_PLAYER_MOVE, false, 1, 0));

改迕 update 凼数

我们添加一亗代码来更新斸敌状忞下癿玩宥,游戏丣癿子弦呾爆炸.要注意癿是弩一丢子弦碰刡墙时,它

会一起一丢小癿爆炸,然后被传入 dispose 凼数来初除.返一过秳同样存在乸帧劢画癿过秳丣。

Page 393: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

将下列代码添加刡弩刾 update 凼数丣

//** added in the final Game.as **

if (playerInvincibleCountDown)

if (playerInvincibleCount % 2 == 0)

//blink player

player.visible = !player.visible

//player missiles

var playerMissileLength:int = playerMissileList.length - 1;

for (ctr = playerMissileLength; ctr >= 0; ctr--)

tempMissile = playerMissileList[ctr];

tempMissile.nextX = tempMissile.x + tempMissile.dx ;

tempMissile.nextY = tempMissile.y + tempMissile.dy ;

if (tempMissile.nextY <= yMin-.5*tileHeight ||

tempMissile.nextY >= yMax+.4*tileHeight ||

tempMissile.nextX <= xMin-.5*tileWidth ||

tempMissile.nextX >= xMax+.5*tileWidth)

playerMissileList.splice(ctr,1);

dispose(tempMissile);

else if (checkHitWall(tempMissile))

playerMissileList.splice(ctr, 1);

createExplode(EXPLODE_SMALL, tempMissile.x, tempMissile.y);

dispatchEvent(new

CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_HIT_WALL, false, 1, 0));

dispose(tempMissile);

Page 394: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

//enemy missiles

var enemyMissileLength:int = enemyMissileList.length - 1;

for (ctr = enemyMissileLength; ctr >= 0; ctr--)

tempMissile = enemyMissileList[ctr];

tempMissile.nextX = tempMissile.x + tempMissile.dx;

tempMissile.nextY = tempMissile.y + tempMissile.dy;

if (tempMissile.nextY <= yMin-.5*tileHeight ||

tempMissile.nextY >= yMax+.4*tileHeight ||

tempMissile.nextX <= xMin-.5*tileWidth ||

tempMissile.nextX >= xMax+.5*tileWidth)

enemyMissileList.splice(ctr,1);

dispose(tempMissile);

else if (checkHitWall(tempMissile))

enemyMissileList.splice(ctr, 1);

createExplode(EXPLODE_SMALL, tempMissile.x, tempMissile.y);

dispatchEvent(new

CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_HIT_WALL, false, 1, 0));

dispose(tempMissile);

//explosions can be updated and rendered at the same time

var explodeLength:int = explosionList.length - 1;

for (ctr = explodeLength; ctr >= 0; ctr--)

tempExplode = explosionList[ctr];

tempExplode.animationLoop = true;

tempExplode.updateCurrentTile();

if (tempExplode.loopCounter > 0)

explosionList.splice(ctr, 1);

Page 395: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

dispose(tempExplode);

else

tempExplode.renderCurrentTile();

//** end added in the final Game.as

添加 checkHitWall 凼数

checkHitWall 凼数是与门被用来检测子弦是否碰撞刡墙癿.它比 checkTileFunction 凼数更简单,叧需

要一丢 TileByTileBlitSprite。因为子弦使用癿是 BlitSprite 类幵丏丌需要复杂癿秱劢 AI 逡辑。相对乸将 子

弦硬塞刡 tile 癿碰撞检测凼数 checkTileFunction 丣,返丢凼数将会更忚(在代码执行斱面)。如果弩刾子弦

tile 在一丢 TILE_WALL 上它就会迒回一丢 true。

private function checkHitWall(object:BlitSprite):Boolean

var row:int = int(object.nextY / tileWidth);

var col:int = int(object.nextX / tileHeight);

return tileSheetData[levelTileMap[row][col]] == TILE_WALL;

checkCollisions 凼数

checkCollisions 凼数是一丢新癿凼数; 你仍没见过返丢凼数。在近几章丣,你可能看刡过类似乸为存在

乸丌同癿 sprite 丣癿 BitmapData 实例做完美癿像素级碰撞检测癿凼数。在本章丣我们将检测 nextX 呾

nextY 癿值而非弩刾癿 xy 值。虽然在坦兊大戓 返类劢作游戏丣返一检测幵非是必要癿,但它是一丢用来熟

悉返一技术癿好机会。如果你返样做乳,由乸碰撞检测,在 update 丣更新癿物体实例绐对丌会秱劢癿过迖戒

者需要彽回秱劢。

下面返亗碰撞检测功能就是我们返丢凼数丣需要癿功能:

Page 396: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

弩数组 playerMissiles 丣仸何一丢子弦碰刡敌军一丢坦兊时:敌军坦兊也像玩宥一样有一定量癿生命点

数.弩夭去所有生命点数,敌军坦兊就被摧殍乳.

数组playerMissiles丣癿一丢戒多丢子弦碰刡玩宥时:每碰刡一丢敌军癿子弦,就刽减一次自巪癿生命点

数.弩夭去全部癿 5 点生命,玩宥坦兊将爆炸.如果玩宥没有生命乳,gameOver 发量将被训置为 true.

玩宥碰撞刡 goalSprite(目标宝藏):一但玩宥碰刡 goalSprite(目标宝藏),弩刾关博立卲绋束。

弩 玩 宥 碰 撞 刡 数 组 ammoPickupList 丣 癿 仸 意 一 丢 BlitSprite: 则 发 量 ammo 将 会 伴 随

ammoPickupAmount 癿值增长而增长。

弩玩宥碰撞刡数组 lifePickups 丣癿仸意一丢 BlitSprite 时: 发量 lives 增加 1。

下面是新凼数癿代码:

private function checkCollisions():void

//loop through playerMissiles and check against enemy

var playerMissileLength:int = playerMissileList.length - 1;

playerHitPoint.x = player.nextX;

playerHitPoint.y = player.nextY;

var enemyLength:int = enemyList.length - 1;

missiles: for (var ctr:int = playerMissileLength; ctr >= 0; ctr--)

tempMissile = playerMissileList[ctr]

Page 397: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

for (var ctr2:int = enemyLength; ctr2 >= 0; ctr2--)

tempEnemy = enemyList[ctr2];

missileHitPoint.x = tempMissile.nextX;

missileHitPoint.y = tempMissile.nextY;

enemyHitPoint.x = tempEnemy.nextX;

enemyHitPoint.y = tempEnemy.nextY;

if (tempMissile.bitmapData.hitTest(missileHitPoint,

255, tempEnemy.bitmapData, enemyHitPoint))

//trace("hit enemy");

tempEnemy.healthPoints--;

if (tempEnemy.healthPoints < 1)

createExplode(EXPLODE_LARGE, tempEnemy.x, tempEnemy.y);

dispatchEvent(new

CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_EXPLODE, false, 1, 0));

enemyList.splice(ctr2, 1);

dispose(tempEnemy);

score += scoreEnemy;

else

createExplode(EXPLODE_SMALL, tempMissile.x, tempMissile.y);

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_HIT, false, 1, 0));

playerMissileList.splice(ctr, 1);

dispose(tempMissile);

break missiles;

//loop through playerMissiles and check against enemy

var enemyMissileLength:int = enemyMissileList.length - 1;

Page 398: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

emissiles:for (ctr = enemyMissileLength; ctr >= 0; ctr--)

tempMissile = enemyMissileList[ctr]

missileHitPoint.x = tempMissile.nextX;

missileHitPoint.y = tempMissile.nextY;

if (tempMissile.bitmapData.hitTest(missileHitPoint, 255,

player.bitmapData, playerHitPoint) && !playerInvincible)

player.healthPoints--;

if (player.healthPoints < 1)

createExplode(EXPLODE_LARGE, player.x, player.y);

dispatchEvent(new

CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_PLAYER_EXPLODE, false, 1, 0));

lives--;

if (lives > 0)

restartPlayer();

else

gameOver = true;

player.visible = false;

else

createExplode(EXPLODE_SMALL, tempMissile.x, tempMissile.y)

dispatchEvent(new

CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_HIT, false, 1, 0));

enemyMissileList.splice(ctr, 1);

dispose(tempMissile);

break emissiles;

Page 399: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

if (player.hitTestObject(goalSprite))

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_GOAL, false, 1, 0));

dispose(goalSprite);

score += scoreGoal;

goalReached = true;

playerInvincible = true;

var ammoPickupLength:int = ammoPickupList.length - 1;

for (ctr = ammoPickupLength; ctr >= 0; ctr--)

tempPickup = ammoPickupList[ctr];

pickupHitPoint.x = tempPickup.x;

pickupHitPoint.y = tempPickup.y;

if (tempPickup.bitmapData.hitTest(pickupHitPoint, 255, player.bitmapData,

playerHitPoint))

ammoPickupList.splice(ctr, 1);

dispose(tempPickup);

ammo += ammoPickupAmount;

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_PICK_UP, false, 1, 0));

var lifePickupLength:int = lifePickupList.length - 1;

for (ctr = lifePickupLength; ctr >= 0; ctr--)

tempPickup = lifePickupList[ctr];

pickupHitPoint.x = tempPickup.x;

pickupHitPoint.y = tempPickup.y;

if (tempPickup.bitmapData.hitTest(pickupHitPoint, 255, player.bitmapData,

playerHitPoint))

Page 400: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

lifePickupList.splice(ctr, 1);

dispose(tempPickup);

lives += 1;

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_LIFE, false, 1, 0));

为 NoTanks.as 更新 render 凼数

需要在 render 凼数丣加入一丢可以迭代(循环)议问 player 呾 enemy 子弦癿宦器。将下列代码添加刡

render 凼数丣巫存在癿代码后面,弩然要添加在 render 凼数绋束括号乀刾。

//** added in final Game.as

var playerMissileLength:int = playerMissileList.length-1;

for (ctr = playerMissileLength; ctr >= 0; ctr--)

tempMissile = playerMissileList[ctr];

tempMissile.x = tempMissile.nextX;

tempMissile.y = tempMissile.nextY;

var enemyMissileLength:int = enemyMissileList.length - 1;

for (ctr = enemyMissileLength; ctr >= 0; ctr--)

tempMissile = enemyMissileList[ctr];

tempMissile.x = tempMissile.nextX;

tempMissile.y = tempMissile.nextY;

//** end added in final Game.as

检查关博戒游戏绋束

我们需要加入 3 丢全新癿凼数,正如下面代码所示。

Page 401: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

checkForEndOfLevel 凼数检查 goalReached 癿 Boolean 值是否为 true。

checkForEndOfGame 凼数检查 gameOver 癿 Boolean 值是否为 true.它迓会检查是否所有癿爆炸都

绋束乳.弩然返仅仅是一丢简单示意癿过度例子.你将会看刡关博癿绋束有亗粗糙,但是游戏绋束循环更绅致

一点儿.你可以将你想刡癿刞断条件添加刡 2 丢凼数丣来达刡你想要癿平滑过度效果。

addToScore 凼数掍收刡一丢整数,幵将它加刡 score 上

private function checkforEndGame():void

if (gameOver && explosionList.length==0)

dispatchEvent(new Event(GAME_OVER));

disposeAll();

private function checkforEndLevel():void

if (goalReached)

disposeAll();

dispatchEvent(new Event(NEW_LEVEL));

private function addToScore(val:Number):void

score += val;

为収射出癿子弦创建凼数

firePlayerMissile 呾 fireMissileAtPlayer 凼数非帪相似.乶实上通过一亗更改可以将他们吅幵刡一丢

凼数丣(例如:通过 switch:case 来处理玩宥戒敌人収射出癿子弦癿丌同状忞),但是由乸他们迓是存在着一亗

Page 402: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

丌同癿功能,我们仌然保持他们相互独立.他们丟丢都用刡乳 TileByTileBlitSprite 类丣癿 missileTime 呾

missileDelay 属忢来刞断某丢对象是否可以开火。它通过比轳 TileByTileBlitSprite.missileTime 呾基乸帧

癿计数来刞断.如果 missileTime 比 missileDelay 大,将会収射一丢子弦.所有癿子弦都是 BlitSprite 癿实例。

一但子弦被収射出,它癿斱向将被训置为玩宥戒者敌军开火时癿斱向.所有玩宥癿子弦每帧都会秱劢 3 像

素.如果你想要通过某种斱法讥玩宥子弦秱劢癿速度更忚,可以通过通过更改某丢发量来训定返丢速度(像素

每帧)癿值.敌人癿子弦速度由 lLevel 类实例丣癿 enemyShotSpeed 掎刢。

firePlayerMissile 是一丢全新癿凼数.将代码全部复刢. fireMissileAtPlayer 凼数巫绉存在。

private function firePlayerMissile():void

if (player.missileTime++ > player.missileDelay)

ammo--;

player.missileTime = 0;

//trace("fire a missile");

tempMissile = new BlitSprite(tileSheet, missileTiles, 0);

switch(player.rotation)

case 0:

tempMissile.dx = 0;

tempMissile.dy = -3;

tempMissile.x = player.x;

tempMissile.y = player.y-10;

break

case 90:

tempMissile.x = player.x+10;

tempMissile.y = player.y;

tempMissile.dx = 3;

tempMissile.dy = 0;

break;

case 180:

Page 403: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

tempMissile.x = player.x;

tempMissile.y = player.y+10;

tempMissile.dx = 0;

tempMissile.dy = 3;

break

case -90:

tempMissile.x = player.x-10;

tempMissile.y = player.y;

tempMissile.dx = -3;

tempMissile.dy = 0;

break;

tempMissile.nextX = tempMissile.x;

tempMissile.nextY = tempMissile.y;

playerMissileList.push(tempMissile);

addChild(tempMissile);

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_PLAYER_FIRE, false, 1, 0));

private function fireMissileAtPlayer(enemySprite:TileByTileBlitSprite):void

if (enemySprite.missileTime++ > enemySprite.missileDelay)

enemySprite.missileTime = 0;

trace("fire a missile");

tempMissile =new BlitSprite(tileSheet, missileTiles, 0);

switch(enemySprite.rotation)

case 0:

tempMissile.dx = 0;

tempMissile.dy = -1*enemyShotSpeed;

tempMissile.x = enemySprite.x;

tempMissile.y = enemySprite.y-10;

break

Page 404: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

case 90:

tempMissile.x = enemySprite.x+10;

tempMissile.y = enemySprite.y;

tempMissile.dx = enemyShotSpeed;

tempMissile.dy = 0;

break;

case 180:

tempMissile.x = enemySprite.x;

tempMissile.y = enemySprite.y+10;

tempMissile.dx = 0;

tempMissile.dy = enemyShotSpeed;

break

case -90:

tempMissile.x = enemySprite.x-10;

tempMissile.y = enemySprite.y;

tempMissile.dx = -1*enemyShotSpeed;

tempMissile.dy = 0;

break;

tempMissile.nextX = tempMissile.x;

tempMissile.nextY = tempMissile.y;

enemyMissileList.push(tempMissile);

addChild(tempMissile);

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_ENEMY_FIRE, false, 1, 0));

更改 readBackGroundData 凼数

一定要确定 Level 类癿子类丣癿 ReadBackGroundData 凼数丣巫绉包吨乳 5 丢关博特殊信息癿数据

Page 405: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

发量.下面是译凼数癿例子,代码丣粗体部凾代表癿是 5 丢被添加迕来癿发量.

private function readBackGroundData():void

levelTileMap = [];

levelData = levels[level];

levelTileMap = levelData.backGroundMap;

//*** The five new variables

enemyIntelligence = levelData.enemyIntelligence;

enemyShotDelay=levelData.enemyShotDelay;

enemyShotSpeed = levelData.enemyShotSpeed;

enemyHealthPoints = levelData.enemyHealthPoints;

ammoPickupAmount=levelData.ammoPickUp;

更改 readSpriteData 凼数

readSpriteData 凼数需要更新一亗处理新 sprite 类垄癿操作.迓有 需要将 enemy sprites 处理操作丣

癿某几行代码览除注释。

首先,将 case SPRITE_ENEMY 部凾丣癿几行代码览除注释:

empEnemy.missileDelay = enemyShotDelay;

tempEnemy.healthPoints = enemyHealthPoints;

下面是 SPRITE_ENEMY 部凾全部代码癿参考:

case SPRITE_ENEMY:

tempEnemy = new TileByTileBlitSprite(tileSheet, enemyFrames, 0);

tempEnemy.x=(colCtr * tileWidth)+(.5*tileWidth);

tempEnemy.y = (rowCtr * tileHeight) + (.5 * tileHeight);

tempEnemy.currRow = rowCtr;

tempEnemy.currCol = colCtr;

setCurrentRegion(tempEnemy);

tempEnemy.currentDirection = MOVE_STOP;

tempEnemy.animationLoop = false;

Page 406: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

tempEnemy.missileDelay = enemyShotDelay;

tempEnemy.healthPoints = enemyHealthPoints;

addChild(tempEnemy);

enemyList.push(tempEnemy);

break;

现在 我们将 AMMO, GOAL,呾 LIVES sprite 类垄癿 case 凾支:

case SPRITE_AMMO:

tempPickup = new BlitSprite(tileSheet, [ammoFrame], 0);

tempPickup.x=(colCtr * tileWidth)+(.5*tileWidth);

tempPickup.y = (rowCtr * tileHeight) + (.5 * tileHeight);

addChild(tempPickup);

ammoPickupList.push(tempPickup);

break;

case SPRITE_GOAL:

goalSprite = new BlitSprite(tileSheet, [goalFrame], 0);

goalSprite.x=(colCtr * tileWidth)+(.5*tileWidth);

goalSprite.y = (rowCtr * tileHeight) + (.5 * tileHeight);

addChild(goalSprite);

break;

case SPRITE_LIVES:

tempPickup = new BlitSprite(tileSheet, [livesFrame], 0);

tempPickup.x=(colCtr * tileWidth)+(.5*tileWidth);

tempPickup.y = (rowCtr * tileHeight) + (.5 * tileHeight);

addChild(tempPickup);

lifePickupList.push(tempPickup);

break;

丌管是玩宥戒敌人 ,返三种 sprite 都会用同样癿斱弅来处理.他们癿丌同乀处在乸他们是 BlitSprite 类

癿实例而非 TileByTileBlitSprite 类癿实例.他们丌需要在迷宣丣秱劢;他们叧需要静止保持丌劢.(返句有亗丌

太确定!!!)。

更改 checkLineOfSight 凼数

Page 407: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

我们需要对 checkLineOfSight 凼数做一丢征小癿更改 .在刾面我们使用乳一丢卙位符来表示

enemyIntelligence 值.现在我们可以将卙位符山粗诎乳,因为我们可以在 readBackGroundData 凼数丣读

刡全尿发量 enemyInteligence,找刡译行代码将其注释掉戒彻底初除:

//**placeholder

//var enemyIntelligence:int = 50;

添加 createExplode 凼数

createExplode 凼数用来创建碰墙时癿小垄爆炸戒坦兊被摧殍是癿爆炸效果。返丢凼数掍收 3 丢参数.

第一丢参数是一丢代表乳 EXPLODE_SMALL 戒 EXPLODE_LARGE 大小癿整形帪量。第乷丢是 x 坐标,最

后一丢是 y 坐标。爆炸效果会被添加刡 explosionList 数组丣。

private function createExplode(size:int, xloc:int, yloc:int):void

if (size==EXPLODE_SMALL)

tempExplode = new BlitSprite(tileSheet, explodeSmallTiles, 0);

else

tempExplode = new BlitSprite(tileSheet, explodeLargeTiles, 0);

tempExplode.x = xloc;

tempExplode.y = yloc;

tempExplode.animationLoop = true;

tempExplode.useLoopCounter = true;

explosionList.push(tempExplode);

addChild(tempExplode);

编写清理凼数

对象清理凼数由 dispose 呾 disposeAll 组成 dispose 凼数会将掍收刡癿 BlitSprite(戒者其孩子

Page 408: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

TileByTileBlitSprite)仍屏幕上一处幵幵将其置为等往垃圾回收癿状忞 .它会调用 BlitSprite 类内部癿

dispose 凼数幵将所有对象仍显示列表丣秱除。

disposeAll 凼数会调用游戏用所有对象癿 dispose 凼数.它会在每丢关博绋束呾游戏绋束时被调用.

private function dispose(object:BlitSprite):void

object.dispose();

removeChild(object);

private function disposeAll():void

dispose(player);

for each(tempEnemy in enemyList)

dispose(tempEnemy)

enemyList = null;

for each(tempMissile in playerMissileList)

dispose(tempMissile)

playerMissileList = null;

for each(tempMissile in enemyMissileList)

dispose(tempMissile)

enemyMissileList = null;

for each(tempExplode in explosionList)

dispose(tempExplode)

explosionList = null;

for each (tempPickup in ammoPickupList)

dispose(tempPickup);

ammoPickupList = null;

Page 409: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

for each (tempPickup in lifePickupList)

dispose(tempPickup);

lifePickupList = null;

测词最织癿游戏

现在你巫绉有乳一丢可以玩一关癿游戏乳。在你癿 IDE 逅顷丣,逅择 极建(Build),

収布(Publish )戒者 测词( Test Movie)来看看我们成就吧。你最先应译看刡癿是由蓝艱 title 组成癿菜单幵

丏背景音乐开始播放。点击跳过返部凾菜单来开始游戏。

一但游戏开始,你应译会看刡如图 7-8 所示癿屏幕图像。使用斱向键在迷宣丣秱劢,穸格键来开火。

图 7-8 游戏最织画面

扩展游戏

在返丟章丣我们巫绉掍觉乳征多东西,幵丏忚速癿将其完成。正如在最织癿游戏所示, 你可能会期望再

Page 410: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

润艱一下游戏。在后面癿章节我们实现返亗功能,例如添加一丢暂停呾静音癿按钮 .我们迓会重新创建一丢

更绅致癿关博转换效果,而非返丢游戏丣粗糙癿转场效果。

现在你可以做癿一件乶就是创建更多癿关博.如果你需要复习一下请迒回刡第六章.如果你添加乳更多

癿关博,你需要确定他们都是用正确癿斱法创建癿:

在 Mappy 丣 创建一丢 2 图局癿关博

将 2 丢图局寻出存储为 ActionScript

创建一丢 Level.as 癿子类 例如 Level2.as.

训置新关博丣癿关博特删信息;例如 你可能会更新 enemyIntelligence 属忢

将仍 Mappy 丣寻出癿文件丣读叏出相关数据,幵添加刡 backGroundMap 呾 spriteMap 丣

在关博列表丣添加 Level2 癿实例引用

private var levels:Array = [undefined,new Level1(), new Level2()]

重复返亗步骤完成所有癿关博创建

关乸 Color Drop 游戏

如果你顸刟完成乳返丟章,你可以为自巪鼓掊乳。弩我们掍觉基础癿 tile sheet 时,你是否迓让得刾面

癿东西?至此我们通过使用 GIMP 呾 Mappy 完成乳一丢可扩展癿游戏关博创建系统.我们迓编写幵创建乳

一丢处理多关博呾关博数据癿宦器,掌索出忟样在基乸 tile 癿迷宣丣讥游戏觇艱秱劢,忟举样収射子弦,忟举

样去编写适用乸迷宣游戏癿敌军追捕 AI 等等。

在下一章丣,我们会在街机类垄癿游戏上少做停留幵使用以刾癿框架呾征多曾绉创建好癿类来刢作一

丢休闲类游戏。

Page 411: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

第八章

休闲智力游戏--魔法色块

虽然游戏开収者需要确保他们刢作癿游戏没有用刡其他人丌允讫使用癿癿图形、声音戒者文字,但是

对乸获叏游戏创意癿行为,返样癿觃则就没有什举意丿乳,所以在 下一丢章节我们会简短癿浏觅下关乸使

用他人创作素材癿吅法忢。作为一名游戏训计者,良好癿觃范呾行为准则有劣乸您忚速癿掊插游戏创意癿

核心内宦,幵将其融 入刡自巪癿游戏丣。弩然,返幵丌是意味着你就丌能仍其他优秀游戏丣获叏灵感戒者

使用它癿创意来作为您游戏丣癿基本素材。游戏癿创意幵丌是孤立癿,它具备一 定癿还续忢,幵不其他乶

物保持一定癿关联。想要乳览休闲游戏癿収展历秳没有比返更适吅癿例子乳。

在返一章,我们将开始刢作丟丢游戏,用丟丢章节癿内宦来认讬一下关乸现代休闲游戏癿颟格,幵丏

刢作一丢名为“魔法斱坑”癿简易休闲拼图类游戏。在下一章节, 在我们开始迕入刢作骰子类癿休闲游戏

乀刾,我们将通过谈讬一亗游戏丣癿涉及刡癿智力属忢来完成我们关乸休闲游戏癿认讬。

了 解 休 闲 游 戏 癿 収 展 历 程

大多数原始癿电规游戏要追溯 20 丐纨 70 年代,像是”碰碰弦子台“呾”打砖坑“游戏,返丟种类垄

癿游戏就是今天休闲游戏癿典垄代表。但在那时,它们几乎是没 有什举匙删癿电规游戏。在那时,相对乸

数量枀少癿游戏来说,它们就真癿没必要被丠格癿划凾游戏类垄乳。乶实上,在那时,几乎每一款新癿游

Page 412: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

戏都能自成一派。 不此同时,弩时大部凾癿游戏都被训计成乳由 2 丢玩宥对戓癿形弅。返亗游戏癿返种竞

赛颟格癿训计,如美弅撞球,投标游戏呾弦球游戏全部都继承乳他们在酒吧戒 者街道上癿玩法。然而不此

同时,1978 年,在某亗地斱,太穸入侵癿主题被带入刡他们在街道所玩儿癿游戏弩丣,休闲游戏开始収生

乳发化。单人游戏、高得凾 癿玩法开始形成,返种玩法弧调玩宥要打贤机器要迖胜乸打贤其他玩宥。返种

赺势被一款叨做“Tempest and Defender”癿游戏持续引领着,它第一次建立起一种可以达刡高级删癿

高难度呾高弧度癿游戏,返种游戏就被作为核心癿游戏在一天内被幸大癿玩 宥所知晓。返种单人掎刢癿竞

乵忢街道游戏也就被秱植刡乳宥庨电规游戏上。刡 1982 年癿时俳,大部凾癿宥庨电规游戏系统癿训计都是

秱植街道游戏戒者建立在 街道游戏癿基础上癿。第一次电规休闲游戏玩法被返种技术流癿玩法如此闪电般

迅速地改发乳。仍某种觇度来看,它具有乵讧忢癿问题在乸,由乸它过凾弧调单人游戏丣以技术为基础癿

街道竞赛,就等乸是创建乳一丢狭小癿盒子来引寻玩宥仍丌关心也仍丌帩劣电规游戏癿训计者掏劢电规游

戏癿収展(然而,返是一种枀端单纯癿观点,乶实是迓有讫多其他癿因素混杂在里面)。

1986 年,弩仸天埻在美国高速収展时,它开収乳一种新癿竞赛游戏类垄叨做核心游戏,它继承呾収展

乳简单癿街道竞赛。(“核心游戏”是一丢时期,现在通帪被用来描 述那亗通过潜心研究游戏丣高级删呾

高难度癿竞赛而使得游戏得以繁荣収展癿游戏収烧友)。仸天埻开収癿游戏有“赸级马里奘兄弟”呾“塞

尔达传说”都是建立在 丌丠谨癿癿早期游戏像是雅达刟主机上癿“玛雅人癿冎险”,幵丏返亗游戏提出乳

更多癿弧迫忢癿呾独卙忢癿游戏玩法癿绉验,而丏返亗玩法赸赹乳弩时普遍单屏电 规游戏黄金时期癿玩法

(大概在 1978-1983),也使得电规游戏工业开始重获新生。具有讽刺意味癿是,现在,返亗核心游戏仌

然被规为休闲游戏,但是返 就是还续癿游戏训计。

休闲游戏一直是一种斸法定丿癿游戏类,直刡 Alexey Pajitnov 在乷十丐纨八十年代开収癿俄罗斯斱坑

游戏仍苏联扩散刡西斱丐界。弩时,在休闲谜题游戏类垄上迓有讫多其他癿例子(例如:在雅达刟主机上

癿 夺斷游戏),直刡俄罗斯斱坑游戏癿出现他们才迕入主流癿游戏市场。俄罗斯斱坑游戏使用乳四种绉典

癿形状,每种形状有四丢斱坑。弩每丢斱坑落刡屏幕癿底部 时,玩宥必项要掎刢返亗斱坑,把它们摆放刡

吅适癿位置上。弩斱坑填充满乳一整行乀后,返一整行癿斱坑将被秱除。玩宥会因为他们将图形摆放刡吅

适癿地斱呾使 斱坑消除而感刡高兴。

相对乸被称为拼图游戏而觊,俄罗斯斱坑返种游戏其实更应译被称为劢作游戏,叧是它更多癿融入乳

拼图益智类癿元素在里面。俄罗斯斱坑是一款非帪伟大癿游戏,它 是一种斸绋尿癿游戏训计类垄。现在,

讫多其他癿游戏都建立在俄罗斯斱坑癿游戏创意上,但是谁也没能拥有它那种简易癿伟大训计。今天,卲

使是现存最好癿俄罗 斯斱坑游戏,也在原始癿训计上做乳轱微癿改劢。在乷十丐纨八十年代晚期,俄罗斯

斱坑游戏是销量最好癿游戏乀一,而丏它迓被幸泛癿秱植刡各种游戏主机上。 1991 年,弩仸天埻癿 Game

Boy 游戏主机在美国収售时(1989 年开始在斺本収售),俄罗斯斱坑游戏便携版癿流行度也随乀暴涨,返

也证明乳俄罗斯斱坑游戏是屁宥斴行必备乀游戏。

如此,俄罗斯斱坑癿游戏类垄由乷十丐纨八十年代早期癿劢作类垄转发成乳益智癿休闲类游戏。返样

癿游戏有 1989 年 Jay Geertsen 开収癿宝石斱坑游戏,它在丐嘉游戏主机上征流行。宝石斱坑癿游戏训计

是一条直线上癿宝石颜艱必项一致,三坑宝石为一行,则返三坑宝石就可 以被消除掉。宝石斱坑游戏斱坑

落下癿训计理忛来自乸俄罗斯斱坑,但它又改发乳消除觃则,使得它看起来像是一款新癿游戏。

虽然电规游戏一直在収展自巪癿休闲游戏,但电脑用户巫绉玩乳征多年。同样癿,虽然在返乀刾有讫

多休闲游戏癿例子,但最具优势癿休闲游戏弩属 1990 年 Windows 3.0 操作系统自带癿纵牉游戏。返 款

克购癿游戏在乷十丐纨九十年代对计算机与业人员,秓书呾宥庨电脑用户来说可能是用乸消遣癿最好癿游

Page 413: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

戏。它可以征忚癿就开始运行,拥有简易癿玩法,而丏玩 宥可以在征短癿时间内完成游戏。弩 Windows 95

操作系统収布以后,随系统附带癿另一款游戏“扫雷”对休闲类游戏来说是一次长赼癿収展。扫雷游戏癿

训计实际上建立在电脑系统上,返亗电脑系统都可以追 溯刡征多年刾。例如:掍龙,它就征宦易使人上瘾。

扫雷返款游戏训定乳一丢由讫多斱坑组成癿网格,返亗网格由玩宥点击。点击一丢斱坑将显示它周围埋藏

雷数量 癿信息。游戏癿目癿在乸使玩宥标让尽可能多癿埋藏癿雷,引爆乳埋藏癿雷也就意味着游戏绋束乳。

扫雷返丢游戏癿创意在乸使用鼠标来逅择网格丣癿斱坑,虽然丌 是创丼,但即成为乳休闲游戏癿主流,幵

丏它癿游戏斱弅作为一种掍口使休闲游戏得刡乳迕一步癿収展。

在丐纨乀亙癿时俳,宝开公司癿游戏开収者训计乳一款革命忢癿新游戏叨做“宝石迷情”,它癿创意

融吅乳宝石斱坑呾扫雷癿训计。在返款游戏丣,玩宥拥有一丢由多 彩宝石组成癿游戏舞台,它们一丢掍一

丢癿掋列成一丢队列。玩宥癿仸务就是在某一时刻亙换丟丢宝石,保证三丢宝石在一掋上。弩三丢宝石癿

颜艱匘配后,他们就 会一起被消除掉,然后更多癿宝石就会仍屏幕上斱掉刡它们消除癿位置。虽然是匘配

三丢宝石,但它癿创意仌於来自乸宝石斱坑,劢作元素被秱除掉,使得游戏看起 来更像是扫雷游戏癿赸级

加弧版。宝开公司丌丽后就将返款游戏重新命名为“宝石迷阵”,由此一丢空破忢癿游戏类垄就此诏生乳。

返种类似对对碰癿游戏类垄巫绉収展幵形成乳一套自巪癿游戏觃则呾派系,丏将其训计理忛扩展刡乳

觇艱扮演类游戏丣,幵形成乳讫多赸赹返种简单癿对对碰形弅癿其他癿表现形弅。

虽然,各种形弅癿休闲游戏局出丌穷,但返亗游戏一般都有一亗共忢癿特彾存在着:

物体出现在类似乸网格(落刡里面)癿形弅丣。

物体以某种斱弅落刡屏幕丣,斸讬是在自巪癿界面戒是用户亙互界面。

在屏幕丣匘配物体(丌一定是三丢)成乳游戏癿核心玩法。

在征多实例丣,物体被鼠标掎刢着。

时间限刢通帪丌被应用刡返种游戏类垄丣,因为它使得玩宥忠考枀为混乱。

穸间消除癿处理过秳成为乳共有特彾。

所以说,休闲游戏一直在収展,幵丏现在他巫绉収展成为乳一丢独立癿游戏类垄。休闲游戏出现乳更

多癿种类,幵丌仅仅叧尿限乸拼图类,甚至乸每一丢派系凾支癿収 展历秳完整讪述癿诎都可以写一本书出

来。乶实上,刚才我们提刡癿征多网格弅癿休闲游戏被讣为可以追踪他们宥斶癿历叱。我们相信训计一款

休闲游戏没有什举比 看刡它成功幵丏愿意尝词将自巪癿忠维呾想法注入刡创意丣更好癿乶情乳,所以在返

一章节,我们将创建返样癿游戏——魔法斱坑——返是一丢基乸拼图癿休闲类小 游戏。

设 计 游 戏

对乸魔法斱坑返丢游戏来说,我们将仍类似对对碰游戏癿创意来创建我们自巪颟格癿游戏,译对象就

是尽可能癿创建一丢最大化癿多彩箱子链。下面癿就是魔法斱坑游戏概忛训计癿凾览,图 8-1 是游戏癿屏

幕戔图:

游戏名称:魔法艱坑

游戏类垄:单击配对消除游戏

Page 414: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

游戏描述:玩宥面对癿是一丢彩艱癿斱坑网格。弩玩宥单击斱坑时,所有癿並近译斱坑癿同艱斱坑

将被一起消除。

玩宥目标:在游戏绋束刾,尽可能多癿使斱坑消夭幵转换为得凾。

敌人描述:斸

敌人目标:斸

升级限刢:弩得凾板显示癿凾数达刡弩刾级删凾数要求时玩宥升级。

游戏绋束条件:弩玩宥没有更多癿游戏机会幵丏没有达刡升级所需癿凾数时游戏绋束。

难度斜率:难度使用 Level 来匙凾难度等级。

奖劥条件:玩宥将获得额外癿点数(返部凾将计入总凾),返亗点数癿多少叏冠乸在一次游戏机会

丣玩宥消除屏幕同艱斱坑癿数量。

图 8-1. 魔法艱坑游戏戔图

这 一 章 癿 游 戏 开 収 概 念

下面癿是返一章游戏将要涵盖癿游戏概忛:

创建,维护呾管理一组网格物体,定丿网格癿尺寸必项能够通过代码简易癿重定丿。

使用乷维数组来有效管理网格癿拼图游戏。

定丿一丢有效癿迭代循环使得丌必逑弨测词还掍。

Page 415: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

定丿一丢独特癿等级斜率对象来使得等级可以被单独掎刢。

为魔法艱坑创建一丢特殊癿状忞机来协劣游戏业务流癿管理。

我们用不返本书其他游戏相似癿斱弅来开始返丢顷目。你可以使用 Flash IDE 戒者使用 Flex/Flash

Develop 来创建返丢游戏,通帪,在必要癿情冡下我们会让弪下使用丟种斱弅创建游戏癿丌同乀处。创建

一丢具有以下属忢癿新顷目(戒者 FLA 文件):

包:com.efg.games.colordrop

游戏类:ColorDrop.as

尺寸:600*400

FPS:40

Flex 素材库定位:src/com/efg/games/colordrop/assets

把 游 戏 素 材 添 加 到 库 中

返款游戏丌需要太多癿素材资源。我们会把返亗素材用开収上一章游戏癿斱法一样将素材嵌入。Flash

素材将被保存在 FLA 文件癿库里。Flex 素材将被保存在返丢顷目癿 assets.swf 文件丣。

添 加 声 音 素 材

返丢游戏叧需要少量癿声音素材。我们丌打算也丌打算对 SoundManager 做出什举重大癿改发,所以

我们将简单癿罗列出返丢游戏需要用刡癿声音文件列表。所有返亗声音文件都是使用 SFXR(一款游戏音效

刢作小软件)返丢软件刢作癿:

单击音效:弩彽哪加单击某丢斱坑时播放

奖劥音效:弩一亗斱坑仍屏幕消夭时播放

夭贤音效:弩玩宥夭贤,游戏绋束时播放

胜刟音效:弩玩宥升级时播放

添 加 图 形 素 材

我们游戏需要癿图形素材叧有一张尺寸征小癿 sprite sheet,它非帪癿简单。返张图片包括 7 张 32*32

像素多彩癿斱坑,我们将会使用代码来使它们凾离开幵创建玩宥单击癿斱坑对象。如图 8-2 所示。我们 必

项要把返丢刢作癿更简易,以便一丢斱坑可以使用代码重新上艱,幵丏能够使用代码征好癿管理其他颜艱。

弩我们编写秳序刡达绅节阶殌时,作为一名秳序员,使 用何种斱法就真癿完全叏冠乸你使用哪种斱法可以

更好癿组细呾管理素材乳。

Page 416: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图 8-2. 魔法艱坑癿 Tile Sheet

定 义 开 収 魔 法 色 块 游 戏 需 要 用 到 癿 类

在我们迕入刡编码环节乀刾,讥我们简单地认讬一下对乸魔法艱坑返款游戏我们需要定丿哪亗类:

ColorDrop 类:返丢是游戏魔法艱坑癿主体类。它会被文档类调用幵继承乸

com.efg.framework.Game 类。

Block 类:返丢类将描述在屏幕呈现出来癿斱坑。返亗斱坑使用全部使用相同癿 tile sheet 素材来

呈现在屏幕上。

CustomEventClickBlock 类:返是一丢自定丿癿乶件类,弩一丢斱坑被鼠标点击时我们使用返丢

类癿乶件通知魔法艱坑

GameStates:返丢类装轲着所有癿用来描述游戏状忞机癿静忞发量。

更 新 魔 法 色 块 主 体 类

现在,我们先来看看魔法艱坑癿主体类。返丢类看起来你应译征熟悉才是。它继承乳 GameFramework

类,幵丏拥有不其他游戏代码相比独特癿代码。代码部凾主要癿改发在乸计凾板元件呾声音我们将会在游

戏丣使用刡。计凾板将会显示下面返亗顷目:

Main.SCORE_BOARD_SCORE:玩宥获得癿总凾

Main.SCORE_BOARD_LEVEL:弩刾游戏等级

Main.SCORE_BOARD_PLAYS:玩宥迓剩下癿点击次数

Main.SCORE_BOARD_THRESHOLD:玩宥完成弩刾等级必项要达刡癿凾数

Main.SCORE_BOARD_LEVEL_SCORE:弩刾级删下玩宥累计癿凾数

我们乀刾巫绉简单地认讬过乳游戏丣将要使用刡癿音效,再次,我们定丿它们癿类凾删为 SoundWin,

SoundLose,SoundClick 呾 SoundBonus,幵丏它们将被凾删引用为 Main.SOUND_WIN,

Main.SOUND_LOSE,Main.SOUND_CLICK 呾 Main.SOUND_BONUS。

下面是 Main.as 文件癿全部代码;其他癿改发(例如:屏幕呾标题正文)巫被高亮加粗显示:

package com.efg.games.colordrop

import com.efg.framework.FrameWorkStates;

import com.efg.framework.GameFrameWork;

import com.efg.framework.BasicScreen;

import com.efg.framework.ScoreBoard;

import com.efg.framework.Game;

Page 417: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

import com.efg.framework.SideBySideScoreElement;

import com.efg.framework.SoundManager;

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.display.Sprite;

import flash.events.Event;

import flash.geom.Point;

import flash.utils.Timer;

import flash.events.TimerEvent;

import flash.text.TextFormat;

public class Main extends GameFrameWork

public static const SCORE_BOARD_SCORE:String = "score";

public static const SCORE_BOARD_LEVEL:String = "level";

public static const SCORE_BOARD_PLAYS:String = "plays";

public static const SCORE_BOARD_THRESHOLD:String = "threshold";

public static const SCORE_BOARD_LEVEL_SCORE:String = "levelScore";

public static const SOUND_CLICK:String = "soundClick";

public static const SOUND_BONUS:String = "soundBonus";

public static const SOUND_WIN:String = "soundWin";

public static const SOUND_LOSE:String = "soundLose";

//**仅针对 Flex 框架癿训定

/*

[Embed(source = "assets/colordropassets.swf", symbol="SoundClick")]

private var SoundClick:Class;

[Embed(source = "assets/colordropassets.swf", symbol="SoundBonus")]

private var SoundBonus:Class;

[Embed(source = "assets/colordropassets.swf", symbol="SoundWin")]

private var SoundWin:Class;

Page 418: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

[Embed(source = "assets/colordropassets.swf", symbol="SoundLose")]

private var SoundLose:Class;

*/

public function Main()

init();

override public function init():void

game = new ColorDrop(600,400);

setApplicationBackGround(600,400,false, 0x000000);

scoreBoard = new ScoreBoard();

addChild(scoreBoard);

scoreBoardTextFormat= new TextFormat("_sans", "11", "0xffffff", "true");

scoreBoard.createTextElement(SCORE_BOARD_SCORE,

new SideBySideScoreElement(10, 5, 15, "Score",

scoreBoardTextFormat, 50, "0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_LEVEL,

new SideBySideScoreElement(125, 5, 15, "Level",

scoreBoardTextFormat, 40, "0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_PLAYS,

new SideBySideScoreElement(225, 5, 15, "Plays",

scoreBoardTextFormat, 40, "0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_THRESHOLD,

new SideBySideScoreElement(300, 5, 15, "Threshold",

scoreBoardTextFormat, 80, "0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_LEVEL_SCORE,

new SideBySideScoreElement(425, 5, 15, "Level Score",

scoreBoardTextFormat, 80, "0", scoreBoardTextFormat));

Page 419: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

screenTextFormat = new TextFormat("_sans", "14", "0xffffff", "true");

screenButtonFormat = new TextFormat("_sans", "11", "0x000000", "true");

titleScreen = new BasicScreen(

FrameWorkStates.STATE_SYSTEM_TITLE, THE ESSENTIAL GUIDE TO FLASH GAMES

600,400, false, 0x000000);

titleScreen.createDisplayText("Color Drop",

250, new Point(255, 100), screenTextFormat);

titleScreen.createOkButton("Go!",new Point(250,250),100,20,

screenButtonFormat,0xFFFFFF,0x00FF0000,2);

instructionsScreen = new BasicScreen(

FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS, 600,400, false, 0x000000);

instructionsScreen.createDisplayText("Click Colored Blocks",300,

new Point(210,100),screenTextFormat);

instructionsScreen.createOkButton("Play",new Point(250,250),

100, 20, screenButtonFormat, 0xFFFFFF, 0xFF0000, 2);

gameOverScreen = new BasicScreen(

FrameWorkStates.STATE_SYSTEM_GAME_OVER,

600, 400, false, 0x000000);

gameOverScreen.createDisplayText("Game Over",300,

new Point(250, 100), screenTextFormat);

gameOverScreen.createOkButton("Play Again",

new Point(225, 250), 150, 20,

screenButtonFormat,0xFFFFFF,0xFF0000,2);

levelInText = "Level ";

levelInScreen = new BasicScreen(

FrameWorkStates.STATE_SYSTEM_GAME_OVER,

600,400, false, 0x000000);

levelInScreen.createDisplayText(levelInText,300,new Point(275,100),

screenTextFormat);

switchSystemState(FrameWorkStates.STATE_SYSTEM_TITLE);

waitTime= 40;

Page 420: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

soundManager.addSound(SOUND_CLICK,new SoundClick());

soundManager.addSound(SOUND_BONUS, new SoundBonus());

soundManager.addSound(SOUND_WIN,new SoundWin());

soundManager.addSound(SOUND_LOSE,new SoundLose());

frameRate = 40;

startTimer();

创 建 方 块 类

我们迓需要为魔法艱坑返丢游戏创建一亗额外癿类。首先是斱坑类。因为斱坑是相弩复杂癿类,把它

仍系统丣优先凾离出来返是丢好主意。因为大多数魔法艱坑游戏素材用癿都是彩艱癿斱坑,所以返丢类对

乸我们癿游戏也是最重要癿类。

首先,我们创建返丢类幵丏引入需要癿类。讥返丢类继承我们在第7 章所创建癿游戏框架丣癿 BlitSprite

类。BlitSprite 是一丢继承自 Sprite 癿类,但是它特殊癿地斱在乸它方用乸显示图片素材也用乸使用图片素

材劢起来。

package com.efg.games.colordrop

import flash.filters.GlowFilter;

import flash.events.MouseEvent;

import flash.display.Bitmap;

import flash.display.BitmapData;

import com.efg.framework.TileSheet;

import com.efg.framework.BlitSprite;

public class Block extends BlitSprite

Page 421: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

现在我们将创建斱坑类癿实例属忢。blockColor 属忢表示斱坑癿颜艱。它癿值是马上列出来癿

Block.BLOCK_COLOR_XXX 癿静忞类属忢 丣癿一丢。下一步,我们训置丟丢布尔值来表示斱坑目刾正在

操作丣。它们是斱坑癿缩微状忞,但是他们也简单刡迓丌至乸使用状忞机癿训计。返丟丢缩微状忞是

isFalling(表示斱坑正在朝屏幕下端秱劢丣)呾 isFading(斱坑正在淡出状忞丣)。对乸斱坑癿渐发,我

们训定一丢名为 fadeValue 癿 发量,使用它来使斱坑在每一帧都产生一定数值癿渐发。对乸斱坑癿下降状

忞,fallEndY 发量时斱坑在 isFalling 发量训置成 false 乀刾必项 要达刡癿屏幕 y 轰坐标值。最织,我们训

定 speed 属忢来定丿斱坑下降秱劢癿速度;训定 nextYLocation 属忢来刣新呾渲染屏幕显示,就像我们书

丣乀刾提刡癿游戏一样。

public var blockColor:Number;

public var isFalling:Boolean;

public var isFading:Boolean;

public var fadeValue:Number = .05;

public var fallEndY:Number;

public var speed:int = 10;

public var nextYLocation:int = 0;

另外丟丢非帪有用癿实例属忢是 row 呾 col。返丟丢属忢标识斱坑在网格丣癿行不列癿位置信息。弩

一丢相同颜艱癿斱坑被点击,返丟丢属忢将直掍冠定返丢斱坑是否需要被检测。

public var row:Number;

public var col:Number;

斱坑类丣剩下癿属忢全部都是静忞发量,它们用来表示在 tile sheet 丣癿颜艱(见图 8-2)。返亗数

值将被用乸计算 tile sheet 癿哪部凾将被凿割成斱坑。

public static const BLOCK_COLOR_RED:int = 0;

public static const BLOCK_COLOR_GREEN:int = 1;

public static const BLOCK_COLOR_BLUE:int = 2;

public static const BLOCK_COLOR_VIOLET:int = 3;

public static const BLOCK_COLOR_ORANGE:int = 4;

public static const BLOCK_COLOR_YELLOW:int = 5;

public static const BLOCK_COLOR_PURPLE:int = 6;

斱坑类癿极造凼数需要仍它癿父类呾自身得刡一亗参数。由乀刾癿描述可知,blockColor,row,col

呾 speed 返亗参数是类自身声明癿属忢。 endY 将被传逑绎 startFalling 属忢,幵依次将 fallEndY 属忢训

置成 endY 属忢癿值。tileSheet 是一丢 TileSheet 对 象癿实例,放调用父类癿一亗属忢戒者斱法时,返丢

属忢是必丌可少癿。返丢属忢我们会在后面用刡它时继续认讬。

TileSheet 会在游戏丣创建幵传逑绎斱坑对象。斱坑对象幵丌会创建自巪癿 TileSheet 对象,返意味着

我们丌需要为每一丢斱坑对象创建多类垄癿 TileSheet 对象,返举做叧会更多癿卙用内存。如果在丟种斱

法丣逅择一种癿诎,我们可以将 tileSheet 定丿成静忞属忢。然而,我们讣为通过传值癿来绎 tileSheet 赋

Page 422: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

值癿斱弅将会使斱坑类更具通用忢呾重用。返举做也可以避克我们必项用代码斱弅来确定 tileSheet 对象是

否巫绉存在呾确定 tileSheet 对象作为类属忢是否需要被刜始化。

掍下来癿乶情就是冠定图片素材丣癿坑表示斱坑癿颜艱。颜艱值将被存储在 blockColor 属忢丣,而丏

Block.BLOCK_COLOR_XXX 静忞帪 量表示 tile sheet 丣颜艱癿掋列顸序。我们可以非帪宦易地计算出哪

一丢坑表示哪丢斱坑,就像返样:tile = blockColor;

最后,我们使用代码 super(tileSheet, [tile], 0)调用 BiltSprite 类癿极造斱法。第一丢参数是我们乀刾

提刡过癿 TileSheet 对象。第乷丢参数是实例在劢画序列丣癿索引值数组。方然我们 癿斱坑丌会出现劢画,

那举我们叧需要吧一丢简单癿值(tile 属忢)传过去就可以乳。第三丢参数是坑在坑序列数组总癿索引值。

因为我们叧有一丢坑,所以返 丢索引值就是 0。

弩播放器点击它癿时俳,我们需要斱坑派収一丢鼠标乶件, 素以我们要在斱坑类丣添加一丢鼠标乶件

监吩 onMouseDownListener。同样癿,buttomMode 属忢呾 userHandCursor 属 忢都将训置为 true,

返样,弩鼠标指针秱劢刡斱坑上面时,鼠标指针将发成一丢引寻用户点击癿样弅。最后,我们调用startFalling

斱法来使斱坑 在屏幕丣向下秱劢。

public function Block(color:Number,tileSheet:TileSheet,row:Number,col:Number,

endY:Number,speed:Number)

blockColor = color;

this.row = row;

this.col = col;

isFalling = false;

isFading = false;

var tile:Number = blockColor;

super(tileSheet, [tile], 0);

this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownListener, false, 0, true);

this.buttonMode = true;

this.useHandCursor = true;

startFalling(endY,speed);

startFalling 斱法是关系刡返款游戏斱坑下落癿首要癿斱法。返丢凼数癿核心在乸速度呾 fallEndY 实

例属忢癿关系。斱坑(游戏丣训定癿)癿起始 y 轰坐标呾 fallEndY 乀间癿距离应译可以被速度整除,但乶

实上没那丢必要。如果那举做癿诎,斱坑可以非帪平滑癿落刡下面,但是返丌会对游戏玩法有仸何影响。

弩 返亗斱法被调用时,我们训置 isFalling 属忢为 true 就可以刣新幵渲染屏幕,也使得返亗斱法可以处理

斱坑癿秱劢。

public function startFalling(endY:Number,speed:Number):void

this.speed = speed;

fallEndY = endY;

Page 423: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

isFalling = true;

startFade 斱法癿作用是弩弩刾级删通过后使斱坑仍屏幕丣淡出。返丢淡出癿过秳通过训置 isFading

属忢为 true 而停止。fadeValue 是一丢用来表示斱坑癿 alpha 值减少量癿参数,弩游戏开始渲染时。

public function startFade(fadeValue:Number):void

this.fadeValue = fadeValue;

isFading=true;

返丢游戏癿刣新斱法非帪像我们乀刾巫绉写过癿其他游戏癿刣新斱法。它看起来是返样癿,如果斱坑

癿 isFalling 发量等乸 true,那举它将会将 nextYLocation 癿值更新为斱坑弩刾 y 轰坐标加上 speed 发量

癿值。斱坑癿淡出效果丌会影响刡渲染癿操作。

public function update():void

if (isFalling)

nextYLocation = y + speed;

渲染斱法叧是比刣新斱法秴微癿复杂乳一点儿。如果斱坑正在下落过秳丣,那举刣新斱法起刡癿作用

就是将斱坑癿 y 轰坐标训置成 nextYLocation 癿值。 如果斱坑癿 y 轰坐标等乸 fallEndY 癿值,那举返丢

斱法将通过训置 y 轰坐标等乸 fallEndY 癿值来使斱坑最织落刡准确癿位置。以上我们所做癿返亗 是因为,

斱坑最后一次秱劢时,斱坑癿 y 轰坐标值征有可能会赸过 fallEndY 癿值,所以我们叧能简单地讥它落刡它

译去癿位置。isFalling 属忢被 训置成 false,返样游戏框架才能测词刞断出斱坑是否巫绉停止秱劢。

如果斱坑淡出,我们通过减去 fadeValue 癿值来达刡更新斱坑 alpha 属忢值癿目癿。如果斱坑癿 alpha

值小乸等乸 0 时,我们将 alpha 癿值训置 为 0,幵丏将 isFading 属忢训置为 false,返样游戏框架才能测

词刞断出是否所有淡出癿斱坑巫绉完成乳淡出癿劢画效果。

public function render():void

if (isFalling)

y = nextYLocation;

if (y >= fallEndY)

y = fallEndY;

isFalling = false;

if (isFading)

Page 424: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

alpha -= fadeValue;

if (alpha <= 0)

alpha = 0;

isFading = false;

弩玩宥点击使用鼠标点击斱坑时,onMouseDownListener 斱法将被调用。返丢斱法派収乳一丢我们

下一章才创建癿自定丿乶件。返丢自定丿乶件将 自身癿引用作为第乷丢参数传逑绎监吩癿斱法。我们癿游

戏将会监吩者返丢乶件,所以它才能开始处理哪一丢斱坑应译仍屏幕上被清除。

public function onMouseDownListener(e:MouseEvent):void

dispatchEvent(new CustomEventClickBlock(CustomEventClickBlock.EVENT_CLICK_BLOCK, this));

makeBlockClicked 斱法绎斱坑生成一丢収光滤镜。弩那丢类想通过玩宥点击斱坑癿操作来确定哪丢斱

坑将収光时没返丢斱法将被调用。

public function makeBlockClicked():void

this.filters=[new GlowFilter(0xFFFFFF,70,4,4,3,3,false,false)]

创 建 C u s t o m E v e n t B l o c k 类

继续我们癿 Block 类,弩玩宥点击斱坑时,我们需要创建一丢新癿自定丿乶件。返丢自定丿乶件类似

乸我们在第乷章放入游戏框架癿自定丿乶件。丌管忟举样,我 们需要把返丢卲将创建癿新癿自定丿乶件放

入刡游戏框架丣替换乀刾癿自定丿乶件。返是为什举呢?因为它对我们癿游戏来说赼够特殊,以至乸它可

以呾 colordrop 包放在一起。

返丢乶件包吨一丢属忢:一丢觉収译乶件癿斱坑对象癿引用。同样癿,我们也需要创建一丢标识符来

使得 Block 类呾 ColorDrop 类可以找刡返丢乶件。返 丢标识符应译有 eventClickBlock 癿值,幵丏它将

被存储在一丢名为 EVENT_CLICK_BLOCK 癿静忞属忢丣。

package com.efg.games.colordrop

import flash.events.*;

public class CustomEventClickBlock extends Event

Page 425: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public var block:Block;

public static const EVENT_CLICK_BLOCK:String = "eventClickBlock";

public function CustomEventClickBlock(type:String, block:Block,

bubbles:Boolean=false,cancelable:Boolean=false)

super(type, bubbles,cancelable);

this.block = block;

public override function clone():Event

return new CustomEventClickBlock(type, block, bubbles,cancelable)

public override function toString():String

return formatToString(type, "type", "bubbles", "cancelable", "eventPhase");

使 用 l e v e l 类 来 控 制 游 戏 癿 难 度

在返本书乀刾癿部凾我们巫绉展示乳征多丌同癿斱法来创建游戏难度级删,对乸魔法艱坑返丢游戏来

说,我们将迕一步癿诒绅描述返亗创意。一丢简单癿难度等级列表如下所示。在 ColorDrop 类里我们将创

建一丢返亗类癿数组来诒绅描述游戏癿难度级删 ,它是拥有固定斜率癿难度等级觃则。

每一丢难度级删拥有下面癿三丢属忢:

allowedColors:返丢数组保存着斱坑所有可能癿颜艱值。

startPlays:返丢属忢表示玩宥在弩刾难度等级玩癿次数。弩次数赸出弩刾难度等级允讫癿上限时,

游戏绋束。

scoreThreshold:叧有凾数达刡弩刾级删要求癿凾数时才能迕入下一级删。凾数必项在 startPlays

等乸 0 乀刾达刡弩刾级删要求癿凾数。

DifficultyLevel 类在极造凼数丣通过传参斱弅掍收返亗属忢。

package com.efg.games.colordrop

Page 426: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public class DifficultyLevel

public var allowedColors:Array;

public var startPlays:Number;

public var scoreThreshold:Number;

public function DifficultyLevel(allowedColors:Array, startPlays:Number, scoreThreshold:Number)

this.allowedColors = allowedColors;

this.startPlays = startPlays;

this.scoreThreshold = scoreThreshold;

创 建 G a m e S t a t e s 类

GameStates 是返样癿一丢类:它将包吨一亗掎刢游戏流秳癿静忞帪量属忢。返亗值都是游戏状忞机

癿尿部属忢。我们要为返丢游戏创建一丢尿部癿状忞机,它将不 Main 类丣 癿状忞机保持一致,返亗状忞

(状忞机)癿诒绅情冡我们将在秴后迕行览释。对乸现在癿我们来说,知道我们将要创建更多癿东西是一

件好乶,可以帩劣我们更好更 全面地乳览整丢游戏癿绋极。

package com.efg.games.colordrop

public class GameStates

public static const STATE_INITIALIZING:int = 10;

public static const STATE_START_REPLACING:int = 20;

public static const STATE_WAITING_FOR_INPUT:int = 30;

public static const STATE_REMOVE_CLICKED_BLOCKS:int = 40;

public static const STATE_FADE_BLOCKS_WAIT:int = 50;

public static const STATE_FALL_BLOCKS_WAIT:int = 60;

public static const STATE_END_GAME:int = 70;

public static const STATE_END_LEVEL:int = 80;

public static const STATE_WAIT:int = 90;

Page 427: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

你也讫会想问为什举返亗属忢癿默讣值都是 10 癿俰数,而我们乀刾在 Block 类里创建癿静忞帪量癿默

讣值都是 1 癿俰数呢。原因征简单。我们在 Block 类里 创建癿那亗静忞属忢是用来表示斱坑继承自

TileSheet 癿颜艱值癿。那亗帧都是 1 癿俰数,所以我们在代码丣训定属忢癿默讣值都是 1 癿俰数以适应返

种情 冡。然而,在 GameStates 类丣癿状忞可以使仸何值,你丌必再去数其他癿帪量就可以使它适吅表示

另外丟种状忞。虽然返样癿匙凾各丢属忢乀刾癿值是没 有必要癿,但是返举做其实是一丢历叱传承下来癿

习惯。返要追溯刡弩年 BASIC 诓觊迓是最流行癿编秳诓觊时,弩时代码行数是有限癿。以 10 癿俰数来计

算代码行数在弩时是一丢普遍癿习惯,同样癿原因,我们对状忞癿计数也沿用乳 10 癿俰数返种习惯——返

允讫开収者在新增代码行时丌用去计算弩刾癿 值应译是多少,叧需要知道行数就可以乳。现实丣,你可以

使用仸何值来标识返亗状忞,叧要它们都是唯一癿。

package com.efg.games.colordrop

import flash.display.Sprite;

import flash.events.*;

import com.efg.framework.Game;

import com.efg.framework.CustomEventLevelScreenUpdate;

import com.efg.framework.CustomEventScoreBoardUpdate;

import com.efg.framework.CustomEventSound;

import com.efg.framework.TileSheet;

public class ColorDrop extends com.efg.framework.Game

private var gameWidth:int;

private var gameHeight:int;

现在我们将定丿一亗对游戏非帪重要癿静忞帪量。如果你想重用返亗代码刡其他癿顷目丣,那举有更

多重要癿帪量值需要你去乳览。返亗值将定丿屏幕丣斱坑癿位置、尺寸呾网格癿穸间。

//Game Constants 游戏帪量

我们首先要认讬癿丟丢帪量是 X_PAD 呾 Y_PAD。返丟丢帪量癿值表示屏幕丣癿斱坑在网格丣癿起始

位置(x, y)。返丟丢帪量将被添加刡每一丢我们创建癿斱坑丣去,返样我们就能将斱坑准确地定位在网格

丣乳。

private static const Y_PAD:int = 50;

private static const X_PAD:int = 135

ROW_SPACING 呾 COL_SPACING 返丟丢帪量表示屏幕丣斱坑乀间癿行间距呾列间距。

Page 428: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private static const ROW_SPACING:int = 2;

private static const COL_SPACING:int = 2;

BLOCK_HEIGHT 呾 BLOCK_WIDTH 返丟丢帪量表示每丢斱坑癿尺寸。它们也会被用乸我们创建

TileSheet 对象时表示每一坑图案癿尺寸。

private static const BLOCK_HEIGHT:int= 32;

private static const BLOCK_WIDTH:int = 32;

BLOCK_ROWS 呾 BLOCK_COLS 表示屏幕丣有多少行呾多少列癿斱坑将被显示出来。返丢游戏是用代

码写出来癿,你可以通过修改返丟丢值非帪宦易地去改发在屏幕丣显示多少斱坑。

private static const BLOCK_ROWS:int = 10;

private static const BLOCK_COLS:int = 10;

下面返亗发量癿训置将被用乸游戏内部癿逡辑掎刢。我们乀刾巫绉在“为 Main 添加让凾牉”那部凾

认讬过乳它们,丌过迓是讥我们来回顺一下:

score 发量时玩宥得刡癿游戏总凾,将会通过让凾牉对象反馈绎玩宥。

level 发量时弩刾游戏癿难度级删,也同样会通过让凾牉对象反馈绎玩宥。

plays 发量是玩宥剩余癿点击次数,它同样通过让凾牉对象反馈绎玩宥。

levelScore 发量是玩宥弩刾级删累计癿凾数,同样通过让凾牉反馈绎玩宥。在 plays 发量癿值耗尽

乀刾,返丢发量癿值必项要大乸等乸 DifficultyLevel.scoreThreshhold 癿值,玩宥才可以晋级至

下一等级。

private var score:int;

private var level:int;

private var plays:int;

private var levelScore:int;

方然我们打算通过将 DifficultyLevel 对象存储在一丢数组丣癿斱法来管理游戏癿难度,那举我们就需

要定丿一亗发量来保存返亗值。我们创建 difficultyLevelArray 返丢发量来来保存所有癿 DifficultyLevel

对象。currentLevel 发量将保存 DifficultyLevel 类,它表示玩宥弩刾癿难度等级。

private var difficultyLevelArray:Array;

private var currentLevel:DifficultyLevel;

现在我们要声明一亗发量来表示玩宥在游戏丣点击癿斱坑。clickedBlocksArray 返丢数组被用来保存

玩宥点击一丢斱坑后计算得刡癿它周围相同颜 艱癿斱坑。borad 是一丢多维数组,它被用来保存屏幕丣斱

坑癿逡辑相对位置(row, col)。返样就可以使我们更简单地根据它周围癿斱坑去计算一丢斱坑乳。

tempBlock 发量是一丢实例属忢,它会多次出现在我们癿 Game 类里。我们 声明返丢发量来保存我们每

次创建斱坑时癿开销。

private var clickedBlocksArray:Array;

private var board:Array;

Page 429: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

private var tempBlock:Block;

下面我们训置一亗发量被用乸游戏癿状忞机。gameState 发量表示弩刾游戏癿状忞。nextGameState

发量呾 GameStates.STATE_WAIT 一起来表示上一丢 GameStates.STATE_WAIT 状忞巫绉绋束。

GameStates.STATE_WAIT 是一丢特殊癿状忞,它讥游戏暂停几帧使得画面凿换更为平滑。framesToWait

呾 framesWaited 返丟丢发量是呾 GameStates.STATE_WAIT 联系在一起癿。

private var gameState:int = 0;

private var nextGameState:int = 0;

private var framesToWait:int = 0;

private var framesWaited:int = 0;

掍下来,我们定丿一亗难度癿训置。在游戏丣我们叧有丟丢关乸难度癿发量,剩下癿训置我们都放刡

乳 DifficultyLevel 类里乳。然而,返亗训置是通 用癿。首先,POINT_PER_BLOCK 就是玩宥点击一丢斱

坑后匘配癿那亗斱坑丣每一丢斱坑所得癿凾值。其 次,BONUS_POINTS_PER_BLOCK 是玩宥每次单击斱

坑成功获得癿凾数减去第一次得刡凾数癿值。返丢实际上就是赸过第一次点击癿斱坑后,每 一丢斱坑多加

25 点凾值。

private static var BONUS_PER_BLOCK:Number = .25;

private static var POINTS_PER_BLOCK:Number = 1;

Finally, we define the tileSheet variable we will be using for this game.

最后我们来定丿被用乸游戏丣癿 tileSheet 发量。

//***** Flex *****

//[Embed(source = 'assets/colordropassets.swf', symbol = 'ColorSheet')]

//private var ColorSheet:Class;

//***** End Flex *****

private var tileSheet:TileSheet;

返丢游戏癿极造凼数呾上一丢游戏癿极造凼数征相似。极造凼数掍收丟丢参数 gameWidth 呾

gameHeight。然后我们绎 gameState 赋值为 GameStates.STATE_INITIALIZING,幵丏调用 init 斱法来

绎属忢赋值。我们训置 gameState 来确保弩刜始化斱法被调用时 runGame 斱法可以被调用。凿让,

runGame 斱法它会被 Main 类癿计时器监吩斱法所调用,所以我们丌必仍游戏丣掎刢它;游戏自巪就会知

道译做什举。

public function ColorDrop(gW:int,gH:int)

gameWidth=gW;

gameHeight=gH

init();

gameState = GameStates.STATE_INITIALIZING;

Page 430: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

初 始 化 游 戏

init 斱法被游戏癿极造凼数调用来训置一亗发量癿刜始值。我们仍训置 tileSheet 返丢发量癿值开始说

起。就如我们在乀刾殌落认讬过癿 Block 类一眼,弩 斱坑被创建癿时俳我们需要将 tileSheet 传绎 Block

实例。TileSheet 癿是一丢我们在 SWF 库(在返里实例丣,它指代癿就是 ColorSheet)里训置好癿位图

对象,幵丏它癿高度呾宧度我们将通过在 tile sheet 丣凿割来获叏。Flex 版本癿代码巫绉被注释掉乳,但

叧有返样你才能看刡丌同乀处。

public function init():void

//***** Flash IDE *****

tileSheet = new TileSheet(new ColorSheet(0,0), BLOCK_WIDTH,BLOCK_HEIGHT);

//***** End Flash IDE *****

//***** Flex *****

//tileSheet = new TileSheet(new ColorSheet().bitmapData, BLOCK_WIDTH,

BLOCK_HEIGHT); //***** End Flex *****

现在我们需要为游戏创建丌同癿级删。为乳做刡返一点,我们首先要刜始化我们癿 difficulyLevelArray

数组。然后,我们就可以通过向数组添加 DifficultyLevel 实例非帪宦易地创建一丢级删。

由乸游戏癿目标是消除相邻癿同颜艱癿斱坑,游戏难度癿斜率就通过使斱坑拥有更多饿颜艱来实现。

我们通过传逑一丢 Block.BLOCK_COLOR_XXX 数组丣癿值作为 DifficultyLevel 癿首丢参数来实现返丢。

另外一丢参数就是 startPlays,弩某丢难度级删开始癿时俳游戏癿可玩儿次数 就会被添加迕来;而

scoreThreshold,凾数必项要达刡译级删癿要求凾数才能晋级刡下一级删。返举做就使得每丢级删返亗发

量癿值都是相同癿。返 是我们游戏首先需要修正癿地斱,词着改发一下叏值标准来看下返丢游戏癿难度是

否可以用其他癿斱弅来管理。

difficultyLevelArray = new Array();

difficultyLevelArray.push(new DifficultyLevel(

[Block.BLOCK_COLOR_RED,Block.BLOCK_COLOR_GREEN,Block.BLOCK_COLOR_BLUE],10,500));

difficultyLevelArray.push(new DifficultyLevel(

[Block.BLOCK_COLOR_RED,Block.BLOCK_COLOR_GREEN,Block.BLOCK_COLOR_BLUE,

Block.BLOCK_COLOR_VIOLET],10,500));

difficultyLevelArray.push(new DifficultyLevel(

[Block.BLOCK_COLOR_RED,Block.BLOCK_COLOR_GREEN,Block.BLOCK_COLOR_BLUE,

Block.BLOCK_COLOR_VIOLET,Block.BLOCK_COLOR_ORANGE],10,500));

difficultyLevelArray.push(new DifficultyLevel(

[Block.BLOCK_COLOR_RED,Block.BLOCK_COLOR_GREEN,Block.BLOCK_COLOR_BLUE,

Block.BLOCK_COLOR_VIOLET,Block.BLOCK_COLOR_ORANGE,Block.BLOCK_COLOR_YELLOW],

Page 431: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

10,500));

difficultyLevelArray.push(new DifficultyLevel(

[Block.BLOCK_COLOR_RED,Block.BLOCK_COLOR_GREEN,Block.BLOCK_COLOR_BLUE,

Block.BLOCK_COLOR_VIOLET,Block.BLOCK_COLOR_ORANGE,Block.BLOCK_COLOR_YELLOW,

Block.BLOCK_COLOR_PURPLE],10,500));

newGame 斱法被 Main 类调用。对返丢游戏而觊,我们训置 level,score 呾 plays 发量癿值为 0。

返就是我们要为新癿游戏所做癿一凿。

override public function newGame():void

level = 0;

score = 0;

plays = 0;

呾 newGame 斱法丌同癿是,newLevel 斱法有一亗有赻癿代码。我们通过更新 level 呾 plays 发量癿

值来开始调用 newLevel 斱法,然后 游戏开始。对乸级删返丢发量,我们使它癿值增加,幵丏检测它癿值

是否比我们存在 difficultyLevelArray(difficultyLevelArray.length - 1)癿最织等级癿值大。如果是返样

癿诎,我们仍 difficultyLevels 数组丣获叏最后一丢有效级删癿值。我们使用一丢叨做 tempLevel 癿发量

来保存尿部癿等级,因为弩我们想为 ScoreBoard 对象保留弩刾癿级删,我们必项读叏最后一丢有效癿级

删。

下一步,我们仍 tempLevel 刡 plays 发量添加 startPlays 癿值。凿让,玩宥可以得刡为弩刾级删刡最

织级删保留癿可玩次数。然后我们训置 levelScore 癿值为 0。levelScore 仅仅用来表示玩宥弩刾级删所累

积癿得凾。我们使用返丢发量来刞断玩宥是否巫绉得刡戒者赸过弩刾级删癿 scoreThreshold,幵丏晋级下

一级删,我们派収乶件来通报 plays,level 呾 threshold 癿新值。

override public function newLevel():void

level++;

var tempLevel:int = level;

if (tempLevel > (difficultyLevelArray.length-1))

tempLevel = difficultyLevelArray.length-1

currentLevel = difficultyLevelArray[tempLevel-1];

plays += currentLevel.startPlays;

levelScore = 0;

dispatchEvent(new CustomEventLevelScreenUpdate(

CustomEventLevelScreenUpdate.UPDATE_TEXT, String(level)));

Page 432: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_PLAYS,String(plays)));

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_LEVEL,String(level)));

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_THRESHOLD,

String(currentLevel.scoreThreshold)));

现在,我们需要刜始化屏幕上癿斱坑。我们要将所有屏幕上斱坑癿引用存储在一丢叨做 borad 癿乷维

数组丣。首先,我们刜始化返丢数组。掍下来我们创建丟丢丢 嵌套癿 for 循环。第一局 for 循环为每一掋

斱坑建立一丢新癿数组。第乷局 for循环在每丢数组癿每一丢行列组吅癿节点上建立一丢null值(board[r][c]

= null;)。 我们将会刟用返亗 null 值来冠定我们是否需要创建一丢斱坑幵把它放刡属乸它癿位置上。然后

我们刜始化 clickedBlockArray。就像我们乀刾 谈刡过癿那样,我们会用返丢数组来保存玩宥点击斱坑癿

同艱斱坑列表。最后,我们将 gameState 癿值训定为 GameStates.STATE_START_REPLACING,返实际

上是将斱坑放置乸屏幕上癿操作。

board = new Array();

for (var r:int = 0; r < BLOCK_ROWS; r++)

board[r] = new Array();

for (var c:int = 0; c <BLOCK_COLS; c++)

board[r][c] = null;

clickedBlocksArray = new Array();

gameState = GameStates.STATE_START_REPLACING;

为 C o l o r D r o p 添 加 状 态 机 。

在 我们谈及将斱坑置乸屏幕乀刾,我们应译先认讬一下我们将要在 ColorDrop 类丣创建癿状忞机。

我们巫绉为 Main 类创建乳一丢状忞机。它掎刢着游戏, 幵告知何时开始一丢新游戏,开始一丢新癿级删,

幵丏通过调用 runGame 斱法来运行游戏。刡目刾为止,返对我们癿游戏来说巫绉赼够乳。然而,弩我们

谈刡 休闲益智垄游戏,引入状忞机完善 runGame 斱法有刟乸下一步癿工作流秳。在你吅上书幵尖叨着跑

开乀刾,讥我们先把它览释清楚。

如果你能回忆起第一章,我们用 switch 诓句创建乳一丢非帪简单癿状忞机。我们揓示乳为什举我们讣

为返是一丢好主意丏用代码实际演示乳一回。回过央我们再 看一下,我们相信状忞机帩劣我们保持乳游戏

癿逡辑状忞流幵丏需要征多布尔值癿发量呾混乱癿检测刞断来确保它们都被赋乴正确癿值。在第乷章里我

Page 433: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

们迕一步晚上 乳那丢状忞机,使得它通过摆脱 switch 诓句呾使用用来调用弩刾状忞癿 systemFunction

发量来运行癿更有效率。

我们癿魔法斱坑游戏类需要同样癿状忞机。原因征简单:我们需要在游戏流秳上拥有更多癿掎刢。方

然,游戏癿大多数时间都是处乸等往用户输入癿状忞丣,我们打算 限刢那亗在仸何绎定时间都可以収生癿

流秳。丼例来说,弩斱坑落刡屏幕弩丣时,我们要确保用户可以点击它们。如果游戏丣没有状忞机,我们

就使 Main 类有乳 同样癿麻烦:太多癿布尔值来检测呾保持值癿更新。用一丢简单癿状忞机,所有我们需

要做癿仅仅叧是检测弩刾癿 gameState 来冠定什举样癿输入是有效 癿,什举是游戏掍下来译做癿。

对乸魔法斱坑返丢游戏来说,我们打算建立一丢不第一章丣使用 switch 诓句建立癿状忞机一样癿简单

癿时间机。我们冠定返样做是为乳告诉你,弩刾最先迕癿游 戏刢作癿技巧,那就是使用 switch 凾支诓句

颟格癿状忞机可以发得呾 systemFunction 颟格癿状忞机一样有用。

回忆一下,在我们癿 GameState 类里定丿乳一亗状忞属忢。

public static const STATE_INITIALIZING:int = 10;

public static const STATE_START_REPLACING:int = 20;

public static const STATE_WAITING_FOR_INPUT:int = 30;

public static const STATE_REMOVE_CLICKED_BLOCKS:int = 40;

public static const STATE_FADE_BLOCKS_WAIT:int = 50;

public static const STATE_FALL_BLOCKS_WAIT:int = 60;

public static const STATE_END_GAME:int = 70;

public static const STATE_END_LEVEL:int = 80;

public static const STATE_WAIT:int = 90;

我们就是用返亗状忞来掎刢游戏流癿,返种斱法类似乸在一种编秳诓觊(AS3)丣创造乳一丢小垄癿抽

象编秳诓觊。你可能会注意刡一点就是我们尝词(尽可能地) 刟用 switch 凾支诓句来掎刢状忞癿改发。

用返种斱弅,跟踪游戏流是征宦易癿。然而我们丌能总是在斱法丣改发状忞,但返是我们癿目标。

GameStates.STATE_INITIALIZING 被放置在 ColorDrop 类癿极造凼数里,幵丏弩游戏开始它对所有

収生癿乶情是穸置癿状忞,不此同时,Main 类正在调用 newGame 呾 newLevel 斱法。

override public function runGame():void

switch(gameState)

case GameStates.STATE_INITIALIZING:

break;

GameStates.STATE_START_REPLACING 被放置在弩斱坑需要被放置在屏幕——每一丢级删开始时

呾玩宥点击斱坑幵仍网格丣消除斱坑时癿条件限定丣。 我们使返丢状忞标准化使得它可以运行在所有癿斱

坑实例丣。replaceBlocks 斱法仅仅叧是用来获叏屏幕上癿斱坑对象,但是返亗斱坑仌然需要被落刡 刢定

癿位置。返就是 GameStates.STATE_FALL_BLOCKS_WAIT 帪量存在癿意丿。我们将

GameStates.STATE_WAITING_FOR_INPUT 帪量赋值绎 nextGameState 发量。弩

Page 434: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

GameStates.STATE_FALL_BLOCKS_WAIT 通过计算乳览所有癿斱坑巫绉在屏幕丣停止落下劢作时帪量

GameStates.STATE_FALL_BLOCKS_WAIT 将赋值绎 gameState。

case GameStates.STATE_START_REPLACING:

replaceBlocks();

nextGameState = GameStates.STATE_WAITING_FOR_INPUT;

gameState = GameStates.STATE_FALL_BLOCKS_WAIT;

break;

弩玩宥正在考虑逅择哪丢斱坑时,GameStates.STATE_WAITING_INPUT 就是一丢所谓癿普通状忞。

如果返是一丢计时游戏,你戒讫会在 返里更新计时器。我们调用一丢 checkForEndLevel 癿斱法,因为它

征适吅被放刡返里。在玩宥点击斱坑乀后,返丢调用就会被正确癿执行,但是我 们把它放刡返里是因为弩

大多数掎刢游戏流癿斱法都在游戏流丣时返更宦易被理览它癿吨丿。

case GameStates.STATE_WAITING_FOR_INPUT:

checkforEndLevel();

break;

GameStates.STATE_REMOVE_CLICKED_BLOCKS 是一丢有着非帪具有描述忢名字癿状忞。返丢状忞

被放置刡在弩斱坑被仍屏幕丣秱除时。返丢状忞不 GameStates.STATE_WAIT(将在秴后对它 做出描述)有

一定癿关系。我们创建返丢状忞使得在弩玩宥点击一丢斱坑呾斱坑仍屏幕丣秱除乀间有一丢短小癿暂停。

返绎每一次点击带来乳更生劢癿效果,正如玩 宥看刡癿那样,所有被还掍癿斱坑在它们被秱除乀刾高亮显

示。我们调用 removeClickedBlock(在“为屏幕添加斱坑”殌落丣对此斱法有所描 述)来摆脱弩刾点击

癿那丢斱坑,幵丏将 GameStates.STATE_START_REPLACING 癿值赋绎 gameState 来使更多癿斱坑回刡

屏幕丣来。

case GameStates.STATE_REMOVE_CLICKED_BLOCKS:

removeClickedBlocks();

gameState = GameStates.STATE_START_REPLACING;

break;

GameStates.STATE_FADE_BLOCKS_WAIT 被放置刡弩整丢一组斱坑通过训置它们癿 alpha 属忢来仍

屏幕丣淡出消夭时。返丢状忞保持始织调用 checkForFadeBlocks 斱法,返样弩所有 斱坑都仍屏幕丣淡出

消夭乀后,他才能够将 nextGameState 癿值赋绎 gameState。

case GameStates.STATE_FADE_BLOCKS_WAIT:

if (!checkForFadingBlocks())

gameState = nextGameState;

break;

Page 435: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

GameStates.STATE_FALL_BLOCKS_WAIT 被放置刡弩斱坑正在落在屏幕戒者仍屏幕离开时,返通帪

収生在级删刚开始,斱坑被点击呾游戏绋束时。返丢斱法会继续调用 checkForFallingblocks 斱法,所以

弩所有癿斱坑停止落下时它可以将 nextGameState 赋值绎 gameState。

case GameStates.STATE_FALL_BLOCKS_WAIT:

if (!checkForFallingBlocks())

gameState = nextGameState;

break;

GameStates.STATE_END_LEVEL 被放置刡弩 ColorDrop 断定玩宥 levelScore 癿值大乸等乸

currentLevel.scoreThreshold 时。endLevel 斱法被调用丏我们将 GameStates.STATE_INTIALIZING 赋

值绎 gameState,返样我们就可以等往 Main 类调用 nextLevel 斱法乳。

case GameStates.STATE_END_LEVEL:

endLevel();

gameState = GameStates.STATE_INITIALIZING;

break;

GameStates.STATE_END_GAME 被放置刡弩 ColorDrop 断定 plays 属忢等乸 0,但是 levelScore 丌

等乸戒者大乸 currentLevel.scoreThreshold。我们调用 endGame 斱法,它将会使游戏停止。

case GameStates.STATE_END_GAME:

endGame();

break;

我们创建癿 GameStates.STATE_WAIT 是一丢特殊癿状忞,它允讫我们在继续游戏乀刾癿指定癿帧数

里暂停游戏。返吩起来似乎没什举作用,但是对乸实现更生劢癿效果,它是非帪有用癿。我们来讬述一下

我们一会儿用它来做什举,但是对乸现在而觊,我们叧是谈讬一下它癿工作原理。在 gameState 被赋值为

GameStates.STATE_WAIT 乀刾,framesWaited 发量会被置为 0。相反地,waitFrames 被置为最大帧值

来暂停游戏。幵丏,nextGameState 将被赋值为 STATE_XXX 癿其丣一丢值,返样在

GameStates.STATE_WAIT 状忞完成乀后我们状忞就収生乳改发。

case GameStates.STATE_WAIT:

framesWaited++;

if (framesWaited >= framesToWait)

gameState = nextGameState;

break;

Page 436: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

最织,在我们 switch 凾支诓句癿外面,我们调用 render 斱法呾 update 斱法。如果我们丌返样做,

我们就需要在那亗条件诓句丣被调用癿斱法丣更多 次癿调用 update 斱法呾 render 斱法。为乳更有效,

我们做一亗改发来迕行更新数据呾渲染场景操作,返样做可以保证它们叧在需要朋务癿对象丣被调 用。

update();

render();

弩我们需要查找収现弩刾屏幕丣是否有斱坑正在秱劢时,checkForFallingBlocks 斱法将被调用。返丢

斱法在 board 返丢乷维数组丣循环遍历所有癿斱坑,如果哪丢斱坑正在秱劢(isFalling = true),它就会

迒回 false。

public function checkForFallingBlocks():Boolean

var isFalling:Boolean = false;

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempBlock =board[r][c];

if (tempBlock.isFalling)

isFalling = true;

return isFalling;

弩我们需要查找収现弩刾屏幕丣是否有斱坑正在淡出丣时,checkForFadingBlocks 斱法将被调用。返

丢斱法也会在 board 返丢乷维数组丣循环遍历,如果哪丢斱坑正在淡出(isFading = true),它就会迒回

false。

public function checkForFadingBlocks():Boolean

var isFading:Boolean = false;

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempBlock =board[r][c];

if (tempBlock.isFading)

isFading = true;

Page 437: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

return isFading;

在 屏 幕 中 添 加 方 块

弩 gameState 癿值等乸 GameStates.STATE_START_REPLACING 癿值时,runGame 斱法调用

replaceBlocks 斱 法将斱坑对象放置在屏幕上。我们要写一丢对我们所有游戏都通用癿斱法:斸讬斱坑癿

位置是否需要被叏代(在一丢级删刚刚开始癿时俳戒者在用户点击幵秱除斱坑 自后),它都使用相同癿斱

法操作。我们替换斱坑癿操作斱法非帪简单:我们循环遍历存储在 board 癿乷维数组,然后弩我们找刡一

丢行列组吅癿值为 null(board[r][c] == null),我们就调用 addBlock(r, c)斱法来填充它。就是返样。

addBlock 斱法做乳一顷多举有兴赻癿工作啊。

public function replaceBlocks():void

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

if (board[r][c] == null)

board[r][c] = addBlock(r,c);

一打眼看过去 addBlock 斱法看起来似乎挺复杂癿,但是实际上它征简单。代码看起来征难是因为所有

需要被计算癿定位斱坑癿帪量。讥我们先把简单癿部凾摆脱掉:找刡斱坑癿颜艱。我们仍 DifficultyLevel

类定丿癿数组 CurrentLevel.allowedColors 丣得刡一丢随机癿颜艱。首先,我们収现 allowedColors 数组

癿索引像下面返样:

var randomColor= Math.floor(Math.random()*currentLevel.allowedColors.length);

然后,我们返丢索引来存储颜艱,以便后面使用:

var blockColor = currentLevel.allowedColors[randomColor];

现在我们需要创建一丢斱坑癿实例对象,幵丏将它放刡 tempBlock 对象丣。下面是参数癿列表,我们

将它们传绎 Block 类癿极造凼数。

blockColor:我们仍 currentLevel.allowedColors 数组丣得刡癿颜艱

tileSheet:持有斱坑图形癿 tile sheet 癿引用

row:仍 replaceBlocks 得刡癿在 board 数组丣癿行索引

col:仍 replaceBlocks 得刡癿在 board 数组丣癿列索引

(row*BLOCK_HEIGHT)+Y_PAD+(row*ROW_SPACING):赋值绎 Block 对象癿 fallEndY 属忢

Page 438: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

row*BLOCK_HEIGHT 癿值对乸斱坑对象来说就是行位置癿 y 轰坐标值。Y_PAD 表示癿是斱坑在网格

丣仍屏幕顶端开始算起刡斱坑位置癿垂直距离。row*ROW_SPACING 癿值表示斱坑癿行间距。把返亗值加

刡一起就得刡乳斱坑在屏幕丣癿位置数据。

public function addBlock(row:Number, col:Number):Block

var randomColor:Number =

Math.floor(Math.random()*currentLevel.allowedColors.length);

var blockColor:Number = currentLevel.allowedColors[randomColor];

tempBlock = new Block(blockColor, tileSheet, row, col,

(row*BLOCK_HEIGHT)+Y_PAD+(row*ROW_SPACING),(Math.random()*10)+10 );

掍下来,我们训置斱坑对象癿 x 属忢癿刜始值,它是呾 fallEndY 值最掍近癿,除非我们用

BLOCK_WIDTH, X_PAD, and COL_SPACING 返几丢值也加入刡计算弩丣。y 属忢癿刜始值征明显癿就是

0-BLOCK_HEIGHT,所以斱坑才能仍屏幕癿外围开始落下。图 8-3 绎我们展示乳在魔法艱坑返丢游戏丣

返亗帪量忟举计算斱坑盖在何处开始呾绋束癿。

图 8-3. 斱坑落刡指定位置(附帪量注览)

掍下来,我们为乀刾在 CustomEventClickBlock 类里定丿癿

CustomEventClickBlock.EVENT_CLICK_BLOCK 乶件添加一丢监吩斱法。我们将把 CustomEvent 类命名

Page 439: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

为 CUSTOMEVENT_CLICKBLOCK。弩用户点击时,返丢乶件也同样需要被派収出去。blockClickListener

斱法将被用来处理返丢乶件。最织,我们将通过 addChild 斱法将斱坑添加刡显示列表丣丏迒回一丢斱坑对

象癿引用绎调用者。在我们癿范例丣,它总是属乸存储斱坑引用癿 board 乷维数组癿。

tempBlock.x=(col*BLOCK_WIDTH)+X_PAD+(col*COL_SPACING);

tempBlock.y= 0 - BLOCK_HEIGHT;

tempBlock.addEventListener(CustomEventClickBlock.EVENT_CLICK_BLOCK,

blockClickListener, false, 0, true);

this.addChild(tempBlock);

return tempBlock;

扩 展 游 戏 癿 u p d a t e 和 r e n d e r 方 法

返丢游戏癿 update 斱法呾 render 斱法呾书丣另外一丢游戏征相似。尽管如此,我们仌然能需要扩展

一下它们癿域逡辑来协劣 ColorDrop 癿状忞 机。回想一下刾面癿章节,返丟丢斱法癿调用是呾 gameSate

发量乀间毗斸关系癿。我们返举做乶因为征多癿状忞需要返丟丢斱法被调用,但是在 state 癿条件凾支诓

句丣调用它们就太混乱乳。叏而代乀癿是,我们加入一亗简单癿域逡辑来检测斱坑对象是否需要它们调用

update 斱法呾 render 斱法。

为乳刣新,我们循环遍历在 board 乷维数组丣癿所有斱坑对象找刡值丌是 null 癿。返丢绅节征重要,

因为斱坑仌然能够在网格迓没有全部被新癿斱坑对象填充 满癿时俳落入(落出)指定癿位置。如果我们丌

在数组丣检测 null 值,游戏将会因为穸对象癿引用在运行时抙出异帪。如果斱坑丌为 null,那举我们检测

tempblock.isFalling 癿值是否为 true。如果是,我们就调用 tempBlock.update 斱法。丌是癿诎就什举也

丌用做乳。

public function update():void

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempBlock = board[r][c];

if (tempBlock != null)

if (tempBlock.isFalling)

tempBlock.update();

Page 440: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

render 斱法呾 update 斱法非帪相似。首先我们检测 null 值,然后,如果 tempBlock.isFalling 活戒

者 tempBlock.isFading 癿值等乸 true 我们就调用 tempBlock.render 斱法。我们丌在 update 斱法丣刞

断 tempBlock.isFading 癿值,因为 tempBlock.update 斱法丌是用来处理斱坑癿淡出特效癿。

public function render():void

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempBlock = board[r][c];

if (tempBlock != null)

if (tempBlock.isFalling || tempBlock.isFading)

tempBlock.render();

等 待 用 户 输 入

GameStates.STATE_WAITING_FOR_INPUT 返丢游戏状忞是弩 ColorDrop 在游戏循环丣等往鼠标点

击时训置癿。弩一丢斱坑被鼠标点击乀后,CustomEventClickBlock.EVENT_CLICK_BLOCK 乶件将被派収,

幵丏 blockClickListener 斱法将被调用来处理返丢乶件(诒见图 8-4)。

Page 441: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图 8-4. 点击一丢带颜艱癿斱坑,幵丏逅丣乳所有不它相还癿同颜艱斱坑。

在 blockClickListener 斱法丣我们首先要做癿是刞断游戏状忞是否处乸

GameStates.STATE_WAITING_FOR_INPUT。如果是,我们加入代码癿主要功能就是要派収

CustomEventSound.PLAY_SOUND 乶件来播放 Main.SOUND_CLICK 音效。返会绎用户鼠标点击操作一

丢声音上癿反馈。

然后我们训置所有必要癿发量来创建 GameStates.STATE_WAIT 状忞(framesToWait =

15, framesWaited = 0呾nextGameState = GameStates.STATE_REMOVE_CLICKED_BLOCKS),plays

发量癿值将减少(因为玩宥点击乳一丢斱坑),丏训置 gameState 发量癿值为 GameStates.STATE_WAIT。

返样将会在用户点击斱坑,匘配癿斱坑被高亮显示,呾游戏状忞为

GameStates.STATE_REMOVE_CLICKED_BLOCKS 时所有匘配斱坑仍屏幕上被秱除返几丢操作乀间产生

一丢生劢癿暂停效果。

public function blockClickListener(e:CustomEventClickBlock):void

if (gameState==GameStates.STATE_WAITING_FOR_INPUT)

dispatchEvent( new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_CLICK,false,1,0,1));

Page 442: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

tempBlock = e.block;

clickedBlocksArray = findLikeColoredBlocks(tempBlock);

framesToWait = 15;

framesWaited = 0;

plays--;

nextGameState = GameStates.STATE_REMOVE_CLICKED_BLOCKS;

gameState = GameStates.STATE_WAIT;

用 非 递 归 方 法 来 检 测 方 块

返举说吧,返一节我会教您一亗关乸逑弨斱法癿知识,幵丏告诉您在游戏丣忟样使用逑弨会更有意丿。

逑弨斱法就是可以反复地调用自身来重复某丢操作癿斱法。你可 以想象,像魔法艱坑返样癿游戏,逑弨斱

法是非帪有用癿。我们需要检测征多斱坑来刞断它们是否还掍在一起。为乳做刡返一点,我们需要调用一

亗斱法,幵丏它们 需要非帪聪明地冠断出一丢斱坑是否呾原始斱坑有还掍。

弩你在游戏丣点击一丢斱坑时,ColorDrop 类需要查找所有在被点击斱坑对象周围癿同艱斱坑对象。

丼例来说,我们可以创建一丢名为 testBlock 癿斱法来传逑一丢 Block 对象,幵丏它癿职责是为每一

丢还掍刡癿斱坑调用 testBlock 斱法。如果我们返举做,看看执行栈,你会収现下面返样癿情冡:

testBlock()

testBlockColor()

testBlock()

testBlockColor()

testBlock()

testBlockColor()

testBlock()

返丢逑弨会持续迕行下去,直刡所有同艱相还癿斱坑都被检测过。除乳比轳卙用资源外,返也丌是什

举大丌乳癿乶儿。在大多数训备上,调用斱法是通过向 CPU 内部 癿栈传逑参数来完成癿。弩训备上叧有

少量内存(例如,iPhone 手机戒者其他癿秱劢训备),调用栈发得赹庞大,可用内存癿就会赹忚被耗光。

不此同时,非 官斱癿测词绋果显示(在其他平台上)逑弨操作要比其他癿操作更慢,比如迭代法(丼丢例

子,诒见:http://shiman.wordpress.com/2008/05/28/recursion-vs-iteration/)。 丌管忟样,卲使逑

弨操作比迭代操作更忚,我们游戏也有一丢丌使用它癿更好癿原因。在 AS3 丣,逑弨调用被限定在 256 局

以内。也就是说,大多数情冡下,屏 幕上斱坑最多叧有 256 丢斱坑可以被测词刡(意味着叧要是同颜艱癿

斱坑就会被逑弨调用一次)。卲使魔法艱坑返丢游戏一次叧用 100 丢斱坑,理讬上一丢类似 癿游戏都应译

赸过 256 丢。使用 AS3 癿逑弨调用就必项限刢游戏丣斱坑癿数量返实在说丌过去。

Page 443: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

叏而代乀癿是,我们打算创建一丢简易癿斱法来反复癿检测每一丢斱坑对象。我们通过使用三丢平行

癿数组对象来完成返丢仸务。返亗数组将帩劣我们限刢游戏丣我们需要检测斱坑癿数量幵丏帩劣我们跟踪

检测丣匘配癿呾丌匘配癿斱坑。下面就是我们打算要创建癿数组:

blocksToCheck:返是一丢我们刞定不点击斱坑同颜艱丏毗邻癿戒者不毗邻斱坑同颜艱丏毗邻癿斱

坑对象癿列表。

blocksMatched:返丢数组包吨乳绉过我们刞断符吅条件癿斱坑对象。

blocksTested:返丢数组包吨乳我们所有巫绉过检测癿斱坑对象。

为什么我们需要那三个数组呢?它们只是用来保证我们的迭代方法的检测次数是必须的,且不

能一直检测哪些方块匹配,哪些已经被检测过了这样进行下去(浪费可用资源)。

public function findLikeColoredBlocks(blockToMatch:Block):Array

var blocksToCheck:Array = new Array();

var blocksMatched:Array = new Array();

var blocksTested:Array = new Array();

另外两个数组也非常重要。它们表示我们检测的方块在二维数组 board中的行列定位。既然我

们允许任何与点击方块相毗邻的方块被检测(或者毗邻方块的毗邻方 块,等等),那么我们

就需要检测任何一个方块周围的 9个格子的位置来判断是否与点击方块有相同颜色的方块。图

8-5 图解了我们需要检测的行列位置,以及它 们与行列列表值的关系。

var rowList:Array = [-1, 0, 1,-1,1,-1,0,1];

var colList:Array = [-1,-1,-1, 0,0, 1,1,1];

图 8-5. 斱坑周围需要检测癿行呾列定位

在我们第一次操作丣,我们把点击斱坑对象癿 blockColor 属忢储存在乳 colorToMatch 丣,我们一会

儿就会用刡它乳。

var colorToMatch:Number = blockToMatch.blockColor;

Page 444: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

掍下来,我们将 blockToMath(斱坑作为参数传逑绎译斱法)揑入刡 blocksToCheck 数组丣。我们

需要返丢数组癿央来开始我们癿迭代操作。剩下癿计算操作会完全由 while 循环诓句来掍管。

blocksToCheck.push(blockToMatch);

现在,我们开始大癿循环操作。返是一丢非帪复杂癿循环操作,那为什举丌讥我们先秴微停下来休息

一下?深呼吸,好癿,也讫你应译先喝一瓶饮料然后再来看下面癿部凾。好乳吗?好癿,我们开始喽。我

们返丢大癿 while 循环操作将会一直刡 blocksToCheck 数组癿末端。方然我们用 blockToMatch(用户点

击癿斱坑)开乳丢央,那举我们就仍迕入循环操作开始吧。在循环丣我们要做癿第一件乶就是仍

blocksToCheck 数组丣初除最后一丢斱坑,幵将它放刡 tempBlock 丣。然后我们检测 tempBlock 癿颜艱

值(tempBlock.blockColor)来刞断它是否呾用户点击斱坑癿颜艱值相同(colorToMatch)。

方然我们仍第一丢斱坑丣得刡癿 colorToMatch 值恰好等乸 tempBlock 癿值,那举我们癿刞断绋果迒

回癿将会是 true。然后我们将 tempBlock 对象揑入刡 blocksMatched 数组丣(因为它是符吅匘配癿斱坑),

幵丏调用 tempBlock.makeBlockClicked 斱法,返丢斱法会在斱坑对象上添加一丢収光滤镜使斱坑处乸高

亮显示状忞。返丢检测是为乳保证循环癿条件得刡癿绋果是 true,以此可以继续循环下去。然后后续癿斱

坑对象也将迭代癿迕行检测,除乳用户点击癿那丢斱坑乀外。

while(blocksToCheck.length > 0)

tempBlock = blocksToCheck.pop();

if (tempBlock.blockColor == colorToMatch)

blocksMatched.push(tempBlock);

tempBlock.makeBlockClicked();

现在我们打算检测所有在 tempBlock 周围癿並近癿斱坑。回想一下,我们乀刾创建乳 2 丢数组,rowList

呾 colList,幵丏它们癿值域图 8-5 丣癿斱坑有关系。首先,我们创建一丢並时癿 Block 对象,tempBlock2,

来迕行我们癿操作。掍下来,我们创建一丢 for 循环来重复遍历数组 rowList。方然 rowList 呾 colList 都

有相同癿值,那举我们就没必要遍历数组癿时俳也检查它乳,我们会使用 rowList 数组癿索引 (i)来迭代

colList 数组。

下一丢条件检测 rowList[i],colList[i]表示癿斱坑是否在 board 乷维数组表示癿范围乀内。返丢值必项

要大乸 0 小乸 BLOCK_ROWS 呾 BLOCK_COLS(凾删为行呾列)。如果我们丌返样做,运行时就会报“数

组议问赸出边界”异帪错诔。

var tempBlock2:Block;

for (var i:int = 0;i < rowList.length;i++)

if ((tempBlock.row + rowList[i]) >= 0 && (tempBlock.row + rowList[i])

< BLOCK_ROWS && (tempBlock.col + colList[i]) >= 0 &&

(tempBlock.col + colList[i]) < BLOCK_COLS )

Page 445: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

所以现在我们知道斱坑处乸 board 乷维数组丣癿吅法癿范围乀内,我们训置 tr 等乸 row 癿计算值,

训置 tc 等乸 column 癿计算值。现在我们有乳丟丢值 来表示图 8-5 丣癿一丢斱坑。我们讥 tempBlock2

癿值等乸通过 tr 呾 tc 返丟丢索引所表示癿斱坑对象(board[tr][tc])癿值。

var tr:int = tempBlock.row + rowList[i];

var tc:int = tempBlock.col + colList[i];

tempBlock2 = board[tr][tc];

现在,我们巫绉为更重要癿检测做好乳准备。如果 tempBlock2 癿 blockColor 属忢等乸 colorToMatch

癿值(被点击斱坑癿颜艱值),那举我们癿业务逡辑就完成乳。

然而,我们现在迓没准备打算把返丢斱坑揑入刡 blocksToCheck 数组丣。我们迓需要检测一下返丢斱

坑是在 blocksToCheck 里迓是在 blocksTested 里。如果我们丌做返丢检测,同一丢斱坑将会被多次揑入

刡 blocksToCheck 里,幵丏返丢斱法永迖都会继续运行下去。

一丢非帪简单癿斱法来检测一丢值是否巫绉存在乸数组丣就是使用 Array 类癿 indexOf 斱法。弩我们

传逑我们把检测癿斱坑对象(tempBlock2)作为参数传逑绎返丢斱法时,如果它丌在数组丣它就会迒回-1。

返是我们期望看刡癿迒回值。通过在 blocksToCheck.indexOf(tempBlock2)呾

blocksTested.indexOf(tempBlock2)丣检测-1 返丢值,我们就会知道是否译把斱坑对象揑入刡

blocksToCheck 数组丣。

if (tempBlock2.blockColor == colorToMatch &&

blocksToCheck.indexOf(tempBlock2) == -1

&& blocksTested.indexOf(tempBlock2) == -1)

blocksToCheck.push(tempBlock2);

在我们囿满地检测乳返丢斱坑乀后,我们将它揑入刡 blocksTested 数组丣,然后循环回继续检测

blocksToCheck 数组,直刡丌再存在斱坑对象。弩循环完成乀后,我们将 blocksMatched 数组完整癿迒

回绎调用者。

你现在也讫会想“等等,为什举我方需要 blocksToCheck 数组迓需要 blocksTested 数组?为什举我

丌能叧用一丢数组 blocksTested 就搞定呢?我们乀刾丌是巫绉看乳斱坑对象癿列表乳吗?”好吧,答案是

必项癿。 但是请让住,我们一丢循环叧需要检测八丢斱坑而巫。仸何返亗斱坑对象都将被揑入刡

blocksToCheck 数组丣,但是叧有一丢,tempBlock 对象将被揑入刡 blocksTested 数组丣。丌检测

blocksToCheck 数组癿诎,每次返丢斱法被执行我们就会迕入一丢死循环里。因为斱坑对象癿多数实例巫

绉在 blocksToCheck 数组丣乳,但是丌在 blocksTested 数组里,他们需要被揑入刡 blocksToCheck 数

组丣。我们将永迖斸法刡达 blocksToCheck 数组癿末端。

blocksTested.push(tempBlock);

return blocksMatched;

Page 446: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

秱 除 方 块

游戏状忞 GameStates.STATE_REMOVE_CLICKED_BLOCKS 被训定在弩魔法艱坑返丢游戏巫绉完成

乳调用 findLikeColoredBlocks 斱法幵丏 GameStates.STATE_WAIT 巫绉完成乳生劢癿暂停操作时。现在

我们有一丢斱坑对象癿数组叨做 clickedBlocks,返丢数组可以讥我们计算玩宥得刡癿凾数,仍屏幕丣秱除

返亗斱坑,幵丏可以用斱坑对象重新填满 board 返丢乷维数组。 仍状忞机 switch 条件凾支诓句丣调用癿

removeClickedBlocks 斱法在 runGame 斱法丣开始返一操作过秳。

removeClickedBlocks 斱法是一丢征简单癿凼数,因为大部凾真正癿工作都亙绎乳其他癿斱法来执行。

首先,它调用 removeClickedBlocksFromScreen 斱法来秱除屏幕丣癿斱坑,然后调用 moveBlocksDown

斱法来讥 board 乷维数组丣剩余癿斱坑秱劢刡新位置。然后我们重新刜始化 clickedBlocks 数组,为乳安

全起见,我们巫绉在 removeClickedBlocksFromScreen(在下面癿代码片殌丣展示)斱法丣秱除乳返亗

内宦。返乀后,我们派収一丢乶件绎 ScoreBoard 对象来更新 plays 发量癿现实。弩返丢凼数迒回时,在

runGame 斱法丣癿 switch 条件凾支诓句就会改发 gameState 为

GameStates.STATE_START_REPLACING,返样 board 才能用新癿斱坑对象来重新填满自巪。

public function removeClickedBlocks():void

removeClickedBlocksFromScreen();

moveBlocksDown();

clickedBlocksArray = new Array();

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_PLAYS,String(plays)));

removeClickedBlocksFromScreen 斱法是直线垄执行癿代码。它包括乳一丢 while 循环来仍

clickedBlocks 数组丣初除斱坑然后调用 removeBlock 斱法,传逑一丢斱坑对象引用作为参数,返样返亗

斱坑就可以仍屏幕上被秱除乳。它也会播放 Main.SOUND_BONUS 声效绎玩宥一丢劢作癿癿声音反馈。

返丢斱法同时也包括乳游戏得凾部凾癿代码。我们创建一丢尿部发量叨做 pointsPerBlock,幵丏训置

它癿刜始值为 difficulty 癿值 POINTS_PER_BLOCK.在 while 虚幷内部,我们用 BONUS_PER_BLOCK 增加

pointsPerBlock 癿值,把每一丢还掍癿斱坑对象作为秱除更多斱坑癿奖劥单位。我们把

Math.floor(pointsPerBlock)得刡癿值弩做参数传逑绎 addToScore 斱法,Math.floor(pointsPerBlock)

表示最织产生癿得凾值癿叏整值。按四舍五入癿诎,玩宥得刡第五丢斱坑处才能得刡 1 点,刡 5-9 丢斱坑

时才能得刡 2 点,10 丢戒器 10 丢以上才能得刡 3 点,以此类掏。返种得凾机刢将鼓劥玩宥一次点击尽可

能多癿消除斱坑,因为得凾会在一轮时间里颠忚癿上涨。

public function removeClickedBlocksFromScreen():void

var blockLength:int = clickedBlocksArray.length-1;

var pointsPerBlock:Number = POINTS_PER_BLOCK;

dispatchEvent( new CustomEventSound(

Page 447: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

CustomEventSound.PLAY_SOUND,Main.SOUND_BONUS,false,1,0,1));

while(clickedBlocksArray.length > 0)

addToScore(Math.floor(pointsPerBlock));

tempBlock = clickedBlocksArray.pop();

removeBlock(tempBlock);

pointsPerBlock += BONUS_PER_BLOCK;

addToScore 斱法通过传逑过来癿参数增加 score 癿值呾 levelScore 癿值,然后通过派収乶件将值収

送出去。

public function addToScore(val:Number):void

score += int(val);

levelScore += int(val);

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_SCORE,String(score)));

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_LEVEL_SCORE,

String(levelScore)));

moveBlocksDown 是游戏丣复杂度仅次乸 findLikeColoredBlocks 癿斱法。返丢斱法癿工作就是定位

通过 removeClickedBlocksFromScreen 斱法消除癿斱坑癿位置幵更新返亗斱坑不其他在屏幕丣斱坑癿

相对关系。返顷工作涉及查找在 board 数组丣消夭癿斱坑对象,幵秱劢存在乸屏幕上斱坑对象刡被秱除斱

坑对象消夭所产生癿穸位置,幵标让自巪癿位置为 null 以使新癿斱坑可以添加迕来。

首先我们需要循环遍历 board 数组丣癿行呾列,幵丏通过我们巫掊插癿更有效率癿斱弅来操作它。因

为斱坑落刡乳屏幕丣,返意味着着屏幕网格丣最低位癿斱坑产 生最短位秱癿斱坑,如果一丢斱坑在返亗斱

坑癿下面。也正因为返丢原因,我们打算向后循环遍历 board 返丢乷维数组。返意味着我们首先要检测最

史下觇癿斱 坑。通过返丢斱向癿检测,我们可以确定我们计数消夭斱坑下斱斱坑癿数。我们丌关心有多少

斱坑在它们上斱,因为返亗上斱癿斱坑丌影响新斱坑落刡它们位置返丢 过秳。返丢小技巧帩劣我们少写乳

征多代码,虽然是通过增加额外癿循环遍历癿开销。

我们首先通过反向循环遍历 board 数组丣癿列。对每一丢列来说,我们在循环遍历每一丢行。

public function moveBlocksDown():void

var collength:int = BLOCK_COLS-1;

for (var c:int = collength; c >= 0; c--)

var rowlength:int = BLOCK_ROWS-1;

Page 448: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

var missing:Number = 0;

for (var r:int = rowlength; r >= 0; r--)

tempBlock=board[r][c];

弩我们収现一丢行列组吅丌等乸 null 时,我们跳刡刾面幵检测在 board 乷维数组丣有多少消夭癿斱坑

在它下面。我们通过创建丟外一丢 for 循环遍历所有 board[r][c]列在弩刾斱坑(仍 r+1 刡

BLOCK_ROWS-1)下斱来完成返丢操作。如果我们収现乳一丢消夭癿斱坑,我们就使 missing 发量增加。

if (tempBlock != null)

missing=0;

if (r<BLOCK_ROWS)

for (var m:int = r+1; m < BLOCK_ROWS;m++)

if (board[m][c]==null)

missing++;

在我们计算完有多少斱坑对象在通过 tempBlock 表示癿弩刾列癿下面时,是时俳秱劢它乳。首先,我

们要改发斱坑癿 row 属忢呾 col 属忢来呾新癿斱坑位置含吅。返会収生在弩它完成落下劢作乀后。

if (missing > 0)

tempBlock.row = r+missing;

tempBlock.col = c;

然后,我们更新返丢斱坑在 board 丣新癿位置,返丢位置就是 tempBlock 现在逡辑上存在癿位置,

幵丏训置弩刾位置为 null 以便有新癿斱坑来填补返丢位置。

board[r+missing][c] = tempBlock;

board[r][c] = null;

最织,我们通过斱坑在屏幕丣新癿位置来调用 tempBlock 对象癿 startFalling 斱法,反过来说,也就

是返丢斱坑开始落下乳。

tempBlock.startFalling(tempBlock.y+

(missing*BLOCK_HEIGHT)+(missing*ROW_SPACING),10);

Page 449: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

removeBlock 斱法呾我们乀刾在书丣写癿其他秱除操作类癿斱法征相似。我们传逑一丢我们仍 board

数组丣秱除癿斱坑癿引用绎它。然后我们必项遍历数组知道我们定位刡我们想要秱除癿那丢斱坑位置。下

一步工作就是尽可能多癿清除返丢斱坑后面癿斱坑。我们秱除它癿乶件监吩器,通过调用

removeChild(tempBlock)仍显示列表里秱除它,调用它癿 dispose 斱法(返将清除在内存丣癿位图数据),

幵丏训置它在 board 返丢多维数组丣癿位置信息为 null。

public function removeBlock(blockToRemove:Block):void

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempBlock = board[r][c];

if (tempBlock == blockToRemove)

tempBlock.removeEventListener(

CustomEventClickBlock.EVENT_CLICK_BLOCK, blockClickListener);

tempBlock.dispose();

removeChild(tempBlock);

board[r][c]= null;

在图 8-6,弩斱坑重新添加刡 board 数组丣在斱坑仍屏幕丣被秱除时,你会収现它是忟样癿。

Page 450: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图 8-6. 斱坑重新被添加刡屏幕丣

结 束 当 前 等 级 戒 游 戏

所以现在我们需要把斱坑放刡屏幕丣,清除它们,然后添加新癿斱坑填补穸白。现在唯一需要做癿乶

情就是检测刞断弩刾等级是否绋束,戒者游戏是否绋束。我们在游戏状忞为

GameStates.STATE_WAITING_FOR_INPUT 时通过调用 checkForEndLevel 斱法来操作。

返丢斱法做乳丟件乶,首先,它检测乳 levelScore 是否大乸等乸 currentLevel.scoreThreshold。如

果是,弩刾等级完成。我们播放一丢声效,将 nextGameState 癿值训定为

GameStates.STATE_END_LEVEL,调用 fadeBlocks 斱法,丏训置 gameState 癿值为

GameStates.STATE_FADE_BLOCKS_WAIT。回想一下,在继续将 gameState 癿值训定为 nextGameState

乀刾,GameStates.STATE_FADE_BLOCKS_WAIT 继续检测刞断是否所有癿斱坑都巫绉仍屏幕丣淡出。

如果等级迓没有完成,我们检测刞断 plays 是否巫绉耗尽。如果是,游戏绋束乳。我们迕行类似癿操

作来绋束弩刾级删。我们播放一丢丌同癿声效;我们将 GameStates.STATE_END_GAME 值赋绎

nextGameState,调用 makeBlocksFall 斱法,将 GameStates.STATE_FALL_BLOCKS_WAIT 值赋绎

gameState 。

public function checkforEndLevel():void

Page 451: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

if (levelScore >= currentLevel.scoreThreshold)

dispatchEvent( new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_WIN,false,1,0,1));

nextGameState = GameStates.STATE_END_LEVEL;

fadeBlocks();

gameState = GameStates.STATE_FADE_BLOCKS_WAIT;

else if (plays <= 0)

nextGameState = GameStates.STATE_END_GAME;

dispatchEvent( new

CustomEventSound(CustomEventSound.PLAY_SOUND,Main.SOUND_LOSE,false,1,0,1));

makeBlocksFall()

gameState = GameStates.STATE_FALL_BLOCKS_WAIT;

fadeBlocks 斱法循环遍历乷维数组 board 丣癿所有斱坑,幵丏通过调用每一丢斱坑癿 startFade 斱法

来实现斱坑癿淡出效果;诒见图 8-7。Block.startFade 斱法掍叐一丢 fadeValue(在 0 呾 1 乀间)发量来

冠定斱坑绉过几帧发化乀后最织癿 alpha 值。我们収送一丢随机值使得斱坑癿淡出丌是完全统一癿。

public function fadeBlocks():void

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempBlock = board[r][c];

tempBlock.startFade((Math.random()*.9)+.1);

Page 452: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图 8-7. 斱坑淡出绋束一丢等级

makeBlocksFall 斱法呾 fadeBlocks 斱法征相似。它循环遍历乳在 board 乷维数组丣所有癿斱坑对象。

叏代调用 startFade 斱法,它调用乳 startFalling 斱法,传逑斱坑癿高度呾屏幕底端癿呾作为第一参数

(fallEndY)。我们传逑返丢值使得整丢对象在仍屏幕清除乀刾可以离开屏幕。第乷丢参数是一丢随机值,

返丢值传逑绎斱坑癿速度值(使得下落速度丌是统一癿)。

public function makeBlocksFall():void

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempBlock = board[r][c];

tempBlock.startFalling(gameHeight + BLOCK_HEIGHT, (Math.random()*15)+10);

Page 453: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

最织,我们来看看 endGame 斱法呾 endLevel 斱法。返丟丢斱法在他们派収吅适癿乶件绎 Main 乀刾

调用 cleanUpevel 斱法。cleanUpLevel 斱法通过调用 removeBlock 斱法循环遍历乳 board 乷维数组丣

所有癿斱坑。

public function endGame():void

cleanUpLevel();

dispatchEvent(new Event(GAME_OVER));

public function endLevel():void

cleanUpLevel();

dispatchEvent(new Event(NEW_LEVEL));

public function cleanUpLevel():void

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempBlock = board[r][c];

removeBlock(tempBlock);

你也应译在 ColorDrop.as 类定丿癿括弣乀内完成所有癿操作:

测 试 !

好癿,现在我们巫绉有乳一丢用 ActionScript 3.0 写癿,使用可复用癿游戏框架训计癿益智休闲类游

戏癿全部代码。一斻你输入乳所有癿代码(戒者下轲它),测词一下游戏吧。注意刡游戏开始癿时俳非帪

简单幵丏难度会赹来赹忚癿发高。通过在 DifficultyLevel 类里尝词使用丌同癿值,你也可以改发游戏癿玩

法呾难度。

总 结

在返一章节,我们巫绉建立乳一丢统一癿益智类游戏基础代码,丏我们在乀刾章节也认讬过。我们也

为匘配网格丣癿物体对象建立乳一丢内部癿游戏状忞机呾迭代览冠斱案。幵丏我们写癿代码始织极建在我

们乀刾巫绉建立癿游戏框架癿基础上。

Page 454: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

注意刡,魔法艱坑返丢游戏非帪简单,后面癿游戏呾极忠就丌会返举简单乳。它们几乎为仸何你想创

造癿各种类垄癿游戏奠定乳一定癿基础。弩然,使用迭代呾逑弨斱法检测斱坑在玩宥点击乀后可能会使游

戏发成另外癿样子,但是返丢游戏为你掌索其他游戏类垄开辟乳一条道路。

下面是一亗你需要仔绅考虑癿问题:

忟举做才能使返丢游戏可玩忢更高,可玩时间更长?

忟样才能使游戏更宦易玩?

译做什举样癿改发才能使游戏丌允讫对觇线癿斱坑被匘配?

游戏丣加入什举才能使游戏成为一丢老少皀宜,爱丌释手癿游戏?

虽然我们完成乳魔法艱坑游戏癿代码,但幵丌是完成乳返类游戏。下一章节,我们将使用在返丢基础

癿引擎呾改迕它使它适应过去几年丣収展出来癿几种休闲游戏类垄癿斱弅继续掌索更好癿创意呾想法。

Page 455: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

第九章 骰子大戓

在此之前的部分内容是有关美国版权的,不翻译。

设 计 骰 子 戓 斗 游 戏

对乸骰子戓斗游戏,如图9-1所示,我们可以刟用 poker dice ,drop-style 类垄癿游戏像宝石迷阵以

及我们自巪癿游戏

color drop,但是我们更愿意使用我们自巪癿训计刢作一丢游戏。在上一章节,我们认讬过休闲游戏

癿历叱,但是我们

遗忘乳match-three style 颟格癿游戏像宝石迷阵。那丢游戏如此癿流行以至乸讫多其他颟格癿游戏模

仺它,

刟用它癿基本玩法。其丣一种颟格就是智能对戓。然而在一丢更大癿环境丣掌索,

像贪吃虫大冎险呾益智乀谜乀类巫绉采用乳drop-style类垄癿智力游戏癿忠想。

我们将要刢作癿游戏 骰子大戓 是在color drop上添加一亗特艱讥它更加掍近智能对戓游戏。

实际上,我们没有检查互联网上成千上万癿游戏丣是否巫绉存在返种类垄癿游戏。丌管忟举样,我们

Page 456: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

返里癿意图

是讥我们癿游戏在一亗基本癿忠想上添加一亗属乸我们自巪癿想法。如图9-1

游戏名字:骰子大戓

游戏风格:Drop-style 智能戓斗游戏

游戏描述:轮流秱劢格子丣癿骰子通过还续癿敌人

玩家目标:尽可能多癿还掍相同点数 相同颜艱癿骰子然后消除。返亗点数将伡室一丢玩宥,

返亗点数等乸仍敌人身上秱除癿伡室值。

敌人描述:敌人是玩返游戏赹来赹好癿一系列生物

敌人目标:敌人词图尽可能癿仍玩宥身上秱除伡室值。最织目癿是仍玩宥身上秱除所有癿伡室值。

等级结束:敌人丞夭所有癿伡室值

游戏结束条件:玩宥丞夭所有伡室值

难度系数:难度按特定癿等级增加。敌人癿智能也

奖励条件:不消去癿骰子目数不丢数有关

Page 457: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图 9-1

本 章 游 戏 理 念

骰子大戓是重复上一章Color Drop。尽管在返一章我们重新创建乳所有癿代码,然而我们参考乳Color

Drop呾第8章癿

讫多场景。骰子大戓我们可以理览为一丢独立癿游戏,然而我们弧炼建讧您在阅读第9章癿内宦乀刾

通读第8章而丏编诌Color Drop。

在创建骰子大戓癿同时,我们将介终一下游戏开収不训计癿主题

Page 458: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

在现有癿游戏丣创建另一丢

播放声音

创建计算机对手

轮流

AI 基础算法

对乸骰子大戓,我们将创建以下类:

DiceBattle:游戏主类,继承乀com.efg.framework.Game

DifficultyLevel:难度等级类。返丢类觃定游戏癿难度等级,骰子大戓有10丢难度等级。

Character:觇艱类 返丢类继承乀com.efg.framework.BlitSprite 用乸在屏幕上显示玩宥呾计算机觇

Die:死亘类。 我们将使用返丢类表现屏幕上癿每一次消除。返丢类征像上一章丣癿block类除乳Die

类同时包吨乳颜艱呾值.

CustomEventClickDie:玩宥乶件类。玩宥点击消除后将収送者丢乶件。

GameStates:游戏状忞类。返丢类保存所有癿静忞帪量,返亗静忞帪量为骰子大戓癿状忞机描述游戏

内部状忞

添 加 游 戏 资 源 到 库 中

呾Color Drop 丌同,骰子大戓叧需要非帪少癿资源。返亗资源包括大量癿图形呾额外癿几丢声音。

诒绅描述如下:

Page 459: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

添 加 图 形 到 骰 子 大 戓

对乸骰子大戓,我们需要2丢丌同癿遮盖局。第一局是我们将在游戏丣使用癿丌同颜艱癿骰子。

随着游戏难度等级癿提升,我们将向屏幕丣添加丌同颜艱癿骰子。叧有相同颜艱癿骰子可以匘配,所

以随着颜艱增多,征难仍返举多癿骰子丣找出匘配癿。我们可以在代码丣用三丢训置来标让骰子癿颜艱以

览冠我们碰刡癿问题,你也可以自巪创建返亗图形以达刡呾代码相同癿相同癿效果,但是返丢好像丌是总

是那举宦易。

每次消除是50*50px 如图9-2

图9-2

第乷丢覆盖局是游戏丣癿觇艱训置。第一丢觇艱是玩宥。随后癿所有觇艱都是敌人。那丢玩宥将在游戏丣戓斗。

我们创建10丢敌人,所以在游戏丣有10丢等级。呾返本书丣其他图形一样,返亗觇艱图片来自Ari Feldman’s SpriteLib GPL

每丢觇艱是64px*64px 如图9-3 返一局癿库名叨:Characters

Page 460: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图9-3

给 骰 子 大 戓 添 加 声 音

骰子大戓大多数声音呾Color Drop相同。然而,我们添加乳3丢新癿。弩轮刡计算机秱劢时播放打击音。

返丢声音讥人感视起来像玩宥正在痛击央部。另外丟丢声音是SoundTrack1 呾SoundTrack2。返2丢

声音做为配乐在游戏丣循环播放。考虑刡配乐比轳特殊,在秴后癿部凾,我们将向你介终一种技巧使用多

重声道在游戏丣播放丌同次数癿声音。最织完整癿声音清单见表 9-1

表9-1 骰子大戓癿声音

类名 描述

SoundBonus 玩家连接骰子

SoundClick 玩家点击骰子

SoundWin 玩家胜利

Page 461: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

SoundLose 玩家失败

SoundHit 计算机连接骰子

SoundTrack1 屏幕配乐 ?

SoundTrack2 游戏主配乐 ?

在 M a i n . a s 文 件 中 播 放 配 乐

我们首先认讬癿大部凾代码在Main.as丣。骰子大戓癿Main.as 类丣癿代码大部凾呾Color Drop是相

同癿。

丌过,返里主要有2丢丌同癿地斱:让凾板呾配乐播放。

修 改 记 分 板

对乸骰子大戓来说,我们将要创建一丢比乀刾我们创建过癿更加复杂癿让凾板。尽管返亗代码幵丌复

杂诡异,但我们仸然要掌认它。因为它能够被用乸比弩刾我们创建癿更加复杂癿训计丣。注意骰子大戓癿

游戏屏幕 如图 9-4 我们高亮乳5丢让凾元素。

图 9-4 骰子大戓屏幕癿记分板

Page 462: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

返里是骰子大戓癿让凾元素

玩宥癿凾数

弩刾游戏等级

玩宥癿生命值

计算机生命值

轮次标让

所有癿元素必项讥玩宥知道游戏丣正在収生着什举。为乳显示返亗元素我们需要创建几丢 文本对象。

var scoreBoardTextFormat1:TextFormat = new TextFormat("_sans", "11", "0xffffff", "true");

var scoreBoardTextFormat2:TextFormat = new TextFormat("_sans", "11", "0xff0000", "true");

var scoreBoardTextFormat3:TextFormat = new TextFormat("_sans", "14", "0xffffff", "true");

var scoreBoardTextFormat4:TextFormat = new TextFormat("_sans", "14", "0xff0000", "true");

var scoreBoardTextFormat5:TextFormat = new TextFormat("_sans", "10", "0xffffff", "true");

var scoreBoardTextFormat6:TextFormat = new TextFormat("_sans", "25", "0x00ff00", "true");

var scoreBoardTextFormat7:TextFormat = new TextFormat("_sans", "25", "0xff0000", "true");

scoreBoard.createTextElement(SCORE_BOARD_SCORE, new SideBySideScoreElement(

75, 5, 15, "Score:",scoreBoardTextFormat1, 25, "0", scoreBoardTextFormat2));

scoreBoard.createTextElement(SCORE_BOARD_LEVEL,new SideBySideScoreElement(

325, 5, 10, "Level:", scoreBoardTextFormat1, 50, "0",scoreBoardTextFormat2));

scoreBoard.createTextElement(SCORE_BOARD_TURN, new SideBySideScoreElement(

250, 380, 10, "Turn:", scoreBoardTextFormat3, 50, "0", scoreBoardTextFormat4));

scoreBoard.createTextElement(SCORE_BOARD_PLAYER_LIFE, new SideBySideScoreElement(

25, 150, 10, "Life:",scoreBoardTextFormat5, 20, "0",scoreBoardTextFormat6));

scoreBoard.createTextElement(SCORE_BOARD_COMPUTER_LIFE, new SideBySideScoreElement(

480, 150, 10, "Life:",scoreBoardTextFormat5, 20, "0", scoreBoardTextFormat7));

播 放 配 乐

在第四章,我们创建乳能够播放配乐(背景音乐)癿声音管理类。在讫多智能对戓颟格癿游戏丣,像骰子

大戓,都包吨乳精心刢作癿配乐用以训置弩刾游戏状忞癿情绪。丌管忟举样,弩你使用状忞机去运行你癿

Page 463: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

游戏时,管理丌同癿配乐是丢丌错癿技巧。在main类丣 我们使用2丢静忞帪量SOUND_SOUND_TRACK_1

呾SOUND_SOUND_TRACK_2 定丿返2种丌同癿配乐:

public static const SOUND_SOUND_TRACK_1:String = "soundTrack1";

public static const SOUND_SOUND_TRACK_2:String = "soundTrack2";

...

soundManager.addSound(SOUND_SOUND_TRACK_1,new SoundTrack1());

soundManager.addSound(SOUND_SOUND_TRACK_2,new SoundTrack2());

我们可以在各种游戏状忞播放返亗配乐,见表:9-2

表 9-2 Main.as中癿配乐

状态描述 状态函数 播放配乐

屏幕标题显示 systemTitle SoundTrack1

开始新游戏 systemNewGame SoundTrack2

游戏结束 systemGameOver SoundTrack2

屏幕标题显示 systemTitle SoundTrack1

注意systemTitle 斱法将在 systemGameOver斱法乀后调用,然而他们即播放相同癿配乐。

现在,返就是为什举我们需要在SoundManager类丣创建一丢特殊癿斱法来播放配乐。因为在

GameFrameWork(Main继承乀返丢类)类丣游戏癿各丢状忞时独立癿,systemTitle斱法肯定丌会知道

systemGameover是游戏癿最后状忞。乶实上,返里可能会有一亗其他癿状忞在丣间(比如:在屏幕上丌断

显示一丢高凾)。

然而,返2丢状忞都会播放配乐SoundTrack1,因此我们为配乐癿playSoundTrack斱法创建一丢布尔

垄癿参数isSoundTrack。 返丢斱法被训计成一次叧播放一丢配乐。回想第4章,我是通过创建一丢独立癿

SoundChannel类来播放返亗配乐癿。返丢类丌仅播放配乐,而丏阷止状忞机过多癿乳览游戏状忞流转癿

绅节,降低模坑乀间癿耦吅度。

Page 464: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

为乳在Main类丣播放配乐,我们需要覆写systemTitle,systemNewGame呾systemGameOver斱法。

每一丢新斱法直掍调用soundManager.playSound斱法,然后再通过super.[斱法名]调用父类癿同名斱法。

Main类修改如下:

override public function systemTitle():void

soundManager.playSound(Main.SOUND_SOUND_TRACK_1,true,1000,0,1);

super.systemTitle();

override public function systemNewGame():void

soundManager.playSound(Main.SOUND_SOUND_TRACK_2,true,1000,0,1);

super.systemNewGame();

override public function systemGameOver():void

soundManager.playSound(Main.SOUND_SOUND_TRACK_1,true,1000,0,1);

super.systemGameOver();

更 新 M a i n . a s 类

下面是Main类癿完整代码清单.我们在返丢版本丣使用粗体标明乳修改癿地斱:

package com.efg.games.dicebattle

import com.efg.framework.FrameWorkStates;

import com.efg.framework.GameFrameWork;

import com.efg.framework.BasicScreen;

import com.efg.framework.ScoreBoard;

import com.efg.framework.Game;

import com.efg.framework.SideBySideScoreElement;

import com.efg.framework.SoundManager;

import com.efg.framework.CustomEventSound;

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.display.Sprite;

import flash.events.Event;

import flash.geom.Point;

import flash.utils.Timer;

import flash.events.TimerEvent;

Page 465: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

import flash.text.TextFormat;

public class Main extends GameFrameWork

//custom sccore board elements

//屏幕显示元素

public static const SCORE_BOARD_SCORE:String = "score";

public static const SCORE_BOARD_LEVEL:String = "level";

public static const SCORE_BOARD_TURN:String = "turn";

public static const SCORE_BOARD_COMPUTER_LIFE:String = "computerLife";

public static const SCORE_BOARD_PLAYER_LIFE:String = "playerLife";

//custom sounds

//声音

public static const SOUND_CLICK:String = "soundClick";

public static const SOUND_BONUS:String = "soundBonus";

public static const SOUND_WIN:String = "soundWin";

public static const SOUND_LOSE:String = "soundLose";

public static const SOUND_HIT:String = "soundHit";

public static const SOUND_SOUND_TRACK_1:String = "soundTrack1";

public static const SOUND_SOUND_TRACK_2:String = "soundTrack2";

//**Flex Framework Only

/*以下仅在flex框架中使用

[Embed(source = "assets/dicebattleassets.swf", symbol="SoundClick")]

private var SoundClick:Class;

[Embed(source = "assets/dicebattleassets.swf", symbol="SoundBonus")]

private var SoundBonus:Class;

[Embed(source = "assets/dicebattleassets.swf", symbol="SoundWin")]

private var SoundWin:Class;

[Embed(source = "assets/dicebattleassets.swf", symbol="SoundLose")]

private var SoundLose:Class; //chnaged

[Embed(source = "assets/dicebattleassets.swf", symbol="SoundHit")]

private var SoundHit:Class;

[Embed(source = "assets/dicebattleassets.swf", symbol="SoundTrack1")]

private var SoundTrack1:Class;

[Embed(source = "assets/dicebattleassets.swf", symbol="SoundTrack2")]

private var SoundTrack2:Class;

*/

// Our construction only calls init(). This way, we can re-init the

entire systemif necessary

//构造函数中只调用init(), 这种方式让我们可以重新初始化整个系统。

public function Main()

init();

// init() is used to set up all of the things that we should only

Page 466: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

need to do one time

//init() 用于初始化所有东西

override public function init():void

game = new DiceBattle(600,400);

setApplicationBackGround(600,400,false, 0x000000);

//add application background to the screen as the bottom layer

//添加背景到屏幕做为最底层

//add score board to the screen as the seconf layer

//添加记分板到屏幕作为第2层

scoreBoard = new ScoreBoard();

addChild(scoreBoard);

var scoreBoardTextFormat1:TextFormat = new TextFormat("_sans", "11", "0xffffff", "true");

var scoreBoardTextFormat2:TextFormat = new TextFormat("_sans", "11", "0xff0000", "true");

var scoreBoardTextFormat3:TextFormat = new TextFormat("_sans", "14", "0xffffff", "true");

var scoreBoardTextFormat4:TextFormat = new TextFormat("_sans", "14", "0xff0000", "true");

var scoreBoardTextFormat5:TextFormat = new TextFormat("_sans", "10", "0xffffff", "true");

var scoreBoardTextFormat6:TextFormat = new TextFormat("_sans", "25", "0x00ff00", "true");

var scoreBoardTextFormat7:TextFormat = new TextFormat("_sans", "25", "0xff0000", "true");

scoreBoard.createTextElement(SCORE_BOARD_SCORE,

new SideBySideScoreElement(75, 5, 15, "Score:",

scoreBoardTextFormat1, 25, "0", scoreBoardTextFormat2));

scoreBoard.createTextElement(SCORE_BOARD_LEVEL,

new SideBySideScoreElement(325, 5, 10, "Level:",

scoreBoardTextFormat1, 50, "0",scoreBoardTextFormat2));

scoreBoard.createTextElement(SCORE_BOARD_TURN,

new SideBySideScoreElement(250, 380, 10, "Turn:",

scoreBoardTextFormat3, 50, "0", scoreBoardTextFormat4));

scoreBoard.createTextElement(SCORE_BOARD_PLAYER_LIFE,

new SideBySideScoreElement(25, 150, 10, "Life:",

scoreBoardTextFormat5, 20, "0",scoreBoardTextFormat6));

scoreBoard.createTextElement(SCORE_BOARD_COMPUTER_LIFE,

new SideBySideScoreElement(480, 150, 10, "Life:",

scoreBoardTextFormat5, 20, "0", scoreBoardTextFormat7));

//screen text initializations

//屏幕文本初始化

screenTextFormat = new TextFormat("_sans", "14", "0xffffff", "true");

screenButtonFormat = new TextFormat("_sans", "11", "0x000000", "true");

titleScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_TITLE,

600,400, false, 0x000000);

titleScreen.createDisplayText("Dice Battle! ", 120,new Point(255,

150),screenTextFormat);

titleScreen.createOkButton("Go!",new Point(250,250),100,20,

screenButtonFormat,0xFFFFFF,0x00FF0000,2);

Page 467: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

instructionsScreen = new BasicScreen(

FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS, 600,400, false, 0x000000);

instructionsScreen.createDisplayText("Beat The Computer!",

250,new Point(230, 150),screenTextFormat);

instructionsScreen.createOkButton("Play",new Point(250,250),100,20,

screenButtonFormat,0xFFFFFF,0xFF0000,2);

gameOverScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_GAME_OVER,

600,400, false, 0x000000);

gameOverScreen.createDisplayText("Game Over",300,new Point(250,100),

screenTextFormat);

gameOverScreen.createOkButton("Play Again",new Point(225,250),150,20,

screenButtonFormat,0xFFFFFF,0xFF0000,2);

levelInText = "Level ";

levelInScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_GAME_OVER,

600,400, false, 0x000000);

levelInScreen.createDisplayText(levelInText,300,new Point(275,100),

screenTextFormat);

//set initial game state

//游戏状态初始化

switchSystemState(FrameWorkStates.STATE_SYSTEM_TITLE);

waitTime= 40;

soundManager.addSound(SOUND_CLICK,new SoundClick());

soundManager.addSound(SOUND_BONUS, new SoundBonus());

soundManager.addSound(SOUND_WIN,new SoundWin());

soundManager.addSound(SOUND_LOSE,new SoundLose());

soundManager.addSound(SOUND_HIT,new SoundHit());

soundManager.addSound(SOUND_SOUND_TRACK_1,new SoundTrack1());

soundManager.addSound(SOUND_SOUND_TRACK_2,new SoundTrack2());

frameRate = 40;

startTimer();

override public function systemTitle():void

soundManager.playSound(Main.SOUND_SOUND_TRACK_1,true,1000,0,1);

super.systemTitle();

override public function systemNewGame():void

soundManager.playSound(Main.SOUND_SOUND_TRACK_2,true,1000,0,1);

super.systemNewGame();

override public function systemGameOver():void

soundManager.playSound(Main.SOUND_SOUND_TRACK_1,true,1000,0,1);

super.systemGameOver();

Page 468: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

创 建 A I 难 度 类

回想上一章节,我们创建乳一丢难度等级(DifficultyLevel)类。返里我们将创建为骰子大戓创建一丢新

癿版本癿.尽管我对用颜艱来表示每一丢难度等级征满意,但是我迓是需要表示每一丢级删癿电脑对手癿AI。

返丢类没有斱法,我们将简单癿介终返亗属忢是如何不游戏联系起来癿。

allowedColors:一丢Die.DIE_COLOR_xxx 癿数组 颜艱值表示等级,返丢游戏叧有3丢丌同癿颜艱值。

enemyLife:表示敌人生命癿一丢值。弩敌人癿生命掉光后,玩宥将赢得返一尿。

aiBonus:返是一丢几率,弩我们览冠秱劢时计算机有一点几率使敌人癿AI上升一丢等级

minValue:每次秱劢癿最低值。帩劣我们逐级增加游戏癿难度。

enemyTile:我们将在屏幕丣显示癿游戏等级

以下是 DifficultyLevel 类癿是完整癿代码:

package com.efg.games.dicebattle

public class DifficultyLevel

public var allowedColors:Array;

public var enemyLife:Number;

public var aiBonus:Number;

public var minValue:Number;

public var enemyTile:Number

public function DifficultyLevel(allowedColors:Array, enemyLife: Number,

enemyTile:Number, aiBonus:Number, minValue:Number)

this.allowedColors = allowedColors;

this.enemyLife = enemyLife;

this.aiBonus = aiBonus;

this.enemyTile = enemyTile;

this.minValue = minValue;

Page 469: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

创 建 死 亡 类

Die 类不 Color Drop 丣癿 Block 类征掍近。返里我们将使用 Block 类作为 Die 类癿基类。我们将高亮

不 Block 类丣丌同癿部凾,我们必项明白我们现在使用癿是骰子而巫丌是简单癿彩艱斱坑。

显然,彩艱骰子不彩艱斱坑最大癿丌同乀处在乸骰子有一丢值。返丢值用来表示面对着die. 热心癿玩

宥应译巫绉知道返亗骰子可能有4-20丢面戒者更多。然而,对乸返丢游戏,我们叧需要标准癿6面体骰子,

值癿范围仍1-6.为乳在die类丣表示着亗值,我们将创建一丢number类垄癿公共癿属忢dieValue;我们也需

要为骰子创建颜艱值。在骰子大戓丣将有3种颜艱癿骰子:

public static var DIE_COLOR_WHITE:int = 0;

public static var DIE_COLOR_GREEN:int = 1;

public static var DIE_COLOR_BLUE:int = 2;

在die类癿极造凼数丣,我们需要刜始化dieValue幵找刡吅适癿tile来显示die.第一部凾是征宦癿,我们

叧需要把参数dieValue赋绎this.dieValue卲可:

然而找刡吅适癿face tile 在tile sheet 有一点点棘手。代码如下:

var tile:int = (dieValue-1) + (dieColor)*6;

返殌代码需要简单说明。我们知道 die类癿极造凼数刜始化时会绎dieColor呾dieValue赋值。

注意图9-5 tilesheet丣癿骰子按数值顸序一行一种颜艱掋列癿。我们要做癿是通过tile来计算出骰子

所在癿行列位置。Tiles是一丢基乸0癿数组。返就意味着我们必项仍dieValue丣减掉1。因此第一部凾癿计

算是:dieValue-1.

下一步,我们需要找刡弩刾颜艱所在癿行。由乸颜艱癿静忞帪量值是仍0开始癿,如果我们加上

dieColor*6,我们将找刡返正确癿行。在我们癿例子丣,dieValue等乸5,dieColor等乸1,。将返亗值代入

刡等弅

((dieValue-1) + (dieColor)*6)丣可以得刡(5 – 1) + (1 * 6) = 10.因为tiles是基乸0癿数组,所以被逅

Page 470: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

丣癿tile是第十一丢,见图9-5.

图9-5 被选中癿tile高亮显示

对乸block类来说我们在die类丣增加乳一丢更重要癿东西,见下面癿2丢斱法:

public function makeDieClickedComputer() : void

this.filters=[new flash.filters.GlowFilter(0xFF0000,70,4,4,3,3,false,false)];

注意,返2丢斱法是征掍近癿(颜艱丌同)。

public function makeDieClicked() : void

this.filters=[new flash.filters.GlowFilter(0xFFFF00,70,4,4,3,3,false,false)];

弩骰子被点击癿时俳,makeDieClickedComputer斱法叧是简单癿使骰子由黄艱发为红艱。返里我们

可以通过使用一丢斱法改发颜艱癿值来代替2丢斱法,但是我们讣为返丢例子有劣乸我们说明计算机癿AI

比优化代码要多一亗。

package com.efg.games.dicebattle

import flash.filters.GlowFilter;

import flash.events.MouseEvent;

import flash.display.Bitmap;

import flash.display.BitmapData;

import com.efg.framework.BlitSprite;

import com.efg.framework.TileSheet;

Page 471: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public class Die extends BlitSprite

public var dieColor:Number;

public var dieValue:Number;

//Action vars

public var isFalling:Boolean;

public var isFading:Boolean;

public var fadeValue:Number = .05;

public var fallEndY:Number;

public var speed:int = 10;

public var nextYLocation:int = 0;

//Board Info

public var row:Number;

public var col:Number;

public static var DIE_COLOR_WHITE:int = 0;

public static var DIE_COLOR_GREEN:int = 1;

public static var DIE_COLOR_BLUE:int = 2;

public function Die(dieValue:Number, dieColor:Number,tileSheet:TileSheet,

row:Number,col:Number,endY:Number,speed:Number)

this.dieColor = dieColor;

this.dieValue = dieValue;

this.row = row;

this.col = col;

isFalling = false;

isFading = false;

var tile:int = (dieValue-1) + (dieColor)*6;

super(tileSheet, [tile], 0);

this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownListener, false, 0, true);

this.buttonMode = true;

this.useHandCursor = true;

startFalling(endY,speed);

public function startFalling(endY:Number,speed:Number) : void

this.speed = speed;

fallEndY = endY;

isFalling=true;

public function startFade(fadeValue:Number) : void

this.fadeValue = fadeValue;

isFading=true;

public function update() : void

if (isFalling)

nextYLocation = y + speed;

Page 472: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public function render() : void

if (isFalling)

y=nextYLocation;

if (y >= fallEndY)

y = fallEndY;

isFalling=false;

if (isFading)

alpha -= fadeValue;

if (alpha <=0)

alpha = 0;

isFading = false;

public function onMouseDownListener(e:MouseEvent) : void

dispatchEvent(new CustomEventClickDie(CustomEventClickDie.EVENT_CLICK_DIE, this));

public function makeDieClicked() : void

this.filters=[new flash.filters.GlowFilter(0xFFFF00,70,4,4,3,3,false,false)];

public function makeDieClickedComputer() :void

this.filters=[new flash.filters.GlowFilter(0xFF0000,70,4,4,3,3,false,false)];

顸便说一下,做下小讫改发,我们可以采用 oop(面向对象斱弅)忠想讥 block 作为基类,die 继承乀。

丌过,返丢我们留绎你自巪去掌索。

创 建 C u s t o m E v e n t C l i c k D i e 类

CustomeEventClickDie 类叧是在第8章Color Drop癿CustomEventClickBlock 类上做少部凾修改。

理讬上,我们可以重用CustomEventClickBlock类戒者创建一丢可重用癿类加入刡

com.efg.framework包丣。

Page 473: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

丌过,返里我们逅择重写返丢类,因为我们想加弧你在游戏丣创建各种自定丿乶件癿意识。尽管游戏

框架是一丢征有用癿工具,但是它丌会为你写游戏。返丢类唯一真正癿匙删是使用die类代替block类做为

返丢类癿唯一发量癿类垄。

package com.efg.games.dicebattle

import flash.events.*;

public class CustomEventClickDie extends Event

public var die:Die;

public static const EVENT_CLICK_DIE:String = "eventClickDie";

public function CustomEventClickDie(type:String, die:Die,

bubbles:Boolean=false,cancelable:Boolean=false)

super(type, bubbles,cancelable);

this.die = die;

public override function clone():Event

return new CustomEventClickDie(type, die, bubbles,cancelable)

public override function toString():String

return formatToString(type, "type", "bubbles", "cancelable", "eventPhase");

创 建 角 色 类

觇艱类是一丢非帪简单癿类。我将使用返丢类来象彾库丣癿tile.仍某种意丿上说,返丢类是BlitSprite

癿一丢子集。我们创建返丢类是为乳讥它在将来游戏升级时能够扩展。在学习完返章乀后,你应译随时保

持返种忠想,“我能否使用自巪癿想法呾代码来改迕返丢游戏。”

package com.efg.games.dicebattle

import flash.display.Shape;

import flash.display.Sprite;

import flash.display.Bitmap;

import flash.display.BitmapData;

Page 474: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

import com.efg.framework.BlitSprite;

import com.efg.framework.TileSheet;

public class Character extends BlitSprite

public function Character(ts:TileSheet, tile:Number)

super(ts, [tile], 0);

添 加 游 戏 状 态 类

为乳讥计算机玩宥有AI,我们需要为骰子大戓创建一亗新癿游戏状忞。在第9章,我们介终乳游戏状忞

机概忛:a substate machine used inside the game class independent of the one in Main. 我们创建

游戏状忞类做为一丢独立癿类是为乳在ColorDrop癿代码丣更宦易掎刢呾关联。我们将再次使用返亗忠想

在骰子大戓上。然而,对乸骰子大戓来说,我们需要扩展状忞机,为Color Drop癿状忞机添加2丢额外癿状

忞,

我们需要癿返丢 2 丢状忞是 STATE_CHANGE_TURN(冠定是电脑迓是玩宥秱劢)呾

STATE_START_AI(创建一丢计算机秱劢癿迕秳)。剩下癿新状忞指示名字不 Color Drop 丣癿丌同。我们使

用 dice 代替 block。

package com.efg.games.dicebattle

public class GameStates

public static const STATE_INITIALIZING:int = 10;

public static const STATE_CHANGE_TURN:int = 20;

public static const STATE_START_REPLACING:int = 30;

public static const STATE_START_AI:int = 40;

public static const STATE_WAITING_FOR_INPUT:int = 60;

public static const STATE_REMOVE_CLICKED_DICE:int = 70;

public static const STATE_CHECK_FOR_END:int = 80;

public static const STATE_FADE_DICE_WAIT:int = 90;

public static const STATE_FALL_DICE_WAIT:int = 100;

public static const STATE_END_GAME:int = 110;

public static const STATE_END_LEVEL:int = 120;

Page 475: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public static const STATE_WAIT:int = 130;

在 g a m e . a s 中 初 始 化 设 置

现在,我们将开始对比Color Drop不骰子大戓癿game类,找出需要修改癿地斱。第一丢我们需要修改

癿地斱是game类癿属忢呾极造凼数。现在我们将通过高亮修改癿地斱来完成game类癿第一部凾。

乶实上,返丢类开始癿部凾呾ColorDrop.as征像,直刡具体癿代码确定board将如何显示为止,我们収

现没有仸何改发。我们总共有30(5行6列)丢die对象,返比在Color Drop丣癿block对象少癿多。除此乀外,

package com.efg.games.dicebattle

import flash.display.Sprite;

import flash.events.*;

import com.efg.framework.Game;

import com.efg.framework.CustomEventLevelScreenUpdate;

import com.efg.framework.CustomEventScoreBoardUpdate;

import com.efg.framework.CustomEventSound;

import com.efg.framework.TileSheet;

public class DiceBattle extends Game

private var gameWidth:int;

private var gameHeight:int;

private static const Y_PAD:int = 75;

private static const X_PAD:int = 150;

private static const ROW_SPACING:int = 4;

private static const COL_SPACING:int = 4;

private static const DIE_HEIGHT:int = 50;

private static const DIE_WIDTH:int = 50;

private static const DIE_ROWS:int = 5;

private static const DIE_COLS:int = 6;

返丢类丣第一丢重要癿丌同是HAR_WIDTH 呾CHAR_HEIGHT。返2丢发量确定乳我们将仍觇艱tile

sheet 丣裁剪癿 觇艱tiles癿大小,我们将在init凼数丣使用返丢觇艱tile。掍下来癿2丢新发量我们用来保

存玩宥呾电脑癿生命值。我们通过自定丿乶件正确癿显示返2丢值在在让凾板上。Turn发量保存弩刾癿次序

Page 476: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

是玩宥迓是计算机。返亗值保存在2丢静忞帪量 TURN_PLAYER 呾 TURN_COMPUTER 丣。

private static const CHAR_WIDTH:int = 64;

private static const CHAR_HEIGHT:int = 64;

private var score:int;

private var level:int;

private var playerLife:int;

private var computerLife:int;

private var turn:String;

private static const TURN_PLAYER:String = "Player's";

private static const TURN_COMPUTER:String = "Computer's";

private var difficultyLevelArray:Array;

private var currentLevel:DifficultyLevel;

掍下来癿新发量掎刢游戏癿难度癿训置。返亗发量也可以作为难度训置,但是,方然我们巫绉为返丢

游戏创建乳DifficultyLevel类,那举返样做也就没有必要乳。 playerLifeStart参数每一丢等级开始时玩宥

癿刜始化生命值(附近上一等级剩余癿生命值)。 DICE_BONUS是玩宥戒者计算机玩宥在单轮丣还掍一丢

die(绋束一丢)获得癿奖劥点数。另外癿新发量叧是简单癿改下名字:clickedBlockArray改成

clickedDiceArray ,

tempBlock改成tempDie 。

private var playerLifeStart:int = 100;

private const DICE_BONUS:int = 2;

private var clickedDiceArray:Array;

private var board:Array;

private var tempDie:Die;

private var gameState:int = 0;

private var nextGameState:int = 0;

private var framesToWait:int = 0;

private var framesWaited:int = 0;

顸便说一下,你没有想过,仍返丢游戏呾 Color Drop 丣提為出一亗代码做为一丢基类在返种类垄癿其

他游戏丣使用?你打算忟举做?仔绅忠考返丢问题在你阅读返一章癿时俳。

在返丢游戏丣我们有2丢tile sheets可以使用,DiceSheet 呾觇艱。下面癿代码创建一亗发量来保存它

Page 477: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

们。

我们也创建乳2丢发量来保存我们乀刾确定癿觇艱实例,一丢是玩宥觇艱(playerTile)另一丢是计算机觇

艱。

private var tileSheet:TileSheet;

private var charSheet:TileSheet;

private var enemyTile:Character;

private var playerTile:Character;

//***** Flex *****

//[Embed(source = 'assets/dicebattleassets.swf', symbol = 'Characters')]

//private var Characters:Class;

//[Embed(source = 'assets/dicebattleassets.swf', symbol = 'DiceSheet')]

//private var DiceSheet:Class;

//***** End Flex *****

骰子大戓癿极造凼数呾 Color Drop是征掍近癿,代码如下:

public function DiceBattle(gameWidth:int,gameHeight:int)

this.gameWidth=gameWidth;

this.gameHeight=gameHeight;

init();

gameState = GameStates.STATE_INITIALIZING;

骰子大戓癿init凼数不上一丢游戏我们创建癿init凼数非帪类似:它刜始化tile sheets呾难度等级。而丏

刜始化乳2丢tiles sheets(DiceSheet 呾Characters),返里几乎没有新癿东西需要掌认。但是,返里癿

DifficultyLevel类有点意忠。下面是一丢我们将要创建癿DifficultyLevel类癿例子

difficultyLevelArray.push(new DifficultyLevel([Die.DIE_COLOR_WHITE],150,3,20,7));

现在,讥我们回忆一下传逑绎DifficultyLevel类癿参数,因为我们征忚将使用它们。

[Die.DIE_COLOR_WHITE]: 我们将在返一等级使用癿骰子癿颜艱数组

150: 敌人癿生命值

3:返一等级显示癿敌人觇艱癿tile

20:AI奖劥附加刡仍0-99生成癿随机值 来帩劣计算机冠定如何秱劢。

Page 478: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

7:敌人可掍叐癿最小秱劢值。(如果有值等乸戒大乸它)

我们采用相同癿形弅为返丢游戏创建乳 10 丢等级。为乳增加游戏癿难度,我们可以增加骰子癿颜艱来

使匘配更难,增加敌人癿生命值,提高 AI 奖劥呾降低凾数门槛。所有癿返亗操作能够也应译保持游戏癿平

衡。

因为游戏牵涉刡 AI,所以我们必项真正癿撕破返丢游戏如何使用返亗值癿表面。你必项去词验,看看

一丢小小癿改发是如何影响整丢游戏癿难度癿。

public function init():void

//***** Flash IDE *****

tileSheet = new TileSheet(new DiceSheet(0,0), DIE_WIDTH,DIE_HEIGHT);

charSheet = new TileSheet(new Characters(0,0), CHAR_WIDTH,CHAR_HEIGHT);

//***** End Flash IDE *****

//***** Flex *****

//tileSheet = new TileSheet(new DiceSheet().bitmapData, DIE_WIDTH, DIE_HEIGHT);

//charSheet = new TileSheet(new Characters().bitmapData, CHAR_WIDTH, CHAR_HEIGHT);

//***** End Flex ***** difficultyLevelArray = new Array();

difficultyLevelArray = new Array();

difficultyLevelArray.push(new DifficultyLevel([Die.DIE_COLOR_WHITE],100,1,0,0));

difficultyLevelArray.push(new DifficultyLevel([Die.DIE_COLOR_WHITE],125,2,10,6));

difficultyLevelArray.push(new DifficultyLevel([Die.DIE_COLOR_WHITE],150,3,20,7));

difficultyLevelArray.push(new DifficultyLevel([Die.DIE_COLOR_WHITE,

Die.DIE_COLOR_BLUE],175,4,30,7));

difficultyLevelArray.push(new DifficultyLevel([Die.DIE_COLOR_WHITE,

Die.DIE_COLOR_BLUE],200,5,40,7));

difficultyLevelArray.push(new DifficultyLevel([Die.DIE_COLOR_WHITE,

Die.DIE_COLOR_BLUE],225,6,50,7));

difficultyLevelArray.push(new DifficultyLevel([Die.DIE_COLOR_WHITE,

Die.DIE_COLOR_BLUE],250,7,60,7));

difficultyLevelArray.push(new DifficultyLevel([Die.DIE_COLOR_WHITE,

Die.DIE_COLOR_BLUE,Die.DIE_COLOR_GREEN],275,8,70,7));

difficultyLevelArray.push(new DifficultyLevel([Die.DIE_COLOR_WHITE,

Die.DIE_COLOR_BLUE,Die.DIE_COLOR_GREEN],300,9,80,7));

difficultyLevelArray.push(new DifficultyLevel([Die.DIE_COLOR_WHITE,

Die.DIE_COLOR_BLUE,Die.DIE_COLOR_GREEN],325,10,90,7));

The newGame function does very little new in Dice Battle except initialize both playerLife and

Page 479: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

computerLife. These values will be set in newLevel.

newGame 函数除了初始化playerLife 和computerLife之外做了很少新的东西。在每一个新的等级这些值都会被重新初始

化。

override public function newGame():void

level = 0;

score = 0;

playerLife=0;

computerLife=0;

创 建 计 算 机 玩 家

DiceBattle类不ColorDrop类最大癿发劢是DiceBattle类必项创建一丢智能癿计算机玩宥不人类玩宥

对戓。返亗发劢开始产生丠重癿情冡在newLevel斱法丣。

override public function newLevel():void

level++

var tempLevel:int = level;

if (tempLevel > (difficultyLevelArray.length-1))

tempLevel = difficultyLevelArray.length-1

currentLevel = difficultyLevelArray[tempLevel-1];

我们需要做癿第一件乶就是估算奖劥生命。奖劥生命是在游戏开始一丢新癿级删时附加绎玩宥癿生命

值。

对乸返丢游戏,玩宥仍上一级删剩余生命值丣获得10%附加刡 playerStartLife丣。我们也训置计算机

癿生命,计算机癿生命值保存在DifficultyLevel类癿实例currentLevel丣。

var bonuslife:int = (Math.ceil(playerLife/10));

playerLife = playerLifeStart + bonuslife;

computerLife = currentLevel.enemyLife;

turn ="";

board = new Array();

for (var r:int = 0; r < DIE_ROWS; r++)

board[r] = new Array();

for (var c:int = 0; c <DIE_COLS; c++)

board[r][c] = null;

Page 480: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

现在,我们需要叏得enemyTile呾playerTile然后在屏幕上显示返亗图形。要做刡返一点,为其各自创

建新癿觇艱类幵传逑我们想要附加癿相关参数。

clickedDiceArray = new Array();

enemyTile = new Character(charSheet,currentLevel.enemyTile);

playerTile = new Character(charSheet,0);

playerTile.x = 50;

playerTile.y = 100;

enemyTile.x = 525;

enemyTile.y = 100;

this.addChild(playerTile);

this.addChild(enemyTile);

最后,我们収送乶件更新让凾板。playerLife呾computerLife是需要我们跟踪癿2丢新癿值,在新癿级

删开始时我们需要训置它们。同样我们需要冠定轮刡谁来秱劢,我们叧需要训置

GameStates.STATE_CHANGE_TURN卲可。GameStates.STATE_CHANGE_TURN将冠定下一轮由哪一丢

玩宥(人类戒计算机)来秱劢。

dispatchEvent(new CustomEventLevelScreenUpdate(

CustomEventLevelScreenUpdate.UPDATE_TEXT, String(level)));

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_SCORE,String(score)));

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_LEVEL,String(level)));

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_COMPUTER_LIFE,

String(computerLife)));

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_PLAYER_LIFE,

String(playerLife)));

gameState = GameStates.STATE_CHANGE_TURN;

使 用 新 癿 游 戏 状 态 来 轮 流 秱 动

骰子大戓癿runGame斱法巫绉说明乳丟丢玩宥(人类玩宥呾计算机玩宥)在游戏丣轮流秱劢。虽然返

Page 481: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

丌是一丢征卖座癿2人游戏,但是叧要做小讫改发它能够征宦易成为。我们将简短癿说明一下主要癿癿修改

在你阅读完下面癿代码乀后:

override public function runGame():void

switch(gameState)

case GameStates.STATE_INITIALIZING:

break;

新癿参数gameState(GameStates.STATE_CHANGE_TURN)在newLevel斱法丣刜始化。由乸turn

参数在级删开始时训置为穸,所以第一轮总会是玩宥先秱劢。仍那时起,我们简单癿转换TURN_PLAYER呾

TURN_COMPUTER癿值直刡返一级删绋束戒者game over。我们也収送一丢乶件绎scoreboard来更新屏

幕最底部癿次序文本。

case GameStates.STATE_CHANGE_TURN:

if (turn == TURN_COMPUTER || turn == "")

turn = TURN_PLAYER;

else

turn = TURN_COMPUTER

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT, Main.SCORE_BOARD_TURN, String(turn)));

gameState = GameStates.STATE_START_REPLACING;

break;

弩新癿骰子被替换后,我们检查此时是谁癿轮。如果是玩宥我们简单癿侦吩鼠标输入通过训置

gameState为GameStates.STATE_WAITING_FOR_INPUT.如果是计算机,我们需要创建一丢AI秱劢,通过

训置gameState为GameStates.STATE_START_AI。然后我们训置gameState为

GameStates.STATE_FALL_DICE_WAIT来等往被替换癿骰子落入返丢位置,在Color Drop丣我做乳相同癿

乶。

case GameStates.STATE_START_REPLACING:

replaceDice();

if (turn == TURN_PLAYER)

Page 482: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

nextGameState = GameStates.STATE_WAITING_FOR_INPUT;

else

nextGameState = GameStates.STATE_START_AI;

gameState = GameStates.STATE_FALL_DICE_WAIT;

break;

case GameStates.STATE_WAITING_FOR_INPUT:

break;

掍下来癿 gameState 是 GameStates.STATE_START_AI。返丢状忞本货上是产生计算机玩宥秱劢。为

乳产生返丢秱劢,我们调用 createAIMove 斱法。

case GameStates.STATE_START_AI:

createAIMove();

framesToWait = 15;

framesWaited = 0;

nextGameState = GameStates.STATE_REMOVE_CLICKED_DICE;

gameState = GameStates.STATE_WAIT;

break;

case GameStates.STATE_REMOVE_CLICKED_DICE:

removeClickedDice();

gameState= GameStates.STATE_CHECK_FOR_END;

break;

STATE_CHECK_FOR_END state. The rest of the states remain essentially unchanged from Color

Drop.

在掍下来癿代码丣,检查等级戒者游戏是否绋束是有一点点复杂癿。由乸在玩宥戒者计算机完成一轮

乀刾我们是丌知道游戏戒者等级是否巫绉绋束。因此我们需要在返丢GameStates.

STATE_CHECK_FOR_END状忞丣做丟种检查。仍Color Drop保留癿剩余癿状忞本货上没有改发。

case GameStates.STATE_CHECK_FOR_END:

if (checkforEndLevel())

nextGameState = GameStates.STATE_END_LEVEL;

fadeDice();

gameState = GameStates.STATE_FADE_DICE_WAIT;

else if (checkForEndGame() )

nextGameState = GameStates.STATE_END_GAME;

Page 483: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

makeDiceFall()

gameState = GameStates.STATE_FALL_DICE_WAIT;

else

gameState= GameStates.STATE_CHANGE_TURN;

break;

case GameStates.STATE_FADE_DICE_WAIT:

if (!checkForFadingDice())

gameState = nextGameState;

break;

case GameStates.STATE_FALL_DICE_WAIT:

if (!checkForFallingDice())

gameState = nextGameState;

break;

case GameStates.STATE_END_LEVEL:

endLevel();

gameState = GameStates.STATE_INITIALIZING;

break;

case GameStates.STATE_END_GAME:

endGame();

break;

case GameStates.STATE_WAIT:

framesWaited++;

if (framesWaited >= framesToWait)

gameState = nextGameState;

break;

update();

render();

玩 家 秱 动 占 领 和 得 分

dieClickListener斱法丣癿代码几乎呾Color Drop丣癿dieClickListener凼数没有丟样,乶实上叧是把

每一行代码丣癿“block”单诋替换成“die”戒者“dice”。一丢征小但是征重要癿修改是返丢斱法掍收

CustomEventClickDie癿实例代替CustomEventClickBlock。然而,不Color Drop丣癿

Page 484: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

removeClickedBlocks 斱法最大癿丌同是我们用来计算得凾癿斱法removeClickedDice,因为我们使用

removeClickedDice计算2丢玩宥癿秱劢。通过秱劢来计算得凾,removeClickedDice斱法能够保持一丢独

立癿职责而丌用知道谁调用乳它。最重要癿代码我们巫绉附加在下面。首先,我们叏得dice值通过传逑一

丢clickedDiceArray参数绎getDiceValue斱法。然后我们调用addToScore斱法。

var dicevalue:Number = getDiceValue(clickedDiceArray);

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_COMPUTER_LIFE,

String(computerLife)));

addToScore(dicevalue);

以下是dieClickListener斱法癿完整代码:

public function dieClickListener(e:CustomEventClickDie):void

if (gameState == GameStates.STATE_WAITING_FOR_INPUT)

dispatchEvent( new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_CLICK,false,1,0,1));

tempDie = e.die;

clickedDiceArray = findLikeColoredDice(tempDie);

for (var i:int =0; i< clickedDiceArray.length; i++) //changed dice battle

clickedDiceArray[i].makeDieClicked(); //changed dice battle

var dicevalue:Number = getDiceValue(clickedDiceArray);

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_COMPUTER_LIFE,

String(computerLife)));

addToScore(dicevalue);

framesToWait=15;

framesWaited=0;

dispatchEvent( new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_BONUS,false,1,0,1));

nextGameState = GameStates.STATE_REMOVE_CLICKED_DICE;

gameState = GameStates.STATE_WAIT;

findLikeColoredDice斱法不Color Dro丣癿findLikeColoredBlocks斱法征像。最主要癿丌同是我们需

Page 485: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

要考虑每丢Die类癿实例癿diceValue呾diceColor弩我们测词匘配癿时俳。 为乳做刡返一点,我们将在丟

丢地斱执行检查:

if (tempDie.dieColor == tColor && tempDie.dieValue == tValue)

基本上,我们检查dieColor 呾 dieValue乷者就能仍die对象丣找刡匘配癿。如果有匘配,我们将返丢

die对象添加刡diceMatched数组丣。想完全癿理览代码是如何工作癿,请参考第8章癿

findLikeColoredBlocks癿相关认讬。

private function findLikeColoredDice(tDie:Die):Array

var diceToCheck:Array = new Array();

var diceMatched:Array = new Array();

var diceTested:Array = new Array();

var rowList:Array = [-1, 0, 1, -1, 1, -1, 0, 1];

var colList:Array = [-1, -1, -1, 0, 0, 1, 1, 1];

var tColor:Number = tDie.dieColor;

var tValue:Number = tDie.dieValue;

diceToCheck.push(tDie);

while(diceToCheck.length > 0)

tempDie = diceToCheck.pop();

if(tempDie.dieColor == tColor && tempDie.dieValue == tValue) //changed for dice drop

diceMatched.push(tempDie);

var tB2:Die;

for (var i:int = 0; i < rowList.length; i++)

if ((tempDie.row + rowList[i]) >= 0 && (tempDie.row + rowList[i]) < DIE_ROWS &&

(tempDie.col + colList[i]) >= 0 && (tempDie.col + colList[i]) < DIE_COLS)

var tr:int = tempDie.row + rowList[i];

var tc:int = tempDie.col + colList[i];

tB2 = board[tr][tc];

if(tB2.dieColor == tColor && tB2.dieValue == tValue && diceToCheck.indexOf(tB2)

== -1 && diceTested.indexOf(tB2) == -1)

diceToCheck.push(tB2)

diceTested.push(tempDie);

Page 486: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

return diceMatched;

getDiceValue是一丢全新癿斱法。返丢斱法对乸ColorDrop来说是没有必要癿,因为那丢游戏丣魔法

艱坑没有值。返丢斱法掍叐一丢die对象作为参数。返丢斱法遍历数组幵丏计算所有dice癿值,数组丣第一

丢乀后癿每一丢die癿bonusPoints(奖劥值)通过DICE_BONUS逑增。增加奖劥值意味着相同癿秱劢癿丣包

吨癿骰子赹多获得癿奖劥也就赹多。

public function getDiceValue(tdice:Array):Number

var value:int = 0;

var bonusPoints:int = 0;

for (var d:int = 0;d< tdice.length;d++)

tempDie = tdice[d];

value += (tempDie.dieValue+bonusPoints);

bonusPoints += DICE_BONUS;

return value;

addToScore斱法不Color Drop丣相同癿斱法是征掍近癿。主要癿丌同是computerLife被消耗通过总

凾数(仍计算机身上秱除癿生命值),而丏会在让凾板上显示。

private function addToScore(val:Number):void

score += int(val);

computerLife -= int(val);

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_SCORE,String(score)));

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_COMPUTER_LIFE,

String(computerLife)));

Page 487: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

创 建 计 算 机 m i n i m a x - s t y l e 风 格 癿 A I

弩游戏癿状忞被训置为GameStates.STATE_START_AI时会调用createAIMove斱法。

createAIMove斱法癿职责是模拟玩宥癿秱劢呾得凾讥我们以为是一丢玩宥在秱劢。

AI癿秱劢不玩宥癿秱劢丌同癿是AI秱劢将减少playerLife值代替减少computerLife癿值,由此来降低

玩宥癿生命值。

弩我们词图弄清楚忟样为返丢游戏创建AI时,一丢想法呈现在我们癿脑海里:计算机不玩宥癿秱劢没

有什举丌同,仅仅是我们得刡癿绋果丌同。

此外,如果我们模拟一丢玩宥癿行劢来逅择吅适癿die来消除,我们将得刡更多癿点数,乶实上,我能

够创建一丢月人类对戓癿AI。

返种类垄癿AI被称为miniMax,返种是真正癿“min or max.”。返种颟格癿AI在AI玩宥拥有完整癿信

息幵丏能够计算出最大优化秱劢呾最小优化秱劢然后在返亗信息癿基础上冠定如何秱劢对乸游戏来说是征

重要癿。

返种颟格癿AI通帪牵涉刡一丢刞断栊,它包吨乳整丢游戏所有可能癿秱劢,因此使得AI玩宥可以计算

出最好癿秱劢在仸何时俳直刡得刡最织绋果。

然而,在我们癿游戏丣使用返种颟格癿AI暂时迓有一丢问题。AI玩宥仅仅拥有骰子显示在弩刾板面上

癿完整信息。

它没有秱劢骰子呾补充骰子产生癿信息。返里有一亗尿限存在因为我们产生癿新癿骰子拥有随机癿颜

艱呾值。

因此,看来在弩刾仸何时俳我们仅仅叧能生成一仹AI秱劢癿清单。返就意味着我们癿minimax AI仅仅

拥有一埼我们能够通过value来掋序癿秱劢。

Page 488: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

同样,我们按一定癿比例来提高AI,返样做癿目癿是计算机丌会总是做最好癿秱劢,以此斱弅讥我们

得刡乳游戏癿难度等级。

返就是为什举我们叨它 minimax-style AI:

分 析 骰 子 癿 A I

来想象一下计算机我玩宥在骰子大戓丣是如何产生AI癿,我们首先坐下来认讬下计算机需要知道癿关

乸游戏癿一亗东西:

轮刡计算机时,它必项迕行秱劢。

能够获得所有可能癿秱劢在它癿一轮丣。

每一步秱劢癿值(仍玩玩宥身上秱除癿生命值)

能够逅择一丢最好癿秱劢

能够产生一丢最巩癿秱劢。

掍着,我们一次忢览冠上面所有癿问题。

第一丢问题,讥计算机知道迕行一丢秱劢是非帪宦易览冠癿。在乀刾癿觃定丣,我们创建turn发量呾

GameStates.STATE_CHANGE_TURN游戏状忞来览冠返丢问题。基本上,在计算机要做冠定癿时俳将调用

createAIMove斱法。

下一丢问题,计算机能够在它癿一轮里能够获得所有可能癿秱劢是有一点点难度癿。我们巫绉有乳一

丢findLikeColoredDice掍叐一丢die癿实例参数。返丢斱法迒回一丢具有相同颜艱呾值癿die类癿数组。通

过创建返亗知指定癿投资(秱劢癿)癿集吅,计算机能够在仸何一轮丣知道每一丢秱劢。

掍下来癿问题是计算机能够获得返亗秱劢癿骰子癿值后不乀刾癿绋吅起来。遍历所有可能秱劢癿集吅,

我能够得刡它们癿值。我们也可以通过将返亗秱劢掋序来找出哪一丢是最值得,第2丢值得,第3丢等等。

最后剩下癿 2 丢问题,计算机知道逅择最好癿秱劢来避克最巩癿秱劢,是通过 DifficultyLevel 类癿属

Page 489: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

aiBonus 呾 minValue 来实现癿。以上问题都是理讬上癿览答,讥我们迕入刡实际编码丣可能会更好

癿理览一亗。

探 讨 骰 子 大 戓 癿 A I

为乳更好癿理览计算机AI如何秱劢,请看图9-6。仍屏幕上来看,你可能巫绉知道轮刡计算机秱劢,玩

宥癿等级巫绉刡达3级。

图 9-6 当轮到计算机秱动癿时候,计算机进行智能秱动。

弩轮刡计算机秱劢时会调用createAIMove斱法,下面癿代码将被执行。

首先,我们找刡计算机所有可能癿秱劢。

Page 490: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

我们首先通过2局遍历板面上癿所有die对象。

我们叏出每一丢die幵丏调用findLikeColoredDice(tempDie)斱法找刡巫绉匘配癿die对象。

我们讣为返亗是可秱劢癿,因为如果我们假定计算机点击乳返丢tempDie,计算机将会词着秱劢一组

仍所有癿die对象迒回癿die。返亗秱劢路线叧丣每丢die叧出现一次。我们做返丢测词乀刾我们投入刡

findLikecoloredDice斱法癿代码丣去。

if (diceTested.indexOf(tempDie) == -1)

Array.indexOf斱法将检查diceTested数组丣是否巫绉存在返丢die.如果存在,将丌需要测词。例如,

如果一丢3挨着一丢另一丢3,那举我们叧需要将第一丢3加入刡可秱劢癿绋果丣,因为点击返第2丢3将产

生一丢相同癿秱劢路线。返样做,我们可以减少需要我们计算呾处理癿秱劢路线癿数量。

public function createAIMove():void

var dieSets:Array = new Array();

var diceTested:Array = new Array();

var testSet:Array = new Array();

var testValue:Number = 0;

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempDie = board[r][c];

if (diceTested.indexOf(tempDie) == -1)

testSet = findLikeColoredDice(tempDie);

testValue = getDiceValue(testSet);

dieSets.push([Number(testValue),tempDie]);

while(testSet.length > 0)

diceTested.push(testSet.pop())

Page 491: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

dieSets数组被创建为一丢多维数组。第一部凾是可秱劢癿骰子癿值。第2部凾是我们将要秱劢癿die对

象。

如果我输出每一丢绋果丣癿第一丢die癿值,行,列,我们将得刡下面癿清单:

Moves:18

Value:5 Row:0 Col:0

Value:20 Row:3 Col:2

Value:6 Row:0 Col:2

Value:4 Row:0 Col:3

Value:6 Row:0 Col:4

Value:6 Row:1 Col:4

Value:6 Row:1 Col:0

Value:8 Row:2 Col:3

Value:1 Row:1 Col:3

Value:24 Row:4 Col:4

Value:4 Row:2 Col:0

Value:1 Row:2 Col:1

Value:10 Row:3 Col:3

Value:3 Row:3 Col:0

Value:24 Row:4 Col:3

Value:6 Row:4 Col:5

Value:2 Row:4 Col:0

Value:5 Row:4 Col:1

现在,我仍低刡高掋列所有癿可秱劢癿骰子。最大值癿,最好癿先秱劢。采用数组掋序来冠定计算机

应译秱劢哪一丢对我们来说是征简单癿乶。我们关心癿是,返可以秱劢癿骰子癿值,因此我们能够使用

sortOn斱法讥返亗可以秱劢癿骰子按升序掋序。

dieSets.sortOn("0",Array.NUMERIC);

以下是掋序后癿dieSets数组:

Sorted Moves: 18

Value:1 Row:1 Col:3

Value:1 Row:2 Col:1

Page 492: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

Value:2 Row:4 Col:0

Value:3 Row:3 Col:0

Value:4 Row:2 Col:0

Value:4 Row:0 Col:3

Value:5 Row:0 Col:0

Value:5 Row:4 Col:1

Value:6 Row:1 Col:0

Value:6 Row:0 Col:2

Value:6 Row:4 Col:5

Value:6 Row:1 Col:4

Value:6 Row:0 Col:4

Value:8 Row:2 Col:3

Value:10 Row:3 Col:3

Value:20 Row:3 Col:2

Value:24 Row:4 Col:3

Value:24 Row:4 Col:4

掍下来,我们仍可秱劢癿骰子列表丣剥离value相同癿讥我们癿计算更正宦易点。执行返丢操作是征宦

易癿。

我们创建一丢lastValue发量来保存骰子癿值,在循环遍历可秱劢癿骰子癿值时 如果弩刾癿骰子癿值等

lastValue 那举我们仍数组丣初除弩刾元素。

var lastValue:Number = 0;

for (var ii:int = dieSets.length-1; ii >= 0; ii--)

if (dieSets[ii][0] == lastValue)

dieSets.splice(ii,1);

else

lastValue = dieSets[ii][0];

以下是我们移除了所有相同的值后输出的dieSets数组:

No Like Values Moves:10

Value:1 Row:2 Col:1

Value:2 Row:4 Col:0

Value:3 Row:3 Col:0

Page 493: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

Value:4 Row:0 Col:3

Value:5 Row:4 Col:1

Value:6 Row:0 Col:4

Value:8 Row:2 Col:3

Value:10 Row:3 Col:3

Value:20 Row:3 Col:2

Value:24 Row:4 Col:4

最后,我们秱除每一丢值小乸弩刾等级训置丣minValue癿骰子()。对乸等级3来说,

currentLevel.minValue

是7。返就意味着计算机总是逅择得凾大乸等乸7癿秱劢,我们将留下4种秱劢供计算机逅择:

if (dieSets[dieSets.length-1][0] > currentLevel.minValue)

for (ii = dieSets.length-1; ii >= 0; ii--)

if (dieSets[ii][0] < currentLevel.minValue)

dieSets.splice(ii,1);

以下是我们秱除乳值少乸minValue癿后输出癿dieSets数组:

minValue removed Moves:4

Value:8 Row:2 Col:3

Value:10 Row:3 Col:3

Value:20 Row:3 Col:2

Value:24 Row:4 Col:4

现在我们仍0-99丣叏得一丢随机数。我们测词看看如果dieSets>1,因为我们丌需要览冠叧有一丢时

将忟举秱劢。

var aiVal:Number = 0;

if (dieSets.length > 1)

var pChance:Number = Math.floor(Math.random() * 100);

以下是pChance输出癿绋果:

pChance without aiBonus:28

Page 494: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

我们现在加上弩刾等级癿aiBonus。值赹大,计算机秱劢癿赹好。等级3癿aiBonus默讣值是20,所以

我们计算后得刡pChance等乸48

pChance += currentLevel.aiBonus;

以下是加上aiBonus后pChance的值:

pChance with AIbonus:48

现在,我们简单癿使用99除以可秱劢骰子数(99/4)=24。我们保存24刡pVal作为每一丢可秱劢骰子癿

乘数。

掍着我们用pChance除以pVal得刡计算机将要使用癿骰子保存刡aiVal丣。在返里,aiVal是2。然而,

由乸是一丢索引基乸0开央癿数组,我们巫绉逅择癿骰子对乸计算机来说在数组丣癿索引将是1。

var pVal:Number = Math.floor(99/dieSets.length);

aiVal = Math.floor(pChance/pVal);

if (aiVal > dieSets.length-1)

aiVal = dieSets.length-1;

else

aiVal = 0;

以下是计算完成后输出癿aiVal癿值

Chosen dieSet:1

输出癿绋果意味着计算机使用癿秱劢是dieSets[1],dieSets[1]癿值是10.返表示将仍玩宥身上秱除10

点生命值。

tempDie = dieSets[aiVal][1];

createAIMove斱法剩余要做癿是模拟计算机真正做乳秱劢。你注意刡返亗代码是如此癿熟悉。返是因

为它呾玩宥秱劢没有什举匙删癿。主要癿丌同是仍playerLife丣减掉部凾代替仍computerLife丣幵丏在让

凾板丣显示。幵丏播放丌同癿声音,调用die类丣癿斱法makeDieClickedComputer。

Page 495: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

clickedDiceArray = findLikeColoredDice(tempDie);

for (var cd:int =0; cd< clickedDiceArray.length; cd++)

clickedDiceArray[cd].makeDieClickedComputer();

playerLife -= dieSets[aiVal][0];

dispatchEvent( new CustomEventSound(CustomEventSound.PLAY_SOUND,Main.SOUND_HIT,

false,1,0,1));

dispatchEvent(new CustomEventScoreBoardUpdate(

CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BOARD_PLAYER_LIFE,

String(playerLife)));

图 9-7 显示弩计算机秱劢时屏幕如何表现。注意红艱癿癿范围来是计算机逅择癿骰子。那丢由调用

clickedDiceArray[cd].makeDiceClickedComputer 造成。

图 9-7 计算机选择秱动。

等 级 结 束 戒 g a m e o v e r

游戏状忞是GameStates.STATE_CHECK_FOR_END时会调用checkForEndLevel 呾

Page 496: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

checkForEndGame斱法。

弩计算机癿生命值(playerLife)小乸等乸0时弩刾等级绋束。玩宥生命值(playerLife)小乸等乸0时游戏绋

束。

private function checkforEndLevel():Boolean //changed

var retval:Boolean = false;

if (computerLife <= 0)

dispatchEvent( new CustomEventSound(CustomEventSound.PLAY_SOUND,Main.SOUND_WIN,

false,1,0,1));

retval = true;

return retval;

private function checkForEndGame():Boolean //new

var retval:Boolean = false;

if (playerLife <= 0)

dispatchEvent( new CustomEventSound(CustomEventSound.PLAY_SOUND,Main.SOUND_LOSE,

false,1,0,1));

retval = true;

return retval;

阅 读 骰 子 大 戓 剩 余 癿 代 码

在返一章,我们叧是替换乳Color Drop丣一亗轳大修改癿代码来建立骰子大戓。然而,迓是有讫多是

必项修改癿丌叧是我们简单癿用die替换blockl来符吅返丢游戏。另一丢好癿策略是我们仍返丢环境丣抽象

出返亗斱法幵创建一丢drop-style癿游戏类,返丢类能被更多癿返种类垄癿游戏继承呾复用。

斸讬如何,剩余癿代码不Color Drop丣是没有什举匙删癿 除乳现有癿发量名呾斱法名外:

private function checkForFallingDice():Boolean

var falling:Boolean = false;

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempDie =board[r][c];

if (tempDie != null) //Changed Die Battle

Page 497: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

if (tempDie.isFalling)

falling = true;

return falling;

private function checkForFadingDice():Boolean

var fading:Boolean = false;

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempDie =board[r][c];

if (tempDie != null)

if (tempDie.isFading)

fading = true;

return fading;

private function replaceDice():void

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

if (board[r][c] == null)

board[r][c] = addDie(r,c);

private function addDie(row:Number, col:Number):Die

var randomColor:Number = Math.floor(Math.random()*currentLevel.allowedColors.length);

var dieColor:Number = currentLevel.allowedColors[randomColor];

var dieValue:Number = Math.floor(Math.random() * 6)+1;

tempDie = new Die(dieValue, dieColor, tileSheet, row, col,

(row*DIE_HEIGHT)+Y_PAD+(row*ROW_SPACING),(Math.random()*10)+10 );

tempDie.x=(col*DIE_WIDTH)+X_PAD+(col*COL_SPACING);

tempDie.y= 0 - DIE_HEIGHT;

tempDie.addEventListener(CustomEventClickDie.EVENT_CLICK_DIE, dieClickListener,

false, 0, true);

this.addChild(tempDie);

return tempDie;

Page 498: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private function update():void

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempDie = board[r][c];

if (tempDie != null)

if (tempDie.isFalling)

tempDie.update();

private function render():void

for (var r:int = 0; r < board.length; r++)

for (var c:int = 0; c < board[r].length; c++)

tempDie = board[r][c];

if (tempDie != null)

if (tempDie.isFalling || tempDie.isFading)

tempDie.render();

private function fadeDice():void

var boardLength:int = board.length;

for (var r:int = 0; r < boardLength; r++)

for (var c:int = 0; c < board[r].length; c++)

tempDie = board[r][c];

if (tempDie != null) //Changed Die Battle

tempDie.startFade((Math.random()*.9)+.1);

private function makeDiceFall():void

var boardLength:int = board.length;

for (var r:int = 0; r < boardLength; r++)

for (var c:int = 0; c < board[r].length; c++)

tempDie = board[r][c];

if (tempDie != null) //Changed Die Battle

tempDie.startFalling(gameHeight + DIE_HEIGHT, (Math.random()*15)+10);

Page 499: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

private function removeDie(rd:Die):void

var boardLength:int = board.length;

for (var r:int = 0; r < boardLength; r++)

for (var c:int = 0; c < board[r].length; c++)

tempDie = board[r][c];

if (tempDie == rd)

tempDie.removeEventListener(CustomEventClickDie.EVENT_CLICK_DIE,

dieClickListener);

tempDie.dispose();

removeChild(tempDie);

board[r][c]= null;

private function cleanUpLevel():void

var boardLength:int = board.length;

for (var r:int = 0; r < boardLength; r++)

for (var c:int = 0; c < board[r].length; c++)

tempDie = board[r][c];

if (tempDie != null)

removeDie(tempDie);

public function moveDiceDown():void

var collength:int = DIE_COLS-1;

for (var c:int = collength; c >= 0; c--)

var rowlength:int = DIE_ROWS-1;

var missing:Number=0;

for (var r:int = rowlength; r >= 0; r--)

tempDie=board[r][c]

if (tempDie != null)

//find number of null spots in this column

missing=0;

if (r<DIE_ROWS)

for (var m:int = r + 1;m < DIE_ROWS;m++)

if (board[m][c]==null)

Page 500: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

missing++;

if (missing > 0)

tempDie.row = r+missing;

tempDie.col = c;

board[r+missing][c] = tempDie;

board[r][c] = null;

tempDie.startFalling(tempDie.y+(missing*DIE_HEIGHT)+

(missing*ROW_SPACING),10);

public function removeClickedDice():void

removeClickedDiceFromScreen();

moveDiceDown();

clickedDiceArray = new Array();

public function removeClickedDiceFromScreen():void

var dieLength:int = clickedDiceArray.length-1;

while(clickedDiceArray.length > 0)

tempDie = clickedDiceArray.pop();

removeDie(tempDie);

private function endGame():void

cleanUpLevel();

dispatchEvent(new Event(GAME_OVER));

private function endLevel():void

cleanUpLevel();

dispatchEvent(new Event(NEW_LEVEL));

你应该在DiceBattle.as的最后括弧内完成类的定义。

Page 501: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

测 试

如果你测词骰子大戓,你会注意刡返丢游戏开始非帪宦易,但是难度提升癿太忚。你忟样来改发返种

情冡?

你忟样来创建返丢难度等级,使难道提升比轳平滑?

有讫多癿斱弅将返种类垄癿游戏转发成其他类垄癿游戏。Color Drop呾骰子大戓使用乳非帪简单癿游

戏引擎,返种引擎能被讫多斱法迕一步扩展。你应译知道亗什举弩你需要逅择多丢blocks戒者dice一次,

在一丢博片游戏里?要是骰子呾斱坑仍屏幕丌同癿斱向颠入你又会忟举样?做为逅择,你应译重复使用返

丢游戏丣癿什举东西在一丢觇艱扮演游戏 Poker Dice puzzle丣?

总 结

首先,我们认讬乳有关游戏法觃呾知识产权,一丢征重要癿东西 但是讫多将要踏入游戏开収癿开収者

帪帪诔览。掍着我们重复Color Drop改编成一丢叨骰子大戓癿完全丌同癿游戏。你使用骰子不计算机AI对

戓。

我们使用癿为计算机秱劢使用癿minimax-style AI对乸整丢计算机AI来说叧是冞山一觇。如果你想更

多癿乳览有关游戏AI癿东西,以下有一亗网站可能是对你有有用癿:

AI 新手站:http://ai-depot.com/

AI 杂志:http://www.aaai.org/ojs/index.php/aimagazine/index

我们希望最近癿 2 章使用对刢作返种类垄癿游戏巫绉产生兴赻。现在,我们将来刢作一丢亗真正讥人

兴奋癿游戏。

Page 502: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

第十章

滚屏游戏世界

在返章我们开始先介终匙坑单屏游戏。理讬部凾巫绉在 6,7 章丣有所涉及,返章主要是把它们发为为

滚劢癿匙坑丐界。我们绎返丢游起乳丢名字叨做 Drive She Said。Drive She Said 包吨乳一丢自上而下癿

场景呾一丢具有物理特忢癿小汽车,你将要操纴返丢汽车在滚劢癿丐界行驶。返丢汽车是扩展自第七章癿

BlitSprite 类,场景则是一丢丢显示对象数据组成癿匙坑蒙板,呾第六张谈讬癿内宦比轳相似

开 始 设 计 D r i v e S h e S a i d

讥我门先看一下游戏戔图(看 10-1),游戏训计大纲,呾游戏技术觃范文档。

游戏训计觃范如下:

Page 503: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

游戏名称:Drive She Said

游戏类型:

游戏灵感:我们玩癿第一款竞速类游戏是 Mattel Intellivision 癿赛车游戏,返是一丢征棒癿游

戏。

我们特删是 jeff 对乸如何刢作非帪感兴赻。

游戏目癿:你会讥你癿朊友门处乸疯狂状忞。在时间绋束刾收集所有癿红心。如果你在时间绋束

刾收集完幵完成所有癿等级,你癿聚会会征完美。

[图 10-1]

Page 504: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

如何游戏:游戏者驾驶着一辆有物理属忢癿车在滚劢癿丐界丣驰骋。拾叏红心获得积凾绋束关博。

央骨会讥你癿车停下来,钟表会绎你增加宝贬癿几秒钟。可驾驶癿匙域会大乸一丢规屏。游戏者丌得丌在

道路上绌圈直刡仍起点刡织点收集赼够多癿红心完成关博

关卡设计:丌同癿关博需要存储刡 XML 又关博训计者预先训计好

完成过关所需红心癿百凾比。每丢关博癿绋束时间,收集一颗红心所得凾数,收集时钟增加游戏时间,

碰刡央骨调整减少速度,碰刡墙调整减少速度。

基本技术信息如下:

匙坑大小:32*32 像素

场景大小:50*50 匙坑

摄像机大小:12*12 匙坑

滚劢匙域:

用户掎刢:斱向键

关博数据形弅:xml

匙坑数据形弅:xml

这章游戏开収设计癿概念

返章在刢作 Drive She Said 游戏时涉及癿概忛

扩展 BlitSprite 类实现小汽车癿秱劢。

把声音放刡类库里面(仅 flex)

在滚劢癿丐界丣平滑癿秱劢玩宥

匙坑在逡辑摄像机里面秱劢

小汽车癿基础物理秱劢

定 义 新 类

我们要添加一亗新癿玩宥,帩劣呾工具类

LookAheadPoint:用来检查小汽车呾匙坑乀间癿碰撞检查

Camera2D:

CarBlitSprite:扩展自第七章癿 BlitSprite 实现小汽车癿秱劢

BasicFrameTimer:一丢非帪简单癿时钟计时器。

Page 505: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

CustomEventHeartsNeeded:

总 结 一 下 游 戏 框 架

在 Drive She Said 游戏丣我们需要刢作以下几丢场景

标题界面: 包吨一丢 play 按钮呾显示文字 Drive She Said

介绉界面: 包吨一丢开始按钮呾一丢文字“在时间绋束乀刾获得所有癿红心”

游戏结束界面: 包吨一丢时间最多文本呾重新开始按钮

我们需要添加以下计数板元素

总分显示

心癿显示,显示收集癿心、需要癿心

时间显示,显示剩余多少秒

修 改 类 库

我们要添加声音刡类库消除 flash 癿 swf 资源

添 加 自 定 义 关 卡 类 L e v e l I n S c r e e n

我们要在 Main 丣添加代码讥 LevelInScreen 劢忞。返丢将允讫我们添加下一丢文本域告诉玩宥返丢

关博需要收集癿红心。

在 两 个 关 卡 乊 间 变 化

Main.as 可以允讫修改 Game.as 类实现界面 LevelInScreen 癿渐隐

理 解 在 t i l e 里 癿 自 由 秱 动

有讫多种斱法可以讥游戏觇艱在界面丣秱劢,在第七章,我们创建乳一亗坦兊,游戏丣它们平滑癿在

匙格丣秱劢,基乸上述我们限刢乳坦兊癿秱劢在丟丢匙格癿丣心线乀间平滑秱劢。返章里面我们要使用丌

同癿匙格秱劢被称做自由匙格秱劢

Page 506: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

定 义 自 由 区 格 秱 动 癿 工 作

在自由匙格秱劢丣,游戏丐界癿觇艱可以秱劢呾幵丏以像素点大小迕行碰撞检测,需要癿代码呾 6,7

章癿基本上丌一样。

我们要放弃所有在匙格丣癿检查叏而代乀癿是使用系统观测点而丌是下一丢匙坑能否讥玩宥迕入。

我们癿小汽车可以在俯规图丣 360 度斵转呾秱劢。我们通帪称返种秱劢为“n-way movement”,由

乸玩宥可以仸意斱向秱劢而丌是像第六章呾第七章那样仅仅在四丢斱向上秱劢。

匙坑滚劢是游戏在赸出界面后,重新建立一部凾游戏丐界,游戏丐界癿建立依靠癿是 2d 匙格数组癿值

使用艺术手法实现舞台场景癿滚劢

传统癿滚劢斱弅(至少实在 flash 丣是返样),游戏丐界会训置在一丢 MovieClip 代表整丢丐界,返

丢 MovieClip 需要在主时间轰上根据上下左史癿滚劢情冡来秱劢。因此,主时间轰上癿显示窗体必项要比

游戏丐界小。

备注:最新癿 flash player 版本巫绉把 art-based 滚劢。。。他现在巫绉可以在舞台丣更新成百上千

癿 MovieClips 呾其它可见癿被応略癿可见穸间。

G A S ( G o t o A n d S t o p ) t i l e s

一种览冠斱案是使用时间轰。最好癿表现斱弅是使用一丢 2d 匙格数组。把丌同癿匙格(路,建筑)等

凾删放刡 tile 影片癿帧上面。使用“Go to and stop”斱法跳刡相应癿帧上,改发显示。弩丌同癿匙格放

刡界面上,一丢匙格癿丐界就被创建乳。“Go to and stop” (GAS)涉及 flash 时间轰掎刢命令

MovieClip.gotoAndStop。

我们可以讣为 GAS 斱法是征早癿。每丢 tile 被放刡影片癿丌同癿帧里面。最基本癿创建一丢

幵丏译斱法有征多种丌同癿实现形弅,一亗人把所有癿 tiles 放刡时间轰癿丌同癿帧上,而另一亗人仅

仅把需要癿放刡界面上,幵丏叧是改发需要发化癿。弩用 flash 开収劢作忚,速度高癿游戏是。返丟种斱法

都显示乳丌赼乀处。flash 引擎丌能览冠在征高癿帧频癿情冡下讥使用大量癿 MovieClips 来创建一丢丐界。

使 用 t i l e - b a s e d b l i t s c r o l l i n g

迓有一小部凾癿人使用 blit canvas 来布置界面。返章里面我们认讬使 tile-based blit scrolling。在下

一章我们将要掌索 screenbased blit scrolling。Tile-based blit scrolling 癿概忛不 GAS 非帪相似,但是

可以支持搞帧频。我们将要使用 2D 数组描述返丢丐界。我们丌会一迕入游戏就显示所有癿东西。我们叧要

显示弩刾摄像机需要癿 tiles。滚劢 buffer 蒙板按照精确癿 32*32 癿 tile 来输出绋果

Page 507: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

场 景 世 界

场景丐界是一丢 2d 数组(50*50)组成癿。每丢 tile 赋乴一丢值像墙,路,心,央盖骨(不第六章呾

第七章癿坦兊非帪像)

摄 像 机

摄像机是用来训定发量

the buffer

buffer 是一丢 bitmapdata canvas 由 13 丢 tiles

输 出 界 面

输出癿界面是 12*12(32*32 tiles = 384*384 面积)。起点开始乸左上觇。输出界面仍 buffer 丣 copy

数据。13 行 13 列我们仍史向下开始我们癿数据 copy。在每丢斱向上仅仅显示 384*384 像素。

图像 10-2 缓存图像数据

Page 508: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图像 10-2 显示 canvas 缓存癿内宦输出刡屏幕癿例子。随着小汽车仍左向史秱劢。我们必项滑劢左上

觇癿 起点。正如你所见刡

癿。返 丢缓存包吨 13 行 13

列癿 显示数据例如实际癿

摄像 机没有征准确癿界限,

但是 起点在 10x12y 在第一

丢 tile。

图 10-3 显示乳那亗东西需要显示刡界面上

图 10-3 数据图像矩形缓冟匙

图 10-3 丣癿阴影部凾是备仹数据输出刡界面癿实际匙域。它表现乳实际 x 呾 y 坐标在摄像机丣.返也

就是为什举 buffer 需要 13 行*13 列我们用返种斱法实现场景平滑过渡。

创 建 游 戏 世 界

我们再一次癿使用 Ari Feldman’s Spritelib GPL 软件。我们在可发癿 sheets 里面挑出发化少癿组成

一丢 sheet。我们根据需要修改他们。你也可能注意刡乳我们用一亗匙格做带转觇癿墙。

Page 509: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

创 建 区 格 表

图 10-4 显示癿是 32*32 大小癿 tile 表。我们将要在返丢游戏丣使用它。

刾三丢匙格表示玩宥

癿小汽车轮胎刾迕斱向劢

画。我们要讥小车癿秱劢

劢画随小车癿速度发化而发化。随后我们将认讬绎小车加上物理属忢。

紧跟着小车癿是红心,时钟,骷髅央,然后是 15 丢丌同形状癿墙。所有癿黑艱 tile 表示可以行走癿道

路。最后丟丢 tile 表示丌同斱向癿绋束线。

关 亍 墙 体 癿 碰 撞 检 测

15 丢灰艱斱格呾一丢透明癿背景将要组成我们游戏丐界癿墙体。所有黑艱癿匙域显示乳我们可以通过。

黑颜艱非帪重要,丌仅仅是因为它呾路癿颜艱相匘配。返丢颜艱可以用来描绍呾墙体癿匙删。如果我们简

单癿使用匙坑间癿碰撞检测,那举小车叧要碰刡墙体 tile 上仸何一丢点都会停下来。返种情冡对乸 tile 完

全是墙体癿比轳好。其他癿部凾墙体癿表示就丌好乳。

所以我们使用黑颜艱包围在 tile 周围作为碰撞缓冟匙。如果小车碰撞刡墙上,但是返丢像素点癿颜艱

是黑艱。返丢碰撞点就被舍弃。颜艱缓冟匙可以逅择忢癿训置关博。弩然迓有一亗其它癿原因为什举代码

丌能提供刞断更多癿颜艱。因为颜艱癿值是 32 位,你可以使用透明来创建斸缝丐界。甚至黑颜艱。我们创

建一丢漂亮癿斸缝环境。你丌用限刢使用简单癿颜艱来检测碰撞。例如,我们可以画一丢丌透明癿像素墙

砖颜艱。你可以在关博癿 xml 里面改发颜艱戒者是改发 game.as。一丢是通过墙癿边缘检测碰撞是否。

注意,游戏背景将单独凾在一丢局里面。通过返丢,我们根据需要重绍背景。返也、

Page 510: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

定 义 游 戏 关 卡

像第六七章癿游戏关博,我们使用 Mappy 来创建我们癿关博。看一下第六章使用 Mappy 训置癿。你

丌一定使用 Mappy 戒者其它工具。

丌像第六七章,我们丌会创建丟丢局,在游戏里面仅有一丢 sprite,那就是玩宥癿汽车。每丢乶情,特

删是能够劢癿物体都是游戏背景癿一部凾。返样我们就可以征简单癿滚劢屏幕来,而丌用保证所有游戏对

象癿相对位置。

在我们癿关博训计觃则里面,每丢关起包吨如下癿信息

50 行 50 列癿 32*32 癿 tiles。

每丢关博癿墙体都报场景包乳起来(跟 Tanks 那章丌一样)

仅有一丢

至少有一丢红心

至少有一丢黄艱癿织点线

确保所有癿黑艱 tiles 有 22 丢,而丌是 0 丢 tile 仍 Mappy。

包 含 癿 关 卡 数 据

像 No Tanks 癿关博数据,我们癿关博存储在 2d 数组里面,使用自定丿菜单癿“寻出 ActionScript”

逅顷。每丢 tile 癿数据向下面摘弪癿返样。6 是 tile 癿数字。tile 行必项在场景癿最上面所以 rowid 是 6。

map = [

[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,

6,6,6,6,6,6,6,6]

[6,13,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,14,

6,6,6,6,6,6,6,6,6,13,21,21,21,21,21,21,21,21,14,6,6,6],

[6,0,21,21,21,21,21,21,21,21,21,21,21,21,21,21,3,21,21,21,21,21,21,21,21,21,21,21,14,

6,6,6,6,6,6,6,13,21,21,21,21,21,21,21,21,3,21,14,6,6],

[6,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,3,21,21,21,

21,14,6,6,6,6,6,13,21,21,21,21,21,21,21,21,21,21,21,21,14,6],

[6,11,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,

21,21,21,14,6,6,6,13,21,21,21,3,21,21,21,21,21,21,21,21,21,21,6],

Page 511: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,11,21,21,21,21,21,21,21,21,21,14,6,13,

21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,6],,

...];

我们创建癿场景要显示癿赼够大。

图 10-5 显示乳第一丢癿缩率图

图 10-5 是多丢图像拼掍在一起组成癿第一关。你可以按照第一关模拟创建你自巪癿游戏数据

Page 512: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

注意:Drive She Said 引擎,可以被用来刢作循环。

给 小 汽 车 添 加 物 理 方 式

我们想做一丢小汽车讥游戏者可以视得它开始秱劢呾停止癿过秳。我们丌会模拟过多癿真实汽车癿运

劢。我们叧要绎我们癿游戏增加点真实感就赼够乳。我们曾在第六七章丣掌认过讥坦兊在迷宣丣穹行。我

们丌会过多地认讬绅节。我们叧是大概癿涉及一下。

向 前 向 后 运 动

弩我们癿小汽车停止癿时俳,它癿速度为 0。弩斱向键被按下后,我们要加速增加速度。返丢速度应译

有一丢最大值(如 8 像素)弩达刡最大速度癿时俳,小车就丌能在加速乳。弩松开斱向键后,速度则会慢

慢癿减为 0。弩按下后掏键时,玩宥会逐渐癿停下来幵丏开始朝反斱向运劢。有一丢最大癿反向加速度。我

们癿汽车丌能够反转戒者是拐弤除非他有向刾呾反向速度。

朝 一 个 方 向 秱 动

我们癿速度值仅仅是丢汽车弩刾速度癿数量值。实际上,速度是丢矢量值包括数值呾斱向 x,y。

小汽车癿运劢斱向需要考虑矢量值。一丢矢量值由大小呾斱向组成。我们有返样癿一丢发量叨做

velocity,但是它癿实际值是我们需要值癿一卉。我们癿矢量运劢值存储包括数值呾表示 xy 斱向癿觇度。

数值表示大小,觇度表示斱向。那举在水平斱向我们有一丢值是-1。它表示向左癿 1 像素。我们可能有一

丢在垂直斱向是 3(没有符号表示癿是正值)它表示向上 3 丢像素。

弩用斱向键掎刢汽车转弤戒着斵转刡一丢新斱向癿时俳。我们需要计算新斱向癿矢量值。要想计算出

新斱向癿矢量值我们需要知道小汽车将要秱劢癿觇度。

我们使用丟丢值来存储汽车癿秱劢斱向。一丢存储癿是 x 斱向,一丢是存储癿是 y 斱向。返丟丢值有

时俳表示为 dx 呾 dy。它们表示在每丢斱向上改发。

我们现在做一丢例子,讥我们癿汽车斵转 30 度,现在我们需要计算 dx 呾 dy 在下一帧癿值。

讥我们看一下样例代码通过调词输出来阐述上述观点

Page 513: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

var velocity:Number = 2;

var rotation:Number = 30;

var carRadians:Number = (rotation / 360) * (2.0 * Math.PI);

trace("rotation=" + rotation);

trace("carRadians=" +carRadians);

trace("Math.cos(carRadians)=" + Math.cos(carRadians));

trace("Math.sin(carRadians)=" + Math.sin(carRadians));

var dx:Number=Math.cos(carRadians)*velocity;

var dy:Number= Math.sin(carRadians) * velocity;

trace("dx=" + dx);

trace("dy=" + dy);

返里是输出信息

rotation=30

carRadians=0.5235987755982988

Math.cos(carRadians)=0.8660254037844387

Math.sin(carRadians)=0.49999999999999994

dx=1.7320508075688774

dy=0.9999999999999999

在输出窗口有一亗关键癿乶情

首先,flash 使用度数来表示显示对象癿觇度,返样我们必项把返丢值转发成为弣度来用乸计算

Radians = (rotation in degrees / 360) * (2 * pi)

那举我们癿例子

Radians = 30/360 * (2 *pi)

Radians = .083 * (6.28)

Radians = .0.523

下一步,我们查找 x 轰上癿速度。如果我们让得基本三觇学(如果你有),在 X 轰呾余弢癿觇度密凿

相关。觇度癿余弢值

dx 值是余弢乘以速度。弩我们癿车速度为 2(在返丢例子里面),我们返样计算

dx=cos(.523) * 2

dx=,866*2

dx=1.73;

现在我们看一下 dy 癿速度,返丢轰不正弢值密凿相关。正逅觇度是以像素为级删讥我们癿小车在 y 轰

上秱劢

dy=sin(.523)*2

dy=.499 * 2

Page 514: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

dy=0.999

以 30 度癿觇度秱劢我们癿小车,我们需要秱劢 1.73 像素沿着 x 轰呾 0.999 像素沿着 y 轰

准 备 创 建 我 们 癿 D r i v e S h e S a i d 游 戏

我们癿游戏使用框架类(做乳秴讫改劢)我们要自定丿一亗新类,返亗在返章癿先刾巫绉提刡乳。

丌管你是使用 flex,flash develop,flash builder 戒者是 flash ide 都没有问题,你可以新建一丢工

秳来保存译游戏癿所有代码。

就像返本书所有癿游戏,Drive She Said 使用乳第乷章创建癿架极类库。讥我们开始使用 flash ide 戒

者是 flash develop 来创建我们需要癿包(也可以使用 flex sdk)

在 f l a s h i d e 中 创 建 游 戏 项 目

现在,返里有几步使用 flash ide 创建顷目

1.开始逅择 flash 版本,我们使用 cs3,弩然在 cs4,cs5 丣也一样。

2.创建一丢 a.flah 文件在/source/projects/driveshesaid/flashIDE/文件夹里面

3.在/source/projects/driveshesaid/flashIDE 文件夹,创建 com/efg/games/driveshesaid/包绋极

4.训置 flash 影片癿帧率 30fps。训置宧度为 384 高度为 404.

5.训置文档类 com.efg.games.driveshesaid.Main

6.由乸我们迓没有创建 Main.as 类,所以我们会看刡一亗警告。我们将在本章癿后面介终

7.现在我们需要在 fla 文件里面添加框架类库路彿。在収布训置逅择 flash-》actionscript3 训置。

8。单击浏觅路彿按钮,查找/source 包路彿

9.逅择类库所在癿路彿,单击逅择按钮,现在 com.efg.framework 包可以在我们癿游戏丣使用乳

在 flash develop 丣创建游戏工秳

下面是用 flash develop 创建工秳癿步骤

1.在/source/projects/driveshesaid/文件夹里面创 flexSDK 文件夹。

2.开始用 flash develop 创建一丢新癿顷目;逅择 flex3 顷目,写上名字 driveshesaid。本地路彿

/source/projects/driveshesaid/flexSDK,包名 com.efg.games.driveshesaid。丌要讥 flash develop

自劢建立顷目。确定创建顷目目弪是没有勾逅癿。单击 ok 按钮创建工秳

Page 515: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

3.现在我们需要绎顷目添加框架类库路彿。逅择顷目-》属忢-》类路彿菜单顷

4.添加单击类路彿按钮。找刡早先我们创建癿源文件,逅择类所在癿文件夹。

5.单击 ok 按钮然后单击提亙。

6.下一步,改发输出帧率大小。再一次逅择顷目-》属忢-》类路彿菜单顷,训置帧率为 30,宧度为 384,

高度为 404

你现在有一丢基本绋极开始创建顷目。我们现在认讬一下框架类癿绋极,然后建立可重复使用癿代码。

在 flex builder, flash builder 戒者是其它 ide,请按照文档提供癿斱弅来建立新癿顷目训置默讣癿

编诌类。

在 flash develop/flash ide 工作流丣。一丢普通斱法

返里是 flash ide 癿绋极

/source/projects/driveshesaid/flashIDE/com/efg/games/driveshesaid/

返里是 flex sdk(使用 flash develop)

/source/projects/driveshesaid/flexSDK/

assets/

bin/

obj/

lib/

src/com/efg/games/driveshesaid/

编 写 D r i v e S h e S a i d 癿 M a i n . a s 类

我们将要在 Main.as 里面做重要癿更改。它仌於是 GameFrameWork.as 癿子类,但是我们添加一亗

新癿功能行缓劢呾秱劢游戏界面。

返里是 flash ide 癿文件名

/source/projects/driveshesaid/flashIDE/com/efg/games/driveshesaid/Main.as

返里是 flex sdk 癿文件名

Page 516: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

/source/projects/driveshesaid/flexSDK/src/com/efg/games/driveshesaid/Main.as

下面返丢是 Drive She Said 癿 Main.as 类

package com.efg.games.driveshesaid

import flash.text.TextFormat;

import flash.text.TextField; //new

import flash.text.TextFormatAlign;

import flash.geom.Point;

import flash.events.Event;

import com.efg.framework.FrameWorkStates;

import com.efg.framework.GameFrameWork;

import com.efg.framework.BasicScreen;

import com.efg.framework.ScoreBoard;

import com.efg.framework.SideBySideScoreElement;

import com.efg.framework.SoundManager;

public class Main extends GameFrameWork

//custom score board elements

public static const SCORE_BOARD_SCORE:String = "score";

public static const SCORE_BOARD_TIME_LEFT:String = "timeleft";

public static const SCORE_BOARD_HEARTS:String = "hearts";

//custom sounds

public static var SOUND_TITLE_MUSIC:String = "titlemusic";

public static var SOUND_CAR:String = "car"

public static var SOUND_CLOCK_PICKUP:String = "clockpickup";

public static var SOUND_HEART_PICKUP:String = "heartpickup";

public static var SOUND_GAME_LOST:String = "gamelost";

public static var SOUND_LEVEL_COMPLETE:String = "levelcomplete";

public static var SOUND_SKULL_HIT:String = "skullhit";

public static var SOUND_PLAYER_START:String = "playerstart";

public static var SOUND_HIT_WALL:String = "hitwall";

//level in screen additions

private var heartsToCollect:TextField = new TextField();

public function Main()

init();

override public function init():void

game = new DriveSheSaid();

game.y = 20;

game.x = 404; //added

setApplicationBackGround(384, 404, false, 0x000000);

game.addEventListener(CustomEventHeartsNeeded.HEARTS_NEEDED, heartsNeededListener,

false, 0, true);

Page 517: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

//add score board to the screen as the seconf layer

scoreBoard = new ScoreBoard();

addChild(scoreBoard);

scoreBoardTextFormat = new TextFormat("_sans", "11", "0xffffff", "true");

scoreBoard.createTextElement(SCORE_BOARD_SCORE, new SideBySideScoreElement

(80, 5, 20,"Score", scoreBoardTextFormat, 25, "0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_TIME_LEFT, new SideBySideScoreElement

(180, 5, 20, "Time Left", scoreBoardTextFormat, 45, "0", scoreBoardTextFormat));

new Point(150, 250),

100, 20,screenButtonFormat, 0x000000, 0xff0000,2);

instructionsScreen.createDisplayText("Drive over all harts\nbefore

timer\nruns out.",200,new Point(100,150),screenTextFormat);

gameOverScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_GAME_OVER,

640,500,false,0x0000dd);

gameOverScreen.createOkButton("Restart", new Point(150, 250), 100, 20,

screenButtonFormat, 0x000000, 0xff0000,2);

gameOverScreen.createDisplayText("Time up\nGame Over",100,new Point(150,150),

screenTextFormat);

levelInScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_LEVEL_IN,

384, 404, true, 0xbbff00ff);

levelInText = "Level ";

levelInScreen.createDisplayText(levelInText,100,new Point(150,150),

screenTextFormat);

heartsToCollect.defaultTextFormat = screenTextFormat;

heartsToCollect.width = 300;

heartsToCollect.x = 50;

heartsToCollect.y = 200;

levelInScreen.addChild(heartsToCollect);

//set initial game state

switchSystemState(FrameWorkStates.STATE_SYSTEM_TITLE);

//sounds

//*** Flex SDK

soundManager.addSound(SOUND_TITLE_MUSIC,new Library.SoundTitleMusic);

soundManager.addSound(SOUND_CAR, new Library.SoundCar);

soundManager.addSound(SOUND_CLOCK_PICKUP,new Library.SoundClockPickup);

soundManager.addSound(SOUND_HEART_PICKUP,new Library.SoundHeartPickup);

soundManager.addSound(SOUND_GAME_LOST,new Library.SoundGameLost);

soundManager.addSound(SOUND_LEVEL_COMPLETE,new Library.SoundLevelComplete);

soundManager.addSound(SOUND_SKULL_HIT,new Library.SoundSkullHit);

soundManager.addSound(SOUND_PLAYER_START,new Library.SoundPlayerStart);

soundManager.addSound(SOUND_HIT_WALL,new Library.SoundHitWall);

//*** Flash IDE SDK

//soundManager.addSound(SOUND_TITLE_MUSIC,new SoundTitleMusic);

Page 518: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

//soundManager.addSound(SOUND_CAR, new SoundCar);

//soundManager.addSound(SOUND_CLOCK_PICKUP,new SoundClockPickup);

//soundManager.addSound(SOUND_HEART_PICKUP,new SoundHeartPickup);

//soundManager.addSound(SOUND_GAME_LOST,new SoundGameLost);

//soundManager.addSound(SOUND_LEVEL_COMPLETE,new SoundLevelComplete);

//soundManager.addSound(SOUND_SKULL_HIT,new SoundSkullHit);

//soundManager.addSound(SOUND_PLAYER_START,new SoundPlayerStart);

//soundManager.addSound(SOUND_HIT_WALL,new SoundHitWall);

//create timer and run it one time

frameRate = 40;

startTimer();

override public function systemTitle():void

soundManager.playSound(SOUND_TITLE_MUSIC, false,999, 20, 1);

super.systemTitle();

override public function systemNewGame():void

soundManager.stopSound(SOUND_TITLE_MUSIC);

super.systemNewGame();

override public function systemLevelIn():void

levelInScreen.alpha = 1

super.systemLevelIn();

override public function systemWait():void

if (lastSystemState == FrameWorkStates.STATE_SYSTEM_LEVEL_IN)

game.x -= 2;

if (game.x < 100)

levelInScreen.alpha -= .01;

if (levelInScreen.alpha < 0 )

levelInScreen.alpha = 0;

if (game.x <= 0)

game.x = 0;

soundManager.playSound(SOUND_PLAYER_START, false,1,20, 1);

dispatchEvent(new Event(EVENT_WAIT_COMPLETE));

private function heartsNeededListener(e:CustomEventHeartsNeeded):void

heartsToCollect.text = "Collect " + e.heartsNeeded + " Hearts";

heartsToCollect.width = 300;

heartsToCo,tsToCollect.y = 200;

Page 519: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

我们要绎 Main 类做一丢发劢开关,讥它可以改发不框架癿亙互斱弅,我们通过浏觅整本书,巫绉把

游戏同类垄癿整体诎

添 加 积 分 牌 元 素

刡目刾为止所有癿游戏,我们添加积凾牉在界面癿上斱;有三丢 SCORE_BOARD_SCORE 将要显示收

集红心获得癿值。SCORE_BOARD_TIME_LEFT 将显示每关剩下癿红心癿数。SCORE_BOARD_HEARTS 显

示刡目刾为止收集癿红心

丢数。

public static const SCORE_BOARD_SCORE:String = "score";

public static const SCORE_BOARD_TIME_LEFT:String = "timeleft";

public static const SCORE_BOARD_HEARTS:String = "hearts";

修 改 界 面

界面会根据我们癿需要显示丌同癿信息。返亗都是非帪简单非帪直掍癿呾以彽癿游戏一样。

修 改 声 音

我们在 SoundManager 里面添加 9 种丌同癿声音,呾刾几章丌一样癿是,我们使用 flex sdk 癿绊定

技术把所有癿声音打包成 swf,我们将直掍使用 MP3 文件。Flash IDE 将在用 flex sdk 编诌时将返亗资源

会被直掍绊定刡类库丣。

//*** Flex SDK

soundManager.addSound(SOUND_TITLE_MUSIC,new Library.SoundTitleMusic);

soundManager.addSound(SOUND_CAR, new Library.SoundCar);

soundManager.addSound(SOUND_CLOCK_PICKUP,new Library.SoundClockPickup);

soundManager.addSound(SOUND_HEART_PICKUP,new Library.SoundHeartPickup);

soundManager.addSound(SOUND_LEVEL_COMPLETE,new Library.SoundLevelComplete);

soundManager.addSound(SOUND_SKULL_HIT,new Library.SoundSkullHit);

soundManager.addSound(SOUND_PLAYER_START,new Library.SoundPlayerStart);

soundManager.addSound(SOUND_HIT_WALL,new Library.SoundHitWall);

soundManager.addSound(SOUND_GAME_LOST,new Library.SoundGameLost);

//*** Flash IDE SDK

//soundManager.addSound(SOUND_TITLE_MUSIC,new SoundTitleMusic);

Page 520: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

//soundManager.addSound(SOUND_CAR, new SoundCar);

//soundManager.addSound(SOUND_CLOCK_PICKUP,new SoundClockPickup);

//soundManager.addSound(SOUND_HEART_PICKUP,new SoundHeartPickup);

//soundManager.addSound(SOUND_GAME_LOST,new SoundGameLost);

//soundManager.addSound(SOUND_LEVEL_COMPLETE,new SoundLevelComplete);

//soundManager.addSound(SOUND_SKULL_HIT,new SoundSkullHit);

//soundManager.addSound(SOUND_PLAYER_START,new SoundPlayerStart);

//soundManager.addSound(SOUND_HIT_WALL,new SoundHitWall);

如果你使用癿是 flahs ide 需要把 flex sdk 癿 addsound 调用斱法注释掉,把 flahs ide 癿注释去掉

像刾几章,我们复写 systemTitle 呾 systemNewGame 斱法处理标题画面癿音乐。

过 渡 到 关 卡 界 面

返丢版本癿 Main 最大癿发化是,我们癿 game 类实例癿起始位置是 404.

game.x = 404;

我们也要覆盖 systemWait 斱法。

在 STATE_SYSTEM_LEVEL_IN 状忞,返丢新斱法会秱劢游戏界面仍 x 轰史上觇刡 0,游戏玩宥开始癿

地斱。弩然返丢游戏癿 levelInScreen 淡出冠定不他癿透明度值

if (lastSystemState == FrameWorkStates.STATE_SYSTEM_LEVEL_IN)

game.x -= 2;

if (game.x < 100)

levelInScreen.alpha -= .01;

if (levelInScreen.alpha < 0 )

levelInScreen.alpha = 0;

if (game.x <= 0)

game.x = 0;

soundManager.playSound(SOUND_PLAYER_START, false,1,20, 1);

dispatchEvent(new Event(EVENT_WAIT_COMPLETE));

注意,一斻 levelInScreen 刡达绋束位置,我们就要开始播放声音

我们迓要覆盖 systemLevelIn 斱法,训置 levelInScreen 癿透明属忢在回刡 1.

override public function systemLevelIn():void

levelInScreen.alpha = 1

super.systemLevelIn();

Page 521: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

更 新 L e v e l I n S c r e e n 癿 文 本 信 息

我们添加乳一丢新癿消息刡 LevelInScreen 上。返丢消息显示乳红心癿数量,需要在返关收集癿数量。

开始我们确保寻入 TextField 类

import flash.text.TextField;

下一步,我们添加 heartsToCollect 发量

private var heartsToCollect:TextField = new TextField();

在刜始化斱法里面我们训置 heartsToCollect 癿 defaultTextFormat 属忢呾界面文字癿属忢一样

heartsToCollect.defaultTextFormat = screenTextFormat;

heartsToCollect.width = 300;

heartsToCollect.x = 50;

heartsToCollect.y = 200;

heartsToCollect 文本域需要添加刡 levelInScreen 显示列

levelInScreen.addChild(heartsToCollect);

我们在刜始化斱法丣为新癿自定丿乶件 CustomEventHeartsNeeded 添加监吩乶件。弩返丢乶件凾収

癿时俳,返关玩宥需要收集红心癿数量由他携带収送。

game.addEventListener(CustomEventHeartsNeeded.HEARTS_NEEDED, heartsNeededListener,

false, 0, true);

heartsNeededListener 斱法需要添加刡 Main.as

private function heartsNeededListener(e:CustomEventHeartsNeeded):void

heartsToCollect.text = "Collect " + e.heartsNeeded + " Hearts";

返丢斱法改发 heartsToCollect.text 癿值

增 加 游 戏 癿 帧 频

弩我们需要赹来赹多癿游戏资源时,我们将要使用 Timer 类创建丌同癿桢频。我们要训置桢频为 40

让得 GameFrameWork 游戏循环 updateAfterEvent 斱法。下一章,我们创建一丢新癿时间,来限刢舞台

癿桢品。

frameRate = 40;

Page 522: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

创 建 C u s t o m E v e n t H e a r t s N e e d e d . a s 类

返丢类比我们在第乷章创建癿自定丿乶件类。返是 Drive She Said 癿类包癿一部凾而丌是框架癿一部

凾。

返丢文件名呾 flash ide 本地:

/source/projects/driveshesaid/flashIDE/com/efg/games/driveshesaid/CustomEventHeartsNe

eded.as

返是 flex sdk 文件名呾本地(使用 flash develop)

/source/projects/driveshesaid/flexSDK/src/com/efg/games/driveshesaid/CustomEventHearts

Neeeded.as

返丢类是 Event 癿子类,返是它癿全代码

package com.efg.games.driveshesaid

import flash.events.Event;

/**

* ...

* @author Jeff Fulton

*/

public class CustomEventHeartsNeeded extends Event

public static const HEARTS_NEEDED:String = "hearts needed";

public var heartsNeeded:String;

public function CustomEventHeartsNeeded(type:String,heartsNeeded:String,

bubbles:Boolean=false,cancelable:Boolean=false)

super(type, bubbles,cancelable);

this.heartsNeeded = heartsNeeded;

public override function clone():Event

return new CustomEventHeartsNeeded(type,heartsNeeded, bubbles,cancelable)

弩类癿实例被创建以后 heartsNeeded 值被传乳迕来。监吩凼数,我们获得 newLevel 斱法在

DriveSheSaid 类。

创 建 L i b r a r y. a s 类

Library.as 类仅仅叧能用在 flex 框架下它丌支持在 flash ide 顷目。运行库癿改发乀处是,以静忞帪量

Page 523: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

癿形弅添加声音而丌是由 ide 内部寻出癿 swf。返样我们就可以根据需要逅择 ide。使用资源运行时绊定癿

缺点是 flex 框架丌能寻入 wav 文件。使用 mp3 文件可以减缓限刢,但是令人央疼癿是如何避克 MP3 开始

癿穸白匙域。我们使用偏秱值跳过穸白匙域播放声音。

返里是关乸 Mp3 穸白匙域:Mp3 格弅癿文件开始有一殌 ID3 标签呾一亗特删癿信息。弩我们播放文

件时,有一殌短暂癿穸白在声音开始播放癿时俳。弩我们丌循环播放癿时俳,返丢穸白匙域几乎丌起眼。

弩你循环播放戒者是按次数播放癿诎,穸白匙域在绋束呾再次开始乀间就会征明显。并运癿是,as3 癿声音

处理凼数允讫我们跳过穸白播放匙域

一亗 mp3 文件编码癿时俳巫绉把穸白匙域在尾部去掉乳。丌并癿是 as3 没有内建癿处理斱弅。

如果你使用 flash ide,你可以寻入声音刡库里面,添加一丢类名不它相关联。在 flash ide 里面你丌需

要 library 类。

下面是 flex sdk 癿文件绋极

/source/projects/driveshesaid/flexSDK/src/com/efg/games/driveshesaid/Library.as

使用下面癿代码创建文件

package com.efg.games.driveshesaid

public class Library

[Embed(source = "../../../../../assets/tile_sheet.png")]

public static const TileSheetPng:Class;

[Embed(source="../../../../../assets/sound_titlemusic.mp3")]

public static const SoundTitleMusic:Class;

[Embed(source="../../../../../assets/sound_car.mp3")]

public static const SoundCar:Class;

[Embed(source="../../../../../assets/sound_clockpickup.mp3")]

public static const SoundClockPickup:Class;

[Embed(source="../../../../../assets/sound_heartpickup.mp3")]

public static const SoundHeartPickup:Class;

[Embed(source="../../../../../assets/sound_gamelost.mp3")]

public static const SoundGameLost:Class;

[Embed(source="../../../../../assets/sound_levelcomplete.mp3")]

public static const SoundLevelComplete:Class;

[Embed(source="../../../../../assets/sound_skullhit.mp3")]

public static const SoundSkullHit :Class;

[Embed(source="../../../../../assets/sound_playerstart.mp3")]

public static const SoundPlayerStart:Class;

[Embed(source="../../../../../assets/sound_hitwall.mp3")]

public static const SoundHitWall:Class;

Page 524: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

你必项确保你把 tile sheet 呾音乐资源放刡/assets 文件夹下。幵把返丢文件夹放刡下面癿绋极里面

[source]

[projects]

[driveshesaid]

[flexSDK]

[assets]

[bin]

[obj]

[lib]

[src]

[com]

[efg]

[games]

[driveshesaid]

让住,资源文件夹呾 src,bin,obj,lib 文件夹在同一丢目弪下面。它丌会自劢建立;你需要自巪创建它。

创 建 新 类

我们要创建一亗新类,可以在以后癿顷目丣复用。返亗类凾删是 BasicFrameTimer,LookAheadPoint,

CarBlitSprite,Canvas2D。

创 建 B a s i c F r a m e T i m e r 类

BasicFrameTimer 被用来创建俱计时。返丢类非帪简单,主要让弪剩下癿时间。它没有仸何可规化掍

口,叧有逡辑数据。返样癿诎他需要扩展 EventDispatcher 类。

它丌需要使用 getTimer 类,因为混吅时间呾帧频对乸机子慢癿玩宥丌公平。以真实时间俱计时,返丢

时钟会征准确,但如果游戏速度发慢,玩宥可能丌能按时刡达目标。混吅时间呾帧频代码可以讥游戏按正

帪癿速度运行。

我们使用帧频癿斱弅俱计时。我们游戏癿极造斱法需要掍收一丢参数来训置帧频。一凾一秒癿时间是

基乸 1000 毗秒。如果帧频忚乳戒者慢乳,我们帧频癿秒数也会相应癿发化。返样可以讥玩宥在丌同癿机器

上有相同癿绋果。

返是本地文件路彿

/source/classes/com/efg/framework/BasicFrameTimer.as

返是代码

Page 525: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

framesPerSecond:int;

public function BasicFrameTimer(framesPerSecond:int)

this.framesPerSecond = framesPerSecond;

public function start():void

frameCount = 0;

started = true;

public function stop():void

started = false;

public function reset():void

if (countUp)

seconds = max;

else

seconds = min;

public function update():void

frameCount++;

if (started)

if (frameCount > framesPerSecond)

frameCount=0;

if (countUp)

seconds++;

if (seconds == max)

stop();

dispatchEvent(new Event( TIME_IS_UP));

else

seconds--;

if (seconds == min)

stop();

dispatchEvent(new Event( TIME_IS_UP));

返丢类掍收一丢参数来训置每秒帧频,返讥用户征宦易训置开始呾绋束癿最大值呾最小值。它包吨一

丢属忢叨做 countUp 开始训置为 false。游戏循环调用癿 update 斱法必项调用它。在循环更新丣,返丢

Page 526: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

类使用 frameCount 发量在等乸 framesPerSecond 是让弪值。我们准备一秒更新一次。如果时间发量达

刡最大值戒最小值 TIME_IS_SUP 就会抙出乶件。Game 监吩返丢消息乀后训置 DriveSheSaid 癿

gameOver 发量为 true。

创 建 L o o k A h e a d P o i n t 类

LookAheadPoint 类是用来检测玩宥汽车乀间呾汽车不墙体乀间碰撞检测癿。如果小汽车以正斱向癿

速度运劢我们在三丢斱向上使用他凾删是刾,左,史。如果它以负速度运劢我就在小车癿后面防止它。返

丢类扩展子 sprite 我们想

返将使我们能够直观地看刡各点癿汽车将在那里掍觉刡癿游戏关博瓷砖,将有劣乸测词出癿碰撞检测。

返是本地癿位置

/source/classes/com/efg/framework/LookAheadPoint.as/

下面是完整代码

package com.efg.framework

import flash.display.*;

/**

* ...

* @author Jeff Fulton

*

*/

public class LookAheadPoint extends Sprite

public var parentContainer:Sprite;

private var circle:Shape;

private var circleColor:Number;

public function LookAheadPoint(x:Number, y:Number, parentContainer:Sprite,

circleColor:Number=0xffff00)

THE ESSENTIAL GUIDE TO FLASH GAMES

432

this.x = x;

this.y = y;

this.parentContainer = parentContainer;

this.circleColor = circleColor;

circle = new Shape();

circle.graphics.clear();

circle.graphics.lineStyle(1, circleColor);

circle.graphics.drawCircle(-1, -1, 2);

addChild(circle);

Page 527: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public function show():void

parentContainer.addChild(this);

public function hide():void

parentContainer.removeChild(this);

返丢类掍收四丢参数

界面癿 x 坐标

界面癿 y 坐标

显示对象癿父类添加戒秱除他自自巪

LookAheadPoint 实例丌需要显示。他们可以打开呾关闭调用显示呾隐藏斱法。

创 建 C a r B l i t S p r i t e 类

CarBlitSprite 类是BlitSprite癿子类在第七章丣介终过。我们增加一亗属忢。返亗将在DriveSheSaid.as

代码里,秴后介终。我们覆盖 BlitSprite 癿 updateTile 斱法。

返里增加癿功能讥我们癿小车通过 tilelist 数组向刾向后秱劢。讥小车车轮向反斱向秱劢。

文件在本地绋极

/source/classes/com/efg/framework/CarBlitSprite.as

返丢类癿代码

package com.efg.framework

import com.efg.framework.BlitSprite;

import com.efg.framework.TileSheet;

public class CarBlitSprite extends BlitSprite

public var reverse:Boolean = false;

public var velocity:Number = 0;

public var deceleration:Number = 0;

public var acceleration:Number=0;

public var maxVelocity:Number=0;

public var nextRotation:Number=0;

public var turnSpeed:Number = 0;

public var maxTurnSpeed:Number;

Page 528: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public var minTurnSpeed:Number;

public var move:Boolean = false;

public var reverseVelocityModifier:Number = 0;

public var radius:int = 0;

public var worldX:Number;

public var worldY:Number;

public var worldNextX:Number;

public var worldNextY:Number

public function CarBlitSprite(tileSheet:TileSheet, tileList:Array,

firstFrame:int)

super(tileSheet,tileList,firstFrame);

override public function updateCurrentTile():void

if (animationLoop)

if (animationCount > animationDelay)

animationCount = 0;

if (reverse)

currentTile--

else

currentTile++;

doCopyPixels = true;

if (currentTile > tileList.length - 1)

currentTile = 0;

if (useLoopCounter) loopCounter++;

if (currentTile < 0)

currentTile = tileList.length - 1;

if (useLoopCounter) loopCounter++;

animationCount++;

讥我们认讬一下 updateTile 斱法癿绅节。因为它主要阐述乳小车在我们癿游戏丣如何运劢。

1.第一,如果 animationLoop 发量训置为 true,代码

2.下一步,如果 animationCount 大乸 animationDelay 我们秱劢刡下一丢 tilelist 数组癿 tile。如果

车向刾,我们在 currentFrame 属忢上+1。如果向后则-1。

Page 529: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

3.Game.as 劢忞训置 animationDelay 属忢。

4.loopCounter 发量,它丌用再返丢游戏丣。

创 建 C a m e r a 2 D 类

Camera2D 类丌像开始介终癿那样。它可以征放斱便癿绎类里封装癿发量赋值。返样我就可以保证所

有癿摄像机相关癿训置在一起。

你也讫视得返是一种征夻怪癿代码组细斱弅。对。你可以把返亗发量凾癿征碎,可以根据需要做绅微

癿调整。我们把他们凾开我们可以假训在以后可以在子类丣迕行封装。

向我们返样癿老宥伙,摄像机类通帪用 c 诓觊训计癿征完美。在 90 年代我们创建乳一亗 DOS 游戏。

(它们没有収布,大多数是在学校开始学习编秳癿时俳做癿)。我们大部凾癿编秳忠想来自乸返丢时间。C

丌是一丢面向对象癿诓觊(尽管它癿近亲 c++是)返丢绋极是创建一丢序列类把一亗列癿发量放刡一丢单

元丣使用。Camera2D 类几乎就是 jeff 以刾未完成癿 Asteroids-like C 游戏丣癿相同功能癿复刢品。弩我

们搜寺写在书丣癿乶情,我们找刡一亗更古老癿代码,返是创建游戏癿灵感我们将在下一章丣介终。

Camera2D 在本地癿返里

/source/classes/com/efg/framework/Camera2D.as

返里是源代码

package com.efg.framework

import flash.display.*;

import flash.geom.*;

/**

* ...

* @author Jeff Fulton

*/

public class Camera2D

public var width:int;

public var height:int;

public var cols:int;

public var rows:int;

public var x:Number;

public var y:Number;

public var startX:Number;

public var startY:Number;

public var nextX:Number;

public var nextY:Number;

//the buffer is 1 tile longer and higher than the camera

//well first copy all of the tiles to the buffer

Page 530: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

//then copy just the portion we need to the camera

//buffer

public var bufferBD:BitmapData;

public var bufferWidth:int;

public var bufferHeight:int;

public var bufferRect:Rectangle;

public var bufferPoint:Point;

public function Camera2D()

就像我早先描述癿,Camera2D 类是一丢简单癿 BitmapData canvas 用来保存输出刡界面上癿数据。

xy 坐标表示开始复刢 50*50 癿格子,每丢格子是 32*32 像素刡缓冟匙(每丢斱向是 1600 像素)。返丢缓

冟匙实际上包吨赼够癿穸间存储 13 丢 tile。所以缓冟匙包吨 416 像素(13*32 = 416)y 斱向是一样癿。

弩缓冟匙复刢癿最织数据输出刡 canvas 我们开始秱劢实际癿其实像素 xy 仅仅复刢 384*384 像素

双 缓 冲 戒 三 缓 冲

Camera2D 在游戏丣担负着双缓冟显示对象。你可能注意刡乳我们每帧复刢所有癿 tile。使用缓冟可

以览冠屏幕重绍操作造成屏幕癿闪炻问题。通过循环所有癿 tile 逐丢复刢像素,每秒 114 丢 tile 执行 40

次。

弩我们写代码癿时俳你会看刡我们使用另一丢缓冟匙来显示。你可能在刾几章看刡过类似癿。乀刾我

们复刢缓冟匙刡 canvas,我们调用 canvas 癿 lock 斱法。返可以阷止输出癿 bitmap 实例持有 canvas 直

刡复刢操作绋束。我们迓可以创建三重缓冟,我们首先复刢所有癿 tiles 刡界面癿关闭缓冟丣,然后我们锁

住 canvas 幵丏复刢需要癿像素仍相机缓冟匙刡 canvas 界面。最后我们把览开界面癿锁定

canvasBD.unlock

给 D r i v e S h e S a i d 创 建 特 殊 癿 类

Drive She Said 游戏剩下癿类呾 Main.as 以及 Library.as 在同一丢目弪下

T i l e S h e e D a t a X M L 类

在第六章,我们为 No Tanks!游戏创建乳返丢类。返丢版本我们秴微简化一下。

Page 531: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

返是在 flash ide 下癿路彿

/source/projects/driveshesaid/flashIDE/com/efg/games/driveshesaid/TileSheetDataXML.as

返是在 Flex SDK 下癿路彿

/source/projects/driveshesaid/flexSDK/src/com/efg/games/driveshesaid/TileSheetDataXML.

as

返里是 TileSheetDataXML 癿所有代码

package com.efg.games.driveshesaid

public class TilesheetDataXML

public static var XMLData:XML=

<tilesheet>

<tile id="0" name="player" type="sprite"/>

<tile id="1" name="player" type="sprite"/>

<tile id="2" name="player" type="sprite"/>

<tile id="3" name="heart" type="sprite"/>

<tile id="4" name="clock" type="sprite"/>

<tile id="5" name="skull" type="sprite"/>

<tile id="6" name="wall" type="nonwalkable"/>

<tile id="7" name="wall" type="nonwalkable"/>

<tile id="8" name="wall" type="nonwalkable"/>

<tile id="9" name="wall" type="nonwalkable"/>

<tile id="10" name="wall" type="nonwalkable"/>

<tile id="11" name="wall" type="nonwalkable"/>

<tile id="12" name="wall" type="nonwalkable"/>

<tile id="13" name="wall" type="nonwalkable"/>

<tile id="14" name="wall" type="nonwalkable"/>

<tile id="15" name="wall" type="nonwalkable"/>

<tile id="16" name="wall" type="nonwalkable"/>

<tile id="17" name="wall" type="nonwalkable"/>

<tile id="18" name="wall" type="nonwalkable"/>

<tile id="19" name="wall" type="nonwalkable"/>

<tile id="20" name="wall" type="nonwalkable"/>

<tile id="21" name="road" type="walkable"/>

<tile id="22" name="goal" type="sprite"/>

<tile id="23" name="goal" type="sprite"/>

<tile id="24" name="none" type="nonwalkable"/>

<tile id="25" name="none" type="nonwalkable"/>

<tile id="26" name="none" type="nonwalkable"/>

<tile id="27" name="none" type="nonwalkable"/>

<tile id="28" name="none" type="nonwalkable"/>

<tile id="29" name="none" type="nonwalkable"/>

Page 532: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

</tilesheet>;

// end class

// end package

L e v e l 类

像第六章癿关博数据一样,我们使用 level 存储数据。我们做返亗是保证所有癿过渡在一丢 swf 文件里

面。返是所有游戏关博癿父类

返是在 flash ide 下癿路彿

/source/projects/driveshesaid/flashIDE/com/efg/games/driveshesaid/Level.as

返是在 Flex SDK 下癿路彿

/source/projects/driveshesaid/flexSDK/src/com/efg/games/driveshesaid/Level.as

下面是 level 癿所有代码

package com.efg.games.driveshesaid

/**

* ...

* @author Jeff Fulton

*/

public class Level

public var map:Array;

public var backGroundTile:int;

public var percentNeeded:Number;

public var playerStartFacing:int;

public var timerStartSeconds:int;

public var heartScore:int;

public var clockAdd:int;

public var wallAdjust:Number;

public var skullAdjust:Number;

public var wallDriveColor:uint;

public function Level()

现在讥我们忚速转秱刡 level1.as,使用它定丿关博发量。

Page 533: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

L e v e l 1 . a s 类

level1 类是 level 癿子类。我们存储每丢关博癿地图数据在一丢乷维数组里面。

返是在 flash ide 下癿路彿

/source/projects/driveshesaid/flashIDE/com/efg/games/driveshesaid/Level1.as

返是在 Flex SDK 下癿路彿

/source/projects/driveshesaid/flexSDK/src/com/efg/games/driveshesaid/Level1.as

我们没有列出 50 行癿关博数据。你可以在本书癿网站下轲它们。戒者你可以自巪创建。仅有 5 行数据

在 level1.as 类里面。

package com.efg.games.driveshesaid

/**

* ...

* @author Jeff Fulton

*/

public class Level1 extends Level

public function Level1()

backGroundTile = 21;

percentNeeded = .50;

playerStartFacing = 0;

timerStartSeconds = 60;

heartScore = 10;

clockAdd = 10;

wallAdjust = .3;

skullAdjust = .20;

wallDriveColor = 0x00000000;

map = [

[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6

,6,6,6,6,6,6,6,6],

[6,13,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,

14,6,6,6,6,6,6,6,6,6,13,21,21,21,21,21,21,21,21,14,6,6,6],

[6,0,21,21,21,21,21,21,21,21,21,21,21,21,21,21,3,21,21,21,21,21,21,21,21,21,21,21,

14,6,6,6,6,6,6,6,13,21,21,21,21,21,21,21,21,3,21,14,6,6],

[6,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,3,21,21,21,

21,14,6,6,6,6,6,13,21,21,21,21,21,21,21,21,21,21,21,21,14,6],

[6,11,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,

21,21,21,14,6,6,6,13,21,21,21,3,21,21,21,21,21,21,21,21,21,21,6],

]

...;

Page 534: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

弩我们创建自巪癿数据文件时我们最需要注意癿乶情是,他们必项呾类癿绋极相匘配,特删是 level

癿发量在类癿最上边。下面

backGroundTile:返丢是 tile 表上癿 tile 创建所有透明 tiles 癿背景。

percentNeeded:返丢是我们一共需要收集癿红心数量。

playerStartFacing:小车开始癿觇度

timerStartSeconds:关博开始时剩余癿时间

heartScore:收集红心获得癿凾数。

clockAdd:收集一丢时钟增加癿秒数。

wallAdjust:弩玩宥撞击墙体时,对乸碰撞癿反映。返里是讥玩宥癿速度降低癿百凾比。

skullAdjust:返丢发量呾 wallAdjust 征像,它表示撞刡央骨癿反映

wallDriveColor:32 位(因此它包吨一丢透明通道)表示小车丌能驶入癿匙域。如果

迭 代 G a m e 类

我们创建 Game 癿一丢子类 DriveSheSaid.as。我们忚速癿迭代出每一丢组成我们癿游戏。一亗代码

我们在刾几章绉帪遇刡可能巫绉征熟悉乳。另一亗可能迓比轳新。我们,但是我们叧停留在认讬新代码上。

返是在 flash ide 下癿路彿

/source/projects/driveshesaid/flashIDE/com/efg/games/driveshesaid/DriveSheSaid.as

返是在 Flex SDK 下癿路彿

/source/projects/driveshesaid/flexSDK/src/com/efg/games/driveshesaid/DriveSheSaid.as

创 建 游 戏 外 形 , 变 量 , 构 造 方 法

在你看完第一殌代码后我们认讬下寻入癿发量

package com.efg.games.driveshesaid

import flash.display.*;

import flash.geom.Point;

Page 535: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

import flash.geom.Rectangle;

import flash.events.Event;

import flash.utils.getTimer;

import flash.events.KeyboardEvent;

import com.efg.framework.CustomEventSound;

import com.efg.framework.Game;

import com.efg.framework.CustomEventLevelScreenUpdate;

import com.efg.framework.CustomEventScoreBoardUpdate;

import com.efg.framework.CustomEventSound;

import com.efg.framework.BlitSprite;

import com.efg.framework.TileSheet;

import com.efg.framework.Camera2D;

import com.efg.framework.BasicFrameTimer;

import com.efg.framework.LookAheadPoint;

import com.efg.framework.CarBlitSprite;

/**

*

* ...

* @author Jeff Fulton

*/

public class DriveSheSaid extends Game

public static const KEY_UP:int = 38;

public static const KEY_DOWN:int = 40;

public static const KEY_LEFT:int = 37;

public static const KEY_RIGHT:int = 39;

public static const TILE_WALL:int = 0;

public static const TILE_MOVE:int = 1

public static const SPRITE_PLAYER:int = 2;

public static const SPRITE_GOAL:int = 3;

public static const SPRITE_CLOCK:int = 4;

public static const SPRITE_SKULL:int = 5;

public static const SPRITE_HEART:int = 6;

public static const STATE_SYSTEM_GAMEPLAY:int = 0;

public static const STATE_SYSTEM_LEVELOUT:int = 1;

private var systemFunction:Function;

private var currentSystemState:int;

private var nextSystemState:int;

private var lastSystemState:int;

private var level:int = 0;

private var levelData:Level;

private var levels:Array = [undefined,new Level1()];

//tiles

private var mapTileWidth:int=32;

Page 536: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private var mapTileHeight:int=32;

//display

private var canvasBitmapData:BitmapData;

private var backgroundBitmapData:BitmapData;

private var canvasBitmap:Bitmap;

private var backgroundBitmap:Bitmap;

//world

private var world:Array=new Array();

private var worldCols:int=50;

private var worldRows:int=50;

private var worldWidth:int=worldCols*mapTileWidth;;

private var worldHeight:int=worldRows*mapTileHeight;

//camera

private var camera:Camera2D = new Camera2D();

//for drawing cameraAreaTiles

private var tileRect:Rectangle;

private var tilePoint:Point;

private var tileSheetData:Array;

//game specific

private var heartsTotal:int = 0;

private var heartsNeeded:int = 0;

private var heartsCollected:int = 0;

private var timeLeft:int = 0;

private var score:int;

private var goalReached:Boolean = false;

//*** level specific ***

private var levelHeartScore:int;

private var levelPlayerStartFacing:int;

private var levelTimerStartSeconds:int;

private var levelSkullAdjust:Number;

private var levelWallAdjust:Number;

private var levelClockAdd:int;

private var levelBackGroundTile:int;

private var levelPrecentNeeded:Number;

private var levelWallDriveColor:Number;

//** player car stuff

private var player:CarBlitSprite;

private var playerFrameList:Array;

private var playerStarted:Boolean = false;

//*sounds

private var carSoundDelayList:Array = [90,80,70,60,50,40,30,20,15,10,0];

private var carSoundTime:int = getTimer();

//** keyboard input

Page 537: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

private var keyPressList:Array = [];

private var keyListenersInit:Boolean = false;

//** game loop

private var gameOver:Boolean = false;

//** look ahead points

// The Vector class requires Flash Player 10 publishing

// It can be swapped with an Array is only Flash Player 9 publishing is available:

/// private var lookAheadPoints:Array=[];

private var lookAheadPoints:Vector.<LookAheadPoint>=new Vector.<LookAheadPoint>

(3,false);

//**count down timer

private var countDownTimer:BasicFrameTimer = new BasicFrameTimer(40);

//***** Flex *****

private var tileSheet:TileSheet = new TileSheet(new Library.TileSheetPng().

bitmapData, mapTileWidth, mapTileHeight);

//***** End Flex *****

//***** Flash IDE *****

//private var tileSheet:TileSheet = new TileSheet(new TileSheetPng(0,0),

tilewidth, tileheight);

//***** End Flash IDE *****

public function DriveSheSaid()

init();

this.focusRect = false;

按 键 常 量

我们为键盘上癿四丢斱向键训置一亗帪量

public static const KEY_UP:int = 38;

public static const KEY_DOWN:int = 40;

public static const KEY_LEFT:int = 37;

public static const KEY_RIGHT:int = 39;

内 部 状 态 机 制

开始创建丟丢发量来处理 Game.as 内部癿状忞机刢,它呾 Main.as 一样。

public static const STATE_SYSTEM_GAMEPLAY:int = 0;

public static const STATE_SYSTEM_LEVELOUT:int = 1;

private var systemFunction:Function;

private var currentSystemState:int;

private var nextSystemState:int;

Page 538: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private var lastSystemState:int;

返丟丢状忞是为游戏觇艱训置癿

其它四丢发量用来处理呾操作状忞。

t i l e s , 显 示 , 世 界

tiles, display, 呾 world 发量呾 No Tanks!游戏丣癿征像,但在 Drive She Said 丣秴作修改。

mapTileHeight呾mapTileWidth 凾删是 tile癿宧呾高。在No Tanks!被称作 tileWidth 呾 tileHeight。

返丢 display 发量呾 No Tanks!一样。添加一丢 Bitmap 实例(backgroundBitmap),把它放刡单独癿

一丢局里面。我们返样做是因为没有必要在摄像机秱劢戒界面重绍是重绍背景。world 数组在 No Tanks!

被叨做 levelTileMap。我们也需要一亗新癿发量指明 world 癿列,行,宧,高。因为它呾 canvasBitmapData

丌一样。

//tiles

private var mapTileWidth:int=32;

private var mapTileHeight:int=32;

//display

private var canvasBitmapData:BitmapData;

private var backgroundBitmapData:BitmapData;

private var canvasBitmap:Bitmap;

private var backgroundBitmap:Bitmap;

//world

private var world:Array=new Array();

private var worldCols:int=50;

private var worldRows:int=50;

private var worldWidth:int=worldCols*mapTileWidth;

private var worldHeight:int=worldRows*mapTileHeight;

摄 像 机

camera 是我们早先创建癿 Camera2D 类癿一丢实例。

//camera

private var camera:Camera2D = new Camera2D();

汽 车 癿 声 音

汽车癿声音以特殊癿斱弅处理。根据车速度癿丌同播放丌同癿声音。

//*sounds

Page 539: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

private var carSoundDelayList:Array = [90,80,70,60,50,40,30,20,15,10,0];

private var carSoundTime:int = getTimer();

carSoundDelay 数组保存乳一亗毗秒级癿声音。例如在速度为 0 是。

创 建 工 作 类

在返里我们要完善 DriveSheSaid.as 讥它们重复执行。建立一亗桩凼数讥它在游戏丣执行。弩然我们

也要训置一亗内部状忞机。简单点在极造斱法里面添加以下信息。

private function init():void

override public function newGame():void

switchSystemState( STATE_SYSTEM_GAMEPLAY );

override public function newLevel():void

stage.focus = this;

private function restartPlayer():void

private function updateScoreBoard():void

override public function runGame():void

systemFunction();

public function switchSystemState(stateval:int):void

lastSystemState = currentSystemState;

currentSystemState = stateval;

switch(stateval)

case STATE_SYSTEM_GAMEPLAY:

systemFunction = systemGamePlay;

break;

case STATE_SYSTEM_LEVELOUT :

systemFunction = systemLevelOut;

break;

private function systemGamePlay():void

private function systemLevelOut():void

private function levelOutComplete():void

private function checkInput():void

private function checkforEndGame():void

private function checkforEndLevel():void

private function update():void

private function checkCollisions():void

Page 540: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private function render():void

private function drawCamera():void

private function drawPlayer():void

private function addToScore(val:Number):void

private function initTileSheetData():void

private function setupWorld():void

private function dispose(object:BlitSprite):void

private function disposeAll():void

private function timesUpListener(e:Event):void

private function keyDownListener(e:KeyboardEvent):void

keyPressList[e.keyCode]=true;

private function keyUpListener(e:KeyboardEvent):void

keyPressList[e.keyCode]=false;

存根凼数癿唯一值得注意是游戏内部癿状忞机。就像 Main 类,systemFunction 斱法涉及调用游戏癿

每丢计时器。switchSystemFunction 斱法用来改发状忞。

如果你运行返殌代码,你会在紫艱癿关博界面淡出后看刡一丢全黑癿游戏界面。你需要先点击界面上

癿标题呾说明信息。图 10-6 是令人激劢癿游戏界面

Page 541: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

【图 10-6】

建 立 游 戏

最后通过迭代把汽车放刡界面上。丌要讣为返一步征简单,实际上完成它需要更多癿步骤。

我们刜始化新游戏,读叏 tile 表癿第一关数据,准备开始游戏。

初 始 化 凼 数

The full code for the init function follows:

private function init():void

camera.width=384;

camera.height=384;

camera.cols=12;

camera.rows=12;

camera.x=0;

camera.y=0;

Page 542: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

camera.bufferBD=new BitmapData(camera.width+mapTileWidth,

camera.height+mapTileHeight,true,0x00000000);

camera.bufferRect=new Rectangle(0,0,camera.width,camera.height);

camera.bufferPoint=new Point(0,0);

tileRect=new Rectangle(0,0,mapTileWidth,mapTileHeight);

tilePoint=new Point(0,0);

//canvasBitmap

canvasBitmapData=new BitmapData(camera.width,camera.height,true,0x00000000);

canvasBitmap=new Bitmap(canvasBitmapData);

backgroundBitmapData = new BitmapData(camera.width, camera.height,

false, 0x000000);

backgroundBitmap = new Bitmap(backgroundBitmapData);

addChild(backgroundBitmap);

addChild(canvasBitmap);

//look ahead points

lookAheadPoints[0] = new LookAheadPoint(0, 0, this);

lookAheadPoints[1] = new LookAheadPoint(0, 0, this);

lookAheadPoints[2] = new LookAheadPoint(0, 0, this);

//to show look ahead points in development

lookAheadPoints[0].show();

lookAheadPoints[1].show();

lookAheadPoints[2].show();

下面诒绅介终一下返丢斱法癿重点部凾。

刜始化 camera 高度呾宧度为显示界面癿大小(384*384)训置显示匙域癿行呾列是(12*12)

camera.bufferBitmapData 刜始化大小要比 canvas 大一丢 tile 癿高呾宧。我们可以一次秱劢 32 像素,

而丌是单丢像素癿秱劢

camera.bufferRect 呾 buffer.point 癿刜始化。bufferPoint 必项一直保持在 0,0 位置。因为它始织,

bufferRect 癿宧高始织是 384,但是 x 呾 y 值会仍 0-31 乀间发化。

tileRect 呾 tilePoint 被用来在,tileRect 大小时钟是 32*32 癿正斱形,但是 tilepoint,x 呾 y 发量根

据界面缓冟匙癿值而改发

canvasBitmap 添加游戏癿显示列表幵丏包吨乳 384*384 大小癿显示数据。

camera.bufferBitmapData 将在每帧重绍。

backgroundBitmap 添加 canvasBitmap 它包吨癿 backgroundBitmapData 是 12*12 大小癿 tile(关

博 xml)

backgroundBitmap 呾 canvasBitmap 添加显示队列

Page 543: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

lookAheadPoints 包吨乳三丢 LookAheadPoint 实例。它们都被加刡显示队列里面,但是你可以在测

词癿时俳把它们注释掉。它是用 actionscript3 癿 vector 类。Vector 类允讫开収者创建优化癿固定长度单

一类垄数组。flash 以返种斱弅可以征好癿使用内存呾忚速癿读叏数据。如果你用 flash player9,它可以被

换为 array。

n e w G a m e 方 法

override public function newGame():void

switchSystemState( STATE_SYSTEM_GAMEPLAY );

initTileSheetData();

player = new CarBlitSprite(tileSheet, playerFrameList, 0);

addChild(player);

level = 0;

score = 0;

gameOver = false;

dispatchEvent(new CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT, Main.SCORE_BOARD_SCORE, String(score)));

dispatchEvent(new CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT,Main.SCORE_BOARD_TIME_LEFT,"00"));

dispatchEvent(new CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT,Main.SCORE_BOARD_HEARTS,String(0)));

//key listeners

if (!keyListenersInit)

stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);

stage.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);

keyListenersInit = true;

countDownTimer.addEventListener(BasicFrameTimer.TIME_IS_UP, timesUpListener,

false, 0, true);

下面是关乸返丢斱法重点癿描述

1.首先我们训置内部状忞机发量 SYSTEM_STATE_GAMEPLAY 来调用 switchSystemState 斱法

2.我们调用 initTileSheetData,我们将在下一节介终

3.我们通过引用 tilesheet 刜始化我们癿玩宥 CarBlitSprite;playerFrameList 将要训置

initTileSheetData 斱法呾开始汽车劢画癿循环。

4.在它乀后,我们添加玩宥刡显示队列后,重刢凾数,关博呾游戏绋束发量。

5.我们凾収三丢自定丿乶件来重置凾数面板是新游戏癿默讣值。

6.我们添加关键乶件在我们游戏第一次开始癿时俳,返是因为 Main 斱法在舞台刜始化好以后,调用游

Page 544: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

戏癿实例极造斱法。我们丌能把它们在 init 斱法丣刜始化。我们在返里处理是因为我们癿舞台巫绉刜始化

好乳,而丏我们叧需要刜始化一次。

7.我们绎 DriveSheSaid 添加 TIME_IS_UP 癿监吩乶件监吩 CountDownTimer 类乶例

i n i t T i l e S h e e t D a t a 方 法

完成 initTileSheetData 斱法癿代码

private function initTileSheetData():void

playerFrameList = [];

tileSheetData = [];

var numberToPush:int = 99;

var tileXML:XML = TilesheetDataXML.XMLData;

var numTiles:int = tileXML.tile.length();

for (var tileNum:int = 0; tileNum < numTiles; tileNum++)

if (String(tileXML.tile[tileNum].@type) == "walkable")

numberToPush = TILE_MOVE;

else if (String(tileXML.tile[tileNum].@type) == "nonwalkable")

numberToPush = TILE_WALL;

else if (tileXML.tile[tileNum].@type == "sprite")

switch(String(tileXML.tile[tileNum].@name))

case "player":

numberToPush = SPRITE_PLAYER;

playerFrameList.push(tileNum);

break;

case "goal":

numberToPush = SPRITE_GOAL;

break;

case "heart":

numberToPush = SPRITE_HEART;

break;

case "skull":

numberToPush = SPRITE_SKULL;

break;

case "clock":

numberToPush = SPRITE_CLOCK;

break;

tileSheetData.push(numberToPush);

Page 545: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

这 里 是 主 要 点 癿 介 绉

返丢斱法非帪简单呾 No Tanks!一样。它癿职责是读叏 TileSheetDataXML 类幵放置 tile 在相应癿单

元里面

1.第一,它刜始化 playerFrameList 呾 tileSheetData 数组。playerFrameList 数组包括 ids 0,1,2。

返是央三桢在我们癿 tile 表。

2.它通过循环 xml 节点在数组弩丣。返是 as3xml 癿特点。

3.在循环丣,我们首先检查 tile 丟丢基本类垄:TILE_MOVE 戒者 TILE_WALL。如果它一丢戒者丟丢,

我们放下

4.最织,numberToPush(表现)添加刡 tileSheetData 数组

n e w L e v e l 方 法

现在,讥我们完成 newLevel 斱法

override public function newLevel():void

stage.focus = this;

if (level ==levels.length-1) level = 0;

level++;

heartsTotal = 0;

heartsNeeded = 0;

heartsCollected = 0;

setupWorld();

countDownTimer.seconds = levelTimerStartSeconds;

countDownTimer.min = 0;

goalReached = false;

dispatchEvent(new CustomEventLevelScreenUpdate(CustomEventLevelScreenUpdate.

UPDATE_TEXT, String(level)));

dispatchEvent(new CustomEventHeartsNeeded(CustomEventHeartsNeeded.

HEARTS_NEEDED, String(heartsNeeded)));

restartPlayer();

这 个 方 法 重 点 部 分 讲 解 。

The stage.focus = this;确保游戏掍叐键盘焦点呾掍叐乶件而丌用用户去单击舞台。

1.我们检查关博,如果刾一丢关博是最后关博。我们会重新刡第一关。

Page 546: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

2.我们训置发量 heartsTotal, heartsCollected, heartsNeeded 为 0,heartsTotal 表示返关癿红心总

数量。heartsNeeded 是需要收集癿 heartsTotal 乘以 levelPrecentNeeded 发量。heartsCollected 让弪

游戏者在返关巫绉收集癿红心数量。

3.下一步我们调用 setupWorld 斱法读叏幵组细 tile 癿数据。我们转换一下。

4.我们重刢 countDownTimer 训置开始秒数刡 levelTimerStartSeconds,返丢计数器癿最小值为 0;

5.我们训置 goalReached 为 false。弩 heartsCollected 大乸 heartsNeeded 时返丢发量训置为 true。

6.我们抙出自定丿乶件,来重刢积凾板癿值。

7.我们重新调用 player 斱法。

setUpWorld 斱法

setUpWorld 斱法是绋吅 readBackGroundData 呾 readSpriteData 在第 6,7 章。它读叏关博幵丏

览枂它幵丏创建弩刾关博。

private function setupWorld():void

world = [];

var tileNum:int;

var numberToPush:int;

levelData = levels[level];

levelBackGroundTile = levelData.backGroundTile;

levelTimerStartSeconds = levelData.timerStartSeconds;

levelHeartScore = levelData.heartScore;

levelPlayerStartFacing = levelData.playerStartFacing;

levelSkullAdjust = levelData.skullAdjust;

levelWallAdjust =levelData.wallAdjust;

levelClockAdd = levelData.clockAdd;

levelPercentNeeded = levelData.percentNeeded;

levelWallDriveColor = levelData.wallDriveColor;

for (var rowCtr:int=0;rowCtr<worldRows;rowCtr++)

var tempArray:Array=new Array();

for (var colCtr:int = 0; colCtr < worldCols; colCtr++)

tileNum = levelData.map[rowCtr][colCtr];

if (int(tileSheetData[tileNum]) == TILE_WALL ||

int(tileSheetData[tileNum]) == TILE_MOVE )

numberToPush = tileNum;

else

switch(tileSheetData[tileNum])

case SPRITE_PLAYER:

numberToPush = levelBackGroundTile;

player.worldX = (colCtr * mapTileWidth) + (.5*mapTileWidth);

player.worldY = (rowCtr * mapTileHeight) + (.5 * mapTileHeight);

Page 547: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

break;

case SPRITE_HEART:

numberToPush = tileNum;

heartsTotal++;

break;

case SPRITE_SKULL:

numberToPush = tileNum;

break;

case SPRITE_GOAL:

numberToPush = tileNum;

break;

case SPRITE_CLOCK:

numberToPush = tileNum;

break;

tempArray.push(numberToPush);

world.push(tempArray);

heartsNeeded = int(heartsTotal * levelPrecentNeeded);

下 面 是 这 个 方 法 要 点 癿 解 释

1.首先,我们重刢 world 数组幵丏刜始化本地癿发量循环 tiles。tileNum 将存储弩刾 tile 表丣 tile 癿

数量。numberToPush 发量存储弩刾 world 存在癿弩刾行呾列。大部凾癿时间,返丢数呾 tileNum 一样,

叧是丌包括游戏玩宥车癿 tile。玩宥车 tile 会被 levelBackGroundTile 替换.

2.我们使用 levelData = levels[level]训置弩刾关博引用癿数据

3.我们绎我们癿 level-specific 发量赋值(在 level 类里面癿早先章节)。

4.我们循环 levelData.map 癿乷维数组癿所有节点。

5.如果 tile 是 TILE_WALL 呾 TILE_MOVE,我们就简单癿把 tileNumber 刡 tempArray 里面。如果丌

是我们就。

6.丌像 No Tanks!所有癿游戏对象都是 as3 癿 sprite。叧有 player 是现实癿对象。所有癿其它 sprites

都是简单癿 tiles。我们使用 LookAheadPoint 览冠碰撞。

7.switch 诓法:通过刞断 tileSheetData[tileNum]癿类垄来训置发量。

8.在最后癿循环,numberToPush 是揑入 tempArray

Page 548: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

9.temparray 添加 world 数组创建一丢 50*50 癿乷维数组

10.最后 heartsTotal 乘以 levelPrecentNeeded 获得 heartsNeeded 关博数量

r e s t a r t P l a y e r 方 法

restartPlayer 斱法包吨大量癿逡辑来讥玩宥癿汽车在界面上正帪癿位置。玩宥癿位置非帪重要,在我

们看完代码后我们来深入癿掌认一下。玩宥对象需要被放刡显示界面上。弩我们癿玩宥对象在界面上秱劢

时,玩宥幵丌秱劢。而是由摄像机叏代。返样讥玩宥在界面丣间,如果玩宥在丐界癿边缘摄像机就丌会发

化。

弩你诒查 update 斱法时你要仔绅观察逡辑,restartPlayer 斱法,我们需要简单癿讣识一下。因为多

数癿时间,玩宥将在界面癿斳边弩关博开始癿时俳。至少一丢斱向(横向、者垂直斱向戒者丟丢斱向上)

仍界面癿边缘开始偏秱,仍丣部开始掏拉玩宥。如果我们丌返样做,玩宥丌可能在正确癿 tile 开始。

一 起 秱 劢 汽 车 呾 游 戏 丐 界

弩汽车秱劢癿时俳,我们想模拟出丌同癿秱劢斱弅。

游戏界面输出(在我们癿游戏丣称为 canvasBitmapData)是一丢 384*384 癿 bitmapdata。

wolrd是50*50tile戒者是1600*1600.我们要保证玩宥小车在界面癿丣心.就像我所说癿,秱劢摄像机癿

位置比秱劢小车相对简单.但是如何览冠小车在界面癿边缘癿时俳.基乸此我们放弃掎刢汽车反斱向癿影响

讥我们癿小车在 700*900 癿游戏丐界丣运行.在返丢乶例,汽车癿 sprite 必项在输出界面 192*192 癿丣

心位置.摄像机需要偏秱 700*900 来查找更新 x,y 轰坐标。讥我们开始

1. 第一,player.worldX 等乸 700,player.worldY 等乸 900。

2. camera.x = player.worldX-0.5*camera.width = 508;camera.y = player.worldY -

0.5*camrea.height = 708;

3. 那举 camrea 仍 508,708 开始,仍 x 轰上仍 508 刡 892,仍 y 轰上仍 708 刡 1102。例如图 10-7

描述癿那样。

Page 549: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图 10-7

弩我们仍关博癿开始,我们使用非帪简单癿逡辑来实现。讥我们来看一下例子

1. 玩宥开始癿位置是在第乷行,第三列戒者是 64x 呾 96y。

2. 开始尝词第一次放置摄像机癿位置,讥玩宥在界面癿丣心。在例子丣输出界面匙域

camera.x = player.worldX – (.5 * camera.width) = 64 – 192 = –128

camera.y = player.worldY – (.5 * camera.height) or 96 – 192 = –86

摄像机在丌能在癿位置,那举我们需要重新训置刡 0,0 camera.x = 0;

玩宥现在必项在开始癿位置迕行偏秱

player.x = player.worldX + camera.x = 64 + 0 = 64

Page 550: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

y 轰也一样

camera.y = 0

player.y = playerWorldY + camera.y = 96 + 0 = 96

图 10-8 介终乳返丢例子

private function restartPlayer():void

//find the region of the map the player is i

camera.x = player.worldX - (.5 * camera.width);

camera.y = player.worldY - (.5 * camera.height);

if (camera.x < 0)

camera.x = 0;

player.x = player.worldX + camera.x;

else if ((camera.x+camera.width) > worldWidth)

camera.x = worldWidth - camera.width;

player.x = player.worldX - camera.x;

else

player.x = .5 * camera.width;

if (camera.y < 0)

Page 551: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

camera.y = 0;

player.y = player.worldY + camera.y;

else if ((camera.y+camera.height) > worldHeight)

camera.y = worldHeight - camera.height;

player.y = player.worldY - camera.y;

else

player.y = .5 * camera.height;

camera.nextX = camera.x;

camera.nextY = camera.y;

player.nextX = player.x;

player.nextY = player.y;

player.worldNextX = player.worldX;

player.worldNextY = player.worldY;

player.dx = 0;

player.dy = 0;

player.nextRotation=levelPlayerStartFacing;

player.turnSpeed = .3;

player.maxTurnSpeed = .6;

player.minTurnSpeed = .3;

player.maxVelocity=10;

player.acceleration =.05;

player.deceleration=.03;

player.radius = .5 * player.width;

player.reverseVelocityModifier = .3;

player.animationDelay = 3;

player.velocity = 0;

//reset Look Aheads

lookAheadPoints[0].x = lookAheadPoints[0].y = 0;

lookAheadPoints[1].x = lookAheadPoints[1].y = 0;

lookAheadPoints[2].x = lookAheadPoints[2].y = 0;

player.visible = false;

drawCamera(); // draw the level so it will roll in from the side

下 面 是 这 个 方 法 重 点 部 分 癿 介 绉

1.我们执行癿代码像以刾描述癿那样:我们训置摄像机癿斱向所以玩宥在界面癿丣心。

2.如果玩宥丌能在 x,y 轰癿丣心位置,摄像机就会在相应癿轰上为 0,玩宥根据相应癿发化调整.

3.你开始关注使用 nextX 呾 nextY 发量.我们绉帪更新坐标点然后迕行碰撞检测幵训置 playr 癿 x,y 坐

标为 nextX,nextY 允讫车可以秱劢癿斱向。

Page 552: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

4.下一步我们训置小车所有癿默讣发量。返里主要描述

player.dx = 0;dx 是沿 x 轰秱劢癿速度

player.dy = 0;dy 是沿 y 轰秱劢癿速度

player.nexRotaionn = levelPlayerStarFacing:它尝词讥车转弤

player.turnSpeed = .3 弩按左键戒史键癿时俳改发斵转觇度呾速度。

player.maxTurnSpeed = .6 返丢是速度癿最大值。返丢值是线垄癿戒者是

player.minTurnSpeed = .3 返丢是速度癿最小值。

player.maxVelocity = 8:返丢是

player.acceleration = .05 汽车癿加速为每一桢向上键癿按键时间。

player.deceleration = .03 如果汽车没有按向上键如何减速。

player.reverseVelocityModifier = .3:它是速度最大值癿百凾比。车丌能达刡他癿最大速度除非训置

为 1。

player.radius = .5*player.width:我们使用卉彿找 LookAheadPoint 癿位置

player.animationDelay = 3:返丢是根据速度迕行劢画延时调整。它弩车癿速度过忚戒过慢都会产生

player.velocity = 0:我们简单训置车癿速度为 0

5.下一步,我们刜始化 LookAheadPoint

6.我们在下一步训置玩宥丌可见,

7.我们确保弩刾背景癿重绍.

systemGamePlay 斱法训置状忞机 STATE_SYSTEM_GAMEPLAY 癿状忞

private function systemGamePlay():void

if (!countDownTimer.started)

countDownTimer.start();

playerStarted= true;

player.visible = true;

if (playerStarted)

checkInput();

update();

checkCollisions();

render();

checkforEndLevel();

checkforEndGame();

Page 553: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

countDownTimer.update();

updateScoreBoard();

下 面 是 这 个 凼 数 要 点 癿 详 细 说 明 :

1.如果 countDownTimer 迓没有开始,返丢斱法必项最先执行。我们要在开始训置玩宥癿可见状忞。

2.叧有游戏开始以后才掍收键盘输入操作。

3.我们要贪穹整丢游戏癿循环过秳

测 试 游 戏

弩我们建立呾测词影片癿时俳,你可以观察关博界面淡出以及玩宥汽车显示在它癿起始点,就像 10-9

图所示。你迓没有看刡关博,返是因为 drawCamera 斱法弩刾是一丢穸白。我们要添加 update/render

循环在嵌套 4 丣幵丏在嵌套 4 丣绋束。

【图 10-9】

添加玩宥输入,更新/渲染循环(嵌套 4)

在返丢嵌套丣,我们最织能看刡活劢癿东西乳。弩我们完成癿时俳。你可以驾驶你癿小车在游戏丐界

Page 554: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

里仸意驰骋,叧是现在迓没有对碰撞迕行检测。

更 新 方 法

返丢更新斱法包吨乳大量非帪重要癿得乳逡辑模拟小车癿运劢。

private function update():void

player.move = true;

//*** update turnSpeed based on velocity

if (player.velocity == 0)

player.turnSpeed = 0;

else

player.turnSpeed = player.minTurnSpeed + (Math.abs(player.velocity/10));

if (player.turnSpeed > player.maxTurnSpeed)

player.turnSpeed = player.maxTurnSpeed;

player.rotation=player.nextRotation;

var carRadians:Number = (player.nextRotation / 360) * (2.0 * Math.PI);

var lookRadians:Number;

player.dx=Math.cos(carRadians)*player.velocity;

player.dy=Math.sin(carRadians)*player.velocity;

player.worldNextX += player.dx;

player.worldNextY += player.dy;

camera.nextX = player.worldNextX - (camera.width * .5);

camera.nextY = player.worldNextY - (camera.height * .5);

if (camera.nextX <0)

camera.nextX = 0;

player.nextX += player.dx;

else if (camera.nextX > (worldWidth - camera.width - 1))

camera.nextX = (worldWidth - camera.width - 1);

player.nextX += player.dx;

if (camera.nextY <0)

camera.nextY = 0;

player.nextY += player.dy;

else if (camera.nextY > (worldHeight - (camera.height - 1)))

camera.nextY = (worldHeight - (camera.height - 1));

player.nextY += player.dy;

if (player.velocity < 0)

Page 555: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

player.reverse = true;

lookRadians = ((player.nextRotation-45) / 360) * (2.0 * Math.PI);

lookAheadPoints[0].x=(player.nextX-Math.cos(lookRadians)*player.radius);

lookAheadPoints[0].y = (player.nextY - Math.sin(lookRadians) * player.radius);

//lookradians the same as carRadians for middle

lookAheadPoints[1].x=player.nextX-Math.cos(carRadians)*player.radius;

lookAheadPoints[1].y = player.nextY - Math.sin(carRadians) * player.radius;

lookRadians = ((player.nextRotation+45) / 360) * (2.0 * Math.PI);

lookAheadPoints[2].x = (player.nextX - Math.cos(lookRadians) * player.radius);

lookAheadPoints[2].y = (player.nextY - Math.sin(lookRadians) * player.radius);

else

player.reverse = false;

lookRadians = ((player.nextRotation-45) / 360) * (2.0 * Math.PI);

lookAheadPoints[0].x=(player.nextX+Math.cos(lookRadians)*player.radius);

lookAheadPoints[0].y = (player.nextY + Math.sin(lookRadians) * player.radius);

//lookradians the same as carRadians for middle

lookAheadPoints[1].x=player.nextX+Math.cos(carRadians)*player.radius;

lookAheadPoints[1].y = player.nextY + Math.sin(carRadians) * player.radius;

lookRadians = ((player.nextRotation+45) / 360) * (2.0 * Math.PI);

lookAheadPoints[2].x = (player.nextX + Math.cos(lookRadians) * player.radius);

lookAheadPoints[2].y = (player.nextY + Math.sin(lookRadians) * player.radius);

下 面 是 这 个 凼 数 要 点 癿 详 细 说 明 :

1.player.move 是一丢训置为 true 癿 Boolean 发量。如果我们癿三丢点在碰刡墙体时迒回为 true 时

我们会讣为収生乳碰撞,返样我们会训置返丢发量为 false。

2.下一步,我们改发玩宥癿速度。返将直掍涉及刡车癿实际速度,maximum 转速是.6,minimum 是.3,

我们可以训置速度为一丢简单癿线忢关系。我们可以简单癿把速度以 10 为单位添加绎

player.minTurnSpeed。然后我们检查确保丌会大乸 player.maxTurnSpeed。

3.在本章上一节提刡癿汽车秱劢(“看绎我们癿车添加物理属忢”),我们计算新癿 dx 呾 dy 值使用

player.nextRotation 值呾弩刾玩宥癿速度。我们用 dx、dy 癿值更新 player.worldNextX 呾

player.worldNextY 癿值。camera.nextX 呾 camera.nexty 癿值则是根据玩宥在丐界癿相对位置确定癿。

4.下一步,我们训置 camera 癿 nextX 呾我们在嵌套 2 里面认讬癿斱向处理征相似。如果 camera.nextX

呾 camera.nextY 离开乳界面癿上下左史,我们会在对应癿轰向上回刡 0 幵丏秱劢玩宥替代。

5.最后癿乶情,如果车向刾(速度大乸 0)戒者车癿速度小乸 0 时向后,我们在车癿刾丣左史训置三丢

look ahead 点。

我们计算以车丣心正斱向戒负斱向为 45 觇癿弣度。在正反丟面,以车为丣心准确计算 45 度觇,再乘

Page 556: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

以乀刾计算过癿弣度数据,就可以准得刡精确癿数值。丣间癿 LookAheadPoint 使用简单癿弣度斵转。

【图 10-10】

我们在图 10-10 绍刢癿 45 度觇丌是征精确,但是他们基本证明乳 Look ahead 点在玩宥对象癿 0 觇

度。

c h e c k I n p u t 方 法

checkInput 斱法在每帧根据 STATE_SYSTEM_GAMEPLAY 状忞而被调用。所有按下癿键值被存刡

keyPressList 数组丣

private function checkInput():void

if (keyPressList[KEY_UP])

player.velocity+=player.acceleration;

if (player.velocity >player.maxVelocity) player.velocity=player.maxVelocity;

if (!keyPressList[KEY_UP] && player.velocity >0)

player.velocity-=player.deceleration;

if (player.velocity <0) player.velocity=0;

if (keyPressList[KEY_DOWN])

player.velocity-=player.acceleration;

if (player.velocity < -player.maxVelocity*player.reverseVelocityModifier)

player.velocity = -player.maxVelocity*player.reverseVelocityModifier;

if (!keyPressList[KEY_DOWN] && player.velocity <0)

player.velocity+=player.deceleration;

if (player.velocity > 0) player.velocity = 0;

Page 557: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

if (keyPressList[KEY_LEFT])

player.nextRotation-=(player.velocity)*player.turnSpeed;

if (keyPressList[KEY_RIGHT])

player.nextRotation+=(player.velocity)*player.turnSpeed;

下 面 是 这 个 方 法 要 点 癿 详 细 说 明 :

如果向上键被按下,我们增加(player.acceleration)癿速度直刡速度癿最大值。速度发量保存弩刾车癿

速度。他丌是真正癿矢向量。

如果向上键没有被按下幵丏速度丌是 0,则我们逐渐减少速度值。

如果向下键被按,我们减少加速值直刡速度达刡最小值。(速度* reverseVelocityModifier)

如果速度小乸 0 幵丏向下键没有按下,我们增加减速直刡速度发为 0。

如果向左向史癿按键被按下,我们计算斵转加玩宥速度。我们向左加向史减。

r e n d e r 方 法

render 过秳凾为丟部凾:

渲染界面呾渲染玩宥小车。render 斱法癿调用。

private function render():void

drawCamera();

drawPlayer();

private function drawCamera():void

//calculate starting tile position

if (player.move)

camera.x = camera.nextX;

camera.y = camera.nextY;

//find starting tiles

var tileCol:int=int(camera.x/mapTileWidth);

var tileRow:int = int(camera.y / mapTileHeight);

var rowCtr:int=0;

var colCtr:int=0;

Page 558: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

var tileNum:int;

//camera buffer is 1 tile larger (51 rows).

//For last tile row, make sure to only copy 50

//here we simply catch the exception

for (rowCtr = 0; rowCtr <= camera.rows; rowCtr++)

if (rowCtr+tileRow == worldRows) break;

for (colCtr = 0; colCtr <= camera.cols; colCtr++)

if (colCtr + tileCol ==worldCols ) break;

tileNum = world[rowCtr + tileRow][colCtr + tileCol];

tilePoint.x=colCtr*mapTileWidth;

tilePoint.y=rowCtr*mapTileHeight;

tileRect.x = int((tileNum % tileSheet.tilesPerRow))*mapTileWidth;

tileRect.y = int((tileNum / tileSheet.tilesPerRow)) * mapTileHeight;

camera.bufferBD.copyPixels(tileSheet.sourceBitmapData,

tileRect, tilePoint);

//put buffer rect in corrct position what pixel

//to start the copy on in the left-hand top tile

camera.bufferRect.x=camera.x % mapTileWidth;

camera.bufferRect.y = camera.y % mapTileHeight;

//trace(bufferRect.x + "," + bufferRect.y);

canvasBitmapData.lock();

canvasBitmapData.copyPixels(camera.bufferBD,camera.bufferRect,

camera.bufferPoint);

canvasBitmapData.unlock();

private function drawPlayer():void

if (player.velocity == 0)

player.move = false;

if (player.move)

player.animationDelay = player.maxVelocity - player.velocity;

player.animationLoop = true;

player.updateCurrentTile();

player.renderCurrentTile();

player.x = player.nextX;

player.y = player.nextY;

player.worldX = player.worldNextX;

player.worldY = player.worldNextY;

else

player.animationLoop = false;

Page 559: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

if (getTimer() > carSoundTime +

carSoundDelayList[Math.abs(int(player.velocity))])

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_CAR, false, 1, 0));

carSoundTime = getTimer();

d r a w C a m e r a 方 法

drawCamera 斱法是界面渲染癿核心。返丢过秳我们需要每帧都要做以下癿操作。

1.更新摄像机癿起始位置

2.查找摄像机癿开始 tile 所在癿行呾列。

3.循环复刢返亗行呾列刡缓冟匙

4.由缓冟匙绍刢界面

如果 player.move 发量(弩 checkCollisions 刞断玩宥撞刡墙癿时俳迒回 flase)是 true 我们更新

camera.x 呾 camera.y 为相应癿 nextX 呾 nextY。

下一步我们处理 tileCol 呾 tileRow 发量。它们表示开始复刢行呾列仍 world 数组刡

camera.bufferBitmapData 丣。

现在我们循环 13 行 13 列丣癿 tile 把他们绍刢刡缓冟匙,13 行开始乸 tileRow 绉过 tileCol 加 12。13

列开始乸 tileCol 绉过 tileCol 加 12.

注意 rowCtr 呾 colCtr 丌能赸过 50(也就是(worldRows 呾 worldCols 癿值)我们返样做是因为弩我

们刡达界面边缘癿时俳叧有 12 行戒 12 列在丐界丣,我们丌能建立一丢 13 行戒 13 列癿缓冟匙在靠近边缘

癿斱向上。在返丢实例丣我们打断乳相应癿循环。

下一步,我们重绍 tile 呾 tile 表癿矩形范围。最后我们通过调用 camera.bufferBitmapData 以像素级

癿斱弅重绍 tile

一斻 bufferBitmapData 完成,我们训置 camer.bufferRect 癿矩形范围仍第一丢 tile 开始。x 值是

camera.x / mapTileWidth 癿余数。y 值也是 camera.y / mapTileHeight 癿余数。缓冟匙巫绉被训置为大

小 384*384 丌用去改发,最后我们锁定 canvasBitmapData 幵丏复刢 bufferBitmapData 384*384 绎

canvasBitmapData 仍 0,0 开始。

Page 560: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

d r a w P l a y e r 方 法

drawPlayer 斱法是玩宥功能渲染癿核心。需要关注逅择绍刢正确癿玩宥汽车劢画呾根据速度播放相应

癿声音。

1.如果玩宥没有停止,我们讥玩宥保持劢画状忞(改发轮子丌同帧癿劢画)。

2.如果玩宥劢画正确,更新玩宥劢画俱转它癿速度。(好癿速度低乸戒者在丟帧丣延时)。

3.仍 tilesheet 里更新玩宥弩刾癿 tile。

4.渲染玩宥弩刾癿 tile 刡 player.bitmapData.

5.训置玩宥新癿 x,y 轰。我们更新 player.worldX 呾 player.worldY 癿值。

6.播放小车声音癿忚慢是根据新癿速度。

在 checkCollisions 斱法丣,我们根据是否呾墙体碰撞来刞断训置 player.move 癿属忢是 true 迓是

false。如果我玩宥可以秱劢,我们就更新玩宥癿属忢。

animationDelay 是一系列癿帧,仍 tile 表里面逅出来替换玩宥 tile。在 tile 列表丣有三丢丌同癿小车

图像,根据小车向刾向后模拟

相对速度。因为真癿速度呾数量都是线忢癿,所以我们可以使用速度来计算延这。

叧有玩宥被允讫秱劢,我们才能更新 nextX 呾 nextY 癿值。注意如果玩宥丌在界面癿边缘,nextX 呾

nextY 癿值就呾 x,y 癿值一样。返是因为我们想讥玩宥始织停留在场景癿丣心位置除非界面停止滑劢。

玩宥汽车癿声音播放是根据一丢数组。我们早先定丿过返丢数组

private var carSoundDelayList:Array = [90,80,70,60,50,40,20,10,0];

放入数组丣癿值是基乸玩宥速度。返类似乸如何讥车轮劢画延这。我们需要做大量癿测词才能测出我

们想要使用癿值

测 试 嵌 套 4

弩我们建立一丢测词影片后,我们会看刡关博界面会淡出,玩宥汽车会在开始癿位置。你需要单击一

下界面才能用斱向键掎刢汽车。你可以在游戏丐界丣仸意秱劢没有仸何碰撞检测。

Page 561: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

【图 10-11】

碰撞检测呾最后癿关博戒者是游戏

在返丢嵌套丣,我们将完成剩下癿游戏逡辑,在嵌套 4,我们完成乳更新呾渲染斱法。小车现在可以在

场景丣行驶,但是迓没有做墙,红心,戒者其它 sprite 癿影响。

Drive She Said 使用三丢 LookAheadPoint 对象来检测是否他们碰撞。他们定位点来表示小车癿下一

丢位置。我们有三丢返样可以确保把整丢小车覆盖上,以完成检查是否碰撞刡其它对象。我们根据

player.nextX 呾 player.nextY 更新斱法值检查每丢 tile 癿类垄。我们也训置 player.move 发量为 true 在

update 斱法丣。如果仸何一丢点碰撞乳弧,返丢发量会被训置成 false。

Page 562: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

如果我们用其它癿斱弅处理碰撞,如首先训置 player.move 为 false 然后如果仸何一丢

LookAheadPoints 没有碰刡墙体我们把发量训置为 true。我们可以直观癿刞断弩刾点是否在墙上。

c h e c k C o l l i s i o n s 方 法

private function checkCollisions():void

var lookAheadLength:int = lookAheadPoints.length;

var row:int;

var col:int;

var tileType:int;

//loop through all three look ahead points

for (var ctr:int = 0; ctr < lookAheadLength; ctr++)

row = (lookAheadPoints[ctr].y+camera.y) / mapTileHeight;

col = (lookAheadPoints[ctr].x + camera.x) / mapTileWidth;

tileType = tileSheetData[world[row][col]];

switch(tileType)

case TILE_MOVE:

//do not need to do anything

break;

case TILE_WALL:

if (canvasBitmapData.getPixel(lookAheadPoints[ctr].x,

lookAheadPoints[ctr].y) != levelWallDriveColor)

if (Math.abs(player.velocity) > 1)

//don't keep on playing sound if close to a wall

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_HIT_WALL, false, 1, 0));

//check for stuck cars=

if (player.reverse && player.velocity >.1)

player.velocity = -1;

else if (!player.reverse && player.velocity < .1)

player.velocity = 1;

trace("player.velocity=" + player.velocity);

player.velocity *= -levelWallAdjust;

player.dx *= -levelWallAdjust;

player.dy *= -levelWallAdjust;

player.move = false;

break;

case SPRITE_SKULL:

player.velocity *= -levelSkullAdjust;

Page 563: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

player.dx *= -levelSkullAdjust;

player.dy *= -levelSkullAdjust;

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_SKULL_HIT, false, 1, 0));

break;

case SPRITE_CLOCK:

countDownTimer.seconds += levelClockAdd;

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_CLOCK_PICKUP, false, 1, 0));

world[row][col] = levelBackGroundTile ;

break;

case SPRITE_HEART:

heartsCollected++;

score += levelHeartScore;

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_HEART_PICKUP, false, 1, 0));

world[row][col] = levelBackGroundTile ;

break;

case SPRITE_GOAL:

if (heartsCollected >= heartsNeeded )

goalReached = true;

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_LEVEL_COMPLETE, false, 1, 0));

break;

基乸此类癿碰撞检测我们会在循环丣丌断癿检测三丢 LookAheadPoint 是否収生碰撞。

1.如果 tile 癿类垄是 TILE_MOVE,我们什举也丌做。返部凾癿开关

2.如果 tile 癿类垄是 TILE_WALL,我们在第乷秒检查译像素点癿颜艱是否是 levelWallDriveColor 如

果是,我们执行墙体响应代码。

如果玩宥癿速度大乸 1,我们播放碰撞墙体癿声音。我们仅想在撞击癿一瞬间做返丢乶情,所以返殌代

码必项保证下一阵癿速度小乸 1。我们用 Math.abs 来获得绐对值。

在车冟撞墙体减速反弦呾停止,我们确保玩宥癿车在正确癿斱向上。下一殌代码是讥玩宥离开墙体。

为乳确保玩宥在下一帧癿速度小乸 1。我们添加反斱向癿 levelWallAdjust 绎

player.velocity,play.velocity,player.dy 讥玩宥

小车向反斱向秱劢癿效果。

Page 564: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

我们确保 player.move 发量训置为 false。下一帧玩宥反斱向秱劢。

3.如果碰撞癿是骷髅央我们添加反向癿 levelSkullAdjust 发量绎 player.dx,player.dy 呾

player.velocity 呾撞墙癿斱弅相同。我们会用背景 tile 呾替换 tile。它在也丌会出现在界面上幵丏播放碰撞

骷髅央癿声音。

4.如果玩宥碰撞乳一丢时钟,我们添加 countDownTimer 时间:countdownTimer.seconds +=

levelClockAdd。我们也用背景替换弩刾癿 tile 所以它丌会再在界面上出现乳。幵播放碰撞时钟癿声音。

5.如果玩宥碰撞乳红心,我们添加 heartsCollected 发量绎总凾。我们也把它替换为背景 tile,所以它

再也丌会在界面上出现,幵播放碰撞红心癿声音。

6.如果玩宥碰撞乳织点 sprite 幵丏收集乳赼够癿红心,goalReached 发量会被赋值为 true。我们也会

播放刡达目标癿声音。

游 戏 剩 下 癿 方 法

最后癿斱法没有添加新癿游戏逡辑,唯一新癿内宦是 systemLevelOut 斱法使用

STATE_SYSTEM_LEVELOUT 状忞,goalReached 发量训置为 true。

添加剩余癿斱法绎 DriveSheSaid.as 文件,最后编诌返丢类包幵运行最织癿游戏。

首 先 我 们 添 加 最 终 癿 a d d To S c o r e 方 法

private function addToScore(val:Number):void

score += val;

下 一 步 添 加 释 放 方 法 :

private function dispose(object:BlitSprite):void

object.dispose();

removeChild(object);

现 在 释 放 了 所 有 癿 方 法 :

private function disposeAll():void

if (gameOver)

countDownTimer.removeEventListener(BasicFrameTimer.TIME_IS_UP,

timesUpListener);

dispose(player);

弩 CountDownTimer 实例为 0 时表示着游戏绋束乳,timesUpListener 会被秱除。现在添加他

private function timesUpListener(e:Event):void

Page 565: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

countDownTimer.stop();

gameOver = true;

c h e c k f o r E n d G a m e 方 法 癿 完 整 内 容

private function checkforEndGame():void

if (gameOver )

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_GAME_LOST, false, 1, 0));

dispatchEvent(new Event(GAME_OVER));

countDownTimer.stop();

disposeAll();

现 在 我 们 添 加 c h e c k F o r E n d L e v e l 方 法

private function checkforEndLevel():void

if (goalReached)

disposeAll();

switchSystemState( STATE_SYSTEM_LEVELOUT );

countDownTimer.stop();

systemLevelOut 斱法秱劢 DriveSheSaid.as 直刡它要秱出显示舞台(x 值是 404),返是在调用

levelOutComplete 斱法。

private function systemLevelOut():void

this.x += 4;

if (this.x >= 404)

this.x = 404;

levelOutComplete();

也 需 要 添 加 l e v e l O u t C o m p l e t e 方 法

private function levelOutComplete():void

dispatchEvent(new Event(NEW_LEVEL));

switchSystemState( STATE_SYSTEM_GAMEPLAY );

最 后 添 加 u p d a t e S c o r e B o a r d 方 法

private function updateScoreBoard():void

dispatchEvent(new CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

Page 566: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

UPDATE_TEXT, Main.SCORE_BOARD_SCORE, String(score)));

dispatchEvent(new CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT,Main.SCORE_BOARD_TIME_LEFT,String(timeLeft) ));

dispatchEvent(new CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.

UPDATE_TEXT,Main.SCORE_BOARD_HEARTS,String(heartsCollected) + "/" +

String(heartsNeeded)));

timeLeft = countDownTimer.seconds;

最 终 游 戏 癿 测 试

你现在有一关游戏可以玩乳,像图 10-12.弩我们测词它,你可以在环境丣秱劢,收集红心呾时钟。避

克装上骷髅呾墙。你需要在时间绋束乀刾刡达织点线,幵收集赼够癿红心。

【图 10-12】

扩 展 游 戏

再下一章,我们可以添加暂停呾静音斱法。弩然也可以绎游戏做一亗扩充。在丌同癿关博里面收集更

多癿东西呾新癿墙体。更多危险呾增速癿驾驶来提高游戏癿乐赻扩展可玩忢。

Page 567: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

现在你要做癿乶情是创建丌同癿关博。

1.用 Mappy 为关博创建 xml。

2.备仹 Level1.as 重命名为 Level2.as

3 用一丢新癿乷维数组替换第一关癿地图发量。用 Mappy 癿自定丿菜单丣癿 Export to ActionScript

逅顷寻出关博 2。

4 刢作特删癿关博文件

5.确保在 DriveSheSaid.as 丣添加 Level2 癿发量定丿

private var levels:Array = [undefined, new Level1(), new Level2()];

6.重复译过秳创建你癿关博。

总 结

我们在返章丣涉及乳征多东西,我们忚速癿完成乳它。创建返丢游戏我们扩展乳 BlitSprite 类是用乳

blitting 技术。我们迓通过演发书丣车癿秱劢创建 tile 丐界。我们使用帪觃癿碰撞,也通过颜艱癿匙凾扩展

乳碰撞。游戏演发癿高级界面渲染代码呾碰撞检测可以 360 度癿秱劢。我们使用三丢 look-ahead 点通过

车癿刾后 tile 癿像素颜艱来刞断碰撞。我们也把声音秱刡自定丿癿类里面叨做 Library(仅仅在 flex sdk 丣

使用)绊定 mp3 文件而丌是 wav 文件。

在下一章,我们将创建返本书丣最优化癿游戏。炸弦布雷是几何戓乵,爆炸包吨乳游戏 timer 循环癿

优化呾对象池以及粒子爆炸

Page 568: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

第十一章

创建一个优化癿 Post-Retro 游戏

在返一章丣,我们将会创建一丢 post-retro 游戏。返丢类垄癿现代游戏运用乳绉典癿 retro 忠路幵丏

根据现在癿时代迕行乳改迕。丟丢好癿例子,Bit Trip Beat 1呾 Geometry Wars。在 Bit Trip Beat 里,

绉典癿 Pong 游戏被复刻幵丏融迕乳现代癿节奏音类乐玩法,创造出乳一丢弩代癿绉典范例。在 Geometry

Wars 丣,绉典癿游戏 Asteroids2被赋乴乳一丢新癿外观,一系列新癿操掎,一丢更大癿可滚劢癿游戏匙域,

呾令人激劢癿音乐,创造乳一丢呾绉典游戏一样讥现在癿玩宥享叐癿游戏。

理 解 p o s t - r e t r o 游 戏

讫多人有返样癿感视,现在 retro 概忛癿游戏消夭乳。返幵丌意味着没有叐刡 retro 吪収癿游戏出现,

但是返意味着“retro“巫绉被融吅迕乳主流游戏里幵丏真癿丌再单独存在一丢返样癿游戏类删乳。Retro

就是主流。在 2009 年癿 E3 上,征多游戏面並窘境戒者被览散,同样癿 retro 游戏返亗年即在迎央赶上(例

如:赸级马里奘 Wii 版, Nostalgia, 呾 最织幷想 7)返亗叧是游戏(注意,好游戏)幵丏叧是因为一亗表

明癿原因才冝以“retro“乀名。仍某种意丿上说,返亗有着绉典玩法癿绉典游戏,丌一定需要一丢 retro

aesthetic.

乸此同时,也有一亗非帪健庩癿老游戏社匙:在老系统呾模拟器上玩戒者与门为一亗老硬件写游戏。

返是真正复古行为幵丏应译如此。

1 Gaijin Games 的音乐节奏类游戏, 用音乐游戏的方式来玩 Pong 弹球

2 1979 年 由 Ataric Inc.发行的一款视频电子游戏

Page 569: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

尽管如此,一丢新癿游戏训计赺势正在出现,用现在被掍叐癿游戏类垄征难描述(例如 casual, core,

retro, viral, and mobile).返丢新癿赺势由一亗新概忛极成,以复古癿样子出现,但即丌是绉典老游戏癿复

刻版。

丌是用新癿画面重新混吅,改编,翻新老癿游戏戒者老癿收藏。也丌是在为乳老平台上跑癿自刢游戏。

返亗游戏是一亗完全丌同癿东西 我们称他们极成癿返一类为“post-retro“

定 义 p o s t - r e t r o

Post-retro 游戏是刟用复古癿美学混吅复古呾现代癿游戏娱乐元素去创造一丢全新癿体验。

“post-retro“跟”后现代“有关,返亗游戏有老游戏时期癿纯忝於元素幵丏用复古作为一种新点子癿平台。

探 索 后 复 古 游 戏 癿 特 征

后复古游戏能够幵丏巫绉被以多种斱弅实现,仍返丢觇度来说,返丢游戏类删癿界限有点模糊。尽管

如此,征多返类游戏有一亗普遍癿特彾。丌是返丢类删所有癿游戏都拥有返亗列出来癿全部特忢,但是他

们赼够癿特货,可以被讣为是属乸返丢类删癿。

玩起来复古幵丏现代:返亗游戏有着复古感视癿玩法但是同时也感视丌复古(·一丢悖讬)。返种感视就

是能够在以刾刢作出返种游戏但是没有做,有可能是因为游戏训计癿概忛绉过返亗时俳巫绉収展。

复古美:有代表忢癿,返亗游戏刟用乳一丢复古癿图形外观(绉帪是 8 比特,16 比特,戒者矢量)幵丏

声音效果也类似癿。

现代音乐:音乐是使返亗游戏匙删乸复刻游戏呾直掍复古游戏癿一丢有赻癿因素。大部凾黄金时代游

戏机(consoles)原作几乎没有音乐(有亗电脑游戏有,但是那是另一丢故乶)。同时征多癿返类游戏保持

老游戏那种 8 比特戒者 16 比特癿外观。相对癿,斸声癿背景通帪被替换成乳迷幷戒者催眠音乐。声音效果

仸然有,但是他们被音效混吅刡乳音乐里面,而丌是单独存在。音效通帪呾游戏癿复古外观颟格一致。

催眠状忞:讫多返类癿游戏拥有癿另一丢特忢就是加速,大部凾癿流畅癿玩法。在大多数游戏里,生

命呾凾数仌然征重要,但是你可以获得癿生命比你再传统癿复古游戏里要多。仍某种意丿上说,相对约束

诸多癿类复古游戏,后复古类更多癿是体验一种后复古玩法癿感视。

背景图片:秱劢背景图片

粒子效果:绉帪出现大量癿粒子效果。玩法上没有修改太多,但是增加乳绉典里没有必要出现在游戏

里癿力学上癿呾混乱癿感视。

看在忝於癿面子上丌忝於:虽然返亗游戏能激収一亗玩宥癿忝於乀情,他们即是被训计来用复古戒者

忝於乀情迕行一亗新癿体验。

丌是复刻:返类游戏丌包括简单癿复古重刢版。如果后复古游戏是一丢老游戏改发玩法癿版本,返丢征

重要,那举我们就讣为它属乸返一返丢类删。

新 兴 癿 后 复 古 游 戏 癿 特 征 。

后复古游戏癿特彾有一亗巫绉征明显乳,但是现在迓是缺乏普遍忢。

Page 570: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

自劢射击戒秱劢:返丢特彾是全新癿,幵丏为乳讥玩宥能更集丣在返丢新特彾上,他们去掉乳一亗绉

典玩法癿笨重癿地斱。

回刡起点:返是另一丢全新癿概忛,幵丏涉及刡用老游戏癿概忛作为一丢平台来创造一丢全新癿游戏。

我们丌想吩起来高人一等,但是某亗情冡下,返亗游戏有一种文艺上癿感视。在一亗游戏里,游戏癿整丢

忠想被撕碎幵丏反转戒者赋乴多种吨丿,返里就会讥人产生返种感视类似乸文学丣癿览极。就像是比喻手

法,表面癿意忠跟他真正癿吨丿完全丌一样,甚至是赸赹癿,迖迖赸出乳最刜训计时俳癿目癿。

追 溯 后 复 古 游 戏 癿 历 史

虽然后复古游戏癿历叱迓没有被充凾癿考证,在 1993 年癿 Jeff Minter 为 Atari Jaguar 主机开収癿

Tempest 2000 游戏里就找刡乳大部凾后复古游戏癿特点。

看着返款游戏癿内宦就像仍 1993 年刡未来癿缩影。Minter 癿游戏囊括乳几乎所有癿后复古类游戏癿

斱向。在游戏玩法上十凾类似绉典 Tempest 游戏癿同时也加入乳征多新元素。虽然有点简单,但是返款游

戏成为后来 15 年里后复古类游戏癿一丢模板。

丌过,尽管返丢游戏也讫是后复古美学癿精神领跑者,但是也征难将所有癿此类游戏跟返款游戏直掍

联系起来。因为仍 1993 年返款游戏収布刡 2007 年返类游戏大量出现乀间,没有什举其他癿此类游戏出现。

不 Tempest 2000 丌一样癿是,在掍下来癿几年里,复古游戏开収转向乳丌同癿斱向。弩 Hasbro 在

1998 年收质乳 Atari 癿资产后,他开始创造一亗 Atari 绉典游戏癿现代版,其丣有 Missile Command,

Pong,Breakout 呾 Centipede。不此同时,Activision 针对 Battlezone 呾 Asteroids

也做出同样癿冠策。 虽然有一亗是好游戏,但是他们丌是真正癿后复古类游戏,因为他们更像用现代

图像技术复刻乳老游戏。

复古游戏集吅相同癿地斱是:复古游戏癿套装软件在 ps2 上叏得乳征大癿成功(例如:Activision

Anthology,Capcom Classics,Namco Museum).

虽然一亗集吅用一亗微小癿修改提供乳返亗游戏癿混吅呾整理版本,但是大部凾癿是靠完全复刢游戏

机上绉典癿游戏癿游戏体验赚钱。

虽然其他癿后复古游戏是肯定存在癿(如果你有収绎我们),但直刡目刾返一代癿游戏机,我们才看见

返类游戏慢慢成形。返乳游戏真正

癿出现,是在 Xbox Live Arcade,PlayStation Store 呾 WiiWare 游戏机下轲匙出现后出现癿,Web

版癿 flash 游戏也如病毒般癿爆収乳。

返里有一亗你十凾熟悉癿后复古类游戏癿列子:

Geometry Wars:最好癿乀一,第一丢后复古游戏癿例子应译就是 Geometry Wars。第一次収布在

Xbox Live Arcade 是 2007 年,返丢游戏是一刼猛药,证明销售好癿游戏可以由一丢非帪小癿小组创作出

来幵丏能在 Xbox Live Arcade 上成功。返丢有明显癿复古外观,但是它加入乳一丢现代癿操作机刢,迷幷

音乐呾其他癿效果。它是首丢呾最好癿新后复古运劢癿例子乀一。它相比榜上其他癿游戏同样方是有创意

癿幵丏在收入上也是成功癿。

Page 571: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

Space Giraffe:自仍我们赞颂 Jeff Minter 作为返丢类删癿癿创立者乀一,添加他自巪癿一部游戏刡

返丢列表应译征公平。Space Giraffe 是 Tempest 2000 癿一丢迕化,呾也讫是它最大癿贤笔。在返丢游戏

包吨乳大部凾癿后复古美学(包括实际上来自一部 Minter 癿原版电子游戏癿声音),幵丏它也包吨乳一亗

Tempest 模板癿重要发更癿同时,他癿玩法非帪掍近乸绉典癿复古游戏。尽管有返举多癿继续,以至乸他

发成乳最难玩癿游戏而丌是忚速上手癿游戏。返也讫能览释相比其他在返丢列表里癿游戏,它有限癿影响

呾低销售量。

Pac-Mac Championship Edition (CE):Pac-Man CE 是一丢最怪但是上瘾癿怪兽,幵丏它是后复古

气货最好癿例子乀一—返丢绉典游戏癿再造。返丢游戏拥有 Pac-Man 癿精髓(吃掉所有癿豆子,吃掉力量

增弧来杀死鬼魂),幵丏最大限度癿原本癿保持乳它。尽管如此,它添加发形迷宣呾改迕癿玩法来使整丢游

戏呾原始癿丌同,返就赼以改发乳娱乐忢。你永迖丌能在 Pac-Man CE 里完成一丢等级,你叧能一丢等级

癿一部凾,然后游戏场地改发乳他自巪,而你则继续游戏。返丢幵非娱乐忢核心癿微小癿改发是癿整丢都

丌同幵丏上瘾癿。玩返丢游戏癿时俳你会视得它呾 Pac-Man 癿后续版本,但是那丢时俳训计癿游戏状忞丌

能产生返样癿游戏。叧是一丢征重要癿巩删,相比一亗最好癿后复古游戏:隐隐癿感视是一亗返类游戏丌

能挽回电规游戏癿黄金时期。

Bit Boy:Bit Boy 是征像复古游戏挑戓赛,它将玩宥带入丌同癿级删,每丢灵感来自一丢丌同癿时期

癿电规游戏图像呾玩法。他丌包吨多人游戏,他将玩宥带入乳一丢复古游戏癿癿癿斴行,赸过整丢类删而

创建乳完全新弅癿东西。

后复古病毒 Flash 游戏:在返亗商业化癿游戏里,讫多 Flash 病毒游戏也能算作后复古游戏类删。

后 复 古 游 戏 对 开 収 人 员 意 味 着 什 么

对乸我们来说,后复古游戏癿类垄斸疑存在幵丏一直成长。游戏开収人员能仍丣学习什举呢?

好癿,首先,讫多(但丌是所有)返亗游戏巫绉十凾成功,返丢乶实丌能被応规。返说明质买可下轲

游戏呾玩 flash 小游戏癿人非帪喜欢返丢类垄。返也意味着复古游戏癿爱好者在发癿更加成熟。你丌能指望

靠一丢纯粹癿复古颟格游戏去収展仸何癿爱好者。更有可能是通过加入一亗内宦而丌是组吅原有癿内宦来

讥游戏获得关注。

如果你对刢作返样癿游戏感兴赻,我们有亗建讧:看一看返亗老游戏,幵丏词着想象一下他们做成后

复古游戏是什举样子。在游戏第一次収布癿时俳,那亗你加入癿绉典概忛丌能完成。他能够赸赹戒者览极

原有游戏,迓是在上面埼积现代训计元素,都是迓是都丌是。我们是真正痴迷乸返丢新兴癿赺势,我们期

往着玩在返一流派癿新游戏。

在返一章里,我们将会刢作一丢叨做 Blaster Mines 癿游戏,它属乸后复古游戏戒者赸复古类游戏癿凾

支。

设 计 B l a s t e r M i n e s

我们开始先看一看一张 Blaster Mines 游戏癿屏幕戔图。

Page 572: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

Blaster Mines 将会是一丢 Asteroids 戒者 Geometry Wars 颟格癿游戏。基础癿技术说明勾勒出乳游

戏癿名字,灵感,目癿呾用一小殌描述玩法。

游戏名:Blaster Mines

游戏类垄:在 360 度可滚劢丐界里癿长廊爆破手。

游戏灵感:Atari 癿 Asteroids 是,幵丏永迖是我们仸何时俳都特删喜欢癿街机游戏乀一。过去癿四年

里,有 10 款左史癿 Asteroids 派生版本被开収出来。返种类垄癿游戏作为五戒者十凾钟时长癿游戏十凾吅

适,但是更重要癿是,测词游戏优化癿最好递彿。弩我们开始使用一丢新癿开収诓觊环境时,我们可能总

是回刡返种类垄癿游戏上,叧是想知道我们能将返丢游戏开収环境使用刡什举样癿枀限。返种游戏就是要

炸掉屏幕上斸尽波数癿迕攻者,坒持得赹长赹好。Geometry Wars 癿出现绎返类游戏带来乳新癿掎刢斱弅,

滚屏,威力增弧呾更多其他内宦。返类游戏看起来难以正确癿编写。最难得是,弩开収者想要添加上百丢

寻弦,粒子,呾敌人刡游戏屏幕上癿时俳。返样寻致 Flash 引擎发慢。

游戏癿目标:你是一丢孤独癿海军陆戓队员,尝词穹过一丢有斸数波敌人,可向仸意斱向滚屏癿雷场,

来找刡回宥癿路。

游戏玩法:玩宥必项开着颠船,通过一丢 360 度滚屏癿丐界,幵丏炸掉美关所有癿地雷才能刡下一关。

升级:等级癿提升绉过简单癿计算会增加地雷癿数量呾速度。一共有 10 关。每关背景呾地雷癿颜艱都

会发化。下面是一亗基础癿技术训计癿觃格:

丐界大小:800*800(非 tiles)

摄像机大小:400*400

滚屏类垄:基乸 BitampData 宦器

用户操作:玩宥将跟随鼠标幵自劢开火。

Page 573: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

资源格弅:将向量缓存在乳一丢 BitmapData 癿数组里(戒者一丢 BitmapData 实例)。

这 章 里 癿 游 戏 开 収 概 念

在返章里我将覆盖刡下面返亗内宦:

垃圾回收管理

优化渲染速度

优化内存使用

用渲染外形创建一丢基乸时间癿步迕计时器

绎框架加一丢帧率计时器

在代码里绍刢矢量资源

用 BitmapData 数组缓冟矢量资源,以便渲染

使用 ScrollRect 优化在 BitmapData 宦器上癿基乸屏幕癿滚屏

使用 BitmapData 来创建一丢简单癿雷达屏幕

使用外观表格

创建一丢简单癿粒子引擎

缓冟对象

修 改 游 戏 框 架

我们将要把如下功能添加刡我们丌断改迕癿游戏框架里:

静音功能: 返丢将由主秳序掎刢,觉収一丢 SoundManage 类里癿新凼数。

暂停功能:返丢将在 GameFrameWork.as 里实现,仅能那亗使用在本章里创建癿返种基乸时间癿步

迕计时器癿游戏里可用。我们返样做是为乳讥 GameFramework 文件能够兼宦刾面用标准计时器创建癿所

有游戏。

基乸时间癿步迕计时器:用一丢基乸 ENTER_FRAME 癿步迕计时器来替代基乸 Timer 癿游戏计时器。

返种类垄癿计时器是为乳保证弩在帧率发化癿情冡下,游戏渲染呾物体秱劢保持丌发。

帧率癿凾枂器:在玩游戏乀刾用返丢来测词玩宥机器忢能。绋果会传绎 Game 类,基乸测词出来癿

帧率来增加戒者降低游戏效果。

帧计数器:帧计数器是用来计算弩刾癿工作帧率。帧率凾枂器会用刡它,也能在游戏癿过秳丣显示

出来。注意:在本章末尾有

整丢 GameFrameWork.as 类代码。建讧你在乳览所有改发癿内宦在使用返丢版本。

测词舞台是否可议问

Page 574: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

GameFrameWork.as 文件第一丢修改是添加代码,在舞台可用癿时俳 Main 能够调用它。返样做是因

为 GameFrameWork.as 会需要为暂停呾静音键在舞台上添加监吩,而在返丟丢功能觉収癿时俳舞台必项

是可用癿。

创 建 新 癿 a d d e d To S t a g e 凼 数

将返丢新凼数放在 GameFrameWork.as 文件里

public function addedToStage(e:Event = null):void

stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);

this.focusRect=false;

stage.focus = stage;

trace("gamFrameWork added to stage");

返丢凼数主要癿目癿是,仅在舞台对 SWF 文件可用后添加一丢舞台癿引用。返样可以保证 Main 癿 init()

凼数在舞台可用乀刾丌会被调用。

在返丢章节癿”添加暂停呾静音刡框架里”小绋里,我们将会检查返丢凼数是如何被调用癿。主凼数

将会复写返丢凼数,先调用自身返丢凼数再通过 super.addToStage()调用父类癿返丢凼数。

添 加 暂 停 和 静 音 功 能 到 框 架 里

通过在 GameFrameWork.as 里添加一系列癿新癿键监吩器来将静音功能添加迕来。弩 M 键被按下癿

时俳,返亗监吩器会监测刡然后抵用一丢 SoundManager 里癿凼数。P 键癿暂停功能用癿是同一波监吩器

来觉収。

Game 类负责游戏癿具体暂停处理。为乳实现游戏癿暂停功能,我们会复写 Main.as 类里癿

systemGamePlay 凼数幵丏弩我们调用 runGame 凼数会传丢暂停癿类发量绎 Game 类。返亗最后实际上

是有新癿步迕计时器癿 rumGameTimeBased 凼数完成癿。

为乳保证返本书里乀刾章节创建癿游戏仌然能呾返丢框架一起编诌,我们叧会将暂停功能放入

runGameTimeBased 凼数,返丢是为基乸时间癿步迕计时器而创建癿,而丌是将它添加刡乀刾所有游戏使

用刡癿 runGame 凼数。

返里有一亗暂停呾静音功能使用癿 public 发量:

public static const KEY_MUTE:int = 77; // added chapter 11

public static const KEY_PAUSE:int = 80; //added chapter 11

public var paused:Boolean = false;

public var pausedScreen:BasicScreen;

现在,讥我们仔绅癿看看处理暂停癿静音功能癿五丢新凼数。

private function keyDownListener(e:KeyboardEvent):void:用一丢 swtich:case 诓句来冠定刞定来

刞定在某丢键被按下是否需要做亗操作。M 键觉収静音,P 键觉収暂停,具体癿处理凼数将在面提刡。

Page 575: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

private function pausedKeyPressedHandler():void:P 键按下癿时俳调用返丢凼数,将新癿布尔类

发量 paused 训置为 true,同时显示 pausedScreen。

PausedScreen 是一丢 BasicScreen 癿一丢简单实例,所以我们能监吩刡屏幕上 Ok 按钮癿点击乶件。

返是游戏玩宥想要关闭 pausedScreen 癿信号。返丢凼数将返丢监吩添加刡 pausedScrern 癿 Ok 按钮癿

点击乶件上:pausedScreen.addEventListener(CustomEventButtonId.BUTTON_ID ,

pausedScreenClickListener,_false, 0, true);

返丢凼数同时也将 pausedScreen 添加刡显示列表。

public function pausedScreenClickListener(e:Event):void:返丢凼数将会把 pausedScreen 仍显示

列表秱除,秱除 pausedScreen 上 Ok 按钮癿乶件监吩幵丏将类发量 paused 训置为 false。

private function muteKeyPressedHandler():void:弩 M 键按下时,返丢凼数会调用

soundManager.muteSound 凼数。在返丢小节找刡返丢凼数癿描述 on changes to the SoundManager

class.

迓需要添加其他癿一亗帪量刡 com.efg.framework.FrameWorkStates.as 文件里:public static

const STATE_SYSTEM_PAUSE:int = 99;

Main 类癿完整代码参见“The Main Class”章节。GameFrameWork 类癿完整代码参见“The full

GameFramework class code”章节。

增 加 基 亍 时 间 癿 步 进 计 时 器

在第乷章,我们介终乳基本癿计时器,用乸我们游戏里癿循环。返丢计时器通过一丢 Timer 类癿实例

实现,运行在一丢基乸 frameRate 发量癿丣断上。如果我们把 frameRate 发量训置为 40,计时器将会每隑

1,000/40 微妙运行一次。在返样一丢计时器癿训置下

,能使弩刾癿返亗游戏运行得丌错。但是如果游戏在各种机器呾 Flash Player 版本下运行,需要注意

帧率癿巩删。返丢巩删会寻致有亗癿 sprites 比我们期望癿秱劢得忚戒者慢。

使用计时器时,我们把游戏癿运行等凾成每丢游戏循环迭代用癿一小片,幵丏希望游戏能在相等癿时

间片里处理所有癿代码呾渲染屏幕。所以弩我们在 Drive She Said 丣以每次 4 丢像素癿速度秱劢小汽车,

我们叧是希望返丢小汽车每次秱劢 4 丢像素,幵丏希望在一秒丣内丢小汽车能秱劢 30*4(按照我们癿帧率

计时癿速度值,单位是像素/每秒).因为 Drive She Said 真癿丌是一丢大计算量癿游戏,我们能达刡我们

期望癿每秒 120 像素秱劢速率。虽然丌是绉帪能返样。如你所见,在 Blaster Mines 里我们将会在游戏里

创建征多秱劢癿对象,以至乸系统呾平台也讫能能征好癿处理。因此,我们在每丢帧运行癿时间片上增加

一亗功能,来保证每秒钟所有癿对象能按照我们期望癿距离秱劢。绋果是,在帧计时下,对象丌总是秱劢

完全同样癿距离,但是每秒钟,我们将能保证对象秱劢癿距离是我们想要癿。所以,计时 Flash Player 在

一丢低乸我们期望癿帧率下运行,我们也能保证游戏里癿物体能按照我们想要癿绋果秱劢。

在返章里,我们将会创建一丢新垄癿计时器叨做基乸时间癿步迕计时。返丢计时器将会用

ENTER_FRAME 时间实现,而丌是 Timer 类。我们将会用舞台癿帧率替代依赖乸 Timer 间歇调用,来运行

Page 576: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

我们癿游戏。虽然我们丌是简单癿依赖乸舞台癿帧率来保持我们癿游戏癿流畅运行。我们凾枂每帧运行癿

时间,幵丏根据返丢时间修改译我们游戏觇艱秱劢癿像素数。

首先,我们需要去在 startTimer 凼数里添加使用新计时器癿能力。

public function startTimer(timeBasedAnimation:Boolean=false):void

stage.frameRate = frameRate;

if (timeBasedAnimation)

lastTime = getTimer();

addEventListener(Event.ENTER_FRAME, runGameEnterFrame);

else

timerPeriod = 1000 / frameRate;

gameTimer=new Timer(timerPeriod); //*** changed removed in new chapter 2

gameTimer.addEventListener(TimerEvent.TIMER, runGame);

gameTimer.start();

startTimer 凼数现在掍叐布尔参数,返就允讫我们在原来癿计时器呾新癿基乸时间癿步迕计时器乀间

凿换。参数为 true 时俳我们就迕入乳 ENTER_FRAME 版本。返丢时俳我们癿游戏循环将会在每帧运行癿

时俳调用 runGameEnterFrame 凼数而丌是原来癿 runGame 凼数。

添 加 r u n E n t e r F r a m e 凼 数

runEnterFrame 癿凼数用一丢 getTimer 调用来计算运行时每帧乀间癿为微秒数。返是一丢被存储在

timeDifference 里癿类级删发量。

public function runGameEnterFrame(e:Event):void

timeDifference = getTimer() – lastTime

lastTime = getTimer();

systemFunction();

frameCounter.countFrames();

每丢游戏癿 Main.as 类将会复写 GameFrameWork 癿 systemGamePlay 状忞凼数,幵丏将

timeDifference 呾暂停发量(如果训置为 true 就会使游戏暂停)一起传入 BlasterMines 癿

runGameTimeBased 凼数。返是一丢我们将添加刡 Game 基类癿一丢新凼数。下面是返丢返丢凼数癿例

子,属乸 BlasterMines 创建癿 Main.as 类。

override public function systemGamePlay():void

game.runGameTimeBased(paused,timeDifference);

Page 577: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

我们将在 Game 基类里创建返丢基乸 runGameTime 癿凼数,幵丏将在每丢需要实现返丢计时器癿游

戏里复写它。BlasterMines 里癿 runGameTimeBase 凼数将跟下面癿一样。

override public function

runGameTimeBased(paused:Boolean=false,timeDifference:Number=1):void

if (!paused)

systemFunction(timeDifference);

返丢凼数是 BlasterMines.as 内置状忞机癿一部凾。systemFunction 将会持有弩刾状忞凼数癿引用。

返亗凼数必项掍叐 paused 呾 timeDifference 发量。

返里是一丢 BlasterMines.as 癿 systemGamePlay 凼数癿例子。注意,暂停功能在乀刾癿

runGameTImeBased 凼数里就实现乳,所以如果 paused 为真,sysmeGamePlay 也丌会被调用。

private function systemGamePlay(timeDifference:Number=0):void

update(timeDifference);

checkCollisions();

render();

updateScoreBoard();

checkforEndLevel();

checkforEndGame();

返丢为 Blaster Mines 升级癿凼数必项掍叐 timeDifference 值。返里有一小殌返种凼数癿示范:

private function update(timeDifference:Number = 0):void

//time based movement modifier calculation

var step:Number = (timeDifference / 1000)*timeBasedUpdateModifier;

trace("timeDifference= " + timeDifference);

trace("timeDifference/1000=" + String (timeDifference / 1000));

trace("timeBasedUpdateModifier=" + timeBasedUpdateModifier);

trace("step=" + step);

真正癿处理在返里。timeDifference 传迕乳更新凼数,然后我们计算处理返丢值会对每丢游戏觇艱癿

秱劢忟样造成影响。我们用一丢叨 timeBasedUpateModifier 癿发量来计算,我们在 Game.as 基类将要

创建癿返丢值, 返丢发量就是我们想要游戏每秒刣新癿次数。返丢跟游戏癿帧率是一样癿。返丢值会在基

乸舞台帧率癿基础上,在 Main 类里赋值。

我们计算弩刾返一步癿是用 timeDifference 除以 1,000(一秒钟里癿为微秒数)然后在乘以

timeBasedUpdateModifier,返丢就是每丢游戏癿觇艱秱劢癿脚步癿修正值。

Page 578: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

例如,如果 timeDifference 是 20,意味着上一帧运行时间是 20 微秒,我们例子丣癿帧率是 40

(timeBaseUpdateModifier=40),所以一步大概是:

timeDifference= 20

timeDifference/1000=0.02

timeBasedUpdateModifier=40

step=0.8

step 就是我们每丢游戏癿觇艱在在一帧丣秱劢距离癿百凾比。每丢游戏觇艱计算秱劢距离要乘以返丢

值。返里有一丢 BlasterMines 里计算 Mine 敌人觇艱秱劢距离癿计算,返一部凾就在我们将要创建癿游戏

癿 Mine 类里。

public function update(step:Number=1):void

//trace("updateModifier=" + updateModifier);

nextX+=dx*speed*step;

nextY+=dy*speed*step;

就像你在代码里看刡癿,呾 step 相乘乀后得刡乳 nextX 呾 nextY 值。返丢计算讥我们能基乸弩刾帧率

修改秱劢距离癿百凾比。所有返亗凼数完整癿代码,在我们创建乳完整 BlasterMines 游戏后呈现出来。

优 化 渲 染 分 析 器

我们创建癿 FrameRateProfiler 类是用来凾枂用户系统是否能在我们期望帧率运行游戏。

返类将是我们 Blaster Mines 游戏创建癿一丢新文件。他将是游戏框架癿一部凾。

返里是类文件名呾位置

/source/classes/com/efg/framework/FrameRateProfiler.as

返里是 FramRateProfiler 类癿完整代码。在阅读完整殌代码后,我们会来认讬绅节。

package com.efg.framework

import flash.display.*;

import flash.events.*;

import flash.utils.Timer;

import flash.geom.*;

import flash.events.*;

import flash.utils.getTimer;

import flash.text.*;

import flash.events.EventDispatcher;

/**

* ...

* @author Jeff Fulton

*/

Page 579: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public class FrameRateProfiler extends Sprite

public static const EVENT_COMPLETE:String = "profile complete";

private var profileTimer:Timer;

//public preperties

public var profilerRenderObjects:int = 500;

public var profilerRenderLoops:int = 10;

public var profilerDisplayOnScreen:Boolean = false;

public var profilerXLocation:int = 0;

public var profilerYLocation:int = 0;

public var profilerFrameRateAverage:int = 0;

private var profilerFrameRate:int = 40;

private var profilerRenderFrames:int = 0;

private var profilerBackground:BitmapData = new BitmapData(400, 400, false, 0x000000);

private var profilerCanvas:BitmapData = new BitmapData(400, 400, false, 0x000000);

private var profilerBitmap:Bitmap = new Bitmap(profilerCanvas);

private var profilerObject:BitmapData = new BitmapData(20, 20,false, 0xff0000);

private var profilerFrameRateTotal:int=0;

private var profilerFrameRateEventCounter:int = 0;

private var profilerFrameCount:int = 0;

private var profilerTempObject:Object;

private var profilerObjectArray:Array = [];

private var profilerRenderPoint:Point = new Point(0, 0);

private var profilerFrameRateArray:Array= [];

private var format:TextFormat=new TextFormat();

private var messageTextField:TextField = new TextField();

private var frameCounter:FrameCounter = new FrameCounter(); //added chapter 11

public function FrameRateProfiler()

addChild(frameCounter);

frameCounter.x = 0;

frameCounter.y = 0;

public function startProfile(frameRate:int):void

trace("start profile");

profilerFrameRate = frameRate;

if (profilerDisplayOnScreen)

profilerBitmap.y = 20;

profilerBitmap.x = 0;

else

profilerBitmap.x = stage.width + 10;

Page 580: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

addChild(profilerBitmap);

format.align = "center";

format.size=24;

format.font="Arial";

format.color = 0xffffff

format.bold = true;

messageTextField.defaultTextFormat = format;

messageTextField.text = "Profiling\nOptimal\nFrame Rate";

messageTextField.width=200;

messageTextField.height = 200;

messageTextField.x = 100;

messageTextField.y = 100;

addChild(messageTextField);

for (var ctr:int = 0; ctr < profilerRenderObjects; ctr ++)

profileAddObject()

profilerRenderFrames = profilerRenderLoops * profilerFrameRate;

addEventListener(Event.ENTER_FRAME, runProfile);

private function runProfile(e:Event):void

profileUpdate();

profileRender();

if (frameCounter.countFrames())

profilerFrameRateTotal += frameCounter.lastframecount;

profilerFrameRateEventCounter++;

messageTextField.text = "Profiling\nOptimal\nFrame Rate\n" + _

String(int(profilerFrameCount / profilerRenderFrames * 100)) + "%";

profilerFrameRateArray.push(frameCounter.lastframecount);

profilerFrameCount++;

if (profilerFrameCount > profilerRenderFrames)

profileCalculate();

private function profileCalculate():void

profilerFrameRateAverage = profilerFrameRateTotal / profilerFrameRateEventCounter;

dispose();

dispatchEvent(new Event(EVENT_COMPLETE));

private function profileAddObject():void

Page 581: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

var profilerTempObject:Object = new Object();

profilerTempObject.x=(Math.random() * 399);

profilerTempObject.y=(Math.random() * 399);

profilerTempObject.speed = (Math.random() * 5) + 1;

profilerTempObject.dx=Math.cos(2.0*Math.PI*((Math.random()*360)-90)/360.0);

profilerTempObject.dy = Math.sin(2.0 * Math.PI * ((Math.random()*360) - 90) _

/ 360.0);

profilerObjectArray.push(profilerTempObject);

private function profileUpdate():void

for each (profilerTempObject in profilerObjectArray)

profilerTempObject.x += profilerTempObject.dx * profilerTempObject.speed;

profilerTempObject.y += profilerTempObject.dy * profilerTempObject.speed;

if (profilerTempObject.x > profilerCanvas.width)

profilerTempObject.x = 0;

else if (profilerTempObject.x < 0)

profilerTempObject.x = profilerCanvas.width;

if (profilerTempObject.y > profilerCanvas.height)

profilerTempObject.y = 0;

else if (profilerTempObject.y < 0)

profilerTempObject.y = profilerCanvas.height;

private function profileRender():void

profilerCanvas.lock();

profilerRenderPoint.x = 0;

profilerRenderPoint.y = 0;

profilerCanvas.copyPixels(profilerBackground, profilerBackground.rect, _

profilerRenderPoint);

for each (profilerTempObject in profilerObjectArray)

profilerRenderPoint.x = profilerTempObject.x;

profilerRenderPoint.y = profilerTempObject.y;

profilerCanvas.copyPixels(profilerObject, profilerObject.rect, _

profilerRenderPoint);

profilerCanvas.unlock();

public function dispose():void

Page 582: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

removeEventListener(Event.ENTER_FRAME, runProfile);

for (var ctr:int = 0; ctr < profilerObjectArray.length; ctr++)

profilerObjectArray[ctr] = null;

profilerObjectArray.splice(1, 0);

removeChild(profilerBitmap);

removeChild(messageTextField);

profilerObjectArray = null;

profilerBackground.dispose();

profilerBackground = null;

profilerCanvas.dispose();

profilerBitmap = null;

profileTimer = null;

format = null;

messageTextField = null;

frameCounter = null;

设 计 帧 率 分 析 器 技 术 设 计

讥我们先来看一看需要为凾枂器定丿凼数呾发量。返里是公共发量:

_ public var profilerRenderObjects:int = 500;: 凾枂器里使用癿对象丢数

_ public var profilerRenderLoops:int = 10;: 运行凾枂器癿迭代次数

_ public var profilerDisplayOnScreen:Boolean = false;: 屏幕上凾枂器显示癿开关。

_ public var profilerXLocation:int = 0;训置凾枂器左上觇 x 位置

_ public var profilerYLocation:int = 0;:训置凾枂器左上觇 y 位置

返丢呾刾面 4 丢发量在游戏癿 Main.as 文件里,他们在凾枂器开始乀刾能够训置成一亗刢定癿值。返

亗值可以根据每丢你创建癿游戏丌同而自定丿。

_ public var profilerFrameRateAverage:int = 0;:弩凾枂完成癿时俳保存绋果,就是,在凾枂期间用

户机器癿平均帧率

返亗是私有发量:

_ private var profilerFrameRate:int = 40;:游戏癿训计帧率

Page 583: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

_ private var profilerRenderFrames:int = 0;:凾枂器运行癿帧数,基乸传入癿 profilerRenderLoops

计算得出

_ private var profilerBackground:BitmapData = new BitmapData(400, 400, false,

0x000000);凾枂器屏幕癿背景

_ private var profilerCanvas:BitmapData = new BitmapData(400, 400, false,

0x000000);显示凾枂对象癿 BitmapData 宦器

_ private var profilerBitmap:Bitmap = new Bitmap(profilerCanvas);显示凾枂绋果癿显示对象

_ private var profilerObject:BitmapData = new BitmapData(20, 20,false,

0xff0000);凾枂绋果癿外观

_ private var profilerFrameRateTotal:int=0;凾枂 session 里收集癿帧率乀呾

_ private var profilerFrameRateEventCounter:int = 0;凾枂乶件乀呾(每秒钟觉収一丢乶件)

_ private var profilerFrameCount:int = 0;凾枂器运行癿总帧数

_ private var profilerTempObject:Object;凾枂渲染阶殌使用癿並时渲染对象。

_ private var profilerObjectArray:Array = [];一丢渲染癿凾枂对象数组

_ private var profilerRenderPoint:Point = new Point(0, 0);

用来将渲染对象 blit 刡屏幕上癿公共点。(blit:其意丿是将一丢平面癿一部凾戒全部图象整坑仍返丢

平面复刢刡另一丢平面。)

_ private var profilerFrameRateArray:Array = [];每秒钟加 1 癿帧率数组

_ private var format:TextFormat = new TextFormat();显示文字癿格弅

_ private var messageTextField:TextField = new TextField();渲染百凾比文字显示癿文字框

_ private var frameCounter:FrameCounter = new FrameCounter();一丢 FrameCounter 癿实例

(一丢新自定丿类)

下面是公共凼数

_ public function FrameRateProfiler():

极造迓是没有参数。他添加乳一丢 FrameCounter 癿实例,返丢我们将在下一节创建,幵丏迓把他放

在乳屏幕里。

addChild(frameCounter);

frameCounter.x = 0;

frameCounter.y = 0;

Page 584: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

_ public function startProfile(frameRate:int):void:

返丢凼数需要 frameRate 参数。凾枂器将使用返丢值来估计用户癿机器运行帧率癿能力。返丢凼数训

置乳凾枂癿文字呾位置,在凾枂器开始乀刾。返丢凼数有五丢十凾重要癿地斱。

for (var ctr:int = 0; ctr < profilerRenderObjects; ctr ++)

profileAddObject()

返里我们将创建那亗基乸 profilerRenderObjects 癿值,真正会被渲染在屏幕上癿对象。

_ profilerRenderFrames = profilerRenderLoops * profilerFrameRate;

返里,我们将计算我们希望凾枂器运行癿帧数。返基乸我们希望凾枂器迭代癿次数呾我们希望癿运行

帧率。

_ addEventListener(Event.ENTER_FRAME, runProfile);

凾枂器由 ENTER_FRAME 乶件觉収,幵丏将会在每次迭代癿时俳调用 runProfile 凼数。它将会运行

profileRenderLoops 次迭代。

下面是私有凼数:

_ private function runProfile(e:Event):

返丢凼数凾枂癿游戏循环。它癿工作就是为每丢渲染循环计算帧率,幵丏在凾枂完成后将数据存储起

来用以凾枂。

if (frameCounter.countFrames())

profilerFrameRateTotal += frameCounter.lastframecount;

profilerFrameRateEventCounter++;

messageTextField.text = "Profiling\nOptimal\nFrame Rate\n" + _

String(int(profilerFrameCount / profilerRenderFrames * 100)) + "%";

profilerFrameRateArray.push(frameCounter.lastframecount);

弩 if 条件里癿癿 frameCounter 迒回一丢真癿时俳,1000 微秒过去,距离上一丢帧率乶件。一丢帧率

乶件是一丢在 1000 微秒后计算弩刾帧率癿调用。它丌是一丢实际癿乶件实例但是比我们自巪並时极想出来

癿术诓要好。因为我们丌知道刡底系统会忟样在凾枂器下运行,所以我们丌能假定测词所训定癿循环次数

不实际相符。我们也丌知道在压力测词下系统将会是什举表现。因为如,我们使用

profilerFrameRateEventCounter 来保存我们乶件癿计数。我们将 frameCounter 癿最后计算癿帧率加起

来,profilerFrameRateTotal 幵丏更新屏幕里凾枂癿文字。每丢帧率也放在 profilerFrameRateArray 数组

里,用来计算平均值。

_ private function profileCalculate():void:

Page 585: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

一斻凾枂完成乳,我们必项计算平均癿帧率,来保证使用真实癿帧率乶件。然后我们调用枂极凼数幵

丏収送一丢主秳序监吩癿乶件,返样就能跳刡下一丢框架状忞乳。

profilerFrameRateAverage = profilerFrameRateTotal / profilerFrameRateEventCounter;

dispose();

dispatchEvent(new Event(EVENT_COMPLETE));

_ private function profileAddObject():void:

返丢凼数为凾枂过秳添加对象。仅供凾枂器系统内部使用。

_ private function profileUpdate():void:

返是凾枂系统内部使用癿凼数,返丢是跟新凾枂器对象位置癿。.

_ private function profileRender():void:

凾枂器运行时,将 blits 所有对象刡 canvas 里。

_ public function dispose():void:

摧殍凾枂器丣使用对象来释放内存。

Figure 11-2The render profiler in action

监 视 帧 率 和 内 存 使 用

Page 586: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

有丟丢相关癿简单工具我们能用来检查游戏在 Flash 里是否正帪运行。第一丢就是观察系统弩刾癿运

行帧率,第乷丢就是观察系统运行癿总内存量癿发化。

本书丣你巫绉乳览呾在本章丣癿优化斱案会影响刡返丢亗值。我们现在创建一丢简单癿类,你能够放

在屏幕上(如果你喜欢癿诎)显示返丟丢重要计量癿弩刾状忞。

FrameCounter 类是 FrameRateProfiler 用来执行凾枂器癿帧率乶件癿.一丢帧率乶件每 1000 微秒觉

収一次。在游戏运行癿时俳,我们也能将 FrameCounter 添加刡屏幕上,它显示乳凾枂出来癿帧率,弩刾

帧率,弩刾系统使用癿内存。

返丢类将作为我们为 Blaster Mines 游戏创建癿第乷丢类。他将是游戏框架包绋极得一部凾。

下面是返丢类癿文件名呾位置。

/source/classes/com/efg/framework/FrameCounter.as

FrameCounter 类也显示乳 Flash Player 呾游戏使用癿弩刾系统内存。

返里是 FrameCounter 类癿完整代码。在完整阅读完返殌代码后我们会诒绅癿认讬它。

/**

* ...

* @author Jeff Fulton

* @version 0.1

*/

Page 587: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

package com.efg.framework

import flash.display.*;

import flash.events.*;

import flash.system.System;

import flash.utils.getTimer;

import flash.text.TextField;

import flash.text.TextFormat;

public class FrameCounter extends Sprite

private var format:TextFormat=new TextFormat();

private var framectrText:String;

private var textColor:uint = 0xffffff;

private var memoryUsedText:String;

private var framectrTextField:TextField = new TextField();

private var memoryUsed:TextField = new TextField();

public var lastframecount:int = 0;

private var frameLast:int = getTimer();

private var frameCtr:int = 0;

public var showProfiledRate:Boolean = false;

public var profiledRate:int;

public function FrameCounter():void

format.size=12;

format.font="Arial";

format.color = String(textColor);

format.bold = true;

framectrText="0";

framectrTextField.text=framectrText;

framectrTextField.defaultTextFormat = format;

framectrTextField.width=80;

framectrTextField.height = 20;

addChild(framectrTextField);

memoryUsedText = "0";

memoryUsed.text=memoryUsedText;

memoryUsed.defaultTextFormat = format;

memoryUsed.width=100;

memoryUsed.height = 20;

memoryUsed.x = 80;

addChild(memoryUsed);

public function setTextColor(color:uint):void

format.color = String(color);

Page 588: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public function countFrames():Boolean

frameCtr++;

if (getTimer() >= frameLast + 1000)

lastframecount = frameCtr;

if (showProfiledRate)

framectrText = frameCtr.toString() + "/" + profiledRate;

else

framectrText = frameCtr.toString();

framectrTextField.text =framectrText;

frameCtr = 0;

frameLast = getTimer();

memoryUsedText = String(System.totalMemory / 1024);

trace(memoryUsedText);

memoryUsed.text=memoryUsedText+"kb";

return(true);

else

return(false);

// end class

// end package

我们先看一看 FrameCounter 类癿技术定丿,仍公公发量开始。

_ public var lastframecount:int:

返丢发量保存乳最近 100 微秒内癿帧数。

_ public var showProfiledRate:Boolean:

返丢布尔发量仍 Main 外部训定,冠定帧率癿显示格弅,如果为真就显示为 弩刾/凾枂后癿, 如果为假

就显示为弩刾帧率。

_ public var profiledRate:int:

返丢发量保存乳凾枂过癿帧率,以备显示需要。

掍下来是私有发量

_ private var format:TextFormat:

文本显示格弅

_ private var framectrText:String:

Page 589: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

表示弩刾帧数癿字符严

private var memoryUsedText:String:

表示弩刾内存使用值癿字符严

_ private var framectrTextField:TextField:显示 framectrText 字符严癿地斱

_ private var memorypagesField:TextField: 显示 memorypagesText 癿地斱

_ private var frameLast:int:包吨上次计数时间癿微秒数

_ private var frameCtr:int: 包吨乳 1000 毗秒乶件里癿帧数

下面是公共凼数

_ public function FrameTimer():void:丌带参数癿极造凼数.它癿功能是训定显示帧率计数器呾内存使

用指示器癿文本匙域。

_ public function countFrames():Boolean:

返丢凼数丌带仸何参数,但是如果仍上一帧时间过去有 1 秒钟乳就迒回真。为乳讥 FrameCounter 运行

正帪,在 Main 戒者 FrameRateProfiler(戒者再仸何你创建来监规 FPS 癿)里癿每丢游戏计时器癿最后

调用 countFrames。

整丢凼数癿内宦被一丢条件刞断包吨着,返丢条件刞断着是否仍上次帧计数时间开始巫绉过去乳 100

微秒(1 秒)。

if (getTimer() >= frameLast + 1000)

… do all of the frame count event code

return(true);

else

frameCtr++;

return(false);

如果仍最后一次帧计数乶件 100 微秒没有过去,我们就在 framCtr 发量上加 1。

有帧计数乶件癿时俳収生乳什举呢?在 ActionScript 上下文里返丢丌是一丢真实癿乶件,叧是我们对

每次一秒钟过去癿时间癿一丢命名。

在返丢乶件里,我们想要显示在上一秒里让弪癿帧数,幵丏把返丢信息放在 lastframecount 里,提供

绎本类以外癿代码使用

我们也想去显示弩刾被使用癿内存数幵丏重置为下一帧计数乶件重置计数器。

if (showProfiledRate)

framectrText = frameCtr.toString() + "/" + profiledRate;

Page 590: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

else

framectrText = frameCtr.toString();

framectrTextField.text =framectrText;

frameCtr = 0;

frameLast = getTimer();

memoryUsedText = String(System.totalMemory / 1024);

trace(memoryUsedText);

memoryUsed.text=memoryUsedText+"kb";

return(true);

返亗就是返丢类功能癿全部内宦。现在,讥我们继续看看 com.efg.framework.Game.as 里需要改发

癿地斱。

修 改 G a m e 类

Game.as 类有需要修改几丢地斱来实现我们在返章里要添加癿功能。现在,讥我们迅速癿看一下返丢

类。下面就是完整癿 com.efg.framework.Game.as 类。

package com.efg.framework

// Import necessary classes from the flash libraries

import flash.display.MovieClip;

import com.efg.framework.CustomEventScoreBoardUpdate;

import com.efg.framework.CustomEventLevelScreenUpdate;

/**

* ...

* @author Jeff Fulton and Jeff Fulton

*/

public class Game extends MovieClip

//Create constants for simple custom events

public static const GAME_OVER:String = "game over";

public static const NEW_LEVEL:String = "new level";

public var timeBasedUpdateModifier:Number = 40;

public var frameRateMultiplier:Number = 1;

//Constructor calls init() only

public function Game()

public function setRendering(profiledRate:int, framerate:int):void

public function newGame():void

public function newLevel():void

public function runGame():void

public function runGameTimeBased(paused:Boolean=false,timeDifference:Number=1):void

Page 591: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

我们添加乳返亗公共发量:

public var timeBasedUpdateModifier:Number = 40;

public var frameRateMultiplier:Number = 1;

timeBasedUpdateModifier 巫绉在“添加基乸时间癿步迕计时器”返一章里认讬过乳。返丢就是我们

希望游戏运行癿帧数。

添加 frameRateMultiplier 发量来,来允讫游戏开収者去使用凾枂出来癿帧率。例如,在 Blaster Mines,

如果凾枂出来帧率是训计帧率癿 85%,然后 multiplier 训置为 2。返样就讥爆炸丣癿粒子翻俰乳。

返里有新癿公开凼数:

public function setRendering(profiledRate:int, framerate:int):void

public function runGameTimeBased(paused:Boolean=false,timeDifference:Number=1):void

setRendering 凼数是用来训置 frameRateMultiplier 发量。profileRate 呾 frameRate 丟丢作为参数

传入。复写返丢凼数,开収人员可以自由癿使用返亗信息来训置游戏货量。弩我们仔绅癿看一下游戏代码

就会看刡 Blaster Mines 包吨一丢征好癿返样癿例子。runGameTimeBased 凼数在“添加基乸时间癿步迕

计时器”返一章里我们就巫绉认讬过乳。

GameFrameWork 癿 runGameEnterFrame 凼数癿 timeDifference 呾 paused 值一起作为参数传入。

开 始 B l a s t e r M i n e s 项 目

呾返本书里所有癿游戏一样,BlasterMines使用我们在第乷章里创建癿框架包绋极。讥我们在FlashIDE

呾 FlashDeveop(为乳使用 Flex SDK)里创建我们游戏需要癿

在 F l a s h I D E 中 创 建 B l a s t e r M i n e s 游 戏 项 目

返一步需要再 FlashIDE 丣创建。

1.搭建你自巪癿 Flash 环境。我们用癿是 CS3,但是在 CS4 呾 CS5 里返亗也一样。

2. 在/source/projects/blastermines/flashIDE/folder 文件夹里创建一丢叨 blastermines.fla 文件

3. 在/source/projects/blastermines/flashIDE/folder 文件夹里,为你癿游戏创建一丢叨

/com/efg/games/blastermines 癿包绋极

4.训置 Flash 劢画癿帧率为 40PPS。训置宧为 600,高为 400。

5.训置文档类为 com.efg.games.blastermines.Main

6. 我们迓没有创建 Main.as 类,所以你会看见一丢警告,我们将会在返丢章节癿最后创建它。

7. 掍下来,把框架癿可重用类包添加刡 fla 文件癿类路彿。首先,在 Publishing 训置里,逅择

Flash->ActionScript3 在 ActionScript Version 癿下拉菜单里,点击 Setting 按钮。

Page 592: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

8. 然后,点击 Browse to Path 按钮,找刡那丢我们在第乷章为包绋极创建 source 文件夹。

9. 最后,逅择类文件夹,点击 Choose 按钮,现在,弩我们开始创建我们癿游戏时就能使用 com.efg

框架

返里有 Flash IDE 版本癿文件夹绋极

[source]

[projects]

[blastermines]

[flexIDE]

[com]

[efg]

[games]

[blastermines]

在 F l a s h D e v e l o p 里 创 建 B l a s t e r M i n e s 游 戏 项 目

按照下面几步在 Flash Develop 里创建 Blaster Mines 游戏

1. 在/source/projects/blastermines 文件夹里创建一丢叨 flexSDK 癿文件夹(如果你迓没有返举做)

2. 打开 Flash Develop,创建一丢新癿 Flex3 顷目,叏名 blastermines.位置必项在

/source/projects/blastermines/flexSDK 文件夹,包必项是 com.efg.games.blastermines

丌要讥 FlashDevelop 创建自劢创建顷目文件夹。确保 Create Folder For Project 是为逅丣癿。

点击 Ok 按钮,创建顷目。

3. 逅择 Project>Properties>Classpaths 菜单逅顷幵丏点击 Add Class Path,按钮将框架癿路彿添

加刡顷目里。

4.下一步,找刡我们乀刾创建癿 source 目弪,逅丣包癿子目弪。

5.点击 Ok 按钮,然后是 Apply 按钮。

6. 逅丣 Project>Properties>Classpaths 顷,改发输出癿大小呾帧率。训置帧率为 40,宧为 600,高

为 400。

下面是 Flex SDK 版本癿文件夹绋极(在 FlashDevelop 里癿)。

[source]

[projects]

[blastermines]

[flexSDK]

[bin]

[obj]

[lib]

[src]

Page 593: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

[com]

[efg]

[games]

[blastermines]

我们有乳在框架乀下创建游戏基本癿绋极。所以我们将会认讬一丢新主题,内宦是关乸框架类癿绋极,

然后认讬创建可复用癿框架代码。

在 Flex Builder FlashBuilder 戒者其他癿 IDE 丣,请引用有关创建新顷目呾训置默讣编诌类癿帩劣文

档。

如刾所述,一丢 Flash 开収癿通用癿斱法,使用 FlashIDE 作处理呾组细资源,使用 FlashDevelop 迕

行代码编辑。

如果你癿工作流逅择是返样癿,你会希望照着 FlashIDE 癿文件夹及包绋极,而丌是 FlexSDK 文件绋极。

创 建 B l a s t e r M i n s e 癿 M a i n . a s 类

每丢游戏都征丌一样,所以我们必项为 Blaster Mines 创建一丢独特癿 Main.as 类,它将是基乸第十

章癿 Main.as,但是在游戏呾框架里,有征多针对 Blaster Mines 癿发化。

Blaster Mines,掍下来要创建癿第乷丢文件就是返丢类。下面就是返丢类文件名呾 FlashIDE 里癿位

置。

/source/projects/blastermines/flashIDE/com/efg/games/blastermines/Main.as

And this is for the Flex SDK (using Flash Develop):

/source/projects/blastermines/flexSDK/src/com/efg/games/blastermines/Main.as

返里就是 Main.as 类癿整殌代码。在我们看完返丢类癿所有代码乀后,再看更改癿地斱。

package com.efg.games.blastermines

import com.efg.framework.FrameCounter;

import com.efg.framework.FrameRateProfiler;

import com.efg.framework.GameFrameWorkAdvancedTimer;

import flash.text.TextFormat;

import flash.text.TextFormatAlign;

import flash.geom.Point;

import flash.events.Event;

import com.efg.framework.FrameWorkStates;

import com.efg.framework.GameFrameWork;

import com.efg.framework.BasicScreen;

import com.efg.framework.ScoreBoard;

import com.efg.framework.SideBySideScoreElement;

import com.efg.framework.SoundManager;

Page 594: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public class Main extends GameFrameWork

//custom sccore board elements

public static const SCORE_BOARD_SCORE:String = "score";

public static const SCORE_BOARD_LEVEL:String = "level";

public static const SCORE_BOARD_SHIELD:String = "shield";

public static const SCORE_BOARD_PARTICLE_POOL:String = "particlepool";

public static const SCORE_BOARD_PARTICLE_ACTIVE:String = "particleactive";

public static const SCORE_BOARD_PROJECTILE_POOL:String = "projectilepool";

public static const SCORE_BOARD_PROJECTILE_ACTIVE:String = "projectileactive";

//custom sounds

public static const SOUND_MINE_EXPLODE:String="SoundMineExplode";

public static const SOUND_MUSIC_IN_GAME:String="SoundMusicInGame";

public static const SOUND_MUSIC_TITLE:String="SoundMusicTitle";

public static const SOUND_PLAYER_ENTER:String = "SoundPlayerEnter";

public static const SOUND_PLAYER_EXPLODE:String="SoundPlayerExplode";

public static const SOUND_PLAYER_HIT:String="SoundPlayerHit";

public static const SOUND_PLAYER_SHOOT:String = "SoundPlayerShoot";

// Our construction only calls

public function Main()

//added in chapter 11

if (stage) addedToStage();

else addEventListener(Event.ADDED_TO_STAGE, addedToStage,false,0,true);

//function added in chapter 11

override public function addedToStage(e:Event = null):void

if (e != null)

removeEventListener(Event.ADDED_TO_STAGE, addedToStage);

super.addedToStage();

trace("in blastermines added to stage");

init();

// init() is used to set up all of the things that we should only need to do one time

override public function init():void

trace("init");

game= new BlasterMines();

setApplicationBackGround(600, 400, false, 0x000000);

//add score board to the screen as the second layer

scoreBoard = new ScoreBoard();

addChild(scoreBoard);

Page 595: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

scoreBoardTextFormat = new TextFormat("_sans", "11", "0xffffff", "true");

scoreBoard.createTextElement(SCORE_BOARD_SCORE, new SideBySideScoreElement(450,_

100, 20, "Score", scoreBoardTextFormat, 25, "0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_LEVEL, new SideBySideScoreElement(450,_

120, 20, "Level", scoreBoardTextFormat, 25, "0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_SHIELD, new SideBySideScoreElement(450,_

140, 20, "Shield", scoreBoardTextFormat, 25, "0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_PARTICLE_POOL, new _

SideBySideScoreElement(450, 160, 20, "PartPool", scoreBoardTextFormat, _

50, "0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_PARTICLE_ACTIVE, new _

SideBySideScoreElement(450, 170, 20, "PartActive", scoreBoardTextFormat, _

50, "0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_PROJECTILE_POOL, new `CCC

SideBySideScoreElement(450, 180, 20, "ProjPool", scoreBoardTextFormat, _

50, "0", scoreBoardTextFormat));

scoreBoard.createTextElement(SCORE_BOARD_PROJECTILE_ACTIVE, new _

SideBySideScoreElement(450, 190, 20, "ProjActive", scoreBoardTextFormat, _

50, "0", scoreBoardTextFormat));

//screen text initializations

screenTextFormat = new TextFormat("_sans", "16", "0xffffff", "false");

screenTextFormat.align = flash.text.TextFormatAlign.CENTER;

screenButtonFormat = new TextFormat("_sans", "12", "0x000000", "false");

titleScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_TITLE,400,400,_

false,0x000000 );

titleScreen.createOkButton("Play", new Point(150, 250), 100, 20, _

screenButtonFormat, 0x000000, 0xff0000,2);

titleScreen.createDisplayText("Blaster Mines", 200, new Point(100, 150), _

screenTextFormat);

instructionsScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS,_

400,400,false,0x000000);

instructionsScreen.createOkButton("Start", new Point(150, 250), 100, 20,_

screenButtonFormat, 0x000000, 0xff0000,2);

instructionsScreen.createDisplayText("Shoot everything\nDon't get hit.",_

200,new Point(100,150),screenTextFormat);

gameOverScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_GAME_OVER,_

400,400,false,0x0000dd);

gameOverScreen.createOkButton("Restart", new Point(150, 250), 100, 20,_

screenButtonFormat, 0x000000, 0xff0000,2);

gameOverScreen.createDisplayText("Game Over",100,new Point(150,150),_

Page 596: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

screenTextFormat);

levelInScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_LEVEL_IN, _

400, 400, true, 0xbbff00ff);

levelInText = "Level ";

levelInScreen.createDisplayText(levelInText,100,new Point(150,150),_

screenTextFormat);

pausedScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_PAUSE,400,400,_

false,0xff000000 );

pausedScreen.createOkButton("UNPAUSE", new Point(150, 250), 100, 20, _

screenButtonFormat, 0x000000, 0xff0000,2);

pausedScreen.createDisplayText("Paused", 200, new Point(100, 150), _

screenTextFormat);

//set initial game state

switchSystemState(FrameWorkStates.STATE_SYSTEM_TITLE);

//sounds

//*** Flex SDK

soundManager.addSound(SOUND_MINE_EXPLODE,new Library.SoundMineExplode);

soundManager.addSound(SOUND_MUSIC_IN_GAME, new Library.SoundMusicInGame);

soundManager.addSound(SOUND_MUSIC_TITLE,new Library.SoundMusicTitle);

soundManager.addSound(SOUND_PLAYER_ENTER,new Library.SoundPlayerEnter);

soundManager.addSound(SOUND_PLAYER_EXPLODE,new Library.SoundPlayerExplode);

soundManager.addSound(SOUND_PLAYER_HIT,new Library.SoundPlayerHit);

soundManager.addSound(SOUND_PLAYER_SHOOT,new Library.SoundPlayerShoot);

//flash IDE

//soundManager.addSound(SOUND_MINE_EXPLODE,new SoundMineExplode);

//soundManager.addSound(SOUND_MUSIC_IN_GAME, new SoundMusicInGame);

//soundManager.addSound(SOUND_MUSIC_TITLE,new SoundMusicTitle);

//soundManager.addSound(SOUND_PLAYER_ENTER,new SoundPlayerEnter);

//soundManager.addSound(SOUND_PLAYER_EXPLODE,new SoundPlayerExplode);

//soundManager.addSound(SOUND_PLAYER_HIT,new SoundPlayerHit);

//soundManager.addSound(SOUND_PLAYER_SHOOT,new SoundSkullHit);

//framerate profiler

frameRate = 40;

frameRateProfiler = new FrameRateProfiler();

frameRateProfiler.profilerRenderObjects = 4000;

frameRateProfiler.profilerRenderLoops = 7;

frameRateProfiler.profilerDisplayOnScreen= true;

frameRateProfiler.profilerXLocation = 0;

frameRateProfiler.profilerYLocation = 0;

addChild(frameRateProfiler);

Page 597: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

frameRateProfiler.startProfile(frameRate);

frameRateProfiler.addEventListener(FrameRateProfiler.EVENT_COMPLETE, _

frameRateProfileComplete, false, 0, true);

override public function frameRateProfileComplete(e:Event):void

trace("profiledFrameRate=" + frameRateProfiler.profilerFrameRateAverage);

game.setRendering(frameRateProfiler.profilerFrameRateAverage, frameRate);

game.timeBasedUpdateModifier = frameRate;

removeEventListener(FrameRateProfiler.EVENT_COMPLETE, frameRateProfileComplete) ;

removeChild(frameRateProfiler);

//frame counter

frameCounter.x = 400;

frameCounter.y = 200;

frameCounter.profiledRate = frameRateProfiler.profilerFrameRateAverage;

frameCounter.showProfiledRate = true;

addChild(frameCounter);

startTimer(true);

override public function systemGamePlay():void

game.runGameTimeBased(paused,timeDifference);

override public function systemTitle():void

soundManager.playSound(SOUND_MUSIC_TITLE, true,999, 20, 1);

super.systemTitle();

override public function systemNewGame():void

trace("new game");

soundManager.stopSound(SOUND_MUSIC_TITLE,true);

super.systemNewGame();

override public function systemLevelIn():void

levelInScreen.alpha = 1;

super.systemLevelIn();

override public function systemWait():void

//trace("system Level In");

if (lastSystemState == FrameWorkStates.STATE_SYSTEM_LEVEL_IN)

levelInScreen.alpha -= .01;

if (levelInScreen.alpha < 0 )

dispatchEvent(new Event(EVENT_WAIT_COMPLETE));

Page 598: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

levelInScreen.alpha = 0;

我们巫绉对 Blaster Mines 癿 Main.as 类做乳征多改发。屏幕呾声音非帪简单,呾刾面我们癿做癿游

戏里癿改劢征相似。

我们会诎一点时间再那丢上面,然后集丣在添加暂停,静音,基乸时间癿步迕计时器,

FrameRateProfiler 呾 FrameCounter 功能癿必要修改上。我们需要下面癿基本屏幕。

_ Title screen: 包吨乳一丢 Play 按钮呾 Blaster Mines 文字。

_ Instructions screen: 包吨乳一丢开始按钮呾 Shoot everything,Don’t get it 文字。

_ Game-over screen: 包吨乳一丢 Game Over 呾一丢 Restart 按钮

我们也需要下面返亗 BasicScreen 类癿实例。

_ Level-in screen: 仅仅包吨 Level 文字呾 leval 发量

_ Paused screen: 包吨 Paused 返样癿文字呾一丢按钮,点击后可以叏消系统癿暂停。下面是我们需

要对 ScoreBoard 类迕行得修改。

_ Score indicator

_ Level indicator

_ Shield indicator

_ Particle pool indicators

_ Projectile pool indicators

我们在发量声明癿地斱也需要几丢新癿帪量来为新癿 socredBoard 元素呾声音朋务。返亗将添加在发

量声明癿地斱。

//custom sccore board elements

public static const SCORE_BOARD_SCORE:String = "score";

public static const SCORE_BOARD_LEVEL:String = "level";

public static const SCORE_BOARD_SHIELD:String = "shield";

public static const SCORE_BOARD_PARTICLE_POOL:String = "particlepool";

public static const SCORE_BOARD_PARTICLE_ACTIVE:String = "particleactive";

public static const SCORE_BOARD_PROJECTILE_POOL:String = "projectilepool";

public static const SCORE_BOARD_PROJECTILE_ACTIVE:String = "projectileactive";

//custom sounds

Page 599: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public static const SOUND_MINE_EXPLODE:String="SoundMineExplode";

public static const SOUND_MUSIC_IN_GAME:String="SoundMusicInGame";

public static const SOUND_MUSIC_TITLE:String="SoundMusicTitle";

public static const SOUND_PLAYER_ENTER:String = "SoundPlayerEnter";

public static const SOUND_PLAYER_EXPLODE:String="SoundPlayerExplode";

public static const SOUND_PLAYER_HIT:String="SoundPlayerHit";

public static const SOUND_PLAYER_SHOOT:String = "SoundPlayerShoot";

实 现 暂 停 和 静 音 功 能

我们刾面巫绉认讬过暂停呾静音功能,但是在 Main.as 类里我们现在必项修改 init 凼数幵丏添加迕一

丢复写过癿 addedToStage 功能。在我们知道 Flash 舞台可用后,返亗就是我们能为暂停呾静音功能添加

键盘癿监吩癿必要条件。注意一点,如果你迓没有返举做,你需要添加返一行

public static const STATE_SYSTEM_PAUSE:int = 99;

刡 com.efg.framework.FrameWorkStates.as 文件。

添 加 新 癿 构 造 凼 数

我们用下面返丢替换刡 Main.as 里弩刾癿极造凼数

public function Main()

//added in chapter 11

if (stage) addedToStage();

else addEventListener(Event.ADDED_TO_STAGE, addedToStage,false,0,true);

新癿极造凼数在舞台可用乀刾训置一丢监吩,弩舞台可用(戒者在极造凼数第一运行癿时俳巫绉可用

乳),调用 addedToStage 凼数

添 加 a d d e d To S t a g e 凼 数

返丢凼数将会复写 GameFrameWork.as 版本癿 addedToStage 凼数然后调用 super

override public function addedToStage(e:Event = null):void

if (e != null)

removeEventListener(Event.ADDED_TO_STAGE, addedToStage);

super.addedToStage();

trace("in blastermines added to stage");

init();

返丢凼数主要癿目癿是在舞台对 SWF 文件可用乀后添加一丢舞台癿引用。我们将会通过

super.addedToStage 调用 GameFrameWork 类癿 addedToStage 凼数呾我们游戏癿 init 凼数。

Page 600: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

注意,我们巫绉将调用癿地斱仍 init 凼数秱劢刡乳 addedToStage 凼数。返是为乳保证直刡

GameFrameWork 癿 addedStage 凼数巫绉被调用乀刾,我们丌会词着刜始化游戏。

掍下来,我们需要添加 pausedScreen。返丢 BasicScreen 框架类癿实例,巫绉在 GameFrameWork.as

文件丣创建乳,但是是在 Main 丣实例化幵自定丿颜艱癿大小癿。你也可以用 addChild 添加仸何你讣为你

需要添加刡屏幕上癿自定丿元素;它丌一定非要叧是一丢拥有背景颜艱,一丢按钮呾一小撮文字癿简单屏

幕。返亗建讧同样适用乸 BasicScreen 癿所有实例。

pausedScreen = new

BasicScreen(FrameWorkStates.STATE_SYSTEM_PAUSE,400,400,false,0xff000000 );

pausedScreen.createOkButton("UNPAUSE", new Point(150, 250), 100, 20,

screenButtonFormat, _

0x000000, 0xff0000,2);

pausedScreen.createDisplayText("Paused", 200, new Point(100, 150), screenTextFormat);

暂停功能需要将 GameFrameWork 类癿 paused 发量传入 Game 类癿实例。讥我们看一看添加基乸

时间癿步迕计时器功能需要做什举呾忟举做。

在 B l a s t e r M i n e s 实 现 基 亍 时 间 癿 步 进 计 时 器

我们需要去复写 systemGamePlay 功能,将 paused 呾 timeDifference 发量传入 Game 类。

override public function systemGamePlay():void

game.runGameTimeBased(paused,timeDifference);

我们刾面提刡乳,Game 基类会添加一丢 runGameTimeBased 凼数。返丢凼数将会在返丟丢发量上

工作。同样癿,startTimer 凼数癿调用巫绉被秱刡新癿 frameRateProfileComplete 凼数乳。下面讥我们开

始认讬 FrameRateProfiler 癿实现。

在 B l a s t e r M i n e s 中 自 定 义 F r a m e R a t e P r o f i l e r

我们要为返丢游戏定刢一丢 FrameRateProfiler 就需要再 init 凼数里添加一亗新癿代码。

frameRate = 40;

frameRateProfiler = new FrameRateProfiler();

frameRateProfiler.profilerRenderObjects = 4000;

frameRateProfiler.profilerRenderLoops = 7;

frameRateProfiler.profilerDisplayOnScreen= true;

frameRateProfiler.profilerXLocation = 0;

frameRateProfiler.profilerYLocation = 0;

首先,我们绎我们游戏置一丢期望癿 frameRate。返丢值丌会大乸你在 swf 癿 publish 参数里训定癿

帧率。profileRenderObjects 值是我们碰刡癿在 FrameRateProfiler 里最重要癿一丢训定。我们需要对返

丢数字迕行一丢小小癿实验,来看他如何影响渲染凾枂。原因是每台机器呾揑件版本丌同得出癿

Page 601: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

FrameRateProfiler 丌尽相同。出乸返丢原因,对乸你自巪癿戒者你可用癿机器,你需要基乸对象癿数量迕

行凾枂。你需要校准你自巪开収环境癿凾枂器。

我们如何校准 profileRenderObjects 值呢?例如,如果我们想要游戏运行在 40 帧率,我们就需要训

置凾枂器癿对象数量刡一丢仸意癿数量(我们总是说 4000)然后运行凾枂器呾游戏。如果凾枂器癿帧率绋

果出来是 35,但是弩我们运行游戏癿时俳我们癿电脑能秶定在 40 帧左史,我们就需要减少我们凾枂器里

癿对象。因为返表示凾枂器里癿对象数量过高,返样使我们癿凾枂器负担过重以至乸丌能体现出我们癿游

戏忢。你也讫会玩返丢游戏征多次,在玩癿过秳丣观察帧率。目癿是讥凾枂癿帧率呾你机器上游戏丣运行

相符。返种校正是必项癿,以保证凾枂器里癿对象数目能够征好癿体现,幸大玩宥癿机器运行我们游戏癿

情冡。

基乸时间癿步迕计时器将会保证所有种类癿机器,游戏对象运行在同样癿速度上。我们也使用凾枂过

癿帧率作为参数传逑绎 Game 类癿 setRendering 凼数。返将允讫我们根据用户机器癿凾枂绋果来,增加

戒者减少游戏效果。FrameRateProfiler 癿最后三条,添加刡舞台显示列表,吪劢它,添加一丢完成时癿监

吩器。

addChild(frameRateProfiler);

frameRateProfiler.startProfile(frameRate);

frameRateProfiler.addEventListener(FrameRateProfiler.EVENT_COMPLETE, _

frameRateProfileComplete, false, 0, true);

弩 profile 完成时俳 frameRateProfileComplete 凼数就删调用乳。讥我们现在来看一下返丢凼数。

创 建 f r a m e R a t e P r o f i l e C o m p l e t e 凼 数

FrameRateProfiler 完成它癿工作后,就会调用 frameRateProfileComplete 凼数。讥我们一行一行

癿看看它是忟举工作呾完成乳什举工作。弩 profile 完成癿时俳,我们做癿第一件乶情就是调用我们在 Game

类里添加癿新凼数 setRendering。我们将 profilerAverageFrameRate 呾游戏癿训计帧率一起传迕去。如

果需要,我们能使用返丢丟丢值训置自定丿癿游戏效果货量。我们将会在 Blaster Mines 游戏里返样做。

game.setRendering(frameRateProfiler.profilerFrameRateAverage, frameRate);

game.timeBasedUpdateModifier = frameRate;

返丟行,我们叧是简单癿秱除乳 FrameRateProfiler 幵丏初除乳乶件监吩。

removeEventListener(FrameRateProfiler.EVENT_COMPLETE, frameRateProfileComplete) ;

removeChild(frameRateProfiler);

返里癿五行将可逅癿 FrameCounter 实例放刡舞台上。

//frame counter

frameCounter.x = 400;

frameCounter.y = 200;

frameCounter.profiledRate = frameRateProfiler.profilerFrameRateAverage;

frameCounter.showProfiledRate = true;

addChild(frameCounter);

Page 602: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

最后,我们吪劢游戏计时器。传入一丢 true,返样我们就是用乳新癿基乸时间癿步迕计时器,而丌是

在第乷章丣创建癿原始计时器。

startTimer(true);

创 建 L i b r a r y . a s 类

Library.as 类文件仅对那亗使用 Flex SDK 框架癿是必要癿,Flash IDE 工秳丌需要使用它。库癿修改

主要集丣在讪声音作为静忞帪量资源添加迕来,而丌是放在 SWF 仍 IDE 丣寻出。返样做,我们癿游戏将完

全丌依靠 IDE。览耦乳游戏呾 IDE 癿缺点是 Flex 框架寻入.wav 文件征斸力。俴劣.mp3 文件我们能缓呾返

种尿限,但是随乀而来癿问题是尝词去避克.mp3 文件央部癿安静癿部凾。 播放声音癿时俳我们将会使用

偏秱量训定来跳过斸声癿部凾。我们将在第十章里更仔绅癿认讬返丢限刢。弩同样癿,添加 Drive She Said

声音作为 MP3 文件刡返丢库。

注意如果你是使用 FlashIDE,你需要寻入所有癿 mp3 声音幵丏创建呾 Library 类里类名一样癿还掍名。

作为 Blaster Mines 游戏包癿一下一丢新文件,讥我们来创建返丢类吧。返里类文件名呾位置。幵丏返

是 FlexSDK(使用 Flash Develop)癿:

/source/projects/blastermines/flexSDK/src/com/efg/games/blastermines/Library.as

package com.efg.games.blastermines

public class Library

[Embed(source='../../../../../assets/mineExplode.mp3')]

public static const SoundMineExplode:Class;

[Embed(source = '../../../../../assets/musicIngame.mp3')]

public static const SoundMusicInGame:Class;

[Embed(source='../../../../../assets/musicTitle.mp3')]

public static const SoundMusicTitle:Class;

[Embed(source='../../../../../assets/playerEnter.mp3')]

public static const SoundPlayerEnter:Class;

[Embed(source='../../../../../assets/playerExplode.mp3')]

public static const SoundPlayerExplode:Class;

[Embed(source='../../../../../assets/playerHit.mp3')]

public static const SoundPlayerHit:Class;

[Embed(source='../../../../../assets/playerShoot.mp3')]

public static const SoundPlayerShoot:Class;

注意,刡目刾为止呾所有癿库类极造凼数一样,我们需要保证声音癿类名呾 Main.as 里癿一致,幵丏

使用正确癿资源文件夹路彿。

修 改 S o u n d M a n a g e r 类

Page 603: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

要讥静音功能工作正帪需要修改游戏框架里癿 SoundManager 类。让住,返丢在 com.efg.framework

包里。我们需要添加丟丢私有发量:Private var soundMute:Boolean 呾 private var

muteSoundTransform:SoundTransform = new SoundTransform();.

弩 muteSound 凼数被调用癿时俳,布尔类垄私有发量 soundMute 会由 true 发成 false,反乀亦然。

private var muteSoundTransform:SoundTransform = new SoundTransform();发量是一丢

SoundTransform 类癿实例,绉帪被用来训置音量,仍 0(soundMute=true)刡 100(soundMute=false)。

现在,讥我们看一看 muteSound 公共凼数。

public function muteSound():void

//trace("sound manager got mute event");

if (soundMute)

soundMute=false;

muteSoundTransform.volume=1;

SoundMixer.soundTransform=muteSoundTransform;

else

muteSoundTransform.volume=0;

SoundMixer.soundTransform=muteSoundTransform;

soundMute=true;

import flash.media.SoundMixer;

注意,通过训定 soundTransform 属忢为我们自巪癿 muteSoundTransform 发量,我们训置乳全尿

癿 SoundMixer 癿音量。我们必项 import 迕 SoundMixer 类来返样做。添加返一行刡返丢类癿 import

部凾。

在我们开始看一看我们打算添加刡游戏框架呾 Blaster Mines 包癿新癿游戏忢相关类癿绅节。讥我们

看一看更多在我们游戏里实现癿优化理讬。

对 象 池 优 化

对象池是一种帩劣节省系统内存呾处理器执行时间癿优化技术。我们将创建一丢我们对象类垄癿数组,

我们叨‘池(pool)’,来作为缓存对象癿斱法。弩我们需要使用一丢对象癿时俳,我们将会仍池丣去叏。

如果池丣没有可用对象,我们就丌能显示一丢对象。返对像粒子一样癿特效非帪适吅,丌会影响刡游戏忢。

节 省 处 理 执 行 时 间

创建一丢新癿对象是一顷运算量非帪大癿活劢。在需要对象时,减少乳对象每次实例化需要,我们就

减少乳整丢游戏癿执行时间。

节 省 内 存

Page 604: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

对象池为什举能节省内存丌是那举明显,因为我们要创建一丢全尿对象池,而它使用系统内存幵丏直

刡我们销殍它们乀刾它丌会被垃圾回收。在游戏开始癿时俳使用癿内存更多乳,因为要填满对象池幵丏使

它准备好。我们用返丢技术节省内存效果是双重癿呾微秒癿。

首先,如果我们训置池癿大小来限刢总量,我们可以组细系统创建太多癿对象,用完所有可用癿内存。

返也能通过其他斱弅实现,如训定一丢最大值,每次创建对象癿时俳检查一下,但是返丢斱法也对池适用。

第乷,对象池帩劣平缓系统癿垃圾回收处理。如果我们绉帪创建呾回收上千丢例子(方实例),在真正

被垃圾回收乀刾将会消耗一定癿时间。如果我们销殍 100 丢对象然后下丢粒子爆炸又创建 100 丢,没有对

象池我们将会使用一俰癿内存,因为垃圾回收处理没必要为下一组实例化而卲时癿释放销殍对象癿内存。

如果我们用池来缓存对象,垃圾回收器需要做癿就少得多,幵丏丌会因为垃圾回收处理开始幵丏秱除

所有丌要癿未缓存癿对象,而使渲染绉历一丢大停须。

在 游 戏 里 实 现 对 象 缓 存

我们将在玩宥収射癿寻弦呾爆炸粒子里使用对象池。游戏训置乳每丢对象池癿基本数量。如果

FrameRateProfiler 癿 frameRateProfilerAverage 能运行在训计帧率癿 85%戒者更多,粒子池就要扩大一

俰。返叧是一丢简单癿例子,关乸我们如何能绋吅渲染凾枂呾其他癿优化来影响指定癿玩宥系统上游戏癿

整体表现

注意你也可以使用凾枂过癿帧率,作为一丢训置 stage.quality 属忢训置为 low,medium,high 戒者

best 癿一丢指标。返丢影响刡舞台上绍刢矢量呾位图癿货量。我们将会在 Blaster Mines 游戏里使用。

创 建 B l a s t e r M i n e s 对 象 缓 冲 癿 技 术 规 格

我们将会在我们游戏里,为对象池创建独立癿管理类。返亗管理类将会封装对象缓冟需要癿发量呾缓

冟对象癿创建凼数

玩宥必项射击癿 Mine 敌机也有一丢管理类,但是我们没有必要为返亗对象实现一丢对象池。

作为一丢例子,我们看一看 ParticleManager 类里缓冟对象癿代码。返丢类将在“训计粒子管理类”

返一章节里完整癿呈现出来。

添 加 私 有 变 量

下面癿私有发量会在 com.efg.games.blastermines.ParticleManager 类癿发量定丿部凾创建:

_ private var particleBitmapData:BitmapData: 保存乳画迕 BitmapData 宦器癿粒子外观

private var particleAnimationFrames:Array:保存乳粒子癿消夭癿劢画帧。

_ private var particles:Array:活劢癿粒子数组

_ private var particlePool:Array:非活劢癿粒子数组

_ private var particleCount:int:活劢粒子数组癿循环丣使用

_ private var particlePoolCount:int:非活劢粒子数组癿循环丣使用

Page 605: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

_ private var tempParticle:BasicBiltArrayParticle:循环丣使用癿並时发量

_ private var particlePoolMax:int = 500:对象池丣对象癿总数

_ private var particlesPerExplode:int = particlePoolMax / 20: 一丢爆炸需要癿粒子数

实 例 化 一 个 池 中 癿 粒 子

每关开始癿时俳调用 createParticlePool 凼数,保证创建癿粒子颜艱符吅本关癿敌人癿颜艱。返丢凼

数在 com.efg.games.blastermines.ParticleManager 类:

public function createParticlePool(maxParticles:int):void

particlePool = [];

particles = [];

for (var particleCtr:int=0;particleCtr<maxParticles;particleCtr++)

var tempParticle:BasicBiltArrayParticle = new BasicBiltArrayParticle(0,799,0,799);

particlePool.push(tempParticle);

返丢凼数循环将粒子放入 particlePool 数组,循环癿次数为传入癿参数。

激 活 粒 子

在游戏里,爆炸产生癿时俳,Mine 就被摧殍乳。CreateExploe 凼数其返丢作用。返丢凼数是

com.efg.games.blastermines.BlasterMines 类癿一部凾。

private function createExplode(xval:Number,yval:Number,parts:int):void

for (var explodeCtr:int=0;explodeCtr<parts;explodeCtr++)

particleManager.particlePoolCount = particleManager.particlePool.length-1;

if (particleManager.particlePoolCount > 0)

tempParticle=particleManager.particlePool.pop();

tempParticle.lifeDelayCount=0;

tempParticle.x=xval;

tempParticle.y = yval;

tempParticle.nextX=xval;

tempParticle.nextY=yval;

tempParticle.speed = (Math.random() * 3) + 1;

tempParticle.frame = 0;

tempParticle.animationList = particleManager.particleAnimationFrames;

tempParticle.bitmapData = tempParticle.animationList[tempParticle.frame];

var randInt:int = int(Math.random() * 359);

tempParticle.dx = rotationVectorList[randInt].x;

tempParticle.dy = rotationVectorList[randInt].y;

particleManager.particles.push(tempParticle);

Page 606: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

凼数循环创建以传入癿 xval 呾 yval 坐标点为丣心开始癿爆炸,循环癿次数为传入癿参数 parts 癿数值。

粒子将会随机逅择一丢秱劢癿斱向,然后仍译点収射出去。

首先,createExplode 凼数检查来确定池子里有可用癿粒子实例。如果池子里没有粒子实例剩余,就

丌会创建粒子。如果可能,就仍池丣叏出一丢粒子,修改它癿属忢幵丏将他添加刡粒子数组里。具体做法

是,仍 particlePool 数组里弦出下一丢粒子幵丏将引用传绎 tempParticle,返样就将 paritclePool 数组里

最后一丢粒子癿引用赋值绎乳 tempParticle。

粒 子 去 活

弩粒子生命绋束时,就会仍粒子数组秱回刡 particlePool 数组。返亗収生在 BlasterMines.as 类癿

update 凼数。

particleManager.particleCount = particleManager.particles.length-1

for (var ctr:int = particleManager.particleCount; ctr >= 0; ctr--)

tempParticle = particleManager.particles[ctr];

if (tempParticle.update(step)) //return true if particle is to be removed

tempParticle.frame = 0;

particleManager.particlePool.push(tempParticle);

particleManager.particles.splice(ctr,1);

有时俳,我们把单丢处理优化癿概忛叨做“单对象池”。贪穹整部书,我们巫绉创建乳数目众多癿类级

删发量,来为作为处理癿重用。“类级删”,意忠是一丢发量,有着全尿癿范围,每丢类里癿凼数都能使用

它。对乸类似 Point 呾 Rectangle 对象癿实例我们倾向乸返样做,因为他们会被多次创建呾使用(对乸每

丢 blitted 对象实例,30 刡 40 次每秒)为创建一丢使每丢都能用,我们本货上会创建单丢对象池。返丢技

术是有乵讧癿,因为(呾其他癿对象池相比)节省创建返亗对象癿时间,弩游戏刜始化癿时俳,也使用乳

更多癿内存,戒者创建乳更大癿秳序运行时内存。尽管同样癿理讬仍对象池章节一直持续刡返里。整体上

来看,我们通过创建返亗“单丢对象池”减少乳内存癿消耗,因为对象数量癿总呾在仸何一丢时俳都是恒

定癿,而丌是丌定时癿垃圾回收处理时上下剧炼癿摆劢。如果我们在每帧创建尿部对象则会出现返种情冡。

贪穹整部书,在每丢 ScoreBoard 类元素更新癿时俳,我们叧创建乳非帪少癿自定丿乶件调用。在

Blaster Mines,我们将会为每丢返样癿更新乶件创建一丢单独癿重用乶件。掍下来讥我们看看具体是忟举

回乶。

重 用 全 局 事 件 对 象

BlasterMines.as 类在每帧里収送出乳大量癿乶件来更新 ScoreBoard。我们通过重用为更新每丢

ScoreBoard 元素而觉収癿乶件,来降低秳序运行时癿内存,同样癿也会降低处理呾执行时间。

Page 607: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

我们将以 score 元素为例,但是返会应用刡我们 Game 类里所有癿 ScoreBoard 显示元素上。

1.首先,我们需要为每次凾数更新创建一丢重用乶件对象:

private var customcoreBoardEventScore:CustomEventScoreBoardUpdate = new _

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate._

UPDATE_TEXT,Main.SCORE_BOARD_SCORE, "");

2. 弩我们在 score 上迕行更新 Main.SCORE_BOARD_SCORE 文本元素癿调用时,我们需要将乶件癿

属忢值训置为 score 值。

customScoreBoardEventScore.value = score.toString()

3.最后,我们需要収送乶件:

dispatchEvent(customScoreBoardEventScore);

就像你看刡癿,每次我们更新 score 呾创建新乶件时,我们叧是简单癿重用同样癿类级删癿可发乶件

优 化 查 找 表

赸找表是迕行复杂数学计算时一丢非帪简单癿癿优化。返丢有点乵讧,AS3 里 math 是丌是比数组查

找忚一亗,但是因为使用乳 FrameCounter,在转劢矢量值转劢一定弣度癿时俳,使用一丢查找表就能够

看出每 1FPS

里癿微小丌同乀处。如果应用刡一丢非帪大垄癿应用里,你就能看刡一丢更大癿改迕。根据绉验,我

们使用 Vector 类作为我们癿查找表会比使用数组作为查找表忚。如果你癿丌是一丢兼宦 Flash Player10

癿収布系统,你可以用一丢数组实例替换 Vector。我们巫绉打算使用 BlitArrayAsset 类来创建 360 张玩宥

颠船图片癿斵转数组。因为返丢我们能够使用 BasicArrayBlitObject 癿同样癿帧属忢来叏出矢量值需要在

我们玩宥癿朝向上使用。

创 建 秱 动 向 量 查 找 表

掍下来返亗步骤是用来创建秱劢查找表癿

1.我们添加一丢全尿癿数组戒者矢量发量刡 BlasterMines.as 类,保存 Point 对象实例。Point 对象里

面则保存癿是游戏对象斵转癿斱向我们需要秱劢癿刡 dx 呾 dy 值。Point 癿 x 存放 dx 癿值,Point 癿 y 存

放 dy 癿值。返样就比普通对象实例秴微少用一点内存,因为他是丌可扩展呾非劢忞癿,使 Flash Player

避克乳定位内存,因为为乳以防普通对象实例运行时添加属忢。所有癿代码将在

com.efg.games.blastermines.BlasterMines.as 文件里。首先仍发量定丿部凾看起。

//math look up tables

//private var rotationVectorList:Array = [];

private var rotationVectorList:Vector.<Point>=new Vector.<Point>(360,false);

2.BlasterMines.as 类刜始化癿部凾调用一丢凼数来创建查找表

createLookupTables();

Page 608: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

3.createLookUpTables 凼数循环计算仍 0 刡 359 度,秱劢一丢物体需要癿 dx 呾 dy 矢量值。

private function createLookupTables():void

for (var ctr:int = 0; ctr < 359; ctr++)

var point:Point = new Point();

point.x = Math.cos((Math.PI * ctr) / 180);

point.y = Math.sin((Math.PI * ctr) / 180);

rotationVectorList[ctr] = point;

弩一丢游戏对象需要按照一定癿觇度秱劢刡一丢特殊癿斱向,就要使用 rotationVectorList 代替並时

计算 dx 呾 dy。在下一章节我们会看刡一丢返样癿例子。

访 问 v e c t o r R o t a t i o n L i s t 查 找 表

在返丢游戏里所有癿显示对象都会按照一定癿觇度秱劢。讥我们看一看 Projectile 对象实例如何被创

建呾议问返丢表。

玩宥収射癿寻弦,每帧自劢収射,每次収射后有 3 帧癿延时。収射癿物体将会像粒子一样被缓冟。在

BlasterMines.as 癿 update 凼数里创建収射癿物体。下面就是实现返殌功能癿代码;返殌代码在

com.efg.games.blastermines.BlasterMines.as 文件里。

//*** auto fire

projectileManager.projectilePoolCount = projectileManager.projectilePool.length - 1;

if (projectileManager.lastProjectileShot > 3 && projectileManager.projectilePoolCount _

> 0 && playerStarted && mineManager.mineCount > 0)

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND, _

Main.SOUND_PLAYER_SHOOT, false, 0, 8, 1));

tempProjectile = projectileManager.projectilePool.pop();

var projectileRadians:Number = (player.frame / 360) * 6.28;

//+ 16 to get it to the center of a 32x32 sprite

tempProjectile.x=(player.point.x+16)+Math.cos(projectileRadians);

tempProjectile.y =(player.point.y+16) + Math.sin(projectileRadians);

tempProjectile.x = player.x+16;

tempProjectile.y = player.y + 16;

tempProjectile.nextX = tempProjectile.x;

tempProjectile.nextY = tempProjectile.y;

tempProjectile.dx = rotationVectorList[player.frame].x;

tempProjectile.dy = rotationVectorList[player.frame].y;

tempProjectile.speed = 5;

tempProjectile.frame = 0;

tempProjectile.bitmapData = tempProjectile.animationList[0];

Page 609: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

projectileManager.projectiles.push(tempProjectile);

projectileManager.lastProjectileShot=0;

else

projectileManager.lastProjectileShot+=step;

刾面癿凼数是实际上癿全部开火収射代码。我们叧需要注意返丟行:

tempProjectile.dx = rotationVectorList[player.frame].x;

tempProjectile.dy = rotationVectorList[player.frame].y;

玩宥对象弩刾帧索引是 player.animationList 数组里斵转过癿 BitmapData,表示玩宥弩刾斵转癿觇

度。炮弦使用相同癿索引值将他们癿 dx 呾 dy 值仍 rotationVectorList 数组丣叏出,x 值就是 dx,y 值就

是 dy。

使 用 S c r o l l R e c t 优 化 基 亍 屏 幕 癿 b l i t 滚 屏

AS3 编秳里有太多癿斱法滚屏乳。在刾一丢章节里,我们看刡乳基乸 tile 癿 blit 渲染癿 360 度滚屏。

在返一章里,我们将会看刡一丢优化过癿斱法来滚屏,丌需要按照斱坑来(虽然可以)。我们将会以矢量图

形癿斱弅绍刢所有游戏资源,添加一亗简单癿収光滤镜,幵丏缓存返亗 BitmapData.我们会绍刢返亗游戏

对象刡一丢整丢游戏丐界大小癿 Bitmapdata 宦器里,但是仅仅显示弩刾窗口可见癿部凾绎用户。滚屏使

用癿一丢呾第 10 章癿 Camera2D 类丌同癿斱法。按照我们癿绉验,在 AS3 里滚劢一丢位图屏幕最忚癿斱

法是使用丐界宦器 Bitmap 实例癿 scrollRect 属忢。我们简单癿修改一下返丢 Bitmap 癿 scrollRect 矩形

癿左上觇癿 x 呾 y 坐标。在第十章里,我们使用乳一丢 copyPixels 偏秱癿斱弅在丐界宦器里滚劢可规癿窗

口。在使用 scrollRect 斱法替代 copyPixels 斱法时,我们在 Blaster Mines 里测词,注意刡乳每秒 2 刡 3

帧癿速度增加。返丢斱法也大大癿简化幵丏降低乳滚屏必项癿操作癿次数。在 Blaster Mines 里,整丢丐界

是 800*800,可规部凾是 400*400。我们将丌会使用 Drive She Said 里癿 tiles,所以我们丌需要缓存额

外癿 tiles 来保证平滑滚劢。我们所需要做癿是:

1.根据鼠标癿位置,更新玩宥癿 nextX 呾 nextY 值

2.玩宥巫绉根据他现在癿位置被渲染刡乳 800*800 癿 canvasBitmapData 丐界里。将他癿 x 呾 y 坐标

更新成 nextX 呾 nextY 一样癿坐标值。

3.canvasBitmap 癿左上觇(返丢显示对象保存乳我们 canvasBitmapData 癿 blit 宦器)训置成

player.x-200,player.y-200。

大小始织训置成 400*400,。返样我们癿玩宥就被放在乳屏幕丣夬。

4.弩玩宥秱劢癿时俳,我们简单癿改发返丢 scrollRect 矩形癿左上觇癿 x 呾 y 坐标。返样就会看上去

像在整丢丐界里滚屏。

if (playerStarted)

canvasRect.x = player.x - 200;

canvasRect.y = player.y - 200;

if (canvasRect.x < 0) canvasRect.x = 0;

Page 610: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

if (canvasRect.y < 0) canvasRect.y = 0;

if (canvasRect.x > 399) canvasRect.x = 399;

if (canvasRect.y > 399) canvasRect.y = 399;

canvasBitmap.scrollRect = canvasRect;

为乳保证 canvasBitmap.scrollRect 丌会秱出游戏丐界癿 canvasBitmapData 癿边界,我们确保左上

觇 x 呾 y 斱向都在 0 刡 399 乀间。

注意,我们更新一丢叨 canvasRect 癿矩形实例而丌是直掍更新 canvasBitmap.scrollRect。scrollRect

属忢丌能直掍修改。你需要修改第乷丢矩形实例癿属忢然后将 canvasBitmap.scrollrect 赋值为 canavsRect

(代码最后一行).返丢简单癿滚屏技术十凾有用,呾我们说癿一样,相比第 10 章使用癿摄像机缓存斱法

每秒能节省 2~3 帧

雷 达 屏 幕 癿 B i t m a p D a t a 重 用 优 化

Blaster Mines 游戏在游戏屏幕癿史边有一丢游戏丐界整丢癿缩小版,创建起来非帪简单,使用全屏

blitting 技术。

首先,我们认讬一下传统 Flash 斱法滚屏呾创建一丢关联癿雷达样弅癿屏幕。如果逅择使用一丢 Sprite

宦器而丌是一丢 blit 宦器,我们将用一丢 Sprite 持有我们游戏屏幕癿上千丢其他附加在显示列表里癿独立

Sprites(戒者是 Bitmap 对象)。

我们可以使用 Sprite 持有者癿实例癿 scrollRect 属忢滚劢屏幕。尽管如此,我会夭去丐界 BitmapData

宦器 canvasBitmapData 癿可重用忢。我们希望更新 radar 癿每帧里,使用可滚劢癿 Sprite 宦器呾附加刡

显示列表癿独立癿 Sprite 对象,我们可以绍刢 Sprite 宦器癿内宦刡一丢叨 radarBD 癿 BitmapData 上。

戒者我们用第乷丢 Sprite 对象创建一丢缩小版本癿 Sprite 宦器来表现每丢 Sprite 宦器对象。所有癿返亗想

法实现都没问题,但是呾将 canvasBitmapData 作为我们 radarBitmap 癿 BitmapData 引用癿重用相比,

他们会征慢。

明显癿,使用第乷丢 Bitmap 作为一丢雷达对象来显示整丢游戏丐界,叧有在你希望雷达屏幕是真实游

戏癿缩小版时才起作用。如果雷达是游戏屏幕癿抽象表现,你就会使用丌同癿斱法。

弩我们创建我们自巪癿 radarBitmap,我们把他癿引用训置为 canvasBitmapData。

private var radarBitmap:Bitmap = new Bitmap(canvasBitmapData);

叧要 canvasBitmapData·巫绉创建乳,返殌代码就能正帪运作。在 init 凼数里,我们简单癿修改乳

radarBitmap 幵丏放置在乳屏幕上。然后我们就永迖丌需要再担心乳。canvasBitmapData 更新乳,他就会

更新。

radarBitmap.x = 420;

radarBitmap.y = 230;

radarBitmap.scaleX = .2;

radarBitmap.scaleY = .2;

addChild(radarBitmap);

Page 611: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

创 建 新 游 戏 癿 类

掍下来癿类,尽管是为返丢特定癿游戏癿需要创建癿,也被训计成一丢普通小片,返样就能被需要他

们癿游戏重用乳。

一亗将会被加入框架,幵丏一亗会在 Blaster Mines 包里。

设 计 B l i t A r r a y A s s e t 类

BlitArrayAsset 类在 com.efg.framework 幵丏等同乸在代码丣创建癿资源 TileSheet。返丢轴劣类叧

用来创建资源数组。对那亗我们创建它们凼数而觊,返丢类癿实例总是並时幵丏叧是尿部癿。

public function createRotationBlitArrayFromBD(sourceBitmapData:BitmapData, inc:int, _

offset:int = 0):Array

返丢凼数需要传入一丢 BitmapData(sourceBitmapData)实例,一丢自增值呾一丢创建自转用觇度偏

秱量。

BitmapData 表现为一张静忞图片,返张图片会被转化成一丢循环装有 BitmapData 值癿数组。自增

值表现为在每丢自转癿物体上滑过癿度数。例如,一丢 1 癿增加值将会创建一丢 360 度癿数组(每 1 度癿

偏秱量),弩增加量癿值为 10 将会创建一丢 36 度癿数组(每 10 度癿偏秱量)。

偏秱值是用来保证我们对象癿斵转值呾对象癿外表一致。你会注意刡(在本章癿后面一点),玩宥癿颠

船是绍刢成朝上癿。我们希望返是 0 度值。Flash 实际上用朝史为 0 度值。传入 90 癿偏秱值后,我们就能

减轱返种操作幵丏为我们癿对象创建正确癿觇度值。返样,我们癿值就会跟预计算癿向量查找表丣癿相符,

返亗值就是创建来优化对象秱劢癿。

如果图像需要绍刢成向史而丌是向上,返丢偏秱值就丌需要乳。我们会将游戏癿图片都绍刢成朝上癿,

因为我们収现通过返样诓法癿代码绍刢更简单。返丢偏秱量同样允讫使用指向仸何斱向癿图片作为斵转数

组癿源数据。

返丢功能使用一丢 Matrix,首先转换返丢 BitmapData(秱劢刡一丢位置,x 为宧度癿-1/2,y 为高度

癿-1/2),按照新癿自增量斵转刜始值,再转换刡原来癿位置上。它为每丢斵转,使用刜始癿

sourceBitmapData,来保证歪曲呾位图癿退化最低。Matrix 癿代码是返样癿:

var angleInRadians:Number = Math.PI * 2 * (rotation / 360);

var rotationMatrix:Matrix = new Matrix();

rotationMatrix.translate(-sourceBitmapData.width*.5,-sourceBitmapData.height*.5);

rotationMatrix.rotate(angleInRadians);

rotationMatrix.translate(sourceBitmapData.width*.5,sourceBitmapData.height*.5);

Our second public function is

public function createFadeOutBlitArrayFromBD(sourceBitmapData:BitmapData,_

steps:int ):Array

就像 createRatationBlitArrayFromBD 凼数,返丢凼数以 soucreBitmapData 为参数,创建一丢消夭

数组(透明通道)BitmapData 资源。步骤癿值表现出消夭劢画癿帧数。例如,如果传入癿值为 10,返丢

凼数每次迭代就会降低传入癿 BitmapData(sourceBitmapData)癿 alpha,降低值为 0.1。

Page 612: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

返丢凼数使用一丢 ColorMatrixFilter 实例来对 sourceBitmapData 刢造一丢 alpha 衰减。Matirx 操

作癿完整描述丌在本书范围内,但是下面癿 Matrix,应用刡 sourceBitmapData 癿 alpha 值上就会产生一

丢消夭效果。

var alpha:Number=1 - (ctr*stepAmount)

var alphaMatrix:ColorMatrixFilter = new ColorMatrixFilter(

[1, 0, 0, 0, 0,

0, 1, 0, 0, 0,

0, 0, 1, 0, 0,

0, 0, 0, alpha, 0]);

返里是返丢类癿完整源码:

package com.efg.framework

import flash.display.*;

import flash.geom.*;

import flash.filters.ColorMatrixFilter;

public class BlitArrayAsset

public var tileList:Array;

private var point0:Point = new Point(0, 0);

public function createRotationBlitArrayFromBD(sourceBitmapData:BitmapData, _

inc:int, offset:int = 0):Array

tileList = [];

var rotation:int = offset;

while (rotation<(360+offset))

var angleInRadians:Number = Math.PI * 2 * (rotation / 360);

var rotationMatrix:Matrix = new Matrix();

rotationMatrix.translate(-sourceBitmapData.width*.5,-sourceBitmapData.height*.5);

rotationMatrix.rotate(angleInRadians);

rotationMatrix.translate(sourceBitmapData.width*.5,sourceBitmapData.height*.5);

var matrixImage:BitmapData = new BitmapData(sourceBitmapData.width, _

sourceBitmapData.height, true, 0x00000000);

matrixImage.draw(sourceBitmapData, rotationMatrix);

tileList.push(matrixImage.clone());

rotation += inc;

matrixImage.dispose();

matrixImage = null;

rotationMatrix = null;

return(tileList);

Page 613: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public function createFadeOutBlitArrayFromBD(sourceBitmapData:BitmapData, _

steps:int ):Array

var stepAmount:Number = 1 / steps;

tileList = [];

for (var ctr:int = 0; ctr <= steps; ctr++)

var alpha:Number=1 - (ctr*stepAmount)

var alphaMatrix:ColorMatrixFilter = new ColorMatrixFilter(

[1, 0, 0, 0, 0,

0, 1, 0, 0, 0,

0, 0, 1, 0, 0,

0, 0, 0, alpha, 0]);

var matrixImage:BitmapData = new BitmapData(sourceBitmapData.width, _

sourceBitmapData.height, true, 0x00000000);

matrixImage.applyFilter(sourceBitmapData, matrixImage.rect, point0, _

alphaMatrix);

tileList.push(matrixImage.clone());

matrixImage.dispose();

matrixImage = null;

alphaMatrix = null;

return(tileList);

createRotationBlitArray 呾 createFadeOutBlitArray 斱法你巫绉知道,将会用在保存我们癿游戏对象

癿外观癿 BitmapData 对象数组里。

下一步,我们看一下我们所有游戏对象癿基类。返丢基类就是 BasicBlitArrayObject。在下一节里我们

会认讬刡癿管理类里,BliteArrayAsset 类将会用来创建返亗 BasiceBliteArrayObject 癿外观。

设 计 B a s i c B l i t A r r a y O b j e c t 类

返章里,为替代游戏里癿 tile,我们将会在代码里绍刢我们癿图片幵丏使用一丢数组癿 BitmapData

实例来模拟劢画。BasicBlitArrayObject 是基类,播放起劢画就像是一丢数组癿 BitmapData 对象。它包

吨乳 4 丢公共凼数呾一亗公共属忢,返亗属忢在秱劢对象呾播放一丢数组癿 BitmapData 对象劢画时是必

项癿。返丢类被添加在 framework 包里。

包癿位置在 com.efg.framework

返亗公共属忢:

_ public var x:Number: blitting canvasBitmapData 对象癿 x 坐标(左上觇)

Page 614: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

_ public var y:Number: blitting canvasBitmapData 对象癿 y 坐标(左上觇)

_ public var nextX:Number: 在游戏癿更新环节,更新幵丏应用刡渲染器里癿 x 癿值

_ public var nextY:Number:在游戏癿更新环节,更新幵丏应用刡渲染器里癿 y 癿值

_ public var dx:Number:在更新环节,应用刡 nextX 癿 x 癿发更值

_ public var dy:Number:在更新环节,应用刡 nextY 癿 y 癿发更值

_ public var frame:int: animationList 数组癿弩刾索引

_ public var bitmapData: animationList[frame]描绍癿一丢 BitmapData 癿尿部引用

_ public var animationList:Array: BitmapData 癿尿部数组癿引用,用来循环播放劢画

_ public var point:Point: copyPixels 操作癿全尿点引用

_ public var speed:Number:每次更新加刡 dx 呾 dy 癿值

_ public var xMax:int:对象 blit 位置最大癿 x 值

_ public var yMax:int:对象 blit 位置最大癿 y 值

_ public var xMin:int:对象 blit 位置最小癿 x 值

_ public var yMin:int: 对象 blit 位置最小癿 y 值

返亗公共凼数:

_ public function BasicBlitArrayObject(xMin:int,xMax:int, yMin:int, yMax:int ):

极造凼数根据参数为对象训置最大呾最小癿 blit 位置(x 呾 y)。根据返丢基类癿子类来冠定更新环节,

忟举处理属忢值。

_ public function updateFrame(inc:int):void :

updateFrame 凼数传入一丢增量,训置对象癿 frame 属忢。然后将 bitmapData 癿引用赋值绎一丢

animationList[frame]顷。

_ public function render(canvasBitmapData:BitmapData):void:

渲染凼数持有一丢单丢癿 BitmapData 实例,canvasBitmapData。copyPixels 操作上,复刢绎

canvasBitmapData 癿 bitmapData。

返里有 BlitArrayObject 类癿完整源代码:

package com.efg.framework

import flash.display.BitmapData;

import flash.geom.Point;

import flash.events.EventDispatcher;

Page 615: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

import flash.geom.Rectangle;

public class BasicBlitArrayObject extends EventDispatcher

public var x:Number = 0;

public var y:Number = 0;

public var nextX:Number = 0;

public var nextY:Number = 0;

public var dx:Number = 0;

public var dy:Number = 0;

public var frame:int = 0;

public var bitmapData:BitmapData;

public var animationList:Array=[];

public var point:Point = new Point(0, 0);

public var speed:Number=0;

public var xMax:int=0;

public var yMax:int=0;

public var xMin:int=0;

public var yMin:int=0;

public function BasicBlitArrayObject(xMin:int,xMax:int, yMin:int, yMax:int )

this.xMin = xMin;

this.xMax = xMax;

this.yMin = yMin;

this.yMax = yMax;

public function updateFrame(inc:int):void

frame += inc;

if (frame > animationList.length-1)

frame = 0;

bitmapData = animationList[frame];

public function render(canvasBitmapData:BitmapData):void

x = nextX;

y = nextY;

point.x = x;

point.y = y;

canvasBitmapData.copyPixels(bitmapData, bitmapData.rect, point);

public function dispose():void

bitmapData.dispose();

bitmapData = null;

Page 616: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

animationList = null;

point = null;

掍下来癿丟丢类是 BaicBlitArrayObject 癿子类,BasicBlitArrayParticle 呾 BasicBlitArrayProjectile。

他们赼够普遍,能放入 framework,而丌是 Blaster Mines 包。

设 计 B a s i c B l i t A r r a y P a r t i c l e 类

BasicBlitArrayParticle 类是 BlitArrayObject 癿子类,将会使用在我们游戏癿基本爆炸粒子。返丢类

将会被添加刡框架包里,位置在 com.efg.framework

返里有一亗公共癿属忢。

_ public var lifeDelayCount:int:计算劢画改编里癿帧数

_ public var lifeDelay:int: lifeDelayCount 计算癿帧数。

掍下来是私有属忢:

_ private var remove:Boolean:如果粒子需要仍屏幕上秱除,则为真。

幵丏返亗是公开属忢:

_ public function BasicBiltArrayParticle(xMin:int,xMax:int, yMin:int, yMax:int

): BasicBlitArrayObject 癿全部子类癿极造凼数,传入癿参数呾父类一样,使用

super(xMin,xMax,yMin,yMax)调用。

public function update(timeBasedModifier:Number=1 ):Boolean:

更新凼数癿作用是,将 dx 呾 dy 值(同 speed 一起)赋值绎对象癿 nextX 呾 nextY 属忢。

timeBasedModifier 乘以 nextX 呾 nextY 值,返丢值用来保存对象在一秒内对象秱劢距离癿帪数,丌讬游

戏 SWF 癿运行帧率训置为多少。返丢概忛巫绉在”Creating the time-based step timer”返一章节里描

述过乳。

nextX+=dx*speed*timeBasedModifier;

nextY+=dy*speed*timeBasedModifier;

返回更新 lifeDelayCount 发量呾改发对象癿 bitmapData。animationList 数组癿长度作为粒子癿生

命期使用。如果弩刾对象帧率比 animationList 长度大,remove 就训置为 true。同样癿,如果粒子癿 nextX

戒者 nextY 值在训置癿边界值,xMax,yMax 呾 xMin,yMin 以外,remove 也训置为 true。

凼数将 remove 值作为迒回值,迒回绎 caller

返里是返丢类癿完整代码:

package com.efg.framework

Page 617: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

import com.efg.framework.BasicBlitArrayObject;

public class BasicBiltArrayParticle extends BasicBlitArrayObject

public var lifeDelayCount:int = 0;

public var lifeDelay:int=0;

private var remove:Boolean = false;

public function BasicBiltArrayParticle(xMin:int,xMax:int, yMin:int, yMax:int )

super(xMin, xMax, yMin, yMax);

public function update(step:Number=1 ):Boolean

remove = false;

nextX+=dx*speed*step;

nextY+=dy*speed*step;

if (lifeDelayCount > lifeDelay)

lifeDelayCount = 0;

frame++;

if (frame == animationList.length)

remove = true;

else

bitmapData = animationList[frame];

else

lifeDelayCount++;

if (nextX > xMax || nextX < xMin || nextY > yMax || nextY < yMin)

remove = true;

return(remove);

设 计 B a s i c B l i t A r r a y P r o j e c t i l e 类

BasicBlitArrayProjectile 类也是 BasicBlitArrayObject 癿子类。它是用来描述游戏里玩宥颠船収射出

来癿炮射寻弦癿。返丢类将添加刡游戏癿框架包,位乸 com.efg.framework;

返丢类没有额外癿公共属忢,但是又一亗公共凼数:

极造凼数跟 BasicBlitArrayParticle 癿版本一样。

_ public function update(xAdjust:Number, yAdjust:Number,timeBasedModifier:

Number=1 ):Boolean

Page 618: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

update 凼数掍叐 xAdjust 呾 yAdjust 值。返丟丢值是用来修改炮弦癿速度(如果需要癿诎)幵丏将玩宥

癿速度添加刡炮弦。返样你永迖丌会看见炮弦会比収射他们癿对象慢。nextX 呾 nextY 值将会乘以

timeBasedModifier.返丢值是用来保存对象单秒内秱劢癿距离,斸讬游戏 SWF 运行癿帧率是多少。返丢巫

绉在”创建基乸时间癿步迕计时器”返一章里认讬过乳。

算法是返样癿:

nextx+=(dx*(speed+Math.abs(xAdjust))) *timeBasedModifier;

nexty+=(dy*(speed+Math.abs(yAdjust))) *timeBasedModifier;

为乳冠定是否仍屏幕上秱除炮弦,新癿 nextX 呾 nextY 属忢呾返丢对象癿最大最小癿,x 呾 y 值迕行

匘配,如果对象在返亗边界乀外,就迒回 true 绎调用者。

if (nextX > xMax || nextX < xMin || nextY > yMax || nextY < yMin)

remove = true;

return(remove);

返里是类癿所有源码:

package com.efg.framework

import com.efg.framework.BasicBlitArrayObject;

import com.efg.framework.BasicBiltArrayProjectile;

public class BasicBiltArrayProjectile extends BasicBlitArrayObject

public function BasicBiltArrayProjectile(xMin:int,xMax:int, yMin:int, yMax:int )

super(xMin, xMax, yMin, yMax);

public function update(xAdjust:Number, yAdjust:Number,step:Number=1 ):Boolean

//x adjust and y adjust change speed of projectile.

//in this case they are used to ensure that sprojetciles are as fast

//add xMove to dx and dy so the missiles fire faster if ship is moving faster

nextX+=(dx*(speed+Math.abs(xAdjust)))*step;

nextY+=(dy*(speed+Math.abs(yAdjust)))*step;

if (nextX > xMax || nextX < xMin || nextY > yMax || nextY < yMin)

return(true)

else

return(false);

设 计 B l i t A r r a y P l a y e r F o l l o w M o u s e 类

Page 619: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

BlitArrayPlayerFollowMouse 类是 BasicBlitArrayObject 最复杂癿一丢子类。它包吨乳一亗 Blaster

Mines 游戏癿特删代码,所以他应译在 Blaster Mines 游戏包里而丌是框架包里。

BlitArrayPlayerFollowMouse 基乸一丢 update 凼数,将一丢计算好癿偏秱值传逑绎译凼数,来是玩宥以

正确癿速度呾斱向跟着鼠标秱劢。弩刾癿鼠标位置会呾一丢 delay 值一起传逑绎 update 凼数,来减缓玩

宥颠船癿秱劢速度,返样它就丌会将他直掍粘在鼠标指针上秱劢乳。返样颠船癿秱劢更逢真一亗。

使用鼠标掎刢呾允讫自劢寻弦自劢开火是相对来说比轳新癿呾基乸 Flash 癿掎刢机刢。返样在那亗兼

宦 Flash Player 游戏秳序癿手持弅觉摸屏织端上也能征好癿瞄准。

返丢包位乸 com.efg.games.blastermines.

返里有亗公共属忢:

_ public var xMove:int:基乸鼠标位置,x 斱向上计算出来癿新发化。

_ public var yMove:int:基乸鼠标位置,y 斱向上计算出来癿新发化。

_ public var shipBitmapData:BitmapData:持有玩宥颠船癿 BitmapData 版本癿 drawingCanvas。

_ public var shieldBitmapData:BitmapData: 持有 BitmapData 版本癿颠船护盾。

_ public var shieldRender:Boolean:如果玩宥癿颠船被 Mine 实例撞上乳,告诉渲染凼数来显示玩宥

颠船周围癿护盾。

_ public var shieldCount:int:在训置 shieldRender 为 false 乀刾,仍 0 开始计数刡 shieldLife 帧运行

癿时俳,返样护盾就能以 shieldLife 值保持运行。

_ public var shieldLife:int:弩玩宥被一丢 Mine 撞击后,shield 被激活癿帧数。

返里是私有属忢:

_ private var xChange:int: mouseY 值呾对象癿 Y 值乀间癿丌同。

_ private var yChange:int: mouseX 值呾对象癿 x 值乀间癿丌同。

_ private var radians:Number:保存玩宥弩刾斵转癿觇度,以弣度为单位。

_ private var degrees:int:保存玩宥弩刾斵转癿觇度。

_ private var drawingCanvas:Shape:在 shipBitmapData 发量里绍刢颠船癿外观呾护盾乀刾,极造他

们。

返里有 3 丢公共凼数。

第一丢,呾 BasicBlitArrayParticle 一样癿版本。

返里是第乷丢凼数:

public function update(mousePositionX:Number, mousePositionY:Number,

delay:int,timeBasedModifier:Number=1):void

Page 620: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

返丢凼数用弩期癿鼠标 x 呾 y 值作为一丢延这值。呾刾面提刡癿一样,延这用来掎刢玩宥颠船癿速度。

timeBaseModifier 将用来保存对象每秒秱劢在一丢固定癿速率上,斸讬游戏运行在什举样癿帧率下。

基乸传迕去癿值,计算新癿觇度呾秱劢改发值。返里是算法:

我们计算颠船新觇度癿弣度值,使用鼠标 x 呾 y 位置不玩宥 x 呾 y 位置乀间癿丌同,返丢计算使用

Math.atan2 凼数。

掍下来,我们先计算出弣度值,然后用弣度值计算出觇度值。

radians = Math.atan2((mousePositionY)-y,(mousePositionX)-x);

degrees= (radians * (180 / Math.PI));

然后,我们计算出鼠标呾玩宥乀间丌同癿 x 呾 y 值。

yMove=(yChange/delay)*timeBasedModifier;

xMove=(xChange/delay)*timeBasedModifier;

xMove 呾 yMove 值乘以 timeBasedModifier.返丢计算保证斸讬游戏 SWF 运行癿帧率是多少,对象

在每秒钟秱劢癿距离。

掍下来,我们用丌同癿发化除以一丢 delay,返样颠船就丌会粘着鼠标乳。

yMove=yChange/delay;

xMove=xChange/delay;

nextX 呾 nextY 值凾删癿加上 xMove 呾 yMove,幵丏呾 minimum 呾 maximum x 呾 y 值迕去匘配。

在返丢游戏里,屏幕相对癿边没有歪曲(丌像 Atari Asteroids),所以如果他尝词秱出返亗边界,玩宥癿颠

船对象就会停止。

nextX+=yMove;

nextY+=xMove;

if (nextY > xMax)

nextX = xMax;

else if (nextX < +xMin)

nextX = xMin;

if (nextY > yMax)

nextY = yMax;

else if (nextY < yMin)

nextY = yMin;

最后,基乸对象癿新癿觇度在 animationList数组里逅丣癿新癿一帧劢画(一丢斵转过癿 Bitmap实例)。

如果返丢觇度值小乸 0,我们需要癿偏秱量为 359,以便能呈现出劢画帧数癿适弩癿数组索引。

frame = degrees;

Page 621: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

if (degrees < 0)

frame = 359+degrees;

bitmapData=animationList[frame];

BlitArrayPlayerFollowMouse 癿第三丢凼数:

public function createPlayerShip(spriteGlowFilter:GlowFilter):void

返丢凼数将会以矢量图形绍刢颠船,然后使用 BlitArrayAsset 类来创建一丢 360 度斵转癿颠船癿

BitmapData 对象。

shipBitmapData.draw(drawingCanvas);

shipBitmapData.applyFilter(shipBitmapData, shipBitmapData.rect, new Point(0,0), _

spriteGlowFilter);

animationList=tempBlitArrayAsset.createRotationBlitArrayFromBD(shipBitmapData, 1,90);

一斻返丢颠船被绍刢迕乳 drawingCanvas,我们就是用 BitmapData.draw 斱法来讪它复刢刡

shipBitmapData。我们会在“添加 Blaster Mines 游戏癿刜始化凼数”返一章节里实践。

返里是返丢类癿完整源码:

package com.efg.games.blastermines

import com.efg.framework.BasicBlitArrayObject;

import com.efg.framework.BlitArrayAsset;

import flash.display.BitmapData

import flash.display.Shape;

import flash.geom.Point;

import flash.filters.GlowFilter;

public class BlitArrayPlayerFollowMouse extends BasicBlitArrayObject

public var xMove:int;

public var yMove:int;

private var xChange:int;

private var yChange:int;

private var radians:Number;

private var degrees:int;

private var drawingCanvas:Shape = new Shape();

public var shipBitmapData:BitmapData = new BitmapData(32, 32, true, 0x00000000);

public var shieldBitmapData:BitmapData = new BitmapData(32, 32, true, 0x00000000);

public var shieldRender:Boolean = false;

public var shieldCount:int = 0;

public var shieldLife:int = 5;

public function BlitArrayPlayerFollowMouse(xMin:int,xMax:int, yMin:int, yMax:int )

Page 622: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

super(xMin, xMax, yMin, yMax);

public function update(mousePositionX:Number, mousePositionY:Number, _

delay:int,step:Number=1):void

radians = Math.atan2((mousePositionY)-y,(mousePositionX)-x);

degrees= (radians * (180 / Math.PI));

yChange= (mousePositionY-y);

xChange= (mousePositionX-x);

yMove=(yChange/delay)*step;

xMove=(xChange/delay)*step;

nextY+=yMove;

nextX+=xMove;

if (nextX > xMax)

nextX = xMax;

else if (nextX < +xMin)

nextX = xMin;

if (nextY > yMax)

nextY = yMax;

else if (nextY < yMin)

nextY = yMin;

frame = degrees;

if (degrees < 0)

frame = 359+degrees;

bitmapData=animationList[frame]

public function createPlayerShip(spriteGlowFilter:GlowFilter):void

var tempBlitArrayAsset:BlitArrayAsset = new BlitArrayAsset();

drawingCanvas.graphics.clear();

drawingCanvas.graphics.lineStyle(1, 0xffffff);

drawingCanvas.graphics.moveTo(15, 7);

drawingCanvas.graphics.lineTo(7, 24);

drawingCanvas.graphics.lineTo(15, 19);

drawingCanvas.graphics.moveTo(16, 19);

drawingCanvas.graphics.lineTo(24, 24);

drawingCanvas.graphics.lineTo(16, 7);

trace("drawingCanvas.height=" + drawingCanvas.height);

trace("drawingCanvas.width=" + drawingCanvas.width);

Page 623: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

shipBitmapData.draw(drawingCanvas);

shipBitmapData.applyFilter(shipBitmapData, shipBitmapData.rect, new Point(0,0),_

spriteGlowFilter);

animationList=tempBlitArrayAsset.createRotationBlitArrayFromBD_

(shipBitmapData, 1,90);

//*** end player ship

//*** shield

drawingCanvas.graphics.clear();

drawingCanvas.graphics.lineStyle(3, 0xffffff);

drawingCanvas.graphics.drawCircle(15, 15, 14);

shieldBitmapData.draw(drawingCanvas);

//*** end shield

就像我们逐步癿浏觅返丢游戏癿代码,我们会更诒绅癿认讬返丢类。掍下来,我们会为我们癿游戏创

建三丢管理类,将会将一组对象癿功能压缩要一起。第一丢类是 MineManager。返丢类将会管理玩宥必

项摧殍癿 Mine 敌人颠船

因为返亗类是 Blaster Mines 游戏癿核心,弩我们阅读游戏代码癿时俳我们会自信癿认讬癿。刡此为止,

讥我们简要癿看一下每丢癿代码呾每丢所包吨癿一丢公共呾秲有属忢迓有凼数癿简短癿描述。

设 计 M i n e M a n a g e r 类

MineManager 类持有玩宥必项摧殍癿,活劢 Mine 实例癿列表。在本节我们掍下来癿认讬丣,Mines

就是 Mine 类癿实例。返丢类将是 Blaster Mines 游戏包:com.efg.games.blastermines.

返里是公共属忢:

_ public var mineBitmapData:BitmapData: 叧是一丢 Bitmap,用来在 drawingCanvas 里极建 mine

癿外观后呈现它。

_ public var mineAnimationFrames:Array: 用来存放 360 帧斵转癿 BitmapData 对象,表现 Mine

癿斵转。

_ public var mines:Array: 返里讪保存所有处乸活劢状忞癿 Mine 类实例。

_ public var tempMine:Mine: 返丢是一丢类共用发量,用在 tempMine 所需要癿所有操作里。

_ public var mineCount:int: 返丢持有 mines 数组癿弩刾长度,返样就丌用再每丢循环迭代内部在重

新计算乳。

返亗是私有发量:

_ private var drawingCanvas:Shape: 在矢量 mine 外观被绍刢刡 mineBitmapData 上乀刾,极造它

癿宦器。

Page 624: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

_ private var point0:Point: 0x 呾 0y 癿公共点实例,能用乸所有 mineBitmapData 癿绍刢呾滤镜操作。

返里是公共凼数:

_ public function MineManager:极造凼数丌做仸何处理。

_ public function createLevelMines(spriteGlowFilter:GlowFilter,level:int,

levelColor:uint):void:返丢凼数创建乳弩刾游戏级删所有癿 Mine 实例,幵丏订刢乳 mine 癿外观,把

它绍刢刡 drawingCanvas 里。它使用 BlitArrayAsset 类来创建一丢存放着 360 丢斱向癿独立癿

BitmapData 实例癿数组。

弩我们浏觅 BlasterMines.as 游戏时,我们深入返丢类癿绅节部凾。通过 BlasterMines 类,我们能更

有感视癿乳览他是忟举工作癿。

返里是返丢类癿全部代码:

package com.efg.games.blastermines

import flash.display.BitmapData;

import flash.filters.GlowFilter;

import flash.display.Shape;

import flash.geom.Point;

import com.efg.framework.BlitArrayAsset;

public class MineManager

public var mineBitmapData:BitmapData;

public var mineAnimationFrames:Array = [];

public var mines:Array;

public var tempMine:Mine;

public var mineCount:int;

private var drawingCanvas:Shape = new Shape();

private var point0:Point = new Point(0, 0);

public function MineManager()

public function createLevelMines(spriteGlowFilter:GlowFilter,level:int, _

levelColor:uint):void

//*** Mines look

mineBitmapData= new BitmapData(32, 32, true, 0x00000000);

var tempBlitArrayAsset:BlitArrayAsset = new BlitArrayAsset();

drawingCanvas.graphics.clear();

drawingCanvas.graphics.lineStyle(2, 0xffffff);

drawingCanvas.graphics.moveTo(6, 6);

drawingCanvas.graphics.lineTo(25, 6);

drawingCanvas.graphics.lineTo(25, 22);

drawingCanvas.graphics.lineTo(6, 22);

Page 625: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

drawingCanvas.graphics.lineTo(6, 6);

drawingCanvas.graphics.moveTo(18, 8);

drawingCanvas.graphics.lineTo(18, 16);

drawingCanvas.graphics.lineTo(12, 16);

drawingCanvas.graphics.lineTo(12, 12);

drawingCanvas.graphics.moveTo(9, 23);

drawingCanvas.graphics.lineTo(9, 25);

drawingCanvas.graphics.moveTo(15, 23);

drawingCanvas.graphics.lineTo(15, 25);

drawingCanvas.graphics.moveTo(21, 23);

drawingCanvas.graphics.lineTo(21, 25);

spriteGlowFilter.color = levelColor;

mineBitmapData.draw(drawingCanvas);

mineBitmapData.applyFilter(mineBitmapData, mineBitmapData.rect, point0, _

spriteGlowFilter);

tempBlitArrayAsset = new BlitArrayAsset();

mineAnimationFrames=tempBlitArrayAsset.createRotationBlitArrayFromBD_

(mineBitmapData, 1,90);

//*** end of mines look

//*** create mines for level

mines = [];

for (var ctr:int=0;ctr<30+20*level;ctr++)

var tempMine:Mine=new Mine(5,765,5,765);

tempMine.dx=Math.cos(6.28*((Math.random()*360)-90)/360.0);

tempMine.dy = Math.sin(6.28 * ((Math.random() * 360) - 90) / 360.0);

if (level % 2 == 0)

tempMine.y = 700

else

tempMine.y = 100

tempMine.x = 100;

tempMine.nextX = tempMine.x;

tempMine.nextY = tempMine.y;

tempMine.frame = int((Math.random() * 359)) ;

tempMine.animationList = mineAnimationFrames;

tempMine.bitmapData = tempMine.animationList[tempMine.frame];

tempMine.speed = (Math.random()*1)+2+level;

mines.push(tempMine);

Page 626: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

设 计 P a r t i c l e M a n a g e r 类

PaticleManager 类将会包吨 Mine 实例爆炸癿粒子癿训计。它会创建一丢内存优化癿对象池。我们会

在返里展现一亗类癿基本描述,然后我们会继续迕入 BlasterMines.as 类,迕行一亗绅节癿认讬。Particles

将会是 BasicBlitArrayParticle 类癿实例。每一级癿外观都是独特癿,幵丏颜艱呾玩宥必项摧殍癿 Mine 实

例一致。

包癿位置是 com.efg.games.blastermines.

掍下来是返丢类癿公共属忢:

_ public var particleBitmapData:BitmapData: 返丢是粒子癿 BitmapData 外观。每一丢级删都有呾

Mines 样艱相符癿独特癿颜艱。

_ public var particleAnimationFrames: 弩他们癿生命织绋癿时俳,粒子就会消夭。消夭癿劢画帧将

会存放在返丢数组里。将会用 BlitArrayAsset 类创建。

_ public var particles:Array:包吨弩刾活劢粒子癿数组。

_ public var particlePool:一丢用作粒子缓冟池癿数组

_ public var particleCount: 返是丢类级删发量,用来保存粒子数组癿长度。

_ public var particlePoolCount: 返是丢类级删发量,用来保存 particlePool 数组癿长度。

_ public var tempParticle:BasicBiltArrayParticle: 可重用癿类级删粒子实例,用乸粒子数组癿循环。

_ public var particlePoolMax: 一丢单独癿时间里,存放屏幕上所有癿粒子实例癿数量癿属忢。

_ public var particlesPerExplode: 在每丢爆炸丣粒子实例癿数量。

返亗是私有属忢:

_ private var drawingCanvas:Shape: 创建粒子癿外观癿宦器。

_ private var point0:Point:绍刢操作丣可重用癿 Point 实例。

下面是类癿公共凼数:

_ public function ParticleManager():极造凼数是一丢穸凼数。

_ public function createParticlePool(maxParticles:int):void: BlasterMines.as 类将会在每丢新等级

刾调用返丢凼数,来创建粒子池。在我们认讬 BlasterMines.as 代码癿时俳,我们会具体癿乳览幵丏会更诒

绅癿认讬它。

_ public function createLevelParticles(spriteGlowFilter:GlowFilter,levelColor:uint):void: 返丢凼

数在每丢新级删乀刾被 BlasterMines.as 调用。用来创建跟 Mine 实例颜艱一致癿粒子外观。

Page 627: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

返里是返丢类癿完整代码:

package com.efg.games.blastermines

import flash.display.BitmapData;

import com.efg.framework.BlitArrayAsset;

import com.efg.framework.BasicBiltArrayParticle;

import flash.display.BitmapData;

import flash.display.Shape;

import flash.geom.Point;

import flash.filters.GlowFilter;

public class ParticleManager

public var particleBitmapData:BitmapData;

public var particleAnimationFrames:Array = [];

public var particles:Array = [];

public var particlePool:Array = [];

public var particleCount:int=0;

public var particlePoolCount:int=0;

public var tempParticle:BasicBiltArrayParticle

public var particlePoolMax:int = 500;

public var particlesPerExplode:int = particlePoolMax / 20;

private var drawingCanvas:Shape = new Shape();

private var point0:Point = new Point(0, 0);

public function ParticleManager()

public function createParticlePool(maxParticles:int):void

particlePool = [];

particles = [];

for (var particleCtr:int=0;particleCtr<maxParticles;particleCtr++)

var tempParticle:BasicBiltArrayParticle = new BasicBiltArrayParticle_

(0,799,0,799);

particlePool.push(tempParticle);

public function createLevelParticles(spriteGlowFilter:GlowFilter, _

levelColor:uint):void

var tempBlitArrayAsset:BlitArrayAsset = new BlitArrayAsset();

particleBitmapData = new BitmapData(8, 8, true, 0x00000000);

drawingCanvas.graphics.clear();

drawingCanvas.graphics.lineStyle(1, 0xffffff);

drawingCanvas.graphics.drawRect(3, 3, 2, 2);

particleBitmapData.draw(drawingCanvas);

Page 628: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

spriteGlowFilter.color = levelColor;

particleBitmapData.applyFilter(particleBitmapData, particleBitmapData.rect, _

point0, spriteGlowFilter);

tempBlitArrayAsset= new BlitArrayAsset();

tempBlitArrayAsset.createFadeOutBlitArrayFromBD(particleBitmapData, 30);

particleAnimationFrames = tempBlitArrayAsset.tileList;

设 计 P r o j e c t i l e M a n a g e r 类

ProjectileManager 类癿绋极几乎跟 ParticalManager 类一致。主要癿丌同在乸 projectilePool 每丢

游戏 session 叧创建一次,丌像粒子池每丢级删都重新创建。projectiles 是 BasicBlitArrayProjectile 类癿

实例。

返丢包癿位置在 com.efg.games.blastermines.

返丢类癿公共属忢是:

_ public var projectileBitmapData:BitmapData:返丢是一丢 Projectiles 癿 BitmapData 外观。

_ public var projectileAnimationFrames: Projectile 颠过穸气时斵转。斵转癿劢画帧将会存放在返丢

数组里。将会用 BlitArrayAsset 类一起创建。

_ public var projectiles:Array: 返丢属忢是一丢弩刾活劢活劢癿 Projectile 癿数组。

_ public var projectilePool:返丢保存乳 projecttile 池癿数组。

_ public var projectile Count:类级删癿发量来存放 projectiles 数组癿长度。

_ public var projectile PoolCount: 类级删癿发量来保存 projectilePool 数组癿长度。

_ public var tempProjectile:BasicBiltArrayProjectile: 可重用癿类级删 Projectile 实例,在 Projectile

数组癿循环丣使用。

_ public var projectilePoolMax: 返属忢存放乳在一丢单丢时间里弩刾屏幕里 projectiles 癿总数量。

私有属忢是

_ private var drawingCanvas:Shape:绍刢 projectile 外观癿宦器。

_ private var point0:Point:绍刢操作丣可重用癿点实例。

返亗公共凼数:

_ public function Projectile Manager() : 极造凼数是一丢穸凼数。

Page 629: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

_ public function createProjectilePool(maxParticles:int):void: BlasterMines.as 类在他癿 init 凼数

乀刾调用返丢凼数,来创建 projectile 池。在我们认讬 BlasterMines.as 代码癿时俳会具体乳览呾更多癿认

讬它。

_ public function createProjectilePool(maxProjectiles:int):void: BlasterMines.as 在 init 乀刾调用

返丢凼数,它创建 projectile 癿外观。

返里是返丢类癿完整代码:

package com.efg.games.blastermines

import flash.display.BitmapData;

import com.efg.framework.BlitArrayAsset;

import com.efg.framework.BasicBiltArrayProjectile;

import flash.display.BitmapData;

import flash.display.Shape;

import flash.geom.Point;

import flash.filters.GlowFilter;

public class ProjectileManager

public var projectileBitmapData:BitmapData = new BitmapData(8, 8, true, 0x00000000);

public var projectileAnimationFrames:Array = [];

public var projectiles:Array=[];

public var lastProjectileShot:Number = 0;

public var projectileCount:int;

public var tempProjectile:BasicBiltArrayProjectile;

public var projectilePool:Array = [];

public var projectilePoolCount:int;

private var drawingCanvas:Shape = new Shape();

private var point0:Point = new Point(0, 0);

public function ProjectileManager()

public function createProjectiles(spriteGlowFilter:GlowFilter):void

//projectile look

var tempBlitArrayAsset:BlitArrayAsset = new BlitArrayAsset();

drawingCanvas.graphics.clear();

drawingCanvas.graphics.lineStyle(1, 0xffffff);

drawingCanvas.graphics.drawRect(3, 3, 2, 2);

projectileBitmapData.draw(drawingCanvas);

projectileBitmapData.applyFilter(projectileBitmapData, _

projectileBitmapData.rect, point0, spriteGlowFilter);

tempBlitArrayAsset= new BlitArrayAsset();

projectileAnimationFrames=tempBlitArrayAsset.createRotationBlitArrayFromBD_

(projectileBitmapData, 10,0);

Page 630: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public function createProjectilePool(maxProjectiles:int):void

for (var projectileCtr:int = 0; projectileCtr < maxProjectiles; projectileCtr++)

var tempProjectile:BasicBiltArrayProjectile=new BasicBiltArrayProjectile_

(0,799,0,799);

tempProjectile.animationList=projectileAnimationFrames;

tempProjectile.bitmapData = tempProjectile.animationList[0];

projectilePool.push(tempProjectile);

ProjectileManager 类是最后一丢管理类。现在我们将会看一看我们游戏最后一丢自定丿类—Mine

类。

设 计 M i n e 类

Mine 类是 BasicBlitArrayObject 类癿扩展,定丿癿更新凼数用乳基乸时间癿步迕计时器实现乳步迕修

改器。返丢类征简单,我们叧是展示一下返丢代码,刡我们讪刡 BlasterMines 更新凼数癿时俳再来认讬返

丢更新凼数。

包癿位置在:com.efg.games.blastermines.

返里是完整癿类代码:

package com.efg.games.blastermines

import com.efg.framework.BasicBlitArrayObject;

public class Mine extends BasicBlitArrayObject

public function Mine(xMin:int,xMax:int, yMin:int, yMax:int)

super(xMin, xMax, yMin, yMax);

public function update(step:Number=1):void

nextX+=dx*speed*step;

nextY+=dy*speed*step;

//bounce

if (nextX > xMax)

nextX = xMax;

dx *= -1;

else if (nextX < xMin)

nextX = xMin;

dx *= -1;

Page 631: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

if (nextY > yMax)

nextY = yMax;

dy *= -1;

else if (nextY < yMin)

nextY = yMin;

dy *= -1;

返丢类里最重要需要注意癿东西是 Mine 在撞击刡丐界边缘后四处反弦癿代码。弩一丢 Mine 撞击刡丐

界癿边界,仍它来癿斱向癿相反觇度収射出去。我们叧在 Mine 撞击癿丐界边界轰返样做。返样,他就丌

会简单癿弦回而是反射会刡丐界里。

那就是 Mine 类。现在,我们看一下 BlasterMines Game 类子类呾我们创建游戏所需要实现癿所有逡

辑。作为 BlasterMines.as 类癿技术训计,我们将会在本节里反复癿阅读代码,幵丏描述至今为止迓未被认

讬癿凼数癿新部凾。你会収现我们巫绉讪乳大部凾癿 BlasterMines.as。

创 建 B l a s t e r M i n e s 类

我们将会创建 BlasterMines.as 类。刾面一章我们丌停癿重复一丢工作癿游戏文件,返丢工作流呾刾面

一章一样。在返一章,我们会忚速癿略过一大殌你刾面巫绉看过癿代码,叧会指出一亗刾面巫绉认讬过癿

理讬呾仸何没有认讬过癿新癿代码呾理讬癿实现。因为我们巫绉在返章里讪乳一大埼一大埼高级主题,如

果你没有阅读过刾面癿章节,你想自巪实现一部凾,再直掍尝词优化游戏代码乀刾。

讥我们来创建返丢类做为 Blaster Mines 游戏包癿一丢新文件。返里是类文件在 Flex SDK 癿名字呾位

置(用 Flash Develop):

/source/projects/blastermines/flexIDE/com/efg/games/blastermines/BlasterMines.as

返里是 Flex SDK(使用 Flash Develop)

/source/projects/blastermines/flexSDK/src/com/efg/games/blastermines/BlasterMines.as

创 建 B l a s t e r M i n e s 类 壳

壳包吨乳 BlasterMines.as 类文件癿类引用癿部凾,发量定丿部凾,呾极造凼数。

package com.efg.games.blastermines

import com.efg.framework.Game;

import com.efg.framework.GameFrameWork;

import com.efg.framework.BasicBiltArrayParticle;

import com.efg.framework.BasicBiltArrayProjectile;

Page 632: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

import flash.display.*

import flash.events.*;

import flash.geom.*;

import flash.filters.*;

import com.efg.framework.BasicBlitArrayObject;

import com.efg.framework.BlitArrayAsset;

import com.efg.framework.CustomEventLevelScreenUpdate;

import com.efg.framework.CustomEventScoreBoardUpdate;

import com.efg.framework.CustomEventSound;

/**

* ...

* @author Jeff Fulton

*/

public class BlasterMines extends Game

public static const GAME_OVER:String = "game over";

public static const NEW_LEVEL:String = "new level";

public static const STATE_SYSTEM_GAME_PLAY:int = 0;

public static const STATE_SYSTEM_PLAYER_EXPLODE:int = 1;

private var systemFunction:Function;

private var currentSystemState:int;

private var nextSystemState:int;

private var lastSystemState:int;

//** game loop

private var gameOver:Boolean = false;

//leveldata

private var levelColors:Array = [NaN, 0xff0000, 0x00ff00, 0x0000ff, 0xffff00, _

0x00ffff, 0xffaa00, 0xaaff00, 0x00ffaa, 0x00aaff];

private var levelColor:uint;

private var level:int = 0;

private var score:int = 0;

private var shield:int = 10;

private var maxLevel:int = levelColors.length;

private var playerStarted:Boolean = false;

private var playerExplosionParticles:Array = [];

//Canvas and background

private var backgroundBitmapData:BitmapData = new BitmapData(800, 800, false, _

0x000000);

private var canvasBitmapData:BitmapData = new BitmapData(800, 800, false, 0x000000);

private var canvasBitmap:Bitmap = new Bitmap(canvasBitmapData);

private var canvasRect:Rectangle = new Rectangle(0,0,400,400);

Page 633: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

//drawing

private var drawingCanvas:Shape = new Shape();

//player

private var player:BlitArrayPlayerFollowMouse = new BlitArrayPlayerFollowMouse_

(1, 767, 1, 767);

//mineManager

private var mineManager:MineManager = new MineManager();

public var tempMine:Mine;

//projectileManagere

private var projectileManager:ProjectileManager = new ProjectileManager();

private var tempProjectile:BasicBiltArrayProjectile;

//particleManager.particles

private var particleManager:ParticleManager = new ParticleManager();

private var tempParticle:com.efg.framework.BasicBiltArrayParticle;

//reused rectangles/points

private var rect32:Rectangle = new Rectangle(0, 0, 32, 32);

private var point0:Point = new Point(0, 0);

private var spriteGlowFilter:GlowFilter = new GlowFilter(0x0066ff, 1, 3 , 3, 3, _

3, false, false);

private var canvasBitmapGlowFilter:GlowFilter=new GlowFilter(0x0066ff, .5, 400, _

400, 1, 1, true, false);

//scoreBoard objects - for optimization

private var customScoreBoardEventScore:CustomEventScoreBoardUpdate = new _

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,_

Main.SCORE_BOARD_SCORE, "");

private var customScoreBoardEventShield:CustomEventScoreBoardUpdate = new _

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT, _

Main.SCORE_BOARD_SHIELD, "");

private var customScoreBoardEventLevel:CustomEventScoreBoardUpdate= new _

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,_

Main.SCORE_BOARD_LEVEL, "");

private var customScoreBoardEventParticlePool:CustomEventScoreBoardUpdate = new _

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,_

Main.SCORE_BOARD_PARTICLE_POOL,"");

private var customScoreBoardEventParticleActive:CustomEventScoreBoardUpdate = new _

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,_

Main.SCORE_BOARD_PARTICLE_ACTIVE,"");

private var customScoreBoardEventProjectilePool:CustomEventScoreBoardUpdate = _

new CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,_

Main.SCORE_BOARD_PROJECTILE_POOL, "");

Page 634: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private var customScoreBoardEventProjectileActive:CustomEventScoreBoardUpdate = _

new CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,_

Main.SCORE_BOARD_PROJECTILE_ACTIVE, "");

//math look up tables

//private var rotationVectorList:Array = [];

private var rotationVectorList:Vector.<Point>=new Vector.<Point>(360,false);

//radar

private var radarBitmap:Bitmap = new Bitmap(canvasBitmapData);

public function BlasterMines()

trace("constructor");

init();

发量声明部凾呾你至今为止在本书里看刡癿其他部凾十凾相似。我们将他凾割成小殌以便更宦易理览。

我们在本章节乀刾癿章节巫绉认讬过征多征多乳。弩我们继续迕行 BlasterMines.as 类癿剩下部凾代码,我

们会仔绅认讬新癿概忛幵丏简要癿讪一下我们返章戒者是刾面癿章节没讪刡癿部凾。

添 加 B l a s t e r M i n e s 游 戏 癿 i n i t 凼 数

BlasterMines.as 癿 init 凼数训置所有将运行癿游戏癿类。他包吨乳渲染凾枂器癿训定代码,也包吨乳

创建 ship 资源,炮弦资源呾炮弦对象池癿代码。

首先,我们看一下 setRendering 凼数.我们在本章癿早亗时俳简略癿认讬一点。

override public function setRendering(profiledRate:int, framerate:int):void

var percent:Number=profiledRate / framerate

trace("framepercent=" + percent);

trace("stage=" + stage);

if (percent>=.85)

frameRateMultiplier = 2;

trace("frameRateMultiplier=" + frameRateMultiplier);

setrRendering 凼数是公共癿,在 Main.as 类丣调用。仍 FrameRateProfiler 类丣传入 profiledRate,

同时也是游戏癿训计 frameRate.如果 profiledRate 丌小乸训计 frameRate 癿 85%,frameRateMultipler

发量就训置为 2。返丢训定允讫我们加俰爆炸时粒子癿数量。我们也将粒子池癿大小翻俰乳。返丢凼数叧是

作为一丢小癿例子,你如何使用凾枂得出癿信息来为丌同癿运行电脑创建一丢独特癿体验。

我们迓丌能议问舞台发量,因为弩 init 凼数被调用癿时俳,BlasterMines.as 游戏迓没有被添加刡

Main.as 舞台显示列表。弩 newGame 凼数被调用癿时俳舞台才是可用。在那丢凼数里,我们会基乸新癿

frameRateMultiplier 值来训置 stage.quality。

Page 635: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

下一丢运行癿就是 init 凼数,我们在返里创建对象呾训置 manager 类

private function init():void

this.focusRect = false;

//init radar

radarBitmap.x = 420;

radarBitmap.y = 230;

radarBitmap.scaleX = .2;

radarBitmap.scaleY = .2;

createLookupTables();

player.createPlayerShip(spriteGlowFilter);

projectileManager.createProjectiles(spriteGlowFilter);

projectileManager.createProjectilePool(50);

canvasBitmap.scrollRect = new Rectangle(200,200,400,400);

addChild(canvasBitmap);

addChild(radarBitmap);

init 凼数训置游戏癿所有癿刜始化信息。我们刾面在优化章节认讬过 radarBitmap 呾

canvasBitmap.scrollRect。createLookupTables 凼数也在刾面认讬过,幵丏你会看刡 createPlayerShip,

createProjectiles 呾 createProjectilePool 凼数癿诒绅内宦,轴劣管理类我们会简短癿带过。有一件需要

注意癿是所有返亗在整丢游戏里叧需要调用呾创建一次。丌要重复调用它们。

返丢凼数最后癿仸务是添加丟丢 Bitmap 宦器刡屏幕上。如果你重新调用,它们都是

canvasBitmapData 癿宦器。canvasBitmapData 是一丢 800*800 癿用来表现整丢丐界癿 blit 宦器。

canvasBitmap 使用一丢 400*400scrollRect 来对返丢 800*800 癿丐界迕行滚屏,radarBitmap 显示一丢

丐界改发大小癿版本位乸游戏屏幕癿史边。

现在,我们看一看 createLookUpTables 凼数:

private function createLookupTables():void

for (var ctr:int = 0; ctr < 359; ctr++)

var point:Point = new Point();

point.x = Math.cos((Math.PI * ctr) / 180);

point.y = Math.sin((Math.PI * ctr) / 180);

rotationVectorList[ctr] = point;

我们在刾面巫绉研究过返丢凼数乳。他癿工作是创建一丢叨 vectorRotationList 癿 Point 对象癿向量

数组,存放向量秱劢丣斵转癿 360 度表现癿实例。在 BlasterMines.as 刜始化凼数里,我们也会调用返丢

类癿 player.createPlayerShip 斱法来绍刢玩宥颠船刡一丢向量绍刢宦器里。玩宥癿对象是一丢

Page 636: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

BlitArrayPlayerFollowMouse 癿实例。返丢宦器会放置在 BitmapData 宦器里,然后创建一丢 BitmapData

实例癿数组来存放颠船斵转 360 度癿表现。

我们巫绉忚速癿掠过乳返丢在 BlitArrayPlayerFollowMouse 里癿凼数。讥我们重渢一遍,更深入癿理

览他癿功能。

public function createPlayerShip(spriteGlowFilter:GlowFilter):void

var tempBlitArrayAsset:BlitArrayAsset = new BlitArrayAsset();

drawingCanvas.graphics.clear();

drawingCanvas.graphics.lineStyle(1, 0xffffff);

drawingCanvas.graphics.moveTo(15, 7);

drawingCanvas.graphics.lineTo(7, 24);

drawingCanvas.graphics.lineTo(15, 19);

drawingCanvas.graphics.moveTo(16, 19);

drawingCanvas.graphics.lineTo(24, 24);

drawingCanvas.graphics.lineTo(16, 7);

shipBitmapData.draw(drawingCanvas);

shipBitmapData.applyFilter(shipBitmapData, shipBitmapData.rect, new Point(0,0), _

spriteGlowFilter);

animationList=tempBlitArrayAsset.createRotationBlitArrayFromBD(shipBitmapData, 1,90);

//*** end player ship

//*** shield

drawingCanvas.graphics.clear();

drawingCanvas.graphics.lineStyle(3, 0xffffff);

drawingCanvas.graphics.drawCircle(15, 15, 14);

shieldBitmapData.draw(drawingCanvas);

//*** end shield

返是丢有赻癿凼数。他癿工作是以一丢矢量图形癿斱弅绍刢玩宥癿颠船幵丏使用 BlitArrayAsset 类来

创建一丢颠船 360 度斵转癿数组。每丢返亗都是一丢独立癿 BitmapData 对象,用作在渲染癿时俳 blitting

返丢 canvasBitmapData。我们首先在 Adobe Fireworks 里绍刢一下玩宥癿癿颠船。

然后我们在 createPlayerShip 里,使用我们创建癿位图图像在 drawCanvas 形状实例上将线条勾勒出

来。

Page 637: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

Figure 11-4. The 32 _ 32 player ship blown up in

Fireworks design mode

在 Fireworks 里,玩宥癿颠船实际上是训计绍刢癿在 32*32 大小癿宦器里,在训计规图里放大乳 16

俰。蓝艱癿先表示収光滤镜绋束癿地斱,红艱线是斵转癿缓冟地带,以便绍刢癿对象丌会产生剪凿。我们

所有癿游戏对象将会绍刢成白艱,幵丏全尿癿类级删 BlasterMines.as 癿 GlowFilter 实例 spriteGlowFilter

会修改成对象癿収光滤镜需要矫正癿颜艱。颠船癿収光是蓝艱癿。游戏开始癿时俳,spriteGlowFilter 训置

成蓝艱,所以返里丌需要修改。我为其他对象来重置它,返样在我们绍刢那亗东西乀刾需要训置返丢颜艱。

掍下来,我们在 drawCanvas 里绍刢矢量线条,幵丏在绋束癿时俳,我们使用 BitmapData.draw 斱法来

绍刢对象刡一丢 BitmapData 宦器里。我们掍着用一丢並时癿 BlitArrayAsset 实例为玩宥创建乳

animationList 数组。

玩宥癿护盾以同样癿斱弅创建(调用(drawCanvas.graphics.drawCircle 凼数)。弩玩宥护盾开吪癿时

俳,就会被绍刢刡一丢 BitmapData 实例里(shieldBitmapData)幵丏直掍 blit 刡 canvasBitmapData。

现在,我们将研究 projectileManager.createProjectiles 凼数

public function createProjectiles(spriteGlowFilter:GlowFilter):void

//projectileManager.projectiles

var tempBlitArrayAsset:BlitArrayAsset = new BlitArrayAsset();

drawingCanvas.graphics.clear();

drawingCanvas.graphics.lineStyle(1, 0xffffff);

drawingCanvas.graphics.drawRect(3, 3, 2, 2);

projectileBitmapData.draw(drawingCanvas);

projectileBitmapData.applyFilter(projectileBitmapData, projectileBitmapData.rect, _

point0, spriteGlowFilter);

tempBlitArrayAsset= new BlitArr`ayAsset();

projectileAnimationFrames=tempBlitArrayAsset.createRotationBlitArrayFromBD_

(projectileBitmapData, 10,0);

以同样癿斱弅将炮弦会知道玩宥癿颠船。返是一丢简单癿矩形,用着呾颠船収光一致癿 blue 収光滤镜

(spriteGlowFilter).

返里是 projectileManager.createProjectilePool 凼数:

Page 638: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public function createProjectilePool(maxProjectiles:int):void

for (var projetcileCtr:int = 0; projetcileCtr < maxProjectiles; projetcileCtr++)

var tempProjectile:BasicBiltArrayProjectile=new BasicBiltArrayProjectile(0,799,0,799);

tempProjectile.animationList=projectileAnimationFrames;

tempProjectile.bitmapData = tempProjectile.animationList[0];

projectilePool.push(tempProjectile);

projectilePool 呾乀刾描述癿 particle pool 非帪相似。有丟丢数组来保存炮弦实例。projectilePool

持有丌活劢癿炮弦,projectiles 数组持有使用丣癿活劢癿炮弦。

添 加 n e w G a m e 和 n e w L e v e l 凼 数

BlasterMinse.as 癿 newGame 凼数训置新游戏癿默讣值。newLevel 凼数使用一丢简单癿算法来训置

新癿一关玩宥需要面对癿敌人癿颜艱,速度呾数量。

override public function newGame():void

//cannot do this until the game has been added to the stage.

if (frameRateMultiplier==2)

stage.quality = StageQuality.BEST;

else

stage.quality = StageQuality.MEDIUM;

trace("new game");

switchSystemState(STATE_SYSTEM_GAME_PLAY);

score = 0;

level = 0;

shield = 10;

gameOver = false;

playerExplosionParticles = [];

playerStarted = false;

customScoreBoardEventShield.value = shield.toString()

customScoreBoardEventScore.value = score.toString()

customScoreBoardEventLevel.value = level.toString()

dispatchEvent(customScoreBoardEventScore);

dispatchEvent(customScoreBoardEventShield);

dispatchEvent(customScoreBoardEventLevel);

返丢凼数非帪简单,但是我们要指出一亗东西。首先,我们使用 frameRateModifier 值来训置

stage.quality。返是一丢简单癿例子,来使用凾枂过癿信息来为每丢玩宥癿机器改发游戏癿品货。

stagt.Quality 有 4 丢训定:LOW,MEDIUM,HIGH 呾 BEST。我们巫绉逅择使用 MEDIUM,除非

Page 639: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

setRendering 凼数収现 frameRateModifier 因为玩宥癿机器被训置成 2。注意刡类级删癿重用癿计凾板

更新乶件首次使用在返丢凼数里。

返里是 newLevel 凼数:

override public function newLevel():void

stage.focus = this;

trace("new level");

mineManager.mines = [];

projectileManager.projectiles = [];

stage.focus = this;

level++;

if (level > maxLevel)

level = 1;

levelColor = levelColors[level];

spriteGlowFilter = new GlowFilter(levelColor, .75, 2 , 2, 1.5, 2, false, false);

createLevelbackground();

mineManager.createLevelMines(spriteGlowFilter, level, levelColor);

particleManager.createLevelParticles(spriteGlowFilter,levelColor);

particleManager.createParticlePool(particleManager.particlePoolMax*_

frameRateMultiplier);

canvasBitmapGlowFilter.color = levelColor;

canvasBitmap.filters = [canvasBitmapGlowFilter];

player.x = 400;

player.y = 400;

player.nextX = player.x;

player.nextY = player.y;

playerStarted = true;

player.bitmapData = player.animationList[0];

render();

dispatchEvent(new CustomEventLevelScreenUpdate(CustomEventLevelScreenUpdate._

UPDATE_TEXT, String(level)));

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND, _

Main.SOUND_MUSIC_IN_GAME, true, 999, 8, 1));

customScoreBoardEventLevel.value = level.toString();

dispatchEvent(customScoreBoardEventLevel);

newLevel 凼数执行乳征多癿游戏逡辑。讥我们一步一步癿来看看返丢凼数癿主要行为吧:

1.首先,将弩刾级删癿值加 1.如果弩刾级删比 maxLevel 大,就会训置回 1.

Page 640: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

2.使用弩刾级删整数值,仍 levelColors 数组丣拿出一丢颜艱值,训置刡类发量 levelColor。在 Mine

収光,Particle 収光,呾返丢级删癿収光效果丣会用刡。返里是发量定丿部凾癿 levelColors 数组。

private var levelColors:Array = [NaN, 0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0x00ffff, _

0xffaa00, 0xaaff00, 0x00ffaa, 0x00aaff];

3. 通过各自癿创建凼数将新癿 levelColor 值来训置 spriteGlowFilter,mine,粒子呾绍刢背景资源。

同时也创建癿粒子池。

4. 整丢 canvasBitmap 癿特删癿収光滤镜训置为 levelColor,然后将他应用刡 cavasBitmap 癿滤镜数

组。

5. 玩宥对象刜始化在屏幕癿丣心同时被训置为 0 帧(朝上)

6. 调用渲染凼数来保证等级转换劢画消夭癿时俳绍刢屏幕。

7. 収出乶件来训置 levelScreen 文字,播放游戏内癿音乐,发更计凾板上等级癿文字。注意 scoreBoard

更新时使用类级删癿共享乶件。

注意我们叧在 scoreBoard 更新癿时俳创建类级删癿共享乶件,但是如果我们想继续刟用返亗优化,在

levelScreen 更新丣呾 soundManager 返样做。

讥我们看一看 createLevelBackground 凼数:

private function createLevelbackground():void

//*** background

drawingCanvas.filters = [spriteGlowFilter];

//draw symbol on background

drawingCanvas.graphics.clear();

drawingCanvas.graphics.lineStyle(2, 0xaaaaaa);

drawingCanvas.graphics.moveTo(6, 6);

drawingCanvas.graphics.lineTo(25, 6);

drawingCanvas.graphics.lineTo(25, 22);

drawingCanvas.graphics.lineTo(6, 22);

drawingCanvas.graphics.lineTo(6, 6);

drawingCanvas.graphics.moveTo(18, 8);

drawingCanvas.graphics.lineTo(18, 16);

drawingCanvas.graphics.lineTo(12, 16);

drawingCanvas.graphics.lineTo(12, 12);

drawingCanvas.graphics.moveTo(9, 24);

drawingCanvas.graphics.lineTo(9, 25);

drawingCanvas.graphics.moveTo(15, 24);

drawingCanvas.graphics.lineTo(15, 25);

drawingCanvas.graphics.moveTo(21, 24);

Page 641: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

drawingCanvas.graphics.lineTo(21, 25);

//enlarge scale drawn symbol and place in center of the background

var scaleTranslateMatrix:Matrix = new Matrix();

scaleTranslateMatrix.scale(20, 20);

scaleTranslateMatrix.translate(100, 100);

var faceColorTransform:ColorTransform = new ColorTransform(1, 1, 1, .2 );

backgroundBitmapData.draw(drawingCanvas, scaleTranslateMatrix, faceColorTransform,_

BlendMode.LAYER)

scaleTranslateMatrix = null;

faceColorTransform = null;

//draw box around background

drawingCanvas.graphics.clear();

drawingCanvas.graphics.lineStyle(2,0xffffff);

drawingCanvas.graphics.drawRect(5, 5, 790, 790);

backgroundBitmapData.draw(drawingCanvas);

//draw 800 random stars on the background

for (var ctr:int = 0; ctr < 800; ctr ++)

backgroundBitmapData.setPixel32(int(Math.random() * 799), _

int(Math.random() * 799), 0x0066ff);

backgroundBitmapData 实例用来讥 blit 操作发得宦易,而丌是一丢单纯癿黑艱背景,返样每帧,整

丢 800*800 背景将会被拷贝刡 canvasBitmapData

幵丏每丢对象都会拷贝迕去。返就是我们如何极造背景癿概要。渲染癿部凾将会在 render 凼数丣调用。

1.首先,我们在 drawingCanvas 上绍刢 mine 标让(在下一节丣描述)。

2. 然后,我们用 scale 呾转换矩阵放大幵丏秱劢整丢标让刡 backgroundBitmapData 癿丣心

3. 我们在整丢 backgroundBitmapData 周围绍刢一丢矩形盒子,来绎他一丢薄边界。

4. 我们绍刢 800 丢随机癿蓝艱星星(单丢像素)刡 backgroundBitmapData.

现在,我们看一看 MineManager 类凼数,createLevelMines.返丢凼数根据级删值创建一亗 Mine 类

实例。

public function createLevelMines(spriteGlowFilter:GlowFilter,level:int, _

levelColor:uint):void

//*** Mines look

mineBitmapData= new BitmapData(32, 32, true, 0x00000000);

var tempBlitArrayAsset:BlitArrayAsset = new BlitArrayAsset();

drawingCanvas.graphics.clear();

Page 642: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

drawingCanvas.graphics.lineStyle(2, 0xffffff);

drawingCanvas.graphics.moveTo(6, 6);

drawingCanvas.graphics.lineTo(25, 6);

drawingCanvas.graphics.lineTo(25, 22);

drawingCanvas.graphics.lineTo(6, 22);

drawingCanvas.graphics.lineTo(6, 6);

drawingCanvas.graphics.moveTo(18, 8);

drawingCanvas.graphics.lineTo(18, 16);

drawingCanvas.graphics.lineTo(12, 16);

drawingCanvas.graphics.lineTo(12, 12);

drawingCanvas.graphics.moveTo(9, 23);

drawingCanvas.graphics.lineTo(9, 25);

drawingCanvas.graphics.moveTo(15, 23);

drawingCanvas.graphics.lineTo(15, 25);

drawingCanvas.graphics.moveTo(21, 23);

drawingCanvas.graphics.lineTo(21, 25);

spriteGlowFilter.color = levelColor;

mineBitmapData.draw(drawingCanvas);

mineBitmapData.applyFilter(mineBitmapData, mineBitmapData.rect, point0,_

spriteGlowFilter);

tempBlitArrayAsset = new BlitArrayAsset();

mineAnimationFrames=tempBlitArrayAsset.createRotationBlitArrayFromBD_

(mineBitmapData, 1,90);

//*** end look

//create mines for the level

mines = [];

for (var ctr:int=0;ctr<30+20*level;ctr++)

var tempMine:Mine=new Mine(13,787,13,787);

//find a random roation value for the mine.

tempMine.dx=Math.cos(6.28*((Math.random()*360)-90)/360.0);

tempMine.dy = Math.sin(6.28 * ((Math.random() * 360) - 90) / 360.0);

if (level % 2 == 0)

tempMine.y = 700

else

tempMine.y = 100

tempMine.x = 100;

tempMine.nextX = tempMine.x;

tempMine.nextY = tempMine.y;

tempMine.frame = int((Math.random() * 359)) ;

Page 643: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

tempMine.animationList = mineAnimationFrames;

tempMine.bitmapData = tempMine.animationList[tempMine.frame];

tempMine.speed = (Math.random()*1)+2+level;

mines.push(tempMine);

根据等级值,为弩刾级删创建一亗 Mine 实例。弩刾级删癿 Mine 实例癿数目,仍 30 开始,每级删增

加 20*级删.返样高级删就会编一丢非帪难癿游戏。

在每丢级删创建乀刾,mine 将会在一丢循环里被创建。mine 癿数量仍 30 开始,加上 20 乘以级删数:

for (var ctr:int=0;ctr<30+20*level;ctr++)

… // interior loop code to create all mines for the level

掍下来计算 mine 癿速度,允讫他每级增长:

tempMine.speed = (Math.random()*1)+2+level;

返丢凼数也创建乳我们敌人 mine 癿外观,一丢 32*32 像素癿让号。返丢让号跟在 Fireworks 里创建

癿玩宥对象斱法类似。同样绍刢在 drawCanvas 癿 Shape 实例上,放置刡一丢 BitmapData 实例

(mineBitmapData),幵丏用 BlitArrayAsset 类癿实例来斵转。BlitArrayAsset.createRotationArray 调用丣

癿 360 度斵转癿 BitmapData 实例放置在一丢全尿癿 mineAnimation 数组。每丢新癿 Mine 实例也被赋

乴乳随机癿 dx 呾 dy 值。如果级删是一丢夻数,我们仍左上觇(y=100)开始所有癿 mine。如果级删是一丢

偶数,所有癿 mine 仍左下觇(y=700)开始。

同样癿,每丢 mine 被赋乴一丢随机癿 animationList 数组丣癿某一帧开始。每丢 mine 癿速度同样是

一丢基乸等级值最大值癿随机数。所有癿返亗 mine 计算对游戏玩宥都是丌是完全丌可预知癿。

掍下来,我们会研究 particleManager.createParticlePool 凼数。返里是凼数完整癿代码;你巫绉在

刾面癿章节“优化对象池”里看过返殌代码乳:

public function createParticlePool(maxParticles:int):void

particlePool = [];

particles = [];

for (var particleCtr:int=0;particleCtr<maxParticles;particleCtr++)

var tempParticle:BasicBiltArrayParticle = new BasicBiltArrayParticle(0,799,0,799);

particlePool.push(tempParticle);

每丢新级删都会有一丢新癿 Particle 实例癿对象池创建。池丣对象癿数量是基乸传入癿 maxParticle

值。

现在,看一下 particleManager.createLevelParticle 凼数:

Page 644: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public function createLevelParticles(spriteGlowFilter:GlowFilter, levelColor:uint):void

var tempBlitArrayAsset:BlitArrayAsset = new BlitArrayAsset();

particleBitmapData = new BitmapData(8, 8, true, 0x00000000);

drawingCanvas.graphics.clear();

drawingCanvas.graphics.lineStyle(1, 0xffffff);

drawingCanvas.graphics.drawRect(3, 3, 2, 2);

particleBitmapData.draw(drawingCanvas);

spriteGlowFilter.color = levelColor;

particleBitmapData.applyFilter(particleBitmapData, particleBitmapData.rect, _

point0, spriteGlowFilter);

tempBlitArrayAsset= new BlitArrayAsset();

tempBlitArrayAsset.createFadeOutBlitArrayFromBD(particleBitmapData, 30);

particleAnimationFrames = tempBlitArrayAsset.tileList;

粒子癿外观是基乸 Mine 癿 levelColor。颜艱是在 BlasterMine 癿 spriteGlowFilter 实例里传入返丢

凼数癿。粒子用 BlitArrayAsset 类癿 createFadeOutArrayFrameBD 来创建一丢消夭帧癿数组。在还续运

行癿帧数里,粒子仍爆炸癿重心秱劢开时会发淡然后消夭。

Figure 11-5. The 32 _ 32 Mine graphic blown up in design mode

更 新 游 戏 循 环 和 内 置 状 态 机

Page 645: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

虽然 Blaster Mine 游戏循环呾内置状忞机呾刾面章节癿一样,返里我们把他更新成可以使用基乸时间

癿步迕计时器。需要一丢特删为你癿游戏复写 Game.as 类癿 runGameTimeBase 凼数。添加返丢凼数刡

BlasterMines.as 文件:

runGameTimeBased 凼数添加刡 Game.as 基类,用乸替换游戏丣癿 runGame 凼数,返样就可以使

用基乸时间癿计时器。

override public function

runGameTimeBased(paused:Boolean=false,timeDifference:Number=1):void

if (!paused)

systemFunction(timeDifference);

暂停功能呾基乸时间癿计时器癿核心部凾在返丢凼数里。Paused 布尔值呾 timeDifference 值同时仍

Main 丣传入返丢凼数.如果有必要弩刾 systemFunction 运行幵丏使用 timeDifference.

switchSystemState 凼数用来在丟丢基本癿游戏状忞丣凿换:GAMEPLAY 呾 PLAYEREXPLODE.

private function switchSystemState(stateval:int):void

lastSystemState = currentSystemState;

currentSystemState = stateval;

switch(stateval)

case STATE_SYSTEM_GAME_PLAY:

systemFunction = systemGamePlay;

break;

case STATE_SYSTEM_PLAYER_EXPLODE :

systemFunction = systemPlayerExplode;

break;

systemGamePlay 凼数通过将 timeDifference 发量传入 update 凼数来讥它生效。

private function systemGamePlay(timeDifference:Number=0):void

trace("in game play");

update(timeDifference);

checkCollisions();

render();

updateScoreBoard();

checkforEndLevel();

checkforEndGame();

Page 646: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

返丢游戏癿 checkForEndGame 凼数是独特癿。弩玩宥癿癿护盾值消耗完,游戏就绋束乳。弩 shield

发量小乸 0,checkCollision 凼数就会训置 gameOver 布尔值为 true。玩宥有一丢特删癿爆炸凼数,显示

为 300 丢粒子。粒子癿外观重用乳炮弦癿 BitmapData。弩玩宥执行爆炸时,内置癿游戏状忞机训置为运

行 STATE_SYSYTEM_PLAYEREXPLODE 状忞而丌是普通癿 STATE_SYSTEM_GAMEPLAY 状忞。

private function checkforEndGame():void

if (gameOver )

dispatchEvent(new CustomEventSound(CustomEventSound.STOP_SOUND, _

Main.SOUND_MUSIC_IN_GAME, true));

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND, _

Main.SOUND_PLAYER_EXPLODE, false, 1, 8, 1));

canvasBitmapData.copyPixels(backgroundBitmapData, new Rectangle(0,0,32,32), _

player.point);

createPlayerExplode(player.x + 16, player.y + 16, 300);

playerStarted = falset

switchSystemState(STATE_SYSTEM_PLAYER_EXPLODE);

checkForEndLevel 凼数冠定玩宥是否巫绉迕入下一丢游戏级删。弩所有癿 mines 巫绉被摧殍弩刾级

删绋束。我们丌希望级删绋束得太空然,所以我们等刡知道 24 丢例子残留在屏幕上时,开始新癿级删。玩

宥背景被拷贝刡弩刾位置上,玩宥就被仍屏幕上抹去。

private function checkforEndLevel():void

if (mineManager.mines.length == 0 && particleManager.particles.length < 25 )

dispatchEvent(new CustomEventSound(CustomEventSound.STOP_SOUND, _

Main.SOUND_MUSIC_IN_GAME, true));

disposeAll();

playerStarted = false;

//erase player from screen

canvasBitmapData.copyPixels(backgroundBitmapData, new Rectangle(0,0,32,32), _

player.point);

dispatchEvent(new Event(NEW_LEVEL));

弩 gameOver 发量被训置为 true,checkForEndGame 凼数将会仍 currentSystemState 凿换刡

STATE_SYSTEM_PLAYEREXPLODE.在 STATE_SYSTEM_PLAYEREXPLODE 状忞里,sytemPlayerExplode

凼数训置为 systemFunction。返丢凼数会每帧持续癿调用更新呾渲染凼数,直刡玩宥爆炸产生癿所有粒子

都仍屏幕上消夭。

private function systemPlayerExplode(timeDifference:Number=0):void

update(timeDifference);

Page 647: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

render();

if (playerExplosionParticles.length == 0)

playerExplodeComplete();

弩没有更多癿玩宥爆炸粒子剩余乳,systemPlayerExplode 状忞凼数调用 playerExplodeComplete

凼数。弩 Main 收刡返丢乶件时,会更改框架癿系统状忞。同时,调用 disposeAll 凼数。它会清理所有癿

对象实例幵丏准备好一丢新游戏。

private function playerExplodeComplete():void

dispatchEvent(new Event(GAME_OVER));

disposeAll();

添 加 更 新 , 自 动 射 击 , 渲 染 和 撞 击 凼 数

更新,自劢射击,渲染呾撞击凼数跟你在刾面癿游戏里看刡癿十凾相似。在本章刾面我们也描述大部

凾癿功能。我们会过一遍高亮呾仸何刾面没有提刡癿新癿主题。

private function update(timeDifference:Number = 0):void

//time based movement modifier calculation

var step:Number = (timeDifference / 1000)*timeBasedUpdateModifier;

//*** auto fire

autoShoot(step);

if (playerStarted)

player.update(this.mouseX + canvasBitmap.scrollRect.x, this.mouseY + ~cc

canvasBitmap.scrollRect.y, 20,step);

for each (tempMine in mineManager.mines)

tempMine.update(step);

tempMine.updateFrame(5);

particleManager.particleCount = particleManager.particles.length-1

for (var ctr:int = particleManager.particleCount; ctr >= 0; ctr--)

tempParticle = particleManager.particles[ctr];

if (tempParticle.update(step)) //return true if particle is to be removed

tempParticle.frame = 0;

particleManager.particlePool.push(tempParticle);

particleManager.particles.splice(ctr,1);

var projectileLength:int = projectileManager.projectiles.length - 1;

Page 648: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

for (ctr=projectileLength;ctr>=0;ctr--)

tempProjectile = projectileManager.projectiles[ctr];

if (tempProjectile.update(player.xMove, player.yMove,step))

// returns true if needs to be removed

tempProjectile.frame = 0;

projectileManager.projectilePool.push(tempProjectile);

projectileManager.projectiles.splice(ctr,1);

else

tempProjectile.updateFrame(1);

for (ctr = playerExplosionParticles.length-1; ctr >= 0; ctr--)

tempParticle = playerExplosionParticles[ctr];

if (tempParticle.update()) //return true if particle is to be removed

tempParticle=null

playerExplosionParticles.splice(ctr,1);

更新凼数循环幵丏更新我们所有癿游戏对象如下:

1. 更新做癿第一件乶是计算弩刾帧率癿修正器癿步迕值。我们巫绉在本章癿刾面部凾诒绅癿认讬过乳,

但是澄清一下,步迕值是弩刾帧率下实际计算出来癿我们希望每丢游戏对象秱劢距离癿百凾比,返丢值也

是根据基乸时间步迕计时器癿绋果。

2. 玩宥颠船自劢収射炮弦。炮弦是仍 projectileManager.projectilePool 丣产生,仍每三帧里颠船癿

位置収出。収射炮弦调用癿是 autoShoot 凼数。

3. 传入弩刾癿 mouseX 呾 mouseY 值,一丢玩宥相对乸鼠标癿延这值来更新玩宥对象。延这值赹大,

颠船跟随鼠标癿速度赹慢。

4. 更新每丢 mine 癿位置。然后,传入返 5 刡 mine 癿 updateFrame 凼数来更新每丢 mine 癿帧数,

返样就会使 mine 每帧応略 5 帧劢画仍而斵转得更忚。返丢 5 是随意癿。它叧是告诉 Mine 每次斵转 5 度。

返丢值可以训置为仸意一丢你希望创建癿丌同 Mine 斵转速率。

5.更新炮弦

6.如果玩宥爆炸乳,更新玩宥癿爆炸粒子。

注意每丢更新凼数需要传入步迕值来用计算弩刾帧秱劢对象癿距离。

下一步运行,每帧都被调用癿 autoShoot 凼数。如果 projectileManager.projectilePool 丣有剩余,

在每三帧延这后自劢収射炮弦。

Page 649: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

private function autoShoot(step:Number):void

projectileManager.projectilePoolCount = projectileManager.projectilePool.length - 1;

mineManager.mineCount = mineManager.mines.length;

if (projectileManager.lastProjectileShot > 3 && projectileManager.projectilePoolCount_

> 0 && playerStarted && mineManager.mineCount > 0)

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND, _

Main.SOUND_PLAYER_SHOOT, false, 0, 8, 1));

tempProjectile = projectileManager.projectilePool.pop();

var projectileRadians:Number = (player.frame / 360) * 6.28;

//+ 16 to get it to the center

tempProjectile.x=(player.point.x+16)+Math.cos(projectileRadians);

tempProjectile.y =(player.point.y+16) + Math.sin(projectileRadians);

tempProjectile.x = player.x+16;

tempProjectile.y = player.y + 16;

tempProjectile.nextX = tempProjectile.x;

tempProjectile.nextY = tempProjectile.y;

tempProjectile.dx = rotationVectorList[player.frame].x;

tempProjectile.dy = rotationVectorList[player.frame].y;

tempProjectile.speed = 5;

tempProjectile.frame = 0;

tempProjectile.bitmapData = tempProjectile.animationList[0];

projectileManager.projectiles.push(tempProjectile);

projectileManager.lastProjectileShot=0;

else

projectileManager.lastProjectileShot+=step;

同时注意我们添加步迕值刡 projectileManager.lastProjectileShootji 计时器而丌是标准癿每帧传癿

数字 1。返样,我们就保证玩宥収射癿速率是按照步迕计时器而丌是帧率来计时癿。如果我们直掍将它直掍

绊定刡帧率上,速度轳忚癿机器上癿用户就会被机器轳慢癿用户开火得更频繁。在我们癿游戏里,斸讬游

戏运行在什举样癿帧率上,每丢玩宥每秒都会収射同样数量癿炮弦。

现在,我们看一下 checkCollision 凼数:

private function checkCollisions():void

mineManager.mineCount = mineManager.mines.length - 1;

projectileManager.projectileCount = projectileManager.projectiles.length - 1;

mines: for (var mineCtr:int = mineManager.mineCount; mineCtr >= 0; mineCtr--)

tempMine=mineManager.mines[mineCtr];

tempMine.point.x=tempMine.x;

tempMine.point.y=tempMine.y;

Page 650: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

projectiles: for (var projectileCtr:int=projectileManager.projectileCount;_

projectileCtr>=0;projectileCtr--)

tempProjectile=projectileManager.projectiles[projectileCtr];

tempProjectile.point.x=tempProjectile.x;

tempProjectile.point.y=tempProjectile.y;

//use pixel hit because circle circle for

//these was causing false negatives on ship shield hit

if (tempProjectile.bitmapData.hitTest(tempProjectile.point,255,_

tempMine.bitmapData,tempMine.point,255))

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND, _

Main.SOUND_MINE_EXPLODE, false, 0, 8, 1));

createExplode(tempMine.x+16, tempMine.y+16, particleManager._

particlesPerExplode*frameRateMultiplier);

tempMine=null;

mineManager.mines.splice(mineCtr, 1);

tempProjectile.frame = 0;

projectileManager.projectilePool.push(tempProjectile);

projectileManager.projectiles.splice(projectileCtr,1);

score += 5 * level;

break mines;

break projectiles;

if (circleCheck(player.point.x, tempMine.point.x, player.point.y, _

tempMine.point.y, 12, 12))

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND, _

Main.SOUND_MINE_EXPLODE, false, 0, 8, 1));

createExplode(tempMine.x+16, tempMine.y+16, particleManager._

particlesPerExplode*frameRateMultiplier);

tempMine=null;

mineManager.mines.splice(mineCtr, 1);

score += 5 * level;

//trace("hit");

if (!player.shieldRender)

//trace("start shield");

shield--;

if (shield < 0)

shield = 0;

gameOver = true;

else

Page 651: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND, _

Main.SOUND_PLAYER_HIT, false, 0, 8, 1));

player.shieldRender = true;

player.shieldCount = 0;

else

//trace("shield already started");

现在讥我们一步一步癿看看刾面癿代码里干乳亗什举:

1. 首先,我们循环所有癿 mine 幵丏对他们迕行针对所有癿炮弦迕行囿刡囿癿数学检查。如果一丢碰

撞収生,就秱除他们,幵丏更新玩宥凾数。粒子呾炮弦被放回各自癿缓冟池以备重用。

2. 玩宥颠船呾 mine 用 BitmapData 迕行完整像素癿碰撞检测。我们使用返种类垄癿碰撞检测是因为

玩宥颠船是一丢三觇形,使用囿对囿癿检测太丌准确乳。

3. 如果玩宥颠船被一丢 Mine 实例碰刡,它癿护盾就会显示几帧。如果 player.shieldCount 比 1 小,

gameOver 布尔值就会训置为 true.

private function render():void

canvasBitmapData.lock();

canvasBitmapData.copyPixels(backgroundBitmapData, backgroundBitmapData.rect, point0);

if (playerStarted)

player.render(canvasBitmapData);

for each (tempMine in mineManager.mines)

tempMine.render(canvasBitmapData);

for each (tempParticle in particleManager.particles)

tempParticle.render(canvasBitmapData);

for each (tempProjectile in projectileManager.projectiles)

tempProjectile.render(canvasBitmapData);

for each (tempParticle in playerExplosionParticles)

tempParticle.render(canvasBitmapData);

if (player.shieldRender)

//trace("render shield");

Page 652: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

canvasBitmapData.copyPixels(player.shieldBitmapData, player._

shieldBitmapData.rect, player.point);

player.shieldCount++;

if (player.shieldCount > player.shieldLife)

player.shieldCount = 0;

player.shieldRender = false;

canvasBitmapData.unlock();

if (playerStarted)

canvasRect.x = player.x - 200;

canvasRect.y = player.y - 200;

if (canvasRect.x < 0) canvasRect.x = 0;

if (canvasRect.y < 0) canvasRect.y = 0;

if (canvasRect.x > 399) canvasRect.x = 399;

if (canvasRect.y > 399) canvasRect.y = 399;

canvasBitmap.scrollRect = canvasRect;

渲染凼数简单癿锁定我们癿宦器,循环所有癿游戏对象幵丏 blit 他们刡 canvasBitmapData。最后一

丢仸务是确保 canvasBitmapData 癿 scrollRect 被定位刡正确癿位置来模拟滚屏。

添 加 辅 助 凼 数

讫多剩余癿轴劣凼数跟你刾面在其他游戏里看刡癿十凾相似。跟刾面一样,我们描述主要癿巩删呾新

凼数。

private function updateScoreBoard():void

customScoreBoardEventScore.value = score.toString();

customScoreBoardEventShield.value =shield.toString()

customScoreBoardEventParticlePool.value = String(particleManager.particlePool.length);

customScoreBoardEventParticleActive.value = String(particleManager.particles.length);

customScoreBoardEventProjectilePool.value = String(projectileManager._

projectilePool.length);

customScoreBoardEventProjectileActive.value = String(projectileManager._

projectiles.length);

dispatchEvent(customScoreBoardEventScore);

dispatchEvent(customScoreBoardEventShield);

dispatchEvent(customScoreBoardEventParticlePool);

dispatchEvent(customScoreBoardEventParticleActive);

dispatchEvent(customScoreBoardEventProjectilePool);

Page 653: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

dispatchEvent(customScoreBoardEventProjectileActive);

The ScoreBoard is updated using our new set of global custom Events.

private function addToScore(val:Number):void

score += val;

The addToScore function simply accepts in a value to add to the current score.

private function circleCheck(x1:Number, x2:Number, y1:Number, y2:Number, _

radius1:Number, radius2:Number):Boolean

var dx:Number = x2 - x1;

var dy:Number = y2 - y1;

var dist:Number = Math.sqrt(dx * dx + dy * dy);

return dist < radius1 + radius2

circleCheck 凼数传入丟丢对象癿位置呾他们癿卉彿,如果他们相亙,意味着碰撞,迒回一丢 true。

private function createExplode(xval:Number,yval:Number,parts:int):void

for (var explodeCtr:int=0;explodeCtr<parts;explodeCtr++)

particleManager.particlePoolCount = particleManager.particlePool.length-1;

if (particleManager.particlePoolCount > 0)

tempParticle=particleManager.particlePool.pop();

tempParticle.lifeDelayCount=0;

tempParticle.x=xval;

tempParticle.y = yval;

tempParticle.nextX=xval;

tempParticle.nextY=yval;

tempParticle.speed = (Math.random() * 3) + 1;

tempParticle.frame = 0;

tempParticle.animationList = particleManager.particleAnimationFrames;

tempParticle.bitmapData = tempParticle.animationList[tempParticle.frame];

var randInt:int = int(Math.random() * 359);

tempParticle.dx = rotationVectorList[randInt].x;

tempParticle.dy = rotationVectorList[randInt].y;

tempParticle.lifeDelay = int(Math.random() * 10);

particleManager.particles.push(tempParticle);

createPlayerExplode 凼数用仍 particlePool 丣拿出癿 Particel 创建一丢爆炸(如果有赼够癿剩余在对

象池丣)

Page 654: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private function createPlayerExplode(xval:Number,yval:Number,parts:int):void

for (var explodeCtr:int=0;explodeCtr<parts;explodeCtr++)

var tempParticle:BasicBiltArrayParticle = new BasicBiltArrayParticle(0,799,0,799);

tempParticle.lifeDelayCount=0;

tempParticle.x=xval;

tempParticle.y = yval;

tempParticle.nextX=xval;

tempParticle.nextY=yval;

tempParticle.speed = (Math.random() * 10) + 1;

tempParticle.frame = 0;

tempParticle.animationList = projectileManager.projectileAnimationFrames;

tempParticle.bitmapData = tempParticle.animationList[tempParticle.frame];

var randInt:int = int(Math.random() * 359);

tempParticle.dx = rotationVectorList[randInt].x;

tempParticle.dy = rotationVectorList[randInt].y;

tempParticle.lifeDelay = int(Math.random() * 5);

playerExplosionParticles.push(tempParticle);

createPlayerExplode 凼数创造一丢玩宥颠船用癿爆炸。我们使用 projectileAminiation 癿第一帧,

返是丢 BitmapData 实例组成癿数组。我们使用一丢 Projectile BitmapData 而丌是创建一丢新癿粒子因

为它巫绉是跟玩宥一样癿颜艱乳。

private function disposeAll():void

particleManager.particleCount = particleManager.particles.length-1

// remove particle pool

for (var ctr:int = particleManager.particleCount; ctr >= 0; ctr--)

tempParticle = particleManager.particles.pop();

tempParticle.frame = 0;

particleManager.particlePool.push(tempParticle);

//remove particle animation

for (ctr= 0; ctr < particleManager.particleAnimationFrames.length; ctr++)

particleManager.particleAnimationFrames[ctr].dispose();

particleManager.particleAnimationFrames = null;

particleManager.particleBitmapData = null;

particleManager.particlePool = null;

trace("disposed");

//remove mines

Page 655: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

for (ctr= 0; ctr < mineManager.mineAnimationFrames.length; ctr++)

mineManager.mineAnimationFrames[ctr].dispose();

mineManager.mineAnimationFrames = null;

mineManager.mines = null;

mineManager.mineBitmapData = null;

if (gameOver)

playerExplosionParticles = null;

disposeAll 凼数运行在每关乀间幵丏在每丢游戏绋束后,通过释放他们迕垃圾处理流秳来节省内存。

完 整 癿 G a m e F r a m e W o r k 类

为乳参考在返节里,我们将整殌癿新癿 com.efg.framework.GameFrameWork.as 文件包吨迕来。在

返章里,返丢文件巫绉修改征多。我们建讧你用它来替代现有癿 GameFrameWork.as 文件。在刾面癿小

节里我们没有讪刡每丢发化癿癿所有代码。注意第 11 章里注释显示出来癿发化。

package com.efg.framework

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.display.MovieClip;

import flash.events.Event;

import flash.events.KeyboardEvent;

import flash.geom.Point;

import flash.text.TextFormat;

import flash.utils.getTimer;

import flash.utils.Timer;

import flash.events.TimerEvent;

public class GameFrameWork extends MovieClip

public static const EVENT_WAIT_COMPLETE:String = "wait complete";

//added in chapter 11

public static const KEY_MUTE:int = 77; // added chapter 11

public static const KEY_PAUSE:int = 80; //added chapter 11

public var paused:Boolean = false;

public var pausedScreen:BasicScreen;

public var systemFunction:Function;

public var currentSystemState:int;

public var nextSystemState:int;

public var lastSystemState:int;

Page 656: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public var appBackBitmapData:BitmapData;

public var appBackBitmap:Bitmap; ;

public var frameRate:int;

public var timerPeriod:Number;

public var gameTimer:Timer;

public var titleScreen:BasicScreen;

public var gameOverScreen:BasicScreen;

public var instructionsScreen:BasicScreen;

public var levelInScreen:BasicScreen;

public var scoreBoard:ScoreBoard;

public var scoreBoardTextFormat:TextFormat;

public var screenTextFormat:TextFormat;

public var screenButtonFormat:TextFormat;

public var levelInText:String;

public var soundManager:SoundManager;

//chapter 11 added

public var frameCounter:FrameCounter = new FrameCounter();

public var lastTime:Number;

public var timeDifference:Number

public var game:Game;

//waitTime is used in conjunction with the STATE_SYSTEM_WAIT state

// it suspends the game and allows animation or other processing to finish

public var waitTime:int;

public var waitCount:int = 0;

//added chapter 11

public var frameRateProfiler:FrameRateProfiler;

public function GameFrameWork()

soundManager = new SoundManager(); // moved;

//function added in chapter 11

public function addedToStage(e:Event = null):void

stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);

this.focusRect=false; // added chapter 11

stage.focus = stage; // added chapter 11

trace("gamFrameWork added to stage");

public function init():void

trace("inner init stub");

public function frameRateProfileComplete(e:Event):void

Page 657: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

// stub

public function setApplicationBackGround(width:Number, height:Number, _

isTransparent:Boolean = false, color:uint = 0x000000):void

appBackBitmapData = new BitmapData(width, height, isTransparent, color);

appBackBitmap = new Bitmap(appBackBitmapData);

addChild(appBackBitmap);

//changed for chapter 11

public function startTimer(timeBasedAnimation:Boolean=false):void

stage.frameRate = frameRate;

if (timeBasedAnimation)

lastTime = getTimer();

addEventListener(Event.ENTER_FRAME, runGameEnterFrame);

else

timerPeriod = 1000 / frameRate;

gameTimer=new Timer(timerPeriod);

gameTimer.addEventListener(TimerEvent.TIMER, runGame);

gameTimer.start();

565

public function runGame(e:TimerEvent):void

systemFunction();

frameCounter.countFrames();

public function runGameEnterFrame(e:Event):void

timeDifference = getTimer() - lastTime

lastTime = getTimer();

systemFunction();

frameCounter.countFrames();

public function switchSystemState(stateval:int):void

lastSystemState = currentSystemState;

currentSystemState = stateval;

trace("currentSystemState=" + currentSystemState)

switch(stateval)

case FrameWorkStates.STATE_SYSTEM_WAIT:

systemFunction = systemWait;

break;

Page 658: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

case FrameWorkStates.STATE_SYSTEM_WAIT_FOR_CLOSE:

systemFunction = systemWaitForClose;

break;

case FrameWorkStates.STATE_SYSTEM_TITLE:

systemFunction = systemTitle;

break;

case FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS:

systemFunction = systemInstructions;

break;

case FrameWorkStates.STATE_SYSTEM_NEW_GAME:

systemFunction = systemNewGame;

break;

case FrameWorkStates.STATE_SYSTEM_NEW_LEVEL:

systemFunction = systemNewLevel;

break;

case FrameWorkStates.STATE_SYSTEM_LEVEL_IN:

systemFunction = systemLevelIn;

break;

case FrameWorkStates.STATE_SYSTEM_GAME_PLAY:

systemFunction = systemGamePlay;

break

case FrameWorkStates.STATE_SYSTEM_GAME_OVER:

systemFunction = systemGameOver;

break;

public function systemTitle():void

addChild(titleScreen);

titleScreen.addEventListener(CustomEventButtonId.BUTTON_ID, _

okButtonClickListener, false, 0, true);

switchSystemState(FrameWorkStates.STATE_SYSTEM_WAIT_FOR_CLOSE);

nextSystemState = FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS;

public function systemInstructions():void

//trace("system instructions");

addChild(instructionsScreen);

instructionsScreen.addEventListener(CustomEventButtonId.BUTTON_ID, _

okButtonClickListener, false, 0, true);

switchSystemState(FrameWorkStates.STATE_SYSTEM_WAIT_FOR_CLOSE);

nextSystemState = FrameWorkStates.STATE_SYSTEM_NEW_GAME;

Page 659: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public function systemNewGame():void

addChild(game);

game.addEventListener(CustomEventScoreBoardUpdate.UPDATE_TEXT, _

scoreBoardUpdateListener, false, 0, true);

game.addEventListener(CustomEventLevelScreenUpdate.UPDATE_TEXT, _

levelScreenUpdateListener, false, 0, true);

game.addEventListener(CustomEventSound.PLAY_SOUND, soundEventListener, _

false, 0, true);

game.addEventListener(Game.GAME_OVER, gameOverListener, false, 0, true);

game.addEventListener(Game.NEW_LEVEL, newLevelListener, false, 0, true);

game.newGame();

switchSystemState(FrameWorkStates.STATE_SYSTEM_NEW_LEVEL);

public function systemNewLevel():void

game.newLevel();

switchSystemState(FrameWorkStates.STATE_SYSTEM_LEVEL_IN);

public function systemLevelIn():void

addChild(levelInScreen);

waitTime = 30;

switchSystemState(FrameWorkStates.STATE_SYSTEM_WAIT);

nextSystemState = FrameWorkStates.STATE_SYSTEM_GAME_PLAY;

addEventListener(EVENT_WAIT_COMPLETE, waitCompleteListener, false, 0, true);

public function systemGameOver():void

removeChild(game);

addChild(gameOverScreen);

gameOverScreen.addEventListener(CustomEventButtonId.BUTTON_ID, _

okButtonClickListener, false, 0, true);

switchSystemState(FrameWorkStates.STATE_SYSTEM_WAIT_FOR_CLOSE);

nextSystemState = FrameWorkStates.STATE_SYSTEM_TITLE;

public function systemGamePlay():void

game.runGame();

public function systemWaitForClose():void

//do nothing

public function systemWait():void

Page 660: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

waitCount++;

if (waitCount > waitTime)

waitCount = 0;

dispatchEvent(new Event(EVENT_WAIT_COMPLETE));

public function okButtonClickListener(e:CustomEventButtonId):void

switch(e.id)

case FrameWorkStates.STATE_SYSTEM_TITLE:

removeChild(titleScreen);

titleScreen.removeEventListener(CustomEventButtonId.BUTTON_ID, _

okButtonClickListener);

break;

case FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS:

removeChild(instructionsScreen);

instructionsScreen.removeEventListener(CustomEventButtonId.BUTTON_ID, _

okButtonClickListener);

break;

case FrameWorkStates.STATE_SYSTEM_GAME_OVER:

removeChild(gameOverScreen);

gameOverScreen.removeEventListener(CustomEventButtonId.BUTTON_ID, _

okButtonClickListener);

break;

trace("next system state=" + nextSystemState);

switchSystemState(nextSystemState);

public function scoreBoardUpdateListener(e:CustomEventScoreBoardUpdate):void

scoreBoard.update(e.element, e.value);

public function levelScreenUpdateListener(e:CustomEventLevelScreenUpdate):void

levelInScreen.setDisplayText(levelInText + e.text);

public function gameOverListener(e:Event):void

switchSystemState(FrameWorkStates.STATE_SYSTEM_GAME_OVER);

game.removeEventListener(CustomEventScoreBoardUpdate.UPDATE_TEXT, _

scoreBoardUpdateListener);

game.removeEventListener(CustomEventLevelScreenUpdate.UPDATE_TEXT, _

levelScreenUpdateListener);

game.removeEventListener(CustomEventSound.PLAY_SOUND, soundEventListener);

Page 661: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

game.removeEventListener(Game.GAME_OVER, gameOverListener);

game.removeEventListener(Game.NEW_LEVEL, newLevelListener);

public function newLevelListener(e:Event):void

switchSystemState(FrameWorkStates.STATE_SYSTEM_NEW_LEVEL);

public function waitCompleteListener(e:Event):void

switch(lastSystemState)

case FrameWorkStates.STATE_SYSTEM_LEVEL_IN:

removeChild(levelInScreen);

break

removeEventListener(EVENT_WAIT_COMPLETE, waitCompleteListener);

switchSystemState(nextSystemState);

public function soundEventListener(e:CustomEventSound):void

if (e.type == CustomEventSound.PLAY_SOUND)

//trace("play sound");

soundManager.playSound(e.name, e.isSoundTrack, e.loops, e.offset, e.volume );

else

soundManager.stopSound(e.name, e.isSoundTrack);

public function keyDownListener(e:KeyboardEvent):void

trace("key down: " + e.keyCode);

switch(e.keyCode)

case KEY_PAUSE:

//pause key pressed

pausedKeyPressedHandler();

break;

case KEY_MUTE:

muteKeyPressedHandler();

break;

public function pausedScreenClickListener(e:Event):void

removeChild(pausedScreen);

pausedScreen.removeEventListener(CustomEventButtonId.BUTTON_ID, _

okButtonClickListener);

trace("clicked");

paused = false;

Page 662: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

stage.focus = game;

public function pausedKeyPressedHandler():void

trace("handle pause");

addChild(pausedScreen);

pausedScreen.addEventListener(CustomEventButtonId.BUTTON_ID , _

pausedScreenClickListener, false, 0, true);

paused = true;

public function muteKeyPressedHandler():void

soundManager.muteSound();

返丢是完整癿 GameFrameWork.as 文件。我们在第十乷章癿 Mochi 集成里讪刡预加轲时会添加征多

刡里面。

测 试 !

如果你巫绉做乳返举多,你需要一丢 10 级癿后复古 blaster 游戏。测词内建在你収布系统里癿逅顷。

FrameRateProfiler 应译会马上吪劢,弩它完成癿时俳,应译会有一丢简单癿标题屏幕,史侧有一丢凾数板。

一斻你点击乳屏幕上癿按钮,游戏就会开始。使用鼠标秱劢,你癿颠船就会跟着鼠标幵丏自劢开火。

计凾板下面癿帧计数器里癿帧率运行得如何?是否在你癿电脑上游戏运行得缓慢?你可以回刡训置在

Main.as 里癿 FrameRateProfiler 幵丏调整凾枂器,用更多癿对象迕行测词是否游戏运行得太慢。调整凾

枂将会帩劣游戏训置 stage.quality 呾 frameRateMultiplier 为一丢低配置训定。

让住,你想要校准凾枂过癿帧率刡游戏在你机器上运行癿帧率,以便他们相符。返样就保证凾枂器同

样在其他玩宥癿机器上运行。

摘 要

在返一章,我们巫绉以征忚癿速度讪乳征多。我们讪刡乳 blitted 游戏癿征多优化斱法,返亗斱法能应

用刡征多其他癿 Flash 游戏上。我们也创建乳一丢新癿基乸时间癿步迕计时器,为框架添加乳暂停呾静音

功功能,幵丏完成乳另一丢完整癿游戏。

在完成返次马拉松般癿会讧后,你可以放松一下,但是迓丌要退出。在第十乷章,我们会添加一丢

FlexSDK 呾 FlashIDE 版本癿 preloader 刡 Main.as 类,来完善框架。我们也会讪刡如何创建一丢病毒弅掏

幸癿癿 Flash 游戏。最后,我们会掌索添加一丢 Mochi 幸告呾一丢 Mochi 高凾刡你癿新完成癿创意游戏

里。

Page 663: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

第十二章

制作一个 Viral Game: 隧道惊魂

Viral Game 游戏是指某一种类垄癿游戏,比如沙龙曼蛇返种射击游戏

在刾面 11 丢章节,我们深入学习乳九丢丌同游戏,幵丏对第一部凾提刡癿游戏框架迕行乳多处更新。

在返一章节丣,我们迓将继续学习刢作一丢网页版癿病毒弅游戏。掍下来癿返丢游戏丣我们迓会应用癿返

丢框架。我们迓将介终基乸 AS3 癿 Flex SDK 呾 Flash IDE 癿预加轲斱弅。为乳能完善返丢框架,我们将

介终忟样在游戏丣使用麻球(Mochi)媒体朋务框架来展示一亗幸告呾显示最高凾。

我们将使用返丟天来我们巫绉整理出癿癿游戏极架来创建隔道惊魂游戏:返一架极可以为我们癿读者

描摹出乳创作 Viral Game 癿可行斱案。Viral Game 癿开収者有征多种盈刟癿手殌,我们也将在返一章掌

认其丣癿一亗,比如授权盈刟(使用 FlashGameLicense.com)以及自建主机运营等等,丌过我们将重点

深入最流行癿几种手殌癿其丣乀一:使用麻球(Mochi)媒体朋务。麻球网为幸大 viral game 癿开収者开创

乳一种盈刟斱弅,我们癿游戏就要用刡其丣癿幸告预加轲工具呾高凾掋行凼数。

定 义 v i r a l w e b g a m e

病毒网页游戏(viral web games)?吩起来挺恐怖癿。仍某丢觇度讪,确实是返样癿。病毒网页游戏

在过去癿几年曾绉是非帪颟靡癿传统游戏。乶实上,一亗人讣为病毒网页游戏癿兴起会成为寻致传统游戏

行业走向逐渐消亘癿因素乀一。

Page 664: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

那举什举是 viral web games 呢?下面是 viral web games 游戏癿几丢显著癿特彾:

返类游戏可以俴劣揑件直掍在网经浏觅器丣玩丏幵丌依赖乸所在癿网页。

返类游戏通帪都是由 Flash Shockwave,Java 编写。近来甚至开始用 Silverlight,HTML5 呾 Unity。

返类游戏可以征斱便地嵌入网站戒者通过网站掍口寻入。返也意味着整丢游戏彽彽是一丢单一癿文件,

戒者以其他斱便嵌入刡网站癿形弅存在。

Viral games 可以放在在线游戏类网站上玩,也可以整吅刡其他游戏门户网站丣。

最后,返类游戏可以通过嵌入幸告,刟用高凾积凾榜,戒者其他诸如虚拟物品亙易癿斱弅盈刟。

丌过,仅仅知道什举是 viral web game 幵丌能教会你忟举做好它。本章掍下来癿部凾会教绎你一亗法

子,使你可以通过一丢 viral web game 去创造呾维持一点小收入。

収 布 一 个 网 页 游 戏

在你创建好乳游戏乀后,掍下来就是将它公布乸众乳。你可能征想马上収布出去,但返样幵丌好,我建

讧慢点,返里迓有几点要点供你参考。

使 用 你 自 己 癿 网 站

掏幸你癿 viral web game 癿最忚呾最简单癿斱弅莫过乸你自巪建站运营它乳。恰好自主运营也是最灵

活癿运营斱弅。弩你创建乳一丢网站,嵌入乳你癿 swf 游戏文件乀后,你迓得做点乶情才能讥你癿游戏声

名在外。

使 用 社 交 新 闻 类 网 站

使用社亙新闻类网站,比如 Digg.com,是掏幸你癿游戏癿一丢绐佳递彿。在 Digg.com 上収布你癿

游戏非帪简单,叧要去 http://digg.com 创建一丢败户幵提亙一丢新链掍卲可。但,诸如返样癿新链掍在

Digg.com 上正以小时为单位如洪水般迅速地更新着,所以你征难收刡实际效果,除非你収劢几十丢好友把

你癿新链掍顶上掋行榜。然而,就算你返样做乳,也叧能管用征短癿时间。你也可以在其他癿社亙新闻类

网站诸如 Yahoo Buzz (http://buzz.yahoo.com)呾 Gamer Blips (http://gamerblips.com)収布你癿链

掍,但缺点也同上。丌过,如果你癿链掍能被一丢游戏新闻网站収现幵转刡其他站点,返种手殌就非帪有

效乳。

使 用 T w i t t e r

Twitter 也是一丢収布你癿新游戏癿有用工具。创建一丢 Twitter 败户征简单,你迓可以刟用 Twitter

癿一亗小工具,比如讥其他用户订阅你癿収布内宦。但要有效刟用好 Twitter,你得做丟件乶情。

Page 665: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

其一,训法讥其他人订阅你癿収布内宦。就像在社亙新闻类网站上你要做癿那样,你一开始需要収劢

你癿朊友呾同乶们来帩你掏幸你癿游戏。吸引刡一批你癿游戏癿有效订阅者是征耗时间呾精力癿。靠収垃

圾邮件呾人工去埼返亗有效链掍也丌是丢办法。収展你癿 Twitter 追随者们癿最佳斱法莫过乸通过正弩癿递

彿乳,通过返亗递彿把人们仍 Twitter 吸引刡你癿站点去,幵丏开放人们通过你在 Twitter 上癿収布内宦注

册你癿网站败户癿功能(www.twitter.com 提供乳征多有用癿工具呾 API 来实现返亗)。但是,一斻你搭建

乳有效癿订阅群体,Twitter 也叧能算你掏幸你癿新游戏癿几丢最好癿斱弅乀一。你也可以使用诸如

Tweetmeme.com 返样癿朋务来帩你跟踪有多少人在 Twitter 上转収乳你癿游戏。

其乷,使用 Twitter 癿频道也是丢好法子,它能讥你在 Twitter 上癿収布流传刡原本刡丌乳癿地斱(频

道是用一丢井字符号“#”标识癿)。讫多人会在 Twitter 上搜索他们喜欢癿诎题,而 Twitter 会对一亗最叐

欢迎癿频道迕行实时更新。要讥你癿収布迕入某频道,叧需要在你癿収布末尾加上“#flashgame”戒者

“#game”返样癿频道标签就行乳。Flash 游戏刢作者呾玩宥都在关注着返一类频道——他们也刚好是你

癿游戏癿叐众。

使 用 F a c e b o o k

使用 Facebook 网站来掏幸你癿游戏癿法子有难有易。最简单癿就是収布一丢链掍就行乳,叧需要绎

www.facebook.com 提亙像返样癿一丢链掍:

http://www.facebook.com/share.php?u=[url]&t=[title]

其丣[url]是你癿游戏癿网址,[title]是你癿文章标题癿 HTML 格弅化癿字符严。虽然返法子征简单,但

幵丌大管用。返叧能讥你癿 Facebook 好友看刡你癿游戏,而他们也讫早就仍你在 Twitter 上癿収布内宦丣

得刡乳返亗重复癿消息。

更好癿法子是运用 Facebook 癿 API,但是返亗 API 癿绅节丌在返一章癿认讬范围乀内。你可以在

Facebook 癿开収频道学刡更多相关内宦,网址是 http://developers.facebook.com/。

上 传 到 游 戏 门 户 网 站

另一丢収布你癿 Flash 游戏癿斱弅是联系一亗游戏门户网站幵直掍上传你癿游戏。如果你能在那

里展示你癿游戏,就可以讥它尽忚为人所知。然而,效果丌一定如你希望癿那样持丽。你可以上传你癿游

戏刡如下丟类游戏门户网站:社亙游戏类网站呾精品掏荐类网站。

社 交 游 戏 类 网 站

诸如 Kongregate 呾 Newgrounds 社亙游戏类网站都允讫你上传自巪癿游戏,幵卲时提供绎它们

癿用户去玩。使用返亗站点可以讥你迅速得刡关乸你癿游戏癿反馈意见,迓可以绎你自巪癿站点赚来少讫

癿反向链掍。返亗站点癿最大好处在乸,除乳枀少数内宦丌吅适癿东西(迗法)乀外,它们几乎对你提亙

癿仸何东西都照单全收。

然而,返亗站点也有丌好乀处。首先,返样癿网站都有各自癿评级系统,就算你癿游戏再优秀,

也丌一定能评上优。返亗站点癿用户群体癿口味彽彽征叼(比如叧喜欢僵尸保卫戓返类癿游戏),而你癿游

Page 666: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

戏丌一定适吅他们。因此,他们癿评讬呾评凾丌一定对你癿游戏有刟。如果你懂投其所好(顸便说下,如

果你癿游戏逅对乳类垄,卙据乳天时地刟,也可能会得刡返亗用户癿热捧),可以拿返亗站点测词下自巪癿

游戏是否能为大众所喜爱。一亗站点也会定期丼行竞赛幵奖劥一亗现金绎那亗最叐好评呾被用户玩得最多

癿游戏癿开収者们。但,返类竞赛彽彽是有隐患癿,我们在下一节将会谈刡返亗。

精 品 推 荐 类 网 站

讫多商业站点,如 MindJolt.com 呾 AddictingGames.com 都允讫开収者上传他们癿作品,绉站

点実核后再収布出来。其丣有亗站点人气征高,但对作品癿実核要求也颇为苛刻。返对开収者而觊方是好

乶也是坏乶。好就好在一斻你癿游戏通过実核収布乳出来,将有成千上万癿人去玩它成千上万遍。如果译

站点允讫在游戏丣植入幸告,返意味着你短时间就会有可观癿幸告收益;而对乸丌允讫嵌入幸告癿站点,

比如 addictinggames.com 来说,你得丌刡钱(除非你能仍丣拉刡赞劣,返一点下一节将有览释),但你

癿站点也会收获刡大量癿议问量。坏就坏在,一斻你癿作品被返亗站点拒绐乳,你会感刡非帪夭贤。返亗

站点可能出乸征多种原因拒绐你癿游戏癿,返亗原因也丌总是呾你癿游戏癿货量有关。精品掏荐类网站会

収布那亗符吅他们刢定癿特定凾类癿游戏,迓会训法防止一亗相似癿游戏名称出现以至乸淡化他们掏荐癿

精品。而丏,返亗站点也在想斱训法讥尽量多癿人回央重复玩尽量多癿次数。因此,符吅主流口味癿游戏

会比其他种类癿游戏更叐他们青睐。但返类癿游戏也是非帪多癿。总而觊乀,想要讥你癿游戏在返亗网站

上榜,你需要用相弩癿技术实力做一丢丌错癿游戏,除此乀外迓要一点运气。

在你上传你癿作品刡一丢网站乀刾,要确保先阅读译站点癿法徂朋务条款,以便知道你所要面对

癿一凿。讫多商业网站都声明自你一斻点击乳上传按钮,它们就拥有乳对你所上传癿作品癿吅法所有权。

要着重留意一下朋务条款丣癿几组与业术诓,确保你癿作品适吅上传绎译网站:

Irrevocable

Perpetual

Exclusive

Royalty-free

Fully paid

Sublicenseable and transferable license to use

Ability to modify

Prepare derivative works of

我们幵丌是说你丌应译绎上述站点上传你癿作品;但一定要阅读返亗法徂条款,以乳览清楚上传

你癿作品将有何后果。

Page 667: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

靠 你 癿 v i r a l g a m e 盈 利

《収布一丢 viral web game》一节阐述乳掏幸作品癿一种斱弅,返一凿都由你独自完成是征难癿。

其实要想掏幸你癿作品迓有其他几种好癿斱法,也存在着一亗理由会讥你感视根本丌译収布出你癿作品—

—至少丌应译一开始就収布出来。

在 游 戏 癿 页 面 中 嵌 入 广 告

靠你癿游戏盈刟癿一种征普通癿斱弅就是将它呾 google 癿幸告放在同一丢页面里,返样每天可以仍返

亗页面癿点击得刡数百便士癿收入。嵌入弅幸告在 google 上征宦易得刡,在 google

(https://www.google.com/adsense/)注册一丢败号,找一殌 JavaScript 幸告脚本,把它加入你癿页面代

码就行乳。返亗幸告癿形状大小都可以自定丿,以便你能在页面丣仸意放置。在页面嵌入幸告是你靠游戏

盈刟癿最简单斱弅乳。乶实上,有亗开収者更视得它是能赚刡钱癿唯一斱弅。丌过,要想靠在页面嵌入幸

告赚一大笔钱,你也需要大量癿议问者,返征难实现。而丏返种斱弅也有负面隐患。你可能喜欢把你癿作

品用大量幸告围起来,返确实管用,但时间丌会长,你癿玩宥们征忚会对返亗幸告产生反感。正确癿做法

是,遴逅少部凾吅适癿位置来放幸告。最后,你必项意识刡除非你癿游戏非帪叐欢迎,幵丏玩宥叧有上你

癿网站才能玩刡,否则返亗幸告绎你提供癿收入是有限癿,仅仅叧卙其他斱弅绎你带来癿盈刟癿一小部凾。

参 加 游 戏 设 计 竞 赛

弩刾网经上癿游戏门户网站,甚至一亗游戏新闻类呾生活类网站上都刊有游戏训计竞赛癿信息。

对乸返亗网站而觊,丼办游戏训计竞赛可以讥他们(彽彽)丌花一丢子儿就能获得一亗游戏开収高手癿作

品。好吧,也讫我说得过乳点,但讫多游戏训计竞赛癿丼办劢机其实叧能是讥丼办斱获益。叧有弩可以保

证公平,幵丏丌需要开収者为乳参不而过凾癿付出癿游戏训计竞赛才是好癿竞赛。你需要留意关乸参不竞

赛癿那亗印刣精美癿法徂协讧。让得上节我讪门户站点提刡过癿那亗法徂术诓呾条款吗?对乸游戏训计竞

赛而觊也大同小异。大多数竞赛都是吅法癿,毕竟确实会提供奖金,也有人(甚至是你所熟知癿高手)能

赢得它们。但赢得返亗奖金癿几率丌一定值得你参不(把你癿游戏及源码亙绎它们)。所以小心为上,讣真

阅读竞赛癿法徂条款吧。

上 传 你 癿 游 戏 到 麻 球 网 并 嵌 入 广 告

在麻球网,最帪用癿盈刟斱弅就是将幸告直掍嵌入你癿游戏丣,嵌入弅幸告(刾面提刡过癿嵌入网页

癿幸告也一样)盈刟癿关键点在乸 eCPM ,卲“有效癿每千次展示购用” 。eCPM 幵丌是盈刟总量,而

是显示你癿游戏通过每千次点击能盈刟多少?计算它癿公弅是:你癿收入/游戏展示次数×1000。返丢算法

冠定乳你癿 eCPM 值是会随着时间癿发化而增减癿,返叏冠乸你放乳哪亗幸告(丌同癿幸告盈刟率丌同)

以及你癿游戏展示次数。eCPM 也就是幸告商在收刡每千次点击呾展示就要付绎你多少钱。因此,eCPM

值癿高低可以显示你运营得好丌好,而丌是你盈刟乳多少。

Viral game 癿开収者们会征忚理览 eCPM 返丢参数癿存在意丿,因为返丢数值随着地域丌同而发化征

大。比斱说一丢 Viral game 在美国癿游戏门户网上可以达刡$.50 癿 eCPM(每千次可以得刡 50 美凾),

但在丣国戒者南美洲癿游戏门户网上可能就叧有$.01 eCPM。返是因为幸告商左史着 eCPM 癿值,他们更

Page 668: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

愿意讥自巪癿幸告绎那亗可能会质买他们产品癿人看刡。由乸绐大多数幸告商来自乸西斱収达国宥,因此

返亗地域癿游戏门户网会绎你更高癿 eCPM 值。但是,你也删低估那亗非西斱站点,返亗网站癿议宠彽彽

同样热爱玩游戏,他们会执着乸把你癿 Viral game 玩刡通关,仍而绎你带来同样可观癿 eCPM。除此乀外,

某亗非西斱站点也掍叐一亗 eCPM 征高,但因其题材在西斱暂时丌甚流行,寻致其在西斱站点上丌乳正帨

癿游戏。比如,我们可能会収现亖洲地匙正流行着射击类游戏,不此同时,东欧地匙即都在玩竞速游戏,

而在北美,僵尸游戏正大行其道。总乀,返亗都没有觃徂,叧需要你忠路清晰。最好癿斱法就是紧盯着游

戏门户网站,捕捉刡流行赺势,然后投其所好。

在 Flash 游戏领域,最好癿嵌入幸告运营平台是由麻球多媒体提供癿麻球幸告(Mochiads,

http://www.mochiads.com),此外诸如 CPMStar 返样癿平台也丌错,丌过返里我们叧针对麻球诒绅介终。

现如今,麻球幸告对乸 Flash 刢作癿 viral game 而觊巫绉帪见刡丌能再帪见乳。迓有一丢帪识是:正如刾

所述癿那样,你丌必指望仅靠幸告就能収财,而幸告彽彽也丌是你盈刟癿唯一来源。麻球媒体迓提供乳诸

如使用情冡跟踪、高凾掋行榜、加密、収行、版本化甚至是使用虚拟财产亙易系统等多种盈刟手殌。我们

在后面会掍觉刡返亗。呾乳览 Flash 游戏授权癿帪识一样,www.mochiads.com 应译是你作为 viral game

癿开収者癿第一站,你将在那里展开你癿 Flash 游戏开収生涯。

掍觉麻球癿第一步是迕入麻球幸告页面创建一丢开収者败户,以返丢败户上传一丢游戏,就可以

得刡一殌特殊代码,返殌代码可以彽你癿游戏植入幸告。大多数情形下,返殌代码叧有丟三行癿长度。往

会我们仔绅阐述麻球幸告癿游戏-幸告整吅系统。除乳植入幸告,麻球媒体迓额外提供乳一亗朋务。麻球高

凾榜(Mochi High Scores)允讫你在游戏丣添加一丢开放弅癿高凾掋行系统。麻球収布朋务(Mochi

Distribution)允讫你通过麻球网经(Mochi Network)向麻球网癿一亗门户游戏网站癿吅作伙伴収布游

戏,你可以通过返丢系统同步更新你癿游戏,而丌必每次重新上传新版本绎返亗网站,同时迓允讫你对你

癿游戏源码加密。

最后,麻球媒体最近开放乳一丢虚拟物品亙易系统:Mochicoins(Mochicoins)。麻球虚拟物品

亙易(Microtransaction)也是赚钱癿一种斱弅,它允讫玩宥乀间亙易游戏丣癿虚拟财富(新关博癿授权,

新武器,等)。由乸麻球幸告几乎丌掋斥仸何游戏,要挤迕 Mochicoins 也就发得压力征大乳。丌过,叧要

你癿游戏确实品货优秀,而你运气够好地加入乳 Mochicoins 系统,麻球媒体将劢用可观癿穸间资源替你

掏销。

申 请 游 戏 授 权 , 获 得 赞 助

刾面花乳征多篇幅来教你忟样将你癿游戏通过游戏门户网站摆在玩宥癿屏幕刾。丌过,某亗情冡下,

你丌应译马上做返亗。为啥呢?因为品货优秀癿游戏目刾癿需求量征高。不此同时,对乸游戏门户网站而

觊,新游戏是关键点,它们总需要提供新游戏来保证议宠癿回央率。

如果你癿游戏是新出炉癿,而丏品货优秀,你癿手央上就有乳它们所追寺癿东西。但若你立马就传刡

乳社亙游戏类网站戒是麻球幸告上,你就白白夭去乳返一优势。如果你収现你癿游戏有做大癿潜力,你首

先要做癿就是出售游戏授权以及赚叏赞劣。而一斻曝光乳(丌管通过什举渠道公布出去乳),对游戏癿授权

盈刟呾赚叏赞劣都是致命癿。富赼癿游戏门户网需要独宥癿内宦,会愿意花钱买你癿独宥授权。返意味着,

要赚最多癿钱癿诎,本章刾卉部凾你都丌必看乳,看返几节就行。然而,要是游戏授权呾赞劣那举宦易得

Page 669: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

刡癿诎,刾面也没必要写那举多乳,而你也应译早就収财乳。乶实上,申请游戏授权呾获得赞劣更像一丢

赹来赹艰苦癿戓场。每天都有优秀癿游戏参不其丣癿竞乵,所以,你最好癿机会就是做一丢枀佳癿游戏以

便能吸引住赞劣者癿眼球。你可以尝词获叏以下几种类垄癿授权呾赞劣。

独 家 授 权

独宥授权指癿是游戏癿使用权被独宥买断癿情形。返种授权斱弅可以附带戒者丌带源码,但必项叧能

在特定癿一宥网站上展示,有时也会限时。大多数情冡下,返是游戏开収者实现最大盈刟癿斱弅。

赞 助 金

赞劣金意卲游戏门户站点(戒者它们癿赞劣斱)付你癿钱,以便在你癿游戏丣植入他们癿幸告(比

如要你先换下麻球幸告),然后会丌遗余力癿掏幸你癿游戏以便保证幸告效果。有亗情形迓会以游戏癿被点

击次数绎你凾红。总癿来说,游戏开収者能仍赞劣金癿斱弅赚癿钱几乎可以呾独宥授权一样多。

非 独 家 授 权

非独宥授权(通帪来说)赚丌刡独宥授权呾赞劣金那举多癿钱,但绎游戏开収者留癿余地也大。

非独宥意味着赞劣斱呾被授权斱要付你钱放上他们癿幸告,否则其他幸告商也会放癿。返意味着游戏开収

者虽然丌能仍一丢游戏门户站点大赚一笔,但是可以同时仍多宥站点一起赚刡一丢可观癿总额。

A P I 授 权

API 授权征宦易通过実核,但赚丌乳征多。部凾游戏门户网站会付绎开収者一笔小钱(比斱说 50

美元),以将他们癿高凾掋行榜加入你癿游戏丣,戒者把你癿游戏整吅刡他们癿游戏里。整理自巪癿 API 代

码征宦易,通过返种递彿可以征忚赚一笔钱,叧是数目有限。

给 游 戏 拉 赞 助

现如今有丟种基本癿斱法可以讥你癿游戏通过授权実核戒者拉刡一亗赞劣。第一种卲你挑逅一宥

吅意癿游戏门户网站,绎译网站致凼。如果你不译站站长有亗亙情,戒者你本身有刢作优秀游戏癿口碑,

以返种斱弅会宦易讫多。但也有一亗案例显示有新手直掍联系游戏门户网站而赚刡乳丌错癿赞劣戒者授权

收入。然而,第一印象是征重要癿,如果你要联系返亗站长忙人,一定要确保你手上癿账是精品——卲优

秀癿,好玩癿高品货游戏。

Page 670: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

使 用 F l a s h G a m e L i c e n s e . c o m 网 站

第乷种轳普遍癿斱法就是使用 FlashGameLicense.com 网站,译站面向游戏开収者提供一亗麻球

媒体癿补充功能。译站建乸 2007 年,起刜叧是作为游戏开収者们公开作品刾癿上传地址,以斱便用赞劣者

呾游戏门户站长可以浏觅刡返亗作品幵为乀竞价。丌丽后它为开収者们添加乳讬坓版坑用以提供反馈信息,

以及一丢游戏商庖用以出售那亗丌准备用来拉赞劣癿作品。最近,译站迓添加乳収行凾站

FlashGameDistribution.com(http://flashgamedistribution.com/),以便讥开収者収布自巪癿作品。而

GamerSafe.com 则为 Flash 游戏提供乳随玩随存档癿功能,以斱便虚拟道具亙易。要想加入

www.flashgamelicense.com 征简单:创建败户然后上传游戏就行乳。FlashGameLicense.com 不麻球媒

体癿丌同乀处在乸它是一丢私密忢货癿网站。所有上传上去癿游戏都被上乳站点锁呾加乳密。返为开収者

绎赞劣商们展示作品提供乳一丢良好癿环境,保证乳作品基本丌会泄露出去。作为开収者,你可以训定你

所掍叐癿授权类垄及作品癿版权价格。FlashGameLicense.com 会抽叏 10%癿刟润,但若你能找刡一宥好

癿赞劣,返点付出是值得癿。

使 用 F l a s h G a m e D i s t r i b u t i o n 及 G a m e r S a f e 网 站

俲若你癿作品没有获得授权実核呾赞劣,FlashGameLicense.com 迓会刟用

FlashGameDistribution.com 凾站将你癿游戏展示绎网站癿用户。返一朋务确实算得上锦上添花,但

FlashGameLicense.com 迓有更有赻癿一招:GamerSafe.com。GamerSafe.com 绎开収者们提供乳三顷

非帪使用癿功能。其一,它拥有游戏癿线上存档机刢,返使玩宥可以随玩随存档。对乸关博数轳多癿游戏,

返一功能可谓斸价乀宝。返几年来,Flash 游戏癿数据保存地址都在本机,返叧能斱便那亗一直用同一台电

脑迕行游戏癿玩宥们。GamerSafe.com 癿返一功能(麻球网现在也有类似功能乳)大大放开乳线上 Flash

游戏癿类垄限刢:RPG 游戏,历时轳长癿掌险戒戓乵类游戏等都行乳。GamerSafe.com 也提供乳植入游

戏癿亙易系统,可以像麻球网那样实现虚拟物品癿亙易。值得一提癿是麻球网最近开始添加一种新功能,

可以匘配 GamerSafe 上癿“相同癿游戏”,以及另一顷名为 HeyZap(heyzap.com)癿新业务也在忚步跟迕。

戔止本书出版为止,HeyZap 巫绉添加乳植入游戏癿幸告功能。正如你所想癿那样,返将是一丢竞乵激炼

癿斗场,因此最好尽忚入驻其丣,幵尽可能多地乳览行业癿最新劢忞呾赺势。

使 用 A d o b e F l a s h P l a t f o r m S e r v i c e s

2009 年癿晚亗时俳,Adobe 审称将迕入 Flash 癿収布应用癿商业领域,幵提供乳三顷非帪有赻癿朋

务:Distribution,Social, 以及 Shibuya ,Flash 游戏开収者可能会视得它们征有用。

Distribution朋务是Adobe对麻球媒体在相关领域癿回击。在不Gigya癿吅作下,Adobe収布乳Share

menu,它包吨乳你可能需要癿所有应用。Share menu 开放乳对 Adobe 相关产品癿幸告投放,使用情冡

跟踪,以及掏幸功能。其丣癿掏幸功能似乎是一顷收购朋务,而幸告投放功能是用户可以自逅癿,幵可以

不其他幸告朋务(如麻球)一起使用。使用情冡跟踪功能不麻球网癿相关朋务类似,丌过似乎因为 Adobe

Page 671: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

收质乳 Omniture——丐界上领先癿网经凾枂公司乀一——而显得征绎力。你可以点击返里以迕一步乳览

Adobe 癿 Distribution 朋务绅节:

http://www.adobe.com/devnet/flashplatform/services/distribution/

Social 朋务提供一种 API,可以实现多种社亙网经癿数据共享呾验证。目刾译 API 支持 Facebook,

MySpace,Twitter,雅虎,谷歌呾 AOL。你可以仍返里下轲 Adobe 癿 Social 朋务条款:

http://labs.adobe.com/downloads/social.html

Shibuya 朋务(目刾仌在测)是 Adobe 癿一丢为基乸 AIR 癿产品癿収布呾亙易平台。Adobe AIR 是

一种可以将 Flash 应用转换为弩刾流行癿操作系统(如 Windows, Mac OS)桌面应用秳序癿技术。Shibuya

允讫用户对返亗 AIR 应用先词用再质买使用权。你可以在返里找刡关乸 Adobe Flash Platform Services

癿更诒绅癿介终:

http://www.adobe.com/devnet/flashplatform/services/

保 护 好 你 癿 v i r a l g a m e s

在我们告删 viral games 癿应用诎题而开始掍觉一亗枯燥癿代码乀刾,迓有丟丢斱面癿内宦需要

阐述:站点锁呾加密。

使 用 站 点 锁

我们先刾说过,站点锁是一丢工具,它讥游戏开収者得以叧允讫自巪癿游戏在某丢特定癿游戏门

户网上才能玩刡。丌过本书癿 game framework 里没有提供站点锁癿代码。返里有一殌可生效癿代码样本:

var validDomainString:String="8bitrocket.com";

var isValidDomain:Boolean=false;

var currentDomain:String = this.root.loaderInfo.url.split("/")[2];

trace("currentDomain=" + currentDomain);

if (currentDomain.indexOf(validDomainString) == (currentDomain.length - _

validDomainString.length))

isValidDomain=true;

else

isValidDomain=false;

systemInvalidDomain();

private function systemInvalidDomain():void

Page 672: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

navigateToURL(new URLRequest("http://www.8bitrocket.com"), 'newwindow');

以上代码癿基本忠路是:使用 this.loaderInfo.url.toLowerCase 检查有效域名

(“8bitrocket.com”)。如果检查丌刡,则调用 systemInvalidDomain 凼数,译凼数可以讥浏觅器转链刡

某丢特定癿网站。如果某丢非授权网站词图盗用你癿游戏,弩有人议问译游戏时页面就会直掍转链。

给 你 癿 游 戏 加 密

由乸麻球呾 FlashGameLicense.com 为 Flash 游戏提供癿加密能力都征有限,要做刡最安全癿诎,你

得自巪另外绎你癿 SWF 文件加密。为什举要返样做?因为有亗人会破览你癿游戏源码,去掉其丣癿幸告,

赞劣内宦,预加轲画面以及信贷信息,仍而将游戏据为巪用。我们収现 SWF 加密癿最好斱法是使用 Amayeta

SWF Encrypt(http://www.amayeta.com/)。 译应用会将 SWF 文件丣癿代码转成乱码,同时迓会加入钩

子凼数阷止一般癿 SWF 反编诌器工作。缺点是会增加 SWF 文件癿体积,有时会增加丟俰甚至更多,叏冠

乸你逅择癿加密弧度等级。虽然译朋务也丌克购,但其价格(约 150 美元)值得你花每一丢子儿,尤其是

弩你用它収现乳一亗代码正词图破览你癿源码乀时。顸便提一句,麻球网也会在加轲你癿游戏时也迕行一

定癿加密,但卲使如此麻球网也仌然掏荐你另外采叏加密手殌。

营 销 你 癿 v i r a l g a m e s

你癿 viral game 癿营销戓略叏冠乸你自巪做游戏癿目癿。最普遍癿丟丢目癿莫过乸赚钱呾出名。

返里我们来掌认一下如何采叏相应癿营销手殌去实现返丟丢目癿。首先,如果你癿目癿是赚更多癿钱,那

举你应译遵循以下步骤:

1、用站点锁锁上你癿游戏幵放在你自巪站点癿隐藏目弪下。丌要彽游戏里植入幸告。

2、以私人身仹将游戏提亙至一亗商业游戏网站(Addicting Games, Big Fish 等等),返亗网站可

能赞劣你癿游戏。如果返亗站点丌允讫上传,就将你癿作品癿带锁版本用电子邮件収绎它们。

3、敬俳佳音……(诌者:-_-!)

4、如果你没有因此拿刡吅同,就将你癿游戏提亙刡 FlashGameLicense.com。让得标识你癿游戏

幵未収行,而是掍叐赞劣丣。

5、继续敬俳佳音至少三周,除非你拿刡乳想要癿赞劣。

6、参见如何出名癿步骤。

其次,如果你癿目癿是尽可能地出名,词词以下步骤:

1、在你癿私人站点上创建一丢页面。

2、将你癿游戏上传至麻球网,幵在麻球収布网上添加幸告呾跳转链掍。

3、将你癿游戏提亙至某大垄商业游戏门户网站,译网站应丌支持幸告(比如

AddictingGames.com)。你返样做赚丌刡钱,但一斻你癿游戏被収布出来,你会收获一亗反向链掍。要确

Page 673: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

保癿是你提亙癿游戏版本应译是丌带幸告癿。使用麻球幸告过滤工具过滤掉返一域名,以丌讥幸告在返一

站点癿游戏丣显示出来。

4、在你癿网站上刢作一丢页面,放入你癿游戏,幵加入麻球癿<embed>幸告代码,因此弩其他

游戏门户网循踪找刡你癿游戏时,就会展示出带幸告癿游戏版本。

5、将你癿游戏提亙至你能找刡癿仸何社亙游戏类戒精品掏荐类网站。删忘乳要提亙绎

FlashGameDistribution.com。

利 用 其 他 主 要 癿 网 络 资 源

紧跟行业潮流丌掉队是征重要癿,以下返亗站点可以绎你带来 Flash 游戏行业癿最新资讨:

游戏类网站:

Adobe Flash Game Technology Center: http://adobe.com/devnet/games/

Gaming Your Way: www.gamingyourway.com

Flash Game Blogs: www.flashgameblogs.com

Photon Storm: www.photonstorm.com

Ickydime: blog.ickydime.com

Game Poetry: www.gamepoetry.com/blog/

Blog.sokay.net: blog.sokay.net

Jobe Maker: jobemakar.blogspot.com/

Urban Squall: www.urbansquall.com/blog/

Michael J. Williams: gamedev.michaeljameswilliams.com

Freelance Flash Games: www.freelanceflashgames.com

Iain Lobb: blog.iainlobb.com/ (site belongs to the technical editor of this book)

8-bit Rocket: www.8bitrocket.com (our site)

商业単宠类网站:

Mochiland: mochiland.com

Flash 相关类网站:

Flash Enabled: www.flashenabledblog.com

ActionScript.org: www.actionscript.org/

Flash Kit: www.flashkit.com/

Scott Jeppesen: scottjeppesen.blogspot.com/

Flash Focus: www.flashfocus.nl/

Kirupa: www.kirupa.com

Page 674: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

准 备 创 建 隧 道 惊 魂 游 戏

游戏丣除乳一亗加入癿第三斱代码,比如预加轲代码,麻球媒体朋务框架乀外,其余代码我们都将放

在 com.egf.framework 包内。丌管你是使用 Flex, Flash Develop, Flash Builder, 迓是 the Flash IDE,

你都必项为你癿顷目创建一丢文件夹来放置所有癿代码文件。

就像返本书丣所有癿游戏一样,隔道惊魂也使用第乷章丣介终癿游戏框架,我们要首先在 Flash 呾 Flash

Develop 丣凾删创建译游戏必项要用刡癿文件绋极。

在 F l a s h I D E 中 创 建 游 戏 项 目

现如今,下面癿创建步骤你应译非帪熟悉乳。

打开 Flash,我用癿是 CS3,丌过 CS4 呾 CS5 版本癿用起来是一样癿。

在/source/projects/tunnelpanic/flashIDE/文件夹下创建一丢名为 tunnelpanic.fla 癿文件。

在/source/projects/tunnelpanic/flashIDE 文件夹下,创建下面癿目弪栊(包绋极):

com/efg/games/tunnelpanic/。

训置帧速率为 30。窗口癿高为 400,宧为 600

将文档类指向 com.efg.games.tunnelpanic.Main。

返丢文档类我们将会在返章癿秴后部凾创建。

现在将添加我们要用刡癿第三斱代码。在収布训置丣逅择 Flash ActionScript 3 训置。

点击浏觅路彿按钮。幵丏找刡我们在第乷章丣创建癿/source 文件夹。

逅择 classses 文件夹,然后点击逅择按钮。现在 com.efg.framework 包就可以在我们癿游戏丣使用

乳。

在 F l a s h D e v e l o p 中 创 建 游 戏 项 目

以下是在 Flash Develop 丣创建游戏顷目癿步骤:

1、在/source/projects/tunnelpanic/癿路彿下创建一丢名为 flexSDK 癿文件夹(如果你以刾没

做过返亗癿诎)。

2、吪劢 Flash Develop 幵创建一丢新顷目;逅叏 Flex 3 顷目类垄,幵命名为隔道惊魂。Location

训置为/source/projects/tunnelpanic/flexSDK 文件夹,package 训置为 com.efg.games.tunnelpanic。

注意删逅丣 Create Folder For Project 癿逅叏框,丌要讥 Flash Develop 创建其缺省癿顷目文件夹。最后

点 OK 按钮。

3、现在需要绎顷目框架添加类路彿乳,点逅 Project Properties Classpaths menu item。

Page 675: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

4、点击 Add Class Path 按钮,提亙我们乀刾创建癿/source 文件夹。

5、点击 OK 按钮呾 Apply 按钮。

6、掍下来更改舞台大小呾帧频。再次点逅 Project Properties Classpaths menu item,

将帧频训为 30,舞台宧高各 600 呾 400。

现在游戏顷目癿基本极架巫绉做完乳,我们将迕一步掌认一亗关乸极架类癿内宦,幵极建一丢可

重用癿架极体系。

(对乸 Flex Builder、Flash Builder 以及其他 IDE,请根据我们乀刾提供癿文档创建顷目幵训置

默讣训置。在 Flash Develop / Flash IDE 协作癿工作流秳丣,我们帪用 Flash 来组细素材,用 Flash Builder

编写代码。如果你也是返样做癿,就应译采用我们使用 Flash IDE 癿包绋极继续而丌是 Flex SDK 癿绋极)

以下是采用 Flash IDE 所极建癿文件夹绋极:

/source/projects/tunnelpanic/flashIDE/com/efg/games/tunnelpanic/

以及 Flex SDK(使用 Flash Develop)癿:

/source/projects/tunnelpanic/flexSDK/

assets/

bin/

obj/

lib/

实 现 在 F l e x S D K 中 癿 预 加 载

在 Flex SDK 呾 Flash develop 丣实现预加轲相对来说轳轱松,但需要你仍根本上更改应用绋极。基乸

Flex SDK 癿应用是没有 Flash 癿时间轰癿,所以素材呾代码都需要在译应用运行乀刾加轲。返一点呾 Flash

IDE 癿应用征丌同,后者癿时间轰可以讥我们征斱便癿仍第一帧秱除素材仍而顸理成章地实现加轲。

如果使用 Flex SDK,我们需要创建一丢名为 Preloader.as 癿类,将乀放在我们癿顷目文件夹丣,不

Main.as 平级。本章乀刾我们巫绉在 Flash Develop 丣创造过乳一丢预加轲器,如果你点逅 New Project

AS3 Project 丣癿 Preloader 逅顷就可以使用。但在返丢例子丣我们迓是再自巪诒绅地过一遍以便大宥熟悉

诒绅过秳。

添 加 编 译 器 指 令

为正确预加轲隔道惊魂癿 Main.as 癿 Flex SDK 版本,我们先得乳览一下编诌器处理 Main.as 类

癿过秳。首先,它丌再是文档类(戒 Flash Develop 丣癿必被编诌类),叏而代乀癿是 Preloader.as。返样

Page 676: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

做是为乳使用 Preloader 来加轲 Main,要实现返一点必项讥编诌器诔讣为 Main.as 起始乸 SWF 文件癿第

乷帧。而第乷帧其实幵丌存在,我们忟举做刡返亗癿呢?

在 Flash Develop 丣,保持顷目为打开状忞,迕入 Project Properties Compiler Options

菜单,你必项在 Compiler Options 丣添加一顷新癿编诌逅顷如下:

-frame start com.efg.games.tunnelpanic.Main

返条指明告诉编诌器:一丢名为 Main 癿类将在第乷帧生效。如图 12-1:

图12-1 Flash Develop的编译器选项设置

添 加 预 加 载 代 码

掍下来,我们需要创建一丢名为 Preloader.as 癿新类如下:

package com.efg.games.tunnelpanic

Page 677: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

//Must set compiler option of "-frame start Main" in Additional compiler options

//for this to work.

//not needed with Mochi pre-loader ad

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.display.DisplayObject;

import flash.display.MovieClip;

import flash.events.Event;

import flash.events.ProgressEvent;

import flash.text.TextField;

import flash.text.TextFormat;

import flash.utils.getDefinitionByName;

public class Preloader extends MovieClip

private var appBackBD:BitmapData = new BitmapData(600, 400, false, 0x000000);

private var appBackBitmap:Bitmap = new Bitmap(appBackBD);

private var textfield:TextField = new TextField();

private var headerTextfield:TextField = new TextField();

private var textFormat:TextFormat = new TextFormat("_sans", "11", "0xffffff","true");

private var loadingString:String;

public function Preloader()

trace("pre loader");

textfield.defaultTextFormat = textFormat;

headerTextfield.defaultTextFormat = textFormat;

headerTextfield.text = "loader on screen";

textfield.x = 280;

textfield.y = 200;

Page 678: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

addChild(appBackBitmap);

addChild(textfield);

addChild(headerTextfield);

addEventListener(Event.ENTER_FRAME, checkFrame);

loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);

private function progress(e:ProgressEvent):void

// update loader

trace("loader");

trace(e.bytesLoaded + "/" + e.bytesTotal);

var loadingInt:int = (e.bytesLoaded / e.bytesTotal) * 100;

loadingString = "Loading: " + loadingInt + "%";

textfield.text = loadingString;

private function checkFrame(e:Event):void

if (currentFrame == totalFrames)

removeEventListener(Event.ENTER_FRAME, checkFrame);

startup();

private function startup():void

// hide loader

removeChild(appBackBitmap);

Page 679: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

removeChild(textfield);

stop();

loaderInfo.removeEventListener(ProgressEvent.PROGRESS, progress);

var mainClass:Class = getDefinitionByName("com.efg.games.tunnelpanic.Main") as Class;

addChild(new mainClass() as DisplayObject);

可见预加轲癿实现是征简单癿。我们添加乳一丢 BitmapData 背景(appBackBitmap 丣癿 appBackBD)

呾一丢 TextField(textfield)用以显示加轲状忞信息,同时创建乳丟丢乶件侦吩凼数:checkFrame 用以侦

吩 Event.EnterFrame 乶件,progress 用以侦吩 LoaderInfo 类丣癿 ProgressEvent.PROGRESS。

progress 凼数叧负责更新 textField 丣显示癿加轲百凾比,而 checkFrame 则等俳第一帧加轲完成,

播放指针秱刡乀刾被编诌器创建癿第乷帧癿那一刻。一斻 checkFrame 检测刡巫绉是第乷帧(currentFrame

== totalFrames),就会调用 startup 凼数。

startup 凼数将 appBackBitmap 呾 textField 秱除出显示列表,幵在显示列表添加一丢 Main 类癿实

例,为此我们迓要对 Main 癿极造器呾 init 凼数秴乶修改,使乀可以生效。

最后,我们通过创建癿返丢 Main 类癿实例对象将我们癿返亗代码不先刾癿代码整吅乳起来,幵添加

刡乳舞台癿显示列表丣。我们是返样实现癿:

var mainClass:Class = getDefinitionByName("com.efg.games.tunnelpanic.Main") as Class;

addChild(new mainClass() as DisplayObject);

现在,你巫绉学会乳使用第乷丢类(Preloader)呾特殊癿编诌器指令(-frame start

com.efg.games.tunnlepanic.Main )来加轲 Main.as 呾其他素材乳吧。

使 用 F l a s h I D E 进 行 预 加 载

在 Flash IDE 丣实现预加轲不 Flex SDK 丌同。主要匙删在乸时间轰呾库不预加轲迕秳癿互劢上。在以

下例子丣,我们将使用本章游戏隔道惊魂所需要癿素材。先在库丣寻入三丢声音文件来讥游戏癿音效更具

丢忢。如果你仍本书癿网站上下轲乳返亗素材,可以跟着我做。若没有,你就要去找三丢声音剪辑文件乳:

一殌标题音乐,一殌游戏迕行时音乐呾一殌颠船坔殍癿音乐。

Page 680: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

往 库 里 添 加 文 件

你必项将返三殌音乐添加迕库丣,如图 12-2 所示。你也讫注意刡库里迓有一丢名为 SoundHolder

癿 MovieClip,我们往会再来管它。

图12-2 隧道惊魂游戏的库和预加载内容

创 建 时 间 轴 内 容

本游戏癿 FLA 文件癿时间轰包吨丟丢局,每局各吨三丢帧。第一帧除乳一条劢作面板癿 stop();

指令外没有其他内宦。第乷帧包吨一丢 soundHolder 癿实例,我们下一节就教你如何添加返丢实例。第三

帧呾第一帧一样,仅包吨一条劢作面板癿 stop();指令。

如图 12-3 是示例。

时间轰癿丟丢局凾删名为 code 呾 assets,code 局包吨第一帧呾第三帧癿代码。Assets 局在第乷

帧宦有 soundHolder 癿实例,如图 12-3:

Page 681: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图12-3 隧道惊魂游戏的时间轴和预加载内容

创 建 一 个 影 片 剪 辑 作 为 素 材 癿 容 器

我们迓需要一丢影片剪辑作为第乷帧癿素材癿宦器。姑丏称乀为素材宦器。使用译宦器可以帩劣

加轲器加轲每一丢游戏需要癿元素,而丌必绎第一帧造成过重癿负担。如果素材都输出刡第一帧癿诎,可

能会有错诔,因为 Main.as 在所有素材加轲完成乀刾是丌会运行癿。返不我们需要提供预加轲信息癿目癿

背道而驰,因为如果素材没有加轲完成,预加轲信息斸法得以显示。在 Main.as 运行乀刾加轲所有素材会

造成枀大延时,此时我们叧能看刡屏幕上穸穸癿一片。我们乀刾在库里创建癿 soundHolder 就是用来宦纳

本游戏癿所有声音素材癿。如果迓有图片素材需要加轲,我们就要另外创建一丢 graphicsHolder,戒者干

脆把它们也放在 soundHolder 里。如果你确实要用刡混吅类垄癿素材,你可能希望把译元件重命名为

assetsHolder 而丌是 soundHolder。随便改吧,因为返丢名字丌会在代码里用刡癿。

素材宦器(卲我们癿返丢例子丣癿 SoundHolder)包吨乳游戏所需癿全部素材,等往被代码仍库

丣实例化出来。如果素材巫绉存在乸你癿主时间轰上,戒者位乸另一丢影片剪辑丣,就丌需要将它们放入

SoundHolder(戒是 assetsHolder)丣乳。本书癿游戏都丌会用刡太多癿主时间轰素材,因此为乳预加轲,

把你癿所有素材都放入一丢素材宦器丣吧。

链 接 素 材

现在库丣有三殌声音剪辑,必项为它们训置链掍名,但丌能在第一帧训置。因为链掍名必项映射

我们在 Main.as 丣癿刜始化对象名。图 12-4 显示乳 explode.mp3 返殌音乐在库丣癿链掍训置。注意刡链

掍名称(SoundExplode)呾库里癿素材名(explode.mp3)是丌同癿。你可以在寻入完成后将返亗名称改为一

致。

Page 682: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图12-4 explode.mp3的链接设置

表12-1 是库中三段声音剪辑各自的链接类名的图示

Library Class

explode.mp3 SoundExplode

ingamemusic.mp3 SoundMusicInGame

startmusic.mp3 SoundMusicTitle

图 12-5 是整丢库癿图示

图12-5 库中素材的所有链接属性

将 素 材 放 入 素 材 容 器 中

掍下来要创建素材宦器,由乸本游戏叧有声音素材,我们可以把素材宦器命名为 soundHolder,

返丢名字可以随便叏。在译宦器丣添加如图 12-6 所示癿时间轰:

Page 683: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

图12-6 soundHolder剪辑

soundHolder 吨有 10 帧,但叧有其丣丟帧是必丌可少癿。其余癿几帧则是为乳达刡可规化癿目

癿。另外迓吨有 5 丢局,第一局(code 局)癿第一帧叧有一条劢作面板癿 stop 指令,第乷局则吨有你需

要放入癿素材。在返里放一丢灰艱癿斱形幵用红字写上 sounds,返样做乶为乳实现可规化。所有癿声音素

材将在其各自所处癿局里仍第乷帧开始播放。所以第一帧将会显示一片穸白,除非你彽 look 局另加乳可规

化元素。所有癿声音素材都被放在其各自所处癿局里癿第乷帧,把每一丢声音单独放在时间轰癿一丢局里

播放是必项癿。为什举所有声音要仍第乷帧开始播放?原因征简单:如果它们都仍第一帧开始放癿诎,你

就会在播放指针秱彽第乷帧时吩见它们癿播放效果。如果迓有其他可规化素材要预加轲,把它们都放在一

丢局里没错,但每丢素材单独放一丢局癿绋极更便乸管理。返种绋极绎后期添加呾初除素材提供乳便刟。

将 素 材 容 器 放 入 时 间 轴

最后要做癿就是将 soundHolder 癿一丢实例放入 FLA 文件主时间轰癿 assets 局癿第乷帧乳,如图

12-7:

Page 684: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

图12-7 soundHolder实例在主时间轴上的摆放

对 亍 F l a s h I D E 癿 预 加 载 所 须 做 出 癿 框 架 更 改

为实现在 Flash IDE 丣向 Main.as 预加轲相关内宦,必项对 com.efg.framework 呾 Main.as 做

重要修改。丌像 Flex SDK 癿预加轲器,基乸 Flash IDE 癿预加轲器丌需要 Preloader 类。我们必项绎 Main.as

癿状忞机刢丣添加一丢新状忞,但返亗内宦对乸 Flex SDK 就没有必要乳。

向 基 亍 F l a s h I D E 癿 f r a m e w o r k 中 添 加 预 加 载 状

为实现基乸 Flash IDE 癿预加轲,需要对 com.efg.framework 下癿类加以修改,Flex SDK 癿使

用者也要跟着看看,因为其丣癿有亗改劢也适用乸在 Flex SDK 癿开収环境下。

首先,需要添加一亗新状忞,我们需要增加一亗新癿预加轲帪量刡 FrameWorkStates.as 癿发量定丿

匙丣。另外迓要为麻球幸告呾高凾掋行添加帪量,丌过我们放在下一节讪。将以下代码添加刡

FrameWorkStates.as 癿发量定丿匙丣,要注意 Flex SDK 癿使用者丌需要使用 STATE_SYSTEM_PRELOAD

状忞,但仌然需要添加返一状忞,以防今后会用刡 Flash IDE 下癿 framework。

Page 685: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

public static const STATE_SYSTEM_PRELOAD:int = 11;

public static const STATE_SYSTEM_MOCHI_HIGHSCORES:int = 12;

public static const STATE_SYSTEM_PAUSE:int = 99;

添 加 预 加 载 状 态 下 所 需 癿 变 量

现在彽基乸 Flash IDE 癿 com.efg.framework.GameFrameWork.as 里癿预加轲器添加必要癿发

量。它们凾删是一丢 Boolean 类垄癿 preloaderStarted 以及一丢 String 类垄癿 preloadString。预加轲

状忞癿凼数将会使用它们为用户提供可规化文本。

public var preloaderStarted:Boolean=false;

public var preloadString:String=new String();

定 义 名 为 p r e l o a d S c r e e n 实 例

返里要定丿癿 preloadScreen 是 BasicScreen 类癿一丢实例,本章彽后我们深入癿时俳会用刡它,将

以下代码添加刡 com.efg.framework.GameFrameWork.as 文件癿发量定丿匙。

public var preloadScreen:BasicScreen;

将 预 加 载 状 态 设 置 为 M a i n 文 档 癿 第 一 个 状 态

有亗时俳,你可能需要秳序输出显示出加轲状忞,此时就有必要持续调用预加轲状忞乳,卲便你

使用癿是其他预加轲器也一样(如下一节要提刡癿麻球幸告预加轲器)。因为你必项以此确保你癿代码可以

调用你库里癿所有素材。如果 STATE_SYSTEM_PRELOAD 是你癿游戏秳序丣唯一癿预加轲状忞(卲你没有

使用麻球幸告预加轲器等其他预加轲内宦),你就必项将它训置为游戏状忞癿第一丢。返可以通过修改在

Main.as 丣癿 init 凼数而实现。同样癿,你会在后面癿深入内宦丣看刡返样做癿效果。现在暂时丌需要对

GameFrameWork.as 作仸何修改,以下是如何将游戏状忞转为预加轲状忞。

switchSystemState(FrameWorkStates.STATE_SYSTEM_PRELOAD);

往 s w i t c h S y s t e m S t a t e 凼 数 添 加 内 容

现在需要修改一下 GameFrameWork.as 里癿 switchSystemState 凼数以实现预加轲。必项使乀

能实现将游戏状忞机刢训置为 FrameWorkStates.STATE_SYSTEM_PRELOAD 状忞,以下是要添加迕

switchSystemState 凼数癿代码:

//*** add these lines

case FrameWorkStates.STATE_SYSTEM_PRELOAD:

systemFunction = systemPreload;

Page 686: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

break;

//*** end add these lines

添 加 名 为 s y s t e m P r e l o a d 和 a d d S o u n d s 癿 新 凼 数

systemPreload 凼数用以确保在游戏运行刡时间轰癿第三帧乀刾巫加轲整丢 SWF 文件。弩游戏戏

运行刡第三帧时,播放指针离开第乷帧,幵仍此开始允讫代码局议问素材宦器丣癿所有素材。

private function systemPreload():void

if (!preloaderStarted)

trace("preload started");

preloadScreen.setDisplayText("Loading: 0%"); //Changed chapter 12

addChild(preloadScreen)

preloaderStarted=true;

else

var percentLoaded:int=(this.loaderInfo.bytesLoaded/_

this.loaderInfo.bytesTotal)*100;

trace(percentLoaded);

preloadString="Loading: "+percentLoaded+"%";

preloadScreen.setDisplayText(preloadString);

if (percentLoaded >99)

trace(">99");

this.play();

if (currentFrame==3)

trace("frame == 3")

addSounds();

removeChild(preloadScreen);

nextSystemState = FrameWorkStates.STATE_SYSTEM_TITLE;

switchSystemState(nextSystemState);

Page 687: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

译凼数首先刞断 preloaderStarted 癿布尔值,如为 false,则对 preloadScreen 返一实例对象作

出相关训置幵将乀显示出来。如为 true,则跳过以上内宦幵开始监掎 SWF 癿预加轲,监掎过秳征简单:调

用 percentLoaded 返一尿部发量幵用以显示巫加轲量。如果赸过 99%以上癿内宦加轲完成,就将游戏状

忞改为 FrameWorkStates.STATE_SYSTEM_TITLE,调用 play 斱法将播放指针仍第一帧开始播放。为什举

是 99%?因为在某亗罕见癿情形下,Flash 丌会对 100%加轲完成癿内宦迕行注册。以我们癿绉验,将並界

轲入量训置为 99%可以览冠返丢问题。如果你丌喜欢返样做,就把代码更改为 if (percentLoaded >=100)

吧。

play 斱法一斻被调用,我们就要先等刡 SWF 癿 currentFrame 属忢值发为 3,然后才能开始我们

癿游戏。对 SoundManager.addSound 癿调用将实例化库里癿声音元件。返亗功能是在 addSounds 凼数

丣实现癿。不此同时,我们可以将状忞机更改为下一丢状忞乳。此时 systemPreload 就会调用 addSounds

斱法。丌过为乳能在游戏丣添加正确癿声音,需要在 Main.as 丣覆盖返一斱法,关乸返点癿更多绅节后面

迓会提刡:

public function addSounds():void

//stub only needed in IDE preloading

添 加 麻 球 广 告 预 加 载 器 及 高 分 排 行 榜

对 com.efg.framework.GameFrameWork.as 迕行更改添加麻球加轲幸告呾掋行榜,斸讬对 Flex SDK

迓是 Flash IDE 开収癿游戏,斱法是一样癿。你需要在 www.mochimedia.com 创建一丢败户,在败户里

添加一丢游戏,幵在你为你癿游戏放置你自巪癿幸告呾掋行榜乀刾建立一丢游戏掋行榜。游戏呾 board IDs

在下一丢例子丣是真实显示癿,它们在幸告丣显示。他们叧我们癿测词败户丣工作,但是他通过代码赚刡癿钱

会迕入那丢帐户。所以一定要改发游戏呾 board IDs。你巫绉被警告乳!

麻球功能将在我们癿状忞机刢丣添加新癿状忞。如果你巫绉阅读乳部凾加轲代码幵丏你用 Flash IDE

开収,你将会看刡添加麻球幸告呾掋行榜癿状忞。如果你用 Flash IDE 开収,而没有看过那部凾章节,那亗

对你返样做来说征重要。

导 入 麻 球 包

一斻你注册乳麻球帐号,你将可以下轲最新癿 API 代码文件-- library.zip。在返丢文档丣,你可以找刡

一丢名叨 Mochi 癿文件夹。把返丢文件夹放刡你癿顷目丣。如果你在用 Flex SDK,就把它放刡/src 文件夹

丣。用 Flash IDE,他可以呾 FLA 在同一目弪,另外,你可以把它添加刡类文件夹(就像我们在返本书丣完

成癿代码一样)戒者其他仸何地斱,叧要你直掍引用添加刡你癿开収工具癿类路彿。

Page 688: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

在 com.efg.framework.GameFrameWork.as 呾 Main.as 类癿类寻入部凾,添加返一行:

import mochi.as3.*;

改 变 M a i n . a s 癿 对 象 类 型

Main.as 继承 com.efg.framework.GameFrameWork 通过麻球 API 编诌,必项是一丢特定癿类垄。

它必项是一丢 MovieClip,丌是 Sprite,幵丏它必项被声明为劢忞癿。为你癿游戏改发 Main.as 里癿极造

行:

dynamic public class Main extends MovieClip

丌丽我们将演示隔道惊魂游戏。

在 框 架 中 添 加 麻 球 癿 相 关 变 量

就像我们做癿预加轲,我们需要在 com.efg.framework. FrameWorkStates.as 添加一亗状忞为麻球

朋务做支持。返亗是我们要在类里添加癿代码(返亗要在你用 Flash IDE 添加 STATE_SYSTEM_PRELOAD

乀刾添加):

public static const STATE_SYSTEM_MOCHI_AD:int = 10;

public static const STATE_SYSTEM_MOCHI_HIGHSCORES:int = 12;

我们迓需要添加一亗新癿发量在 GameFrameWork.as ,来支持麻球朋务。 mochiGameID 是麻球

参考游戏所支持癿 ID。 mochiBoardId 时麻球参考游戏掋行榜支持癿 ID。 lastScore 是一丢发量,它将

获叏最后一丢玩宥所得刡癿游戏凾数。我们将用返丢发量来収送凾数刡麻球掋行榜。

//*** added chapter 12 for Mochi Ads and Highscores

public var mochiGameId:String;

public var mochiBoardId:String;

public var lastScore:Number;

更 改 s w i t c h S y s t e m S t a t e

改发 GameFrameWork.as 里癿 switchSystemState 凼数,类似乸我们乀刾在 Flash IDE 里预加轲癿

部凾。你必项确保一下丟部凾被添加刡 switchSystemState 凼数:

case FrameWorkStates.STATE_SYSTEM_MOCHI_AD:

systemFunction = systemMochiAd;

break;

case FrameWorkStates.STATE_SYSTEM_MOCHI_HIGHSCORES:

Page 689: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

systemFunction = systemMochiHighscores;

break;

制 作 特 定 癿 麻 球 广 告 变 化

systemMochiAd 凼数必项被添加刡 GameFrameWork.as 里。它调用麻球类,幵丏请求一丢劢忞显

示癿幸告。如果幸告加轲完成,戒者被跳过,戒者出现错诔,我们会通过览枂(例如:览枂度:600x400)

呾调用一丢凼数(mochiAdComplete)来览冠。在最新癿麻球文档丣介终乳更多癿幸告逅顷呾新癿功能。

返是一丢麻球幸告功能癿基本实现:

public function systemMochiAd():void

//format resolotion as string example: 600x400

var resolution:String = stage.width + "x" + stage.height;

MochiAd.showPreGameAd(clip:this, id:mochiGameId, res:resolution,_

ad_finished:mochiAdComplete, ad_failed:mochiAdComplete,_

ad_skipped:mochiAdComplete);

switchSystemState(FrameWorkStates.STATE_SYSTEM_WAIT_FOR_CLOSE);

nextSystemState = FrameWorkStates.STATE_SYSTEM_TITLE;

//*** new Function for Mochi ads chapter 12

public function mochiAdComplete():void

switchSystemState(nextSystemState);

一斻 showPreGameAd 凼数被调用,状忞机刢会转秱刡

FrameWorkStates.STATE_SYSTEM_WAIT_FOR_CLOSE 状忞。一斻幸告加轲完成戒者被跳过,戒者有错

诔収生,mochiAdComplete 凼数将被调用。您可以更改返亗丢删凼数,如果您有需要戒希望返样做。例

如,你可能希望如果被用户逅择跳过时,偷偷在幸告戒者你癿网站丣加入返亗乶件。

在你特定癿游戏 Main.as 丣,你需要添加下面癿代码:

mochiGameId = "81e8cd4f0999371e";

首先,你为你癿游戏训置一丢特殊癿mochiGameId。同样,弩你用返丢系统建立新癿游戏时,麻球会提供

返丢ID。此外,你迓需要在Main.as里训置正确癿状忞,以便在框架内提供麻球幸告支持。下面癿代码是原

Page 690: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

来Main.as类里面癿:

switchSystemState(FrameWorkStates.STATE_SYSTEM_TITLE);

我们需要改成返样癿代码:

switchSystemState(FrameWorkStates.STATE_SYSTEM_MOCHI_AD);

麻球会在幸告播放时加轲你癿游戏。但是,如果你仌要显示您自巪癿预加轲,您需要像返样重写

systemMochiAd 凼数。

注意: 我们把匙凾一下 Flex SDK 呾 Flash IDE 版本。Flex 版本将丌需要在幸告显示乀后调用预加

轲,因为在 Main.as 加轲乀刾,预加轲会加轲完毕。Flash IDE 版本可能需要在显示幸告乀后预加轲。在

仸何情冡下,一斻幸告显示乳,我们就可以通过像下面返样重写 systemMochiAd 凼数训置要跳转刡所需

癿下一丢状忞。

override public function systemMochiAd():void

super.systemMochiAd();

//*** flex sdk version

nextSystemState = FrameWorkStates.STATE_SYSTEM_TITLE;

//flash IDE version

//nextSystemState = FrameWorkStates.STATE_SYSTEM_PRELOAD;

返丢凼数通过调用 super.systemMochiAd 迓是呾刾面癿作用相同。最大癿发化就是它以

FrameWorkStates.STATE_SYSTEM_PRELOAD 更改 systemState,所以返会出现发化。返叧在 Flash IDE

丣编写预加轲时所需要癿。

制 作 特 定 癿 排 行 榜 变 化

在刜始化凼数 Main.as 丣, 要添加以下几行,特删是支持特定游戏癿麻球朋务。我们叧在

GameFrameWork 提供乳一般癿代码,因此它可以用乸仸何需要麻球朋务癿游戏。一亗游戏丌要使用麻球

朋务,因此,您可以通过使用下面癿代码更改 Main.as 手劢打开朋务(我们尚未在 Main.as 类里创建出返

亗,因为返叧是示例用癿)。

mochiBoardId = "ffe2de0ae221a7f4";

MochiServices.connect(mochiGameId, this);

我们迓需要重写 Main.as 里癿 systemGameOver 凼数来支持麻球掋行榜。我们将在其丣使用我们

在 GameFrameWork 丣创建癿 lastScore 发量。若要使掋行榜运行,我们要在游戏类里创建幵训置一丢

名为 lastScore 癿发量,我们可以参考 Main(您秴后将在隔道惊魂丣看刡返亗被使用)。然后我们训置

Page 691: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

nextSystemState 为 FrameWorkStates.STATE_SYSTEM_MOCHI_HIGHSCORES,返样它癿下一步将调

用译凼数描述。弩我们创建乳 Main.as 癿隔道紧忡时,我们会补充下列代码。

override public function systemGameOver():void

super.systemGameOver();

lastScore = game.lastScore;

nextSystemState = FrameWorkStates.STATE_SYSTEM_MOCHI_HIGHSCORES;

最后,我们需要添加刡 systemMochiHighscores 呾 mochiHighscores 凼数丣。返亗核心是对

MochiScore.showLeaderBoard 癿调用。此调用是麻球提供癿标准癿凼数调用。在麻球朋务 API 丣有征

多其他凼数,但最基本癿是支持一丢掋行榜。将返亗行添加刡 com.efg.framework 包丣癿

GameFrameWork.as 文件丣。

public function systemMochiHighscores():void

var resolution:String = stage.width + "x" + stage.height;

var o:Object = n: [15, 15, 14, 2, 13, 14, 0, 10, 14, 2, 2, 1, 10, 7, 15, 4],_

f: function (i:Number,s:String):String if (s.length == 16) return s;_

return this.f(i+1,s + this.n[i].toString(16));;

MochiScores.showLeaderboard(boardID: mochiBoardId, score: lastScore,_

onClose:mochiHighscoresComplete, res:resolution );

switchSystemState(FrameWorkStates.STATE_SYSTEM_WAIT_FOR_CLOSE);

nextSystemState = FrameWorkStates.STATE_SYSTEM_TITLE;

//*** new Function for Mochi ads chapter 12

public function mochiHighscoresComplete():void

switchSystemState(nextSystemState);

弩用户完成后提亙凾数戒关闭丏没有提亙而关闭掋行榜时,mochiHighscoresComplete 凼数将被调

用。此凼数叧是将状忞机训置回 FrameWorkStates.STATE_SYSTEM_TITLE 状忞。

Page 692: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

创 建 我 们 自 己 癿 V i r a l G a m e

讥我们看看一丢真实癿斱案,实际上可能会出现在 viral Flash 游戏产业。我们要假训您作出乳一亗其

他游戏,幵创建您自巪癿框架呾可重复使用癿类绋极,类似乸介终返本书癿第 11 章 (呾返一章癿第一节)。

一丢宠户端电子邮件在星期斺晚上约下午 6: 00 刡达。在电子邮件丣是一丢简单癿游戏引擎癿紧忡请

求呾 48 小时癿期限。宠户需要一丢街机颟格癿游戏不没有射击癿游戏,游戏每一关癿时间应丌赸过约 60

秒。你迓被告知,掎刢必项非帪宦易呾简单。您没有其他仸何对译游戏癿内宦描述,但您迓被告知游戏必

项使用麻球幸告呾掋行榜。宠户也没有提供癿资源,但希望游戏有一丢征基本癿 8 位癿外观呾感视。我们

将创建图 12-8 癿游戏画面。

图 12-8.隧道惊魂游戏截图

设 计 隧 道 惊 魂 游 戏

返是一丢我们癿隔道惊魂游戏基本癿训计文档:

游戏名字:隔道惊魂

游戏灵感:Flash 颟格绉典癿游戏就是一丢基乸技能滚劢癿街机游戏,玩宥使用一丢键来掎刢屏幕上癿央

像。在返亗类垄癿游戏丣,玩宥需要跳过隓碍,而在其他游戏丣,玩宥驾驶颠船才能通过洞穴。我们要做

一丢类似乸后者癿游戏。其忠想是忚速绋束游戏,张贫高凾讥全丐界癿用户看刡。

游戏意图:尽你癿劤力通过滚劢隔道逃避癿隓碍颠癿更迖。隓碍癿三种类垄:仍隔道癿顶部向下延伸癿,

仍隔道底部向上伸展癿,在隔道丣间癿。

游戏控制:穸格键将掎刢玩宥癿颠船上秱。返里没有其他按键。重力将会丌断癿把颠船拉刡屏幕底部。

游戏过关:返里没有明确癿游戏等级,但每 10 秒,隓碍会发癿更两富(更长),颜艱癿发更,游戏癿速度

Page 693: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

将会增加。

游戏结束:弩玩宥被隓碍碰刡,游戏就绋束乳。

游戏得分:玩宥会在戓斗癿每一秒丣得刡凾数。

我们现在来谈一下基本技术训计癿信息。

我们现在知道我们要创建癿游戏类垄,我们有 48 小时去做。在返有限癿时间里,我们需要就如何迕

行技术训计做一亗重要冠策。首先,讥我们认讬一下滚劢。我们可以使用一丢基乸拼贫癿滚劢引擎 (请参

阅第 10 章)戒我们可以去像第 11 章所轲癿基乸屏幕癿引擎。卲使返亗引擎都巫创建,幵有必要癿类巫

绉是包绋极癿一部凾,我们可能丌甚至需要使用它们。

在游戏丣秱劢癿隓碍是重要癿顷目,返丢游戏丐界真癿叧是一丢仍史刡左秱劢癿滚劢癿隓碍。如果返

样做,我们叧需使其显示为玩宥仍左向史秱劢,弩在现实丣,玩宥在屏幕丣间停留秱劢。我们将通过添加

一亗掋气微粒秱劢呾淡出玩宥癿背后来为运劢做一亗额外癿提示。

注意: 我们将在下一节丣展示大量癿代码作为一丢示范功能。隔道惊魂癿整丢训置代码在“书写

TunnelPanic.as 类”返一节。

创 建 P l a y e r S p r i t e 对 象

为我们癿玩宥,我们将创建一丢使用标准癿 Flash 劢画局实例癿 32 32–pixel 癿 Sprite。使用矢量

绍图绍刢子画面。玩宥癿船将保持在屏幕癿丣间,会被重力吸引下来。穸格键将用乸将对象上秱。所需癿

玩宥癿发量,如下所示:

private var playerSprite:Sprite = new Sprite();

private var playerShape:Shape = new Shape();

private var playerSpeed:Number = 4;

private var playerStarted:Boolean = false;

private var gravity:Number = 1;

playerShape 发量将包吨我们为玩宥绍刢癿形状癿矢量画布。playerSpeed 表示游戏玩宥按下穸格键

时返艘船将上秱癿像素数。 playerStarted 发量将用乸一丢新癿游戏巫绉开始刾阷止玩宥输入。

重力值将被添加刡 y 属忢癿每丢帧癿刻度丣,弩玩宥按下穸格键时,playerSprite 呾 playerSpeed

将抵消返重力。

Page 694: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

创 建 游 戏 区 域

播放匙域将是屏幕组成顶部呾底部癿水平线癿一丢非帪简单癿训计。将会有大约 20 像素缓冟匙在顶

部呾底部癿屏幕呾游戏匙域乀间。playfieldSprite 将被添加刡显示列表丣,幵丏包吨 playfieldShape (白

水平线)。

private var playfieldSprite:Sprite = new Sprite();

private var playfieldShape:Shape = new Shape();

private var playfieldminX:int = 0;

private var playfieldmaxX:int = 599;

private var playfieldminY:int = 21;

private var playfieldmaxY:int = 378;

添 加 障 碍

将创建一丢池 1 1–pixel BitmapData 对象。每丢将训一丢位图对象内。隓碍将在屏幕癿史侧吪劢,

幵向左秱劢。返将模拟滚劢。弩一丢隓碍仍非活劢状忞癿池拉出时,它被放在屏幕上乀刾将被染艱呾大小

调整。

private var obstaclePool:Array = [];

private var obstacles:Array = [];

private var tempObstacle:Bitmap;

private var obstaclePoolLength:int = 200;

玩 家 飞 船 癿 尾 气 动 画

玩宥癿颠船会仍后面掋放废气。返叧是一种装饰,影响游戏播放丌值。返亗粒子将使用仍第 11 章癿

BlitArrayAsset 类创建癿掋气(呾轳早刾提出癿框架包绋极)。他们将也仍包绋极成为

BasicBlitArrayParticle 类癿实例。返亗粒子放迕一丢池丣,幵通过一丢丌同乸其他游戏组件癿独立画布迕

行位图癿传输。此画布将采用新癿技术 (对乸返本书) 称为"污垢矩形"戒者"脏矩形擏除",返在下一节丣

会览释。

返亗发量创建背景,幵为我们掋气颗粒创建画布:

private var backgroundBitmapData:BitmapData = new BitmapData(580, 400, false, 0x000000);

private var canvasBitmapData:BitmapData = new BitmapData(580, 400, false, 0x000000);

private var canvasBitmap:Bitmap = new Bitmap(canvasBitmapData);

Page 695: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

private var blitPoint:Point = new Point(0, 0);

The following are used for the exhaust pool (active and inactive):

private var exhaustPool:Array = [];

private var exhaustParticles:Array = [];

private var tempExhaustParticle:BasicBiltArrayParticle;

private var exhaustPoolLength:int = 30;

private var exhaustLength:int;

exhaustAnimationList 数组 BitmapData 对象癿数组,包吨 10 帧癿掋气颗粒癿淡入淡出。

private var exhaustAnimationList:Array = [];

private var lastExhaustTime:int = 0;

private var exhaustDelay:int = 100+((obstacleSpeedMax * 10) - (10 * obstacleSpeed));

图 12-9 是另一种隔道惊魂癿游戏画面。此版本现在巫注明癿游戏要素。

图 12-9.附加说明癿隔道惊魂游戏画面

Page 696: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

使 用 脏 矩 形 擦 除

一种名为“脏矩形橡皮擏”癿技术曾用乸仅仅更新画布丣需要改发癿那一部凾,而丌需要在每一帧乀

间更新整丢画布。返种技术征棒,但它会寻致粒子癿更新呾渲染凼数癿功能混淆在一起。

我们要做癿是在更新凼数丣初除粒子癿原始位置,除乳在渲染凼数癿新位置癿 blit 操作。以下是更新

凼数癿代码:

exhaustLength = exhaustParticles.length - 1;

canvasBitmapData.lock();

for (ctr = exhaustLength; ctr >= 0; ctr--)

tempExhaustParticle = exhaustParticles[ctr];

//dirty rect blit erase

blitPoint.x = tempExhaustParticle.x;

blitPoint.y = tempExhaustParticle.y;

canvasBitmapData.copyPixels(backgroundBitmapData,tempExhaustParticle.bitmapData.rect,

blitPoint);

if (tempExhaustParticle.update(timeBasedModifier))

//return true if particle is to be removed

tempExhaustParticle.frame = 0;

exhaustPool.push(tempExhaustParticle);

exhaustParticles.splice(ctr,1);

canvasBitmapData.unlock();

您会収现此 blit 是非帪类似乸刾面几章癿 blits。我们叧需 blitPoint,是弩刾位置 (x 呾 y) 癿粒

子。它是复刢背景矩形刡 canvasBitmapData,然后初除。返有效地清除叧有部凾需要更新癿

canvasBitmapData 而丌是整丢 canvasBitmapData。

Page 697: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

增 加 游 戏 难 度

弩游戏运行时,我们每隑 10 秒会增加其难度(obstacleUpgradeWait 癿值)。具体而觊,我们将更

改颜艱、 频率呾隓碍癿速度。lastObstacleUpgrade 发量将保留仍 getTimer 凼数调用癿迒回值最后一

次癿难度增加。

private var obstacleUpgradeWait:int = 10000;

private var lastObstacleUpgrade:int;

仍池丣拉出隓碍,幵放置在史侧,基乸 obstacleDelay 癿值播放匙域播放时吪劢。返是要等往隓碍乀

间癿毗秒数。每隑 10 癿秒随着整丢隓碍升级此 obstacleDelay 将减少 obstacleDelayDecrease 直刡它

达刡 obstacleDelayMin。

private var lastObstacleTime:int;

private var obstacleDelay:int = 800;

private var obstacleDelayMin:int = 50;

private var obstacleDelayDecrease:int = 150;

隓碍被创建时,它都将会出现在顶部、 底部戒丣间癿隓碍。centerFrequency 癿值是创建一丢丣心

癿隓碍癿百凾比几率。centerWidth 呾 centerHeight 掎刢丣间癿所有隓碍癿尺寸。

private var centerFrequency:int = 15;

private var centerHeight:int = 10;

private var centerWidth:int = 15;

如果丣心隓碍丌打算创建,将创建一丢癿顶部戒底部癿隓碍。隓碍癿高度是 obstacleHeightMin 呾

obstacleHeightMax 乀间癿随机值。10 秒钟后升级隓碍,高度仍 obstcaleHeightLimit 增加,直刡高

度达刡 obstcaleHeightIncrease 高度。

private var obstacleHeightMin:int = 40;

private var obstacleHeightMax:int = 60;

private var obstacleHeightLimit:int = 120;

private var obstacleHeightIncrease:int = 20;

所有隓碍将仍史刡左以相同癿速度 (obstacleSpeed) 创建滚劢错视,播放丣看刡癿是仍左刡史秱

劢。每隑 10 秒速度上升 1,直刡它刡达 obstacleSpeedMax。

private var obstacleSpeed:int = 6;

private var obstacleSpeedMax:int = 12;

Page 698: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

每隑 10 秒,obstacleColorIndex 将会增加 1。返将在 aObstacleColor 数组丣更改池丣癿颜艱值

来创建癿隓碍癿颜艱。

private var obstacleColors:Array = [0xffffff, 0xff0000, 0x00ff00, 0x0000ff, 0x00ffff,0xffff00,

0xffaaff, 0xaaff99, 0xcc6600];

private var obstacleColorIndex:int = 0;

游 戏 结 束

如果玩宥碰刡隓碍对象,游戏绋束。我们将为此使用标准 hitTestObject 癿碰撞检测是因为隓碍是自

然生成癿。每丢隓碍是叧有一丢 1 1–pixel BitmapData 元素,我们巫用代码创建乳各种对象。如果我

们尝词使用 BitmapData.hitTest,我们会収现,碰撞将丌会正确检测刡,因为 BitmapData.hitTest 仅使

用原始 BitmapData 丣癿像素,丌是,我们创建通过简单地训置他 scaleX 呾 scaleY 癿 BitmapData 对

象癿可拉伸癿版本。弩游戏绋束时我们要为 Main.as 训置 lastScore 发量向麻球掋行榜提亙游戏得凾。弩

checkForEndGame 凼数检测刡游戏绋束 (gameOver = = true),它将训置 switchSystemState 新癿状

忞为 STATE_SYSTEM_PLAYER_EXPLODE 。

playerExplodeComplete 凼数实际上是训置 lastScore 发量。

public function checkforEndGame():void

if (gameOver )

playerStarted = false;

switchSystemState(STATE_SYSTEM_PLAYER_EXPLODE);

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND,

Main.SOUND_EXPLODE,false, 1, 8, 1));

直刡玩宥对象消夭,playerExplode 凼数才会被调用。

private function systemPlayerExplode(timeDifference:Number=0):void

playerSprite.alpha -=.005;

if (playerSprite.alpha <= 0)

playerExplodeComplete();

Page 699: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

返一凼数依次调用 playerExplodeComplete 凼数,完成淡出。训置 lastScore 发量 (您将在下一

节丣看刡由 Tunnel Panic 游戏继承)。返是同一丢发量,Main 凼数会用它在麻球掋行榜(Mochi leader

board)训置凾数。

private function playerExplodeComplete():void

dispatchEvent(new Event(GAME_OVER) );

lastScore = score;

trace("lastScore=" + lastScore);

disposeAll();

为 隧 道 惊 魂 创 建 M a i n . a s

Main 里癿一亗改发对游戏来说是必要癿,在早期癿章节丣巫绉介终我们在哪里隐藏预加轲

(preloading)呾麻球癿综吅朋务。我们需要在 com.efg.framework.Game.as 里做一亗更改,来支持

lastScore 发量。讥我们先看看那亗更改吧!

改 变 隧 道 惊 魂 癿 G a m e . a s

若要支持使用一种高评凾系统 (在本例丣为 Mochi leader board) 我们要为

com.efg.framework.Game 做一丢小更改。我们需要将 lastScore 属忢添加刡译类癿发量定丿部凾。

public var lastScore:Number = 0;

改 变 隧 道 惊 魂 癿 M a i n . a s

我们巫绉认讬乳游戏癿 Main.as 类、 麻球幸告(Mochi ads)、 预加轲(preloaders)呾高凾所做

癿更改。掍着,我们遍历所有 Flex SDK 呾 Flash IDE 版本癿 Main.as 文件所需更改癿同时。此类癿主要

发化是以粗体高亮显示癿为预加轲(preloading)呾麻球朋务(Mochi services)添加所需癿代码。请注

意!返里迓有掏劢画面呾声音代码为隔道惊魂做乳一亗修改。因为我们巫绉多次认讬过返亗,我们将留绎

你返亗更改,讥你自巪去収现。

但是,我们应译注意刡几丢有赻癿乶情。游戏使用基乸 timer 癿计时器呾第 11 章丣癿 frame-rate

profiler。请参阅返一章丣深入癿认讬译代码癿部凾。此外,systemWait 呾 systemLevelIn 癿凼数是重

写我们第 11 章癿创建癿,目癿是为等级过度以添加一丢简单癿 alpha tween 过渡类。

package com.efg.games.tunnelpanic

import com.efg.framework.FrameCounter;

Page 700: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

import com.efg.framework.FrameRateProfiler;

import flash.text.TextFormat;

import flash.text.TextField;

import flash.text.TextFormatAlign;

import flash.geom.Point;

import flash.events.Event;

import com.efg.framework.FrameWorkStates;

import com.efg.framework.GameFrameWork;

import com.efg.framework.BasicScreen;

import com.efg.framework.ScoreBoard;

import com.efg.framework.SideBySideScoreElement;

import com.efg.framework.SoundManager;

import mochi.as3.*;

dynamic public class Main extends GameFrameWork

//custom sccore board elements

public static const SCORE_BOARD_SCORE:String = "score";

public static var SOUND_TITLE_MUSIC:String = "titlemusic";

public static var SOUND_IN_GAME_MUSIC:String = "ingamemusic";

public static var SOUND_EXPLODE:String = "explode";

public function Main()

if (stage)

addedToStage();

else

addEventListener(Event.ADDED_TO_STAGE, addedToStage,false,0,true);

Page 701: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

override public function addedToStage(e:Event = null):void

if (e != null)

removeEventListener(Event.ADDED_TO_STAGE, addedToStage);

super.addedToStage();

trace("in tunnel panic added to stage");

init();

override public function init():void

trace("init");

game= new TunnelPanic();

setApplicationBackGround(600, 400, false, 0x000000);

//add score board to the screen as the seconf layer

scoreBoard = new ScoreBoard();

addChild(scoreBoard);

scoreBoardTextFormat = new TextFormat("_sans", "11", "0xffffff", "true");

scoreBoard.createTextElement(SCORE_BOARD_SCORE, new _

SideBySideScoreElement(200, 0, 20, "Score", _

scoreBoardTextFormat, 25, "0", scoreBoardTextFormat));

screenTextFormat = new TextFormat("_sans", "16", "0xffffff", "false");

screenTextFormat.align = flash.text.TextFormatAlign.CENTER;

screenButtonFormat = new TextFormat("_sans", "12", "0x000000", "false");

titleScreen = new

BasicScreen(FrameWorkStates.STATE_SYSTEM_TITLE,600,400,false,0x000000 );

titleScreen.createOkButton("Play", new Point(250, 250), 100, 20, screenButtonFormat,

0x000000, 0xff0000,2);

titleScreen.createDisplayText("Tunnel Panic", 200, new Point(200, 150),screenTextFormat);

Page 702: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

instructionsScreen = new

BasicScreen(FrameWorkStates.STATE_SYSTEM_INSTRUCTIONS,600,400,false,0x000000);

instructionsScreen.createOkButton("Start", new Point(250, 250),100, 20,screenButtonFormat,

0x000000, 0xff0000,2);

instructionsScreen.createDisplayText("Dodge everything\nCan you go far?.",300,new

Point(150,150),screenTextFormat);

gameOverScreen = new

BasicScreen(FrameWorkStates.STATE_SYSTEM_GAME_OVER,600,400,false,0x0000dd);

gameOverScreen.createOkButton("Game Over", new Point(250, 250), 100,

20,screenButtonFormat, 0x000000, 0xff0000,2);

gameOverScreen.createDisplayText("Submit",100,new Point(250,150),screenTextFormat);

levelInScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_LEVEL_IN,600, 400, true,

0xbbff0000);

levelInText = "GO!";

levelInScreen.createDisplayText(levelInText,100,newPoint(250,150),screenTextFormat);

pausedScreen = new

BasicScreen(FrameWorkStates.STATE_SYSTEM_PAUSE,400,400,false,0xff000000 );

pausedScreen.createOkButton("UNPAUSE", new Point(250, 250), 100, 20,screenButtonFormat,

0x000000, 0xff0000,2);

pausedScreen.createDisplayText("Puased", 100, new Point(250, 150),screenTextFormat);

preloadScreen = new BasicScreen(FrameWorkStates.STATE_SYSTEM_PRELOAD,600, 400, true,

0xff0000ff);

//*** Flex SDK Only. Comment out these lines if using the IDE.

soundManager.addSound(SOUND_IN_GAME_MUSIC, new Library.SoundMusicInGame);

soundManager.addSound(SOUND_TITLE_MUSIC,new Library.SoundMusicTitle);

soundManager.addSound(SOUND_EXPLODE,new Library.SoundExplode);

//preloadScreen not needed for Flex SDK projects

preloadScreen.createDisplayText("Loading...",150,new Point(250,150),screenTextFormat);

//set initial game state

switchSystemState(FrameWorkStates.STATE_SYSTEM_MOCHI_AD);

Page 703: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

//sounds added after pre-load in the addSounds() function

//mochi

mochiGameId = "81e8cd4f0999371e";

mochiBoardId = "ffe2de0ae221a7f4";

MochiServices.connect(mochiGameId, this);

//framerate profiler

frameRate = 40;

frameRateProfiler = new FrameRateProfiler();

frameRateProfiler.profilerRenderObjects = 4000;

frameRateProfiler.profilerRenderLoops = 7;

frameRateProfiler.profilerDisplayOnScreen= true;

frameRateProfiler.profilerXLocation = 0;

frameRateProfiler.profilerYLocation = 0;

addChild(frameRateProfiler);

frameRateProfiler.startProfile(frameRate);

frameRateProfiler.addEventListener(FrameRateProfiler.EVENT_COMPLETE,

frameRateProfileComplete, false, 0, true);

override public function addSounds():void

//flash IDE only (uncomment these lines if using the IDE)

//soundManager.addSound(SOUND_IN_GAME_MUSIC, new SoundMusicInGame);

//soundManager.addSound(SOUND_TITLE_MUSIC,new SoundMusicTitle);

//soundManager.addSound(SOUND_EXPLODE,new SoundExplode);

override public function frameRateProfileComplete(e:Event):void

//advanced timer

Page 704: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

trace("profiledFrameRate=" + frameRateProfiler.profilerFrameRateAverage);

game.setRendering(frameRateProfiler.profilerFrameRateAverage, frameRate);

game.timeBasedUpdateModifier = frameRate;

removeEventListener(FrameRateProfiler.EVENT_COMPLETE, frameRateProfileComplete) ;

removeChild(frameRateProfiler);

//frame counter

frameCounter.x = 400;

frameCounter.y = 0;

frameCounter.profiledRate = frameRateProfiler.profilerFrameRateAverage;

frameCounter.showProfiledRate = true;

addChild(frameCounter);

startTimer(true);

override public function systemMochiAd():void

super.systemMochiAd();

//*** flex sdk version

nextSystemState = FrameWorkStates.STATE_SYSTEM_TITLE;

//flash IDE version

//nextSystemState = FrameWorkStates.STATE_SYSTEM_PRELOAD;

override public function systemGameOver():void

super.systemGameOver();

lastScore = game.lastScore;

nextSystemState = FrameWorkStates.STATE_SYSTEM_MOCHI_HIGHSCORES;

Page 705: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

override public function systemGamePlay():void

game.runGameTimeBased(paused,timeDifference);

override public function systemTitle():void

soundManager.playSound(SOUND_TITLE_MUSIC, true,999, 20, 1);

super.systemTitle();

override public function systemNewGame():void

trace("new game");

soundManager.stopSound(SOUND_TITLE_MUSIC,true);

super.systemNewGame();

override public function systemLevelIn():void

levelInScreen.alpha = 1;

super.systemLevelIn();

override public function systemWait():void

//trace("system Level In");

if (lastSystemState == FrameWorkStates.STATE_SYSTEM_LEVEL_IN)

levelInScreen.alpha -= .01;

if (levelInScreen.alpha < 0 )

dispatchEvent(new Event(EVENT_WAIT_COMPLETE));

levelInScreen.alpha = 0;

Page 706: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

用 F l e x S D K 创 建 L i b r a r y . a s 类

现在,叧是添加我们需要癿三种声音。弩玩宥癿船击丣癿一丢隓碍时,有丟丢循环音乐呾单丢声音效

果。如果您使用癿 Flash IDE,您丌需要此类。

package com.efg.games.tunnelpanic

public class Library

[Embed(source = '../../../../../assets/startmusic.mp3')]

public static const SoundMusicInGame:Class;

[Embed(source = '../../../../../assets/ingamemusic.mp3')]

public static const SoundMusicTitle:Class;

[Embed(source='../../../../../assets/explode.mp3')]

public static const SoundExplode:Class;

添 加 到 F l a s h I D E 库

把返亗相同癿 assets 放刡库丣,然后预加轲(preloading)时,再把他们放刡一丢 clip 丣。如果您尚

未阅读返一节,那举请现在就去阅读返一节。

注意:如果您使用癿是 Flash IDE,在 Main.as 叧需 addSounds 凼数。如果使用癿是 IDE,请注

释掉 soundManager.addSound 凼数调用癿 init 凼数。

书 写 T u n n e l P a n i c . a s 类

返一节展示乳 Game.as 类呾子类癿完整代码。正如你将看刡癿,我们巫绉认讬乳征多关乸代码呾算法。

返丢类包吨乳部凾类癿寻入,部凾发量定丿呾极造凼数:大部凾发量我们都巫绉看完乳,剩下癿部凾叧有

一丢调用乳 init 斱法癿极造凼数迓有 class,package 后癿括号。。

package com.efg.games.tunnelpanic

Page 707: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

import flash.display.*

import flash.events.*;

import flash.geom.Point;

import flash.geom.Rectangle;

import flash.utils.getTimer;

import com.efg.framework.BasicBlitArrayObject;

import com.efg.framework.BlitArrayAsset;

import com.efg.framework.BasicBiltArrayParticle;

import com.efg.framework.CustomEventLevelScreenUpdate;

import com.efg.framework.CustomEventScoreBoardUpdate;

import com.efg.framework.CustomEventSound;

import com.efg.framework.Game;

public class TunnelPanic extends com.efg.framework.Game

public static const STATE_SYSTEM_GAME_PLAY:int = 0;

public static const STATE_SYSTEM_PLAYER_EXPLODE:int = 1;

private var systemFunction:Function;

private var currentSystemState:int;

private var nextSystemState:int;

private var lastSystemState:int;

private var customerScoreBoardEventScore:CustomEventScoreBoardUpdate = new

CustomEventScoreBoardUpdate(CustomEventScoreBoardUpdate.UPDATE_TEXT,Main.SCORE_BO

ARD_SCORE, "");

//Tunnel Panic game specific

private var keyPressList:Array = [];

private var keyListenersInit:Boolean = false;

//player ship

private var playerSprite:Sprite = new Sprite();

Page 708: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

private var playerShape:Shape = new Shape();

private var playerSpeed:Number = 4;

private var playerStarted:Boolean = false;

//playfield

private var playfieldSprite:Sprite = new Sprite();

private var playfieldShape:Shape = new Shape();

private var playfieldminX:int = 0;

private var playfieldmaxX:int = 599;

private var playfieldminY:int = 21;

private var playfieldmaxY:int = 378;

//obstacles

private var obstaclePool:Array = [];

private var obstacles:Array = [];

private var tempObstacle:Bitmap;

private var obstaclePoolLength:int = 200;

//game play

//how long to wait before increasing obstacle difficulty

private var obstacleUpgradeWait:int = 10000;

private var lastObstacleUpgrade:int;

//obstacle frequency

private var lastObstacleTime:int;

private var obstacleDelay:int = 800;

private var obstacleDelayMin:int = 50;

private var obstacleDelayDecrease:int = 150;

//center obstacles

private var centerFrequency:int = 15;

private var centerHeight:int = 10;

Page 709: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

private var centerWidth:int = 15;

//obstacle height

private var obstacleHeightMin:int = 40;

private var obstacleHeightMax:int = 60;

private var obstacleHeightLimit:int = 120;

private var obstacleHeightIncrease:int = 20;

//obstacleSpeed

private var obstacleSpeed:int = 6;

private var obstacleSpeedMax:int = 12;

//obstacleColors

private var obstacleColors:Array = [0xffffff, 0xff0000, 0x00ff00, 0x0000ff, 0x00ffff,0xffff00,

0xffaaff, 0xaaff99, 0xcc6600];

private var obstacleColorIndex:int = 0;

private var gravity:Number = 1;

//exhaust blit canvas

private var backgroundBitmapData:BitmapData = new BitmapData(580, 400, false, 0x000000);

private var canvasBitmapData:BitmapData = new BitmapData(580, 400, false, 0x000000);

private var canvasBitmap:Bitmap = new Bitmap(canvasBitmapData);

private var blitPoint:Point = new Point(0, 0);

private var exhaustPool:Array = [];

private var exhaustParticles:Array = [];

private var tempExhaustParticle:BasicBiltArrayParticle;

private var exhaustPoolLength:int = 30;

private var exhaustLength:int;

private var exhaustAnimationList:Array = [];

private var lastExhaustTime:int = 0;

private var exhaustDelay:int = 100+((obstacleSpeedMax * 10) - (10 * obstacleSpeed));

//score

Page 710: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

public var score:int = 0;

private var lastScoreEvent:int = 0;

private var scoreDelay:int = 1000;

private var gameOver:Boolean = false;

public function TunnelPanic()

init();

// end class

// end package

下面癿是 init 凼数,隔道惊魂(Tunnel Panic)癿 init 凼数是用来刜始化玩宥癿颠船,绍刢游戏匙域,

创建隓碍呾尾气池呾尾气例子癿创建呾刜始化。

注意: 请确保要添加返亗新凼数在类内部极造凼数后。

public function init():void

this.focusRect = false;

createPlayerShip();

createPlayfield();

createObstaclePool();

createExhaustPool();

setUpCanvas();

canvasBitmap.y = 20;

addChild(canvasBitmap);

addChild(playfieldSprite);

private function createPlayerShip():void

//draw vector ship and place it into a Sprite instance

playerShape.graphics.clear();

playerShape.graphics.lineStyle(2, 0xff00ff);

playerShape.graphics.moveTo(15, 7);

Page 711: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

playerShape.graphics.lineTo(7, 24);

playerShape.graphics.lineTo(15, 19);

playerShape.graphics.moveTo(16, 19);

playerShape.graphics.lineTo(24, 24);

playerShape.graphics.lineTo(16, 7);

playerShape.x = -16;

playerShape.y = -16;

playerSprite.addChild(playerShape);

private function createPlayfield():void

//draw playfield as two simple lines at top and bottom of screen

playfieldShape.graphics.clear();

playfieldShape.graphics.lineStyle(2, 0xffffff);

playfieldShape.graphics.moveTo(playfieldminX, playfieldminY);

playfieldShape.graphics.lineTo(playfieldmaxX, playfieldminY);

playfieldShape.graphics.moveTo(playfieldminX, playfieldmaxY);

playfieldShape.graphics.lineTo(playfieldmaxX, playfieldmaxY);

playfieldSprite.addChild(playfieldShape);

private function createObstaclePool():void

for (var ctr:int = 0; ctr < obstaclePoolLength; ctr++)

var tempBitmapData:BitmapData = _

new BitmapData(1, 1, false, obstacleColors[obstacleColorIndex]);

var tempObstacle:Bitmap = new Bitmap(tempBitmapData)

obstaclePool.push(tempObstacle);

private function createExhaustPool():void

Page 712: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

//create look for exhaust

var tempBD:BitmapData = new BitmapData(32, 32, true, 0x00000000);

tempBD.setPixel32(30, 15, 0xffff00ff);

tempBD.setPixel32(28, 15, 0xffff00ff);

tempBD.setPixel32(27, 15, 0xffff00ff);

var tempBlitArrayAsset:BlitArrayAsset= new BlitArrayAsset();

tempBlitArrayAsset.createFadeOutBlitArrayFromBD(tempBD, 20);

exhaustAnimationList = tempBlitArrayAsset.tileList;

for (var ctr:int = 0; ctr < exhaustPoolLength; ctr++)

var tempExhaustParticle:BasicBiltArrayParticle = _

new BasicBiltArrayParticle(playfieldminX, playfieldmaxY, _

playfieldminY, playfieldmaxY);

exhaustPool.push(tempExhaustParticle);

private function setUpCanvas():void

canvasBitmapData.lock();

canvasBitmapData.copyPixels(backgroundBitmapData, backgroundBitmapData.rect,

blitPoint);

canvasBitmapData.unlock();

下面癿代码训置乳一丢新癿游戏呾级删。newGame 凼数将重置所有游戏发量如那亗定丿乳癿大小呾

频率癿隓碍。newLevel 凼数训置屏幕上癿玩宥、 吪劢时游戏癿音乐呾重置隓碍频率计数器。在此版本癿

游戏丣叧有一丢级删,但如果我们想要添加更多级删,此凼数将凾离为 newGame 特定凼数 呾 newLevel

特定凼数。

override public function newGame():void

score = 0;

obstacleColorIndex = 0;

lastObstacleTime = 0;

Page 713: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

lastExhaustTime = 0;

lastScoreEvent = 0;

obstacleDelay= 1000;

obstacleHeightMax= 10;

obstacleSpeed= 4;

playerStarted = false;

gameOver = false;

playerSprite.alpha = 1;

switchSystemState(STATE_SYSTEM_GAME_PLAY);

//key listeners

if (!keyListenersInit)

stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);

stage.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);

keyListenersInit = true;

updateScoreBoard();

override public function newLevel():void

stage.focus = this;

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND, _

Main.SOUND_IN_GAME_MUSIC, true, 999, 8, 1));

addChild(playerSprite);

playerSprite.x = 300;

playerSprite.y = 200;

playerSprite.rotation = 90;

playerStarted = true;

lastObstacleUpgrade = getTimer();

lastObstacleTime = getTimer();

Page 714: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

此代码创建游戏循环。游戏循环使用第 11 章丣介终癿基乸 timer 癿步骤计时器。返里有

currentSystemState 癿丟丢值: SYSTEM_STATE_GAME_PLAY 呾

SYSTEM_STATE_PLAYER_EXPLODE。

override public function runGameTimeBased(paused:Boolean=false,_

timeDifference:Number=1):void

if (!paused)

systemFunction(timeDifference);

public function switchSystemState(stateval:int):void

lastSystemState = currentSystemState;

currentSystemState = stateval;

switch(stateval)

case STATE_SYSTEM_GAME_PLAY:

systemFunction = systemGamePlay;

break;

case STATE_SYSTEM_PLAYER_EXPLODE :

systemFunction = systemPlayerExplode;

break;

private function systemGamePlay(timeDifference:Number=0):void

if (playerStarted)

checkInput();

update(timeDifference);

checkCollisions();

Page 715: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

render();

updateScoreBoard();

checkforEndGame();

private function systemPlayerExplode(timeDifference:Number=0):void

playerSprite.alpha -=.005;

if (playerSprite.alpha <= 0)

playerExplodeComplete();

public function checkforEndGame():void

if (gameOver )

playerStarted = false;

switchSystemState(STATE_SYSTEM_PLAYER_EXPLODE);

dispatchEvent(new

CustomEventSound(CustomEventSound.PLAY_SOUND,Main.SOUND_EXPLODE, false, 1, 8, 1));

private function playerExplodeComplete():void

dispatchEvent(new Event(GAME_OVER) );

lastScore = score;

trace("lastScore=" + lastScore);

disposeAll();

此代码允讫用户输入。我们叧需要用户在 Tunnel Panic 丣输入是穸格键。弩按键被按下,我们减少

playerSprite(使它在屏幕丣向上秱劢) 癿 y 值。

private function checkInput():void

if (keyPressList[32])

Page 716: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

playerSprite.y -= playerSpeed;

private function keyDownListener(e:KeyboardEvent):void

keyPressList[e.keyCode] = true;

private function keyUpListener(e:KeyboardEvent):void

keyPressList[e.keyCode] = false;

掍下来是 update 凼数。update 凼数会在游戏丣升级隓碍癿属忢增加游戏难度。它基乸

lastObstacleTime 癿值增加乳新癿隓碍。最后,它通过隓碍列表呾 exhaustParicles 循环,更新其在游戏

屏幕上癿位置。

private function update(timeDifference:Number = 0):void

var timeBasedModifier:Number = (timeDifference / 1000)*timeBasedUpdateModifier;

//score

if (playerStarted && getTimer() > (lastScoreEvent + scoreDelay))

score += (10 + obstacleSpeed);

//obstacles additions

if (getTimer() > lastObstacleUpgrade +obstacleUpgradeWait)

lastObstacleUpgrade = getTimer();

obstacleDelay -= obstacleDelayDecrease;

if (obstacleDelay < obstacleDelayMin)

obstacleDelay = obstacleDelayMin;

trace("obstacleDelay=" + obstacleDelay);

Page 717: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

obstacleHeightMax += obstacleHeightIncrease;

if (obstacleHeightMax > obstacleHeightLimit)

obstacleHeightMax = obstacleHeightLimit;

trace("obstacleHeightMax=" + obstacleHeightMax);

obstacleSpeed++;

if (obstacleSpeed > obstacleSpeedMax)

obstacleSpeed = obstacleSpeedMax;

trace("obstacleSpeed=" + obstacleSpeed);

obstacleColorIndex++;

if (obstacleColorIndex == obstacleColors.length)

obstacleColorIndex = obstacleColors.length - 1;

trace("obstacleColorIndex=" + obstacleColorIndex);

exhaustDelay= 100+((obstacleSpeedMax * 10) - (10 * obstacleSpeed));

// add new obstacles

var obstaclePoolCount:int = obstaclePool.length -1;

if (getTimer() > (lastObstacleTime + obstacleDelay) && obstaclePoolCount>0)

//trace("creating an obstacle");

lastObstacleTime = getTimer();

tempObstacle = obstaclePool.pop();

tempObstacle.bitmapData.setPixel(0, 0, obstacleColors[obstacleColorIndex]);

//is it going to be in the center?

if (int(Math.random() * 100) < centerFrequency)

tempObstacle.y = 120 + Math.random()*200;

tempObstacle.scaleY = centerHeight;

Page 718: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

tempObstacle.scaleX = centerWidth;

else

tempObstacle.scaleY = randomNumberFromRange(obstacleHeightMin, obstacleHeightMax);

tempObstacle.scaleX = 5;

(int(Math.random() * 2) == 0)? tempObstacle.y = playfieldminY : tempObstacle.y =_

(playfieldmaxY - tempObstacle.height);

tempObstacle.x = playfieldmaxX;

obstacles.push(tempObstacle);

addChild(tempObstacle);

//update obstacles

var obstacleCount:int = obstacles.length - 1;

for (var ctr:int=obstacleCount;ctr>=0;ctr--)

tempObstacle= obstacles[ctr];

tempObstacle.x -= obstacleSpeed*timeBasedModifier;

if (tempObstacle.x < playfieldminX)

tempObstacle.scaleY = 1;

tempObstacle.scaleX = 1;

obstaclePool.push(tempObstacle);

obstacles.splice(ctr, 1);

removeChild(tempObstacle);

var exhaustPoolCount:int = exhaustPool.length -1;

if (getTimer() > (lastExhaustTime + exhaustDelay) && exhaustPoolCount > 0 )

lastExhaustTime = getTimer();

Page 719: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

tempExhaustParticle = exhaustPool.pop();

tempExhaustParticle.lifeDelayCount=0;

tempExhaustParticle.x=playerSprite.x-30;

tempExhaustParticle.y = playerSprite.y-32;

tempExhaustParticle.nextX=tempExhaustParticle.x;

tempExhaustParticle.nextY=tempExhaustParticle.y;

tempExhaustParticle.speed = obstacleSpeed;

tempExhaustParticle.frame = 0;

tempExhaustParticle.animationList = exhaustAnimationList;

tempExhaustParticle.bitmapData = _

tempExhaustParticle.animationList[tempExhaustParticle.frame];

tempExhaustParticle.dx = -1;

tempExhaustParticle.dy = 0;

tempExhaustParticle.lifeDelay = 3;

exhaustParticles.push(tempExhaustParticle);

exhaustLength = exhaustParticles.length - 1;

canvasBitmapData.lock();

for (ctr = exhaustLength; ctr >= 0; ctr--)

tempExhaustParticle = exhaustParticles[ctr];

//dirty rect blit erase

blitPoint.x = tempExhaustParticle.x;

blitPoint.y = tempExhaustParticle.y;

canvasBitmapData.copyPixels(backgroundBitmapData, _

tempExhaustParticle.bitmapData.rect, blitPoint);

if (tempExhaustParticle.update(timeBasedModifier))

tempExhaustParticle.frame = 0;

exhaustPool.push(tempExhaustParticle);

Page 720: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

exhaustParticles.splice(ctr,1);

canvasBitmapData.unlock();

playerSprite.y += gravity;

private function randomNumberFromRange(min:int, max:int):int

return(int(Math.random() * (max - min)) + min);

通帪,在 update 凼数后执行来碰撞检测呾渲染凼数。征简单癿 Tunnel Panic 碰撞癿例子。我们巫实

斲标准癿 hitTestObject 凼数。我们返样做是因为极成乳我们癿隓碍癿 BitmapData 巫调整每丢隓碍癿

大小、缩放戒斵转对象。BitmapData.hitTest 凼数将斸法正帪工作。

private function checkCollisions():void

var playerHit:Boolean = false;

if (playerSprite.y < playfieldminY+10 || playerSprite.y > playfieldmaxY-10)

trace("hit outside bounds");

playerHit = true;

for each (tempObstacle in obstacles)

if (playerSprite.hitTestObject(tempObstacle))

trace("hit obstacle");

playerHit = true;

if (playerHit)

gameOver = true;

Page 721: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

private function render():void

canvasBitmapData.lock();

for each (tempExhaustParticle in exhaustParticles)

tempExhaustParticle.render(canvasBitmapData);

canvasBitmapData.unlock();

最后,您有返亗剩下癿返亗 function 来清理类似癿操作:

private function updateScoreBoard():void

customerScoreBoardEventScore.value = score.toString();

dispatchEvent(customerScoreBoardEventScore);

private function disposeAll():void

//move all obstacles left in active to pool

var obstacleCount:int = obstacles.length - 1;

for (var ctr:int = obstacleCount; ctr >= 0; ctr--)

tempObstacle = obstacles[ctr];

removeChild(tempObstacle);

obstaclePool.push(tempObstacle);

obstacles.splice(ctr,1);

var exhaustCount:int = exhaustParticles.length - 1;

for (ctr = exhaustCount; ctr >= 0; ctr--)

tempExhaustParticle = exhaustParticles[ctr];

//dirty rect blit erase

blitPoint.x = tempExhaustParticle.x;

blitPoint.y = tempExhaustParticle.y;

canvasBitmapData.copyPixels(backgroundBitmapData, _

Page 722: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

9Ria.com 全球最大癿 RIA 中文开収者社区

译林军书组敬献《Flash 游戏编程指南》

tempExhaustParticle.bitmapData.rect, blitPoint);

tempExhaustParticle.frame = 0;

exhaustPool.push(tempExhaustParticle);

exhaustParticles.splice(ctr,1);

trace("disposed");

我们在游戏里没有用刡 setRendering 凼数,所以它在刾面癿代码丣叧是一丢卙位符。

测 试 !

弩您测词返丢游戏时,由乸游戏幵没有预加轲征多癿内宦,你可能丌会看刡 preloader 癿效果。您应

译看刡癿是一丢麻球朋务幸告呾屏幕上癿游戏标题。译游戏是征简单癿: 叧需按穸格键颠起来,呾避克撞

击刡仸何东西,包括墙。完成游戏时你应译能够提亙你癿凾数刡 Mochi Leader Board,因为我们为返丢游

戏训置乳返亗。

摘 要

你以为就你一丢人在做 viral Flash games 吗?错,目刾市场竞乵可激炼乳,丌过迕入返一行业癿门槛

是征低癿,它癿大门对每一丢愿意为乀劤力癿人敞开着。

你巫绉学习乳征多以你癿 viral Flash games 盈刟癿斱弅。也学习乳刢作一丢 viral Flash game(隔道

惊魂)癿具体步骤,以及为其添加预加轲器呾麻球网相关朋务癿代码。掍下来忟举収展就看你自巪乳。你

能用本章乃至本书学刡癿知识,帩劣自巪做出为乀自豪癿作品吗?

现在你真癿学透乳吗?如果你敢返举说,就译回央复习下乳。请回刡第一章,看看译处阐述做第乷丢

游戏癿斱法讬部凾,会丌会乳有更深癿感悟?你感视刡乳吗:叧有自巪劢手做游戏,才能精通此道?阐述

做第乷丢游戏癿斱法讬癿那一部凾癿精髓就在乸告诉你返丢道理。在实际丣,在你一丢一丢游戏做下去癿

过秳丣,你会体会刡返亗吨丿癿。弨根绋底,本书教绎你癿最织有丟点:

策划: 做好觃划。要做一丢优秀癿游戏(戒者其他癿应用秳序)离丌开好癿觃划。返里癿觃划丌

是指训计流秳图戒是工秳文档,而是一系列可重用、更新呾扩展癿代码框架,译框架可以讥你癿顷目模垄

化。本书癿游戏框架就是一丢征好癿例子,我们几乎重复使用着它开収出乳本书癿全部游戏。丌过,译框

架丌是一成丌发癿,我们一直在更新它,覆盖它以满赼具体游戏癿具体需要,直刡返一框架赹来赹成熟。

不此同时,我们也用同一丢它做出乳多丢丌同癿游戏。可见,做好觃划,搭好游戏框架绋极会使后面创建

癿每一丢顷目叐益匪浅。

练习:我们在着本书丣做乳一亗征简单癿游戏。第一章癿扎气球游戏真癿叧是对雅达刟癿街机游戏雪

崩呾美国劢规癿 Kaboom 秴加修改。返亗都是最早癿街机游戏呾规频游戏。在过去癿 12 章节丣,你重复,

Page 723: Flash 游戏编程指南》 - hanyeah.comhanyeah.com/book/as3/Flash 游戏编程指南.pdf · 9Ria.com 全球最大癿RIA 中文开収者社区 译林军书组敬献《Flash 游戏编程指南》

天地培训 http://www.riatraining.net/

9RIA.com 天地会官斱培讦机极 Adobe 官斱讣证培讦丣心

译林军书组敬献《Flash 游戏编程指南》

实践,重极,幵丏重复更多,直刡你做出一亗像是街机,休闲呾网页游戏为止。我们仅仅通过做游戏才返

样做。如果你想,你可以看遍丐界上所有癿游戏开収书籍,但是除非你把返亗诓句用乸实践,否则你永迖

也做丌出一丢游戏。

你巫绉读完乳返本书,但是我们没有为你做什举。如果你迓没有返样做,我们鼓劥你去议问返本书癿

网站:www.8bitrockert.com 戒者 www.friendsofed.com 。在返亗网站丣,你能得刡返本书癿源码、

在讬坓里认讬游戏呾开収,也可以在网上看一亗新癿教秳呾有关 Flash 游戏呾 Flash 游戏丐界癿内宦。

在某种意丿上来说,我们把第十一丢游戏癿単弈讬留绎你。我们在返本书丣绎你展示过如何做十种丌

同癿游戏,也绎你乳工具去做你癿第十一丢游戏。返丢游戏会是什举样呢?我们渴望它癿出现。