【课程内容】设计消除特效及跌落特效,并完善游戏控制算法。
【源代码下载地址】http://download.csdn.net/detail/elong_2009/6455119
1、消除特效DrawDisappear
根据游戏规则,三个动物连成一行时,就会触发消除特效。
我们设计的消除特效是动物闪动几次后消失。当然,你也可以设计出更炫的效果来。
public void draw(GL10 gl, int witch, int col, int row)
{
if(0 == control.getCount() % 2) //这里实现闪动
{
gl.glPushMatrix();
drawAnimal.draw(gl, witch, col, row);
gl.glPopMatrix();
}
}
与DrawExchange类似,DrawDisappear也直接利用了DrawAnimal渲染类。
2、跌落特效DrawFill
当动物消除后,就会触发跌落特效,如果是纵向消除,那么就会连续触发跌落特效,直到所有格子都已经重新填充好动物。跌落完成后,会检测是否需要消除,如果是,又会触发消除特效,周而复始。
public void draw(GL10 gl, int witch, int col, int row)
{
gl.glPushMatrix();
gl.glTranslatef(0f, control.getY()*CrazyLinkConstent.translateRatio, 0f);
drawAnimal.draw(gl, witch, col, row);
gl.glPopMatrix();
}
同样,DrawFill也直接利用了DrawAnimal渲染类。
3、消除检测算法
消除的规则是三个或以上的同类动物连在一起,就会发生消除动作。我们将消除算法分解为X方向检测及Y方向检测,下面以X方向算法为例:
static boolean isInLineX(int col, int row)
{
int picId = mPic[col][row];
if(0 == col)
{
if(picId == mPic[col+1][row] && picId == mPic[col+2][row])
{
return true;
}
}
else if(1 == col)
{
if((picId == mPic[col-1][row] && picId == mPic[col+1][row])
|| (picId == mPic[col+1][row] && picId == mPic[col+2][row]))
{
return true;
}
}
else if(col > 1 && col < 5)
{
if((picId == mPic[col-2][row] && picId == mPic[col-1][row])
|| (picId == mPic[col-1][row] && picId == mPic[col+1][row])
|| (picId == mPic[col+1][row] && picId == mPic[col+2][row]))
{
return true;
}
}
else if(5 == col)
{
if((picId == mPic[col-2][row] && picId == mPic[col-1][row])
|| (picId == mPic[col-1][row] && picId == mPic[col+1][row]))
{
return true;
}
}
else if(6 == col)
{
if(picId == mPic[col-1][row] && picId == mPic[col-2][row])
{
return true;
}
}
return false;
}
Y方向的检测方法略。
综合XY方向检测,就可以得到完整的消除检测算法:
//消除检测算法
static boolean isInLine(int col, int row)
{
return isInLineX(col, row) || isInLineY(col, row);
}
4、跌落算法
当消除特效完成后,将对应的格子置为0,跌落算法检测到有0的格子,就会将其上方的格子跌落;如果消除的格子是最高的那一行,则随机产生跌落动物。
//跌落算法
static void fillPic()
{
for(int i = 0; i < (int)CrazyLinkConstent.GRID_NUM; i++)
{
for(int j = 0; j < (int)CrazyLinkConstent.GRID_NUM; j++)
{
if(0 == mPic[i][j]) //0代表该格子是空的,需要跌落
{
if(j < (int)CrazyLinkConstent.GRID_NUM - 1)
{
//从上一行中跌落
mPic[i][j] = mPic[i][j + 1];
mPic[i][j + 1] = 0;
}
else
{
//如果消除的是最高的一行,则随机产生跌落动物
mPic[i][j] = getRandom();
}
}
}
}
}
5、游戏控制主逻辑
我们的游戏逻辑是通过消息来控制的,我们定义如下消息类型:
public static final int EXCHANGE_START = 1;
public static final int EXCHANGE_END = 2;
public static final int LOADING_START = 3;
public static final int LOADING_END = 4;
public static final int DISAPPEAR_END = 5;
public static final int FILL_END = 6;
游戏控制逻辑通过handleMessage 来处理。丰富这个方法的处理,就可以得到更复杂的控制逻辑。
//消息处理
public static Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg)
{
// process incoming messages here
switch(msg.what)
{
case EXCHANGE_START:
{
Bundle b = msg.getData();
int col1 = b.getInt("col1");
int col2 = b.getInt("col2");
int row1 = b.getInt("row1");
int row2 = b.getInt("row2");
mStatus[col1][row1] = 2; //处于交换状态
mStatus[col2][row2] = 0;
drawExchange = new DrawExchange(drawAnimal, mPic[col1][row1], col1, row1, mPic[col2][row2], col2, row2);
control.exchange = drawExchange.control;
break;
}
case EXCHANGE_END:
{
Bundle b = msg.getData();
int col1 = b.getInt("col1");
int col2 = b.getInt("col2");
int row1 = b.getInt("row1");
int row2 = b.getInt("row2");
int picId = mPic[col1][row1];
mPic[col1][row1] = mPic[col2][row2];
mPic[col2][row2] = picId;
mStatus[col1][row1] = 1; //交换状态解除
mStatus[col2][row2] = 1;
control.exchange = null;
drawExchange = null;
markInLine();
break;
}
case LOADING_START:
drawLoading = new DrawLoading(loadingTextureId); //创建加载动画素材
control.loading = drawLoading.control;
break;
case LOADING_END:
control.loading = null;
drawLoading = null;
mIsLoading = false;
break;
case DISAPPEAR_END:
clearPic();
clearInline();
markFill();
break;
case FILL_END:
if(isNeedFill())
{
markFill();
}
else
{
if(isNeedClear())
{
markInLine();
}
}
break;
}
}
};
本节的运行效果如下,显示游戏加载界面:
然后是游戏主界面,这时候已经完成交换、消除、跌落的特效。
自此,一个游戏的基本雏形已经基本完成。