android 模拟物品移动
上次寫了一個(gè)android模擬下雪的demo。
基本是模擬出來雪花飄落的效果了,但是并沒有達(dá)到真正的“下雪”。因?yàn)橐淮沃划a(chǎn)生了幾朵雪花而已。于是想改進(jìn)一下。
我原打算改進(jìn)的方法是:
? 定義一個(gè)雪花類,繼承runnable,只要在控制類里面啟動(dòng),就讓雪花自動(dòng)飄落,當(dāng)落到屏幕下方的時(shí)候,重新回到屏幕頂部,然后再次下落……
? 這樣設(shè)計(jì),是因?yàn)槲以茸鲞^一下SWT的游戲,讓物品自己繪制自己,自己控制自己的生命周期,這應(yīng)該是面向?qū)ο笤O(shè)計(jì)的第一反應(yīng)……
但是遇到了問題,因?yàn)樵赼ndroid中,界面顯示是靠View來控制的,如果讓需要View把自己的canvas傳遞給雪花,這樣還不如讓所有的界面顯示都交給VIEW來處理。
在不停的實(shí)驗(yàn)之后,發(fā)現(xiàn)我自己的設(shè)計(jì),我沒有走通……歸結(jié)原因,還是自己對android 2D方面的東西不了解。于是網(wǎng)上下載一些資料學(xué)習(xí)
-----------------------------------分割線,一下內(nèi)容來源互聯(lián)網(wǎng)---------------------------------------------------------
android中涉及到顯示的基本都要交給View處理,這里就不不得不提到兩個(gè)類:android.view.View和android.view.SurfaceView。
SurfaceView 是從View基類中派生出來的顯示類,直接子類有GLSurfaceView和VideoView,可以看出GL和視頻播放以及Camera攝像頭一般均使用SurfaceView。
surfaceView 到底有哪些優(yōu)勢呢?
?SurfaceView 可以控制表面的格式,比如大小,顯示在屏幕中的位置,最關(guān)鍵是的提供了SurfaceHolder類,使用getHolder方法獲取,相關(guān)的有
Canvas?lockCanvas()?,Canvas?lockCanvas(Rect?dirty)?、void?removeCallback(SurfaceHolder.Callback?callback)、void?unlockCanvasAndPost(Canvas?canvas)?控制圖形以及繪制,而在SurfaceHolder.Callback?接口回調(diào)中可以通過重寫下面方法實(shí)現(xiàn):
????????????? 使用的SurfaceView的時(shí)候,一般情況下要對其進(jìn)行創(chuàng)建,銷毀,改變時(shí)的情況進(jìn)行監(jiān)視,這就要用到?SurfaceHolder.Callback.?
對于Surface相關(guān)的,Android底層還提供了GPU加速功能,所以一般實(shí)時(shí)性很強(qiáng)的應(yīng)用中主要使用SurfaceView而不是直接從View構(gòu)建,同時(shí)后來做android?3d?OpenGL中的GLSurfaceView也是從該類實(shí)現(xiàn)。
SurfaceView 和View 最本質(zhì)的區(qū)別在于,surfaceView 是在一個(gè)新起的單獨(dú)線程中可以重新繪制畫面,而View必須在UI的主線程中更新畫面。?
那么在UI的主線程中更新畫面?可能會引發(fā)問題,比如你更新畫面的時(shí)間過長,那么你的主UI線程會被你正在畫的函數(shù)阻塞。那么將無法響應(yīng)按鍵,觸屏等消息。?
當(dāng)使用surfaceView?由于是在新的線程中更新畫面所以不會阻塞你的UI主線程。但這也帶來了另外一個(gè)問題,就是事件同步。比如你觸屏了一下,你需要surfaceView中thread處理,一般就需要有一個(gè)event?queue的設(shè)計(jì)來保存touch?event,這會稍稍復(fù)雜一點(diǎn),因?yàn)樯婕暗骄€程同步。
所以基于以上,根據(jù)游戲特點(diǎn),一般分成兩類。
1?被動(dòng)更新畫面的。比如棋類,這種用view就好了。因?yàn)楫嬅娴母率且蕾囉?onTouch?來更新,可以直接使用?invalidate。?因?yàn)檫@種情況下,這一次Touch和下一次的Touch需要的時(shí)間比較長些,不會產(chǎn)生影響。
2?主動(dòng)更新。比如一個(gè)人在一直跑動(dòng)。這就需要一個(gè)單獨(dú)的thread不停的重繪人的狀態(tài),避免阻塞main?UI?thread。所以顯然view不合適,需要surfaceView來控制。
3.Android中的SurfaceView類就是雙緩沖機(jī)制。因此,開發(fā)游戲時(shí)盡量使用SurfaceView而不要使用View,這樣的話效率較高,而且SurfaceView的功能也更加完善。
---------------------------------------------分割線---------------------------------------------
于是就寫了一個(gè)簡單的demo,讓一個(gè)物體(我用的是一朵花),在屏幕中不停的移動(dòng)。選擇使用surfaceView
@Overridepublic void surfaceCreated(SurfaceHolder holder) {SH = this.getHeight();SW = this.getWidth();th.start();}這里我們重載,surfaceCrate方法,獲得屏幕的高度和寬度,啟動(dòng)繪制線程……因?yàn)橹挥挟?dāng)執(zhí)行surfaceCreate的時(shí)候,界面才真正繪制出來,如果在構(gòu)造函數(shù)中獲得屏幕的高度和寬度,就只能為0;
public void draw() {canvas = sfh.lockCanvas();if (canvas == null) {// 防止在按返回鍵的時(shí)候,報(bào)空指針異常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);} 這個(gè)方法會被線程不停的調(diào)用,讓物體有移動(dòng)的效果。其中 canvas.drawRect(0, 0, SW, SH, p); // 刷屏負(fù)責(zé)清理上一次繪制留下的圖片,讓物體“動(dòng)起來”。
為了防止當(dāng)用戶點(diǎn)擊放回按鈕的時(shí)候,線程仍在繪制,會報(bào)空指針異常,所以每次繪制前,要檢查canvas是否為空。
path這個(gè)方法控制著物體移動(dòng)的速度,方向……
代碼下載地址:點(diǎn)擊打開鏈接
總結(jié)
以上是生活随笔為你收集整理的android 模拟物品移动的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 个体工商户国税2.0报税详解
- 下一篇: N1文件服务器,n1盒子搭建ftp服务器