Спонсор: Microsoft
Опубликован: 10.04.2009 | Доступ: свободный | Студентов: 3248 / 243 | Оценка: 4.49 / 4.39 | Длительность: 17:21:00
Специальности: Программист
Самостоятельная работа 3:

Устройства ввода, перемещение объектов

Разработка игрового компонента с функциями перемещения и с ограничениями

Можно заметить, что в предыдущих примерах игровые объекты легко пересекали границы игрового поля. В реальных проектах обычно требуется, чтобы подвижный объект не пересекал этих границ. Это значит, что, во-первых – нам нужно узнать координаты границ экрана, а во-вторых – нужно создать такой код, отвечающий за перемещение объекта, который прежде чем переместить объект в новую позицию, проверял бы допустимость такого перемещения.

Создадим новый игровой проект (P3_4), аналогичный проекту P2_3, разработанному в лабораторной работе №2. Единственное отличие – мы не будем выводить фоновое изображение. Этот проект содержит игровой компонент, который в нашем примере и будет содержать весь необходимый код. Измененный код компонента вы можете видеть в листинге 7.7.

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;

namespace P3_4
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class spriteComp : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private Texture2D sprTexture;
        private Rectangle sprRectangle;
        private Vector2 sprPosition;
        private Rectangle scrBounds;

        public spriteComp(Game game, ref Texture2D newTexture,
            Rectangle newRectangle, Vector2 newPosition)
            : base(game)
        {
            sprTexture = newTexture;
            sprRectangle = newRectangle;
            sprPosition = newPosition;
            scrBounds = new Rectangle(0, 0, 
                game.Window.ClientBounds.Width, 
                game.Window.ClientBounds.Height);
            // TODO: Construct any child components here
        }

        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            KeyboardState kbState = Keyboard.GetState();
            if (kbState.IsKeyDown(Keys.Up))
            {
                sprPosition.Y -= 5;
            }
            if (kbState.IsKeyDown(Keys.Down))
            {
                sprPosition.Y += 5;
            }
            if (kbState.IsKeyDown(Keys.Left))
            {
                sprPosition.X -= 5;
            }
            if (kbState.IsKeyDown(Keys.Right))
            {
                sprPosition.X += 5;
            }
           
            if (sprPosition.X < scrBounds.Left)
            {
                sprPosition.X = scrBounds.Left;
            }
            if (sprPosition.X > scrBounds.Width - sprRectangle.Width)
            {
                sprPosition.X = scrBounds.Width - sprRectangle.Width ;
            }
            if (sprPosition.Y < scrBounds.Top)
            {
                sprPosition.Y = scrBounds.Top;
            }
            if (sprPosition.Y > scrBounds.Height - sprRectangle.Height )
            {
                sprPosition.Y = scrBounds.Height - sprRectangle.Height;
            }

            base.Update(gameTime);
        }
        public override void Draw(GameTime gameTime)
        {
            SpriteBatch sprBatch =
                (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));

            sprBatch.Draw(sprTexture, sprPosition, sprRectangle, Color.White);
            base.Draw(gameTime);
        }
    }
}
Листинг 7.7. Код компонента, рассчитанного на перемещения с ограничениями

В разделе объявления переменных мы добавили новую переменную – scrBounds типа Rectangle. В этой переменной мы будем хранить параметры игрового окна. Мы инициализируем эту переменную в конструкторе класса. В качестве левой верхней координаты прямоугольника, ограничивающего игровое окно, мы записали (0,0), в качестве ширины – ширину игрового поля, полученную с помощью команды game.Window.ClientBounds.Width. Здесь объект game был передан в конструктор при создании игрового объекта, объект Window – это окно игры, ClientBounds содержит информацию о параметрах окна, в частности, о ширине (Width) и высоте (Height).

В методе Update() мы получаем состояние клавиатуры и, если нажаты соответствующие клавиши-стрелки, модифицируем позицию спрайта на экране. Однако здесь, после модификации позиции, мы проводим серию проверок. Например, проверяем, не меньше ли новая координата X игрового объекта координаты X прямоугольника, соответствующего игровому окну. Если эта координата меньше, это значит, что объект, при перемещении в соответствующую позицию, окажется левее левой границы экрана. Поэтому, если проверяемое условие выполняется – мы приравниваем координату левой границы экрана координате объекта. При попытке пересечения левой границы экрана объект "упирается" в нее.

Немного сложнее выглядит проверка на пересечение правой границы экрана. Как вы знаете, координаты X и Y прямоугольника, ограничивающего наш объект, соответствуют его левой верхней точке. Объект имеет ширину и высоту, поэтому для проверки пересечения правой границы экрана, мы сравниваем новую позицию объекта с разностью ширины экрана с шириной объекта. Если оказывается, что новая позиция больше, чем вычисленная разностьобъект устанавливается в позицию, координата X объекта устанавливается равной разности ширины экрана и ширины объекта – он "упирается" в правую границу экрана своей правой частью.

Таким же образом проверяется координата Y – на пересечение объекта верхней и нижней границ экрана.

Как видите, вся логика по перемещению объекта и по проверке на допустимость перемещения, содержится в игровом компоненте и не перегружает основной программный код. Такой подход имеет свои плюсы и минусы. Плюс заключается в удобстве использования подобной конструкции. Но если мы создадим несколько игровых объектов на основе игрового компонента, то окажется, что все они перемещаются одновременно по нажатию на клавиши-стрелки.

Одинаковый механизм перемещения был бы удобен, если бы мы создали алгоритм автоматического перемещения объекта, который перемещал бы каждый из них в соответствии с каким-то законом, например – случайным образом. Если же нам нужно создать несколько объектов, обладающих самостоятельным управлением, используя один и тот же класс, этот механизм будет нуждаться в переработке. Например, в игре Pong предусматривается управление двумя битами – два пользователя, сидя за одной клавиатурой, управляют каждый своей битой с использованием собственных клавиш. Рассмотрим механизмы организации управления несколькими объектами.

Alina Lasskaja
Alina Lasskaja

Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить.....