日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

《Android 应用案例开发大全(第二版)》——2.4节壁纸的实现

發(fā)布時間:2024/3/26 Android 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Android 应用案例开发大全(第二版)》——2.4节壁纸的实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本節(jié)書摘來自異步社區(qū)《Android 應(yīng)用案例開發(fā)大全(第二版)》一書中的第2章,第2.4節(jié)壁紙的實(shí)現(xiàn),作者 吳亞峰 , 于復(fù)興 , 杜化美,更多章節(jié)內(nèi)容可以訪問云棲社區(qū)“異步社區(qū)”公眾號查看

2.4 壁紙的實(shí)現(xiàn)
Android 應(yīng)用案例開發(fā)大全(第二版)
上一節(jié)介紹了壁紙的框架,讓讀者對壁紙的整體框架有了初步認(rèn)識,本節(jié)將要對壁紙實(shí)現(xiàn)服務(wù)類GLWallpaperService、動態(tài)壁紙類LiveWallpaper、自定義渲染器類TDRender的開發(fā)進(jìn)行詳細(xì)介紹。

2.4.1 壁紙服務(wù)類——GLWallpaperService
該類是本項(xiàng)目中最基礎(chǔ)的一個類,沒有這個類就不可能使用壁紙這個功能。這個類為開發(fā)人員提供了壁紙服務(wù),開發(fā)人員可以通過繼承該類,重寫此類中的方法來實(shí)現(xiàn)壁紙的后續(xù)開發(fā)。本小節(jié)只對該類中的兩個地方進(jìn)行介紹,一個是setRender方法,另一個是觸控的響應(yīng)事件onTouchEvent。

(1)首先對setRender方法進(jìn)行介紹,具體代碼如下所示。

