Сенсорное взаимодействие в разработке игр для Windows Phone 7, часть 4

Страница обновлена :
Дата создания страницы :

Программирование! - 4.Пинч, растягивание для масштабирования спрайтов

Об этом примере

Современные смартфоны, такие как просмотрщики изображений, позволяют увеличивать и сжимать изображение с помощью двух пальцев, чтобы увеличить или уменьшить расстояние между пальцами. То же самое можно сделать с помощью Internet Explorer на Windows Phone 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" - для указания на завершение процесса сжатия. Местоположение настройки задается в конструкторе Game.

Программа - Загрузка текстур

Загрузка текстур такая же, как и раньше, но на этот раз мы вычисляем «центральную координату текстуры». Это связано с тем, что при масштабировании спрайта он масштабируется с центральной координатой в качестве начала координат.

// テクスチャーをコンテンツパイプラインから読み込む
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 в цикле while на наличие сведений о жестах и проверьте, присутствуют ли следующие сведения о жестах: Если у вас есть следующие сведения о жестах, используйте метод "TouchPanel.ReadGesture", чтобы получить сведения о жесте.

"GestureSample.GestureType" хранит информацию о том, какой тип жеста включен, поэтому разветвляйте процесс с помощью оператора switch на его основе. В этом примере конструктор задает перечислениям "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 без использования методов или структур, специфичных для жестов, но в этом случае вам нужно будет самостоятельно рассчитать скорость управления идентификаторами multi-touch, время касания, пролистывание и т. Д. Используя методы, специфичные для жестов, эти реализации могут быть упрощены, а также преимущество в том, что все игры и приложения могут работать одинаково.

Когда вы создаете процесс сенсорной панели самостоятельно, если вы можете заменить аналогичный процесс в качестве жеста, мы рекомендуем вам использовать его.

Программирование! - 5.Сжатие для вращения спрайтов

Об этом примере

Сжатие обычно относится к «сжатию» и «растяжению», но процесс сжатия 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, такие как акселерометрический ввод и голосовой ввод. Есть некоторые интересные функции, которые я не смог представить на этот раз, поэтому, пожалуйста, наслаждайтесь изучением функций, которые вы хотите использовать.