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; } } } }
源文件下载地址
联系作者
here is a secret^_^ if i hold on the button SPACE,i can play without eyes for my whole lif e
It might be a bug , but if you want , you can design your own game level!
Thanks for you reply!