1 public void setRenderer(Renderer renderer) { 2 checkRenderThreadState(); // 檢查線程是否啟動 3 if (mEGLConfigChooser == null) { // 創(chuàng)建EGLConfigChooser 4 mEGLConfigChooser = new SimpleEGLConfigChooser(true); 5 } 6 if (mEGLContextFactory == null) { // 創(chuàng)建EGLContextFactory 7 mEGLContextFactory = new DefaultContextFactory(); 8 } 9 if (mEGLWindowSurfaceFactory == null) { // 創(chuàng)建EGLWindowSurfaceFactory 10 mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); 11 } 12 mGLThread = new GLThread(renderer, mEGLConfigChooser, 13 mEGLContextFactory, mEGLWindowSurfaceFactory, mGLWrapper); 14 mGLThread.start(); // 啟動線程 15 this.renderer=(TDRender) renderer; // 設(shè)置渲染器 16 }

第2~8行為檢查渲染器線程是否啟動,然后判斷是否已經(jīng)創(chuàng)建了EGLConfigChooser對象,如果沒有則創(chuàng)建,再判斷是否已創(chuàng)建EGLContextFactory對象,同樣如果沒有則創(chuàng)建。
第9~16行先判斷是否已經(jīng)創(chuàng)建了EGLWindowSurfaceFactory對象,如果沒有則創(chuàng)建。然后啟動渲染線程,再將渲染器設(shè)置為自定義的渲染器。
(2)下面將對屏幕觸控的相應(yīng)事件進(jìn)行介紹,屏幕的觸控事件分為3部分:第一部分是滑動屏幕使背景圖跟著屏幕移動,第二部分是點(diǎn)擊屏幕下方修改標(biāo)志位,最后一部分是手指抬起時判斷是否進(jìn)行喂食,具體代碼如下所示。

1 private float mPreviousX; // 上次的觸控位置_y_坐標(biāo) 2 private TDRender renderer; // 場景渲染器 3 @Override 4 public void onTouchEvent(MotionEvent e) { 5 float y = e.getY(); // 獲得觸控點(diǎn)的_y_坐標(biāo) 6 float x = e.getX(); // 獲得觸控點(diǎn)的_x_坐標(biāo) 7 switch (e.getAction()) { 8 case MotionEvent.ACTION_DOWN: 9 Constant.feeding = true; // 將喂食標(biāo)志位設(shè)為true 10 break; 11 case MotionEvent.ACTION_MOVE: 12 float dy = y - mPreviousY; // 計(jì)算觸控筆_y_位移 13 float dx = x - mPreviousX; // 計(jì)算觸控筆_y_位移 14 if (dx < 0){ // 觸摸左邊_x_為正,觸摸右邊_x_為負(fù) 15 if (Constant.CameraX < Constant.MaxCameraMove) {// 攝像機(jī)移動最大值 16 if(dx<- Constant.Thold){ 17 Constant.feeding = false; // 喂食標(biāo)志位 18 } 19 Constant.CameraX = Constant.cameraX - dx / Constant.Camera ove_SCALE ; 20 Constant.TargetX=Constant.CameraX; 21 }} else { 22 if (Constant.CameraX < -Constant.MaxCameraMove {// 攝像機(jī)移動最大值 23 if(dx> Constant.Thold){ 24 Constant.feeding = false; // 喂食標(biāo)志位 25 } 26 Constant.CmeraX = Constant.CameraX - dx / Constant.CameraMove _SCALE ; 27 Constant.TargetX=Constant.CameraX; 28 }} 29 MatrixUtil.setCamera ( // 將攝像機(jī)的位置信息存入到矩陣中 30 Constant.CameraX, // 攝像機(jī)_x_位置 31 Constant.CameraY, // 攝像機(jī)_y_位置 32 Constant.CameraZ, // 攝像機(jī)_y_位置 33 Constant.TargetX, // 觀測點(diǎn)的_x_位置 34 Constant.TargetY, // 觀測點(diǎn)的_y_位置 35 Constant.TargetZ, // 觀測點(diǎn)的_z_位置 36 Constant.UpX, // UP向量的x分量 37 Constant.UpY, // UP向量的y分量 38 Constant.UpZ); // UP向量的z分量 39 break; 40 case MotionEvent.ACTION_UP: 41 if (Constant.feeding) { // 標(biāo)志位,如果開始喂食 42 if (Constant.isFeed) { 43 Constant.isFeed = false; // 把標(biāo)志位置為false 44 Vector3f[]AB=IntersectantUtil 45 .calculateABPosition( // 通過變換獲得世界坐標(biāo)系中的點(diǎn) 46 x, // 觸控點(diǎn)_x_坐標(biāo) 47 y, // 觸控點(diǎn)_y_坐標(biāo) 48 Constant.SCREEN_WIDTH,// 屏幕寬度 49 Constant.SCREEN_HEGHT, // 屏幕長度 50 Constant.leftABS, // 視角left絕對值 51 Constant.topABS, // 視角top絕對值 52 Constant.nearABS, // 視角near值 53 Constant.farABS); // 視角far值 54 Vector3f Start = AB[0]; // 獲得拾取后世界坐標(biāo)系中被觸控到的近平面的點(diǎn) 55 Vector3f End = AB[1];// 獲得拾取后世界坐標(biāo)系中被觸控到的遠(yuǎn)平面的點(diǎn) 56 if (renderer.feedFish != null) { // 判斷不為空,則開始喂食 57 renderer.feedFish.startFeed(Start, End); // 開始喂食 58 }}} 59 requestRender(); // 重繪畫面 60 break; 61 } 62 mPreviousX = x; // 記錄觸控筆位置 63 super.onTouchEvent(e); 64 }}

第1~10行定義上次觸控點(diǎn)的x、y坐標(biāo),創(chuàng)建渲染器對象,獲得觸控點(diǎn)的x坐標(biāo)和y坐標(biāo),對ACTION_DOWN事件進(jìn)行監(jiān)聽,當(dāng)觸發(fā)時將喂食標(biāo)志位設(shè)為true。
第11~21行獲得手指在屏幕上的觸控點(diǎn),從而得到手指在屏幕上的移動距離,然后按照一定比例移動攝像機(jī)x坐標(biāo),同時,如果攝像機(jī)x坐標(biāo)達(dá)到閾值,則攝像機(jī)不會向滑動方向移動。
第22~32行將攝像機(jī)的位置信息存入到矩陣中,設(shè)置攝像機(jī)位置的坐標(biāo)、觀測點(diǎn)的坐標(biāo)和up向量,最后再次記錄觸控筆的x、y位置。
第33~46行為判斷喂食的標(biāo)志位,喂食有兩個標(biāo)志位,一個是在點(diǎn)擊喂食的時候?yàn)閠rue,另一個是在沒有喂食之前為true,因?yàn)榛瑒悠聊徊荒芪故?#xff0c;當(dāng)前喂的食物在沒有消失之前也不能喂食,所以,用了兩個標(biāo)志位對其進(jìn)行控制。然后通過矩陣變化獲取觸控點(diǎn)的世界坐標(biāo)系坐標(biāo)。
第47~57行通過拾取計(jì)算得到觸控點(diǎn)在世界坐標(biāo)系中的起點(diǎn)(近平面點(diǎn))、終點(diǎn)(遠(yuǎn)平面點(diǎn))坐標(biāo),并且開始進(jìn)行喂食。然后重繪畫面,記錄觸控筆的位置,回調(diào)父類的方法。

