山寨腾讯“爱消除”游戏之屏幕拾取技术

编程入门 行业动态 更新时间:2024-10-26 19:36:18

山寨<a href=https://www.elefans.com/category/jswz/34/1770070.html style=腾讯“爱消除”游戏之屏幕拾取技术"/>

山寨腾讯“爱消除”游戏之屏幕拾取技术

在山寨腾讯“爱消除”游戏项目中,我们使用了两种简单的屏幕拾取技术,这在第五天的教程及山寨腾讯“爱消除”游戏之菜单特效里已经有介绍。

很显然,对于一些有复杂不规则图案,或有层次感的场面,上面的技术并不能满足要求。今天我们将介绍另外一种屏幕拾取的方法。


如下图所示,这个是《教你玩魔方》游戏里的一个场景。

显然,由于以下的原因,用前面介绍的两种技术将很难完成准确的屏幕拾取。

1、中间的魔方体是可以随意缩放的;

2、魔方的每一个面都是可以转动的;

3、每个面在转动过程中,位置都是随时变化的;

4、转动结束后,面上每一个方块都会发生变化;

5、每个方块都有6个面,有些面是可见的,有些面是不可见的,触摸到不同的面,产生的动作效果应该是不一样的。




好,下面详细地看一下DisplaySingleCube函数,该函数分别将方块的6个面渲染出来。

 

1、DisplaySingleCube用于显示一个小方块,一个完整的魔方需要调用27次这个函数,最后一个参数cubeIndex指定了方块的索引(0~26)

2、DisplaySingleCube函数中的渲染操作分为DRAW和SELECT_PLATE两种模式,在屏幕拾取时,要将模式设置为SELECT_PLATE

3、DRAW模式下,使用纹理渲染;SELECT_PLATE模式下,使用色彩渲染,每个面分别渲染出不同的颜色,详细看下面代码的注释;根据选定的颜色,就可以知道触摸到的是哪一个面了。

 

    //显示单个方块private void DisplaySingleCube(ST_DreamCube dreamcube, float fX, float fY,float fZ,float fRX,float fRY,float fRZ, int cubeIndex){E_WORKMODE eMode = GetGLMode();E_COLOR cU, cD, cF, cB, cL, cR;cU = dreamcube.cube_status[cubeIndex].Color.U;cD = dreamcube.cube_status[cubeIndex].Color.D;cF = dreamcube.cube_status[cubeIndex].Color.F;cB = dreamcube.cube_status[cubeIndex].Color.B;cL = dreamcube.cube_status[cubeIndex].Color.L;cR = dreamcube.cube_status[cubeIndex].Color.R;BindVertexAndTexture(cubeBuff, cubetexBuff);mGl.glLoadIdentity();                //可不要GLU.gluLookAt(mGl,-5.0f, 5.0f, 5.0f,0.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f);mGl.glScalef(mCfg.cubeConfig.fZoomFactor, mCfg.cubeConfig.fZoomFactor, mCfg.cubeConfig.fZoomFactor);mGl.glTranslatef((float)0.3, (float)0.3-1, (float)-0.3);mGl.glFrontFace(GL10.GL_CCW);if (mCube.fYDegree != 0){mGl.glRotatef(mCube.fYDegree, 0.0f, 1.0f, 0.0f);}if (fRX != 0 || fRY != 0 || fRZ != 0){mGl.glRotatef(fRotate, fRX, fRY, fRZ);}mGl.glTranslatef(fX, fY, fZ);// FRONT AND BACKif (eMode == E_WORKMODE.DRAW){mGl.glBindTexture(GL10.GL_TEXTURE_2D, texture[cF.ordinal()]);}else if (eMode == E_WORKMODE.SELECT_PLATE){mGl.glColor4f(0, 0, 1, 1);     //RGB(0,0,1) 蓝}mGl.glNormal3f(0.0f, 0.0f, 1.0f);mGl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);if (eMode == E_WORKMODE.DRAW){mGl.glBindTexture(GL10.GL_TEXTURE_2D, texture[cB.ordinal()]);}else if (eMode == E_WORKMODE.SELECT_PLATE){mGl.glColor4f(0, 1, 0, 1);    //RGB(0,1,0) 绿}mGl.glNormal3f(0.0f, 0.0f, -1.0f);mGl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);// LEFT AND RIGHTif (eMode == E_WORKMODE.DRAW){mGl.glBindTexture(GL10.GL_TEXTURE_2D, texture[cL.ordinal()]);}       else if (eMode == E_WORKMODE.SELECT_PLATE){mGl.glColor4f(0, 1, 1, 1);    //RGB(0,0,1) 蓝+绿}mGl.glNormal3f(-1.0f, 0.0f, 0.0f);mGl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);if (eMode == E_WORKMODE.DRAW){mGl.glBindTexture(GL10.GL_TEXTURE_2D, texture[cR.ordinal()]);}else if (eMode == E_WORKMODE.SELECT_PLATE){mGl.glColor4f(1, 0, 0, 1);     //RGB(0,0,1) 红}mGl.glNormal3f(1.0f, 0.0f, 0.0f);mGl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);// TOP AND BOTTOMif (eMode == E_WORKMODE.DRAW){mGl.glBindTexture(GL10.GL_TEXTURE_2D, texture[cU.ordinal()]);}else if (eMode == E_WORKMODE.SELECT_PLATE){mGl.glColor4f(1, 0, 1, 1);     //RGB(0,0,1) 红+蓝}mGl.glNormal3f(0.0f, 1.0f, 0.0f);mGl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);if (eMode == E_WORKMODE.DRAW){mGl.glBindTexture(GL10.GL_TEXTURE_2D, texture[cD.ordinal()]);}else if (eMode == E_WORKMODE.SELECT_PLATE){mGl.glColor4f(1, 1, 0, 1);     //RGB(0,0,1) 红+绿}mGl.glNormal3f(0.0f, -1.0f, 0.0f);mGl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);}


 

