基于symbian s60 开发的纸牌游戏(part 1)

 刚进公司,第一个项目是一个完全free的card game。项目要求:

平台:symbian s60

工具:carbide C++ 2.0

这是一个3D的game,所以选择使用OpenGL ES。

对pc的opengl我还接触过,以前做毕业设计的时候用过。对于嵌入式OpenGL就完全没底了。所以得从新开始学,但是在公司是不会有太多时间给你完全地去学习,需要边学边做。。。。因此,我打算把整个项目中我的学习过程记录下来。。。。

先了解一下OpenGL ES:

以下是小弟在这半个多月学习OpenGL的一点心得,请各位多指教!!!!!

 

OpenGL介绍:

                OpenGL(Open Graphic s Library)开放图形程序库,是一个专业的3D程序接口,是一个功能强大、调用方便的底层3D图形库。

           OpenGL 是个与硬件无关的软件接口,所以可以在不同的平台进行移植。由于OpenGL3D图形的底层图形库,没有提供几何实体图元,不能直接用以描述场景。但是,通过一些转换程序,可以很方便地将AutoCAD3DS3D图形设计软件制作的DFX3DS模型文件转换成OpenGL的顶点数组, 再通过OpenGL的函数将其绘制并显示到相关的设备。

OpenGL ES介绍:

OpenGL ES (OpenGL for Embedded Systems) OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。针对OpenGL API做了一些删减,因为OpenGL的一些API (比如:glBegin()glEnd())在内存狭小的一些嵌入式设备(比如:手机)上面执行 很低,所以OpenGL ES 用了另外一些API进行取代(比如:glDrawElements)。

EGL  介绍:

EGLOpenGL ES 和底层Native 平台视窗系统之间的接口。EGL是为OpenGL ES提供平台独立性而设计的 OpenGL ES 为附加功能和可能的平台特性开发提供了扩展机制,但仍然需要一个可以让 OpenGL ES 和本地视窗系统交互且平台无关的层。 OpenGL ES 本质上是一个图形渲染管线的状态机,而 EGL 则是用于监控这些状态以及维护 Frame buffer 和其他渲染 Surface 的外部层。以下是一个典型的EGL系统布局图:

 

 

 

OpenGL数据类型:

typedef unsigned int GLenum;

typedef unsigned char GLboolean;

typedef unsigned int GLbitfield;

typedef signed char GLbyte;

typedef short GLshort;

typedef int GLint;

typedef int GLsizei;

typedef unsigned char GLubyte;

typedef unsigned short GLushort;

typedef unsigned int GLuint;

typedef float GLfloat;

typedef void GLvoid;

typedef int GLfixed;

如何在s60平台使用OpenGL ES:

 首先需要创建绘图所需的渲染表面,渲染表面的初始化是由EGL API 实现的,每次要使用OpenGL时都需要初始化渲染表面。具体实现看如下代码:

#include<GLES/gl.h>          //OpenGL ES的头文件

以下定义三个成员变量for display

EGLDisplay  iEglDisplay;        //Display where the graphics are drawn

:(EGLDisplay 是一个关联系统物理屏幕的通用数据类型。对于 PC 来说, Display 就是显示器的句柄。不管是嵌入式系统或 PC ,都可能有多个物理显示设备。为了使用系统的显示设备, EGL 提供了 EGLDisplay 数据类型,以及一组操作设备显示的 API )

EGLContext iEglContext;   //rendering context

EGLSurface  iEglSurface;       //window where the graphics are blitted

 

 

iEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);

     

      //Initialize display

      eglInitialize(iEglDisplay,NULL,NULL);

     

      EGLConfig config;             //Config describing properties of EGLSurface

      EGLConfig* configList = NULL;          //Pointer for EGLConfigs

      int configSize = 0;                       //Num of configs we want EGL to return

      int   numOfConfigs = 0;             //Num of configs actually return

     

      //Get the number of all possible EGLConfigs

      eglGetConfigs(iEglDisplay,configList,configSize,&numOfConfigs);

      configSize = numOfConfigs;

     

      //Allocate memory for configList

      configList = (EGLConfig*)User::Alloc(sizeof(EGLConfig)*configSize);

     

      /* Define properties for the wanted EGLSurface.

      *To get the best possible performance, choose

      *an EGLConfig with a buffer size matching

      *the current window's display mode*/

     

     

    TDisplayMode DMode = Window().DisplayMode();

    TInt BufferSize = 0;

 

    switch ( DMode )

         {

         case(EColor4K):

             BufferSize = 12;

             break;

         case(EColor64K):

             BufferSize = 16;

             break;

         case(EColor16M):

             BufferSize = 24;

             break;

         case(EColor16MU):

                 case(EColor16MA):

             BufferSize = 32;

             break;

         default:

             _LIT(KDModeError,"unsupported displaymode");

             User::Panic( KDModeError, 0 );

             break;

         }

      const EGLint attrib_list[] = {EGL_BUFFER_SIZE,BufferSize,EGL_DEPTH_SIZE,16,EGL_NONE};

     

      //Choose configs that fullfill the requirement in attrib_list

      if(eglChooseConfig(iEglDisplay, attrib_list, configList, configSize,&numOfConfigs)==EGL_FALSE)

            {

            _LIT(KChooseConfig,"choose config failed!");

            User::Panic(KChooseConfig,0);

            }

      /* Choose the ‘best’ config and use that in the future */

      config = configList[0];

     

      User::Free(configList);

     

      /* Create a surface where the graphics are blitted */

      iEglSurface = eglCreateWindowSurface(iEglDisplay,config,&Window(),NULL);

      /* Create a rendering context */

      iEglContext = eglCreateContext(iEglDisplay,config,NULL,NULL);

     

      /* Make the context current. Binds to the current rendering thread and surface.

       * Use the same surface for both drawing and reading */

      eglMakeCurrent(iEglDisplay,iEglSurface,iEglSurface,iEglContext);

iPeriodic = CPeriodic::NewL( CActive::EPriorityIdle ); // Create an active object for

                                                                 // animating the scene

      iPeriodic->Start( 10, 1, TCallBack( DrawCallBack, this ) );

注:

当不使用时,记得释放资源:

      eglMakeCurrent(iEglDisplay,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);

                eglDestroySurface(iEglDisplay,iEglSurface);

                eglDestroySurface(iEglDisplay,iEglContext);

                eglTerminate(iEglDisplay);

Cperiodic用来创建一个活动对象不断的启动TcallBack()回调函数进行刷新,你的绘图程序也就在这个毁掉函数里面实现。

以上完成了EGL的初始化,之后便可以开始创建3D图形,通过OpenGL ES  API绘制你所需要的图形,或者可以导入3ds文件获得其定点数组,将其绘制并显示。

:每次绘制完后需要调用EGL API   eglSwapBuffersEGLDisplay display,EGLSurface surface)交换缓冲区,将surface的内容显示。

 

 

接下来就可以进入绘图。OpenGL ES 使用定点数组来存储对象坐标,因此定义一个几何体也就相当于定义一些数组(定点、法向量、索引等)。

这里以绘制一个简单的红色三角形为例:

首先定义三角形的坐标,三角形是三个定点,而且在3D世界里用的是三维坐标;

 

 

 

static const GLbyte vertices[3 * 3] =

{

-1, -1, 0,

1, -1, 0,

0, 2, 0

}; 也就相当于x(-1,-1,0) y(1,-1,0) z(0,2,0)

static const GLubyte triangles[1 * 3] =

{

/* front */

0,1,2

};  这个是定义颜色的索引值,三角形的颜色和最后一个定点的颜色一样,当然也可以绘制颜色渐变的三角形,只需要把三个定点的颜色设置成不同就会有渐变的效果。

 

绘制三角形的数组已经准备好,接下来就需要对OpenGl ES的一些初始状态进行设置,主要包括背景色的清除、投影矩阵、阴影等。

 

glClearColor( 0.f, 0.f, 0.f, 1.f );  //  设置模式窗口的背景颜色,颜色采用的是RGBA

glViewport( 0, 0, iScreenWidth, iScreenHeight );//设置视口的大小以及位置,

视口:也就是图形最终显示到屏幕的区域,前两个参数是视口的位置,后两个参数是视口的宽和长。

glMatrixMode( GL_PROJECTION );   //  设置矩阵模式为投影矩阵,之后的变换将影响投影矩阵。

OpenGL属于状态管理机制,比如:设置当前矩阵为投影矩阵过后,在没有重新调用glMatrixMode()之前,任何矩阵变换都将影响投影矩阵。

glFrustumf( -1.f, 1.f, -1.f, 1.f, 3.f, 1000.f ); //该函数创建一个透视投影矩阵,其中的参数定义了视景体,可以理解为用相机的时候,眼睛的可视范围。就像一个三棱锥,参数135246分别定义了近裁面和远裁面的左下和右上的(xyz)坐标。

