Idea: use OpenGL to draw a circle, the vertex is the center + the point on the circumference, the vertex color value (0, 0, 0, 0), the color value of the circumference point (0, 0, 0, 0, 0xff), enable Alpha mixing, and use glblendfunc (gl_zero, gl_src_alpha). In this way, OpenGL will automatically gradient in the middle area.
Effect:
Code:
Cococs2d-x implementation
Spotlight. h
#ifndef __SPOT_LIGHT_H__#define __SPOT_LIGHT_H__class CCSpotLight: public CCSprite{public:CCSpotLight();~CCSpotLight();static CCSpotLight* spotLightWithRenderTexture(CCRenderTexture* texture, float radius, ccColor4B color);CC_SYNTHESIZE_RETAIN(CCRenderTexture*, m_renderTexture, RenderTexture)CC_SYNTHESIZE(float, m_spotLightRadius, SpotLightRadius)CC_SYNTHESIZE_PASS_BY_REF(ccColor4B, m_renderColor, RenderColor)private:bool initWithRenderTexture(CCRenderTexture* texture, float radius, ccColor4B color);void draw();};#endif// __SPOT_LIGHT_H__
Spotlight. cpp
# Include <cocos2d. h> using namespace cocos2d; # include "spotlight. H "const int spot_light_vertices_count = 45; // The number of vertices on the center and circumference must be greater than 5. Const cccolor4b spot_light_center_color = ccc4 (0, 0, 0, 0 ); const cccolor4b labels = ccc4 (0, 0, 0, 0xff); ccspotlight: ccspotlight () {m_rendertexture = NULL; m_spotlightradius = 0; m_rendercolor.r = 0; m_rendercolor.g = 0; m_rendercolor. B = 0; m_rendercolor.a = 0;} CC Spotlight ::~ Ccspotlight () {cc_safe_release (m_rendertexture);} ccspotlight * ccspotlight: spotlightwithrendertexture (ccrendertexture * texture, float radius, cccolor4b color) {ccspotlight * spotlight = NULL; spotlight = new ccspotlight (); If (spotlight & spotlight-> initwithrendertexture (texture, radius, color) {spotlight-> autorelease (); Return spotlight ;} cc_safe_delete (spotlight); Return spotlight;} bool ccspotlight: ini Twithrendertexture (ccrendertexture * texture, float radius, cccolor4b color) {bool Bret = false; do {Bret = ccsprite: Init (); cc_break_if (! Bret); setrendertexture (texture); setspotlightradius (RADIUS); setrendercolor (color); Bret = true;} while (0); Return Bret;} void ccspotlight: Draw () {ccsprite: Draw (); int segs = spot_light_vertices_count; glfloat * vertices = new glfloat [2 * segs]; // malloc (sizeof (glfloat) * 2 * (segs); glfloat * coordinates = new glfloat [2 * segs]; // malloc (sizeof (glfloat) * 2 * (segs )); cccolor4b * Colors = new cccolor4b [segs]; // malloc (sizeof (cccolor4b) * (segs); memset (vertices, 0, sizeof (glfloat) * 2 * (segs); memset (coordinates, 0, sizeof (glfloat) * 2 * (segs); ccsize winsize = ccdirector: shareddire () -> getwinsize (); m_rendertexture-> clear (m_rendercolor.r, m_rendercolor.g, m_rendercolor. B, m_rendercolor.a); // m_rendertexture-> clear (0, 0, 0, 0xff ); colors [0] = spot_light_center_color; For (INT I = 1; I <segs; I ++) {colors [I] = spot_light_edge_color;} const float coef = 2.0f * (float) m_pi/(segs-2); ccpoint Pos = getposition (); ccsize size = This-> getcontentsize (); vertices [0] = 0; // POS. x; vertices [1] = 0; // POS. y; coordinates [0] = vertices [0]/winsize. width; coordinates [1] = (size. height-vertices [1])/winsize. height; For (INT I = 1; I <segs; I ++) {float rads = I * coef; float J = m_spotlightradius * cosf (rads); // + POS. x; float K = m_spotlightradius * sinf (rads); // + POS. y; vertices [I * 2] = J; vertices [I * 2 + 1] = K; coordinates [I * 2] = (j)/winsize. width; coordinates [I * 2 + 1] = (size. height-k)/winsize. height;} // update the render texture // [self. rendertexture begin]; m_rendertexture-> begin (); glbindtexture ); glvertexpointer (2, gl_float, 0, vertices); gltexcoordpointer (2, gl_float, 0, coordinates); glcolorpointer (4, vertex, 0, colors); gldrawarrays (cost, 0, segs); glcolormask (gl_true, gl_true); glblendfunc (cc_blend_src, cc_blend_dst); // [self. rendertexture end]; m_rendertexture-> end (); cc_safe_delete (vertices); cc_safe_delete (coordinates); cc_safe_delete (colors );}
Call method:
CCRenderTexture* renderLayer = CCRenderTexture::renderTextureWithWidthAndHeight(size.width, size.height);renderLayer->setPosition(ccp(size.width/2, size.height/2));ccBlendFunc bf = {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA};renderLayer->getSprite()->setBlendFunc(bf);addChild(renderLayer);CCSpotLight* spotLight = CCSpotLight::spotLightWithRenderTexture(renderLayer, 60.0f, ccc4(0, 0, 0, 0xFF));CC_BREAK_IF(!spotLight);spotLight->setAnchorPoint(ccp(0, 0));spotLight->setPosition(ccp(size.width/2, size.height/2));//spotLight->setPosition(ccp(0, 0));addChild(spotLight);
Refer:
1. IOS version spotlight effect demo http://www.supersuraccoon-cocos2d.com/zh/2011/09/09/spot-light-demo/
========================================================== ========================================================== ===
Android
Main. xml
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:src="@drawable/dota" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textColor="@android:color/primary_text_light" android:text="@string/hello" /> <Button android:id="@+id/btn_click_me" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_click" /> <com.kle.SpotLight.SpotLightGLSurfaceView android:id="@+id/spotlight_gl_surfaceview" android:layout_width="fill_parent" android:layout_height="fill_parent" /></FrameLayout>
Spotlightactivity. Java
Package COM. gr. spotlight; import android. app. activity; import android. OS. bundle; public class spotlightactivity extends activity {/** called when the activity is first created. * // @ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); m_glview = (spotlightglsurfaceview) findviewbyid (R. id. spotlight_gl_surfaceview); spotlightrender Renderer = new spotlightrender (480,800); m_glview.setrenderer (Renderer); spotlight slight = new spotlight (0,480,100, 5); // the coordinate system is the GL coordinate system, that is, the coordinate origin in the lower left corner of the screen, to the right is the positive direction of the X axis, to the positive direction of the Y axis m_glview.addspotlight (slight); slight = new spotlight (0,480,400, 10); // the coordinate system is the GL coordinate system, that is, the coordinate origin in the lower left corner of the screen, to the right is the positive direction of the X axis, and to the positive direction of the Y axis m_glview.addspotlight (slight); // slight. setposition (240,400); // you can set the coordinate button BTN = (button) findviewbyid (R. id. btn_clic K_me); BTN. setonclicklistener (New onclicklistener () {@ override public void onclick (view v) {// todo auto-generated method stub toast. maketext (getapplicationcontext (), "click me! ", Toast. length_short). Show () ;}}) ;}spotlightglsurfaceview m_glview = NULL ;}
Spotlightglsurfaceview. Java
Package COM. gr. spotlight; import android. content. context; import android. graphics. pixelformat; import android. openGL. glsurfaceview; import android. util. attributeset; import android. view. surfaceholder; public class spotlightglsurfaceview extends glsurfaceview {public spotlightglsurfaceview (context, attributeset attrs) {super (context, attrs ); // todo auto-generated constructor stub // The code must be in Setzorderontop (true) before Renderer; seteglconfigchooser (8, 8, 8, 8, 16, 0); surfaceholder holder = getholder (); holder. setformat (pixelformat. translucent);} public void setrenderer (Renderer) {super. setrenderer (Renderer); m_renderer = (spotlightrender) Renderer;} public int addspotlight (spotlight SL) {int nret = 0; If (m_renderer! = NULL) {m_renderer.addspotlight (SL);} return nret;} public void updatespotlights () {If (m_renderer! = NULL) {m_renderer.updatemove () ;}} private spotlightrender m_renderer = NULL ;}
Spotlightrender. Java
package com.gr.SpotLight;import java.util.ArrayList;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.opengl.GLSurfaceView.Renderer;public class SpotLightRender implements Renderer{ public SpotLightRender(int width, int height) { super(); m_width = width; m_height = height; } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // TODO Auto-generated method stub gl.glDisable(GL10.GL_DITHER); gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); gl.glClearColor(0, 0, 0, 1); gl.glShadeModel(GL10.GL_SMOOTH); //gl.glEnable(GL10.GL_CULL_FACE); gl.glOrthof(0, m_width, 0, m_height, 1, -1); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // TODO Auto-generated method stub m_width = width; m_height = height; gl.glViewport(0, 0, width, height); // make adjustments for screen ratio float ratio = (float)width / height; gl.glMatrixMode(GL10.GL_PROJECTION);// set matrix to projection mode gl.glLoadIdentity();// reset the matrix to its default state gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);// apply the projection matrix } @Override public void onDrawFrame(GL10 gl) { // TODO Auto-generated method stub gl.glClear(GL10.GL_COLOR_BUFFER_BIT); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); for (int i = 0; i < m_spotLightArray.size(); i++) { ((SpotLight)m_spotLightArray.get(i)).moveByFrame(); ((SpotLight)m_spotLightArray.get(i)).draw(gl); } } public int addSpotLight(SpotLight spotLight) { int nRet = 0; if (m_spotLightArray == null) { m_spotLightArray = new ArrayList<SpotLight>(); } if (m_spotLightArray != null && spotLight != null) { m_spotLightArray.add(spotLight); nRet = m_spotLightArray.size(); } return nRet; } public void clearSpotLightArray() { if (m_spotLightArray != null) { m_spotLightArray.clear(); m_spotLightArray = null; } } public void updateMove() { for (int i = 0; i < m_spotLightArray.size(); i++) { ((SpotLight)m_spotLightArray.get(i)).moveByFrame(); } } private ArrayList<SpotLight> m_spotLightArray = new ArrayList<SpotLight>(); private int m_width = 480; private int m_height = 800;}
Spotlight. Java
Package COM. gr. spotlight; import Java. NIO. bytebuffer; import Java. NIO. byteorder; import Java. NIO. floatbuffer; import Java. NIO. intbuffer; import javax. microedition. khronos. opengles. gl10; import android. graphics. color; import android. graphics. point; import android. graphics. pointf; public class spotlight {public spotlight () {Init (0, 0, 0, velocity_default, radius_default, vertex_count_default);} public spotl Ight (float lx, float RX, float y, float v) {Init (LX, RX, Y, V, radius_default, vertex_count_default);} public spotlight (float lx, float RX, float y, float V, float radius) {Init (LX, RX, Y, V, radius, vertex_count_default);} public spotlight (float lx, float RX, float y, float V, float radius, int vertexcount) {Init (LX, RX, Y, V, radius, vertexcount);} private void Init (float lx, float RX, Flo At Y, float V, float radius, int vertexcount) {If (LX> RX) {float TMP = RX; RX = Lx; Lx = TMP;} m_leftx = Lx; m_rightx = RX; m_mydirector = m_rand.nextboolean ()? Director_left: director_right; float x = round () * (m_rightx-m_leftx) + m_leftx; m_position.set (x, y); m_vbyframe = V; m_radius = radius; m_vertexcount = vertexcount; initvertices ();} private void initvertices () {int I = 0; m_vertices = new float [point_size * m_vertexcount]; m_colors = new int [color_size * m_vertexcount]; double coef= 2.0 * Math. PI/(m_vertexcount-2); // center m_vertices [0] = 0; // m_position.x; m_vertices [1] = 0; // m_position.y; m_colors [0] = 0; m_colors [1] = 0; m_colors [2] = 0; m_colors [3] = 0; for (I = 1; I <m_vertexcount; I ++) {double rads = I * coef; m_vertices [I * point_size] = (float) (m_vertices [0] + m_radius * Math. cos (rads); m_vertices [I * point_size + 1] = (float) (m_vertices [1] + m_radius * Math. sin (rads); m_colors [I * color_size] = 0; // 0 xFFFF; m_colors [I * color_size + 1] = 0; m_colors [I * color_size + 2] = 0; m_colors [I * color_size + 3] = 0 xFFFF; // 0;} convert2glpos (); bytebuffer CBB = bytebuffer. allocatedirect (m_colors.length * integer. size/byte. size); CBB. order (byteorder. nativeorder (); m_colorbuffer = CBB. asintbuffer (); m_colorbuffer.put (m_colors); m_colorbuffer.position (0);} private void convert2glpos () {float VT [] = new float [point_size * m_vertexcount]; int I = 0; for (I = 0; I <m_vertexcount; I ++) {vt [I * point_size] = m_vertices [I * point_size] + m_position.x; VT [I * point_size + 1] = m_vertices [I * point_size + 1] + m_position.y;} bytebuffer vBB = bytebuffer. allocatedirect (vt. length * float. size/byte. size); vBB. order (byteorder. nativeorder (); m_vertexbuffer = vBB. asfloatbuffer (); m_vertexbuffer.put (VT); m_vertexbuffer.position (0);} public void draw (gl10 GL) {GL. glfrontface (gl10.gl _ CW); GL. glvertexpointer (point_size, gl10.gl _ float, 0, m_vertexbuffer); GL. glcolorpointer (color_size, gl10.gl _ fixed, 0, m_colorbuffer); GL. trim (gl10.gl _ forward, 0, m_vertexcount);} public void movebyframe () {m_position.offset (m_mydirector * m_vbyframe, 0); If (m_position.x> m_rightx) {forward = m_rightx; m_mydirector = director_left;} else if (m_position.x <m_leftx) {direction = m_leftx; m_mydirector = director_right;} convert2glpos ();} public void setposition (float X, float y) {m_position.set (x, y); convert2glpos ();} public void offposition (float dx, float Dy) {m_position.offset (dx, Dy); convert2glpos ();} public void setradius (float R) {m_radius = r; double coef = 2.0 * Math. PI/(m_vertexcount-2); int I = 0; for (I = 1; I <m_vertexcount; I ++) {double rads = I * coef; m_vertices [I * point_size] = (float) (m_vertices [0] + m_radius * Math. cos (rads); m_vertices [I * point_size + 1] = (float) (m_vertices [1] + m_radius * Math. sin (rads);} convert2glpos ();} private pointf m_position = new pointf (); // relative coordinate, private float m_leftx = 0 in gl_surfaceview; private float m_rightx = 0; private float m_radius; private int m_vertexcount; private point m_parentwinsize = new point (); Private float m_vertices [] = NULL; private int m_colors [] = NULL; private floatbuffer m_vertexbuffer = NULL; private intbuffer m_colorbuffer = NULL; private random m_rand = new random (system. currenttimemillis (); Private Final Static int director_left =-1; private final static int director_right = 1; private int m_mydirector = director_left; private final static float velocity_default = 1; private float m_vbyframe = velocity_default; private final static float radius_default = 100; private final static int vertex_count_default = 45; //> 5 private final static int point_size = 2; private Final Static int color_size = 4; // R, G, B, A private final static int center_color = color. argb (0x00, 0x00, 0x00, 0x00); Private Final Static int edge_color = color. argb (0xff, 0x00, 0x00, 0x00 );}
Refer:
1. android3d collision of objects -- cube collision http://www.2cto.com/kf/201110/109245.html
2. Make glsurfaceview transparent background image http://blog.csdn.net/cc_lq/article/details/6629659
Http://blog.sina.com.cn/s/blog_7705f5140100rive.html
Http://topic.csdn.net/u/20110215/16/c2849359-b07e-424f-bf0d-db0506b69002.html
Summary:
1. Basically, OpenGL is not used, so it is easy to understand. It is very big and you need to learn OpenGL well.
2. At first I was modeled on the cocos2d-x code written Android code, shit doesn't get through it, is not displayed, but also a variety of collapse.
3. The glsurfaceview transparent reference is to make the glsurfaceview transparent and visible background image: three main sentences
mGLSurfaceView.setZOrderOnTop(true);mGLSurfaceView.setEGLConfigChooser(8,8,8,8,16,0);mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
Mglsurfaceview. seteglconfigchooser (8, 8, 8, 8, 16, 0); add it before setrender.
4. Color problems:
The glclearcolor parameter is float, that is, 0 ~ Number between 1, the order of R G B
Glcolorpointer