【課程內容】
今天我們將介紹用戶交互技術--屏幕拾取技術,並設計控制中心類,實現更復雜的控制邏輯。
【源代碼下載地址】http://download.csdn.net/detail/elong_2009/6455097
前面幾天的課程,我們實驗了幾種渲染的技術,這些技術是後續開發的基礎。今天我們將研究用戶交互的技術,以實現與用戶的互動。
1、屏幕拾取技術
在OpenGL ES的開發環境下,可以利用的屏幕拾取技術有很多種,如顏色拾取、射線相交等。但是這些技術對於我們正在山寨的應用來說,顯得過於複雜了。基於應用特定的需求,我們不需要使用複雜的技術就能夠完成屏幕拾取。
從技術角度來說,簡單就是美,能夠滿足需求就是好的。對於基於棋盤佈局的消除遊戲,每個可觸碰對象的座標範圍是可以預測的,因此我們決定採用最簡單的屏幕座標定位技術。
對於更復雜的場景,如對象座標是隨時改變或不能簡單預測的,或者對象表面是不規則形狀的,需要採用其它更復雜的屏幕拾取技術。如果有緣,你們會在筆者另外一個作品《教你玩魔方》中看到這種技術的介紹,合適的時候,我會向大家詳細介紹這種技術。目前這種技術在網絡上可參考的示例還不是太多。
2、ScreenTouch 類
我們設計了屏幕拾取ScreenTouch 類來獲取用戶正在操作的對象,如果用戶的操作是有效的,將通過RaiseTouchEvent 方法產生一個事件,用消息的方式通知控制中心ControlCenter處理該動作。
//產生有效的觸摸事件,發消息給mHandler統一處理
void RaiseTouchEvent()
{
if(!isValidTouch()) //校驗動作是否合法
return;
Toast.makeText(mContext, "Direction:" + getDirection() + " (" + getGridX() + " ," + getGridY() + ")",
Toast.LENGTH_SHORT).show();
Bundle b = new Bundle();
b.putInt("col1", getGridX());
b.putInt("row1", getGridY());
b.putInt("col2", getNeighborX());
b.putInt("row2", getNeighborY());
Message msg = new Message();
msg.what = ControlCenter.EXCHANGE_START;
msg.setData(b);
ControlCenter.mHandler.sendMessage(msg);
}
每個touch事件必定會觸發一個交換動作,因此我們向mHandler發送的消息類型定義爲EXCHANGE_START。
ScreenTouch 類提供了一個公有的方法供CrazyLinkGLSurfaceView.onTouchEvent()方法調用
public boolean Touch(MotionEvent e);
3、控制中心ControlCenter 類設計
到目前爲止,我們已經有了若干個渲染類DrawXxx,渲染動態控制效果類CtlXxx以及用戶交互類ScreenTouch。現在,需要把這些獨立的功能組合起來。
從本節開始,我們開始設計遊戲的邏輯算法類ControlCenter ,該類包含在 package elong.CrazyLink.Core中,後續各種遊戲邏輯控制算法,都會放在這個包下面。
我們將前面課程的代碼進行了少量的修改,以便適合新邏輯。
(1)將紋理操作、渲染對象、渲染動態控制對象等從CrazyLinkGLSurfaceView 移除,取而代之是一個static ControlCenter controlCenter;對象
(2)將紋理操作、渲染對象、渲染動態控制對象等移到ControlCenter 類中。
(3)DrawLoading、DrawExchang 對象根據特定事件動作來創建,不需要在初始化時就創建好。
(4)增加了消息處理的機制。mHandler.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");
mInExchange[col1][row1] = true; //處於交換狀態
mInExchange[col2][row2] = true;
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;
mInExchange[col1][row1] = false; //交換狀態解除
mInExchange[col2][row2] = false;
control.exchange = null;
drawExchange = null;
break;
}
case LOADING_START: //加載動作開始
drawLoading = new DrawLoading(loadingTextureId); //創建加載動畫素材
control.loading = drawLoading.control;
case LOADING_END: //加載動作結束
control.loading = null;
drawLoading = null;
break;
}
}
};
最後的效果如下,瘋狂消除的雛形已經初現了!
用手指在屏幕上滑動,已經可以實現交換的效果了。在下節,我們將完整實現一個遊戲用到的全部基本特效。