使用OGEngine开发FlappyBird.docx
《使用OGEngine开发FlappyBird.docx》由会员分享,可在线阅读,更多相关《使用OGEngine开发FlappyBird.docx(14页珍藏版)》请在冰点文库上搜索。
使用OGEngine开发FlappyBird
FlappyBird
《flappybird》是由来自越南的独立游戏开发者DongNguyen所开发的作品,游戏中玩家必须控制一只小鸟,跨越由各种不同长度水管所组成的障碍,而这只鸟其实是根本不会飞的……所以玩家每点击一下小鸟就会飞高一点,不点击就会下降,玩家必须控制节奏,拿捏点击屏幕的时间点,让小鸟能在落下的瞬间跳起来,恰好能够通过狭窄的水管缝隙,只要稍一分神,马上就会失败阵亡。
本文将介绍使用OGEngine游戏引擎来做一个类似FlayppyBird的游戏,游戏创意及资源属原作者所有,这里只做技术学习使用。
一、没图没真相,先来看看截图
游戏基本上模仿了原版的游戏过程。
。
。
。
。
。
2、游戏场景的设计
游戏场景(GameScene)是本游戏的重点,它包括三种元素:
(1)主角小鸟
(2)障碍物水管
(3)滚动的地板
GameScene所控制的操作:
(1)游戏状态的表示
(2)添加小鸟和水管
(3)分数的实时统计
(4)碰撞的检测
1、创建小鸟类(BirdSprite)
在整个游戏的过程当中,小鸟有三种不同的状态:
(1)准备状态(挥动翅膀,不受重力约束)
(2)飞行状态(飞行过程中,受重力的影响)
(3)死亡状态(倒地的状态)
这里用几个常量来标示小鸟的状态
publicstaticfinalintSTATE_READY=0;
publicstaticfinalintSTATE_FLY=1;
publicstaticfinalintSTATE_DIE=2;
小鸟三种状态下的设置:
/**
*刷新状态
*@paramstate
*/
publicvoidrefreshState(intstate){
switch(state){
caseSTATE_READY:
this.setY(initY);
this.setRotation(0);
this.animate(180);
break;
caseSTATE_FLY:
this.animate(100);
break;
caseSTATE_DIE:
this.stopAnimation(0);
this.setRotation(90);
break;
}
}
注:
①小鸟在准备状态下是恢复初始坐标位置,恢复旋转角度为0,翅膀振动比较慢一些。
②小鸟在飞行过程中,翅膀振动快一些。
③小脑死亡时停止振动翅膀,旋转角度为90°。
2、创建水管类(BarSprite)
我们知道游戏中,小鸟是不停地由左往右飞,通过层层水管障碍物,事实上,我们只需要让水管和地板由右往左移动就可以实现小鸟由左往右飞的感觉了,呵呵。
我们可以使用PhysicsHandler来处理水管的移动问题,使得水管一生成的时候就以设定的速度由右往左匀速移动。
请看下面的代码:
publicBarSprite(floatpX,floatpY,StringpTextureRegionName,booleanisUpBar,
VertexBufferObjectManagerpVertexBufferObjectManager){
super(pX,pY,pTextureRegionName,pVertexBufferObjectManager);
this.isUpBar=isUpBar;
mPhysicsHandler=newPhysicsHandler(this);
this.registerUpdateHandler(mPhysicsHandler);
//设置移动方向和速度
mPhysicsHandler.setVelocityX(-150);
}
/**
*停止移动
*/
publicvoidstopMove(){
this.unregisterUpdateHandler(mPhysicsHandler);
}
3、创建地板类(FloorSprite)
地板类主要是要实现控制地板的循环滚动状态。
publicclassFloorSpriteextendsAnimatedSprite{
/**视差值**/
privatefloatmParallaxValue;
/**视差移动的因数**/
privatefloatmParallaxFactor=5;
/**每秒改变的视差值**/
privatefloatmParallaxChangePerSecond;
publicvoidsetParallaxChangePerSecond(floatmParallaxChangePerSecond){
this.mParallaxChangePerSecond=mParallaxChangePerSecond;
}
publicFloorSprite(floatpX,floatpY,StringpTextureRegionName,
floatmParallaxChangePerSecond,
VertexBufferObjectManagerpVertexBufferObjectManager){
super(pX,pY,pTextureRegionName,pVertexBufferObjectManager);
this.mParallaxChangePerSecond=mParallaxChangePerSecond;
}
@Override
protectedvoidonManagedUpdate(floatpSecondsElapsed){
super.onManagedUpdate(pSecondsElapsed);
//LogUtil.d("onManagedUpdatepSecondsElapsed-->"+pSecondsElapsed);
this.mParallaxValue+=this.mParallaxChangePerSecond*pSecondsElapsed;
}
@Override
protectedvoidonManagedDraw(GLStatepGLState,CamerapCamera){
pGLState.pushModelViewGLMatrix();
{
finalfloatcameraWidth=pCamera.getWidth();
finalfloatshapeWidthScaled=this.getWidthScaled();
floatbaseOffset=(mParallaxValue*this.mParallaxFactor)
%shapeWidthScaled;
while(baseOffset>0){
baseOffset-=shapeWidthScaled;
}
pGLState.translateModelViewGLMatrixf(baseOffset,0,0);
floatcurrentMaxX=baseOffset;
do{
super.onManagedDraw(pGLState,pCamera);
pGLState.translateModelViewGLMatrixf(shapeWidthScaled,0,0);
currentMaxX+=shapeWidthScaled;
}while(currentMaxX}
pGLState.popModelViewGLMatrix();
}
}
4、添加小鸟
前面简单地封装了一下小鸟精灵类,在游戏场景类GameScene里添加小鸟及改变小鸟状态就比较简单了。
birdSprite=newBirdSprite(120,370,pVertexBufferObjectManager);
birdSprite.setZIndex(pZIndex_middle);
birdSprite.refreshState(game_state);
birdSprite.setScale(1.2f);
this.attachChild(birdSprite);
5、添加水管
我们知道,水管在游戏中是源源不断地,水管的添加,主要是通过createBars(floatpX)来生成,每隔一段时间生产上下一对水管,中间留有小鸟通过的缝道。
/**
*创建一对bars
*@parampX
*/
privatevoidcreateBars(floatpX){
floatpY=-newRandom().nextInt(300);
BarSpriteupSprite=newBarSprite(pX,pY,Res.BAR_UP,true,
pVertexBufferObjectManager);
BarSpritedownSprite=newBarSprite(pX,upSprite.getBottomY()+165,
Res.BAR_DOWN,false,pVertexBufferObjectManager);
this.attachChild(upSprite);
this.attachChild(downSprite);
barSprites.add(upSprite);
barSprites.add(downSprite);
this.sortChildren();
}
我们可以通过TimerHandler每隔一段时间创建一对水管。
mTimerHandler=newTimerHandler(pTimerSeconds,true,
newITimerCallback(){
@Override
publicvoidonTimePassed(TimerHandlerpTimerHandler){
createBars(480);
}
});
3、小鸟物理效果以及碰撞检测的设计
我们知道,游戏的一大特点就是玩家每点击一下小鸟就会飞高一点,不点击小鸟就会受到重力效果以一定的加速度往下掉。
我们使用OGEngine引擎集合的Box2D功能,很容易地就可以实现这一的效果。
1、为小鸟添加物理效果
/**
*初始化物理效果
*/
privatevoidinitPhysics(){
this.mPhysicsWorld=newPhysicsWorld(newVector2(0,50),false);
//参数:
密度、弹力、摩擦力
FixtureDefFIXTURE_DEF=PhysicsFactory.createFixtureDef(0,0.0f,0.0f);
BodybirdBody=PhysicsFactory.createBoxBody(mPhysicsWorld,birdSprite,
BodyType.DynamicBody,FIXTURE_DEF);
birdSprite.setBody(birdBody);
this.mPhysicsWorld.registerPhysicsConnector(newPhysicsConnector(birdSprite,
birdBody,true,true));
}
2、在小鸟飞行的状态中,每点击一次屏幕小鸟会有一个向上的速度。
birdSprite.getBody().setLinearVelocity(0,-15);这样就可以为小鸟设置一个向上的速度。
@Override
publicbooleanonSceneTouchEvent(TouchEventpSceneTouchEvent){
if(pSceneTouchEvent.isActionDown()){
if(game_state==STATE_READY){
gameStart();
}
if(!
birdSprite.isCollisionFloor()&&!
birdSprite.isCollisionBar()){
if(birdSprite.getY()>0){
//不能飞过顶部
birdSprite.getBody().setLinearVelocity(0,-15);
//播放音效
SoundRes.playSound(SOUND_WING);
}
}
}
returnsuper.onSceneTouchEvent(pSceneTouchEvent);
}
3、检测碰撞
我们通过注册一个IUpdateHandler不停地监听小鸟跟水管或者地板有没发生碰撞,并根据实际情况做对应的逻辑处理。
/**
*不停检测用的handler
*/
privateIUpdateHandlercheckHandler=newIUpdateHandler(){
@Override
publicvoidreset(){
}
@Override
publicvoidonUpdate(floatpSecondsElapsed){
//LogUtil.d("onUpdate--->"+pSecondsElapsed);
if(game_state==STATE_FLY){
//小鸟旋转
rotateBird();
if(!
birdSprite.isCollisionBar()&&isCollidesWithBar()){
birdSprite.setCollisionBar(true);
//停止水管的生成和移动
barOver();
//播放音效
SoundRes.playSound(SOUND_HIT);
}
//小鸟是否碰撞到地板或者水管
//if(birdSprite.collidesWith(mFloorSprite)&&!
birdSprite.isCollisionFloor()){
if(!
birdSprite.isCollisionFloor()&&isContact(birdSprite,mFloorSprite)){
birdSprite.setCollisionFloor(true);
if(!
birdSprite.isCollisionBar()){
//停止水管的生成和移动
barOver();
//播放音效
SoundRes.playSound(SOUND_HIT);
}
//游戏结束
gameOver();
}
//迭代器遍历bar集合
Iteratoriterator=barSprites.iterator();
while(iterator.hasNext()){
BarSpritebarSprite=iterator.next();
//检测小鸟是否通过水管
if(barSprite.isUpBar()&&!
barSprite.isPass()){
if(barSprite.getCentreX()barSprite.setPass(true);
score++;
updateScore(score);
}
}
//将移出了左边镜头的水管清除掉
if(barSprite.getRightX()<0){
detachChild(barSprite);
barSprite.dispose();
iterator.remove();
}
}
}
}
};
4、小鸟角度旋转逻辑
小鸟在上飞或者下飞的情况下会有不同的角度,这个我们可以根据小鸟的Y速度调试出来。
/**
*小鸟角度旋转逻辑
*/
privatevoidrotateBird(){
floatspeed_y=birdSprite.getBody().getLinearVelocity().y;
floatpRotation=Math.min(Math.max(-30,(speed_y*4f)-45),90);
birdSprite.getBody().setRotation(pRotation);
}
4、分数的处理
分数的处理比较简单,主要用到OGEngine的Text类,以及安卓子身的SharedPreferences来保存每次的最高纪录即可。
publicclassSharedUtil{
privatestaticfinalStringShared_System="Shared_og";
privatestaticfinalStringBEST_SCORE="best_score";
publicstaticvoidsetBestScore(ContextpContext,intpBestScore){
Editoredit=pContext.getSharedPreferences(Shared_System,
Context.MODE_PRIVATE).edit();
edit.putInt(BEST_SCORE,pBestScore);
mit();
}
publicstaticintgetBestScore(Contextcontext){
returncontext
.getSharedPreferences(Shared_System,Context.MODE_PRIVATE)
.getInt(BEST_SCORE,0);
}
}
好了,分析就到这里,更多细节请各位自行看游戏源码。
。
。
。
。
。