前几天在园子里看到有人用Silverlight做了一个"贪吃蛇",一时兴起也想用AS3.0做一个,虽然这个游戏已经被很多开发者做烂了,但是作为AS的初学者,重新做一遍也当是一种学习.
技术"难"点分析:
1.蛇身的构成
可以用数组来存储一堆小球,将它们排列成连续的直线即可
2.蛇身的移动
蛇头移动后,紧跟蛇头后的小球移动到蛇头原来的位置,然后...类推,后面的小球依次移动到前一个球的位置
3.碰撞检测
蛇头移动时,如果超出舞台边界,则Game Over了;同样蛇头如果遇到了蛇身,同样也Over.
4.食物的处理
在舞台上随机放一个小球,蛇头经过时,食物消失/蛇身加长(即数组中新追加一个小球)/食物重新随机定位
代码:
仍然用到Make Things Move中的著名Ball类,不过为了记录下次小球应该移动到的位置,增加二个变量nextx,nexty,Ball类的完整定义如下:
package { import flash.display.Sprite; //小球 类 public class Ball extends Sprite { public var radius:uint;//半径 public var color:uint;//颜色 public var vx:Number=0;//x轴速度 public var vy:Number=0;//y轴速度 public var count:uint=0;//辅助计数变量 public var isDragged=false;//是否正在被拖动 public var vr:Number=0;//旋转速度 public var mass:Number = 1;//质量 public var nextx:Number=0; public var nexty:Number=0; public function Ball(r:Number=50,c:uint=0xff0000) { this.radius=r; this.color=c; init(); } private function init():void { graphics.beginFill(color); graphics.drawCircle(0,0,radius); graphics.endFill(); } } }
当然,就本游戏而言,里面有很多变量都可以删除掉,这里为了完整起见保留下来了,游戏核心代码:
import flash.utils.Timer; var balls:Array; var ballOriginCount:uint=3; var radius:uint=10; var sW:Number=stage.stageWidth; var sH:Number=stage.stageHeight; var tmr:Timer; var speed:uint=200;//毫秒 var food:Ball; var rows:uint = sW/(2*radius); var cols:uint = sW/(2*radius); var isDead:Boolean=false; var isPause:Boolean=true; //初始化 function init():void { balls = new Array(); for (var i:uint=0; i<ballOriginCount; i++) { var b:Ball=new Ball(radius,Math.random()*0xffffff); balls.push(b); b.x=sW/2; b.y=sH/2; b.nextx=b.x; b.nexty=b.y; b.vx=b.width; addChild(b); } //刚开始时,让小球排成直线 for (i=1; i<ballOriginCount; i++) { balls[i].x=balls[i-1].x-balls[i].width; } drawGrid(); //初始化食物 food=new Ball(radius*0.8,0x000000); checkFoodPosition(); addChild(food); stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDowmHandler); tmr=new Timer(speed); tmr.addEventListener(TimerEvent.TIMER,moveSnake); tmr.start(); _gameover.visible=isDead; _notice.visible=isPause; } function restart():void { //先移除原有的蛇 for (var i:int=balls.length-1; i>=0; i--) { removeChild(balls[i]); } //重来一切 balls.length=0; ballOriginCount=3; for (i=0; i<ballOriginCount; i++) { var b:Ball=new Ball(radius,Math.random()*0xffffff); balls.push(b); b.x=sW/2; b.y=sH/2; b.nextx=b.x; b.nexty=b.y; b.vx=b.width; addChild(b); } for (i=1; i<ballOriginCount; i++) { balls[i].x=balls[i-1].x-balls[i].width; } isDead=false; isPause=false; _gameover.visible=isDead; _notice.visible=isPause; } //方向控制 function keyDowmHandler(e:KeyboardEvent):void { var b:Ball=balls[0]; if (e.keyCode==Keyboard.SPACE) { isPause=! isPause; if (isDead) { restart(); } _notice.visible=isPause; } else if (e.keyCode==Keyboard.DOWN&&b.vx!=0) { b.vy=b.width; b.vx=0; } else if (e.keyCode == Keyboard.UP && b.vx!=0) { b.vy=- b.width; b.vx=0; } else if (e.keyCode == Keyboard.LEFT && b.vy!=0) { b.vx=- b.width; b.vy=0; } else if (e.keyCode == Keyboard.RIGHT && b.vy!=0) { b.vx=b.width; b.vy=0; } } //画格子 function drawGrid() { for (var i:uint=radius; i<sW; i+=2*radius) { graphics.lineStyle(1,0,0.1); graphics.moveTo(i,0); graphics.lineTo(i,sH); } for (i=radius; i<sH; i+=2*radius) { graphics.lineStyle(1,0,0.1); graphics.moveTo(0,i); graphics.lineTo(sW,i); } } //蛇身的移动 function moveSnake(e:TimerEvent):void { //如果暂停或挂掉,则不处理 if (isPause||isDead) { return; } var b:Ball=balls[0]; b.nextx=b.x+b.vx; b.nexty=b.y+b.vy; for (var j:uint=1; j<ballOriginCount; j++) { var _b:Ball=balls[j]; _b.nextx=balls[j-1].x; _b.nexty=balls[j-1].y; } for (j=0; j<ballOriginCount; j++) { balls[j].x=balls[j].nextx; balls[j].y=balls[j].nexty; } //边界检测 if (b.x<b.radius||b.x>sW-b.radius||b.y<b.radius||b.y>sH-b.radius) { isDead=true; _gameover.visible=isDead; _notice.visible = isDead; return; } //检测蛇头是否咬到了自己 for (j=1; j<ballOriginCount; j++) { var target:Ball=balls[j]; if (b.x==target.x&&b.y==target.y) { isDead=true; _gameover.visible=isDead; _notice.visible = isDead; return; } } //如果蛇头经过食物,则表示吃掉了 if (b.x==food.x&&b.y==food.y) { //trace("吃掉了!"); var _newBall:Ball=new Ball(radius,Math.random()*0xffffff); _newBall.x=- radius; _newBall.y=- radius; balls.push(_newBall); addChild(_newBall); food.visible=false; ballOriginCount++; } makeFood(); } //生成食物的新坐标 function makeFood() { if (food.visible==false) { checkFoodPosition(); food.visible=true; } if (food.alpha==1) { food.alpha=0.5; food.scaleX=food.scaleY=1.2; } else { food.alpha=1; food.scaleX=food.scaleY=1; } } function checkFoodPosition():void { food.x=radius+int(Math.random()*rows)*2*radius; food.y=radius+int(Math.random()*cols)*2*radius; //检测食物的新坐标是否在“蛇身”上,如果是,则重新生成新坐标 var isWrongPositon:Boolean=true; while (isWrongPositon) { var checkFlag:Boolean=true; for (var i:uint=0; i<ballOriginCount; i++) { var b:Ball=balls[i]; if (b.x==food.y&&b.y==food.y) { checkFlag=false; break; } } if (!checkFlag) { food.x=radius+int(Math.random()*rows)*2*radius; food.y=radius+int(Math.random()*cols)*2*radius; } isWrongPositon=!checkFlag; } } init();
源文件下载: http://cid-2959920b8267aaca.office.live.com/self.aspx/Flash/Snake.rar