Главная » Разработка для Windows Phone 7 » Два приложения, реализующие вращение текста

0

Завершим эту главу двумя приложениями, реализующими вращение текста.

Было бы довольно просто написать приложение, которое просто вращает текст вокруг центральной точки, но давайте попробуем сделать что-то более сложное. Давайте будем постепенно увеличивать скорость вращения и останавливать движение по касанию. После снятия касания вращение должно медленно возобновляться, опять же с постепенным ускорением. Когда количество оборотов в секунду достигает частоты обновления экрана (или какой-то целой его части), вращение текста должно замедляться, останавливаться и возобновляться в обратном направлении. Это будет выглядеть забавно.

Небольшое введение в работу с ускорением. Одним из самых часто встречающихся в повседневной жизни примеров ускорения движущихся объектов является свободное падение. В безвоздушном пространстве на поверхности Земли сила гравитации создает постоянное ускорение в 9,8 метра в секунду на секунду или, как чаще всего говорят, в секунду в квадрате:

а = 9,8 м/с2

Звучит странно: «метров в секунду на секунду». Но на самом деле это означает, что каждую секунду скорость увеличивается на 9,8 метра в секунду. В любой момент времени t скорость вычисляется по простой формуле:

v(t) = at

где a – это 9,8 метра на секунду в квадрате. Если умножить ускорение, выраженное в метрах на секунду в квадрате, на время в секундах, получим метры в секунду, что соответствует скорости. В 0 секунд скорость равна 0. В 1 секунду скорость составляет 9,8 метра в секунду. Через 2 секунды скорость уже будет 19,6 метров в секунду и т.д..

Расстояние, которое объект проходит в свободном падении, описывается уравнением:

X(t) =

Я назвал приложение TextCrawl (Ползущий текст). Поля нам уже знакомы: Проект XNA: TextCrawl Файл: Game1.cs (фрагмент, демонстрирующий поля)

public class Game1 : Microsoft.Xna.Framework.Game {

const float SPEED = 0.1f;                   // циклов в секунду

const string TEXT = "Hello, Windows Phone 7!";

GraphicsDeviceManager graphics; SpriteBatch spriteBatch; SpriteFont segoe14; Viewport viewport; Vector2 textSize; Vector2 textPosition;

float tCorner;                 // высота / периметр

float tLap; float angle;

}

При перемещении текста по периметру против часовой стрелки значение переменной tLap меняется от 0 до 1. Чтобы помочь в определении, на какой стороне находится текст в настоящий момент, я определил переменную tCorner (Угол). Если значение tLap меньше значения tCorner, текст располагается на левом краю экрана; если tLap больше tCorner, но меньше 0,5, текст внизу экрана, и т.д. В методе LoadContent нет ничего особенного:

Проект XNA: TextCrawl Файл: Game1.cs (фрагмент)

protected override void LoadContent() {

spriteBatch = new SpriteBatch(GraphicsDevice); viewport = this.GraphicsDevice.Viewport;

tCorner = 0.5f * viewport.Height / (viewport.Width + viewport.Height); segoe14 = this.Content.Load<SpriteFont>("Segoe14");

textSize = segoe14.MeasureString(TEXT);

Метод Update просто кошмарный, я его боюсь. Его задача – вычислить textPosition и angle для последующего вызова DrawString.

Проект XNA: TextCrawl Файл: Game1.cs (фрагмент)

protected override void Update(GameTime gameTime) {

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit ();

tLap = (tLap + SPEED * (float)gameTime.ElapsedGameTime.TotalSeconds) % 1;

if (tLap < tCorner)                    // вниз вдоль левой стороны экрана

{

textPosition.X = 0;

textPosition.Y = (tLap / tCorner) * viewport.Height; angle = -MathHelper.PiOver2;

if (textPosition.Y < textSize.X)

angle += (float)Math.Acos(textPosition.Y / textSize.X);

}

else if (tLap < 0.5f)                  // вдоль нижнего края экрана

{

textPosition.X = ((tLap – tCorner) / (0.5f – tCorner)) * viewport.Width; textPosition.Y = viewport.Height; angle = MathHelper.Pi;

if (textPosition.X < textSize.X)

angle += (float)Math.Acos(textPosition.X / textSize.X);

}

else if (tLap < 0.5f + tCorner) // вверх вдоль правой стороны экрана {

textPosition.X = viewport.Width;

textPosition.Y = (1 – (tLap – 0.5f) / tCorner) * viewport.Height; angle = MathHelper.PiOver2;

if (textPosition.Y + textSize.X > viewport.Height)

angle += (float)Math.Acos((viewport.Height – textPosition.Y) /

textSize.X); }

else                                   // вдоль верхнего края экрана

{

textPosition.X = (1 – (tLap – 0.5f – tCorner) / (0.5f – tCorner)) * viewport.Width;

textPosition.Y = 0; angle = 0;

if (textPosition.X + textSize.X > viewport.Width)

angle += (float)Math.Acos((viewport.Width – textPosition.X) /

textSize.X); }

base.Update(gameTime);

}

При написании этого кода, я сначала сосредоточился на обеспечении корректной работы первых трех выражений каждого блока if и else. Эти выражения просто обеспечивают перемещение верхнего левого угла строки текста против часовой стрелки по внутреннему периметру экрана. Исходное вычисление angle гарантирует, что верх текста вплотную прилегает к краю экрана. И только когда я добился того, чтобы все это работало, я был готов приступить к созданию кода, который обеспечивает изменение angle при огибании углов. Несколько простых рисунков убедили меня, что для этой работы прекрасно подойдет арккосинус. Несмотря на всю сложность Update, метод Draw абсолютно тривиальный:

Проект XNA: TextCrawl Файл: Game1.cs (фрагмент)

protected override void Draw(GameTime gameTime) {

GraphicsDevice.Clear(Color.Navy); spriteBatch.Begin();

spriteBatch.DrawString(segoe14, TEXT, textPosition, Color.White,

angle, Vector2.Zero, 1, SpriteEffects.None, 0);

spriteBatch.End(); base.Draw(gameTime);

}

В следующей главе мы рассмотрим, как перемещать спрайты вдоль кривых.

Источник: Чарльз Петзольд, Программируем Windows Phone 7, Microsoft Press, © 2011.

По теме:

  • Комментарии