做一个像植物大战僵尸的Flash游戏5

现在,我们来到了这个教程的第5个阶段。
在这个阶段,我们会修改一个漏洞,这个漏洞允许植物开火只要有僵尸与植物处于同一行,不论僵尸是在植物的左边还是右边。同时我们也会增加僵尸攻击植物的功能。
首先,让我来解释一下一些改变:
在前面的步骤里,zombiesArray数组只存储每一行上的僵尸的数量。这个信息对我们想知道僵尸是在植物的左边还是右边是不够的,所以从现在开始zombiesArray改为一个二维数组,用来存储每一行上僵尸的名字。
你将会明白这一特性当我们讨论源代码的时候。
要使僵尸攻击植物,我们必须使他们停下来一旦他们与植物处于同一区块。
让我们来看源代码:

package {
        import flash.display.Sprite;
        import flash.utils.Timer;
        import flash.events.TimerEvent;
        import flash.events.MouseEvent;
        import flash.events.Event;
        import flash.text.TextField;
        public class Main extends Sprite {
                //
                // 一个2维数组用来存储游戏区块
                //
                private var plantsArray:Array;// 种植在游戏区域里的植物
                private var zombiesArray:Array;//在游戏区域里的僵尸
                // 
                // 计时器
                //
                private var flowersTimer:Timer=new Timer(5000);//计时器,使得阳光落下
                private var zombieTimer:Timer=new Timer(5000);// 计时器,让僵尸出场
                //
                // 容器
                //
                private var sunContainer:Sprite=new Sprite();// 所有阳光的容器
                private var plantContainer:Sprite=new Sprite();// 所有植物的容器
                public var bulletContainer:Sprite=new Sprite();// 所有子弹的容器
                private var zombieContainer:Sprite=new Sprite();// 所有僵尸的容器
                private var overlayContainer:Sprite=new Sprite();// 所有覆盖物的容器
                //
                // 我们的演员
                //
                private var movingPlant:plantMc;//  玩家在游戏区域能够拖动的植物
                private var selector:selectorMc;// 选择器(一个高亮的区块),告诉玩家他将把植物种在哪
                //
                // 其它变量
                //
                private var money:uint=0;// 玩家所拥有的金钱数量
                private var moneyText:TextField=new TextField  ;// 动态文本框,用来显示玩家的金钱
                private var playerMoving:Boolean=false;// 布尔型变量,标志玩家是否在移动一个植物
                private var totalZombies:uint=0;//僵尸的总数

                public function Main():void {
                        setupField();//初始化游戏区块
                        drawField();//画出游戏区块
                        fallingSuns();// 初始化下落的阳光
                        addPlants();// 初始化植物
                        addZombies();//初始化僵尸
                        addEventListener(Event.ENTER_FRAME,onEnterFrm);
                }
                //
                //  游戏区域设置,创建用来存储植物和僵尸信息的数组
                //
                private function setupField():void {
                        plantsArray=new Array();
                        zombiesArray=new Array();
                        for (var i:uint=0; i<5; i++) {
                                plantsArray[i]=new Array();
                                zombiesArray[i]=new Array();
                                for (var j:uint=0; j<9; j++) {
                                        plantsArray[i][j]=0;
                                }
                        }
                }
                //
                // 显示玩家的金钱
                //
                private function updateMoney():void {
                        moneyText.text="Money: "+money.toString();
                }
                //
                // 画出游戏区域
                //
                private function drawField():void {
                        var fieldSprite:Sprite=new Sprite();
                        var randomGreen:Number;
                        addChild(fieldSprite);
                        fieldSprite.graphics.lineStyle(1,0xFFFFFF);
                        for (var i:uint=0; i<5; i++) {
                                for (var j:uint=0; j<9; j++) {
                                        randomGreen=(125+Math.floor(Math.random()*50))*256;
                                        fieldSprite.graphics.beginFill(randomGreen);
                                        fieldSprite.graphics.drawRect(25+65*j,80+75*i,65,75);
                                }
                        }
                        addChild(sunContainer);
                        addChild(plantContainer);
                        addChild(bulletContainer);
                        addChild(zombieContainer);
                        addChild(overlayContainer);
                        overlayContainer.addChild(moneyText);
                        updateMoney();
                        moneyText.textColor=0xFFFFFF;
                        moneyText.height=20;
                }
                //
                // 初始化僵尸
                //
                private function addZombies():void {
                        zombieTimer.start();
                        zombieTimer.addEventListener(TimerEvent.TIMER,newZombie);
                }
                //
                // 增加一个新的僵尸
                //
                private function newZombie(e:TimerEvent):void {
                        var zombie:zombieMc=new zombieMc();// 构造僵尸
                        totalZombies++;
                        zombieContainer.addChild(zombie);// 增加僵尸
                        zombie.zombieRow=Math.floor(Math.random()*5);//生成随机行数,用于放置僵尸
                        zombie.name="zombie_"+totalZombies;//给僵尸一个名字
                        zombiesArray[zombie.zombieRow].push(zombie.name);// 增加第row行的僵尸
                        zombie.x=660;// 把僵尸放在屏幕的右边
                        zombie.y=zombie.zombieRow*75+115;
                }
                //
                // 初始化阳光
                //
                private function fallingSuns():void {
                        flowersTimer.start();
                        flowersTimer.addEventListener(TimerEvent.TIMER, newSun);
                }
                //
                // 增加一束新的阳光
                //
                private function newSun(e:TimerEvent):void {
                        var sunRow:uint=Math.floor(Math.random()*5);// 随机行
                        var sunCol:uint=Math.floor(Math.random()*9);// 随机列
                        var sun:sunMc = new sunMc();// 构造阳光
                        sun.buttonMode=true;// 当鼠标滑过阳光时,改变鼠标的形状
                        sunContainer.addChild(sun);// 加入显示列表
                        sun.x=52+sunCol*65;// 把阳光放在合适的位置
                        sun.destinationY=130+sunRow*75;// 定义阳光destinationY属性
                        sun.y=-20;// 把阳光放在舞台顶部的上方
                        sun.addEventListener(MouseEvent.CLICK,sunClicked);// 给阳光注册鼠标点击事件
                }
                //
                // 阳光的鼠标点击事件句柄
                //
                private function sunClicked(e:MouseEvent):void {
                        e.currentTarget.removeEventListener(MouseEvent.CLICK,sunClicked);// 移除鼠标事件侦听
                        money+=5;//让玩家赚到5个金币
                        updateMoney();// 更新动态文本
                        var sunToRemove:sunMc=e.currentTarget as sunMc;// 获得我们必须移除的阳光
                        sunContainer.removeChild(sunToRemove);// 移除该阳光
                }
                // 创建一个植物栏,现在只有一种植物
                //
                private function addPlants():void {
                        var plant:plantMc=new plantMc();// 构造一株新的植物
                        overlayContainer.addChild(plant);// 增加植物
                        plant.buttonMode=true;// 使鼠标改变形状,当它滑过新植物时
                        plant.x=90;
                        plant.y=40;
                        plant.addEventListener(MouseEvent.CLICK,onPlantClicked);// 给新植物注册鼠标点击事件
                }
                //
                // 植物的鼠标点击事件句柄
                //
                private function onPlantClicked(e:MouseEvent):void {
                        // 检查玩家是否有足够的钱(当前是10)来购买植物,并且是否正在拖动一个植物
                        if (money>=10&&! playerMoving) {
                                money-=10;// 付款
                                updateMoney();// 更新动态文本
                                selector=new selectorMc();// 创建一个新的选择器
                                selector.visible=false;// 使选择器不可见
                                overlayContainer.addChild(selector);// 把选择器加入到显示列表
                                movingPlant=new plantMc();// 构建一个新的供玩家拖动的植物
                                movingPlant.addEventListener(MouseEvent.CLICK,placePlant);// 给该植物注册一个鼠标点击事件
                                overlayContainer.addChild(movingPlant);// 把该植物加入到显示列表
                                playerMoving=true;// 告诉脚本正在移动一株植物
                        }
                }
                //
                // 把植物放置在游戏区域中
                //
                private function placePlant(e:MouseEvent):void {
                        var plantRow:int=Math.floor((mouseY-80)/75);
                        var plantCol:int=Math.floor((mouseX-25)/65);
                        // let's see if the tile is inside the game field and it's free
                        if (plantRow>=0&&plantCol>=0&&plantRow<5&&plantCol<9&&plantsArray[plantRow][plantCol]==0) {
                                var placedPlant:plantMc=new plantMc();// 构建一株植物,用来种植
                                placedPlant.name="plant_"+plantRow+"_"+plantCol;// 给植物一个名字
                                placedPlant.fireRate=75;// 植物的开火速率,单位帧
                                placedPlant.recharge=0;// 当recharge 等于 fireRate时,植物已经准备好开火了
                                placedPlant.isFiring=false;// 一个布尔变量来存储植物是否正在开火
                                placedPlant.plantRow=plantRow;// 植物所在的行
                                plantContainer.addChild(placedPlant);// 把该植物加入到显示列表
                                placedPlant.x=plantCol*65+57;
                                placedPlant.y=plantRow*75+115;
                                playerMoving=false;// 告诉脚本玩家不在移动植物了
                                movingPlant.removeEventListener(MouseEvent.CLICK,placePlant);// 移除事件侦听
                                overlayContainer.removeChild(selector);// 移除选择器
                                overlayContainer.removeChild(movingPlant);// 移除供拖动的植物
                                plantsArray[plantRow][plantCol]=1;//  更新游戏区块信息
                        }
                }
                //
                // 游戏循环,游戏的核心函数
                //
                private function onEnterFrm(e:Event):void {
                        var i:int;
                        var j:int;
                        //
                        // 植物管理
                        //
                        for (i=0; i<plantContainer.numChildren; i++) {
                                var currentPlant:plantMc=plantContainer.getChildAt(i) as plantMc;
                                // 让我们看看植物是否能开火
                                if (currentPlant.recharge==currentPlant.fireRate&&! currentPlant.isFiring) {
                                        // 检查是否有僵尸与植物处于同一行
                                        if (zombiesArray[currentPlant.plantRow].length>0) {
                                                // 遍历僵尸
                                                for (j=0; j<zombiesArray[currentPlant.plantRow].length>0; j++) {
                                                        var targetZombie:zombieMc=zombieContainer.getChildByName(zombiesArray[currentPlant.plantRow]

[j]) as zombieMc;// 获得第j个僵尸
                                                        // 如果僵尸在植物的右边
                                                        if (targetZombie.x>currentPlant.x) {
                                                                var bullet:bulletMc=new bulletMc();// 创建一个新子弹
                                                                bulletContainer.addChild(bullet);// 加入到显示列表
                                                                bullet.x=currentPlant.x;
                                                                bullet.y=currentPlant.y;
                                                                bullet.sonOf=currentPlant;// 存储该子弹是由哪一株植物射出的
                                                                currentPlant.recharge=0;// 重新准备开火
                                                                currentPlant.isFiring=true;// 植物正在开火
                                                                break;// 终止for循环
                                                        }
                                                }
                                        }
                                }
                                if (currentPlant.recharge<currentPlant.fireRate) {
                                        currentPlant.recharge++;
                                }
                        }
                        //
                        // 子弹管理
                        //
                        for (i=0; i<bulletContainer.numChildren; i++) {
                                var movingBullet:bulletMc=bulletContainer.getChildAt(i) as bulletMc;
                                movingBullet.x+=3;//把每个子弹向右移动3个像素
                                var firingPlant:plantMc=movingBullet.sonOf as plantMc;// 获得这个子弹是哪个植物射击的
                                // 让我们看看子弹是否飞出了舞台
                                if (movingBullet.x>650) {
                                        firingPlant.isFiring=false;// 植物不再处于正在开火的状态
                                        bulletContainer.removeChild(movingBullet);// 移除子弹
                                } else {
                                        for (j=0; j<zombieContainer.numChildren; j++) {
                                                var movingZombie:zombieMc=zombieContainer.getChildAt(j) as zombieMc;
                                                // 让我们看看植物是否被子弹击中
                                                if (movingZombie.hitTestPoint(movingBullet.x,movingBullet.y,true)) {
                                                        movingZombie.alpha-=0.3;//减少僵尸的能量(透明度)
                                                        firingPlant.isFiring=false;// 植物不再处于正在开火的状态
                                                        bulletContainer.removeChild(movingBullet);// 移除子弹
                                                        // 让我们看看僵尸的能量(透明度)是否降至为0了
                                                        if (movingZombie.alpha<0) {
                                                                zombiesArray[movingZombie.zombieRow].splice(zombiesArray

[movingZombie.zombieRow].indexOf(movingZombie.name),1);// 减少该行的僵尸 
                                                                zombieContainer.removeChild(movingZombie);// 移除显示列表
                                                        }
                                                        break;
                                                }
                                        }
                                }
                        }
                        //
                        // 僵尸管理
                        //
                        var zombieColumn:int;
                        for (i=0; i<zombieContainer.numChildren; i++) {
                                movingZombie=zombieContainer.getChildAt(i) as zombieMc;
                                zombieColumn = Math.floor((movingZombie.x-25)/65);// 得到僵尸所在的列
                                // 检查是否有植物与之处于同一个区块
                                if (zombieColumn<0||zombieColumn>8||plantsArray[movingZombie.zombieRow][zombieColumn]==0) {
                                        movingZombie.x-=0.5;// 每一个僵尸往左移动0.5个像素
                                } else {
                                        // 僵尸开始攻击!!
                                        var attackedPlant:plantMc=plantContainer.getChildByName("plant_"+movingZombie.zombieRow+"_"+zombieColumn) as 

plantMc;
                                        attackedPlant.alpha-=0.01;// drains plant energy
                                        //检查植物是否死了
                                        if (attackedPlant.alpha<0) {
                                                plantsArray[movingZombie.zombieRow][zombieColumn]=0;//把植物移出数组
                                                plantContainer.removeChild(attackedPlant);//移出显示列表
                                        }
                                }
                        }
                        //
                        // 阳光管理
                        //
                        for (i=0; i<sunContainer.numChildren; i++) {
                                var fallingSun:sunMc=sunContainer.getChildAt(i) as sunMc;
                                // 让我们看看阳光是否还在下落
                                if (fallingSun.y<fallingSun.destinationY) {
                                        fallingSun.y++;// 把阳光往下移动一个像素
                                } else {
                                        fallingSun.alpha-=0.01;//  使阳光淡出
                                        // 检查阳光是否消失了
                                        if (fallingSun.alpha<0) {
                                                fallingSun.removeEventListener(MouseEvent.CLICK,sunClicked);// 移除事件侦听
from the 

sun
                                                sunContainer.removeChild(fallingSun);// 移出显示列表
                                        }
                                }
                        }
                        //
                        // 安置植物
                        //
                        if (playerMoving) {
                                movingPlant.x=mouseX;
                                movingPlant.y=mouseY;
                                var plantRow:int=Math.floor((mouseY-80)/75);
                                var plantCol:int=Math.floor((mouseX-25)/65);
                                // 检查是否在游戏区域内
                                if (plantRow>=0&&plantCol>=0&&plantRow<5&&plantCol<9) {
                                        selector.visible=true;// 显示选择器
                                        selector.x=25+plantCol*65;
                                        selector.y=80+plantRow*75;
                                } else {
                                        selector.visible=false;// 隐藏选择器
                                }
                        }
                }
        }
}


