Flappy Bird,好吧,无需多说。今天年初不知咋的,一下子就火了,而且直接跃居榜首,在ios和android平台都是如此,实在难以理解。传说其作者每天收入能达到5w刀,着实碉堡了。。。

好吧,咱没创意,不过山寨一个还是可以的,话说!!!

好了,不罗嗦了,直接代码了。

我使用libgdx框架(你要说是引擎也行)实现的,版本为0.9.9。就设计了一个开始画面和一个游戏画面。

游戏入口和主类:

package com.fxb.flappy;

import com.badlogic.gdx.Game;

public class FlappyBird extends Game{

    //static Skin skin;
StartScreen startScreen;
GameScreen gameScreen;
LevelScreen levelScreen; @Override
public void create() {
// TODO Auto-generated method stub Assets.init(); startScreen = new StartScreen(this);
gameScreen = new GameScreen(this);
levelScreen = new LevelScreen(this); setScreen( startScreen );
} @Override
public void render() {
// TODO Auto-generated method stub
super.render();
} @Override
public void dispose() {
// TODO Auto-generated method stub
//skin.dispose();
Assets.clean();
super.dispose();
} }

开始画面:

package com.fxb.flappy;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton; public class StartScreen extends ScreenAdapter{ FlappyBird game;
Stage stage;
TextButton btnStart, btnMode; public StartScreen(FlappyBird game0){
game = game0;
stage = new Stage(); btnStart = new TextButton( "Start Game", Assets.skin, "default" );
btnStart.setSize( 150, 70 );
Constant.CenterInStage( btnStart, stage );
stage.addActor( btnStart ); btnStart.addListener(new InputListener(){
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return true;
}
@Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
game.setScreen( game.gameScreen );
Constant.state = Constant.GameState.game_on;
}
}); } @Override
public void show() {
// TODO Auto-generated method stub
Gdx.input.setInputProcessor( stage );
} @Override
public void render(float delta) {
// TODO Auto-generated method stub
Gdx.gl.glClearColor( 0, 1, 1, 1 );
Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT ); stage.act();
stage.draw();
} @Override
public void dispose() {
// TODO Auto-generated method stub
stage.dispose();
super.dispose();
} }

游戏场景:

package com.fxb.flappy;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.GL10; public class GameScreen extends ScreenAdapter{ FlappyBird game;
GameStage gameStage;
OverStage overStage; public GameScreen(FlappyBird game0){
game = game0;
gameStage = new GameStage(this);
overStage = new OverStage(this);
} @Override
public void show() {
// TODO Auto-generated method stub
Gdx.input.setInputProcessor( gameStage );
} @Override
public void render(float delta) {
// TODO Auto-generated method stub
Gdx.gl.glClearColor( 0, 1, 1, 1 );
Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT ); if( Constant.state == Constant.GameState.game_on ){
gameStage.act();
gameStage.draw();
Gdx.input.setInputProcessor( gameStage );
}
else if( Constant.state == Constant.GameState.game_preover ){
gameStage.draw();
overStage.act();
overStage.draw();
Gdx.input.setInputProcessor( overStage );
} } @Override
public void dispose() {
// TODO Auto-generated method stub
super.dispose();
} }

游戏舞台:

