上次写了一个android模拟下雪的demo。

基本是模拟出来雪花飘落的效果了,但是并没有达到真正的“下雪”。因为一次只产生了几朵雪花而已。于是想改进一下。

我原打算改进的方法是:

定义一个雪花类,继承runnable,只要在控制类里面启动,就让雪花自动飘落,当落到屏幕下方的时候,重新回到屏幕顶部,然后再次下落……

这样设计,是因为我原先做过一下SWT的游戏,让物品自己绘制自己,自己控制自己的生命周期,这应该是面向对象设计的第一反应……

但是遇到了问题,因为在android中,界面显示是靠View来控制的,如果让需要View把自己的canvas传递给雪花,这样还不如让所有的界面显示都交给VIEW来处理。

在不停的实验之后,发现我自己的设计,我没有走通……归结原因,还是自己对android 2D方面的东西不了解。于是网上下载一些资料学习

-----------------------------------分割线,一下内容来源互联网---------------------------------------------------------

android中涉及到显示的基本都要交给View处理,这里就不不得不提到两个类:android.view.View和android.view.SurfaceView。

SurfaceView 是从View基类中派生出来的显示类,直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及Camera摄像头一般均使用SurfaceView。

surfaceView 到底有哪些优势呢?

SurfaceView 可以控制表面的格式,比如大小,显示在屏幕中的位置,最关键是的提供了SurfaceHolder类,使用getHolder方法获取,相关的有

Canvas lockCanvas() ,Canvas lockCanvas(Rect dirty) 、void removeCallback(SurfaceHolder.Callback callback)、void unlockCanvasAndPost(Canvas canvas) 控制图形以及绘制,而在SurfaceHolder.Callback 接口回调中可以通过重写下面方法实现:

使用的SurfaceView的时候,一般情况下要对其进行创建,销毁,改变时的情况进行监视,这就要用到 SurfaceHolder.Callback.

class XxxView extends SurfaceView implements SurfaceHolder.Callback {public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}
//看其名知其义,在surface的大小发生改变时激发
public void surfaceCreated(SurfaceHolder holder){}
//同上,在创建时激发,一般在这里调用画图的线程。
public void surfaceDestroyed(SurfaceHolder holder) {}
//同上,销毁时激发,一般在这里将画图的线程停止、释放。}

对于Surface相关的,Android底层还提供了GPU加速功能,所以一般实时性很强的应用中主要使用SurfaceView而不是直接从View构建,同时后来做android 3d OpenGL中的GLSurfaceView也是从该类实现。

SurfaceView 和View 最本质的区别在于,surfaceView 是在一个新起的单独线程中可以重新绘制画面,而View必须在UI的主线程中更新画面。

那么在UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。 
当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。

所以基于以上,根据游戏特点,一般分成两类。

1 被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate。 因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。

2 主动更新。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。所以显然view不合适,需要surfaceView来控制。

3.Android中的SurfaceView类就是双缓冲机制。因此,开发游戏时尽量使用SurfaceView而不要使用View,这样的话效率较高,而且SurfaceView的功能也更加完善。

---------------------------------------------分割线---------------------------------------------

于是就写了一个简单的demo,让一个物体(我用的是一朵花),在屏幕中不停的移动。选择使用surfaceView

 @Overridepublic void surfaceCreated(SurfaceHolder holder) {SH = this.getHeight();SW = this.getWidth();th.start();}

这里我们重载,surfaceCrate方法,获得屏幕的高度和宽度,启动绘制线程……因为只有当执行surfaceCreate的时候,界面才真正绘制出来,如果在构造函数中获得屏幕的高度和宽度,就只能为0;

