山寨腾讯“爱消除”游戏之生命特效

【广而告之】山寨腾讯“爱消除”游戏已经正式入驻GitHub,项目地址是:https://github.com/3125788/CrazyLink

欢迎广大寨友一起来完善这个游戏。


好了,山寨了那么久,今天开始,我们自己也要来点创新的东西了。

今天我们就为山寨“爱消除”游戏加上生命指示器的效果。所谓生命指示器,就是告诉玩家当前还剩余几条命。好,废话不多说,直接上图。

多于三条命时的效果如下,数字5代表5条命,三颗星星代表三条命,总共8条命。


当生命不足三条时的效果如下,这里只剩下两条命了。



详细的代码在DrawLife渲染类中。调用 public void draw(GL10 gl, int life)传入生命数,就可以将生命指示器渲染出来了。

public class DrawLife {
	
	private IntBuffer   mLifeVertexBuffer;		//顶点坐标数据缓冲
	private IntBuffer   mNumVertexBuffer;		//顶点坐标数据缓冲
    private FloatBuffer   mLifeTextureBuffer;	//顶点纹理数据缓冲
    private FloatBuffer   mNumTextureBuffer;	//顶点纹理数据缓冲
    int vCount=0;							//顶点数量     
    int textureId;							//纹理索引
    int numTextureId;
    
    final int mBitmapW = 64;
    final int mBitmapH = 32;
    final int mFontSize = 24;	//字体大小
    
    float textureRatio;						//为了准确获取纹理图片中的素材对象,需要设置纹理的变换率
    public DrawLife(GL10 gl, int textureId)
    {
    	this.textureId=textureId;
    	initNumTextureBuffer();
    	int[] textures = new int[1];
		gl.glGenTextures(1, textures, 0);
		this.numTextureId = textures[0];
    }	
	//顶点坐标数据的初始化
    private void initVertexBuffer(int col)
    {
    	    	
    	int w = 16;
    	int h = 16;
        vCount=6;//顶点的数量,一个正方形用两个三角形表示,共需要6个顶点   
        int deltaX = ((col + 2)*2*w*CrazyLinkConstent.UNIT_SIZE);
        int deltaY = 10*2*h*CrazyLinkConstent.UNIT_SIZE;
        int vertices[]=new int[]//顶点坐标数据数组
        {
           	-w*CrazyLinkConstent.UNIT_SIZE+deltaX,h*CrazyLinkConstent.UNIT_SIZE+deltaY,0,
        	-w*CrazyLinkConstent.UNIT_SIZE+deltaX,-h*CrazyLinkConstent.UNIT_SIZE+deltaY,0,
        	w*CrazyLinkConstent.UNIT_SIZE+deltaX,-h*CrazyLinkConstent.UNIT_SIZE+deltaY,0,
        	w*CrazyLinkConstent.UNIT_SIZE+deltaX,-h*CrazyLinkConstent.UNIT_SIZE+deltaY,0,
        	w*CrazyLinkConstent.UNIT_SIZE+deltaX,h*CrazyLinkConstent.UNIT_SIZE+deltaY,0,
        	-w*CrazyLinkConstent.UNIT_SIZE+deltaX,h*CrazyLinkConstent.UNIT_SIZE+deltaY,0
        };
        //创建顶点坐标数据缓冲
        //int类型占用4个字节,因此转换为byte的数据时需要*4
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
        vbb.order(ByteOrder.nativeOrder());		//设置本地的字节顺序
        //特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer
        //转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题    	        
        mLifeVertexBuffer = vbb.asIntBuffer();		//转换为int型缓冲
        mLifeVertexBuffer.put(vertices);			//向缓冲区中放入顶点坐标数据
        mLifeVertexBuffer.position(0);				//设置缓冲区起始位置
        return;
    }
    