package com.fxb.flappy;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.utils.Pool;
import com.badlogic.gdx.utils.Pools; public class GameStage extends Stage{ GameScreen gameScreen;
Group groupUp, groupDown;
Pool<PipeUp> poolUp;
Pool<PipeDown> poolDown;
Bird bird;
Image imgBack;
OrthographicCamera camera; int xIndex;
float leftX = 0;
float speed;
float currentTime;
float lastTouchTime; public GameStage( GameScreen gameScreen0 ){
gameScreen = gameScreen0; groupUp = new Group();
groupDown = new Group(); poolUp = Pools.get( PipeUp.class );
poolDown = Pools.get( PipeDown.class ); bird = new Bird();
imgBack = Constant.CreateImage( Assets.regionBack );
camera = new OrthographicCamera( Assets.regionBack.getRegionWidth(), Assets.regionBack.getRegionHeight() );
camera.position.set( Assets.regionBack.getRegionWidth()/2, Assets.regionBack.getRegionHeight()/2, 0 ); //addActor( imgBack );
addActor( bird );
addActor( groupUp );
addActor( groupDown ); this.addListener(new InputListener(){
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
if( currentTime - lastTouchTime > 0.15f ){
if( bird.speedY < 0 ){
bird.speedY += 15;
}
else if( bird.speedY < 5 ){
bird.speedY += 15;
}
else if( bird.speedY < 8 ){
bird.speedY += 8;
}
else{
bird.speedY += 4;
} if( bird.speedY > 25 ){
bird.speedY = 25;
}
lastTouchTime = currentTime;
}
return true;
}
}); Clear();
} public void Clear(){
xIndex = 3;
//this.camera.translate( -leftX, 0 );
//this.camera.position.set( getWidth()/2, getHeight()/2, 0 );
this.getCamera().translate( -leftX, 0, 0 );
leftX = 0; speed = 2f;
currentTime = 0;
lastTouchTime = -1f; bird.Clear(); groupUp.clear();
groupDown.clear();
poolUp.clear();
poolDown.clear(); for( int i=0; i<xIndex; ++i ){
AddPipe(i);
} Gdx.input.setInputProcessor(this);
} public void AddPipe( int xIndex0 ){
PipeUp pipeup = poolUp.obtain();
PipeDown pipedown = poolDown.obtain(); groupUp.addActor( pipeup );
groupDown.addActor( pipedown ); float rate1 = MathUtils.random( 0.2f, 1.3f );
float rate2 = 1.5f - rate1; //rate1 = 0.8f;
//rate2 = 0.2f; int height1 = (int)( Assets.regionPipeUp.getRegionHeight()*rate1 );
int height2 = (int)( Assets.regionPipeDown.getRegionHeight()*rate2 ); if( rate1 < 1 ){
pipeup.region = new TextureRegion( Assets.regionPipeUp, 0, Assets.regionPipeUp.getRegionHeight()-height1, Assets.regionPipeUp.getRegionWidth(), height1 );
pipeup.setHeight( height1 );
}
else{
pipeup.region = Assets.regionPipeUp;
pipeup.setHeight( height1 );
} if( rate2 < 1 ){
pipedown.region = new TextureRegion( Assets.regionPipeDown, 0, 0, Assets.regionPipeDown.getRegionWidth(), height2 );
pipedown.setHeight( height2 );
}
else{
pipedown.region = Assets.regionPipeDown;
pipedown.setHeight( height2 );
} //pipedown
pipeup.setPosition( getWidth()+xIndex0*300, getHeight()-pipeup.getHeight() );
pipedown.setPosition( getWidth()+xIndex0*300, 0 );
} @Override
public void act() {
// TODO Auto-generated method stub leftX += speed;
this.getCamera().translate( speed, 0, 0 );
bird.translate( speed, bird.speedY ); currentTime += Gdx.graphics.getDeltaTime(); boolean isDis = false;
for( int i=0; i<groupUp.getChildren().size; ++i ){
PipeUp pipeup = (PipeUp)groupUp.getChildren().items[i];
if( pipeup.getRight() < leftX ){
groupUp.removeActor( pipeup );
poolUp.free( pipeup );
if( !isDis ){
isDis = true;
}
} if( Constant.IsCollsion( pipeup, bird ) ){
//Gdx.app.exit();
Constant.state = Constant.GameState.game_preover;
}
} for( int i=0; i<groupDown.getChildren().size; ++i ){
PipeDown pipedown = (PipeDown)groupDown.getChildren().items[i];
if( pipedown.getRight() < leftX ){
groupDown.removeActor( pipedown );
poolDown.free( pipedown );
if( !isDis ){
isDis = true;
}
} if( Constant.IsCollsion( pipedown, bird ) ){
//Gdx.app.exit();
Constant.state = Constant.GameState.game_preover;
}
} if( isDis ){
AddPipe( xIndex );
xIndex++;
} if( bird.getY() < 0 ){
Constant.state = Constant.GameState.game_preover;
} super.act();
} @Override
public void draw() {
// TODO Auto-generated method stub
camera.update(); SpriteBatch batch = this.getSpriteBatch();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw( Assets.regionBack, 0, 0 );
batch.end(); super.draw();
} @Override
public void dispose() {
// TODO Auto-generated method stub
super.dispose();
} }

