分析

仔细观察游戏,需要绘制的有:背景、地板、鸟、管道、分数;

游戏开始时:

地板给人一种想左移动的感觉;

管道与地板同样的速度向左移动;

鸟默认下落;

当用户touch屏幕时,鸟上升一段距离后,下落;

运动过程中需要判断管道和鸟之间的位置关系,是否触碰,是否穿过等,需要计算分数。

好了,大概就这么多,那我们首先开始考虑绘制~~~

3、SurfaceView的一般写法

接下来,我们首先编写下SurfaceView的一般写法:

[java] view plaincopyprint?
  1. package com.zhy.view;
  2. import android.content.Context;
  3. import android.graphics.Canvas;
  4. import android.graphics.PixelFormat;
  5. import android.util.AttributeSet;
  6. import android.view.SurfaceHolder;
  7. import android.view.SurfaceHolder.Callback;
  8. import android.view.SurfaceView;
  9. public class GameFlabbyBird extends SurfaceView implements Callback, Runnable
  10. {
  11. private SurfaceHolder mHolder;
  12. /**
  13. * 与SurfaceHolder绑定的Canvas
  14. */
  15. private Canvas mCanvas;
  16. /**
  17. * 用于绘制的线程
  18. */
  19. private Thread t;
  20. /**
  21. * 线程的控制开关
  22. */
  23. private boolean isRunning;
  24. public GameFlabbyBird(Context context)
  25. {
  26. this(context, null);
  27. }
  28. public GameFlabbyBird(Context context, AttributeSet attrs)
  29. {
  30. super(context, attrs);
  31. mHolder = getHolder();
  32. mHolder.addCallback(this);
  33. setZOrderOnTop(true);// 设置画布 背景透明
  34. mHolder.setFormat(PixelFormat.TRANSLUCENT);
  35. // 设置可获得焦点
  36. setFocusable(true);
  37. setFocusableInTouchMode(true);
  38. // 设置常亮
  39. this.setKeepScreenOn(true);
  40. }
  41. @Override
  42. public void surfaceCreated(SurfaceHolder holder)
  43. {
  44. // 开启线程
  45. isRunning = true;
  46. t = new Thread(this);
  47. t.start();
  48. }
  49. @Override
  50. public void surfaceChanged(SurfaceHolder holder, int format, int width,
  51. int height)
  52. {
  53. // TODO Auto-generated method stub
  54. }
  55. @Override
  56. public void surfaceDestroyed(SurfaceHolder holder)
  57. {
  58. // 通知关闭线程
  59. isRunning = false;
  60. }
  61. @Override
  62. public void run()
  63. {
  64. while (isRunning)
  65. {
  66. long start = System.currentTimeMillis();
  67. draw();
  68. long end = System.currentTimeMillis();
  69. try
  70. {
  71. if (end - start < 50)
  72. {
  73. Thread.sleep(50 - (end - start));
  74. }
  75. } catch (InterruptedException e)
  76. {
  77. e.printStackTrace();
  78. }
  79. }
  80. }
  81. private void draw()
  82. {
  83. try
  84. {
  85. // 获得canvas
  86. mCanvas = mHolder.lockCanvas();
  87. if (mCanvas != null)
  88. {
  89. // drawSomething..
  90. }
  91. } catch (Exception e)
  92. {
  93. } finally
  94. {
  95. if (mCanvas != null)
  96. mHolder.unlockCanvasAndPost(mCanvas);
  97. }
  98. }
  99. }
