您的位置:首页 > 移动开发

研读FlappyBird代码

2016-03-26 23:50 176 查看
一、工程结构

--config                         

  ----Config

  -----Constants

--object

  -----Bird

  -----Column

  -----GameObject

  -----Ground

--util

  -----FileManager

  -----SoundPlayer

--view

  -----BaseView

  -----LoadingView

  -----MainView

MainActivity

二、代码

Config类

package com.hitsz.xiaokai.flybird.config;

/**
* Created by Administrator on 2016/3/26.
*/
public class Config {

public final static int TO_MAIN_VIEW = 1;//命令切换到主视图
public final static int END_GAME = 0;//命令游戏结束

public final static int LOADING_GAME_INTERVAL = 2000;//加载界面时间

public final static int SPEED = (int) (Constants.SCREEN_WIDTH * 5 / 480);//column和ground的运动速度

public final static float COLUMN_Y_GAP = Constants.SCREEN_HEIGHT * 173 / 854;//column图片管子间空隙高度(不得修改,由图片决定)
public final static float COLUMN_X_GAP = Constants.SCREEN_WIDTH / 2 + 50;//两个管子间的水平间距

public final static double v0 = Constants.SCREEN_HEIGHT * 23 / 854;//小鸟上抛初速度
public final static double g = Constants.SCREEN_HEIGHT * 3 / 854;//重力加速度
public final static double t = 0.6;//时间间隔

}
Constants类
package com.hitsz.xiaokai.flybird.config;

/**
* Created by Administrator on 2016/3/26.
*/
public class Constants {

public static float SCREEN_WIDTH;//屏幕宽度
public static float SCREEN_HEIGHT;//屏幕高度

}Bird类
package com.hitsz.xiaokai.flybird.object;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;

import com.hitsz.xiaokai.flybird.R;
import com.hitsz.xiaokai.flybird.config.Config;
import com.hitsz.xiaokai.flybird.config.Constants;

/**
* Created by Administrator on 2016/3/26.
*/
public class Bird extends GameObject {

private Bitmap[] birdImgs;
private Bitmap birdImg;

private final double v0 = Config.v0;
private final double g = Config.g;
private final double t = Config.t;

private double speed;
private double s;
private float angle;

private float groundHeight;

private Rect obj_rect;

public Bird(Resources resources, float groundHeight) {
super(resources);
this.obj_rect = new Rect();
this.groundHeight = groundHeight;
initBitmap();
}

@Override
public void step() {
double v1 = speed;
double v = v1 - g * t;
speed = v;
s= v1 * t - 0.5 * g * t * t;
obj_y = obj_y - (float) s;
if(obj_y <= 0) {
obj_y = this.obj_height / 2;
}
if(obj_y >= Constants.SCREEN_HEIGHT - this.groundHeight - this.obj_height) {
obj_y = Constants.SCREEN_HEIGHT - this.groundHeight - this.obj_height;
}
if(speed >= 0) {
birdImg = birdImgs[(currentFrame / 3)];
currentFrame++;
if(currentFrame == 9) {
currentFrame = 0;
}
} else {
birdImg = birdImgs[2];
}
angle = (float) (s * 4);
if(angle >= 30) {
angle = 30;
}
if(angle <= -90) {
angle = -90;
}

this.obj_mid_y = this.obj_y + this.obj_height / 2;

//obj_rect.left = (int) obj_x;
//obj_rect.top = (int) obj_y;
//obj_rect.right = (int) (obj_x + obj_height + (obj_width - obj_height) * (1 - Math.cos(angle)));
//obj_rect.bottom = (int) Math.floor (obj_y + obj_width - Math.abs((obj_width - obj_height) * Math.sin(angle)));

obj_rect.left = (int) (obj_x + (obj_width - obj_height) / 2);
obj_rect.top = (int) (obj_y + (obj_width - obj_height) / 2);
obj_rect.right = (int) (obj_rect.left + obj_height);
obj_rect.bottom = (int) (obj_rect.top + obj_height - (obj_width - obj_height) / 2);
}

public void flappy() {
speed = v0;
}

@Override
public void drawSelf(Canvas canvas) {
canvas.save();
canvas.rotate(-angle, obj_mid_x, obj_mid_y);
canvas.drawBitmap(birdImg, obj_x, obj_y, paint);
canvas.restore();
/*
paint.setColor(Color.BLACK);
paint.setAlpha(50);
canvas.drawRect(obj_rect, paint);
*/
}

public boolean pass(Column column) {
if(this.obj_mid_x <= column.getObjMidX() && column.getObjMidX() - this.obj_mid_x < 5) {
return true;
}
return false;
}

public boolean hitColumn(Column column) {
if(this.obj_rect.intersect(column.getObjRectTop()) || this.obj_rect.intersect(column.getObjRectBottom())) {
return true;
}
return false;
}

public boolean hitGround(Ground ground) {
/*if(this.obj_rect.intersect(ground.getObjRect())) {
return true;
}
return false;*/

if((this.obj_rect.bottom + 1 ) >= ground.getObjRect().top) {
return true;
}
return false;
}

@Override
public void initBitmap() {
birdImgs = new Bitmap[3];
birdImgs[0] = BitmapFactory.decodeResource(resources, R.drawable.bird0);
birdImgs[1] = BitmapFactory.decodeResource(resources, R.drawable.bird1);
birdImgs[2] = BitmapFactory.decodeResource(resources, R.drawable.bird2);

birdImg = birdImgs[0];

this.obj_width = birdImg.getWidth();
this.obj_height = birdImg.getHeight();

this.obj_x = this.obj_width * 2;
this.obj_y = Constants.SCREEN_HEIGHT / 2 - this.obj_height / 2;

this.obj_mid_x = this.obj_x + this.obj_width / 2;
this.obj_mid_y = this.obj_y + this.obj_height / 2;
}

@Override
public void release() {
for(int i=0; i<3; i++) {
if(!birdImgs[i].isRecycled()) {
birdImgs[i].recycle();
}
}
}

public Rect getObjRect() {
return this.obj_rect;
}

}Column类
package com.hitsz.xiaokai.flybird.object;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;