接下来介绍选择物体的函数SelectObj,参数是手指触碰到屏幕的坐标值。

1、在进入SelectObj函数之前,需要将模式设置为PICK,这样DisplaySingleCube函数内部的DRAW及SELECT_PLATE将不起作用;

2、在绘制每一个小方块之前,调用glColor4f给这个方块设置颜色,每个方块都会设置成不同的颜色,详细看代码注释;

3、我们用(0,0,1)~(1,1,1)来表示不同的颜色,最多只能7种颜色,那么如何用7种颜色来识别27个方块呢?我们采用分组的方法来做到这一点的,详细见代码;

 

    //对象选择操作E_SELECTION SelectObj(int x, int y){E_SELECTION eObj = E_SELECTION.SELE_INVALID;int iObj = 0;InitViewPortMain();    	mGl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);{       mCube.XChgDreamCube4Display(mCube.DREAM_CUBE_CACULATE);mGl.glColor4f(0, 0, 1, 1);   // RGB(0,0,1)  蓝色DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 24);mGl.glColor4f(0, 1, 0, 1);   // RGB(0,1,0)  绿色DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 25);mGl.glColor4f(0, 1, 1, 1);   // RGB(0,1,1)  绿色+蓝色DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 26);mGl.glColor4f(1, 0, 0, 1);   // RGB(1,0,0)  红色DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 15);mGl.glColor4f(1, 0, 1, 1);   // RGB(1,0,1)  红色+蓝色DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 16);mGl.glColor4f(1, 1, 0, 1);   // RGB(1,1,0)  红色+绿色DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 17);iObj = GetObj(x, y);     //分组1if(iObj != 0){switch(iObj){case 1:eObj = E_SELECTION.SELE_BLK24;break;case 2:eObj = E_SELECTION.SELE_BLK25;break;case 3:eObj = E_SELECTION.SELE_BLK26;break;case 4:eObj = E_SELECTION.SELE_BLK15;break;case 5:eObj = E_SELECTION.SELE_BLK16;break;case 6:eObj = E_SELECTION.SELE_BLK17;break;
