Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 859|回复: 0

[转]android 游戏导引(2. 游戏的基础设置) - Android学习

[复制链接]

该用户从未签到

发表于 2011-10-27 08:21:17 | 显示全部楼层 |阅读模式
转自: http://www.cnblogs.com/shengdoushi/archive/2011/01/02/1923940.html


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/
好了,代码就介绍完了。一个三角形大家应该会绘制了吧,大家可以试试其他的图元,点,线,四边形,多边形等等。
学习愉快。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-11 22:54 , Processed in 0.296158 second(s), 36 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表