Опубликован: 01.11.2011 | Доступ: свободный | Студентов: 1425 / 63 | Оценка: 3.84 / 3.44 | Длительность: 15:38:00
Специальности: Программист
Практическая работа 10:

Обработка простого касания в XNA

Аннотация: Мультисенсорный экран устройств, поддерживающих Windows Phone 7, может распознавать касание как минимум в четырех точках. В XNA сенсорный ввод реализуется через статический класс TouchPanel (сенсорная панель), опрашиваемый в ходе выполнения метода update. На данном практическом занятии мы познакомимся с возможностями класса TouchPanel (сенсорная панель).

Дополнительные материалы к занятию можно скачать здесь.

В XNA устройства мультисенсорного ввода называют сенсорной панелью. Для обработки такого ввода используются методы статического класса TouchPanel (Сенсорная панель). Имеется также возможность обработки жестов, но пока начнем с более простыми данными касания. Можно (но это не является обязательным) получать сведения о самом устройстве мультисенсорного ввода через вызов статического метода TouchPanel.GetCapabilities. Объект TouchPanelCapabilities (Возможности сенсорной панели), возвращаемый этим методом, имеет два свойства [25]:

  • IsConnected (Подключен) имеет значение true, если сенсорная панель доступна. Для телефона его значение всегда true [25].
  • MaximumTouchCount (Максимальное число касаний) возвращает количество точек касания, как минимум 4 для телефона [25].

Для большинства задач достаточно использовать один из двух статических методов TouchPanel. Для получения ввода от простого касания при каждом вызове Update после запуска программы, скорее всего, будет вызываться этот метод:

TouchCollection touchLocations = TouchPanel.GetState();
    

TouchCollection (Коллекция касаний) - это коллекция, включающая нуль или более объектов TouchLocation (Место касания). TouchLocation имеет три свойства:

  • State (Состояние), его значениями являются элементы перечисления TouchLocationState (Состояние места касания): Pressed (Нажат), Moved (Перемещен), Released (Высвобожден).
  • Position (Местоположение) - это Vector2, обозначающий положение пальца относительно верхнего левого угла окна просмотра [25].
  • Id - целое число, идентифицирующее отдельное касание от состояния Pressed до Released, то есть в течение всего времени касания [25].

Если ни один палец не касается экрана, коллекция TouchCollection пуста. Когда палец впервые касается экрана, в TouchCollection появляется объект, свойство State которого имеет значение Pressed. Последующие вызовы TouchPanel.GetState покажут, что значение State объекта TouchLocation равно Moved, даже если фактически палец никуда не перемещался. Когда палец будет убран с экрана, свойство State объекта TouchLocation примет значение Released [25].

Последующие вызовы TouchPanel.GetState продемонстрируют, что коллекция TouchCollection опять пуста [25].

Единственное исключение, если палец быстро "постукивает" по экрану - т.е. поднимается и опускается на экран с частотой примерно 1/30 секунды - свойство State объекта TouchLocation от значения Pressed сразу перейдет к значению Released, минуя состояния Moved [25].

Как правило, экрана будут касаться множество пальцев; и опускаться, перемещаться и покидать экран они будут независимо друг от друга.

Для отслеживания отдельного касания используется свойство Id (Идентификатор). Для одного отдельно взятого касания Id будет неизменным от состояния Pressed, на протяжении всех перемещений (значения Moved) и до состояния Released [25].

Части при работе с простым касанием используется объект Dictionary (Словарь) с ключами, созданными на основании свойства Id, для извлечения данных конкретного касания [25].

TouchLocation также имеет очень удобный метод TryGetPreviousLocation (Попытаться получить предыдущее местоположение), который вызывается следующим образом:

TouchLocation previousTouchLocation;
bool success = touchLocation.TryGetPreviousLocation(out previousTouchLocation);
    

Вызов этого метода практически всегда происходит, когда touchLocation.State имеет значение Moved, для получения предыдущего местоположения и вычисления разницы. Если значение touchLocation.State равно Pressed, TryGetPreviousLocation возвратит false, и значением previousTouchLocation.State будет элемент перечисления TouchLocationState.Invalid. Такие же результаты будут получены в случае вызова этого метода для TouchLocation, который был возвращен TryGetPreviousLocation [25].

В данной работе за основу мы взяли пример, описанный в книге Ч. Петзолда "Программирование Windows Phone 7". Мультисенсорный экран устройств, поддерживающих Windows Phone 7, может распознавать касание как минимум в четырех точках. В XNA сенсорный ввод реализуется через статический класс TouchPanel (сенсорная панель), опрашиваемый в ходе выполнения метода update. На данном практическом занятии мы познакомимся с возможностями класса TouchPanel (сенсорная панель). При загрузке приложения на экране появляется надпись Click Me! Функция Update отслеживает нажатия пользователя. Если щелкнуть мышкой по надписи, то ее текст изменится. На экране появится сообщение - You've clicked!

Итак, создаем приложение XNA Windows Phone 7. Назовем проект p10. Далее, добавим к проекту шрифт Lindsey:

<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
  <Asset Type="Graphics:FontDescription">
    <FontName>Lindsey</FontName>
    <Size>72</Size>
    <Spacing>0</Spacing>
    <UseKerning>true</UseKerning>
    <Style>Bold</Style>
    <CharacterRegions>
      <CharacterRegion>
        <Start>&#32;</Start>
        <End>&#126;</End>
      </CharacterRegion>
    </CharacterRegions>
  </Asset>
</XnaContent>
    

Затем внесем изменения в файл Game1.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace WindowsPhoneGame7
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Random rand = new Random();
        string text = "Click Me!";
        SpriteFont Lindsey;
        Vector2 textSize;
        Vector2 textPosition;
        Color textColor = Color.White;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            TargetElapsedTime = TimeSpan.FromTicks(333333);
        }
        protected override void Initialize()
        {
            base.Initialize();
        }
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Lindsey = this.Content.Load<SpriteFont>("Lindsey");
            textSize = Lindsey.MeasureString(text);
            Viewport viewport = this.GraphicsDevice.Viewport;
            textPosition = new Vector2((viewport.Width - textSize.X) / 2,
            (viewport.Height - textSize.Y) / 2);
        }
        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            TouchCollection touchLocations = TouchPanel.GetState();
            foreach (TouchLocation touchLocation in touchLocations)
            {
                if (touchLocation.State == TouchLocationState.Pressed)
                {
                    text = "You've clicked!";
                    Vector2 touchPosition = touchLocation.Position;
                    textColor = new Color((byte)(100), (byte)(50),(byte)(20));
                }
            }
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            this.GraphicsDevice.Clear(Color.Coral);
            spriteBatch.Begin();
            spriteBatch.DrawString(Lindsey, text, textPosition, textColor);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}
    
Листинг .

Результат:


Нажмем мышкой на надпись. Текст изменится.