В этой лабораторной работе мы ознакомимся с основными способами работы с устройствами ввода. В частности, поговорим о перемещении объектов, обсудим работу с различными устройствами ввода, вопросы автоматического перемещения объектов, а так же – вопросы, касающиеся работы в оконном и полноэкранном режимах.
Цель работы:
Научиться работать с устройствами ввода информации
Задачи работы
Научиться получать данные о состоянии мыши и клавиатуры
Научиться перемещать игровые объекты в соответствии с параметрами, полученными от устройства ввода
Научиться перемещать игровые объекты в автоматическом режиме, используя средства игрового цикла
Научиться организовывать управление несколькими объектами для применения в играх, в которые могут играть два игрока, пользующиеся одним компьютером
Научиться узнавать и изменять размеры игрового окна
Научиться переводить программу в полноэкранный режим, настраивать разрешение экрана при работе в таком режиме
Научиться предотвращать пересечение объектом границ экрана при перемещении объекта
Обработка состояния клавиатуры
Создадим новый стандартный проект, назовем его P3_1. Добавим в проект изображение, переменные для хранения текстуры и позиции изображения в игровом окне, загрузим его в методе LoadContent. Вот, как выглядит текст программы после модификации (листинг 3.1.).
usingSystem;usingSystem.Collections.Generic;usingMicrosoft.Xna.Framework;usingMicrosoft.Xna.Framework.Content;usingMicrosoft.Xna.Framework.Graphics;usingMicrosoft.Xna.Framework.Input;namespace P3_1{/// /// This is the main type for your game/// publicclass Game1 : Microsoft.Xna.Framework.Game{ GraphicsDeviceManager graphics; SpriteBatch spriteBatch;private Texture2D MySprite;private Vector2 position =new Vector2(150, 200);public Game1(){ graphics =new GraphicsDeviceManager(this); Content.RootDirectory="Content";}protectedoverridevoid LoadContent(){ spriteBatch =new SpriteBatch(GraphicsDevice); MySprite = Content.Load<Texture2D>("ball");}protectedoverridevoid Update(GameTime gameTime){// Allows the game to exitif(GamePad.GetState(PlayerIndex.One).Buttons.Back== ButtonState.Pressed)this.Exit();base.Update(gameTime);}protectedoverridevoid Draw(GameTime gameTime){ graphics.GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); spriteBatch.Draw(MySprite, position, Color.White); spriteBatch.End();base.Draw(gameTime);}}}
Теперь добавим в метод Update код, который будет изменять позицию выведенного спрайта в соответствии с изменением состояния клавиатуры. В частности, будет реагировать на клавиши-стрелки, перемещая объект в соответствующем направлении. На рис. 3.1. вы можете видеть внешний вид игрового окна.
Рис. 3.1. Игровое окно
Для того, чтобы настроить перемещение спрайта по клавиатурным командам, нам понадобится такой код (листинг 3.2.).
Листинг 3.2. Код, реализующий чтение состояния клавиатуры и перемещение спрайта
Здесь мы сначала создали переменную kbState типа KeyboardState, в которую записали текущее состояние клавиатуры, вызвав метод GetState() объекта KeyBoard. Этот метод возвращает состояние клавиатуры.
После этого мы проверили, с помощью метода IsKeyDown, была ли нажата клавиша-стрелка «Вверх». Наименования клавиш хранятся в перечислении Keys. В нашем случае клавиша-стрелка «вверх» символизируется именем Keys.Up. Если клавиша нажата – изменим координату Y позиции объекта, вычтя из нее 1. Позиция изменится и при следующем выводе спрайта он переместится на 1 пиксель вверх. Точно так же обрабатываются другие клавиши-стрелки. Keys.Down – это клавиша «вниз», если она нажата, к координате Y прибавляется единица и объект перемещается вниз. Keys.Left – это клавиша «влево» - объект перемещается влево – от его координаты X отнимается единица. Keys.Right – это клавиша «вправо» - объект перемещается вправо, к его координате X прибавляется 1.
Если нажать и удерживать одну из клавиш – объект будет непрерывно перемещаться в указанном направлении. Если, не отпуская нажатую клавишу, нажать другую, объект изменит направление или остановится. Например, нажав одновременно клавиши «вверх» и «влево», мы заставим объект двигаться по диагонали влево и вверх. А если в то время, как нажата клавиша «вверх» мы нажмем и клавишу «вниз» - объект остановится – нажатие «вверх» вычитает единицу из его позиции, нажатие «вниз» - прибавляет единицу, в результате объект оказывается неподвижным. С помощью метода IsKeyUp объекта kbState мы проводим проверку, обратную методу IsKeyDown – то есть этот метод возвращает True, если клавиша не нажата, и False – если нажата.
Для перемещения объекта мы модифицируем его координаты на игровом поле. Можно заметить, что модификация ведется с шагом в 1. Это значение можно назвать скоростью перемещения объекта. Увеличив шаг изменения координаты по нажатию клавиши, можно увеличить скорость перемещения.
Можно заметить, что описанный подход к перемещению объекта по клавиатурным командам работает, однако если сложность игровой программы увеличится – он оказывается неудобным. Поэтому ниже мы рассмотрим пример использование управляемого с клавиатуры игрового компонента, унаследованного от DrawableGameComponent. Такой подход делает удобным не только клавиатурное управление, но и автоматическое управление объектом, делает возможным удобное применение ограничений на управление объектом, обработку столкновений объектов (этот вопрос будет рассмотрен на следующем занятии) и другие задачи. Однако, стоит отметить, что принципы управления объектами с клавиатуры даже при управлении игровым компонентом, сохраняются.
Теперь рассмотрим управление игровым объектом с помощью мыши.
Обработка состояния мыши
Создадим новый стандартный игровой проект (P3_2), модифицируем его таким образом, чтобы он соответствовал коду, приведенному в листинге 3.1. – то есть – подготовим все для рассмотрения концепций работы с мышью. Теперь добавим в код метода Update() такой код (листинг 3.3.).
Листинг 3.3. Код, реализующий чтение состояния мыши и перемещение объекта
Для начала мы создали переменную mState типа MouseState – она хранит состояние мыши, полученное с помощью метода GetState() объекта Mouse. Теперь мы приравниваем координату X позиции спрайта текущей координате X мыши, то же самое делаем с координатой Y.
Запустив на выполнение данный пример, можно заметить, что спрайт перемещается в соответствии с перемещениями мыши, при выходе указателя мыши за пределы игрового окна, спрайт так же «уходит» с экрана. Ниже мы рассмотрим пример, показывающий, как избежать такого «ухода».
Состояние мыши, помимо её координат, содержит и другую информацию. В частности – данные о нажатии клавиш, о состоянии колёсика прокрутки. Создадим пример, который демонстрирует перемещение спрайта к позиции игрового окна, в которой мы щёлкнули мышью.
Создадим новый стандартный игровой проект (P3_3), код которого аналогичен листингу 3.1.
Добавим в раздел объявления переменных класса две переменных (листинг. 3.4.).
Листинг 3.4. Определение факта нажатия на левую кнопку мыши
Первую переменную – is_MouseLB_Pressed будем устанавливать в True при нажатии на левую кнопку мыши, в переменную new_position будем записывать координаты, в которых произошло нажатие.
Добавим в метод Initialise() класса Game1 код, который отобразит указатель мыши в игровом окне. По умолчанию при перемещении мыши в пределы игрового окна указатель исчезает. Код, приведенный в листинге 3.5. позволяет отобразить указатель.
Листинг 3.5. Код для отображения указателя мыши в игровом окне
Здесь объект this представляет собой текущий игровой объект. Его свойство IsMouseVisible при установке в True включает отображение указателя в игровом окне.
Теперь дополним метод Update() так, как показано в коде, приведенном в листинге 3.6.
Листинг 3.6. Автоматическое перемещение объекта к месту щелчка мыши
protectedoverridevoid Update(GameTime gameTime){// Allows the game to exitif(GamePad.GetState(PlayerIndex.One).Buttons.Back== ButtonState.Pressed)this.Exit(); MouseState mState = Mouse.GetState();if(mState.LeftButton==ButtonState .Pressed){ is_MouseLB_Pressed = true; new_position.X= mState.X; new_position .Y= mState .Y;}if(is_MouseLB_Pressed){if(new_position .X-position .X>0){ position .X+=1;}else{ position .X-=1;}if(new_position .Y-position .Y>0){ position .Y+=1;}else{ position .Y-=1;}if(position == new_position){ is_MouseLB_Pressed = false;}}}
Сначала мы получаем текущее состояние мыши и сохраняем его в переменной mState. Далее проверяем, была ли нажата левая кнопка мыши. Для этого используем свойство mState.LeftButton и проверяем его равенство ButtonState.Pressed. Если равенство выполняется – устанавливаем переменную is_MouseLB_Pressed в True и записываем в переменную new_Position значения координат мыши в момент нажатия левой кнопки.
Далее, если переменная is_MouseLB_Pressed установлена в True, сравниваем текущую позицию объекта и позицию, в которой мы щелкнули левой кнопкой. Если разность координаты X новой и текущей позиций больше нуля, это значит, что объект расположен левее новой позиции и для перемещения к ней его координата X должна быть увеличена. Если разность меньше нуля – объект находится правее, его координата X будет уменьшена. Точно так же сравниваем координаты Y и модифицируем их. В конце мы проверяем, достиг ли объект заданной позиции. Если да – устанавливаем is_MouseLB_Pressed в False – это значит, что на следующем шаге цикла Update() мы не будем модифицировать координаты – объект достиг заданной позиции.
При запуске программы объект неподвижен. Если мы щелкнем мышью в игровом окне – он начнет перемещаться в позицию щелчка. Если объект уже двигается по направлению к позиции, в которой мы щелкнули мышью, а мы в это время щелкаем мышью в новой позиции – он меняет направление движения и движется к новой позиции. Здесь реализован простой пример автоматического перемещения объекта.
Как упоминалось выше, подход с размещением кода перемещения игрового объекта в основном коде программы неудобен при разработке реальных проектов. Поэтому ниже мы рассмотрим пример разработки самостоятельного игрового объекта, содержащего собственный код, отвечающий за его перемещение. Здесь же мы реализуем проверку на допустимость следующего шага перемещения.
Разработка игрового компонента с функциями перемещения и с ограничениями
Можно заметить, что в предыдущих примерах игровые объекты легко пересекали границы игрового поля. В реальных проектах обычно требуется, чтобы подвижный объект не пересекал этих границ. Это значит, что, во-первых – нам нужно узнать координаты границ экрана, а во-вторых – нужно создать такой код, отвечающий за перемещение объекта, который прежде чем переместить объект в новую позицию, проверял бы допустимость такого перемещения.
Создадим новый игровой проект (P3_4), аналогичный проекту P2_3, разработанному в лабораторной работе №2. Единственное отличие – мы не будем выводить фоновое изображение. Этот проект содержит игровой компонент, который в нашем примере и будет содержать весь необходимый код. Измененный код компонента вы можете видеть в листинге 3.7.
Листинг 3.7. Код компонента, рассчитанного на перемещения с ограничениями
В разделе объявления переменных мы добавили новую переменную – scrBounds типа Rectangle. В этой переменной мы будем хранить параметры игрового окна. Мы инициализируем эту переменную в конструкторе класса. В качестве левой верхней координаты прямоугольника, ограничивающего игровое окно, мы записали (0,0), в качестве ширины – ширину игрового поля, полученную с помощью команды game.Window.ClientBounds.Width. Здесь объект game был передан в конструктор при создании игрового объекта, объект Window – это окно игры, ClientBounds содержит информацию о параметрах окна, в частности, о ширине (Width) и высоте (Height).
В методе Update() мы получаем состояние клавиатуры и, если нажаты соответствующие клавиши-стрелки, модифицируем позицию спрайта на экране. Однако здесь, после модификации позиции, мы проводим серию проверок. Например, проверяем, не меньше ли новая координата X игрового объекта координаты X прямоугольника, соответствующего игровому окну. Если эта координата меньше, это значит, что объект, при перемещении в соответствующую позицию, окажется левее левой границы экрана. Поэтому, если проверяемое условие выполняется – мы приравниваем координату левой границы экрана координате объекта. При попытке пересечения левой границы экрана объект «упирается» в нее.
Немного сложнее выглядит проверка на пересечение правой границы экрана. Как вы знаете, координаты X и Y прямоугольника, ограничивающего наш объект, соответствуют его левой верхней точке. Объект имеет ширину и высоту, поэтому для проверки пересечения правой границы экрана, мы сравниваем новую позицию объекта с разностью ширины экрана с шириной объекта. Если оказывается, что новая позиция больше, чем вычисленная разность – объект устанавливается в позицию, координата X объекта устанавливается равной разности ширины экрана и ширины объекта – он «упирается» в правую границу экрана своей правой частью.
Таким же образом проверяется координата Y – на пересечение объекта верхней и нижней границ экрана.
Как видите, вся логика по перемещению объекта и по проверке на допустимость перемещения, содержится в игровом компоненте и не перегружает основной программный код. Такой подход имеет свои плюсы и минусы. Плюс заключается в удобстве использования подобной конструкции. Но если мы создадим несколько игровых объектов на основе игрового компонента, то окажется, что все они перемещаются одновременно по нажатию на клавиши-стрелки.
Одинаковый механизм перемещения был бы удобен, если бы мы создали алгоритм автоматического перемещения объекта, который перемещал бы каждый из них в соответствии с каким-то законом, например – случайным образом. Если же нам нужно создать несколько объектов, обладающих самостоятельным управлением, используя один и тот же класс, этот механизм будет нуждаться в переработке. Например, в игре Pong предусматривается управление двумя битами – два пользователя, сидя за одной клавиатурой, управляют каждый своей битой с использованием собственных клавиш. Рассмотрим механизмы организации управления несколькими объектами.
Управление несколькими объектами: система классов
Пожалуй, первая мысль, которая придет в голову при разработке раздельного управления двумя объектами - создать второй игровой компонент, отличающийся от первого лишь реакцией на нажатия клавиш. Например, первый будет управляться с помощью клавиш-стрелок, второй – с помощью традиционного для игр набора клавиш ASWD. Грамотнее всего в такой ситуации будет создать игровой компонент, который не содержит клавиатурных команд, после чего создать еще два компонента, каждый из которых унаследует исходный компонент и переопределит его метод, ответственный за обработку событий клавиатуры.
Создадим новый проект (P3_5), аналогичный проекту P2_3 (лишь отключим вывод фона). Игровой компонент spriteComp будет служить основой для двух других компонентов. Изменим его код так, как показано в листинге 3.8.
Обратите внимание на то, что этот компонент практически в точности похож на компонент, код которого приведен в листинге 3.7. Ключевое различие – удаление из метода Update() кода, связанного с перемещением. Этого кода здесь вовсе нет. Зато мы добавили в Update() вызов нового виртуального метода Move(). Из названия метода можно судить о том, что его планируется использовать для управления перемещением объекта. Метод не случайно объявлен с ключевым словом virtual – в дочерних классах мы переопределим этот метод для решения задач каждого из них. В родительском классе мы добавили в него вызов метода Check(). Этот метод одинаков для обоих объектов – он не допускает пересечения ими границ экрана.
Добавим в проект новый игровой компонент, назовем его gameObj1.cs и соответствующим образом модифицируем. В листинге 3.9. вы можете видеть его код, ниже читайте пояснения.
Листинг 3.9. Класс gameObj1 – наследник spriteComp
Так как добавленный в игру компонент был изначально унаследован от GameComponent – он не имел переопределенного метода Draw(). Добавим этот метод в компонент.
Теперь модифицируем конструктор класса. Все, что нужно сделать здесь – получить те же параметры, что и базовый класс и передать их его конструктору.
Далее – переопределим метод Draw() – а именно – добавим в него команды обработки ввода с клавиатуры. Это уже знакомые вам команды, которые меняют положение объекта на 5 пикселей в зависимости от нажатой клавиши-стрелки. Добавим в проект еще один игровой компонент, назовем его gameObj2.cs, проведем с ним те же манипуляции, которые провели с компонентом gameObj1.cs, а вот метод Draw() переопределим по-другому. Напомню, что нам нужно, чтобы этим компонентом можно было управлять не с помощью клавиш-стрелок, а клавишами ASWD. В листинге 3.10. вы можете видеть код этого класса.
Листинг 3.10. Класс gameObj2 – наследник spriteComp
usingSystem;usingSystem.Collections.Generic;usingMicrosoft.Xna.Framework;usingMicrosoft.Xna.Framework.Content;usingMicrosoft.Xna.Framework.Graphics;usingMicrosoft.Xna.Framework.Input;namespace P3_5{/// /// This is the main type for your game/// publicclass Game1 : Microsoft.Xna.Framework.Game{ GraphicsDeviceManager graphics; SpriteBatch spriteBatch; gameObj1 gameObject; gameObj2 gameObject2; Texture2D texture;public Game1(){ graphics =new GraphicsDeviceManager(this); Content.RootDirectory="Content";}protectedoverridevoid Initialize(){// TODO: Add your initialization logic herebase.Initialize();}protectedoverridevoid LoadContent(){// Create a new SpriteBatch, which can be used to draw textures. spriteBatch =new SpriteBatch(GraphicsDevice); Services.AddService(typeof(SpriteBatch), spriteBatch); texture = Content.Load<Texture2D>("BallandBats"); CreateNewObject();// TODO: use this.Content to load your game content here}protectedvoid CreateNewObject(){ gameObject =new gameObj1 (this, ref texture,new Rectangle(18, 9, 17, 88), new Vector2(100, 150)); Components.Add(gameObject1); gameObject2 =new gameObj2(this, ref texture,new Rectangle(17, 106, 17,88), new Vector2(200, 150)); Components.Add(gameObject2);}protectedoverridevoid UnloadContent(){// TODO: Unload any non ContentManager content here}protectedoverridevoid Update(GameTime gameTime){// TODO: Add your update logic herebase.Update(gameTime);}protectedoverridevoid Draw(GameTime gameTime){ graphics.GraphicsDevice.Clear(Color.CornflowerBlue);// TODO: Add your drawing code here spriteBatch.Begin();base.Draw(gameTime); spriteBatch.End();}}}
Для начала мы объявили пару объектных переменных – одну типа gameObj1, вторую – gameObj2. Далее, после загрузки игрового контента, мы выполнили метод CreateNewObject(), который содержит код для создания двух объектов. После создания мы регистрируем каждый из них в списке игровых компонентов.
Как видите, в коде основной программы мы лишь загружаем ресурсы и создаем игровые объекты, после чего вся работа по управлению ими ведется с помощью кода, находящегося в этих же объектах. На рис. 3.2. вы можете видеть игровое окно с двумя выведенными в нем объектами, которые управляются раздельно.
Рис. 3.2. Игровое окно с двумя игровыми компонентами
Еще один подход к управлению несколькими объектами заключается в создании упрощенного, в плане управления, объекта, которому лишь передаются новые координаты, вычисленные после обработки ввода в основной программе. Рассмотрим такой подход.
Централизованное управление несколькими объектами
Создадим новый проект (P3_6), аналогичный проекту P2_3 (лишь отключим вывод фона). Игровой компонент spriteComp будет использован для построения двух объектов. Изменим его код так, как показано в листинге 3.12.
Обратите внимание на то, что класс содержит лишь несколько свойств, собственный конструктор и команды для вывода изображения на экран в методе Draw(). Свойства sprRectangle и sprPosition объявлены с модификатором доступности Public – они пригодятся нам для управления поведением объекта из объекта класса Game1.
Вот как выглядит код класса Game1. Вся логика по перемещению объектов и по проверке допустимости перемещения реализована в нём.
Для перемещения объектов класса spriteComp мы модифицируем их свойства sprPosition из кода объекта Game1. Для удобства мы создали четыре процедуры – Up, Down, Left, Right – каждая из них принимает на входе объект типа spriteComp и модифицирует соответствующую координату, хранящуюся в свойстве sprPosition этого объекта. Эти процедуры вызываются после анализа состояния клавиатуры в методе Update(). После этого вызывается метод Test(), который принимает на входе объект типа spriteComp и объект типа Rectangle, который хранит параметры экрана. В методе производятся проверки допустимости новых значений, при нарушении объектом границ, координаты модифицируются.
Теперь рассмотрим еще один способ организации управления и работы с объектами.
Автоматическое перемещение объекта: несколько автономных объектов без создания объектных переменных
Выше мы создавали схемы управления игровыми объектами, рассчитанными на действия игрока. Но вполне возможно, что нам захочется создать объект, который будет находиться под управлением компьютера, то есть – некоего алгоритма. Часто для таких объектов не выделяют отдельных объектных переменных – их можно динамически создавать в нужных количествах и уничтожать.
Разработаем следующую программу. На игровой экран должно выводиться случайное количество игровых объектов (в диапазоне от 50 до 200), в случайных позициях в пределах границ экрана. Каждый из них перемещается в случайном направлении на случайное число шагов (в диапазоне от 50 до 200). Объекты не могут пересекать границы экрана. При каждом новом шаге цвет объекта должен случайным образом изменяться
Создадим новый игровой проект (P3_7), аналогичный P2_3. Модифицируем его код. В листинге 3.14. вы можете видеть код компонента spriteComp.
usingSystem;usingSystem.Collections.Generic;usingMicrosoft.Xna.Framework;usingMicrosoft.Xna.Framework.Content;usingMicrosoft.Xna.Framework.Graphics;usingMicrosoft.Xna.Framework.Input;namespace P3_7{/// /// This is the main type for your game/// publicclass Game1 : Microsoft.Xna.Framework.Game{ GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D texture; Random randNum;public Game1(){ graphics =new GraphicsDeviceManager(this); Content.RootDirectory="Content";}protectedoverridevoid Initialize(){// TODO: Add your initialization logic herebase.Initialize();}protectedoverridevoid LoadContent(){// Create a new SpriteBatch, which can be used to draw textures. spriteBatch =new SpriteBatch(GraphicsDevice); Services.AddService(typeof(SpriteBatch), spriteBatch); texture = Content.Load<Texture2D>("BallandBats"); randNum =new Random(); CreateNewObject();// TODO: use this.Content to load your game content here}protectedvoid CreateNewObject(){//Цикл от 1 до случайного числ в диапазоне 50,200for(int i =0; i < randNum .Next(50,200); i++){//Добавляем в список компонентов новый компонент класса spriteComp Components.Add(new spriteComp(this, ref texture,new Rectangle(16, 203, 17, 17), i));}}protectedoverridevoid UnloadContent(){}protectedoverridevoid Update(GameTime gameTime){if(GamePad.GetState(PlayerIndex.One).Buttons.Back== ButtonState.Pressed)this.Exit();base.Update(gameTime);}protectedoverridevoid Draw(GameTime gameTime){ graphics.GraphicsDevice.Clear(Color.CornflowerBlue);// TODO: Add your drawing code here spriteBatch.Begin();base.Draw(gameTime); spriteBatch.End();}}}
В целом код этого класса уже хорошо знаком вам по предыдущим примерам. Поэтому обратите особое внимание на процедуру CreateNewObject(). Она содержит циклический вызов метода Add объекта Components, который добавляет в список игровых объектов новый объект типа spriteComp. Номер итерации передается в объект для инициализации генератора случайных чисел. Если принудительно не инициализировать генераторы случайных чисел созданных объектов разными значениями – это приведет к неправильной работе программы – все объекты будут выведены в одной и той же позиции (если объектов много – то в нескольких позициях).
Такой подход позволяет создавать нужное количество объектов, не заботясь о создании объектных переменных. На одной из следующих занятий мы рассмотрим методы работы с такими объектами. На рис. 3.3. вы можете видеть игровое окно проекта P3_7.
Рис. 3.7. Игровое окно, выводящее автоматически созданные объекты
Работа с игровым манипулятором
Для работы с игровым манипулятором служит объект GamePad. Сохранить состояние объекта можно в переменной типа GamePadState. Эта переменная хранит информацию об элементах управления, которые расположены на устройстве. Надо отметить, что игровой манипулятор поддерживает вибрацию – разрабатывая игру, рассчитанная на управление манипулятором, включая в нужный момент вибрацию можно сделать ее интереснее.
Вопросы
1) В переменную типа KeyboardState можно сохранить информацию о
a. Состоянии мыши
b. Состоянии клавиатуры
c. Состоянии игрового манипулятора
d. Состоянии графического устройства
2) Какую клавишу символизирует перечисления Keys.Up?
a. Клавиша-стрелка «вниз»
b. Клавиша-стрелка «влево»
c. Клавиша-стрелка «вправо»
d. Клавиша-стрелка «вверх»
3) В переменную типа MouseState можно сохранить информацию о
a. Состоянии мыши
b. Состоянии клавиатуры
c. Состоянии игрового манипулятора
d. Состоянии графического устройства
4) 4) В переменную типа GamePadState можно сохранить информацию о
a. Состоянии мыши
b. Состоянии клавиатуры
c. Состоянии игрового манипулятора
d. Состоянии графического устройства
5) Параметр IsMouseVisible объекта типа Game позволяет
a. Отображать и скрывать указатель мыши
b. Настраивать разрешение игрового экрана
c. Создать объект типа Mouse
d. Отображать и скрывать игровое окно
6) Можно ли организовать управление несколькими игровыми объектами с одной клавиатуры?
a. Да
b. Нет
7) Какой фундаментальный игровой механизм позволяет организовать автоматическое перемещение объектов?
b. Эта команда позволяет добавить к списку игровых компонентов новый компонент
c. Эта команда нужна для проверки наличия среди игровых компонентов нужного компонента
d. Эта команда позволяет удалить компонент из списка игровых компонентов
9) Переменная sprPosition хранит текущую позицию спрайта. Переменная newPosition хранит позицию, в которую спрайт должен переместиться. Если координата X текущей позиции спрайта больше, чем координата X желаемой позиции, какая команда приведет к сокращению расстояния между позициями?
a. sprPosition.X += 1;
b. sprPosition.X -= 1;
10) Переменная sprPosition хранит текущую позицию спрайта. Переменная newPosition хранит позицию, в которую спрайт должен переместиться. Если координата Y текущей позиции спрайта меньше, чем координата Y желаемой позиции, какая команда приведет к сокращению расстояния между позициями?