    private void initNumVertexBuffer()
    {
        vCount=6;//顶点的数量,一个正方形用两个三角形表示,共需要6个顶点
        float deltaX = 160*CrazyLinkConstent.UNIT_SIZE;//((col-3)*64*CrazyLinkConstent.UNIT_SIZE);
        float deltaY = 320*CrazyLinkConstent.UNIT_SIZE;//(((float)row-3 + y)*64*CrazyLinkConstent.UNIT_SIZE);
        int vertices[]=new int[]//顶点坐标数据数组
        {
           	-mBitmapW/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaX,mBitmapH/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaY,0,
        	-mBitmapW/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaX,-mBitmapH/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaY,0,
        	mBitmapW/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaX,-mBitmapH/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaY,0,
        	mBitmapW/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaX,-mBitmapH/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaY,0,
        	mBitmapW/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaX,mBitmapH/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaY,0,
        	-mBitmapW/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaX,mBitmapH/2*CrazyLinkConstent.UNIT_SIZE+(int)deltaY,0
        };
        //创建顶点坐标数据缓冲
        //int类型占用4个字节,因此转换为byte的数据时需要*4
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
        vbb.order(ByteOrder.nativeOrder());		//设置本地的字节顺序
        //特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer
        //转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题    	        
        mNumVertexBuffer = vbb.asIntBuffer();		//转换为int型缓冲
        mNumVertexBuffer.put(vertices);			//向缓冲区中放入顶点坐标数据
        mNumVertexBuffer.position(0);				//设置缓冲区起始位置
        return;
    }

    
    //顶点纹理数据的初始化    
    private void initTextureBuffer(int witch)
    {
        textureRatio = (float)(1/2.0f);		//图片是2个独立的素材对象组成,每次需要根据witch准确地获取对应的素材
        float textureCoors[]=new float[]	//顶点纹理S、T坐标值数组
	    {
        	witch * textureRatio,0,
        	witch * textureRatio,1,
        	(witch+1) * textureRatio,1,
        	(witch+1) * textureRatio,1,
        	(witch+1) * textureRatio,0,        	
        	witch * textureRatio,0
	    };        
        
        //创建顶点纹理数据缓冲
        //int类型占用4个字节,因此转换为byte的数据时需要*4
        ByteBuffer cbb = ByteBuffer.allocateDirect(textureCoors.length*4);
        cbb.order(ByteOrder.nativeOrder());//设置本地字节顺序
        //特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer
        //转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题
        mLifeTextureBuffer = cbb.asFloatBuffer();//转换为int型缓冲
        mLifeTextureBuffer.put(textureCoors);//向缓冲区中放入顶点着色数据
        mLifeTextureBuffer.position(0);//设置缓冲区起始位置
    	return;
    }
    
    private void initNumTextureBuffer()
    {
        float textureCoors[]=new float[]	//顶点纹理S、T坐标值数组
	    {
        	0,0,
        	0,1,
        	1,1,
        	1,1,
        	1,0,        	
        	0,0
	    };        
        
        //创建顶点纹理数据缓冲
        //int类型占用4个字节,因此转换为byte的数据时需要*4
        ByteBuffer cbb = ByteBuffer.allocateDirect(textureCoors.length*4);
        cbb.order(ByteOrder.nativeOrder());//设置本地字节顺序
        //特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer
        //转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题
        mNumTextureBuffer = cbb.asFloatBuffer();//转换为int型缓冲
        mNumTextureBuffer.put(textureCoors);//向缓冲区中放入顶点着色数据
        mNumTextureBuffer.position(0);//设置缓冲区起始位置
    	return;
    }
    