import com.hitsz.xiaokai.flybird.R;
import com.hitsz.xiaokai.flybird.config.Config;
import com.hitsz.xiaokai.flybird.config.Constants;

import java.util.Random;

/**
* Created by Administrator on 2016/3/26.
*/
public class Column extends GameObject {

private Bitmap columnImg;

private Random random;

private float groundHeight;

private Rect rectTop;
private Rect rectBottom;

public Column(Resources resources, float x, float groundHeight) {
super(resources);
rectTop = new Rect();
rectBottom = new Rect();
this.groundHeight = groundHeight;
random = new Random();
this.obj_mid_x = x;
this.obj_mid_y = random.nextInt((int)(Constants.SCREEN_HEIGHT - this.groundHeight - Config.COLUMN_Y_GAP * 2)) + Config.COLUMN_Y_GAP;
initBitmap();
}

@Override
public void step() {
this.obj_mid_x -=Config.SPEED;
if(this.obj_mid_x <= -(Config.COLUMN_X_GAP - this.obj_width / 2)) {
this.obj_mid_x = Config.COLUMN_X_GAP * 2 + this.obj_width / 2;
this.obj_mid_y = random.nextInt((int)(Constants.SCREEN_HEIGHT - this.groundHeight - Config.COLUMN_Y_GAP * 2)) + Config.COLUMN_Y_GAP;
}
}

@Override
public void drawSelf(Canvas canvas) {
canvas.drawBitmap(columnImg, obj_mid_x - this.obj_width / 2, obj_mid_y - this.obj_height / 2, paint);
}

@Override
public void initBitmap() {
columnImg = BitmapFactory.decodeResource(resources, R.drawable.column);

this.obj_width = columnImg.getWidth();
this.obj_height = columnImg.getHeight();
}

@Override
public void release() {
if(!columnImg.isRecycled()) {
columnImg.recycle();
}
}

public Rect getObjRectTop() {
this.rectTop.set((int)(obj_mid_x - obj_width / 2), 0, (int)(obj_mid_x + obj_width / 2), (int)(obj_mid_y - Config.COLUMN_Y_GAP / 2));
return this.rectTop;
}

public Rect getObjRectBottom() {
this.rectBottom.set((int)(obj_mid_x - obj_width / 2), (int)(obj_mid_y + Config.COLUMN_Y_GAP / 2), (int)(obj_mid_x + obj_width / 2), (int)Constants.SCREEN_HEIGHT);
return this.rectBottom;
}

}
GameObject类
package com.hitsz.xiaokai.flybird.object;

import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;

/**
* Created by Administrator on 2016/3/26.
*/
public abstract class GameObject {

protected int currentFrame;//当前动画帧

protected float obj_x;//对象左上角坐标
protected float obj_y;

protected float obj_mid_x;//对象中心横坐标
protected float obj_mid_y;//对象中心纵坐标

protected float obj_width;//对象宽度
protected float obj_height;//对象高度

protected Resources resources;
protected Paint paint;

public GameObject(Resources resources) {
this.resources = resources;
paint = new Paint();
}

//对象运动逻辑
public abstract void step();

//绘图方法
public abstract void drawSelf(Canvas canvas);

//初始化如片资源
public abstract void initBitmap();

//释放图片资源
public abstract void release();

public void setObjX(float x) {
this.obj_x = x;
}

public float getObjX() {
return this.obj_x;
}

public void setObjY(float y) {
this.obj_y = y;
}

public float getObjY() {
return this.obj_y;
}

public void setObjMidX(float x) {
this.obj_mid_x = x;
}

public float getObjMidX() {
return this.obj_mid_x;
}

public void setObjMidY(float y) {
this.obj_mid_y = y;
}

public float getObjMidY() {
return this.obj_mid_y;
}

public void setObjWidth(float w) {
this.obj_width = w;
}

public float getObjWidth() {
return this.obj_width;
}

public void setObjHeight(float h) {
this.obj_height = h;
}

public float getObjHeight() {
return this.obj_height;
}

}Ground类
package com.hitsz.xiaokai.flybird.object;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;