OpenGL 投影有两种模式,一种是透视投影,也就是通过上述函数创建一个三棱锥视景体,这种模式下观看三维模型是近大远小。另外一种模式是正交模式,视景体是一个平行六面体,离相机的距离不会影响物体的大小。

glMatrixMode( GL_MODELVIEW );   //设置当前矩阵为模式矩阵

glVertexpointer( 3, GL_BYTE, 0, vertices );   //指定从哪里存取空间坐标数据

OpenGL 一共有8个这样的函数可以存取不同的坐标数据:

glColorPointer();

glIndexPointer();

glNormalPointer();

glTexCoordPointer();

glShadeModel( GL_FLAT );       //设置阴影模式为GL_FLAT,默认是GL_SMOOTH

阴影模式一共有两种,GL_SMOOTHGL_FLAT,在有关照的情况下会有不同的效果。

glClear( GL_COLOR_BUFFER_BIT );   //清除颜色缓存

glLoadIdentity();         //设置当前矩阵为单位矩阵

 

OpenGL里面的位置大小都是用矩阵来表示的,比如:glScanf()放大或缩小,其实就是用一个矩阵去乘当前的矩阵,为了使变换不受当前矩阵的影响,所以把当前矩阵设置为单位矩阵。

glTranslatex(0, 0, -100 << 16 ); //将坐标向z轴负方向移动100

 

glColor4f( 1.f, 0.f, 0.f, 1.f );         设置颜色为红色

/* Scale the geometry */

glScalex( 15 << 16, 15 << 16, 15 << 16 ); //   将物体沿xyz者分别放大15

/* Draw the triangle */

glDrawElements( GL_TRIANGLES, 1 * 3, GL_UNSIGNED_BYTE, indices );      //绘制图形,GL_TRIANGLES说明要绘制的图形是三角形,3表示一共有三个定点,GL_UNSIGNED_BYTE表示indices存储的数据类型

A call to eglSwapBuffers() can then be made.

这样便成功地绘制了一个红色的三角形。

 

 

一些常用的OpenGL ES API

void glTranslatef(GLfloat x, GLfloat y, GLfloat z)

void glTranslatex(GLfixed x, GLfixed y, GLfixed z)

功能:沿xyz平移

void glScalef(GLfloat x, GLfloat y, GLfloat z)

void glScalex(GLfixed x, GLfixed y, GLfixed z)

功能:在xyz轴进行缩放,参数xyz为你想要的大小。

void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)

void glRotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z)

功能:沿xyz轴进行旋转。Angle表示将要旋转的角度。

void glClear(GLbitfield mask)

功能:用mask清除缓存可以有三种模式进行清除:GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, and GL_STENCIL_BUFFER_BIT.

void glClearDepthf(GLclampf depth)

void glClearDepthx(GLclampx depth)

功能:设置深度缓存,参数为01,使用glClear清除缓存。3D场景OpenGL程序都使用深度缓存。它的排序决定那个物体先画。这样您就不会将一个圆形后面的正方形画到圆形上来。

void glClearColor(GLclampf red,
    GLclampf green,
    GLclampf blue,
    GLclampf alpha)
 
void glClearColorx(GLclampx red,
    GLclampx green,
    GLclampx blue,

GLclampx alpha)

功能:用指定的颜色值(RGBA)清除颜色缓存

void glColorPointer(GLint size,
    GLenum type,
    GLsizei stride,
const GLvoid * pointer)
 
功能:指定颜色的存储空间,sizeOpenGL ES默认为4,表示(RGBA);typepointer内容的类型;stride为数据在pointer内存中的偏移量;pointer为第一个元素的地址。

 

void glEnableClientState(GLenum array)
void glDisableClientState(GLenum array)
 
功能:启用或者禁止arrayarray有:GL_COLOR_ARRAY, GL_MATRIX_INDEX_ARRAY_OES, GL_NORMAL_ARRAY, GL_POINT_SIZE_ARRAY_ARRAY_OES, GL_TEXTURE_COORD_ARRAY, GL_VERTEX_ARRAY, and GL_WEIGHT_ARRAY_OES
 
void glDrawElements(GLenum mode,
    GLsizei count,
    GLenum type,
    const GLvoid * indices)

 

功能:按照参数给定的值绘制图形,mode指定要绘制的类型:GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, and GL_TRIANGLEScount指定要绘制多少个;type指定indices为数组首地址。

 

以上这些是比较常用的API,就不一一介绍了。可以查阅相关资料。

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值