游戏结束舞台:

package com.fxb.flappy;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Window; public class OverStage extends Stage{ Window window;
TextButton button1;
TextButton button2;
Label label;
GameScreen gameScreen; public OverStage(GameScreen gameScreen0){
gameScreen = gameScreen0; window = new Window( "", Assets.skin );
//window.add( "GAME OVER\n" ); label = new Label( "GAME OVER", Assets.skin );
//label.setFontScale( 1.0f ); button1 = new TextButton( "Again", Assets.skin );
button2 = new TextButton( "Exit", Assets.skin ); button1.addListener( new InputListener(){
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return true;
} @Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
Constant.state = Constant.GameState.game_on;
gameScreen.gameStage.Clear();
}
}); button2.addListener( new InputListener(){
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return true;
} @Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
//Constant.state = Constant.GameState.game_on;
Gdx.app.exit();
}
}); window.setSize( getWidth()/2, getHeight()/6 );
window.addActor( button1 );
window.addActor( button2 );
window.addActor( label ); button1.setSize( 60, 30 );
button2.setSize( 60, 30 );
label.setSize( 100, 50 );
button1.setPosition( window.getWidth()/8, 10 );
button2.setPosition( window.getWidth()*7/8-button2.getWidth(), 10 );
label.setPosition( window.getWidth()/2-label.getWidth()/2, button2.getTop()+20 ); this.addActor( window );
Constant.CenterInStage( window, this );
} }

游戏主角类,即那只鸟

package com.fxb.flappy;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor; public class Bird extends Actor{ Animation animation;
float currentTime;
float speedY; public Bird(){
animation = new Animation( 0.15f, Assets.sRegionBird );
setSize( Assets.sRegionBird[0].getRegionWidth(), Assets.sRegionBird[0].getRegionHeight() );
setOrigin( getWidth()/2, getHeight()/2 );
//setPosition( );
Clear();
} public void Clear(){
currentTime = 0;
setPosition( 100, Gdx.graphics.getHeight()/2-getHeight()/2 );
speedY = Constant.speedY;
} @Override
public void act(float delta) {
// TODO Auto-generated method stub
currentTime += delta; //this.translate( 0, speedY );
//speedY -= 0.5f; if( speedY > -10f ){
speedY += Constant.speedInc;
} super.act(delta);
} @Override
public void draw(SpriteBatch batch, float parentAlpha) {
// TODO Auto-generated method stub TextureRegion keyFrame = animation.getKeyFrame( currentTime, true ); batch.draw( keyFrame, getX(), getY(), getOriginX(), getOriginY(), getWidth(), getHeight(), getScaleX(), getScaleY(), getRotation() ); super.draw(batch, parentAlpha);
} }

上面管道类

package com.fxb.flappy;

import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor; public class PipeUp extends Actor{ TextureRegion region; public PipeUp(){
region = new TextureRegion( Assets.regionPipeUp );
setSize( region.getRegionWidth(), region.getRegionHeight() );
} /*
public UpdateRegion(){
region = new TextureRegion( Assets.regionPipeUp );
}
*/
@Override
public void act(float delta) {
// TODO Auto-generated method stub
super.act(delta);
} @Override
public void draw(SpriteBatch batch, float parentAlpha) {
// TODO Auto-generated method stub //batch.draw( region, region.getRegionX(), region.getRegionY(), region.getRegionWidth(), region.getRegionHeight() );
batch.draw( region, getX(), getY(), getWidth(), getHeight() ); super.draw(batch, parentAlpha);
}
}

下面管道类:

 package com.fxb.flappy;

 import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor; public class PipeDown extends Actor{ TextureRegion region; public PipeDown(){
region = new TextureRegion( Assets.regionPipeDown );
setSize( region.getRegionWidth(), region.getRegionHeight() );
} @Override
public void act(float delta) {
// TODO Auto-generated method stub
super.act(delta);
} @Override
public void draw(SpriteBatch batch, float parentAlpha) {
// TODO Auto-generated method stub
//batch.draw( region, region.getRegionX(), region.getRegionY(), region.getRegionWidth(), region.getRegionHeight() );
batch.draw( region, getX(), getY(), getWidth(), getHeight() );
super.draw(batch, parentAlpha);
}
}

