android 模拟物品移动
上次写了一个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.
对于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是否为空。
path这个方法控制着物体移动的速度,方向……
代码下载地址:点击打开链接
总结
以上是生活随笔为你收集整理的android 模拟物品移动的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 个体工商户国税2.0报税详解
- 下一篇: N1文件服务器,n1盒子搭建ftp服务器