import com.hitsz.xiaokai.flybird.R;
import com.hitsz.xiaokai.flybird.config.Config;
import com.hitsz.xiaokai.flybird.config.Constants;

/**
* Created by Administrator on 2016/3/26.
*/
public class Ground extends GameObject {

private Bitmap groundImg;

private Rect obj_rect;

public Ground(Resources resources) {
super(resources);
this.obj_rect = new Rect();
this.obj_x = 0;
initBitmap();
}

@Override
public void step() {
this.obj_x -= Config.SPEED;
if(this.obj_x <= -(this.obj_width - Constants.SCREEN_WIDTH)) {
this.obj_x = -15;
}
}

@Override
public void drawSelf(Canvas canvas) {
canvas.drawBitmap(groundImg, obj_x, obj_y, paint);
}

@Override
public void initBitmap() {
groundImg = BitmapFactory.decodeResource(resources, R.drawable.ground);

this.obj_width = groundImg.getWidth();
this.obj_height = groundImg.getHeight();

this.obj_y = Constants.SCREEN_HEIGHT - this.obj_height;
}

public Rect getObjRect() {
obj_rect.set(0, (int)obj_y, (int)Constants.SCREEN_WIDTH, (int)Constants.SCREEN_HEIGHT);
return this.obj_rect;
}

@Override
public void release() {
if(!groundImg.isRecycled()) {
groundImg.recycle();
}
}

}
FileManager类
package com.hitsz.xiaokai.flybird.util;

import android.os.Environment;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.http.util.EncodingUtils;

