android 遊戲導引(2. 遊戲的基礎設定)

來源:互聯網
上載者:User

android 遊戲導引(2. 遊戲的基礎設定)

上一節已經學習了一個基本的 OpenGL 架構了,今天這一節就進一步設定一下 2D 遊戲相關的東西了。對 2D 遊戲的喜愛甚於 3D。 相信大多數人也是吧。

Table of Contents
  • 1 遊戲全螢幕顯示
  • 2 設定 OpenGL 的 2D 環境
    • 2.1 onSurfaceCreated
    • 2.2 onSurfaceChanged
    • 2.3 onDrawFrame
  • 3 三角形-測試
1 遊戲全螢幕顯示

2行代碼搞定,一個讓應用去掉自己的標題列,一個設定全屏,放在應用的建立函數 OnCreate 中:

 

public class GlGame extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                requestWindowFeature(Window.FEATURE_NO_TITLE);        getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN ,                      WindowManager.LayoutParams. FLAG_FULLSCREEN);                // ... 其他略    }}

 

2 設定 OpenGL 的 2D 環境

我們先要設計好要建立的世界定位方式,就是座標系,一般的 opengl 程式是標準的笛卡爾座標系,即左下角為原點,x橫向右延伸,y縱向上延伸。像著名的 cocos2d 引擎就是此種方式。我比較偏好另一套就是左上方為原點的描述方式,所以採用了此套座標系:

GLSurfaceView 的 Renderer,給出了三個介面:建立時,大小改變時,繪製。我們在三個函數中採取的操作如下:

  • 建立時, onSurfaceCreated, 進行 OpenGL 的基本設定,如陰影平滑,深度測試啊神馬的。
  • 大小改變時,onSurfaceChanged, 進行投影,視口等設定。
  • 繪製,onDrawFrame, 我們後續的遊戲繪製主要在這個函數了。

2.1 onSurfaceCreated

不多說,都是基本設定。

 

public void onSurfaceCreated(GL10 gl, EGLConfig config) {    // 告訴系統對透視進行修正    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);    // 背景黑色    gl.glClearColor(0, 0, 0, 1);    // 啟用陰影平滑    gl.glShadeModel(GL10.GL_SMOOTH);    // 設定深度緩衝    gl.glClearDepthf(1.0f);    // 啟用深度測試    gl.glEnable(GL10.GL_DEPTH_TEST);    // 所做深度測試的類型    gl.glDepthFunc(GL10.GL_LEQUAL);}

 

2.2 onSurfaceChanged

 

public void onSurfaceChanged(GL10 gl, int width, int height) {    // 設定 OpenGL 情境的大小    gl.glViewport(0, 0, width, height);        // 設定投影矩陣    gl.glMatrixMode(GL10.GL_PROJECTION);    // 重設投影矩陣    gl.glLoadIdentity();    // 設定視口的大小    // gl.glOrthof(0, width, height, 0, -1000, 1000);    GLU.gluOrtho2D(gl, 0, width, height, 0);     // 重設模型矩陣    gl.glMatrixMode(GL10.GL_MODELVIEW);    gl.glLoadIdentity();}

 

代碼中先用 glViewPort 設定了情境的大小,我們所有的opengl世界都被投射到這個情境中,在這裡,我們將情境的大小設定為視窗 Surface 的大小。

繼而設定了投影矩陣,投影矩陣定義了 opengl 世界怎樣反應在你的情境中,在 OpenGL 中又兩種投影方式: 透視和正交。透視比較接近我們現實的方式了,你的眼睛發出的光形成一個夾角,離你的眼睛越近,東西越大,範圍越小;反之離眼睛越遠,東西越小,視野越開闊。因此多用於 3D 中。 而正交卻是世界中的物體按照平行的光線投射到一張紙上(你的畫布),彷彿被壓縮在上面,無論這個物體在世界中多遠,投射結果還是原來的大小, 2d 遊戲多用此種投影。

設定透視投影有 glFrustum 和 glu 庫的 gluPerspective, 都可以設定上面透視投影中的角度,遠近等參數。還可以 gluLookAt 來設定眼睛(相機)的位置。

設定正交投影有 glOrtho 和 glu 庫的 gluOrth2D :

glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);
gluOrth2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top);

glu版本的y軸參數不用我們設定了,因為不會用到。由於我們的座標系以左上方為原點,所以 left 和 top 參數為 0。

glMatrixMode() 函數指定了其下面的代碼操作的是何種矩陣。 我們這裡用到兩類矩陣變換:投影變換和模型視圖變換。投影變換中我們更改了世界空間的裁切範圍,在模型視圖變換中,我們可以移動和旋轉世界中的物體,所以我們在繪製的時候就是在模型視圖矩陣變換中。 glLoadIdentity() 用於重設矩陣,清除上次的殘留資訊。

