之前我们用flash cs工具做过一个打砖块的游戏,那么现在使用flash Builder可以更加容易地做出具备更多功能,在这个例子中,我们主要要做的是让大家明白三点:一,如何在纯代码条件下绘图;二,充分理解面向对象编程的优势,学会使用良好的MVC(数据-视图-控制三元素分离)思想和良好的代码结构来构建我们的工程。列位道友千万不要把我的教程当做新手基础教材在看,我的教程的目的旨在让列位道友看过《殿堂之路》或一系列基础教材并对AS面向对象编程有所认识的基础上在通过我举出的案例了解这些知识,这些类该如何使用到实际开发中去,并增加开发熟练度。所以今天的教程不会把太多篇幅放在解释一些非常基础的东东,若有不明白的地方还请联系我或者天地会众多弟兄,最好还是自己看看教材多琢磨琢磨吧^_^。
相信不少兄弟都听说过MVC,这是一种非常好的设计思想,将工程做成数据-视图-控制三元素分离的话将会非常便于修改和维护。我们先从简单的M-V开始,暂时不涉及到C。先为各位介绍一个概念叫做ValueObject,简称VO,它是一个数据结构体,和C语言中的类似,其中只定义了一系列的变量,一般不带有任何逻辑性的函数,项目中的M,即数据层一般都由许许多多个VO组成,它为视图提供数据。比如我们的打砖块游戏里,玩家操作的底板所需的所有数据都可以放到一个VO中,我们给它取个名字叫PadVO,它内部的初步构造为:
- package org.moon.vo
- {
- public class PadVO
- {
- public static const EXPAND_WIDTH : int = 60;//前三个常量定义了板处于三种不同长度状态时的长度各为多少,第四个则定义了不会改变的板高度
- public static const NORMAL_WIDTH : int = 40;
- public static const SUBSTRACT_WIDTH : int = 20;
- public static const HEIGHT : int = 10;
- public static const STATUS_NORMAL : int = 0;//三个状态各自对应的编号
- public static const STATUS_EXPAND : int = 1;
- public static const STATUS_SUBSTRACT : int = 2;
- public var status : int = 0;//板状态,每个状态对应不同长度的板,在吃了道具后会改变
- public var posX : int;//板的x轴位置
- public var posY : int;//板的y轴位置
- }
- }
暂时在游戏中我们就需要这三个数据,所以就定义了这三个,以后若再有数据上的需求,可以很方便地在这里面添加,记得把这些变量都定义为public的让外部能够拿到,在VO中尽量少地定义private的变量,因为VO存在的意义就是为外部视图提供数据支持。一般需要操作数据的视图都需要个VO来与之配对,所以接下来就来看看我们的底板视图类
PadView:
- package com.life.view
- {
- import flash.display.Sprite;
- import com.life.vo.PadVO;
- public class PadView extends Sprite
- {
- public var padVO : PadVO;
- public function PadView()
- {
- super();
- }
- public function updatePos( ) : void {
- x = padVO.posX;
- y = padVO.posY;
- }
- public function updateGraph( ) : void {
- graphics.clear( );
- graphics.beginFill(0);
- switch(padVO.status) {
- case PadVO.STATUS_NORMAL:
- graphics.drawRect(-PadVO.NORMAL_WIDTH / 2, -PadVO.HEIGHT / 2, PadVO.NORMAL_WIDTH, PadVO.HEIGHT);
- break;
- case PadVO.STATUS_EXPAND:
- graphics.drawRect(-PadVO.EXPAND_WIDTH / 2, -PadVO.HEIGHT / 2, PadVO.EXPAND_WIDTH, PadVO.HEIGHT);
- break;
- case PadVO.STATUS_SUBSTRACT:
- graphics.drawRect(-PadVO.SUBSTRACT_WIDTH / 2, -PadVO.HEIGHT / 2, PadVO.SUBSTRACT_WIDTH, PadVO.HEIGHT);
- break;
- }
- graphics.endFill( );
- }
- }
- }
这样的类中应该没有什么难懂的代码,我们看到它内部含有一个与之对应的PadVO实例来提供数据支持。唯一需要注意的地方就是在updateGraph()函数中对不同类型的板要绘制不同的长度,这里必须把绘制Rect的左上角坐标定义为负的长度和宽度,因为我们得保证板的中心点位置必须保持在视图的中心位置才行。有的道友可能会问,我那些sprite的视图类中都有x,y变量来表示这个类的位置了,干嘛还在它对应的VO中定义个什么xPos,yPos呢,岂不是多此一举?我的回答是,若是多此一举我还写这些干嘛,我还怎么在列位仙家中混……直接使用视图的x,y来进行数据运算是一个非常具局限性的办法,因为你一旦改变了它们,视图就马上发生了位移,可能造成bug,比如你想多次改变PadView的横坐标,若直接操作它的x值将会看见底板自动乱跑,若是使用其内部的数据对象VO来进行运算,不论做多少次运算,在你调用updatePos()方法之前视图的位置都不会发生改变。
暂时先说这些吧,今天这个案例和以往比较起来算是比较大了,所以需要我多次续写才行……
继续我们上次没说完的话题吧,上回我们写到我们打砖块游戏所需的底板它的视图以及和它对应的VO,有了这两个东西我们的底板就算构建完成了,在PadView 类中,我们定义了两个public的方法updatePos()和updateGraph(),前者用来更新视图的位置,后者用来更新视图的外观,有了这两个方法我们就差不多可以在外部灵活地操作一个底板了。接下来我们需要一起来构建我们的小球类,依照和创建底板类一样的创建流程,我们就可以轻松地写出以下两个文件:
BallVO:
- package com.life.vo
- {
- public class BallVO
- {
- public var posX : int;
- public var posY : int;
- public var speedX : Number;
- public var speedY : Number;
- }
- }
BallView:
- package com.life.view
- {
- import flash.display.Sprite;
- import com.life.vo.BallVO;
- public class BallView extends Sprite
- {
- public var ballVO : BallVO;
- public function BallView()
- {
- init( );
- }
- public function updatePos( ) : void {
- x = ballVO.posX;
- y = ballVO.posY;
- }
- private function init( ) : void {
- graphics.beginFill(0);
- graphics.drawCircle(0,0,10);
- graphics.endFill();
- }
- }
- }
是不是一眼就能看懂了?它们唯一不同之处就在于小球不需要改变视图,因为它不像底板一样能够根据吃到的道具变长或者变短,所以我们只需要在初始化的时候就给它画好外形即可。
接下来轮到今天的主角“砖块”出场了,考虑到砖块有多种形态:有的被打掉后会掉落物品,掉落的物品又分两种(你也可以分多种),一种物品吃了可以增加你的长度(自从吃了这个物品,老婆说你越来越棒了),一种吃了会使你变短(遥想当年,哥也是驰骋过夜总会的男人……);有的砖块是如此地强壮,以至于你一击无法将其击破……那么我们应该如何做呢?
想必大家之前在看这篇帖子前一定学过了“继承”的概念,但只是知道有这么个概念并不知道怎么用,今天我们就来用一下它,看看继承的好处在哪里。在动手写代码前我们需要想一想所有这些不同种类的砖块的共同之处有哪些地方,一,是他们内部都必须有一个和之对应的VO来提供数据;二,他们都需要有方法来让外部调用以更新其外观及位置。好了,暂时我就想到这两点,以后若有需要再扩充吧……OK,let`s fucking go!
BrickVO:
- package com.life.vo
- {
- public class BrickVO
- {
- public static const NORMAL : int = 0;
- public static const HARD : int = 1;
- public static const SUPER_HARD : int = 2;
- public static const EXPAND : int = 3;
- public static const SUBSTRACT : int = 4;
- public static const WIDTH : int = 30;
- public static const HEIGHT : int = 10;
- public var hitCount : int = 0; //撞击计数
- public var type : int;
- public var posX : int;
- public var posY : int;
- }
- }
BaseBrickView:
- package com.life.view
- {
- import flash.display.Sprite;
- import com.life.vo.BrickVO;
- public class BaseBrickView extends Sprite
- {
- public var brickVO : BrickVO
- public function BaseBrickView()
- {
- super();
- }
- public function updatePos( ) : void {
- x = brickVO.posX;
- y = brickVO.posY;
- }
- public function updateGraph( ) : void {
- graphics.clear( );
- graphics.beginFill(0);
- graphics.drawRect(0,0,BrickVO.WIDTH,BrickVO.HEIGHT);
- graphics.endFill( );
- }
- }
- }
需要提醒的是,我们不要忽略常量(即以static const定义的东东)的作用,在我之前列出的视图类中在绘画时使用的长和宽都使用了常量来代替单纯的数字,其好处有两点:
1、降低写错的可能性:我们知道,在FB中有着强大的代码提示功能,按Alt + / 快捷键就能弹出代码提示框,利用这一点,我们定义常量来代替基础数据类型的话可以在编码时获得代码提示,防止我们在写数字时漏掉一个0或者什么,在写字符串时写错字母位置等等。
2、便于修改:当我们在所有需要一个数据(比如我们这里的砖块长、宽)的地方都使用一个常量来代替基础数据类型时,当我们需要修改数据时只需要修改这个常量的值即可在工程中所有用到之的地方一起改变,不需要手动去一个个文件地找了,费时不说还很容易漏掉。(如果我们没把砖块长度定义为一个常量BrickVO.WIDTH,在所有绘图的地方都用30来代替,那么当我们需要修改砖块长度时就必须到一个个文件去找这个“30”并改之,当工程大的时候很麻烦还容易漏掉几处)。
有了老爹,接下来就改创建他他的子孙了。先创建“奖励砖块”和“惩罚砖块”:
ExpandBrick:
- package com.life.view.brick
- {
- import com.life.view.BaseBrickView;
- import com.life.vo.BrickVO;
- public class ExpandBrick extends BaseBrickView
- {
- public function ExpandBrick()
- {
- super();
- }
- override public function updateGraph( ):void {
- graphics.clear();
- graphics.beginFill(0x000ff0);
- graphics.drawRect(0,0,5, BrickVO.HEIGHT);//至于这里一连串语句到底画出来是个什么鬼东西,运行一下看结果就晓得了
- graphics.drawRect(6,0,5, BrickVO.HEIGHT);
- graphics.drawRect(12,0,5, BrickVO.HEIGHT);
- graphics.drawRect(18,0,5, BrickVO.HEIGHT);
- graphics.drawRect(24,0,5, BrickVO.HEIGHT);
- graphics.endFill( );
- }
- }
- }
SubstractBrick:
- package com.life.view.brick
- {
- import com.life.view.BaseBrickView;
- import com.life.vo.BrickVO;
- public class SubstractBrick extends BaseBrickView
- {
- public function SubstractBrick()
- {
- super();
- }
- override public function updateGraph( ):void {
- graphics.clear();
- graphics.beginFill(0x0ff000);
- graphics.drawCircle(3,BrickVO.HEIGHT / 2,3);
- graphics.drawCircle(9,BrickVO.HEIGHT / 2,3);
- graphics.drawCircle(15,BrickVO.HEIGHT / 2,3);
- graphics.drawCircle(21,BrickVO.HEIGHT / 2,3);
- graphics.drawCircle(27,BrickVO.HEIGHT / 2,3);
- graphics.endFill( );
- }
- }
- }
它们与它们的老子唯一不同的地方也就是长得不一样罢了。再来看“加强型砖块”与“超强型砖块”:
HardBrick:
- package com.life.view.brick
- {
- import com.life.view.BaseBrickView;
- import com.life.vo.BrickVO;
- public class HardBrick extends BaseBrickView
- {
- public function HardBrick()
- {
- super();
- }
- override public function updateGraph( ):void {
- graphics.clear();
- switch(brickVO.hitCount){
- case 0:
- graphics.beginFill(0x0000ff);
- break;
- case 1:
- graphics.beginFill(0x000000);
- break;
- }
- graphics.drawRect(0,0,BrickVO.WIDTH, BrickVO.HEIGHT);
- }
- }
- }
SuperHardBrick:
- package com.life.view.brick
- {
- import com.life.view.BaseBrickView;
- import com.life.vo.BrickVO;
- public class SuperHardBrick extends BaseBrickView
- {
- public function SuperHardBrick()
- {
- super();
- }
- override public function updateGraph( ):void {
- graphics.clear();
- switch(brickVO.hitCount){
- case 0:
- graphics.beginFill(0x00ff00);
- break;
- case 1:
- graphics.beginFill(0x0000ff);
- break;
- case 2:
- graphics.beginFill(0x000000);
- break;
- }
- graphics.drawRect(0,0,BrickVO.WIDTH, BrickVO.HEIGHT);
- }
- }
- }
我们看到这两位耐打型选手的updateGraph()方法中有点不一样的玩意儿,它会在每次被调用时根据其VO中记录的被撞击次数来更新其外形,挨打前后的颜色不一样。
若你想在子类中绘制和父类一样的图形,即执行和父类updateGraph()方法中一模一样的代码,那么在加上了override重载关键字的updateGraph方法中可以通过使用super.updateGraph()来做到, 也可以直接不用写这个新的updateGraph(),因为他默认已继承了父类的此方法。在这里我们需要画和父类不一样的外表,所以在所有砖块子类中都需要使用override关键字来重载updateGraph方法。
最后,别忘了我们还有一样东东要添加,那就是我们的道具类,依然是M-V的结构:
BonusVO:
- package com.life.vo
- {
- public class BonusVO
- {
- public static const EXPAND : int = 0;
- public static const SUBSTRACT : int = 1;
- public var dropSpeed : int = 5;
- public var type : int;
- public var posX : int;
- public var posY : int;
- }
- }
BonusView:
- package com.life.view
- {
- import flash.display.Sprite;
- import com.life.vo.BonusVO;
- public class BonusView extends Sprite
- {
- public var bonusVO : BonusVO;
- public function BonusView()
- {
- super();
- }
- public function updatePos( ) : void {
- x = bonusVO.posX;
- y = bonusVO.posY;
- }
- public function updateGraphic( ) : void {
- switch(bonusVO.type){
- case BonusVO.EXPAND:
- graphics.beginFill(0x00ffff)
- graphics.drawEllipse(0,0,10,4);
- break;
- case BonusVO.SUBSTRACT:
- graphics.beginFill(0xffff00);
- graphics.drawEllipse(0,0,4,10);
- break;
- }
- graphics.endFill( );
- }
- }
- }
道具分为两种,一种是增大增粗的ZYY一种是变小变细的萎哥,在VO里分别用常量定义之并在VIEW里根据他们类型不同绘制不同外形。
好了,最后我们要做的就只剩把这些零碎的元素组合起来了,带来我们今天的终极BOSS:
GameLayer:
- package com.life.view
- {
- import flash.display.Sprite;
- import flash.events.Event;
- import com.life.view.brick.ExpandBrick;
- import com.life.view.brick.HardBrick;
- import com.life.view.brick.SubstractBrick;
- import com.life.view.brick.SuperHardBrick;
- import com.life.vo.BallVO;
- import com.life.vo.BonusVO;
- import com.life.vo.BrickVO;
- import com.life.vo.PadVO;
- public class GameLayer extends Sprite
- {
- private const RESTRICT_TOP : int = 0;
- private const RESTRICT_LEFT : int = 0;
- private const RESTRICT_RIGHT : int = 400;
- private const RESTRICT_BOTTOM : int = 400;
- private var ballView : BallView;
- private var padView : PadView;
- private var brickViewList : Array = new Array( );
- private var dropItemViewList : Array = new Array( );
- public function GameLayer()
- {
- super( );
- init( );
- }
- private function init( ) : void {
- initBallView( );
- initBricksView( );
- initPadView( );
- initListener( );
- }
- private function initBallView( ) : void {
- ballView = new BallView( );
- var tmpBallVO : BallVO = new BallVO( );
- tmpBallVO.posX = 100;
- tmpBallVO.posY = 300;
- tmpBallVO.speedY = -5;
- tmpBallVO.speedX = 2;
- ballView.ballVO = tmpBallVO;
- ballView.updatePos( );
- addChild(ballView);
- }
- private function initBricksView( ) : void {
- for(var i : int = 0; i < 50; i++) {
- var tmpVO : BrickVO = new BrickVO( );
- tmpVO.posX = 50 + i % 10 * 40;
- tmpVO.posY = 50 + int(i / 10) * 30;
- tmpVO.type = Math.floor(5 * Math.random());
- var tmpView : BaseBrickView = getBrick(tmpVO.type);
- tmpView.brickVO = tmpVO;
- tmpView.updatePos( );
- tmpView.updateGraph( );
- brickViewList.push(tmpView);
- addChild(tmpView);
- }
- }
- private function initPadView( ) : void {
- padView = new PadView( );
- var tmpPadVO : PadVO = new PadVO( );
- tmpPadVO.posX = 200;
- tmpPadVO.posY = 300;
- padView.padVO = tmpPadVO;
- padView.updatePos( );
- padView.updateGraph( );
- addChild(padView);
- }
- private function initListener( ) : void {
- addEventListener(Event.ENTER_FRAME, efHandler);
- }
- private function efHandler(event : Event) : void {
- movePad( );
- moveBall( );
- moveBonus( );
- checkBallHit( );
- }
- private function movePad( ) : void {
- padView.padVO.posX = mouseX;
- padView.updatePos( );
- }
- private function moveBall( ) : void {
- var tmpBallVO : BallVO = ballView.ballVO;
- tmpBallVO.posX += tmpBallVO.speedX;
- tmpBallVO.posY += tmpBallVO.speedY;
- ballView.updatePos( );
- }
- private function moveBonus( ) : void {
- for each(var elem : BonusView in dropItemViewList) {
- elem.bonusVO.posY += elem.bonusVO.dropSpeed;
- elem.updatePos( );
- }
- }
- private function checkBallHit( ) : void {
- //检测砖块碰撞
- checkBrickHit( );
- //检测小板碰撞
- checkPadHit( );
- //检测边界碰撞
- checkEdgeHit(ballView.ballVO);
- //检测是否吃到奖励
- checkBonusHit( );
- }
- private function checkBrickHit( ) : void {
- for(var i : int = 0; i < brickViewList.length; i++) {
- if(brickViewList[i].hitTestObject(ballView)){
- //改变速度
- ballView.ballVO.speedY *= -1;
- (brickViewList[i] as BaseBrickView).brickVO.hitCount++;
- //移除砖块
- if(checkBrickToRemove(brickViewList[i].brickVO)){
- dropBonusItem(brickViewList[i].brickVO);
- //移除
- removeChild(brickViewList[i]);
- brickViewList.splice(i,1);
- i--;
- }else{
- //不移除则更新样式
- (brickViewList[i] as BaseBrickView).updateGraph( );
- }
- }
- }
- }
- private function checkPadHit( ) : void {
- if(ballView.hitTestObject(padView)){
- ballView.ballVO.speedY = -ballView.ballVO.speedY;
- //改变水平坐标的碰撞
- ballView.ballVO.speedX = (ballView.ballVO.posX - padView.padVO.posX) / 5;
- }
- }
- private function checkEdgeHit(tmpBallVO : BallVO) : void {
- if(tmpBallVO.posX > RESTRICT_RIGHT || tmpBallVO.posX < RESTRICT_LEFT){
- tmpBallVO.speedX = -tmpBallVO.speedX;
- }
- if(tmpBallVO.posY > RESTRICT_BOTTOM || tmpBallVO.posY < RESTRICT_TOP) {
- tmpBallVO.speedY = -tmpBallVO.speedY;
- }
- }
- private function checkBonusHit( ) : void {
- for(var i : int = 0; i < dropItemViewList.length; i++) {
- if(dropItemViewList[i].hitTestObject(padView)){
- //移除砖块
- //触发碰撞特效
- doHitEffect(dropItemViewList[i].bonusVO.type);
- //移除
- removeChild(dropItemViewList[i]);
- dropItemViewList.splice(i,1);
- i--;
- }
- }
- }
- private function dropBonusItem(brickVO : BrickVO) : void {
- var tmpBonusView : BonusView;
- var tmpBonusVO : BonusVO = new BonusVO( );
- switch(brickVO.type){
- case BrickVO.EXPAND: tmpBonusVO.type = BonusVO.EXPAND; break;
- case BrickVO.SUBSTRACT: tmpBonusVO.type = BonusVO.SUBSTRACT; break;
- }
- switch(brickVO.type){
- case BrickVO.EXPAND:
- case BrickVO.SUBSTRACT:
- tmpBonusVO.posX = brickVO.posX;
- tmpBonusVO.posY = brickVO.posY;
- tmpBonusView = new BonusView( );
- tmpBonusView.bonusVO = tmpBonusVO;
- tmpBonusView.updateGraphic();
- dropItemViewList.push(tmpBonusView);
- addChild(tmpBonusView);
- break;
- default:
- break;
- }
- }
- private function doHitEffect(type : int) : void {
- switch(type){
- case BonusVO.EXPAND:
- padView.padVO.status = PadVO.STATUS_EXPAND;
- padView.updateGraph( );
- break;
- case BonusVO.SUBSTRACT:
- padView.padVO.status = PadVO.STATUS_SUBSTRACT;
- padView.updateGraph( );
- break;
- }
- }
- private function checkBrickToRemove(brickVO : BrickVO) : Boolean {
- switch(brickVO.type){
- case BrickVO.NORMAL:
- case BrickVO.SUBSTRACT:
- case BrickVO.EXPAND:
- if(brickVO.hitCount >= 1) return true;
- break;
- case BrickVO.HARD:
- if(brickVO.hitCount >= 2) return true;
- break;
- case BrickVO.SUPER_HARD:
- if(brickVO.hitCount >= 3) return true;
- break;
- }
- return false;
- }
- /**
- * 按砖块类型返还相应实例
- */
- private function getBrick(type : int) : BaseBrickView {
- switch(type){
- case BrickVO.EXPAND:
- return new ExpandBrick( );
- break;
- case BrickVO.HARD:
- return new HardBrick( );
- break;
- case BrickVO.SUBSTRACT:
- return new SubstractBrick( );
- break;
- case BrickVO.SUPER_HARD:
- return new SuperHardBrick( );
- break;
- default:
- return new BaseBrickView( );
- break
- }
- }
- }
- }
在init函数中初始化了一我们游戏所需的三要素:球、底板以及砖块并添加了事件侦听器,初始化时遵循先数据再视图的原则,在生成砖块时还需要随机出每块砖的类型,别忘了在那些没有设置过位置或外观的view中需调用updatePos()或者updateGraph()来设置一下。再看到我们的重点——efHandler函数。先看movePad(),它的代码没什么难度,就是把板的位置和鼠标位置绑定住并调用updatePos来更新视图的坐标,记住哦,在调用updatePos之前必须得先改变其中VO的响应数据xPos,yPos才行。继续看moveBall(),也没什么难度,在ballView内部VO已设置过速度的情况下只要把位置加上速度即可。在每产生一个道具时都会被第一时间添加到一个叫做dropItemViewList的数组中收集起来,moveBonus()中做的事情就是把dropItemViewList中所有道具同步移动,让它们一起下落,若dropItemViewList中没有元素,则什么也不会发生。最后看看checkBallHit(),这才是主要难点所在哦,它由四个功能函数联手工作。
先看checkBrickHit()函数吧,它的职责是检测球是否撞到了砖块,并处理撞到后的逻辑。至于如何判断球与砖块的碰撞,相信看过我教程三的道友们已经闭着眼睛都能写出来了,关键是碰撞到之后的逻辑该如何处理。第一步无疑是反弹小球,第二步我们看到这句代码:
- (brickViewList[i] as BaseBrickView).brickVO.hitCount++;
接下来让我们看下面这个条件语句:
- if(checkBrickToRemove(brickViewList[i].brickVO)){
- dropBonusItem(brickViewList[i].brickVO);
- //移除
- removeChild(brickViewList[i]);
- brickViewList.splice(i,1);
- i--;
- }else{
- //不移除则更新样式
- (brickViewList[i] as BaseBrickView).updateGraph( );
- }
接下来再看checkPadHit(),这里有疑问的一句就是
- //改变水平坐标的碰撞
- ballView.ballVO.speedX = (ballView.ballVO.posX - padView.padVO.posX) / 5;
<ignore_js_op>
接下来的边界检测不用说各位也懂的,若你想让球触碰舞台底部让游戏结束,就改变一下这里面的代码好了。最后的这个checkBonusHit()函数中也没什么难点,若各位道友有疑问请跟贴发问,我一般都会解答的。
写完最后的这个GameLayer.as文件后可直接把该文件设为默认应用程序启动,也可以集成到一个总应用中,像我这样:
MainGame:
- package {
- import flash.display.Sprite;
- import com.life.view.GameLayer;
- [SWF(width="500", height="500", frameRate="30")]
- public class MainGame extends Sprite
- {
- private var gameLayer : GameLayer;
- public function MainGame()
- {
- init( );
- }
- private function init( ) : void {
- initGameLayer( );
- }
- private function initGameLayer( ) : void {
- gameLayer = new GameLayer( );
- addChild(gameLayer);
- }
- }
- }
最后看看结果是不是和我们想象中的那样:http://www.iamsevent.com/upload/AdvanceBrickGame.swf
附上大家翘首以盼的源码,记得把它们放在src目录下哦。
<ignore_js_op> AdvanceBrickGame.rar (6.41 KB, 下载次数: 663)