Flash 游戏开发实战(二)
我们必需修改一个在教程一中的代码,就是让阳光只是简简单单地出现在某一区块中,并且在一段时间内,若没有被捡起,它就消失了。我们得让阳光平滑的落下。
修改newSun函数
细心的读者可能会发现,教程一里的newSun函数有一个错误使得新生的阳光无法出现在游戏区域内的任意一个区块。这个错误可以通过修改x属性的值来修复:
sun.x=52+sunCol*65;(教程一里写成了sun.x=52+sunRow*65)
既然我们将要加入使得阳光平滑落下的代码,整个newSun函数可以改成这样:
private function newSun(e:TimerEvent):void { var sunRow:uint=Math.floor(Math.random()*5); var sunCol:uint=Math.floor(Math.random()*9); sun = new sunMc(); sun.buttonMode=true; sunContainer.addChild(sun); sun.x=52+sunCol*65; sun.destinationY=130+sunRow*75; sun.y=-20; sun.addEventListener(MouseEvent.CLICK,sunClicked); }
现在,阳光的y属性被初始化为-20使得阳光出现在我们看不见的地方,并且它有一个destinationY属性用来存储它的最终的y坐标。呆会让我们来看看如何使用这一属性。注意一下buttonMode属性,它能使得鼠标指针改变外形当鼠标滑过阳光时。
收集阳光来筹钱吧
首先,我们需要一个变量来存储玩家金钱的数量,然后我们需要一个文本框来显示它。
这些是我们需要导入的类:
import flash.display.Sprite;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.text.TextField;
下面这些,是所用到的变量
private var gameField:Array;
private var flowersTimer:Timer=new Timer(5000);
private var sun:sunMc;
private var sunContainer:Sprite=new Sprite();
private var money:uint=0;
private var moneyText:TextField=new TextField;
money变量用来存储玩家的金钱,moneyText是一个动态文本。
现在,让我们来看一下整个代码并且讨论一下新特性。
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 { private var gameField:Array; private var flowersTimer:Timer=new Timer(5000); private var sun:sunMc; private var sunContainer:Sprite=new Sprite(); private var money:uint=0; private var moneyText:TextField=new TextField; public function Main():void { setupField(); drawField(); fallingSuns(); addText(); addEventListener(Event.ENTER_FRAME,onEnterFrm); } private function addText():void { addChild(moneyText); updateMoney(); moneyText.textColor=0xFFFFFF; moneyText.height=20; } private function updateMoney():void { moneyText.text="Money: "+money.toString(); } private function onEnterFrm(e:Event):void { for (var i:uint=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); } } } } private function fallingSuns():void { addChild(sunContainer); 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); sun = new sunMc(); sun.buttonMode=true; sunContainer.addChild(sun); sun.x=52+sunCol*65; sun.destinationY=130+sunRow*75; sun.y=-20; sun.addEventListener(MouseEvent.CLICK,sunClicked); } private function sunClicked(e:MouseEvent):void { e.currentTarget.removeEventListener(MouseEvent.CLICK,sunClicked); money+=5; updateMoney(); var sunToRemove:sunMc=e.currentTarget as sunMc; sunContainer.removeChild(sunToRemove); } private function setupField():void { gameField=new Array(); for (var i:uint=0; i<5; i++) { gameField[i]=new Array(); for (var j:uint=0; j<9; j++) { gameField[i][j]=0; } } } 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); } } } } }
让我们来看一下这个代码中的一些新东西。
第19行:调用addText函数(第22到第27行),这个函数很简单,只是创建了一个动态文本框并且在第24行调用了updateMoney函数(第28到第30行)来显示当前玩家的金钱数量。
第20行:注册Event.ENTER_FRAME事件侦听器,使得每帧调用onEnterFrm函数(第31到第44行)。
第32行:for循环遍历sunContainer,得到sunContainer的子对象。每一束阳光要么是正在下落中,要么是已经落地。
正在下落的阳光它的y属性的值小于它的destinationY属性的值(第34行),这种情况下,阳光会继续下落通过增加y属性的值。
已落地的阳光不会再继续下落,在这种情况下,它开始渐渐消失(第37行,通过改变alpha属性)。一旦它完全透明了(第38行),它的鼠标事件侦听器就会被移除(第39行),并且它也会被移出显示列表(第40行)。
最后一个有改动的函数是sunClicked。现在,你每收集一束阳光就会赚到5个金币(第63行),并且更新动态文本框(第64行)。
下面是游戏效果:
收集阳光赚钱或者让它们落到地面后,看着它们消失吧。
购买你的第一株植物
要创造你的第一株植物,首先我们需要两个新的类:一个是plantMc,它代表了植物,另一个是selectorMc,它使得玩家看清楚植物将要被种到哪一个区块。
我们得增加5个新的变量:
private var plantContainer:Sprite=new Sprite();
private var plant:plantMc;
private var movingPlant:plantMc;
private var playerMoving:Boolean=false;
private var selector:selectorMc;
让我们来看下它们的意思:
plantContainer:一个可视对象,用来当植物的容器
plant:代表植物它本身
movingPlant:也是植物,当玩家买了植物之后,它会跟随鼠标移动
playerMoving:一个布尔型变量,用来记录玩家是否正在移动一株植物
selector:选择器
下面是最终源代码:
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 { private var gameField:Array; private var flowersTimer:Timer=new Timer(5000); private var sun:sunMc; private var sunContainer:Sprite=new Sprite(); private var money:uint=0; private var moneyText:TextField=new TextField ; private var plantContainer:Sprite=new Sprite(); private var plant:plantMc; private var movingPlant:plantMc; private var playerMoving:Boolean=false; private var selector:selectorMc; public function Main():void { setupField(); drawField(); fallingSuns(); addText(); addPlants(); addEventListener(Event.ENTER_FRAME,onEnterFrm); } private function onPlantClicked(e:MouseEvent):void { if (money>=10&&! playerMoving) { money-=10; updateMoney(); selector=new selectorMc(); selector.visible=false; plantContainer.addChild(selector); movingPlant=new plantMc() ; plantContainer.addChild(movingPlant); playerMoving=true; } } private function addPlants():void { addChild(plantContainer); plant=new plantMc(); plantContainer.addChild(plant); plant.buttonMode=true; plant.x=90; plant.y=40; plant.addEventListener(MouseEvent.CLICK,onPlantClicked); } private function addText():void { addChild(moneyText); updateMoney(); moneyText.textColor=0xFFFFFF; moneyText.height=20; } private function updateMoney():void { moneyText.text="Money: "+money.toString(); } private function onEnterFrm(e:Event):void { for (var i:uint=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; } } } private function fallingSuns():void { addChild(sunContainer); 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); sun = new sunMc(); sun.buttonMode=true; sunContainer.addChild(sun); sun.x=52+sunCol*65; sun.destinationY=130+sunRow*75; sun.y=-20; sun.addEventListener(MouseEvent.CLICK,sunClicked); } private function sunClicked(e:MouseEvent):void { e.currentTarget.removeEventListener(MouseEvent.CLICK,sunClicked); money+=5; updateMoney(); var sunToRemove:sunMc=e.currentTarget as sunMc; sunContainer.removeChild(sunToRemove); } private function setupField():void { gameField=new Array(); for (var i:uint=0; i<5; i++) { gameField[i]=new Array(); for (var j:uint=0; j<9; j++) { gameField[i][j]=0; } } } 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); } } } } }
跟往常一样,让我们来看下新的代码:
第25行:调用addPlants函数(第40-48行),这将会增加植物选项条。现在,只有一种植物,它就是绿色的圆形(别忘了,我们玩的是“圆形大战方块”)。
第40-48行:addPlants函数把我们唯一能买到的植物加入到显示列表,并且给它注册一个鼠标事件侦听器onPlantClicked。这个侦听函数是代码的核心部分。
让我们来看看onPlantClicked函数是如何工作的:
第29行:当你有足够的钱时你才能买植物,并且不能是你已经买了一株植物,正找个地方放置它。现在,植物的价格是10个金币。
第30-31行:扣掉你买植物所花费的钱,并且更新文本框。
第32-34行:把选择器加入到显示列表,但此刻要使得它不可见。
第34-36行:把植物放到游戏区块中。
第37行:设置playerMoving的值为true,告诉程序我们正在移动一株植物,给它选择一个家。当playerMoving为真时会发生什么呢?在onEnterFrm函数里,一些事因此改变了。
第71-83行:这里是playerMoving为真时所发生的:当我们考虑在要哪个区块放置我们刚刚买到的植物时,我们所买的植物跟随鼠标移动(第74-75行)。如果我们的鼠标滑过一个区块(第76行),我们就使选择器可见,使得该区块高亮显示(第77-79行),否则,我们继续保持选择器不可见(第81行)。
下面是结果:
收集10个金币,然后购买一株植物,把它移向游戏区域。