package { import flash.display.MovieClip; import flash.display.Sprite; import flash.utils.Timer; import flash.geom.Point; import flash.events.TimerEvent; import flash.events.Event; import flash.events.KeyboardEvent; import flash.ui.Keyboard import flash.text.TextField; import flash.events.MouseEvent; public class grid extends MovieClip { private var a:uint=20//方块边长 private var kuan:uint=24//地图宽 private var gao:uint=30//地图高 private var type:Array=[]//各种方块类型 private var nextGrid:Array//下一个方块 private var nextSp:Sprite private var usingGrid:Array//当前方块 private var usingSp:Sprite private var usingPosition:Point private var rongqi:Array=[] private var timer:Timer=new Timer(1000) private var txt:TextField//用于显示分数的文本框 private var score:uint=0//分数(通关行数) private var levelUp:uint=10//每通关多少行升级 public function grid() { init()//初始化地图 reDraw()//绘制地图 getType()//创建所有方块类型 createGrid()//随机创建一个方块,加入到预备 startGrid()//将一个预备中的方块转为正在使用的方块 timer.start()//定时下沉 timer.addEventListener(TimerEvent.TIMER,onTimer) stage.addEventListener(KeyboardEvent.KEY_DOWN,onDown)//侦听键盘事件 stage.addEventListener(MouseEvent.CLICK,togglePause) txt=new TextField txt.x=450 this.addChild(txt) txt.text="0" txt.selectable=false } private function togglePause(e:MouseEvent):void{//点击暂停游戏 if(timer.running)timer.stop() else timer.start() } private function init(){//初始化地图 var i:int,j:int var l:uint=a-1 for(i=0;i<kuan;i++){// 绘制背景方块,供测试者观看 rongqi[i]=[] for(j=0;j<gao;j++){ rongqi[i][j]=0 } } } private function addScore(){ score++ txt.text=score.toString() if(score%levelUp==0){//行数增加,游戏提速 var level:uint=score/levelUp level=level>9?9:level timer.stop() timer.removeEventListener(TimerEvent.TIMER,onTimer) timer=new Timer(1000-level*100) timer.addEventListener(TimerEvent.TIMER,onTimer) timer.start()//定时下沉 } } private function drawAGrid(mc:Sprite,i:int,j:int,aa:int,color:uint):void{ mc.graphics.beginFill(color) mc.graphics.drawRect(i*a,j*a,aa,aa) mc.graphics.endFill() } private function onDown(e:KeyboardEvent):void{//键盘事件 switch(e.keyCode){ case Keyboard.LEFT:left()//向左 break case Keyboard.UP:roll()//旋转方块 break case Keyboard.RIGHT:right()//向右 break case Keyboard.DOWN:down()//向下 break } } private function left():void{ usingPosition.x-- if(hit(usingGrid)){//检测下一状态是否碰撞,如发生碰撞则不允向左 usingPosition.x++ return } else{ usingSp.x=usingPosition.x*a } } private function right():void{ usingPosition.x++ if(hit(usingGrid)){//检测下一状是否碰撞,如发生碰撞则不允许向右 usingPosition.x-- return } else{ usingSp.x=usingPosition.x*a } } private function down(){ usingPosition.y++ if(hit(usingGrid)){//检测下一状是否碰撞,如发生碰撞则方块锁定位置 usingPosition.y-- lockPlace() } usingSp.y=usingPosition.y*a } private function lockPlace():void{ var max:uint=usingGrid.length var i:int,j:int for(i=0;i<max;i++){ for(j=0;j<max;j++){ if(usingGrid[i][j]){ rongqi[usingPosition.x+i][usingPosition.y+j]=1 } } } for(i=0;i<kuan;i++){//绘制背景方块,供测试者观看 for(j=0;j<gao;j++){ if(rongqi[i][j]){ drawAGrid(this,i,j,a,0xffff00) } } } usingSp.graphics.clear() this.removeChild(usingSp) usingSp=null for(j=0;j<max;j++){ checkLine(usingPosition.y+j) } startGrid() } private function checkLine(index:uint):void{//检查某行是否通了,如果通了,则消除 for(var i:uint=0;i<kuan;i++){//检测是否已通,不通就直接返回 if(!rongqi[i][index])return } for(i=0;i<kuan;i++){//通则处理掉这一行 rongqi[i].splice(index,1) rongqi[i].unshift(0) } addScore() reDraw() } private function reDraw():void{//发生通行时,重绘地图 this.graphics.clear() var i:int,j:int for(i=0;i<kuan;i++){// 绘制背景方块,供测试者观看 for(j=0;j<gao;j++){ if(rongqi[i][j])drawAGrid(this,i,j,a,0xffff00) else drawAGrid(this,i,j,a-1,0xff0000) } } } private function roll():void{ var ar:Array=[]//产生一个新的,逆时针旋转后的方块 var max:uint=usingGrid.length var i:uint,j:uint for(i=0;i<max;i++){ ar[i]=[] } for(i=0;i<max;i++){//旋转 for(j=0;j<max;j++){ ar[j][max-i-1]=usingGrid[i][j] } } if(hit(ar))return//检测是否碰撞,如发生碰撞则不允许旋转 usingSp.graphics.clear() for(i=0;i<max;i++){ for(j=0;j<max;j++){ if(ar[i][j]==1){ drawAGrid(usingSp,i,j,a,0x00ff00) } } } usingGrid=ar } private function hit(ar:Array):Boolean{//碰撞测试 var max:uint=ar.length var i:int,j:int for(i=0;i<max;i++){ for(j=0;j<max;j++){ if(ar[i][j]){ if(usingPosition.x+i<0||usingPosition.x+i>=kuan)return true//超出边界,则返回true if(usingPosition.y+j<0||usingPosition.y+j>=gao)return true if(rongqi[usingPosition.x+i][usingPosition.y+j])return true //与物体有重叠,则返回true } } } return false } private function getType():void{ type.push([[0,0,1],[1,1,1],[0,0,0]]);//钩子 type.push([[0,0,0],[1,1,1],[0,0,1]]);//倒钩 type.push([[1,1],[1,1]]);//小方块 type.push([[0,0,0,0],[1,1,1,1],[0,0,0,0],[0,0,0,0]]);//长条 type.push([[0,1,0],[1,1,0],[0,1,0]]);//星 type.push([[1,0,0],[1,1,0],[0,1,0]]);//Z字形 type.push([[0,1,0],[1,1,0],[1,0,0]]);//反Z字形 } private function createGrid():void{//创建一个方块 var i:uint=int(Math.random()*type.length)//随机挑选一个方块类型 var max:uint=type[i].length nextGrid=[] while(max-->0){//当前方块等于这个类型(获得数组副本) nextGrid.unshift(type[i][max].concat()) } drawnextGrid()//在方块层绘制当前方块 } private function drawnextGrid():void{//画出下一方块 nextSp=new Sprite this.addChild(nextSp) var i:int,j:int var max:uint=nextGrid.length for(i=0;i<max;i++){ for(j=0;j<max;j++){ if(nextGrid[i][j]==1){ nextSp.graphics.beginFill(0x00ff00) nextSp.graphics.drawRect(i*a,j*a,a,a) nextSp.graphics.endFill() } } } } private function startGrid():void{//将一个预备中的方块转为正在使用的方块 usingSp=nextSp nextSp=null usingGrid=nextGrid usingPosition=new Point((kuan-usingGrid.length)>>1,0) usingSp.x=usingPosition.x*a createGrid() if(hit(usingGrid)){//如果方块一出来就发生碰撞,则判定游戏死亡 timer.stop() stage.removeEventListener(KeyboardEvent.KEY_DOWN,onDown) stage.removeEventListener(MouseEvent.CLICK,togglePause) stage.addEventListener(MouseEvent.CLICK,onRestart)//点击鼠标,重新开始游戏 } } private function onTimer(e:Event):void{//自由下落 down() } private function onRestart(e:MouseEvent):void{//重新开始游戏 stage.removeEventListener(MouseEvent.CLICK,onRestart) score=0//积分清零 txt.text="0" timer=new Timer(1000) timer.start() timer.addEventListener(TimerEvent.TIMER,onTimer) stage.addEventListener(KeyboardEvent.KEY_DOWN,onDown) init() reDraw() stage.addEventListener(MouseEvent.CLICK,togglePause) } } }