Space is Key游戏算法原型

space is key是一个很简单的小游戏,按下空格键,控制方块跳过一个一个障碍物,听起来很简单,但没有点技巧还真不是那么容易通关的。

space is key

游戏的计算核心是方块跳起落地后角度刚好转了180度。这一点实现起来也不难。

首先我们要清楚方块的两个运动,垂直跳起和角度旋转,而且这两个运动过程是同步的。那么假设整个过程耗时step帧,,方块以jumpVy起跳后到达顶点后,那么根据加速度运算公式

v1-v0=at;

可以知道

jumpVy-0=gravity*step;

所以step=jumpVy/ gravity.另外因为下降过程与上升过程耗时是一样的,所以step要乘以2:step=step*2.

知道step耗时之后,方块的角速度va=180/step.

是不是很简单啊?

另外,关于碰撞检测(仔细看一下可以注意的,方块之间是像素级碰撞),我使用的是Aone的BitmapHitTestPlus,可以轻松实现像素级碰撞。

好了效果及源代码如下:

Main类:

package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;

	[SWF(frameRate="30",backgroundColor="0xCCCCCC")]
	public class Main extends Sprite
	{
		public const GRAVITY:Number=1;
		public const VX:Number=8;

		private var _gap:Number;
		private var _colors:Array;

		private var _rect:Rect;
		private var _jumpVy:Number=-10;
		private var _steps:Number=0;
		private var _index:Number=0;

		private var _enemies:Array;

		public function Main()
		{
			_gap=stage.stageHeight/3;
			_colors=[0x033502,0x039a67,0x036735];
			//绘制背景
			drawBackground(_colors);

			//计算矩形方块从起跳到落地所需的帧数
			calculateStep();
			//创建矩形方块
			_rect=new Rect(20,20);
			_rect.ground=_gap;
			_rect.y=_gap-_rect.height/2;
			_rect.vx=VX;
			//根据计算出来的帧步数,计算方块旋转的速度
			_rect.va=180/_steps;
			_rect.color=_colors[_index+1];
			addChild(_rect);

			//创建敌人
			_enemies=[{rect:new Rect(20,20),x:200,y:_gap,color:_colors[1]},
						{rect:new Rect(20,20),x:400,y:_gap,color:_colors[1]},
						{rect:new Rect(20,30),x:300,y:2*_gap,color:_colors[2]},
						{rect:new Rect(40,20),x:200,y:3*_gap,color:_colors[0]}];
			for each (var item:Object in _enemies)
			{
				item.rect.x=item.x;
				item.rect.ground=item.y;
				item.rect.color=item.color;
				addChild(item.rect);
			}

			//侦听事件
			stage.addEventListener(Event.ENTER_FRAME,loop);
			stage.addEventListener(KeyboardEvent.KEY_DOWN,onsStageKayDown);
		}
		private function calculateStep():void
		{
			//根据重力加速度的公式,上升和下降的时间是一样的,所以重力只计算
			//在上升过程中,速度加至0所消耗的帧数
			_steps=-_jumpVy/GRAVITY;
			//然后乘以2,表示加上下降的时间
			_steps*=2;
		}
		//用一个颜色数组绘制背景
		private function drawBackground(colors:Array):void
		{
			for (var i:int = 0; i < colors.length; i++)
			{
				graphics.beginFill(colors[i]);
				graphics.drawRect(0,i*_gap,stage.stageWidth,_gap);
				graphics.endFill();
			}
		}
		//键盘事件处理器
		private function onsStageKayDown(event:KeyboardEvent):void
		{
			//当方块在地面上时,按下空格键使方块跳起
			if(event.keyCode==Keyboard.SPACE && !_rect.isJumping){
				_rect.vy=_jumpVy;
				_rect.isJumping=true;
			}
		}

		private function loop(event:Event):void
		{
			_rect.vy+=GRAVITY;
			_rect.update();

			wrapBoundary();
			checkCollision();
		}

		private function checkCollision():void
		{
			for each (var item:Object in _enemies)
			{
				//利用BitmapHitTestPlus进行像素级碰撞检测
				if(BitmapHitTestPlus.complexHitTestObject(_rect,item.rect)){
					//检测到碰撞,_rect回到起点重新开始跑
					if(_rect.vx>0){
						_rect.x=0;
					}else{
						_rect.x=stage.stageWidth;
					}
				}
			}

		}

		private function wrapBoundary():void
		{
			//当方块超出边界时
			if((_rect.x>stage.stageWidth+_rect.width/2 && _rect.vx>0)
				||( _rect.x<-_rect.width/2 && _rect.vx<0)){

				_rect.rotation=0;//角度初始化为0
				_rect.isJumping=false;//停止跳动

				_index++;//记录在第几级地面
				_rect.ground+=_gap;//转到下一级地面运动

				//当地面高度超出舞台高度时,将方块放置到初始位置。
				if(_rect.ground>stage.stageHeight){
					_rect.ground=_gap;
					_index=0;
					_rect.x=0;
				}else{
					//否则反相移动和旋转
					_rect.vx*=-1;
					_rect.va*=-1;
				}

				//调整方块所在的地面,调整它的颜色
				if(_index+1>2){
					_rect.color=_colors[0];
				}else{
					_rect.color=_colors[_index+1];
				}
			}
		}
	}
}

Rect类:

package
{
	import flash.display.Sprite;

	public class Rect extends Sprite
	{
		public var isJumping:Boolean=false;
		//方块的水平速度、垂直速度和角速度
		public var vx:Number=0;
		public var vy:Number=0;
		public var va:Number=0;

		//设置方块的尺寸
		private var _width:Number;
		private var _height:Number;
		//设置方块的地面
		private var _ground:Number=0;

		public function get ground():Number
		{
			return _ground
		}
		public function set ground(value:Number):void
		{
			_ground=value;
			this.y=_ground-this._height/2;
		}
		//设置方块的颜色
		public function set color(value:Number):void
		{
			this.graphics.clear();
			this.graphics.beginFill(value);
			this.graphics.drawRect(-_width/2,-_height/2,_width,_height);
		}
		public function Rect(width:Number=50,height:Number=50)
		{
			_width=width;
			_height=height;

			this.color=0;
		}
		public function update():void
		{
			//更新方块的坐标
			this.x+=vx;
			this.y+=vy;

			//如果方块跳起来,同时旋转方块
			if(isJumping){
				this.rotation+=va;
			}
			//落地后设置跳起_isJumping为false
			if(this.y>_ground-this._width/2){
				this.y=_ground-this._width/2;
				isJumping=false;
			}
		}
	}
}

 源文件下载地址

联系作者

公众号:拉小登 | 微博:拉登Dony | B站:拉小登Excel

2 Replies to “Space is Key游戏算法原型”

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注