2.4.2 動態(tài)壁紙類——LiveWallpaper
只有壁紙的服務(wù)類還遠(yuǎn)遠(yuǎn)不夠,還要新建一個類繼承自壁紙服務(wù)類,然后重寫壁紙服務(wù)類的onCreateEngine方法才行,具體代碼如下所示。

1 package com.bn.ld.wallpaper; 2 import com.bn.gl.GLWallpaperService; 3 public class LiveWallpaper extends GLWallpaperService{ 4 private TDRender renderer; // 場景渲染器 5 @Override 6 public Engine onCreateEngine() { // 重寫onCreateEngine方法 7 renderer=new TDRender(this); 8 return new GLEngine() { { 9 setRenderer(renderer); // 設(shè)置渲染器 10 setRenderMode(RENDERMODE_CONTINUOUSLY); // 設(shè)置主動渲染 11 }};}}

說明
定義渲染器類,繼承自GLWallpaperService類 ,創(chuàng)建私有的場景渲染器對象。然后重寫onCreateEngine方法,將渲染器設(shè)置為自定義的渲染器,并且把渲染器的渲染模式設(shè)置為主動渲染。

2.4.3 自定義渲染器類——TDRender
下面將介紹自定義的渲染器代碼,在自定義的渲染器類里,可以進(jìn)行魚、魚群、氣泡、水草、背景圖、石頭、魚食的繪制和初始化紋理等。

(1)由于該類中繪制代碼比較多,在此就先介紹整個渲染器的框架,具體代碼如下所示。

1 package com.bn.ld.wallpaper; 2 ……//此處省略部分類和包的引入代碼,讀者可自行查閱光盤的源代碼 3 public class TDRender extends GLSurfaceView implements GLSurfaceView.Renderer, 4 GLWallpaperService.Renderer { 5 public TDRender(Context context) { 6 super(context); // 獲得上下文對象 7 } 8 ……//此處省略相關(guān)成員變量的聲明代碼,讀者可自行查閱光盤的源代碼 9 public void onDrawFrame(GL10 gl) { 10 gl.glEnable(GL10.GL_CULL_FACE); // 設(shè)置為打開背面剪裁 11 gl.glShadeModel(GL10.GL_SMOOTH); // 設(shè)置著色模型為平滑著色 12 gl.glFrontFace(GL10.GL_CCW); // 設(shè)置為默認(rèn)卷繞順序逆時針 13 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | 14 GL10.GL_DEPTH_BUFFER_BIT); // 清除緩存 15 gl.glMatrixMode(GL10.GL_MODELVIEW); // 設(shè)置當(dāng)前矩陣為模式矩陣 16 gl.glLoadIdentity(); // 設(shè)置當(dāng)前矩陣為單位矩陣 17 GLU.gluLookAt( // 設(shè)置攝像機(jī) 18 gl, 19 Constant.CameraX, // 攝像機(jī)_x_位置 20 Constant.CameraY, // 攝像機(jī)_y_位置 21 Constant.CameraZ, // 攝像機(jī)_z_位置 22 Constant.TargetX, // 觀測點(diǎn)的_x_位置 23 Constant.TargetY, // 觀測點(diǎn)的_y_位置 24 Constant.TargetZ, // 觀測點(diǎn)的_z_位置 25 Constant.UpX, // UP向量x分量 26 Constant.UpY, // UP向量y分量 27 Constant.UpZ); // UP向量z分量 28 ……此處代碼是繪制代碼,將在后面給出 29 } 30 public void onSurfaceChanged(GL10 gl, int width, int height) { 31 gl.glViewport(0, 0, width, height); // 設(shè)置視窗大小及位置 32 gl.glMatrixMode(GL10.GL_PROJECTION); // 設(shè)置當(dāng)前矩陣為投影矩陣 33 gl.glLoadIdentity(); // 設(shè)置當(dāng)前矩陣為單位矩陣 34 float ratio = (float) width / height; // 計(jì)算透視投影的比例 35 Constant.SCREEN_HEGHT=height; // 獲取手機(jī)的高 36 Constant.SCREEN_WIDTH=width; // 獲取手機(jī)的寬 37 Constant.leftABS=ratio*Constant.View_SCALE; // 透視投影的left絕對值 38 Constant.topABS=1 * Constant.View_SCALE; // 透視投影的top絕對 39 Constant.SCREEN_SCALEX=Constant.View_SCALE*((ratio>1)?ratio:(1/ratio)); 40 gl.glFrustumf(-Constant.leftABS, Constant.leftABS, -Constant.topABS, // 產(chǎn)生透視投影矩陣 41 Constant.topABS, Constant.nearABS,Constant.farABS); 42 MatrixUtil.setCamera ( // 將攝像機(jī)的位置信息存入到矩陣中 43 Constant.CameraX, // 攝像機(jī)_x_位置 44 Constant.CameraY, // 攝像機(jī)_y_位置 45 Constant.CameraZ, // 攝像機(jī)_z_位置 46 Constant.TargetX, // 觀測點(diǎn)的_x_位置 47 Constant.TargetY, // 觀測點(diǎn)的_y_位置 48 Constant.TargetZ, // 觀測點(diǎn)的_z_位置 49 Constant.UpX, // UP向量的x分量 50 Constant.UpY, // UP向量的y分量 51 Constant.UpZ); // UP向量的z分量 52 if (backgrounds == null) { 53 backgrounds = new BackGround(); // 初始化背景圖 54 }} 55 public void onSurfaceCreated(GL10 gl, EGLConfig config) { 56 gl.glDisable(GL10.GL_DITHER); // 關(guān)閉抗抖動 57 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, 58 GL10.GL_FASTEST); // 快速模式 59 gl.glClearColor(0, 0, 0, 0); // 設(shè)置屏幕背景色黑色RGBA 60 gl.glEnable(GL10.GL_DEPTH_TEST); // 啟用深度測試 61 gl.glEnable(GL10.GL_CULL_FACE); // 設(shè)置為打開背面剪裁 62 ……此處代碼是加載圖片、OBJ文件、創(chuàng)建各種對象,將在后面介紹 63 }}

第1~8行為部分類和包的引入代碼、相關(guān)成員變量的聲明,這些代碼在此處省略,讀者可自行查閱光盤代碼。創(chuàng)建構(gòu)造器并獲得上下文對象。
第9~29行為進(jìn)行繪制時的各種設(shè)置,如打開背面剪裁、設(shè)置平滑著色、設(shè)置默認(rèn)卷繞方式、設(shè)置模式矩陣和單位矩陣,最后設(shè)置攝像機(jī)位置,初始化背景圖對象。
第30~54行重寫onSurfaceChanged方法設(shè)置視口的大小,將當(dāng)前矩陣設(shè)為投影矩陣、設(shè)置單位矩陣、產(chǎn)生透視投影矩陣、并且生成攝像機(jī)觀察矩陣。
第55~63行重寫onSurfaceCreated方法。關(guān)閉抗抖動、設(shè)置Hint模式為快速模式、設(shè)置屏幕背景顏色、啟用深度檢測、打開背面剪裁。
(2)下面開始對本案例中魚類、氣泡、魚食、石頭等對象的創(chuàng)建以及本案例中用到的紋理ID的初始化進(jìn)行詳細(xì)介紹,具體代碼如下所示。

1 public void onSurfaceCreated(GL10 gl, EGLConfig config) { 2 gl.glDisable(GL10.GL_DITHER); // 關(guān)閉抗抖動 3 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, 4 GL10.GL_FASTEST); // 快速模式 5 gl.glClearColor(0, 0, 0, 0); // 設(shè)置屏幕背景色 6 gl.glEnable(GL10.GL_DEPTH_TEST); // 啟用深度測試 7 gl.glEnable(GL10.GL_CULL_FACE); 8 if (fishAl.size() == 0) { 9 bubbles = initTexture(gl, "bubble.png"); // 氣泡的紋理ID 10 fish0 = initTexture(gl, "fish0.png"); // 魚的紋理ID 11 fish1 = initTexture(gl, "fish1.png"); 12 fish2 = initTexture(gl, "fish2.png"); 13 fish3 = initTexture(gl, "fish3.png"); 14 fish4 = initTexture(gl, "fish4.png"); 15 fish5 = initTexture(gl, "fish5.png"); 16 fishfood = initTexture(gl, "fishfood.png"); // 魚食的紋理ID 17 waterweeds = initTexture(gl, "waterweeds.png");// 水草的紋理ID 18 background = initTexture(gl, "background.png");// 背景的紋理ID 19 stone=initTexture(gl, "stone.png"); // 石頭的紋理 20 fishAl.add(new SingleFish(fish1, TDRender.this, "fish1.obj", // 將單個魚加入魚類列表 21 new Vector3f(-1, 2, 0), // 初始位置 22 new Vector3f(-0.02f, -0.02f, 0.00f), new Vector3f(0, 0, 0), // 初始速度和外力 23 new Vector3f(0, 0, 0), 70)); // 初始吸引力和魚的質(zhì)量 24 fishAl.add(new SingleFish(fish0, TDRender.this, "fish0.obj", 25 new Vector3f(-7, 5, 0), // 初始位置 26 new Vector3f(-0.04f, 0.01f, -0.04f),new Vector3f(0, 0, 0), // 初始速度和外力 27 new Vector3f(0, 0, 0), 150)); // 初始吸引力和魚的質(zhì)量 28 fishAl.add(new SingleFish(fish2, TDRender.this, "fish2.obj", 29 new Vector3f(-0, 3, 0), // 初始位置 30 new Vector3f(0.02f, 0.01f, -0.01f),new Vector3f(0, 0, 0), // 初始速度和外力 31 new Vector3f(0, 0, 0), 70)); // 初始吸引力和魚的質(zhì)量 32 fishAl.add(new SingleFish(fish4, TDRender.this, "fish4.obj", 33 new Vector3f(-1, 0, 0), // 初始位置 34 new Vector3f(-0.03f, 0.02f, -0.02f), new Vector3f(0, 0, 0), // 初始速度和外力 35 new Vector3f(0, 0, 0), 90)); // 初始吸引力和魚的質(zhì)量 36 fishAl.add(new SingleFish(fish4, TDRender.this, "fish4.obj", 37 new Vector3f(-5, 0, 0), // 初始位置 38 new Vector3f(-0.02f, 0.03f, -0.02f), new Vector3f(0, 0, 0), // 初始速度和外力 39 new Vector3f(0, 0, 0), 50)); // 初始吸引力和魚的質(zhì)量 40 fishAl.add(new SingleFish(fish4, TDRender.this, "fish4.obj", 41 new Vector3f(-5, 3, 0), // 初始位置 42 new Vector3f(-0.01f, 0.02f, -0.04f), new Vector3f(0, 0, 0), // 初始速度和外力 43 new Vector3f(0, 0, 0), 60)); // 初始吸引力和魚的質(zhì)量 44 fishAl.add(new SingleFish(fish5, TDRender.this, "fish5.obj", 45 new Vector3f(1, -3, 0), // 初始位置 46 new Vector3f(0.03f, 0.01f, -0.03f),new Vector3f(0, 0, 0f), // 初始速度和外力 47 new Vector3f(0, 0, 0), 80)); // 初始吸引力和魚的質(zhì)量 48 fishAl.add(new SingleFish(fish5, TDRender.this, "fish5.obj", 49 new Vector3f(-4, -1, 0), // 初始位置 50 new Vector3f(0.045f, 0.02f, -0.05f),new Vector3f(0, 0, 0f), // 初始速度和外力 51 new Vector3f(0, 0, 0), 40)); // 初始吸引力和魚的質(zhì)量 52 } 53 if (waterweeds1 == null) { // 創(chuàng)建水草類對象 54 waterweeds1 = LoadUtil.loadFromFileVertexOnly("waterweeds.obj", 55 this.getResources()); // 加載水草模型 56 } 57 if(stones==null){ // 創(chuàng)建石頭類對象 58 stones=LoadUtil.loadFromFileVertexOnly("stone.obj", 59 this.getResources()); // 加載石頭模型 60 } 61 if (fishfoods == null) { // 創(chuàng)建魚食對象 62 fishfoods = LoadUtil.loadFromFileVertexOnly("fishfood.obj", 63 this.getResources()); // 加載魚食模型 64 } 65 if (bubbleControl == null) { // 創(chuàng)建氣泡的Control對象 66 bubbleControl = new BubbleControl(bubbles); 67 } 68 if (fishControl == null) { // 創(chuàng)建魚類的Control對象 69 fishControl = new FishControl(fishAl, TDRender.this); 70 } 71 if (fishSchool == null) { // 創(chuàng)建魚群的Control 72 fishSchool = new FishSchoolControl(fish3, TDRender.this); 73 } 74 if (singleFood == null) { // 食物類 75 singleFood = new FeedFish(fishfoods, TDRender.this); 76 } 77 if (feedFish == null) { // 創(chuàng)建控制喂食的對象 78 feedFish = new SingleFood(TDRender.this); 79 }}

第2~7行為關(guān)閉抗抖動,將Hint的模式設(shè)置為快速模式,設(shè)置屏幕背景顏色為黑色,啟用深度檢測,打開背面剪裁。
第8~52行獲得圖片的紋理ID ,對單個魚進(jìn)行初始化設(shè)置魚的初始位置、初始速度、受到的外力和吸引力,以及魚的質(zhì)量(力的縮放比)。
第53~79行創(chuàng)建背景圖、水草、石頭、氣泡、魚食、群魚、魚群對象。并且只有當(dāng)這些對象為空的時候才會對這些對象進(jìn)行實(shí)例化。
(3)下面開始對3D水族館動態(tài)壁紙案例中各個對象的繪制進(jìn)行介紹,繪制代碼在onDrawFrame方法中,具體代碼如下所示。

1 public void onDrawFrame(GL10 gl) { 2 gl.glEnable(GL10.GL_CULL_FACE); // 設(shè)置為打開背面剪裁 3 gl.glShadeModel(GL10.GL_SMOOTH); // 設(shè)置著色模型為平滑著色 4 gl.glFrontFace(GL10.GL_CCW); // 設(shè)置為默認(rèn)卷繞順序逆時針為正 5 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 清除顏色緩存 6 gl.glMatrixMode(GL10.GL_MODELVIEW); // 設(shè)置當(dāng)前矩陣為模式矩陣 7 gl.glLoadIdentity(); // 設(shè)置矩陣為單位矩陣 8 GLU.gluLookAt( gl, // 設(shè)置攝像機(jī) 9 Constant.CameraX, // 攝像機(jī)_x_位置 10 Constant.CameraY, // 攝像機(jī)_y_位置 11 Constant.CameraZ, // 攝像機(jī)_z_位置 12 Constant.TargetX, // 觀測點(diǎn)的_x_位置 13 Constant.TargetY, // 觀測點(diǎn)的_y_位置 14 Constant.TargetZ, // 觀測點(diǎn)的_z_位置 15 Constant.UpX, // UP向量x分量 16 Constant.UpY, // UP向量y分量 17 Constant.UpZ); // UP向量z分量 18 gl.glPushMatrix(); // 保護(hù)矩陣 19 if (backgrounds != null) { // 背景圖不為空就繪制 20 backgrounds.drawSelf(gl,background); // 繪制背景圖 21 } 22 gl.glPopMatrix(); // 恢復(fù)矩陣 23 gl.glPushMatrix(); // 保護(hù)矩陣 24 if (waterweeds1 != null&&stones!=null) { // 如果沒有繪制過水草和石頭則繪制 25 gl.glPushMatrix(); // 左后邊的水草、石頭 26 gl.glTranslatef(-17, -5.5f,-14); // 平移坐標(biāo)系 27 stones.drawSelf(gl,stone); // 繪制石頭 28 gl.glTranslatef(1.5f, 0, 1); // 平移坐標(biāo)系 29 waterweeds1.drawSelf(gl,waterweeds); // 繪制水草 30 gl.glTranslatef(2, 0, 1); // 平移坐標(biāo)系 31 gl.glPushMatrix(); // 保護(hù)矩陣 32 gl.glScalef(1.5f, 1.5f, 1.5f); // 設(shè)置縮放 33 stones.drawSelf(gl,stone); // 繪制石頭 34 gl.glPopMatrix(); // 恢復(fù)矩陣 35 ……下面的水草和石頭的繪制和上面的類似就不再給出程序,讀者可自行查看源代碼 36 } 37 gl.glPopMatrix(); // 恢復(fù)矩陣 38 gl.glPushMatrix(); // 保護(hù)矩陣 39 if (fishControl != null) { 40 fishControl.drawSelf(gl); // 繪制魚 41 } 42 if (fishSchool != null) { 43 fishSchool.drawSelf(gl); // 繪制魚群 44 } 45 gl.glPopMatrix(); // 恢復(fù)矩陣 46 gl.glPushMatrix(); // 保護(hù)矩陣 47 if (singleFood != null) { 48 singleFood.drawSelf(gl); // 繪制魚食 49 } 50 gl.glPopMatrix(); // 恢復(fù)矩陣 51 gl.glPushMatrix(); // 保護(hù)矩陣 52 gl.glEnable(GL10.GL_BLEND); // 開啟混合 53 gl.glBlendFunc(GL10.GL_SRC_ALPHA, 54 GL10.GL_ONE_MINUS_SRC_ALPHA); // 設(shè)置源混合因子與目標(biāo)混合因子 55 gl.glTranslatef(0, 0, 15f); // 平移 56 if (bubbleControl != null) { 57 bubbleControl.drawSelf(gl); // 繪制氣泡 58 } 59 gl.glDisable(GL10.GL_BLEND); // 關(guān)閉混合 60 gl.glPopMatrix(); // 恢復(fù)矩陣 61 }

第1~17行設(shè)置背面剪裁、卷繞方式、平滑著色、清除顏色緩存和深度緩存,設(shè)置當(dāng)前矩陣為模式矩陣,設(shè)置當(dāng)前矩陣為單位矩陣,設(shè)置攝像機(jī)位置。
第18~36行繪制背景圖、水草和石頭。由于水草和石頭要重復(fù)繪制很多次,在此就不一一列舉了,只給了出其中的部分代碼,其余代碼讀者可自行查看光盤中的源代碼。
第37~61行繪制群魚、魚群、魚食和氣泡。因?yàn)闅馀菔前胪该鞯?#xff0c;所以要開啟混合(繪制氣泡時要根據(jù)氣泡的位置對氣泡進(jìn)行排序),并且要將氣泡在最后繪制,最后不要忘了關(guān)閉混合。
(4)最后將對初始化紋理的initTexture方法進(jìn)行介紹,具體代碼如下所示。

1 public int initTexture(GL10 gl, String pname){ // 初始化紋理 2 int[] textures = new int[1]; // 紋理ID 3 gl.glGenTextures(1, textures, 0); // 生成紋理ID 4 int currTextureId = textures[0]; 5 gl.glBindTexture(GL10.GL_TEXTURE_2D, currTextureId); // 綁定紋理 6 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, 7 GL10.GL_NEAREST); // 最近點(diǎn)采樣 8 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, 9 GL10.GL_LINEAR); // 線性紋理過濾 10 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, 11 GL10.GL_CLAMP_TO_EDGE); // 紋理的橫向拉伸方式 12 gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, 13 GL10.GL_CLAMP_TO_EDGE); // 紋理的縱向拉伸方式 14 InputStream in = null; // 創(chuàng)建輸入流 15 try { 16 in = this.getResources().getAssets().open(pname); // 加載紋理圖片 17 } catch (IOException e1) { 18 e1.printStackTrace(); // 異常處理 19 } 20 Bitmap bitmapTmp; // 創(chuàng)建bitmap對象 21 try { 22 bitmapTmp = BitmapFactory.decodeStream(in); // 對獲取的圖片解碼 23 } finally { 24 try { 25 in.close(); // 關(guān)閉輸入流 26 } catch (IOException e) { 27 e.printStackTrace(); // 異常處理 28 }} 29 GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapTmp, 0); // 指定紋理 30 bitmapTmp.recycle(); // 釋放bitmap 31 return currTextureId; 32 }

第2~13行定義紋理ID、生成紋理ID、綁定紋理、設(shè)置紋理的過濾方式分為最近點(diǎn)采樣和線性紋理過濾,設(shè)置紋理的拉伸方式分為橫向拉伸方式和縱向拉伸方式。
第14~32行創(chuàng)建輸入流,讀取紋理圖片,進(jìn)行異常處理。創(chuàng)建bitmap對象,對獲取的圖片進(jìn)行解碼,關(guān)閉輸入流,異常處理,最后釋放bitmap。

總結(jié)

以上是生活随笔為你收集整理的《Android 应用案例开发大全(第二版)》——2.4节壁纸的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久久久亚洲av无码专区桃色 | 国产经典一区二区三区 | 鲁啊鲁在线视频 | 青青草偷拍视频 | 玉女心经是什么意思 | 狠狠操狠狠| 国产精品高潮呻吟久久久 | 欧美大片在线观看 | 国产成人无码精品久久二区三 | 无套内谢的新婚少妇国语播放 | 成人公开视频 | 伊人天堂av | 影音先锋啪啪 | 欧美黄色小说 | 综合网五月 | 一本视频在线 | 777奇米视频 | 网爆门在线 | 双性娇喘浑圆奶水h男男漫画 | 精精国产 | 神马久久久久久久久 | k8yy毛片| 草视频在线观看 | 草草影院在线播放 | 欧美日韩亚洲国产一区 | 久久精品无码一区 | 91视频青青草 | 欧美极品一区二区三区 | av日韩不卡 | 国产自产在线 | 91久久中文字幕 | 日韩女同一区二区三区 | 中文字幕在线精品 | 亚洲欧美视频一区二区 | 欧美亚洲日本国产 | 亚洲视频网站在线观看 | 日本三级大片 | 久久久久久久香蕉 | 亚洲国产影视 | 五级 黄 色 片 | 最好看十大无码av | 日本三级播放 | 99视频久| 色综合999| www.日本黄 | 日韩一区二区免费看 | 精品伦理一区二区 | 亚洲在线观看免费视频 | 国产无遮挡又黄又爽免费视频 | 成人一区二区精品 | 久久涩视频 | 69视频国产 | 亚洲av无码国产精品色午夜 | 亚洲天堂中文字幕 | 国产成人三级一区二区在线观看一 | 动漫艳母在线观看 | 欧美图片一区 | a级免费观看 | 欧美日韩a√ | 五月婷婷爱爱 | 师生出轨h灌满了1v1 | 91欧美日韩麻豆精品 | 人妻丰满熟妇av无码区不卡 | 日本一区二区网站 | 日本a网| 在线观看中文字幕亚洲 | 免费看日产一区二区三区 | 亚洲一线av | 在线观看网址你懂的 | 欧美一级淫片 | 日韩伦理一区 | 亚洲黄在线观看 | av波多野吉衣| 欧美黑人性猛交xxxx | 久久精品国产一区二区电影 | 91影院在线免费观看 | 国产香蕉视频在线播放 | 伊人青青操| 欧美精品一区二区蜜桃 | 成人香蕉网| 四虎av网址| 超碰日韩在线 | 久久黄色精品视频 | 色福利在线 | jizz成人 | 女同hd系列中文字幕 | 国产精品无码一区二区桃花视频 | 色播亚洲 | 国产黄色片av | av天天干| 日日骚一区二区 | 精精国产xxxx视频在线播放 | julia中文字幕在线 | 日韩精品电影在线观看 | 成人免费在线播放视频 | 国产黄色网页 | 超碰精品在线 | 99ri国产在线| ts人妖在线 |