package com.zhy.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class GameFlabbyBird extends SurfaceView implements Callback, Runnable
{
private SurfaceHolder mHolder;
/**
* 与SurfaceHolder绑定的Canvas
*/
private Canvas mCanvas;
/**
* 用于绘制的线程
*/
private Thread t;
/**
* 线程的控制开关
*/
private boolean isRunning;
public GameFlabbyBird(Context context)
{
this(context, null);
}
public GameFlabbyBird(Context context, AttributeSet attrs)
{
super(context, attrs);
mHolder = getHolder();
mHolder.addCallback(this);
setZOrderOnTop(true);// 设置画布 背景透明
mHolder.setFormat(PixelFormat.TRANSLUCENT);
// 设置可获得焦点
setFocusable(true);
setFocusableInTouchMode(true);
// 设置常亮
this.setKeepScreenOn(true);
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
// 开启线程
isRunning = true;
t = new Thread(this);
t.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
// TODO Auto-generated method stub
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
// 通知关闭线程
isRunning = false;
}
@Override
public void run()
{
while (isRunning)
{
long start = System.currentTimeMillis();
draw();
long end = System.currentTimeMillis();
try
{
if (end - start < 50)
{
Thread.sleep(50 - (end - start));
}
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
private void draw()
{
try
{
// 获得canvas
mCanvas = mHolder.lockCanvas();
if (mCanvas != null)
{
// drawSomething..
}
} catch (Exception e)
{
} finally
{
if (mCanvas != null)
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}

这个基础的类,在 Android SurfaceView实战 打造抽奖转盘已经出现过,就不多说了,大家以后写SurfaceView的相关程序,可以直接拷贝,在此类基础上编写。

4、绘制

1、绘制背景

最简单的当然是背景了,直接drawBitmap即可。

我们添加需要的成员变量,以及初始化一些参数,然后添加drawBg方法,最后在draw中调用drawBg;

[java] view plaincopyprint?
  1. public class CopyOfGameFlabbyBird extends SurfaceView implements Callback,
  2. Runnable
  3. {
  4. /**
  5. * 当前View的尺寸
  6. */
  7. private int mWidth;
  8. private int mHeight;
  9. private RectF mGamePanelRect = new RectF();
  10. /**
  11. * 背景
  12. */
  13. private Bitmap mBg;
  14. public CopyOfGameFlabbyBird(Context context, AttributeSet attrs)
  15. {
  16. //省略了很多代码
  17. initBitmaps();
  18. }
  19. /**
  20. * 初始化图片
  21. */
  22. private void initBitmaps()
  23. {
  24. mBg = loadImageByResId(R.drawable.bg1);
  25. }
  26. private void draw()
  27. {
  28. //省略了很多代码
  29. drawBg();
  30. //省略了很多代码
  31. }
  32. /**
  33. * 绘制背景
  34. */
  35. private void drawBg()
  36. {
  37. mCanvas.drawBitmap(mBg, null, mGamePanelRect, null);
  38. }
  39. /**
  40. * 初始化尺寸相关
  41. */
  42. @Override
  43. protected void onSizeChanged(int w, int h, int oldw, int oldh)
  44. {
  45. super.onSizeChanged(w, h, oldw, oldh);
  46. mWidth = w;
  47. mHeight = h;
  48. mGamePanelRect.set(0, 0, w, h);
  49. }
  50. /**
  51. * 根据resId加载图片
  52. *
  53. * @param resId
  54. * @return
  55. */
  56. private Bitmap loadImageByResId(int resId)
  57. {
  58. return BitmapFactory.decodeResource(getResources(), resId);
  59. }
  60. }
public class CopyOfGameFlabbyBird extends SurfaceView implements Callback,
Runnable
{
/**
* 当前View的尺寸
*/
private int mWidth;
private int mHeight;
private RectF mGamePanelRect = new RectF();
/**
* 背景
*/
private Bitmap mBg;
public CopyOfGameFlabbyBird(Context context, AttributeSet attrs)
{
//省略了很多代码
initBitmaps();
}
/**
* 初始化图片
*/
private void initBitmaps()
{
mBg = loadImageByResId(R.drawable.bg1);
}
private void draw()
{
//省略了很多代码
drawBg();
//省略了很多代码
}
/**
* 绘制背景
*/
private void drawBg()
{
mCanvas.drawBitmap(mBg, null, mGamePanelRect, null);
}
/**
* 初始化尺寸相关
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
mGamePanelRect.set(0, 0, w, h);
}
/**
* 根据resId加载图片
*
* @param resId
* @return
*/
private Bitmap loadImageByResId(int resId)
{
return BitmapFactory.decodeResource(getResources(), resId);
}
}

基本就是添加成员变量,然后初始化,然后绘制,上述代码经过删减,贴出的都是与前面基础代码不同的部分,大家可以将代码对号入座进行填充。

好了,现在背景图绘制好了,接下来,我们绘制小鸟~~~

2、绘制bird

鸟在我们的屏幕中,初始化时需要一个位置,x上,肯定是居中,y上我们取2/3的高度;

关于bird,我们单独创建一个类:

[java] view plaincopyprint?
  1. package com.zhy.view;
  2. import android.content.Context;
  3. import android.graphics.Bitmap;
  4. import android.graphics.Canvas;
  5. import android.graphics.RectF;
  6. public class Bird
  7. {
  8. /**
  9. * 鸟在屏幕高度的2/3位置
  10. */
  11. private static final float RADIO_POS_HEIGHT = 2 / 3F;
  12. /**
  13. * 鸟的宽度 30dp
  14. */
  15. private static final int BIRD_SIZE = 30;
  16. /**
  17. * 鸟的横坐标
  18. */
  19. private int x;
  20. /**
  21. * 鸟的纵坐标
  22. */
  23. private int y;
  24. /**
  25. * 鸟的宽度
  26. */
  27. private int mWidth;
  28. /**
  29. * 鸟的高度
  30. */
  31. private int mHeight;
  32. /**
  33. * 鸟的bitmap
  34. */
  35. private Bitmap bitmap;
  36. /**
  37. * 鸟绘制的范围
  38. */
  39. private RectF rect = new RectF();
  40. public Bird(Context context, int gameWith, int gameHeight, Bitmap bitmap)
  41. {
  42. this.bitmap = bitmap;
  43. //鸟的位置
  44. x = gameWith / 2 - bitmap.getWidth() / 2;
  45. y = (int) (gameHeight * RADIO_POS_HEIGHT);
  46. // 计算鸟的宽度和高度
  47. mWidth = Util.dp2px(context, BIRD_SIZE);
  48. mHeight = (int) (mWidth * 1.0f / bitmap.getWidth() * bitmap.getHeight());
  49. }
  50. /**
  51. * 绘制自己
  52. *
  53. * @param canvas
  54. */
  55. public void draw(Canvas canvas)
  56. {
  57. rect.set(x, y, x + mWidth, y + mHeight);
  58. canvas.drawBitmap(bitmap, null, rect, null);
  59. }
  60. public int getY()
  61. {
  62. return y;
  63. }
  64. public void setY(int y)
  65. {
  66. this.y = y;
  67. }
  68. public int getWidth()
  69. {
  70. return mWidth;
  71. }
  72. public int getHeight()
  73. {
  74. return mHeight;
  75. }
  76. }
package com.zhy.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.RectF;
public class Bird
{
/**
* 鸟在屏幕高度的2/3位置
*/
private static final float RADIO_POS_HEIGHT = 2 / 3F;
/**
* 鸟的宽度 30dp
*/
private static final int BIRD_SIZE = 30;
/**
* 鸟的横坐标
*/
private int x;
/**
* 鸟的纵坐标
*/
private int y;
/**
* 鸟的宽度
*/
private int mWidth;
/**
* 鸟的高度
*/
private int mHeight;
/**
* 鸟的bitmap
*/
private Bitmap bitmap;
/**
* 鸟绘制的范围
*/
private RectF rect = new RectF();
public Bird(Context context, int gameWith, int gameHeight, Bitmap bitmap)
{
this.bitmap = bitmap;
//鸟的位置
x = gameWith / 2 - bitmap.getWidth() / 2;
y = (int) (gameHeight * RADIO_POS_HEIGHT);
// 计算鸟的宽度和高度
mWidth = Util.dp2px(context, BIRD_SIZE);
mHeight = (int) (mWidth * 1.0f / bitmap.getWidth() * bitmap.getHeight());
}
/**
* 绘制自己
*
* @param canvas
*/
public void draw(Canvas canvas)
{
rect.set(x, y, x + mWidth, y + mHeight);
canvas.drawBitmap(bitmap, null, rect, null);
}
public int getY()
{
return y;
}
public void setY(int y)
{
this.y = y;
}
public int getWidth()
{
return mWidth;
}
public int getHeight()
{
return mHeight;
}
}

定义了一个类,代表我们的鸟,以及一堆成员变量,并且提供一个draw方法对外;

在GameFlabbyBird中,只需要,初始化我们的Bird,在draw里面调用bird.draw即可;

部分筛检后代码:

[java] view plaincopyprint?
  1. public class CopyOfGameFlabbyBird extends SurfaceView implements Callback,
  2. Runnable
  3. {
  4. /**
  5. * *********鸟相关**********************
  6. */
  7. private Bird mBird;
  8. private Bitmap mBirdBitmap;
  9. /**
  10. * 初始化图片
  11. */
  12. private void initBitmaps()
  13. {
  14. mBg = loadImageByResId(R.drawable.bg1);
  15. mBirdBitmap = loadImageByResId(R.drawable.b1);
  16. }
  17. private void draw()
  18. {
  19. // drawSomething..
  20. drawBg();
  21. drawBird();
  22. }
  23. private void drawBird()
  24. {
  25. mBird.draw(mCanvas);
  26. }
  27. /**
  28. * 初始化尺寸相关
  29. */
  30. @Override
  31. protected void onSizeChanged(int w, int h, int oldw, int oldh)
  32. {
  33. // 初始化mBird
  34. mBird = new Bird(getContext(), mWidth, mHeight, mBirdBitmap);
  35. }
  36. }
public class CopyOfGameFlabbyBird extends SurfaceView implements Callback,
Runnable
{
/**
* *********鸟相关**********************
*/
private Bird mBird;
private Bitmap mBirdBitmap;
/**
* 初始化图片
*/
private void initBitmaps()
{
mBg = loadImageByResId(R.drawable.bg1);
mBirdBitmap = loadImageByResId(R.drawable.b1);
}
private void draw()
{
// drawSomething..
drawBg();
drawBird();
}
private void drawBird()
{
mBird.draw(mCanvas);
}
/**
* 初始化尺寸相关
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
// 初始化mBird
mBird = new Bird(getContext(), mWidth, mHeight, mBirdBitmap);
}
}

是不是很简单,下面看下此时效果图:

Activity里面这么调用即可:

[java] view plaincopyprint?
  1. package com.zhy.surfaceViewDemo;
  2. import com.zhy.view.GameFlabbyBird;
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.view.Window;
  6. import android.view.WindowManager;
  7. public class MainActivity extends Activity
  8. {
  9. GameFlabbyBird mGame;
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState)
  12. {
  13. super.onCreate(savedInstanceState);
  14. getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  15. WindowManager.LayoutParams.FLAG_FULLSCREEN);
  16. requestWindowFeature(Window.FEATURE_NO_TITLE);
  17. mGame = new GameFlabbyBird(this);
  18. setContentView(mGame);
  19. }
  20. }
package com.zhy.surfaceViewDemo;
import com.zhy.view.GameFlabbyBird;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class MainActivity extends Activity
{
GameFlabbyBird mGame;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
mGame = new GameFlabbyBird(this);
setContentView(mGame);
}
}

不管咋样,我们的鸟已经在指定的位置了~~~有木有一点小激动~~

下面开始添加地板;

3、绘制地板

绘制地板相比来说会难一点,因为我们需要考虑怎么让地板运动,起初我截取了两个大图,希望通过两张图不断变化,产生动画效果,but,动画的太卡,有跳跃感;

于是,我忽然想到了一个东西可以做,我就把基础图变成了这样:

很小的一块图,先不考虑运动,如何填充成我们目标效果呢?

还记得有个类叫做BitmapShader么?我们可以利用它进行填充。

相关知识可以参考:Android BitmapShader 实战 实现圆形、圆角图片

首先我们依旧是定义一个地板类:Floor

Android SurfaceView实战 带你玩转flabby bird相关推荐

  1. Android SurfaceView实战 带你玩转flabby bird (下)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43063331,本文出自:[张鸿洋的博客] 1.概述 在Android Surfa ...

  2. Android SurfaceView实战 带你玩转flabby bird (上)

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 转载请标 ...

  3. Android SurfaceView实战 带你玩切水果1.0

    1.概述 最近开发一个智能项目,项目对象是某智能早教机器人,这个产品主要定位是儿童益智玩的游戏,并且可以从中学习到相关历史知识等相关知识,其中有个游戏关卡就是去到不同国家,可以玩不同的游戏.领导说要用 ...

  4. 详解与重构hyman《Android SurfaceView实战 打造抽奖转盘》

    详解与重构hyman<Android SurfaceView实战 打造抽奖转盘> 作者:邵励治 一.概述--关于SurfaceView您不得不知道的二三事 1.SurfaceView是干什 ...

  5. Android SurfaceView实战 打造抽奖转盘

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41722441 ,本文出自:[张鸿洋的博客] 1.概述 今天给大家带来Surfac ...

  6. 12个真实项目实战带你玩转Java并发编程

    这篇博客,我会总结如下内容,满满的干货,篇幅可能会很长,做好心理准备 Immutable Object:不可变对象模式:在不引入锁的条件下,能保证访问共享变量时是线程安全的,缺点是会频繁的创建变量. ...

  7. 超详细SVG实战——徒手画pipeline,带你玩转SVG

    记录个 svg 实战应用-最近断断续续在搞公司的前端发布平台,本想搞 pipeline ,结果先给 svg 给拦下了.基于发布平台没有同时多项目发布的能力,so-笔者决定搞个 pipeline 把 j ...

  8. Android SurfaceView使用详解(很好的实战例子)

    一.surfaceview  在显示时才会调用callback中的surfaceCreated.注意,是在显示时,在初始化时不会调用 在隐藏时会调用callback中的surfaceDestroyed ...

  9. 独家直播双十一全网动态?前黑客“劳改”带你玩转大数据

    独家直播双十一全网动态?前黑客"劳改"带你玩转大数据 发表于2015-11-24 10:26| 4044次阅读| 来源CSDN| 7 条评论| 作者蒲婧 CTO俱乐部CTOCTO讲 ...

最新文章

  1. ArcGIS Engine10.4版本
  2. 365篇原创后,有三AI喊你正式加入来不来?
  3. 阿里巴巴发送短信接口的使用
  4. android 里程,鹰眼Android SDK | 百度地图API SDK
  5. Python三:面向对象 之 类的封装
  6. SAP BASIS 工作台请求和定制请求的区别
  7. 深入JVM-性能监控工具
  8. 架构师必备之最全最系统的 Android 界面性能调优资料
  9. 计算机c语言程序设计题,《计算机C语言程序设计》模拟题集.doc
  10. 第5课 混合编程和芯片手册阅读
  11. Android零基础入门第42节:自定义BaseAdapter
  12. oracle学习笔记 学习前奏
  13. dosbox运行C语言,DosBox的基本设置和安装
  14. 移动固态硬盘(PSSD)怎么用?WTG随时随地封装系统
  15. c语言简单计算器减编程,C语言实现简单的计算器(加、减、乘、除)
  16. C#自制坦克大战小游戏
  17. 转行测试,11k入职,我写了份1000多字的分享,每一笔都是经历
  18. 小心! Java三目运算符
  19. JavaWeb--用户注册登录案例
  20. C语言的system函数

热门文章

  1. 不小心执行了 rm -f,先别急着跑路 (内附彩蛋)!
  2. Android 4.2 禁止下拉状态栏
  3. 安装配置远程jupyter notebook(原ipython notebook)
  4. 解决电脑开机图标变成白色的问题
  5. opencv-python 指静脉的ROI获取(拟合手指中线加旋转)
  6. 无子女无遗嘱,去世后名下房产该归谁
  7. wps数据库三线表怎么做_WPS文档三线表怎么做?
  8. Thinkpad win11截图快捷键win + sihft +s无反应
  9. Android databinding之数据单向与双向绑定详解与使用(三)
  10. 服务器跨站脚本漏洞修复,如何修复XSS跨站脚本漏洞?