• AS3:小游戏“贪吃蛇”的实现


    前几天在园子里看到有人用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

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    jQuery 参考手册
    jQuery 参考手册
    ASP.NET框架例举
    判断checkbox是否选中
    ajax动态添加的li不能绑定click事件
    缓存代码备用
    关于ajax伪实时动态下拉显示最新数据
    JavaScript中,格式化DateTime
    jquery判断id是否存在
    SSI-Server Side Inclued
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1761475.html
Copyright © 2020-2023  润新知