تفاعلات اللمس في تطوير اللعبة ل Windows Phone 7 Part 4 Pinch

تحديث الصفحة :
تاريخ إنشاء الصفحة :

برمجة! - 4.Pinch، تمتد إلى العفاريت على نطاق واسع

حول هذا النموذج

تسمح لك الهواتف الذكية الحديثة، مثل عارضي الصور، بتكبير الصورة وتقلصها باستخدام إصبعين لزيادة المسافة بين أصابعك أو تقليصها. يمكنك أن تفعل الشيء نفسه مع إنترنت إكسبلورر على ويندوز فون 7. يسمى هذا الإجراء "قرصة، تمدد" في Windows Phone 7.

بالإضافة إلى القرص والتمدد ، يمكنك أيضا استخدام إجراءات مثل "النقر" للمس لفترة وجيزة (النقر) نقطة واحدة على الشاشة و "النقر" لتتبع الشاشة بسرعة. ويشار إلى هذه الإجراءات مجتمعة باسم الإيماءات.

في هذا البرنامج ، أود تكبير وتقليل العفريت المعروض على الشاشة من خلال عملية الضغط والتمدد هذه. أيضا ، حتى المرة الأخيرة ، حصلت مباشرة على معلومات لوحة اللمس ومعالجتها ، ولكن هذه المرة أود التعامل مع عمليات اللمس باستخدام طرق مخصصة للإيماءات.

أهداف هذا البرنامج النموذجي

عمليات الضغط والتمدد لتكبير العفريت وتقلصه.

図 1 :ストレッチでスプライトを拡大
الشكل 1: تمدد لتكبير العفريت

البرنامج - إعلان الحقول

لا توجد فئة جديدة في الإعلان الميداني ، ولكنها تحتوي على "الإحداثيات المركزية للملمس" ، و "تكبير العفريت" ، و "المسافة بين آخر موقعين لللمس عند القرص".

/// <summary>
/// テクスチャー
/// </summary>
Texture2D texture;

/// <summary>
/// テクスチャーの中心座標
/// </summary>
Vector2 textureCenterPos;

/// <summary>
/// スプライトのスケール
/// </summary>
float scale = 1;

/// <summary>
/// 前回の 2 点間の距離
/// </summary>
float previousLength = 0;

البرنامج - تمكين الإيماءات

هذه المرة ، سنقوم بإجراء عملية إيماءات فقط ، ولكن في الحالة الافتراضية ، لا يمكن استخدام أي من الإيماءات. لاسترداد كل معلومات الإيماءة، يجب تعيين الإيماءة لاستخدامها في الخاصية TouchPanel.EnabledGestures.

// タッチパネルでピンチのジェスチャーを有効にする
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. تتم معالجة الإيماءات في شكل تكرار أكبر عدد ممكن من الإيماءات. لا يتم استخدام بنية "TouchCollection" التي تم استخدامها حتى آخر مرة.

// 次のジェスチャー情報が取得できる場合は true を返し続けます
while (TouchPanel.IsGestureAvailable)
{
  // 次のジェスチャー情報を読み込みます
  GestureSample gs = TouchPanel.ReadGesture();
  
  switch (gs.GestureType)
  {
    case GestureType.Pinch:
      // ここにピンチ処理を記述します
      break;
    case GestureType.PinchComplete:
      // ここにピンチ完了処理を記述します
      break;
  }
}

تحقق من حالة الخاصية TouchPanel.IsGestureAvailable في الحلقة أثناء البحث عن معلومات الإيماءة وتحقق مما إذا كانت معلومات الإيماءة التالية موجودة: إذا كانت لديك معلومات الإيماءة التالية ، فاستخدم طريقة "TouchPanel.ReadGesture" للحصول على معلومات الإيماءات.

يخزن "GestureSample.GestureType" معلومات حول نوع الإيماءة المضمن، لذا قم بتفرع العملية باستخدام عبارة تبديل تستند إليها. في هذا النموذج، يقوم المنشئ بتعيين التسميات "GestureType.Pinch" و "GestureType.PinchComplete" إلى الخاصية "TouchPanel.EnabledGestures"، بحيث تكون متفرعة على التوالي.

