做一个像植物大战僵尸的Flash游戏4
欢迎来到第四步。在这个步骤里,我们会使得植物能够开火,并且最终杀死僵尸。
让我们先来明确一下什么时候植能开火: *当至少有一个僵尸与植物处于同一行 *植物一次只能射出一颗子弹 *距离上一次射击必须过去一定的时间 现在让我们来定义一下子弹的活动: *子弹从左往右飞 *当子弹击中一个僵尸时被移除 *当子弹飞到舞台之外时被移除 这6个概念给我们的脚本带来了一些大的改动。意识到把所有的代码写到一个类里使得脚本变得很混乱,我尽力以最清晰的方式来组织它。我尽我最大所能来使得它保持可读性。 我创建了一个叫做bulletMc的对象,它代表了子弹。 准备好去看一个接近300行的代码吗? 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;// 布尔型变量,标志玩家是否在移动一个植物 public function Main():void { setupField();// 初始化游戏区块 drawField();// 画出游戏区块 fallingSuns();// 初始化下落的阳光 addPlants();// 初始化植物 addZombies();// 初始化僵尸 addEventListener(Event.ENTER_FRAME,onEnterFrm); } // // 游戏区域设置,创建用来存储植物和僵尸信息的数组 // private function setupField():void { plantsArray=new Array(); for (var i:uint=0; i<5; i++) { plantsArray[i]=new Array(); for (var j:uint=0; j<9; j++) { plantsArray[i][j]=0; } } zombiesArray=new Array(0,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();// 构造僵尸 zombieContainer.addChild(zombie);// 增加僵尸 zombie.zombieRow=Math.floor(Math.random()*5);// 生成随机行数,用于放置僵尸 zombiesArray[zombie.zombieRow]++;// 增加第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); // 检查该区块是否位于游戏区域内,并且该区块没有其它植物存在 if (plantRow>=0&&plantCol>=0&&plantRow<5&&plantCol<9&&plantsArray[plantRow][plantCol]==0) { var placedPlant:plantMc=new plantMc();// 构建一株植物,用来种植 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 (zombiesArray[currentPlant.plantRow]>0&¤tPlant.recharge==currentPlant.fireRate&&! currentPlant.isFiring) { 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;// 植物正在开火 } 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]--;// 减少该行僵尸的数量 zombieContainer.removeChild(movingZombie);// 移除僵尸 } break; } } } } // // 僵尸管理 // for (i=0; i<zombieContainer.numChildren; i++) { movingZombie=zombieContainer.getChildAt(i) as zombieMc; movingZombie.x-=0.5;// 每一个僵尸往左移动0.5个像素 } // // 阳光管理 // 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);// 移除事件侦听 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;//隐藏选择器 } } } } } 如果你一路跟随着我之前的几个教程做了下来的说话,你就会注意到我改变了很多的代码,但是原来的概念保持不变。 http://www.emanueleferonato.com/wp-content/uploads/2011/01/pvz4.swf (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |