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. word2vec前世今生

    word2vec前世今生 2013年,Google开源了一款用于词向量计算的工具--word2vec,引起了工业界和学术界的关注.首先,word2vec可以在百万数量级的词典和上亿的数据集上进行高效地 ...

  2. chrome浏览器快捷键大全

    浏览器标签页和窗口快捷键: Ctrl+N 打开新窗口.Ctrl+T 打开新标签页.Ctrl+Shift+N 在隐身模式下打开新窗口.Ctrl+O,然后选择文件. 在 Google Chrome 浏览器 ...

  3. 团队项目第二阶段个人进展——Day1

    一.昨天工作总结 冲刺第一天,查看了第一阶段的代码 二.遇到的问题 写个的代码发现看不懂了 三.今日工作规划 重新设计页面布局

  4. C#中使用反射遍历一个对象属性和值以及百分数

    对某个类的实例化对象, 遍历获取所有属性(子成员)的方法(采用反射): using (var context = new YZS_TRAEntities()) { ).FirstOrDefault() ...

  5. leetcode 486 预测赢家

    题目描述 给定一个表示分数的非负整数数组. 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,--.每次一个玩家只能拿取一个分数,分数被拿取之后不再可取.直到没 ...

  6. ACM模拟赛

    今天是毕业的学长给高二的同学测试.组队比赛,ACM赛制,于是就愉快的和学姐一队啦. 看到英文题面感到恐慌,不过好在不难读懂. A:并没有什么技术含量的模拟题: B:字符串题,给定一些比赛和每个队胜利的 ...

  7. mysql insert插入的3种方法

    测试表student的字段 1.插入一条数据 INSERT INTO student(sid,sname,sage,ssex) VALUES(1,"wangdali",18,0); ...

  8. CentOS中安装Azkaban 2.5

    必备软件 yum install git -y 单机安装步骤 git clone https://github.com/azkaban/azkaban.git cd azkaban; ./gradle ...

  9. kettle(一) 安装全过程

    windows 10 环境 所有资料下载 https://pan.baidu.com/s/1vYZVJ3f0QJHsCWiupSp08A 一.下载kettle pdi-ce-7.1.0.0-12.zi ...

  10. css心跳动画

    1.图片无限放大缩小,类似心跳 css如下 @keyframes scaleDraw { /*定义关键帧.scaleDrew关键帧名称*/ 0%{ transform: scale(1); /*开始为 ...