	private void bindTexture(GL10 gl, Bitmap bmp)
	{
		gl.glBindTexture(GL10.GL_TEXTURE_2D, numTextureId);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);//指定缩小过滤方法
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);//指定放大过滤方法
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);//指定S坐标轴贴图模式
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);//指定T坐标轴贴图模式
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
		bmp.recycle();
	}


	Bitmap genBitmap(int life)
	{
		//生成的位图要带ALPHA通道信息,否则无法进行透明化处理
		Bitmap bitmap = Bitmap.createBitmap(mBitmapW, mBitmapH, Config.ARGB_4444);
		Canvas canvas = new Canvas(bitmap);

		Paint paint = new Paint();
		paint.setColor(Color.TRANSPARENT);
		canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);
		paint.setTextSize(mFontSize);	
		paint.setColor(Color.WHITE);
		String str = Integer.toString(life);			
		canvas.drawText(str, 20, 28, paint);	//书写的位置,根据具体情况可以调整一下			

		return bitmap;
	}
	
	public void drawNumber(GL10 gl, int life)
    {
		life -= 3;
		if (life <= 0) return;
    	Bitmap bmp = genBitmap(life);
    	bindTexture(gl, bmp);
    	initNumVertexBuffer();	//根据col,row初始化顶点坐标

    	//顶点坐标,允许使用顶点数组
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		//为画笔指定顶点坐标数据
        gl.glVertexPointer
        (
    		3,				//每个顶点的坐标数量为3  xyz 
    		GL10.GL_FIXED,	//顶点坐标值的类型为 GL_FIXED
    		0, 				//连续顶点坐标数据之间的间隔
    		mNumVertexBuffer	//顶点坐标数据
        );
        
        //纹理坐标,开启纹理
        gl.glEnable(GL10.GL_TEXTURE_2D);   
        //允许使用纹理数组
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        //为画笔指定纹理uv坐标数据
        gl.glTexCoordPointer
        (
    		2, 					//每个顶点两个纹理坐标数据 S、T
    		GL10.GL_FLOAT, 		//数据类型
    		0, 					//连续纹理坐标数据之间的间隔
    		mNumTextureBuffer		//纹理坐标数据
        );        		
        gl.glBindTexture(GL10.GL_TEXTURE_2D,numTextureId);//为画笔绑定指定名称ID纹理   
        
        //绘制图形
        gl.glDrawArrays
        (
    		GL10.GL_TRIANGLES, 
    		0, 
    		vCount
        );
        gl.glDisable(GL10.GL_TEXTURE_2D);//关闭纹理
    	
    }



    void drawLife(GL10 gl, int pic, int col)
    {   
    	initVertexBuffer(col);	//根据col,row初始化顶点坐标
    	initTextureBuffer(pic);	//根据witch来初始化纹理顶点数据
    	//gl.glTranslatef(col * textureRatio, row * textureRatio, 0);	//在x=col,y=row的位置绘制选定的素材对象        
        //顶点坐标,允许使用顶点数组
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		//为画笔指定顶点坐标数据
        gl.glVertexPointer
        (
    		3,				//每个顶点的坐标数量为3  xyz 
    		GL10.GL_FIXED,	//顶点坐标值的类型为 GL_FIXED
    		0, 				//连续顶点坐标数据之间的间隔
    		mLifeVertexBuffer	//顶点坐标数据
        );
        
        //纹理坐标,开启纹理
        gl.glEnable(GL10.GL_TEXTURE_2D);   
        //允许使用纹理数组
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        //为画笔指定纹理uv坐标数据
        gl.glTexCoordPointer
        (
    		2, 					//每个顶点两个纹理坐标数据 S、T
    		GL10.GL_FLOAT, 		//数据类型
    		0, 					//连续纹理坐标数据之间的间隔
    		mLifeTextureBuffer		//纹理坐标数据
        );        		
        gl.glBindTexture(GL10.GL_TEXTURE_2D,textureId);//为画笔绑定指定名称ID纹理   
        
        //绘制图形
        gl.glDrawArrays
        (
    		GL10.GL_TRIANGLES, 
    		0, 
    		vCount
        );
        gl.glDisable(GL10.GL_TEXTURE_2D);//关闭纹理
    }
    
    public void draw(GL10 gl, int life)
    {
    	int lifeCnt = life;
    	if (life > 3) lifeCnt = 3;
    	for(int i = 0; i < 3; i++)
    	{
    		if(lifeCnt >= 3)
    			drawLife(gl, 1, i);
    		else
    			drawLife(gl, 0, i);
    		lifeCnt++;
    	}
    	drawNumber(gl, life);
    }
}

要修改渲染的效果,请修改\CrazyLink\res\drawable-nodpi\life.png图片。如果你设计了更炫的效果,欢迎上传到GitHub上,让更多的寨友一起分享。

当前life.png的效果如下,唯一要注意的是:背景要求是透明的。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值