البرنامج - التعامل مع إيماءات الضغط

من الأسرع النظر إلى التعليقات في التعليمات البرمجية لمعرفة ما نقوم به، ولكن لتلخيص ما نقوم به، نجد الفرق بين المسافة بين نقطتي الاتصال السابقتين ومسافة نقطة الاتصال بين النقطتين هذه المرة، ونستخدم هذا الفرق لزيادة قيمة المقياس أو تقليلها.

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 Game Studio 4.0 لإدخالات GestureType.

يمكنك تنفيذ نفس الشيء من معلومات اللمس التي تم الحصول عليها من طريقة TouchPanel.GetState دون استخدام طرق أو هياكل خاصة بالإيماءات ، ولكن في هذه الحالة ، ستحتاج إلى حساب سرعة إدارة معرف اللمس المتعدد ، ووقت اللمس ، والنقرات ، وما إلى ذلك بنفسك. باستخدام أساليب خاصة بالإيماءات ، يمكن تبسيط هذه التطبيقات ، وهناك أيضا ميزة أنه يمكن تشغيل جميع الألعاب والتطبيقات بنفس الطريقة.

عند إنشاء عملية لوحة لمس بنفسك، إذا كان بإمكانك استبدال عملية مماثلة كإيماءة، فإننا نوصي باستخدام ذلك.

برمجة! - 5.Pinch لتدوير العفاريت

حول هذا النموذج

يشير القرص عادة إلى "القرص" و "التمدد" ، لكن عملية الضغط في XNA Game Studio 4.0 لا تقصر العملية على وجه التحديد على هذين الاثنين ، لذلك يمكنك أيضا إجراء عمليات تدور حول نقطة اتصال واحدة حول نقطة اتصال أخرى.

هنا ، أود تدوير العفريت باستخدام طريقة التشغيل هذه. بالمناسبة ، لم تظهر طرق أو فئات جديدة هذه المرة ، وهي تستند إلى القياس السابق.

في وصف نموذج التعليمة البرمجية في هذه المقالة، يتم حذف نفس الأجزاء مثل نموذج القياس السابق.

أهداف هذا البرنامج النموذجي

من خلال تدوير نقطتي الاتصال ، يدور العفريت. تعمل عملية التحجيم السابقة أيضا.

図 2 :タッチポイントを回してスプライトを回転させています
الشكل 2: تدوير العفريت عن طريق تدوير نقطة الاتصال

البرنامج - إعلان الحقول

تتم إضافة "مقدار دوران العفريت" و "زاوية الدوران الأخيرة" إلى برنامج التحجيم السابق. يتم حساب جميع الزوايا بالراديان.

/// <summary>
/// スプライトの回転量(radian)
/// </summary>
float rotate;

/// <summary>
/// 前回の回転角度(radian)
/// </summary>
float previousAngle;

البرنامج - عملية التناوب

يتم تنفيذ عملية الدوران أثناء إيماءات الضغط بنفس الطريقة التي يتم بها إجراء عملية القياس.

لن أخوض في الكثير من التفاصيل حول حساب الدوران لأنها قصة رياضيات ، ولكن يمكنك الحصول على زاوية راديان باستخدام طريقة "Math.Atan2" عن طريق إيجاد متجه الفرق من نقطة الاتصال 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 Phone 7 و XNA Game Studio 4.0. وتضمن المحتوى الحصول على معلومات اللمس باللمس الأحادي واللمس المتعدد والتلاعب بها، ومعالجتها عن طريق معالجة إيماءات اللمس باستخدام أساليب خاصة بالإيماءات.

هذه المرة ، ركزت على لوحة اللمس ، ولكن لا تزال هناك بعض الوظائف التي لم أقدمها بعد. يتضمن Windows Phone 7 أيضا ميزات إدخال جديدة في XNA Game Studio 4.0، مثل إدخال مقياس التسارع وإدخال الصوت. هناك بعض الميزات المثيرة للاهتمام التي لم أتمكن من تقديمها هذه المرة ، لذا يرجى الاستمتاع باستكشاف الوظائف التي تريد استخدامها.