/**
* Created by Administrator on 2016/3/26.
*/
public class FileManager {

private File sdDir;
private File dirPath;
private File file;

public String fileReader() {
String score = null;
try {
FileInputStream fin = new FileInputStream(file);
int length = fin.available();
byte[] buffer = new byte[length];
fin.read(buffer);
score = EncodingUtils.getString(buffer, "UTF-8");
fin.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return score;
}

public void fileWriter(String msg) {
String score = null;
try {
FileOutputStream fout = new FileOutputStream(file);
byte[] buffer = msg.getBytes();
fout.write(buffer);
fout.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

public void initFile() {
String dirpath = getSDPath() + File.separator + "FlyBird";
dirPath = new File(dirpath);
if(!dirPath.exists()) {
dirPath.mkdirs();
}

String filePath = dirpath + File.separator + "score.txt";
file = new File(filePath);
if(!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}

public boolean sdIsAvalible() {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); //判断sd卡是否存在
}

public String getSDPath(){
sdDir = Environment.getExternalStorageDirectory();//获取跟目录
return sdDir.toString();
}

}SoundPlayer类
package com.hitsz.xiaokai.flybird.util;

import android.media.AudioManager;
import android.media.SoundPool;

import com.hitsz.xiaokai.flybird.MainActivity;
import com.hitsz.xiaokai.flybird.R;

import java.util.HashMap;

/**
* Created by Administrator on 2016/3/26.
*/
public class SoundPlayer {
private SoundPool soundPool;
private MainActivity mainActivity;
private HashMap<Integer,Integer> map;
public SoundPlayer(MainActivity mainActivity) {
this.mainActivity=mainActivity;
map=new HashMap<Integer,Integer>();
soundPool=new SoundPool(8, AudioManager.STREAM_MUSIC,0);
}
public void initSounds() {
map.put(1, soundPool.load(mainActivity, R.raw.flappy, 1));//飞扬
map.put(2, soundPool.load(mainActivity, R.raw.pass, 1));//经过通到
map.put(3, soundPool.load(mainActivity, R.raw.hit, 1));//撞到
map.put(4, soundPool.load(mainActivity, R.raw.die, 1));//死掉
map.put(5, soundPool.load(mainActivity, R.raw.swooshing, 1));//切换
}
public void playSound(int sound,int loop){
soundPool.play(sound,1,1,1,loop,1.0f);
}
}


BaseView类
package com.hitsz.xiaokai.flybird.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.hitsz.xiaokai.flybird.MainActivity;
import com.hitsz.xiaokai.flybird.config.Constants;
import com.hitsz.xiaokai.flybird.util.SoundPlayer;

/**
* Created by Administrator on 2016/3/26.
*/
public class BaseView extends SurfaceView implements SurfaceHolder.Callback, Runnable {

protected float scaleX;//背景图片缩放比例
protected float scaleY;

protected MainActivity mainActivity;
protected SoundPlayer soundPlayer;

protected Canvas canvas;//画布对象
protected Paint paint;//画笔对象
protected SurfaceHolder sfh;

protected Thread thread;//绘画线程
protected boolean threadFlag;//标记线程运行

//构造函数
public BaseView(Context context, SoundPlayer soundPlayer) {
super(context);
this.mainActivity = (MainActivity) context;
this.soundPlayer = soundPlayer;
this.sfh = this.getHolder();
this.sfh.addCallback(this);
this.paint = new Paint();
}

//线程运行的方法
@Override
public void run() {}

//初始化图片资源
public void initBitmap() {}

//释放图片资源
public void release() {}

//绘图方法
public void drawSelf() {}

//视图改变的方法
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {}

//视图创建的方法
@Override
public void surfaceCreated(SurfaceHolder arg0) {
Constants.SCREEN_WIDTH = this.getWidth();
Constants.SCREEN_HEIGHT = this.getHeight();
this.threadFlag = true;
}

//视图销毁的方法
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
this.threadFlag = false;
}

public void setThreadFlag(boolean threadFlag) {
this.threadFlag = threadFlag;
}

}


LoadingView类
package com.hitsz.xiaokai.flybird.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.view.SurfaceHolder;

import com.hitsz.xiaokai.flybird.R;
import com.hitsz.xiaokai.flybird.config.Config;
import com.hitsz.xiaokai.flybird.config.Constants;
import com.hitsz.xiaokai.flybird.util.SoundPlayer;

/**
* Created by Administrator on 2016/3/26.
*/
public class LoadingView extends BaseView {

private Bitmap bgImg;
private Bitmap logoImg;
private Bitmap textImg;

//private float bgImgX;//图片坐标
//private float bgImgY;

private float logoImgX;
private float logoImgY;

private float textImgX;
private float textImgY;

private String author = "仿写者:小开";//绘制文字区域
private Rect rect;

private float strWidth;
private float strHeight;

private float textX;
private float textY;

public LoadingView(Context context, SoundPlayer soundPlayer) {
super(context, soundPlayer);
rect = new Rect();
this.thread = new Thread(this);
}

@Override
public void surfaceCreated(SurfaceHolder arg0) {
super.surfaceCreated(arg0);
initBitmap();
if(this.thread.isAlive()) {
this.thread.start();
} else {
this.thread = new Thread(this);
this.thread.start();
}
}

@Override
public void initBitmap() {
this.bgImg = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
this.logoImg = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
this.textImg = BitmapFactory.decodeResource(getResources(), R.drawable.text_logo);

this.scaleX = Constants.SCREEN_WIDTH / this.bgImg.getWidth();
this.scaleY = Constants.SCREEN_HEIGHT / this.bgImg.getHeight();

this.textImgX = (Constants.SCREEN_WIDTH - this.textImg.getWidth()) / 2;
this.textImgY = Constants.SCREEN_HEIGHT / 2 - this.textImg.getHeight() * 2;

this.logoImgX = (Constants.SCREEN_WIDTH - this.logoImg.getWidth()) / 2;
this.logoImgY = Constants.SCREEN_HEIGHT / 2 - this.logoImg.getWidth() * 0;

this.paint.setTextSize(40);
this.paint.getTextBounds(author, 0, author.length(), rect);

this.strWidth = rect.width();
this.strHeight = rect.height();

this.textX = Constants.SCREEN_WIDTH / 2 - this.strWidth / 2;
this.textY = Constants.SCREEN_HEIGHT / 2 + logoImg.getHeight() + this.strHeight * 2;
}

@Override
public void run() {
while(this.threadFlag) {
drawSelf();
try {
Thread.sleep(Config.LOADING_GAME_INTERVAL);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.threadFlag = false;
}
mainActivity.getHandler().sendEmptyMessage(Config.TO_MAIN_VIEW);
}

@Override
public void drawSelf() {
try {
canvas = sfh.lockCanvas();
canvas.save();
canvas.scale(this.scaleX, this.scaleY);
canvas.drawBitmap(bgImg, 0, 0, paint);
canvas.restore();
canvas.drawBitmap(textImg, textImgX, textImgY, paint);
canvas.drawBitmap(logoImg, logoImgX, logoImgY, paint);
canvas.drawText(author, textX, textY, paint);
} catch(Exception err) {
err.printStackTrace();
} finally {
if(canvas != null) {
sfh.unlockCanvasAndPost(canvas);
}
}
}

@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
super.surfaceDestroyed(arg0);
release();
}

@Override
public void release() {
if(!this.bgImg.isRecycled()){
this.bgImg.recycle();
}
if(!this.logoImg.isRecycled()){
this.logoImg.recycle();
}
if(!this.textImg.isRecycled()){
this.textImg.recycle();
}
}

}

MainView类
package com.hitsz.xiaokai.flybird.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.widget.Toast;

import com.hitsz.xiaokai.flybird.R;
import com.hitsz.xiaokai.flybird.config.Config;
import com.hitsz.xiaokai.flybird.config.Constants;
import com.hitsz.xiaokai.flybird.object.Bird;
import com.hitsz.xiaokai.flybird.object.Column;
import com.hitsz.xiaokai.flybird.object.Ground;
import com.hitsz.xiaokai.flybird.util.FileManager;
import com.hitsz.xiaokai.flybird.util.SoundPlayer;

import java.util.ArrayList;
import java.util.List;

/**
* Created by Administrator on 2016/3/26.
*/
public class MainView extends BaseView {

private Ground ground;
private Column column1;
private Column column2;
private Column column3;
private Bird bird;

private FileManager fileManager;

private Bitmap bgImg;
private Bitmap startImg;
private Bitmap endImg;
private Bitmap restartButtonImg;
private Bitmap exitButtonImg;
private Bitmap noticeImg;
private Bitmap pauseButtonImg;
private Bitmap bigNumbersImg;
private Bitmap smallNumbersImg;
private Bitmap medalImg;

private float startImgX;
private float startImgY;
private float endImgX;
private float endImgY;
private float noticeImgX;
private float noticeImgY;
private float restartButtonImgX;
private float restartButtonImgY;
private float exitButtonImgX;
private float exitButtonImgY;
private float pauseButtonImgX;
private float pauseButtonImgY;
private float bigNumbersImgX;
private float bigNumbersImgY;
private float smallNumbersImgX;//bestScore位置
private float smallNumbersImgY;
private float smallScoreX;
private float smallScoreY;
private float medalImgX;
private float medalImgY;

private boolean isStart;
private boolean isHit;
private boolean isOver;
private boolean isPause;
private boolean isWrite;

private int score;
private int bestScore;

//private Rect rect;

public MainView(Context context, SoundPlayer soundPlayer) {
super(context, soundPlayer);
isStart = false;
isHit = false;
isOver = false;
isPause = false;
isWrite = false;
//rect = new Rect();

//Toast.makeText(this.mainActivity.getApplicationContext(), Constants.SCREEN_WIDTH + " " + Constants.SCREEN_HEIGHT, Toast.LENGTH_LONG).show();

fileManager = new FileManager();
if(fileManager.sdIsAvalible()) {
fileManager.initFile();
if(fileManager.fileReader().length() <= 0) {
bestScore = 0;
} else {
bestScore = Integer.parseInt(fileManager.fileReader());
}
} else {
//Looper.prepare();
Toast.makeText(this.mainActivity.getApplicationContext(), "SD卡不可用,将无法保存您的最高纪录", Toast.LENGTH_LONG).show();
//Looper.loop();
}
ground = new Ground(getResources());
column1 = new Column(getResources(), Config.COLUMN_X_GAP * 2, ground.getObjHeight());
column2 = new Column(getResources(), Config.COLUMN_X_GAP + column1.getObjMidX(), ground.getObjHeight());
column3 = new Column(getResources(), Config.COLUMN_X_GAP + column2.getObjMidX(), ground.getObjHeight());
bird = new Bird(getResources(), ground.getObjHeight());
this.thread = new Thread(this);
}

@Override
public void run() {
while(this.threadFlag) {
if(!isHit && !isOver) {
ground.step();
}
if(isStart && !isHit &&!isOver) {
column1.step();
column2.step();
column3.step();
}
if(isStart) {
bird.step();
}
drawSelf();
if(isOver) {
threadFlag = false;
}
if(isPause) {
synchronized (thread) {
try {
thread.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
try {
Thread.sleep(1000 / 60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
drawSelf();

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
drawNotice();

if(fileManager.sdIsAvalible()) {
if(score > bestScore) {
fileManager.fileWriter(String.valueOf(score));
}
}

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=0; i<=score; i++) {
drawResult(i);
try {
Thread.sleep(1000/60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(thread) {
drawMedal();
}

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
drawButton();
isWrite = true;
}

@Override
public void drawSelf() {
try {
canvas = sfh.lockCanvas();

drawObject();

if(!isHit) {
if(bird.pass(column1) || bird.pass(column2) || bird.pass(column3)) {
soundPlayer.playSound(2, 0);
score++;
}
if(bird.hitColumn(column1) || bird.hitColumn(column2) ||bird.hitColumn(column3)){
soundPlayer.playSound(3, 0);
paint.setAlpha(50);
paint.setColor(Color.WHITE);
canvas.drawRect(0, 0, Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT, paint);
isHit = true;
}
}

/*paint.setTextSize(26);
paint.setColor(Color.WHITE);
paint.getTextBounds(String.valueOf(score), 0, String.valueOf(score).length(), rect);
canvas.drawText(String.valueOf(score), 10, rect.height() + 5, paint);
*/
if(!isOver) {
drawScore(bigNumbersImg, bigNumbersImgX, bigNumbersImgY, score);
}

if(isOver) {
soundPlayer.playSound(5, 0);
canvas.drawBitmap(endImg, endImgX, endImgY, paint);
}
if(!isOver) {
if(bird.hitGround(ground)){
soundPlayer.playSound(4, 0);
isOver = true;
}
}
if(!isStart) {
if(!isStart) {
canvas.drawBitmap(startImg, startImgX, startImgY, paint);
}
}
if(isStart && !isHit && !isOver) {
if(!isPause) {
canvas.save();
canvas.clipRect(pauseButtonImgX, pauseButtonImgY, pauseButtonImgX + pauseButtonImg.getWidth(), pauseButtonImgY + pauseButtonImg.getHeight() / 2);
canvas.drawBitmap(pauseButtonImg, pauseButtonImgX, pauseButtonImgY, paint);
canvas.restore();
}
else {
canvas.save();
canvas.clipRect(pauseButtonImgX, pauseButtonImgY, pauseButtonImgX + pauseButtonImg.getWidth(), pauseButtonImgY + pauseButtonImg.getHeight() / 2);
canvas.drawBitmap(pauseButtonImg, pauseButtonImgX, pauseButtonImgY - pauseButtonImg.getHeight() / 2, paint);
canvas.restore();
}
}
} catch (Exception err) {
err.printStackTrace();
} finally {
if(canvas != null) {
sfh.unlockCanvasAndPost(canvas);
}
}
}

public void drawNotice() {
try {
canvas = sfh.lockCanvas();

drawObject();

soundPlayer.playSound(5, 0);
canvas.drawBitmap(endImg, endImgX, endImgY, paint);

canvas.drawBitmap(noticeImg, noticeImgX, noticeImgY, paint);
} catch (Exception err) {
err.printStackTrace();
} finally {
if(canvas != null) {
sfh.unlockCanvasAndPost(canvas);
}
}
}

public void drawResult(int i) {
try {
canvas = sfh.lockCanvas();

drawObject();

//soundPlayer.playSound(5, 0);
canvas.drawBitmap(endImg, endImgX, endImgY, paint);

canvas.drawBitmap(noticeImg, noticeImgX, noticeImgY, paint);

/*
paint.setTextSize(26);
paint.setColor(Color.WHITE);
paint.getTextBounds(String.valueOf(bestScore), 0, String.valueOf(bestScore).length(), rect);
canvas.drawText(String.valueOf(bestScore), noticeImgX + noticeImg.getWidth() - rect.width(), noticeImgY + noticeImg.getHeight() - rect.height(), paint);
*/

drawScore(smallNumbersImg, smallScoreX, smallScoreY, i);

//drawScore(smallNumbersImg, smallNumbersImgX, smallNumbersImgY, bestScore);

} catch (Exception err) {
err.printStackTrace();
} finally {
if(canvas != null) {
sfh.unlockCanvasAndPost(canvas);
}
}
}

public void drawMedal() {
try {
canvas = sfh.lockCanvas();

drawObject();

soundPlayer.playSound(5, 0);
canvas.drawBitmap(endImg, endImgX, endImgY, paint);

canvas.drawBitmap(noticeImg, noticeImgX, noticeImgY, paint);

/*
paint.setTextSize(26);
paint.setColor(Color.WHITE);
paint.getTextBounds(String.valueOf(bestScore), 0, String.valueOf(bestScore).length(), rect);
canvas.drawText(String.valueOf(bestScore), noticeImgX + noticeImg.getWidth() - rect.width(), noticeImgY + noticeImg.getHeight() - rect.height(), paint);
*/

drawScore(smallNumbersImg, smallScoreX, smallScoreY, score);

drawScore(smallNumbersImg, smallNumbersImgX, smallNumbersImgY, bestScore);

drawMedalImg();
} catch (Exception err) {
err.printStackTrace();
} finally {
if(canvas != null) {
sfh.unlockCanvasAndPost(canvas);
}
}
}

public void drawButton() {
try {
canvas = sfh.lockCanvas();

drawObject();

soundPlayer.playSound(5, 0);
canvas.drawBitmap(endImg, endImgX, endImgY, paint);

canvas.drawBitmap(noticeImg, noticeImgX, noticeImgY, paint);

drawScore(smallNumbersImg, smallScoreX, smallScoreY, score);

drawScore(smallNumbersImg, smallNumbersImgX, smallNumbersImgY, bestScore);

drawMedalImg();

canvas.drawBitmap(restartButtonImg, restartButtonImgX, restartButtonImgY, paint);
canvas.drawBitmap(exitButtonImg, exitButtonImgX, exitButtonImgY, paint);
} catch (Exception err) {
err.printStackTrace();
} finally {
if(canvas != null) {
sfh.unlockCanvasAndPost(canvas);
}
}
}

public void drawObject() {
canvas.save();
canvas.scale(scaleX, scaleY);
canvas.drawBitmap(bgImg, 0, 0, paint);
canvas.restore();
column1.drawSelf(canvas);
column2.drawSelf(canvas);
column3.drawSelf(canvas);
bird.drawSelf(canvas);
ground.drawSelf(canvas);
}

public void drawMedalImg() {
canvas.save();
canvas.clipRect(medalImgX, medalImgY, medalImgX + medalImg.getWidth(), medalImgY + medalImg.getHeight() / 2);
if(score >= 60) {
canvas.drawBitmap(medalImg, medalImgX, medalImgY - medalImg.getHeight() / 2, paint);
}
else {
canvas.drawBitmap(medalImg, medalImgX, medalImgY, paint);
}
canvas.restore();
}

public void drawScore(Bitmap numbersImg, float x, float y, int num) {
List<Integer> list = new ArrayList<Integer>();
int scoreCopy = num;
int quotient = 0;

while((quotient = scoreCopy / 10) != 0) {
list.add(scoreCopy % 10);
scoreCopy = quotient;
}
list.add(scoreCopy % 10);

float posX = x;
float posY = y;

int len = list.size();

float oddNumW = numbersImg.getWidth() / 10;
float oddNumH = numbersImg.getHeight();

posX -= len * oddNumW / 2;

canvas.save();
for(int i=len-1; i>=0; i--) {
switch(list.get(i)) {
case 0:
canvas.clipRect(posX, posY, posX + oddNumW, posY + oddNumH);
canvas.drawBitmap(numbersImg, posX - 0 * oddNumW, posY, paint);
posX += oddNumW;
canvas.restore();
canvas.save();
break;

case 1:
canvas.clipRect(posX, posY, posX + oddNumW, posY + oddNumH);
canvas.drawBitmap(numbersImg, posX - 1 * oddNumW, posY, paint);
posX += oddNumW;
canvas.restore();
canvas.save();
break;

case 2:
canvas.clipRect(posX, posY, posX + oddNumW, posY + oddNumH);
canvas.drawBitmap(numbersImg, posX - 2 * oddNumW, posY, paint);
posX += oddNumW;
canvas.restore();
canvas.save();
break;

case 3:
canvas.clipRect(posX, posY, posX + oddNumW, posY + oddNumH);
canvas.drawBitmap(numbersImg, posX - 3 * oddNumW, posY, paint);
posX += oddNumW;
canvas.restore();
canvas.save();
break;

case 4:
canvas.clipRect(posX, posY, posX + oddNumW, posY + oddNumH);
canvas.drawBitmap(numbersImg, posX - 4 * oddNumW, posY, paint);
posX += oddNumW;
canvas.restore();
canvas.save();
break;

case 5:
canvas.clipRect(posX, posY, posX + oddNumW, posY + oddNumH);
canvas.drawBitmap(numbersImg, posX - 5 * oddNumW, posY, paint);
posX += oddNumW;
canvas.restore();
canvas.save();
break;

case 6:
canvas.clipRect(posX, posY, posX + oddNumW, posY + oddNumH);
canvas.drawBitmap(numbersImg, posX - 6 * oddNumW, posY, paint);
posX += oddNumW;
canvas.restore();
canvas.save();
break;

case 7:
canvas.clipRect(posX, posY, posX + oddNumW, posY + oddNumH);
canvas.drawBitmap(numbersImg, posX - 7 * oddNumW, posY, paint);
posX += oddNumW;
canvas.restore();
canvas.save();
break;

case 8:
canvas.clipRect(posX, posY, posX + oddNumW, posY + oddNumH);
canvas.drawBitmap(numbersImg, posX - 8 * oddNumW, posY, paint);
posX += oddNumW;
canvas.restore();
canvas.save();
break;

case 9:
canvas.clipRect(posX, posY, posX + oddNumW, posY + oddNumH);
canvas.drawBitmap(numbersImg, posX - 9 * oddNumW, posY, paint);
posX += oddNumW;
canvas.restore();
canvas.save();
break;

}
}
canvas.restore();
}

// 响应触屏事件的方法
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN && event.getPointerCount() == 1) {
float x = event.getX();
float y = event.getY();

if(isWrite) {
if(x >= restartButtonImgX && x <= restartButtonImgX + restartButtonImg.getWidth() && y >= restartButtonImgY && y <= restartButtonImgY + restartButtonImg.getHeight()) {
mainActivity.getHandler().sendEmptyMessage(Config.TO_MAIN_VIEW);
}

if(x >= exitButtonImgX && x <= exitButtonImgX + exitButtonImg.getWidth() && y >= exitButtonImgY && y <= exitButtonImgY + exitButtonImg.getHeight()) {
mainActivity.getHandler().sendEmptyMessage(Config.END_GAME);
}
}

if(!isStart) {
isStart = true;
}
if(!isHit && !isOver) {
if(x <= pauseButtonImgX || x>= pauseButtonImgX + pauseButtonImg.getWidth() || y <= pauseButtonImgY || y>= pauseButtonImgY + pauseButtonImg.getHeight() / 2) {
bird.flappy();
soundPlayer.playSound(1, 0);
}
}

if(isStart && !isHit && !isOver) {
if(x >= pauseButtonImgX && x<= pauseButtonImgX + pauseButtonImg.getWidth() && y >= pauseButtonImgY && y<= pauseButtonImgY + pauseButtonImg.getHeight() / 2) {
isPause = !isPause;
if(isPause == false) {
synchronized(this.thread) {
thread.notify();
}
}
}
}

return true;
}
return false;
}

@Override
public void surfaceCreated(SurfaceHolder arg0) {
super.surfaceCreated(arg0);
initBitmap();
if(this.thread.isAlive()) {
this.thread.start();
} else {
this.thread = new Thread(this);
this.thread.start();
}
}

@Override
public void initBitmap() {
bgImg = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
startImg = BitmapFactory.decodeResource(getResources(), R.drawable.start);
endImg = BitmapFactory.decodeResource(getResources(), R.drawable.text_gameover);
restartButtonImg = BitmapFactory.decodeResource(getResources(), R.drawable.restartbutton);
exitButtonImg = BitmapFactory.decodeResource(getResources(), R.drawable.exitbutton);
noticeImg = BitmapFactory.decodeResource(getResources(), R.drawable.notice);
pauseButtonImg = BitmapFactory.decodeResource(getResources(), R.drawable.pausebutton);
bigNumbersImg = BitmapFactory.decodeResource(getResources(), R.drawable.bignumbers);
smallNumbersImg = BitmapFactory.decodeResource(getResources(), R.drawable.smallnumbers);
medalImg = BitmapFactory.decodeResource(getResources(), R.drawable.medal);

this.scaleX = Constants.SCREEN_WIDTH / bgImg.getWidth();
this.scaleY = Constants.SCREEN_HEIGHT / bgImg.getHeight();

startImgX = Constants.SCREEN_WIDTH / 2 - startImg.getWidth() / 2;
startImgY = Constants.SCREEN_HEIGHT / 2 - startImg.getHeight() / 2;
endImgX = Constants.SCREEN_WIDTH / 2 - endImg.getWidth() / 2;
endImgY = Constants.SCREEN_HEIGHT / 2 - endImg.getHeight() * 3;
noticeImgX = Constants.SCREEN_WIDTH / 2 - noticeImg.getWidth() / 2;
noticeImgY = Constants.SCREEN_HEIGHT / 2 - endImg.getHeight();
restartButtonImgX = Constants.SCREEN_WIDTH / 2 - restartButtonImg.getWidth() * 5 / 4;
restartButtonImgY = Constants.SCREEN_HEIGHT / 2 + noticeImg.getHeight();
exitButtonImgX = Constants.SCREEN_WIDTH / 2 + exitButtonImg.getWidth() / 4;
exitButtonImgY = Constants.SCREEN_HEIGHT / 2 + noticeImg.getHeight();
pauseButtonImgX = 0;
pauseButtonImgY = Constants.SCREEN_HEIGHT - pauseButtonImg.getHeight() / 2;
bigNumbersImgX = Constants.SCREEN_WIDTH / 2;
bigNumbersImgY = 10;
smallNumbersImgX = noticeImgX + noticeImg.getWidth() * 5 / 6;
smallNumbersImgY =noticeImgY + noticeImg.getHeight() - smallNumbersImg.getHeight() * 2;
smallScoreX = smallNumbersImgX;
smallScoreY = smallNumbersImgY - smallNumbersImg.getHeight() * 23 / 10;
medalImgX = noticeImgX + noticeImg.getWidth() / 8;
medalImgY = noticeImgY + noticeImg.getHeight() * 7 / 20;
}

@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
super.surfaceDestroyed(arg0);
release();
}

@Override
public void release() {
if(!bgImg.isRecycled()) {
bgImg.recycle();
}
if(!startImg.isRecycled()) {
startImg.recycle();
}
if(!endImg.isRecycled()) {
endImg.recycle();
}
if(!restartButtonImg.isRecycled()) {
restartButtonImg.recycle();
}
if(!exitButtonImg.isRecycled()) {
exitButtonImg.recycle();
}
if(!noticeImg.isRecycled()) {
noticeImg.recycle();
}
if(!pauseButtonImg.isRecycled()) {
pauseButtonImg.recycle();
}
if(!bigNumbersImg .isRecycled()) {
bigNumbersImg .recycle();
}
if(!smallNumbersImg .isRecycled()) {
smallNumbersImg .recycle();
}
if(!medalImg.isRecycled()) {
medalImg.recycle();
}
ground.release();
column1.release();
column2.release();
column3.release();
bird.release();
}

}


MainActivity类
package com.hitsz.xiaokai.flybird;

import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

import com.hitsz.xiaokai.flybird.config.Config;
import com.hitsz.xiaokai.flybird.util.SoundPlayer;
import com.hitsz.xiaokai.flybird.view.LoadingView;
import com.hitsz.xiaokai.flybird.view.MainView;

public class MainActivity extends Activity {

private LoadingView loadingView;//游戏载入窗口
private MainView mainView;//游戏主窗口

private SoundPlayer soundPlayer;//音乐播放器

private Handler handler = new Handler() {

public void handleMessage(Message msg) {
if(msg.what == Config.TO_MAIN_VIEW) {
toMainView();
}
if(msg.what == Config.END_GAME) {
endGame();
}
}

};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.soundPlayer = new SoundPlayer(this);
this.soundPlayer.initSounds();
this.loadingView = new LoadingView(this, soundPlayer);
this.setContentView(loadingView);
}

public void toMainView() {
if(this.mainView == null) {
this.mainView = new MainView(this, soundPlayer);
} else {
this.mainView = null;
this.mainView = new MainView(this, soundPlayer);
}
this.setContentView(this.mainView);
this.loadingView = null;
}

public void endGame() {
if(this.mainView != null) {
this.mainView.setThreadFlag(false);
}
if(this.loadingView != null) {
this.loadingView.setThreadFlag(false);
}
this.finish();
}

public Handler getHandler() {
return this.handler;
}
}


AndroidManife文件添加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

三、工程文件
github:点击打开链接(https://github.com/stephenxe/flybird)

启动界面

启动界面2

结束界面
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java Android