资源类:

 package com.fxb.flappy;

 import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.ui.Skin; public class Assets {
public static Skin skin;
public static AssetManager manager;
public static TextureAtlas atlas;
public static TextureRegion[] sRegionBird; public static TextureRegion regionPipeUp;
public static TextureRegion regionPipeDown;
public static TextureRegion regionBack; public static void init(){
skin = new Skin( Gdx.files.internal( "skin/uiskin.json" ) );
atlas = new TextureAtlas( Gdx.files.internal( "data/bird.pack" ) ); sRegionBird = new TextureRegion[3];
for( int i=0; i<sRegionBird.length; ++i ){
sRegionBird[i] = atlas.findRegion( "bird_blue", i );
} regionPipeUp = atlas.findRegion( "bound_up" );
regionPipeDown = atlas.findRegion( "bound_down" );
regionBack = atlas.findRegion( "background" ); } public static void clean(){
if( skin != null ) skin.dispose();
if( atlas != null ) atlas.dispose(); }
}

常量及功能函数类:

 package com.fxb.flappy;

 import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image; public class Constant { enum GameState{ game_ready, game_on, game_preover, game_over };
public static GameState state = GameState.game_ready; public static float speedY = -1f;
public static float speedInc = -0.5f; public static void CenterInStage( Actor actor, Stage stage ){
actor.setPosition( stage.getWidth()/2-actor.getWidth()/2, stage.getHeight()/2-actor.getHeight()/2 );
} public static Image CreateImage( TextureRegion region0 ){
Image img = new Image( region0 );
img.setSize( region0.getRegionWidth(), region0.getRegionHeight() );
return img;
} public static boolean IsCollsion( Actor actor1, Actor actor2 ){
float x1 = actor1.getX(), y1 = actor1.getY(), w1 = actor1.getWidth(), h1 = actor1.getHeight();
float x2 = actor2.getX(), y2 = actor2.getY(), w2 = actor2.getWidth(), h2 = actor2.getHeight();
if( x1<x2 && x1+w1<x2 ){
return false;
}
else if( x2<x1 && x2+w2<x1 ){
return false;
}
else if( y1<y2 && y1+h1<y2 ){
return false;
}
else if( y2<y1 && y2+h2<y1 ){
return false;
} return true;
} }

大概就这样了,也是比较粗糙。自己试验了下,在android平台下感觉操作不太顺手,可能里面一些参数还是没有调整好,提升的空间挺大的!!

libgdx自制简易Flappy Bird的更多相关文章

  1. libgdx自制简易版Don't Touch The White Tile

    Don't Toutch The White说来也奇快,本来没什么难的,但是在欧美ios榜上却雄踞榜首好长时间.即使是在国内,也很火,还真是想不通,谁能解释下,难道真是所谓的抓住了用户的G点,或是这些 ...

  2. 65行 JavaScript 代码实现 Flappy Bird 游戏

    飞扬的小鸟(Flappy Bird)无疑是2014年全世界最受关注的一款游戏.这款游戏是一位来自越南河内的独立游戏开发者阮哈东开发,形式简易但难度极高的休闲游戏,很容易让人上瘾. 这里给大家分享一篇这 ...

  3. [MFC] 高仿Flappy bird 桌面版

    这是今年年初做的东西,一直没有时间整理,现在拿出来分享下~ 目录 开发背景 开发语言及运行环境 效果展示 游戏框架说明 游戏状态及逻辑说明 经典算法说明 重量级问题解决 开发感想 一.开发背景: fl ...

  4. 技术宅之flappy bird 二逼鸟

    师雪坤和刘阳 风靡一时的虐心小游戏<Flappy Bird>,以玩法简单.难度超高著称,不过,最近这款让全世界玩家几欲怒摔手机的游戏,被两位中国技术宅设计的"玩鸟机器人" ...

  5. 教你从头到尾利用DQN自动玩flappy bird(全程命令提示,GPU+CPU版)【转】

    转自:http://blog.csdn.net/v_JULY_v/article/details/52810219?locationNum=3&fps=1 目录(?)[-] 教你从头到尾利用D ...

  6. canvas 制作flappy bird(像素小鸟)全流程

    flappy bird制作全流程: 一.前言 像素小鸟这个简单的游戏于2014年在网络上爆红,游戏上线一段时间内appleStore上的下载量一度达到5000万次,风靡一时, 近年来移动web的普及为 ...

  7. 自己动手写游戏:Flappy Bird

    START:最近闲来无事,看了看一下<C#开发Flappy Bird游戏>的教程,自己也试着做了一下,实现了一个超级简单版(十分简陋)的Flappy Bird,使用的语言是C#,技术采用了 ...

  8. C语言版flappy bird黑白框游戏

    在此记录下本人在大一暑假,2014.6~8这段时间复习C语言,随手编的一个模仿之前很火热的小游戏----flappy bird.代码bug基本被我找光了,如果有哪位兄弟找到其他的就帮我留言下吧,谢谢了 ...

  9. 闲扯游戏编程之html5篇--山寨版《flappy bird》源码

    新年新气象,最近事情不多,继续闲暇学习记点随笔,欢迎拍砖.之前的〈简单游戏学编程语言python篇〉写的比较幼稚和粗糙,且告一段落.开启新的一篇关于javascript+html5的从零开始的学习.仍 ...

