netlib.narod.ru | < Назад | Оглавление | Далее > |
Теперь у вас установлены и настроены все необходимые утилиты, так что пришло время запачкать руки кодированием. В данном разделе вы создадите простой проект с помощью шаблонов XNA Studio. Затем вы слегка измените код и добавите функциональность в методы Update и Draw. В следующей главе вы создадите свою первую игру и узнаете о классе SpriteBatch.
Создайте новый проект XNA, выбрав команду New Project в меню File. В качестве типа проекта выберите Windows Game и введите имя вашего первого проекта, например, Hello World, либо оставьте предлагаемое по умолчанию имя WindowsGame1 (рис. 1.10). Как видите, здесь также можно быстро создать игру на основании набора для начинающих.
![]() |
Рис. 1.10 |
Новый проект состоит из двух исходных файлов: Game1.cs и Program.cs. Файл Program содержит следующие строки кода:
using (Game1 game = new Game1()) { game.Run(); } // using
Класс Game1 содержит методы Initialize, Update и Draw, о которых я упоминал ранее. Метод Initialize ничего не делает, а метод Update просто проверяет, нажата ли кнопка Back на первом подключенном игровом пульте.
Сейчас нас интересует только метод Draw, в котором выполняется только одна строка кода, окрашивающая фон в указанный цвет:
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
Если нажать F5, проект будет запущен (это то же самое, что выбрать команду Start Debugging в меню Debug), и вы увидите окно, фон которого окрашен в васильковый цвет, указанный в методе Draw (рис. 1.11).
![]() |
Рис. 1.11 |
Если чувствуете, что пора сделать что-нибудь, измените Color на Color.Green и нажмите F5 снова. Теперь у окна зеленый фон. У метода Clear графического устройства есть другие перегрузки, которые могут использоваться для очиски буфера глубины и буфера трафарета, которая в случае задания цвета выполняется автоматически. Например, позднее в этой книге нам потребуется очистить буфер глубины, не меняя цветов фона. Для этого просто используйте следующую строку кода:
graphics.GraphicsDevice.Clear(ClearOptions.DepthBuffer, Color.Green, 1, 0);
По умолчанию параметру ClearOptions присваивается значение ClearOptions.Target | ClearOptions.DepthBuffer, означающее, что будут очищены фон окна и буфер глубины. Между прочим, если вы еще не знаете, что значит | между параметрами ClearOptions, то этот оператор используется для объединения нескольких параметров.
Вместо того, чтобы остановиться на достигнутом, давайте подумаем какие полезные улучшения можно внести в код. Скорее всего, вы хотите, чтобы работу программы можно было завершать нажав клавишу Escape. По умолчанию XNA добавляет в метод Update следующие строки кода, обеспечивающие выход при нажатии кнопки Back на игровом пульте Xbox:
// Выход по умолчанию для Xbox 360 и Windows if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit();
С классом Input мы ближе познакомимся в главе 3, «Вспомогательные классы». Пока вы будете использовать быстрый и грязный способ получения доступа к клавиатуре. Если модифицировать код показанным ниже образом, выход из приложения будет происходить также и при нажатии клавиши Escape:
// Получаем текущее состояние клавиатуры и пульта GamePadState gamePad = GamePad.GetState(PlayerIndex.One); KeyboardState keyboard = Keyboard.GetState(); // Back или Escape - выход из игры на Xbox 360 и Windows if (gamePad.Buttons.Back == ButtonState.Pressed || keyboard.IsKeyDown(Keys.Escape)) this.Exit();
Как видите, состояния игрового пульта и клавиатуры помещаются в отдельные переменные для упрощения доступа. Если вы снова нажмете F5, то теперь завершить работу приложения можно будет нажатием клавиши Escape.
Давайте двинемся еще дальше, и загрузим в нашу игру графику. Более подробно спрайты будут обсуждаться в главе 2. Идея состоит в том, чтобы отобразить небольшую фоновую текстуру и замостить ею весь экран. Затем добавим простые возможности управления с клавиатуры и игрового пульта, чтобы фон перемещался как в гоночных играх с видом сверху и блочных движках, которые часто используются в двухмерных ролевых играх. Для более сложных блочных движков вам может потребоваться больше текстур, таких как камни, трава, вода и земля, и, кроме того, могут понадобиться переходные текстуры, которые вы будете располагать, например, между травой и водой. Для этого потребуется немного больше текстур и свой код, но это не должно вызвать особых трудностей. Если вы действительно интересуетесь блочными движками, то без труда найдете необходимую информацию по этой теме в Интернете.
Для первого несложного проекта мы просто добавим текстуру, изображенную на рис. 1.12.
![]() |
Рис. 1.12 |
Для загрузки данной текстуры (CityGroundSmall.jpg) в вашу игру просто перетащите ее в окно Solution Explorer вашего проекта. Затем щелкните по имени файла в списке компонентов проекта и выберите Properties. Вы должны увидеть окно, показанное на рис. 1.13.
![]() |
Рис. 1.13 |
Обычно вы видите параметры построения и ряд параметров для копирования файла содержимого в выходной каталог (это если вы включаете файл .dll или .xml). Но если XNA Studio обнаружит один из поддерживаемых форматов файлов содержимого, вы увидите дополнительные параметры XNA. Наиболее важные из них — Asset Name, Content Importer и Content Processor. Asset Name используется позже при загрузке содержимого; у каждого файла содержимого должно быть собственное уникальное значение Asset Name. Для Content Importer вы в данном случае выбираете Texture, но также возможны варианты Model Importer для файлов .x и Effect Importer для файлов .fx.
У параметра Content Processor может быть много различных значений; например, для текстуры сейчас вы можете выбрать DXT, DXT mip-mapped или Sprite 32bpp. DXT — это формат со сжатием, используемый также в файлах .dds и хорошо приспособленный для игровых текстур, поскольку обеспечивает сжатие с коэффициентом 1:6 (или 1:4, если в текстуре есть прозрачные пиксели). Это означает, что в том же объеме пространства жесткого диска и видеопамяти вы сможете хранить в шесть раз больше текстур. Для двухмерных спрайтов обычно лучше не использовать сжатие, чтобы видеть их в полном размере и использование 32-разрядного формата обеспечит наилучшее качество. Мы подробнее поговорим о конвейере содержимого позже в этой главе.
Если вы нажмете F5 или построите проект (F6), содержимое будет обработано и в выходном каталоге появится новый файл CityGroundSmall.xnb. В окне с результатами построения появится следующая строка:
Building CityGroundSmall.jpg -> bin\x86\Debug\CityGroundSmall.xnb
Финальная вещь, котороую нам надо выполнить — загрузка импортированной текстуры. Можно сделать это в методе Initialize и использовать новую переменную вашего класса backgroundTexture. Для загрузки текстуры вы используете имя компонента (asset name), назначенное ранее (в действительности оно генерируется автоматически на основании имени файла, перетащенного в ваш проект). Для визуализации текстуры на экране вам потребуется класс SpriteBatch, обсуждающийся в следующей главе. Обычно вы устанавливаете режим альфа-смешивания, помещаете текстуры в спрайты и отображаете все на экране.
Texture2D backgroundTexture; SpriteBatch sprites; protected override void Initialize() { backgroundTexture = content.Load<Texture2D>("CityGroundSmall"); sprites = new SpriteBatch(graphics.GraphicsDevice); base.Initialize(); } // Initialize()
Чтобы отобразить фоновую текстуру вы начинаете обработку спрайтов и визуализируете текстуру спрайта в методе Draw:
protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.Green); sprites.Begin(); sprites.Draw(backgroundTexture, Vector2.Zero, Color.White); sprites.End(); base.Draw(gameTime); } // Draw(gameTime)
Визуализация фоновой текстуры происходит в точке (0, 0) поверх зеленого фона. Параметры цвета позволяют перекрашивать спрайты, но сейчас это неважно.
Если вы сейчас нажмете F5, то увидите результат, показанный на рис. 1.14.
![]() |
Рис. 1.14 |
Финальная вещь, которую мы добавим к первому проекту, — возможность прокрутки фона с помощью клавиш управления курсором или игрового пульта, и визуализация состоящего из блоков полноразмерного прокручиваемого фона. Для получения данных от игрового пульта и клавиатуры мы немного модифицируем метод Update:
float scrollPosition = 0; protected override void Update(GameTime gameTime) { // Получаем текущее состояние пульта и клавиатуры GamePadState gamePad = GamePad.GetState(PlayerIndex.One); KeyboardState keyboard = Keyboard.GetState(); // Back или Escape - выход из игры на Xbox 360 и Windows if (gamePad.Buttons.Back == ButtonState.Pressed || keyboard.IsKeyDown(Keys.Escape)) this.Exit(); // Перемещаемся на 400 пикселей в секунду float moveFactorPerSecond = 400 * (float)gameTime.ElapsedRealTime.TotalMilliseconds / 1000.0f; // Перемешаемся вверх или вниз, если нажаты соответствующие // клавиши управления курсором или кнопки пульта if (gamePad.DPad.Up == ButtonState.Pressed || keyboard.IsKeyDown(Keys.Up)) scrollPosition += moveFactorPerSecond; if (gamePad.DPad.Down == ButtonState.Pressed || keyboard.IsKeyDown(Keys.Down)) scrollPosition -= moveFactorPerSecond; base.Update(gameTime); } // Update(gameTime)
Первые строки остались неизменными. Затем вы вычисляете, на сколько пикселей надо переместить изображение в данном кадре. Если кадр формируется 1 секунду, movefactorPerSecond будет равно 400; для 60 кадров в секунду значение будет 400/60. Поскольку здесь используются числа с плавающей запятой, а не целые, частота кадров может достигать нескольких тысяч, и движение вверх или вниз при нажатии клавиш все равно будет осуществляться со скоростью 400 пикселей в секунду.
Если пользователь нажимает клавиши перемещения вверх или вниз, меняется значение переменной scrollPosition. Потом, в методе рисования, вы визуализируете каждый блок фона и прибавляете scrollPosition к его координате Y для перемещения фона вверх и вниз.
protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.Green); sprites.Begin(); int resolutionWidth = graphics.GraphicsDevice.Viewport.Width; int resolutionHeight = graphics.GraphicsDevice.Viewport.Height; for (int x = 0; x <= resolutionWidth / backgroundTexture.Width; x++) for (int y = -1; y <= resolutionHeight / backgroundTexture.Height; y++) { Vector2 position = new Vector2( x * backgroundTexture.Width, y * backgroundTexture.Height + ((int)scrollPosition) % backgroundTexture.Height); sprites.Draw(backgroundTexture, position, Color.White); } // for for sprites.End(); base.Draw(gameTime); } // Draw(gameTime)
Теперь можете запустить ваш проект и перемещаться вверх и вниз. Совсем неплохо для первого небольшого приложения, не так ли?
netlib.narod.ru | < Назад | Оглавление | Далее > |