在setupField函数中,zombiesArray变成了一个二维数组,一个元素代表一行:
private function setupField():void {
        plantsArray=new Array();
        zombiesArray=new Array();
        for (var i:uint=0; i<5; i++) {
                plantsArray=new Array();
                zombiesArray=new Array();
                for (var j:uint=0; j<9; j++) {
                        plantsArray[j]=0;
                }
        }
}
在newZombie函数中,我们根据僵尸所在的行,把僵尸的名字加入到zombiesArray的合适的位置:
private function newZombie(e:TimerEvent):void {
        var zombie:zombieMc=new zombieMc();// 构造僵尸
        totalZombies++;
        zombieContainer.addChild(zombie);// 加入到显示列表
        zombie.zombieRow=Math.floor(Math.random()*5);// 选择一个随机行来安置僵尸
        zombie.name="zombie_"+totalZombies;//给僵尸一个名字
        zombiesArray[zombie.zombieRow].push(zombie.name);//
增加第row行的僵尸
        zombie.x=660;// 把僵尸放在舞台右边
        zombie.y=zombie.zombieRow*75+115;
}
现在,整个判断一株植物是否能开火就被改成了这样:
if (currentPlant.recharge==currentPlant.fireRate&&! currentPlant.isFiring) {
        if (zombiesArray[currentPlant.plantRow].length>0) {
                for (j=0; j<zombiesArray[currentPlant.plantRow].length>0; j++) {
                        var targetZombie:zombieMc=zombieContainer.getChildByName(zombiesArray[currentPlant.plantRow][j]) as zombieMc;

zombie
                        if (targetZombie.x>currentPlant.x) {
                                var bullet:bulletMc=new bulletMc();
                                bulletContainer.addChild(bullet);
                                bullet.x=currentPlant.x;
                                bullet.y=currentPlant.y;
                                bullet.sonOf=currentPlant;
                                currentPlant.recharge=0;
                                currentPlant.isFiring=true;
                                break;
                        }
                }
        }
}
我们遍历了所有与植物处于同一行上的僵尸,然后检查僵尸是在植物的左边还是在植物的右边(第214行)。

下面几行简单的代码使得僵尸攻击植物:
var zombieColumn:int;
for (i=0; i<zombieContainer.numChildren; i++) {
        movingZombie=zombieContainer.getChildAt(i) as zombieMc;
        zombieColumn = Math.floor((movingZombie.x-25)/65);
        if (zombieColumn<0||zombieColumn>8||plantsArray[movingZombie.zombieRow][zombieColumn]==0) {
                movingZombie.x-=0.5;
        } else {
                var attackedPlant:plantMc=plantContainer.getChildByName("plant_"+movingZombie.zombieRow+"_"+zombieColumn) as plantMc;
                attackedPlant.alpha-=0.01;
                if (attackedPlant.alpha<0) {
                        plantsArray[movingZombie.zombieRow][zombieColumn]=0;
                        plantContainer.removeChild(attackedPlant);
                }
        }
}
我们先检查了是否有植物被安置在僵尸当前所在的区块上,如果有,僵尸就停下脚步然后开始攻击植物,减少植物的生命值(当前是透明度)。
下面是结果:

http://www.emanueleferonato.com/wp-content/uploads/2011/03/pvz.swf


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值