//    			default:
//    				eObj = -1;
//    				break;}return eObj;}mGl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);mGl.glColor4f(0, 0, 1, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 6);mGl.glColor4f(0, 1, 0, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 7);mGl.glColor4f(0, 1, 1, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 8);mGl.glColor4f(1, 0, 0, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 23);mGl.glColor4f(1, 0, 1, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 14);mGl.glColor4f(1, 1, 0, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 5);iObj = GetObj(x, y);             //分组2if(iObj != 0){switch(iObj){case 1:eObj = E_SELECTION.SELE_BLK6;break;case 2:eObj = E_SELECTION.SELE_BLK7;break;case 3:eObj = E_SELECTION.SELE_BLK8;break;case 4:eObj = E_SELECTION.SELE_BLK23;break;case 5:eObj = E_SELECTION.SELE_BLK14;break;case 6:eObj = E_SELECTION.SELE_BLK5;break;
//    			default:
//    				eObj = -1;
//    				break;}return eObj;}mGl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);mGl.glColor4f(0, 0, 1, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 2);mGl.glColor4f(0, 1, 0, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 11);mGl.glColor4f(0, 1, 1, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 18);mGl.glColor4f(1, 0, 0, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 19);mGl.glColor4f(1, 0, 1, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 20);mGl.glColor4f(1, 1, 0, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 21);mGl.glColor4f(1, 1, 1, 1);DisplaySingleCube(mCube.DREAM_CUBE_DISPLAY, 0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 22);iObj = GetObj(x, y);              //分组3if(iObj != 0){switch(iObj){case 1:eObj = E_SELECTION.SELE_BLK2;break;case 2:eObj = E_SELECTION.SELE_BLK11;break;case 3:eObj = E_SELECTION.SELE_BLK18;break;case 4:eObj = E_SELECTION.SELE_BLK19;break;case 5:eObj = E_SELECTION.SELE_BLK20;break;case 6:eObj = E_SELECTION.SELE_BLK21;break;case 7:eObj = E_SELECTION.SELE_BLK22;break;
//    			default:
//    				eObj = -1;
//    				break;}return eObj;}    		}mGl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);ShowUnseenPlate(mCube.DREAM_CUBE_CACULATE);        	iObj = GetObj(x, y);if(iObj != 0){switch(iObj){case 1:eObj = E_SELECTION.SELE_LEFT;break;case 2:eObj = E_SELECTION.SELE_RIGHT;break;case 3:eObj = E_SELECTION.SELE_DOWN;break;
//			default:
//				eObj = E_Selection.SELE_INVALID;
//				break;}return eObj;}mGl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);ShowLButton();iObj = GetObj(x, y);if(iObj != 0){switch(iObj){case 1:eObj = E_SELECTION.SELE_MENU;break;case 2:eObj = E_SELECTION.SELE_HELP;break;case 3:eObj = E_SELECTION.SELE_ZOOMOUT;break;case 4:eObj = E_SELECTION.SELE_DISRUPT;break;case 5:eObj = E_SELECTION.SELE_AUTOPLAY;break;case 6:eObj = E_SELECTION.SELE_RESTART;break;case 7:eObj = E_SELECTION.SELE_STUDY;break;}return eObj;}mGl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);ShowRButton();iObj = GetObj(x, y);if(iObj != 0){switch(iObj){case 1:eObj = E_SELECTION.SELE_ZOOMIN;break;case 2:eObj = E_SELECTION.SELE_SETUP;break;}return eObj;}mGl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);ShowProgressStars();        	iObj = GetObj(x, y);if(iObj != 0){switch(iObj){case 1:eObj = E_SELECTION.SELE_STAR;break;}return eObj;}mGl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);ShowCubeTip();iObj = GetObj(x, y);if(iObj != 0){switch(iObj){case 1:eObj = E_SELECTION.TIP_0;break;case 2:eObj = E_SELECTION.TIP_1;break;case 3:eObj = E_SELECTION.TIP_2;break;case 4:eObj = E_SELECTION.TIP_3;break;case 5:eObj = E_SELECTION.TIP_4;break;case 6:eObj = E_SELECTION.TIP_5;break;case 7:eObj = E_SELECTION.TIP_6;break;}return eObj;}mGl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);ShowTime(miCubeClockSec);iObj = GetObj(x, y);if(iObj != 0){switch(iObj){case 1:eObj = E_SELECTION.SELE_TIMER;break;}return eObj;}mGl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);ShowStep(mCube.GetStepBar());iObj = GetObj(x, y);if(iObj != 0){switch(iObj){case 1:eObj = E_SELECTION.SELE_STEP;break;}return eObj;}return eObj;}


 

下面介绍获取对象函数GetObj:

1、根据传入的坐标值,获取指定坐标出的色彩信息;

2、将色彩信息转换为RGB格式,然后返回该信息。


 

    //获取对象private int GetObj(int x, int y){mGl.glFinish();mGl.glFinish();Delay(miSelectDelay);ByteBuffer pixel = ByteBuffer.allocate(4);byte data[] = new byte[4];mGl.glReadPixels(x , iScreenHeight - y, 1, 1, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixel);data = pixel.array();data[0] = (byte) Math.abs(data[0]);data[1] = (byte) Math.abs(data[1]);data[2] = (byte) Math.abs(data[2]);data[0] = (byte) (data[0] << 2);data[1] = (byte) (data[1] << 1);int iObj = data[0] + data[1] + data[2];return iObj;}


 

调用GetObj得到RGB格式的颜色信息,根据该信息,我们可以确定手指触摸到的是哪个方块了:

 

    		iObj = GetObj(x, y);if(iObj != 0){switch(iObj){case 1:eObj = E_SELECTION.SELE_BLK24;break;case 2:eObj = E_SELECTION.SELE_BLK25;break;case 3:eObj = E_SELECTION.SELE_BLK26;break;case 4:eObj = E_SELECTION.SELE_BLK15;break;case 5:eObj = E_SELECTION.SELE_BLK16;break;case 6:eObj = E_SELECTION.SELE_BLK17;break;
//    			default:
//    				eObj = -1;
//    				break;}return eObj;}


 

当触摸事件发生时,我们做了以下事情:

1、将模式设置为PICK

2、用不同颜色来渲染魔方体的各个方块,并拾取到手指触摸处的方块对象

3、将模式设置为DRAW模式

4、按正常的纹理渲染模式,将魔方体完整地渲染出来

 

	case TOUCH:mCubeGL.SetGLMode(E_WORKMODE.PICK);GetTouchObj();mCubeGL.SetGLMode(E_WORKMODE.DRAW);mCubeGL.DisplayCube();				break;


 

采用这种方法,只有模式为DRAW的图案会最终显示出来,PICK或SELECT_PLATE模式下的图案是不会显示的,因此,你不需要担心PICK模式下会破坏整体的渲染效果。


好了,完整的代码请参考我的另一个开源项目《教你玩魔方》

项目地址在GITHUB,欢迎你FORK.







 

转载于:.html

更多推荐

山寨腾讯“爱消除”游戏之屏幕拾取技术

本文发布于:2024-02-16 18:54:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1691106.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:腾讯   山寨   屏幕   技术   游戏

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!