觸摸操作在Windows手機7遊戲開發第4部分捏
程式設計! - 4. 捏合,通過拉伸縮放子畫面
關於此範例
在現代智能手機上,您可以使用兩個手指(如圖像查看器)來放大和縮小手指之間的間距。 您可以在 Windows 電話 7 附帶的互聯網資源管理器中執行相同的操作。 在 Windows 電話 7 中,這稱為「捏合、拉伸」。。
除了捏合和拉伸操作外,還有“點擊”(輕擊)或“輕拂”以快速跟蹤螢幕。 這些操作統稱為「手勢」。
在這個程式中,我想通過捏和拉伸來放大和縮小螢幕上可見的子畫面。 此外,直到上次,我們直接獲取觸摸屏資訊並進行處理,但這次我想使用手勢專用方法處理觸摸操作。
此示例程序的目標
捏合和拉伸操作可放大和縮小子畫面。
圖 1:拉伸以放大子畫面
程式 - 聲明欄位
欄位聲明中沒有新類,但我們希望它具有紋理的中心座標、子畫面的放大率和捏合操作前兩個觸摸位置之間的距離。
<summary>
テクスチャー
</summary>
Texture2D texture;
<summary>
テクスチャーの中心座標
</summary>
Vector2 textureCenterPos;
<summary>
スプライトのスケール
</summary>
float scale = 1;
<summary>
前回の 2 点間の距離
</summary>
float previousLength = 0;
程式 - 啟用手勢
這一次,我們將只處理手勢,但在默認狀態下,我們無法使用任何手勢。 若要獲取每個手勢資訊,必須設置用於「觸控面板.啟用 Gestures」屬性的手勢。
// タッチパネルでピンチのジェスチャーを有効にする
TouchPanel.EnabledGestures = GestureType.Pinch | GestureType.PinchComplete;
由於啟用所有手勢會影響性能,因此請確保僅設置要使用的手勢。 在這裡,我們設置“GestureType.Pinch”以獲取捏合操作的資訊,並設置“GestureType.PinchComplete”,指示捏合過程已完成。 設置位置在遊戲構造函數中設置。
程式 - 載入紋理
紋理導入與以往沒有什麼不同,但這次我們計算了紋理的中心座標。 在縮放子畫面時,將中心座標縮放為原點。
// テクスチャーをコンテンツパイプラインから読み込む
texture = Content.Load<Texture2D>("Texture");
// テクスチャーの中心座標を求める
textureCenterPos = new Vector2(texture.Width / 2, texture.Height / 2);
程式 - 獲取手勢資訊
在 Game.Update 方法中獲取手勢資訊(此處為捏合)。 手勢處理是一種形式,您可以重複您啟用的手勢數。 我們不會使用以前使用的“觸摸收集”結構。
// 次のジェスチャー情報が取得できる場合は true を返し続けます
while (TouchPanel.IsGestureAvailable)
{
// 次のジェスチャー情報を読み込みます
GestureSample gs = TouchPanel.ReadGesture();
switch (gs.GestureType)
{
case GestureType.Pinch:
// ここにピンチ処理を記述します
break;
case GestureType.PinchComplete:
// ここにピンチ完了処理を記述します
break;
}
}
手勢資訊在 while 循環中檢查「觸控面板.可訪問」屬性的狀態,並檢查是否存在以下手勢資訊: 使用「觸摸面板.ReadGesture」方法獲取手勢資訊(如果有),包括:
“GestureSample.GestureType”存儲包含哪些手勢類型的資訊,並基於這些類型在開關語句中分支處理。 在此示例中,在構造函數中,在「觸摸面板.啟用 Gestures」屬性中設置了“Gesture 類型.Pinch”和“GestureType.PinchComplete”枚舉類型,因此我們分別分支了該枚舉。
程式 - 處理捏合手勢
看到代碼註釋時,我們越早看到操作,我們就越容易總結我們在做什麼,我們計算了前兩個點之間的接觸點距離與兩個接觸點之間的距離之間的差異,並根據差異增加或減少比例值。
case GestureType.Pinch:
// 現在の2点間の距離を求めます
float nowLength = (gs.Position - gs.Position2).Length();
if (previousLength == 0)
{
// 前回の2点間の距離が 0 の場合は
// 現在の2点間の距離を設定します
// 初回はスケール計算を行いません
previousLength = nowLength;
}
else
{
// 前回の2点間の距離との差分を計算します
float diffLength = nowLength - previousLength;
// ピンチ、ストレッチした距離に応じて
// スケールを変化させています
// 補正値は適当に設定します
scale = MathHelper.Max(scale + diffLength / 150, 0);
// 今回の距離を次の計算のために保持します
previousLength = nowLength;
}
break;
兩個觸摸位置可以分別在“GestureSample.Position”和“GestureSample.Position2”中獲取。 通過減去兩個獲得的向量,可以求和差異,然後調用 Vector2.Length 方法來確定兩點之間的距離。
順便說一下,當我們不執行捏合時,我們定義了上一個距離0,因此,在開始捏合處理時,我們將在第二個和後續迴圈中分支處理。 因為第一次捏合時沒有上次的距離,因此無需縮放。
此外,這一次,我們只使用兩個屬性“GestureSample.Position”和“GestureSample.Position2”,但還有其他屬性“GestureSample.Delta”和“GestureSample.Delta2”屬性,您可以在這裡獲取與上次觸摸位置的差異資訊。 每個屬性各提供兩個屬性,用於多點觸控,對於僅使用單點觸摸的手勢,請使用不帶“2”的屬性。
程式 - 捏合手勢完成時的處理
當捏合手勢完成時(當任一手指從觸摸屏上鬆開時),前兩個點之間的距離將恢復為0。 最初,最好單獨使用標誌,但物理上不可能用兩根手指觸摸同一位置,因此,在距離為0時,我們將其定義為不執行捏合。 (如果解析度較低,則可能觸摸同一位置。)
case GestureType.PinchComplete:
// ピンチが終了した場合は保持している距離を 0 に戻して
// 完了したことにします
previousLength = 0;
break;
程式 - 繪製子畫面
由於這隻是子畫面的繪製內容,因此不會詳細介紹它,但我們將子畫面放在螢幕的中心,並將計算的比例值作為子畫面的中心作為原點進行縮放和繪製。
// スプライトの描画準備
spriteBatch.Begin();
// スプライトを描画する
spriteBatch.Draw(texture,
new Vector2(graphics.PreferredBackBufferWidth / 2,
graphics.PreferredBackBufferHeight / 2),
null,
Color.White,
0.0f,
textureCenterPos,
scale,
SpriteEffects.None,
0.0f);
// スプライトの一括描画
spriteBatch.End();
此示例摘要
這一次,我們討論了手勢專用處理。 示例僅創建捏合,但還有其他「輕拂」和“保持”。 有關手勢類型的資訊,請參閱 XNA 遊戲工作室 4.0 説明中的“GestureType 枚舉”。
即使不使用手勢專用方法或結構,也可以從 TouchPanel.GetState 方法獲取的觸摸資訊中實現類似的實現,但在這種情況下,您需要自行計算多點觸控 ID 管理、觸摸時間、輕拂等速度。 通過使用僅手勢方法,可以簡化這些實現,並且任何遊戲或應用程式都可以以相同的方式操作。
如果您自己創建觸控螢幕處理,並且可以使用類似的操作替換手勢,則最好使用此方法。
程式設計! - 5. 在捏合過程中旋轉子畫面
關於此範例
通常,捏合是指“捏合”和“拉伸”,但 XNA Game Studio 4.0 的捏合操作並不特別局限於這兩個操作,因此您可以在一個接觸點周圍執行另一個接觸點周圍的操作。
在這裡,我想旋轉子畫面的方式。 順便說一下,這次沒有出現任何新方法或類,而是基於以前的縮放進行應用。
此範例代碼中的說明與上一個縮放範例相同。
此示例程序的目標
通過旋轉兩個接觸點,子畫面將旋轉。 以前的縮放過程也同時工作。
圖 2:旋轉接觸點以旋轉子畫面
程式 - 聲明欄位
為上一個縮放程式添加了「子畫面旋轉量」和「上一個旋轉角度」。 所有角度均以弧度計算。
<summary>
スプライトの回転量(radian)
</summary>
float rotate;
<summary>
前回の回転角度(radian)
</summary>
float previousAngle;
程式 - 旋轉處理
旋轉過程在捏合手勢時完成,就像縮放時一樣。
旋轉計算是數學問題,因此不太詳細,但您可以使用Math.Atan2方法獲取radian的角度,以獲得從接觸點1到接觸點2的差分向量。 獲取獲取的角度與上次獲取的角度之間的差異,並添加到子畫面的旋轉角度。
switch (gs.GestureType)
{
case GestureType.Pinch:
//===== スケール計算 =====//
// 前回と同じなので省略
//===== 回転計算 =====//
// 2点間のベクトルを求めます
Vector2 pinchVector = gs.Position2 - gs.Position;
// Atan2 で角度を求めます
float nowAngle = (float)Math.Atan2(pinchVector.Y,
pinchVector.X);
if (previousAngle == 0)
{
// 前回の角度が 0 の場合は
// 現在の角度を設定します
// 初回は回転計算を行いません
previousAngle = nowAngle;
}
else
{
// 前回の角度との差分をスプライトの回転角度に加算します
rotate += nowAngle - previousAngle;
// 今回の距離を次の計算のために保持します
previousAngle = nowAngle;
}
break;
case GestureType.PinchComplete:
// ピンチが終了した場合は保持している距離、角度を 0 に戻して
// 完了したことにします
previousLength = 0;
previousAngle = 0;
break;
}
程式 - 繪製子畫面
繪製子畫面沒有重大更改。 將計算的旋轉角度設置為SpriteBacth.Draw方法的第五個參數。
// スプライトの描画準備
spriteBatch.Begin();
// スプライトを描画する
spriteBatch.Draw(texture,
new Vector2(graphics.PreferredBackBufferWidth / 2,
graphics.PreferredBackBufferHeight / 2),
null,
Color.White,
rotate,
textureCenterPos,
scale,
SpriteEffects.None,
0.0f);
// スプライトの一括描画
spriteBatch.End();
此示例摘要
這一次,我試圖通過捏操作旋轉子畫面。 我沒有使用任何新的類,但您可能已經知道,根據提供的功能,可以應用它們。
最後
在演示示例時,我們討論了使用 Windows 電話 7 和 XNA 遊戲工作室 4.0 實現觸摸交互。 內容包括單點觸控、多點觸控觸摸資訊的獲取和操作,以及使用特定於手勢的方法的觸摸手勢操作。
這一次,我們專注於觸摸屏,但仍有一些功能尚未介紹。 在 Windows Phone 7 中,XNA 遊戲工作室 4.0 中新增的輸入功能包括加速度計輸入和語音輸入。 功能,不能完全介紹這一次,因為有一個有趣的功能,請享受檢查的功能,你想使用。