public void draw() {canvas = sfh.lockCanvas();if (canvas == null) {// 防止在按返回键的时候,报空指针异常return;}canvas.drawRect(0, 0, SW, SH, p); // 刷屏canvas.save();canvas.drawBitmap(bmp, bmp_x, bmp_y, p);Log.v("DEBUG", bmp_x + " |" + bmp_y + " | " + speed_x + " |" + speed_y);canvas.restore();sfh.unlockCanvasAndPost(canvas);}

这个方法会被线程不停的调用,让物体有移动的效果。其中

canvas.drawRect(0, 0, SW, SH, p); // 刷屏

负责清理上一次绘制留下的图片,让物体“动起来”。

为了防止当用户点击放回按钮的时候,线程仍在绘制,会报空指针异常,所以每次绘制前,要检查canvas是否为空。

 private void path() {if (bmp_x >= SW - 20) {speed_x += 1;if(speed_x>15){speed_x = 3;}speed_x = -speed_x;} else if (bmp_x <= 20) {speed_x -=1;if(speed_x<-15){speed_x = -3;}speed_x = -speed_x;}if (bmp_y >= SH - 20) {speed_y+=5;if(speed_y>15){speed_y = 3;}speed_y = -speed_y;} else if (bmp_y <= 10){speed_y -=5;if(speed_y<-15){speed_y = -3;}speed_y = -speed_y;}bmp_x += speed_x;bmp_y += speed_y;}

path这个方法控制着物体移动的速度,方向……

代码下载地址:点击打开链接

android 模拟物品移动相关推荐

  1. Android模拟器之神奇Genymotion的安装

    Android模拟器之神奇Genymotion的安装 经常有人问我,Android开发不适用真机的情况下,用什么模拟器比较好用!我这里推荐两款,一个是前两年开发时使用的"夜神模拟器" ...

  2. Android模拟神器Genymotion eclipse插件安装问题出解决

    Android模拟神器Genymotion eclipse插件安装问题出解决 参考文章: (1)Android模拟神器Genymotion eclipse插件安装问题出解决 (2)https://ww ...

  3. android 模拟电脑按键精灵,Android 模拟点击 按键精灵 ADB方案

    Android 模拟点击的方案 模拟MotionEvent ADB控制 Instrumentation 通过使用sendevent 这里我们只讨论ADB控制方案,因为这个方案可以点击本APP以外的东西 ...

  4. Android 模拟点击

    Android 模拟点击 前言 最近提出一个需求让做模拟点击,什么意思呢?就是有一个按钮,你点击这个按钮触发的不是按钮本身,而是其他的地方.其实就是在用户不触摸手机屏幕的时候,模拟触发手机屏幕的某个地 ...

  5. Android 模拟游戏手柄按键(跨进程 KeyEvent 事件)实践方案

    Android 模拟游戏手柄按键(跨进程 KeyEvent 事件)实践方案

  6. Android模拟请求调页-广工操作系统课设

    Android模拟请求调页-广工操作系统课设 GitHub地址 目录 Android模拟请求调页-广工操作系统课设 背景 架构 页面展示 下载体验 使用的开源库

  7. Android模拟登录教务处(带验证码)

    前言:我们学习过Android之后,总想写出一两个属于自己的应用,作为学生,可能我们最想尝试的就是实现一个Android版教务处,可以查成绩,学分,绩点,课表,还有学校新闻这样的app吧.下面我们开始 ...

  8. Android模拟服务端下发消息的Socket通讯工具

    Android模拟服务端下发消息的Socket通讯工具 1. 背景简介 背景简介: 有些场景需要依赖服务端下发消息到客户端,比如PowerMsg,服务端下发消息Type,客户端解析Type做出相应动作 ...

  9. android模拟M卡,Android模拟SD卡实现方法解析

    Android手机操作系统是一款开源的操作系统,许多编程爱好者们都需要在模拟器中对这一操作系统进行编写修改已满足自己的需求.在这里我们就来教给大家一个Android模拟SD的方法,帮助大家解决相关问题 ...

  10. Android模拟屏幕点击input tap替代解决方案

    动机解释 本来直接使用 adb shell -> input 即可模拟 键盘事件,触屏事件keyevent ,text,tap  但是手上的这台目标Android机4.0.3系统的input只支 ...

最新文章

  1. [javaSE] 网络编程(URLConnection)
  2. Bias vs. Variance(1)--diagnosing bias vs. variance
  3. 切点方法的事务参数的配置
  4. 一句话输出没有结束符的字符串
  5. c#关于int(或其他类型)的字段在对象初始化时默认初始化问题的解决方法
  6. jeecms 代码生成 Tools
  7. 批量更改图片文件的格式有什么方法?
  8. 15 JS运算符优先级
  9. mac测试电池软件,BattMan(Mac电池监测软件) V1.6 Mac版
  10. 好书、买书、看书---乐在其中
  11. ap mt7260a 华硕_带你入坑,用MT7620A带USB口的路由器搭建一个私有网盘
  12. WGCLOUD部署对服务器硬件配置的一些建议
  13. 可视化展示炫酷3D图表
  14. 运筹学基础【八】 之 图论方法
  15. Miniconda的安装与使用及pip在conda环境中的安装
  16. 电脑端滚动截屏工具FastStone Capture
  17. 在钉钉环境下打开测试网页
  18. Http--跨域请求
  19. 《腾讯数字生活报告2019》发布,互联网时代新马斯洛需求金字塔预示什么?
  20. 质量品质征文《质 量 是 一 种 态 度》

热门文章

  1. GCD中的dispatch_barrier_async函数的使用(栅栏函数)
  2. 计算机博士有哪些专业方向,国内计算机专业博士研究方向-20210619140356.docx-原创力文档...
  3. 战地5未能达到服务器带宽,《战地5》游戏bug汇总以及解决方案介绍
  4. C++的替代:微软如何使用rust?
  5. 用Java解决牛客网小米校招编程真题XM5句子反转
  6. 竟事而后言——谨记微言,聊以自省
  7. python可以excel_python能处理excel吗
  8. 偶的流氓老公zt (超搞笑-转)
  9. 【Unity3D-UGUI原理篇】(二)Canvas Scaler 缩放原理
  10. centos安装Docker与使用构建业务镜像挂载卷harbor仓库的高可用及网络模式和资源限制介绍...