代碼最後設定為模型視圖變換,便於我們在繪製函數中移動和變換物體模型了。

2.3 onDrawFrame

先說明一下 GLSurfaceView 的 Renderer 繪製是在獨立的線程中完成的,這個函數被不斷的迴圈調用。

前面已經設定為模型視圖矩陣了,每次 onDrawFrame 的時候,我們都要 glLoadIdentity 重設一次,清除上次繪製造成的殘留資訊。

 

public void onDrawFrame(GL10 gl) {    // 清除螢幕和深度緩衝    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);    // 重設模型矩陣    gl.glLoadIdentity();     //... 要添加的具體繪製代碼}

 

3 三角形-測試

好了,上面已經設定好了,我們先來個簡單的測試吧,在你的視窗中繪製一個紅色三角形。先定義好三角形的三個角度,左上方為 (60,200), 右上方為 (180, 200), 下角為 (120,300)。

 

private FloatBuffer triggerBuffer = FloatBuffer.wrap(new float[]{    60,200,     // 左上方    180, 200,   // 右上方    120,300,    // 下頂角}); public void onDrawFrame(GL10 gl) {    // 清除螢幕和深度緩衝    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);    // 重設模型矩陣    gl.glLoadIdentity();         gl.glPushMatrix();        gl.glColor4f(1, 0, 0, 0);        // 允許設定頂點        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, triggerBuffer);        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);        // 取消設定頂點        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);    gl.glPopMatrix();}

 

主要程式碼封裝圍在了 glPushMatrix() 和 glPopMatrix() 中,OpenGL內部維護了各種矩陣棧,棧的操作就是 push 和 pop 了。這裡我們的操作是在模型視圖矩陣變換中進行的,所以操作的是模型視圖棧。之所以壓棧,我們不想繪製三角形的矩陣資訊汙染到外層的矩陣中,比如顏色設定等。所以大家在繪製一個單位體的時候盡量使用 push 和 pop 操作。

先用 glColor4f 設定繪製顏色為紅色。opengles 中少了 glBegin, glEnd 類標準函數,採用了數組頂點來設座標方式,主要還是效能考慮吧。預設是關掉這個選項的,所以先開啟,不用了再關閉: glEnableClientState(GL10.GLVERTEXARRAY), glDisableClientState(GL10.GLVERTEXARRAY).

指定數組頂點用 glVertexPointer, 指定完了就可以用 glDrawArray() 來將指定的數組中的頂點繪製出來了。這裡有必要羅嗦一下這兩個函數了,因為這兩個函數用到的太多了。先看第一個:

void glVertexPointer (int size, int type, int stride, Buffer pointer)

參數:

size
每個頂點有幾個數值描述。必須取值2,3,4之一。初始值是 4.
type
數組中每個頂點座標的類型。取值:GLBYTE, GLSHORT, GLFIXED, GLFLOAT。初始值為 GLFLOAT。
stride
數組中每個頂點間的間隔,步長(位元組位移)。取值若為 0 表示數組是連續的。初始值為 0。
pointer
就是你的數組了,儲存著每個頂點的座標值。初始值為 0。

注意了, type 中告訴 opengl 你的數群組類型。 GLBYTE, GLSHORT, GLFLOAT 對應 byte[], short[], float[]. GLFIXED 對應 int[]. 有一個特別的地方, GLFIXED 描述的時候,大家的點座標單位是 0x10000, 比如一個點是 (60, 120), 用 GLFIXED 的時候,需要設定為 (60 * 0x10000, 120 * 0x10000), 所以經常看到 int one = 0x10000 的編程語句, 這個數值就是這麼來的。

再來看 glDrawArray:

void glDrawArrays (int mode, int first, int count);

參數:

mode
指定你要繪製何種圖元, opengl 中的圖元就這幾個: GLPOINTS, GLLINESTRIP, GLLINELOOP, GLLINES, GLTRIANGLESTRIP, GLTRIANGLEFAN, GLTRIANGLES.
first
在已制定的數組中的開始位置(索引位置)
count
點的繪製次數, 比如我們繪製一個三角形,就是繪製三個頂點,即此參數為 3。

這兩個函數就介紹這麼多了,足以應付這個程式了。有問題可以查官方函數文檔: http://www.khronos.org/opengles/sdk/1.1/docs/man/

好了,代碼就介紹完了。一個三角形大家應該會繪製了吧,大家可以試試其他的圖元,點,線,四邊形,多邊形等等。

學習愉快。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.