【广而告之】山寨腾讯“爱消除”游戏已经正式入驻GitHub,项目地址是:https://github.com/3125788/CrazyLink
欢迎广大寨友一起来完善这个游戏。
今天介绍生命特效之失去生命。效果图如下:
游戏中,如果移动小动物后没有能够将其消除,则失去一条生命。所有生命失去后,游戏结束。当然,你也可以加入其它失去生命的条件,如超过一定时间没有移动小动物。
失去生命特效由DrawLifeDel渲染类及CtlLifeDel控制类构成,详细的代码请参考GitHub上的代码。
DrawLifeDel类:
public class DrawLifeDel {
private IntBuffer mVertexBuffer; //顶点坐标数据缓冲
private FloatBuffer mTextureBuffer; //顶点纹理数据缓冲
int vCount=0; //顶点数量
int textureId; //纹理索引
float textureRatio; //为了准确获取纹理图片中的素材对象,需要设置纹理的变换率
public IControl control;
public DrawLifeDel(int textureId)
{
this.textureId=textureId;
control = new CtlLifeDel();
}
//顶点坐标数据的初始化
private void initVertexBuffer()
{
CtlLifeDel ctl = (CtlLifeDel)control;
int w = CrazyLinkConstent.UNIT_SIZE*ctl.getW();
int h = CrazyLinkConstent.UNIT_SIZE*ctl.getH();
float x = ctl.getX();
float y = ctl.getY();
vCount=6;//顶点的数量,一个正方形用两个三角形表示,共需要6个顶点
int deltaX = (int)(x*32*CrazyLinkConstent.UNIT_SIZE);
int deltaY = (int)(y*32*CrazyLinkConstent.UNIT_SIZE);
int vertices[]=new int[]//顶点坐标数据数组
{
deltaX-w,deltaY+h,0,
deltaX-w,deltaY-h,0,
deltaX+w,deltaY-h,0,
deltaX+w,deltaY-h,0,
deltaX+w,deltaY+h,0,
deltaX-w,deltaY+h,0
};
//创建顶点坐标数据缓冲
//int类型占用4个字节,因此转换为byte的数据时需要*4
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder()); //设置本地的字节顺序
//特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer
//转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题
mVertexBuffer = vbb.asIntBuffer(); //转换为int型缓冲
mVertexBuffer.put(vertices); //向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0); //设置缓冲区起始位置
return;
}
//顶点纹理数据的初始化
private void initTextureBuffer(int witch)
{
textureRatio = (float)(1/16.0f); //图片是16个独立的素材对象组成,每次需要根据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(),否则有可能会出问题
mTextureBuffer = cbb.asFloatBuffer();//转换为int型缓冲
mTextureBuffer.put(textureCoors);//向缓冲区中放入顶点着色数据
mTextureBuffer.position(0);//设置缓冲区起始位置
return;
}
public void draw(GL10 gl)
{
if(!control.isRun()) return;
CtlLifeDel ctl = (CtlLifeDel)control;
initVertexBuffer(); //根据col,row初始化顶点坐标
initTextureBuffer(ctl.getPicId()); //根据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, //连续顶点坐标数据之间的间隔
mVertexBuffer //顶点坐标数据
);
//纹理坐标,开启纹理
gl.glEnable(GL10.GL_TEXTURE_2D);
//允许使用纹理数组
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//为画笔指定纹理uv坐标数据
gl.glTexCoordPointer
(
2, //每个顶点两个纹理坐标数据 S、T
GL10.GL_FLOAT, //数据类型
0, //连续纹理坐标数据之间的间隔
mTextureBuffer //纹理坐标数据
);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textureId);//为画笔绑定指定名称ID纹理
//绘制图形
gl.glDrawArrays
(
GL10.GL_TRIANGLES,
0,
vCount
);
gl.glDisable(GL10.GL_TEXTURE_2D);//关闭纹理
}
}
CtlLifeDel类:
通过public void init(int life)方法来初始化特效显示的位置,输入当前生命值,根据生命值计算出即将要消除的星星所在的位置。、
public class CtlLifeDel extends CtlBase{
int mDeltaW = 0;
int mDeltaH = 0;
float mDeltaX = 0;
float mDeltaY = 0;
int mStep = 0;
int mKeep = 0;
int mPicId = 0;
int mGoodCnt = 0;
int mTimeCnt = 0;
public void run()
{
int maxW = 48;
int minW = 16;
int deltaW = 4;
int deltaH = 4;
float deltaY = 0.2f;
if(!mStop)
{
mTimeCnt++;
if (1 == (mTimeCnt %2))
{
mPicId++;
if (mPicId > 15) mPicId = 0;
}
if(0 == mStep)
{
mDeltaW += deltaW;
mDeltaH += deltaH;
mDeltaY = mDeltaY - deltaY;
if (mDeltaW >= maxW)
{
mStep = 1;
}
}
else if(1 == mStep)
{
mKeep++;
if(mKeep >= 30)
{
mKeep = 0;
mStep = 2;
}
}
else if(2 == mStep)
{
mDeltaW -= deltaW;
mDeltaH -= deltaH;
mDeltaY = mDeltaY + deltaY;
if (mDeltaW <= minW)
{
mStep = 3;
}
}
else if(3 == mStep)
{
mStop = true;
sendMsg();
}
}
}
public int getW()
{
return mDeltaW;
}
public int getH()
{
return mDeltaH;
}
public float getX()
{
return mDeltaX;
}
public float getY()
{
return mDeltaY;
}
public void init(int life)
{
if(!mStop) return;
mDeltaW = 0;
mDeltaH = 0;
//根据当前生命值,设定要消除的生命图案所在的位置
if(life > 3) mDeltaX = 5;
else if(3 == life) mDeltaX = 2;
else if(2 == life) mDeltaX = 3;
else if(1 == life) mDeltaX = 4;
mDeltaY = 10;
mStep = 0;
mPicId = 0;
super.start();
}
public int getPicId()
{
return mPicId;
}
public void sendMsg()
{
Message msg = new Message();
msg.what = ControlCenter.LIFEDEL_END;
ControlCenter.mHandler.sendMessage(msg);
}
}