随机推荐

  1. jquery中使用datepicker限制开始日期小于结束日期

    这里是使用Jquery插件实现的,这段代码来自于网络.感觉很实用,就做笔记记录下来. 原文:http://blog.csdn.net/tianyacao8025/article/details/707 ...

  2. 在web中如何调整上传过的图片方向 (exif)

    前提: 相机中拍的照片放到web上不会自动识别方向,如有些竖向显示的照片放到web上横向显示.这些照片在windows上是正确显示的.但是web不会自动旋转照片到正确方向.下面我们通过两种方法来实现这 ...

  3. phpmyadmin 下载、安装、配置

    phpmyadmin 下载.安装.配置 phpmyadmin 下载.安装.配置 地址:https://www.phpmyadmin.net/ 点击右上角下载按钮 下载得到phpMyAdmin-4.7. ...

  4. 使用Amanda ZRM备份远程MySQL数据库

    本文写道最后的时候,我才发现ZRM for MySQL的一个致命问题,就我目前的理解和测试来看,它恢复数据的时候是采取覆盖的方式,举个例子,假定某台数据库服务器上有两个数据库test1,test2,你 ...

  5. 转:C#综合揭秘——细说进程、应用程序域与上下文之间的关系

    引言 本文主要是介绍进程(Process).应用程序域(AppDomain)..NET上下文(Context)的概念与操作.虽然在一般的开发当中这三者并不常用,但熟悉三者的关系,深入了解其作用,对提高 ...

  6. 2018亚太CDN峰会开幕, 阿里云王海华解读云+端+AI的短视频最佳实践

    4月11-12日,2018亚太CDN峰会在北京隆重召开,在11日下午的短视频论坛中,阿里云高级技术专家王海华进行了<短视频最佳实践:云+端+AI>的主题演讲,分享了短视频的生命周期关键点和 ...

  7. plupload 大文件分片上传与PHP分片合并探索

    最近老大分给我了做一个电影cms系统,其中涉及到一个功能,使用七牛云的文件上传功能.七牛javascript skd,使用起来很方便,屏蔽了许多的技术细节.如果只满足与调用sdk,那么可能工作中也就没 ...

  8. ArcGIS pro2.3中添加天地图底图

    应用背景: 很多时候,我们需要使用网络上的遥感影像或者百度地图.天地图等在线地图做一些矢量化工作或者其他. 笔者见过很多人都是把百度地图截图,然后把图片导如Arcmap或者Arcgis pro中,然后 ...

  9. Alpha冲刺报告(9/12)(麻瓜制造者)

    今日已完成 邓弘立: 正在进行主页逻辑的编写 符天愉: 部署商品发布和物品需求的接口 江郑: 尝试完善接口文档,进行进一步测试 刘双玉: 编写接口说明 肖小强: 进行逻辑模块的编写 李佳铭: 修改了U ...

  10. Python3编写网络爬虫01-基本请求库urllib的使用

    安装python后 自带urllib库 模块篇 分为几个模块如下: 1. urllib.request 请求模块 2. urllib.parse 分析模块 3. urllib.error 异常处理模块 ...