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

 http://bbs.9ria.com/thread-83537-1-3.html

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

  1. package {
  2.         import flash.display.Sprite;
  3.         import flash.utils.Timer;
  4.         import flash.events.TimerEvent;
  5.         import flash.events.MouseEvent;
  6.         import flash.events.Event;
  7.         import flash.text.TextField;
  8.         public class Main extends Sprite {
  9.                 //
  10.                 // 一个2维数组用来存储游戏区块
  11.                 //
  12.                 private var plantsArray:Array;// 种植在游戏区域里的植物
  13.                 private var zombiesArray:Array;//在游戏区域里的僵尸
  14.                 //
  15.                 // 计时器
  16.                 //
  17.                 private var flowersTimer:Timer=new Timer(5000);//计时器,使得阳光落下
  18.                 private var zombieTimer:Timer=new Timer(5000);// 计时器,让僵尸出场
  19.                 //
  20.                 // 容器
  21.                 //
  22.                 private var sunContainer:Sprite=new Sprite();// 所有阳光的容器
  23.                 private var plantContainer:Sprite=new Sprite();// 所有植物的容器
  24.                 public var bulletContainer:Sprite=new Sprite();// 所有子弹的容器
  25.                 private var zombieContainer:Sprite=new Sprite();// 所有僵尸的容器
  26.                 private var overlayContainer:Sprite=new Sprite();// 所有覆盖物的容器
  27.                 //
  28.                 // 我们的演员
  29.                 //
  30.                 private var movingPlant:plantMc;//  玩家在游戏区域能够拖动的植物
  31.                 private var selector:selectorMc;// 选择器(一个高亮的区块),告诉玩家他将把植物种在哪
  32.                 //
  33.                 // 其它变量
  34.                 //
  35.                 private var money:uint=0;// 玩家所拥有的金钱数量
  36.                 private var moneyText:TextField=new TextField  ;// 动态文本框,用来显示玩家的金钱
  37.                 private var playerMoving:Boolean=false;// 布尔型变量,标志玩家是否在移动一个植物
  38.                 private var totalZombies:uint=0;//僵尸的总数

  39.                 public function Main():void {
  40.                         setupField();//初始化游戏区块
  41.                         drawField();//画出游戏区块
  42.                         fallingSuns();// 初始化下落的阳光
  43.                         addPlants();// 初始化植物
  44.                         addZombies();//初始化僵尸
  45.                         addEventListener(Event.ENTER_FRAME,onEnterFrm);
  46.                 }
  47.                 //
  48.                 //  游戏区域设置,创建用来存储植物和僵尸信息的数组
  49.                 //
  50.                 private function setupField():void {
  51.                         plantsArray=new Array();
  52.                         zombiesArray=new Array();
  53.                         for (var i:uint=0; i<5; i++) {
  54.                                 plantsArray[i]=new Array();
  55.                                 zombiesArray[i]=new Array();
  56.                                 for (var j:uint=0; j<9; j++) {
  57.                                         plantsArray[i][j]=0;
  58.                                 }
  59.                         }
  60.                 }
  61.                 //
  62.                 // 显示玩家的金钱
  63.                 //
  64.                 private function updateMoney():void {
  65.                         moneyText.text="Money: "+money.toString();
  66.                 }
  67.                 //
  68.                 // 画出游戏区域
  69.                 //
  70.                 private function drawField():void {
  71.                         var fieldSprite:Sprite=new Sprite();
  72.                         var randomGreen:Number;
  73.                         addChild(fieldSprite);
  74.                         fieldSprite.graphics.lineStyle(1,0xFFFFFF);
  75.                         for (var i:uint=0; i<5; i++) {
  76.                                 for (var j:uint=0; j<9; j++) {
  77.                                         randomGreen=(125+Math.floor(Math.random()*50))*256;
  78.                                         fieldSprite.graphics.beginFill(randomGreen);
  79.                                         fieldSprite.graphics.drawRect(25+65*j,80+75*i,65,75);
  80.                                 }
  81.                         }
  82.                         addChild(sunContainer);
  83.                         addChild(plantContainer);
  84.                         addChild(bulletContainer);
  85.                         addChild(zombieContainer);
  86.                         addChild(overlayContainer);
  87.                         overlayContainer.addChild(moneyText);
  88.                         updateMoney();
  89.                         moneyText.textColor=0xFFFFFF;
  90.                         moneyText.height=20;
  91.                 }
  92.                 //
  93.                 // 初始化僵尸
  94.                 //
  95.                 private function addZombies():void {
  96.                         zombieTimer.start();
  97.                         zombieTimer.addEventListener(TimerEvent.TIMER,newZombie);
  98.                 }
  99.                 //
  100.                 // 增加一个新的僵尸
  101.                 //
  102.                 private function newZombie(e:TimerEvent):void {
  103.                         var zombie:zombieMc=new zombieMc();// 构造僵尸
  104.                         totalZombies++;
  105.                         zombieContainer.addChild(zombie);// 增加僵尸
  106.                         zombie.zombieRow=Math.floor(Math.random()*5);//生成随机行数,用于放置僵尸
  107.                         zombie.name="zombie_"+totalZombies;//给僵尸一个名字
  108.                         zombiesArray[zombie.zombieRow].push(zombie.name);// 增加第row行的僵尸
  109.                         zombie.x=660;// 把僵尸放在屏幕的右边
  110.                         zombie.y=zombie.zombieRow*75+115;
  111.                 }
  112.                 //
  113.                 // 初始化阳光
  114.                 //
  115.                 private function fallingSuns():void {
  116.                         flowersTimer.start();
  117.                         flowersTimer.addEventListener(TimerEvent.TIMER, newSun);
  118.                 }
  119.                 //
  120.                 // 增加一束新的阳光
  121.                 //
  122.                 private function newSun(e:TimerEvent):void {
  123.                         var sunRow:uint=Math.floor(Math.random()*5);// 随机行
  124.                         var sunCol:uint=Math.floor(Math.random()*9);// 随机列
  125.                         var sun:sunMc = new sunMc();// 构造阳光
  126.                         sun.buttonMode=true;// 当鼠标滑过阳光时,改变鼠标的形状
  127.                         sunContainer.addChild(sun);// 加入显示列表
  128.                         sun.x=52+sunCol*65;// 把阳光放在合适的位置
  129.                         sun.destinationY=130+sunRow*75;// 定义阳光destinationY属性
  130.                         sun.y=-20;// 把阳光放在舞台顶部的上方
  131.                         sun.addEventListener(MouseEvent.CLICK,sunClicked);// 给阳光注册鼠标点击事件
  132.                 }
  133.                 //
  134.                 // 阳光的鼠标点击事件句柄
  135.                 //
  136.                 private function sunClicked(e:MouseEvent):void {
  137.                         e.currentTarget.removeEventListener(MouseEvent.CLICK,sunClicked);// 移除鼠标事件侦听
  138.                         money+=5;//让玩家赚到5个金币
  139.                         updateMoney();// 更新动态文本
  140.                         var sunToRemove:sunMc=e.currentTarget as sunMc;// 获得我们必须移除的阳光
  141.                         sunContainer.removeChild(sunToRemove);// 移除该阳光
  142.                 }
  143.                 // 创建一个植物栏,现在只有一种植物
  144.                 //
  145.                 private function addPlants():void {
  146.                         var plant:plantMc=new plantMc();// 构造一株新的植物
  147.                         overlayContainer.addChild(plant);// 增加植物
  148.                         plant.buttonMode=true;// 使鼠标改变形状,当它滑过新植物时
  149.                         plant.x=90;
  150.                         plant.y=40;
  151.                         plant.addEventListener(MouseEvent.CLICK,onPlantClicked);// 给新植物注册鼠标点击事件
  152.                 }
  153.                 //
  154.                 // 植物的鼠标点击事件句柄
  155.                 //
  156.                 private function onPlantClicked(e:MouseEvent):void {
  157.                         // 检查玩家是否有足够的钱(当前是10)来购买植物,并且是否正在拖动一个植物
  158.                         if (money>=10&&! playerMoving) {
  159.                                 money-=10;// 付款
  160.                                 updateMoney();// 更新动态文本
  161.                                 selector=new selectorMc();// 创建一个新的选择器
  162.                                 selector.visible=false;// 使选择器不可见
  163.                                 overlayContainer.addChild(selector);// 把选择器加入到显示列表
  164.                                 movingPlant=new plantMc();// 构建一个新的供玩家拖动的植物
  165.                                 movingPlant.addEventListener(MouseEvent.CLICK,placePlant);// 给该植物注册一个鼠标点击事件
  166.                                 overlayContainer.addChild(movingPlant);// 把该植物加入到显示列表
  167.                                 playerMoving=true;// 告诉脚本正在移动一株植物
  168.                         }
  169.                 }
  170.                 //
  171.                 // 把植物放置在游戏区域中
  172.                 //
  173.                 private function placePlant(e:MouseEvent):void {
  174.                         var plantRow:int=Math.floor((mouseY-80)/75);
  175.                         var plantCol:int=Math.floor((mouseX-25)/65);
  176.                         // let's see if the tile is inside the game field and it's free
  177.                         if (plantRow>=0&&plantCol>=0&&plantRow<5&&plantCol<9&&plantsArray[plantRow][plantCol]==0) {
  178.                                 var placedPlant:plantMc=new plantMc();// 构建一株植物,用来种植
  179.                                 placedPlant.name="plant_"+plantRow+"_"+plantCol;// 给植物一个名字
  180.                                 placedPlant.fireRate=75;// 植物的开火速率,单位帧
  181.                                 placedPlant.recharge=0;// 当recharge 等于 fireRate时,植物已经准备好开火了
  182.                                 placedPlant.isFiring=false;// 一个布尔变量来存储植物是否正在开火
  183.                                 placedPlant.plantRow=plantRow;// 植物所在的行
  184.                                 plantContainer.addChild(placedPlant);// 把该植物加入到显示列表
  185.                                 placedPlant.x=plantCol*65+57;
  186.                                 placedPlant.y=plantRow*75+115;
  187.                                 playerMoving=false;// 告诉脚本玩家不在移动植物了
  188.                                 movingPlant.removeEventListener(MouseEvent.CLICK,placePlant);// 移除事件侦听
  189.                                 overlayContainer.removeChild(selector);// 移除选择器
  190.                                 overlayContainer.removeChild(movingPlant);// 移除供拖动的植物
  191.                                 plantsArray[plantRow][plantCol]=1;//  更新游戏区块信息
  192.                         }
  193.                 }
  194.                 //
  195.                 // 游戏循环,游戏的核心函数
  196.                 //
  197.                 private function onEnterFrm(e:Event):void {
  198.                         var i:int;
  199.                         var j:int;
  200.                         //
  201.                         // 植物管理
  202.                         //
  203.                         for (i=0; i<plantContainer.numChildren; i++) {
  204.                                 var currentPlant:plantMc=plantContainer.getChildAt(i) as plantMc;
  205.                                 // 让我们看看植物是否能开火
  206.                                 if (currentPlant.recharge==currentPlant.fireRate&&! currentPlant.isFiring) {
  207.                                         // 检查是否有僵尸与植物处于同一行
  208.                                         if (zombiesArray[currentPlant.plantRow].length>0) {
  209.                                                 // 遍历僵尸
  210.                                                 for (j=0; j<zombiesArray[currentPlant.plantRow].length>0; j++) {
  211.                                                         var targetZombie:zombieMc=zombieContainer.getChildByName(zombiesArray[currentPlant.plantRow]

  212. [j]) as zombieMc;// 获得第j个僵尸
  213.                                                         // 如果僵尸在植物的右边
  214.                                                         if (targetZombie.x>currentPlant.x) {
  215.                                                                 var bullet:bulletMc=new bulletMc();// 创建一个新子弹
  216.                                                                 bulletContainer.addChild(bullet);// 加入到显示列表
  217.                                                                 bullet.x=currentPlant.x;
  218.                                                                 bullet.y=currentPlant.y;
  219.                                                                 bullet.sonOf=currentPlant;// 存储该子弹是由哪一株植物射出的
  220.                                                                 currentPlant.recharge=0;// 重新准备开火
  221.                                                                 currentPlant.isFiring=true;// 植物正在开火
  222.                                                                 break;// 终止for循环
  223.                                                         }
  224.                                                 }
  225.                                         }
  226.                                 }
  227.                                 if (currentPlant.recharge<currentPlant.fireRate) {
  228.                                         currentPlant.recharge++;
  229.                                 }
  230.                         }
  231.                         //
  232.                         // 子弹管理
  233.                         //
  234.                         for (i=0; i<bulletContainer.numChildren; i++) {
  235.                                 var movingBullet:bulletMc=bulletContainer.getChildAt(i) as bulletMc;
  236.                                 movingBullet.x+=3;//把每个子弹向右移动3个像素
  237.                                 var firingPlant:plantMc=movingBullet.sonOf as plantMc;// 获得这个子弹是哪个植物射击的
  238.                                 // 让我们看看子弹是否飞出了舞台
  239.                                 if (movingBullet.x>650) {
  240.                                         firingPlant.isFiring=false;// 植物不再处于正在开火的状态
  241.                                         bulletContainer.removeChild(movingBullet);// 移除子弹
  242.                                 } else {
  243.                                         for (j=0; j<zombieContainer.numChildren; j++) {
  244.                                                 var movingZombie:zombieMc=zombieContainer.getChildAt(j) as zombieMc;
  245.                                                 // 让我们看看植物是否被子弹击中
  246.                                                 if (movingZombie.hitTestPoint(movingBullet.x,movingBullet.y,true)) {
  247.                                                         movingZombie.alpha-=0.3;//减少僵尸的能量(透明度)
  248.                                                         firingPlant.isFiring=false;// 植物不再处于正在开火的状态
  249.                                                         bulletContainer.removeChild(movingBullet);// 移除子弹
  250.                                                         // 让我们看看僵尸的能量(透明度)是否降至为0了
  251.                                                         if (movingZombie.alpha<0) {
  252.                                                                 zombiesArray[movingZombie.zombieRow].splice(zombiesArray

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

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

  297. sun
  298.                                                 sunContainer.removeChild(fallingSun);// 移出显示列表
  299.                                         }
  300.                                 }
  301.                         }
  302.                         //
  303.                         // 安置植物
  304.                         //
  305.                         if (playerMoving) {
  306.                                 movingPlant.x=mouseX;
  307.                                 movingPlant.y=mouseY;
  308.                                 var plantRow:int=Math.floor((mouseY-80)/75);
  309.                                 var plantCol:int=Math.floor((mouseX-25)/65);
  310.                                 // 检查是否在游戏区域内
  311.                                 if (plantRow>=0&&plantCol>=0&&plantRow<5&&plantCol<9) {
  312.                                         selector.visible=true;// 显示选择器
  313.                                         selector.x=25+plantCol*65;
  314.                                         selector.y=80+plantRow*75;
  315.                                 } else {
  316.                                         selector.visible=false;// 隐藏选择器
  317.                                 }
  318.                         }
  319.                 }
  320.         }
  321. }
复制代码


在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);
                }
        }
}
我们先检查了是否有植物被安置在僵尸当前所在的区块上,如果有,僵尸就停下脚步然后开始攻击植物,减少植物的生命值(当前是透明度)。
下面是结果:

你应该知道该怎么玩。尽量让你的植物被僵尸杀死吧。
下载源代码。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值