Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить..... |
Устройства ввода, перемещение объектов
Автоматическое перемещение объекта: несколько автономных объектов без создания объектных переменных
Выше мы создавали схемы управления игровыми объектами, рассчитанными на действия игрока. Но вполне возможно, что нам захочется создать объект, который будет находиться под управлением компьютера, то есть – некоего алгоритма. Часто для таких объектов не выделяют отдельных объектных переменных – их можно динамически создавать в нужных количествах и уничтожать.
Разработаем следующую программу. На игровой экран должно выводиться случайное количество игровых объектов (в диапазоне от 50 до 200), в случайных позициях в пределах границ экрана. Каждый из них перемещается в случайном направлении на случайное число шагов (в диапазоне от 50 до 200). Объекты не могут пересекать границы экрана. При каждом новом шаге цвет объекта должен случайным образом изменяться
Создадим новый игровой проект (P3_7), аналогичный P2_3. Модифицируем его код. В листинге 7.14. вы можете видеть код компонента spriteComp.
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_7 { /// <summary> /// This is a game component that implements IUpdateable. /// </summary> public class spriteComp : Microsoft.Xna.Framework.DrawableGameComponent { protected Texture2D sprTexture; protected Rectangle sprRectangle; protected Vector2 sprPosition; protected Rectangle scrBounds; //Для генерирования случайных чисел protected Random randNum; //Количество шагов, которое пройдет спрайт protected int stepNumber; //Координата, к которой он будет двигаться protected Vector2 newPosition; //Цвет спрайта protected Color sprColor; //Скорость перемещения protected Vector2 speed; public spriteComp(Game game, ref Texture2D newTexture, Rectangle newRectangle, int Speed) : base(game) { sprTexture = newTexture; sprRectangle = newRectangle; //Инициализируем счетчик randNum = new Random(Speed); scrBounds = new Rectangle(0, 0, game.Window.ClientBounds.Width, game.Window.ClientBounds.Height); //Устанавливаем стартовую позицию спрайта sprPosition.X = (float)randNum.NextDouble() * (scrBounds.Width - sprRectangle.Width); sprPosition.Y = (float)randNum.NextDouble() * (scrBounds.Height - sprRectangle.Height); //Колишество шагов равно нулю stepNumber = 0; //Зададим случайный цвет для придания изображению //соответствующего оттенка sprColor = new Color((byte)randNum.Next(0, 255), (byte)randNum.Next(0, 255), (byte)randNum.Next(0, 255)); //Переменная для хранения скорости пока пуста speed = new Vector2 (); // TODO: Construct any child components here } public override void Initialize() { // TODO: Add your initialization code here base.Initialize(); } //Перемещение спрайта public virtual void Move() { //Если выполнены не все шаги if (stepNumber > 0) { //уменьшим переменную, хранящую число шагов stepNumber--; //Модифицируем координаты в соответствии с положением //объекта относительно желаемой координаты //и в соответствии со скоростью if (sprPosition.X < newPosition.X) sprPosition.X += speed.X; if (sprPosition.X > newPosition.X) sprPosition.X -= speed.X; if (sprPosition.Y < newPosition.Y) sprPosition.Y += speed.Y; if (sprPosition.Y > newPosition.Y) sprPosition.Y -= speed.Y; } //Если предыдущий шаг завершен, переменная хранит 0 if (stepNumber ==0) { //Установим случайное количество шагов stepNumber = randNum.Next(50, 200); //Сгенерируем случайную целевую позицию newPosition.X = (float)randNum.NextDouble() * (scrBounds.Width - sprRectangle.Width); newPosition.Y = (float)randNum.NextDouble() * (scrBounds.Height - sprRectangle.Height); //Установим новую скорость speed.X = randNum.Next(1, 5); speed.Y = randNum.Next(1, 5); //Зададим новый цвет спрайта sprColor = new Color((byte)randNum.Next(0, 255), (byte)randNum.Next(0, 255), (byte)randNum.Next(0, 255)); } //Вызов проверки на допустимость перемещения Check(); } //Проверка допустимости перемещения void Check() { 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; } } public override void Update(GameTime gameTime) { //Вызов метода для перемещения спрайта Move(); base.Update(gameTime); } public override void Draw(GameTime gameTime) { SpriteBatch sprBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch)); sprBatch.Draw(sprTexture, sprPosition, sprRectangle, sprColor); base.Draw(gameTime); } } }Листинг 7.14. Код компонента spriteComp
Текст снабжен комментариями, которые достаточно ясно освещают его особенности.
В листинге 7.15. приведен код класса Game1.
using System; using System.Collections.Generic; 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.Net; using Microsoft.Xna.Framework.Storage; namespace P3_7 { /// <summary> /// This is the main type for your game /// </summary> public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D texture; Random randNum; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { // TODO: Add your initialization logic here base.Initialize(); } protected override void 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 } protected void CreateNewObject() { //Цикл от 1 до случайного числ в диапазоне 50,200 for (int i = 0; i < randNum .Next (50,200); i++) { //Добавляем в список компонентов новый компонент класса spriteComp Components.Add(new spriteComp(this, ref texture, new Rectangle(16, 203, 17, 17), i)); } } protected override void UnloadContent() { } protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here spriteBatch.Begin(); base.Draw(gameTime); spriteBatch.End(); } } }Листинг 7.15. Код класса Game1
В целом код этого класса уже хорошо знаком вам по предыдущим примерам. Поэтому обратите особое внимание на процедуру CreateNewObject(). Она содержит циклический вызов метода Add объекта Components, который добавляет в список игровых объектов новый объект типа spriteComp. Номер итерации передается в объект для инициализации генератора случайных чисел. Если принудительно не инициализировать генераторы случайных чисел созданных объектов разными значениями – это приведет к неправильной работе программы – все объекты будут выведены в одной и той же позиции (если объектов много – то в нескольких позициях).
Такой подход позволяет создавать нужное количество объектов, не заботясь о создании объектных переменных. На одном из следующих занятий мы рассмотрим методы работы с такими объектами. На рис. 7.3. вы можете видеть игровое окно проекта P3_7.
Работа с игровым манипулятором
Для работы с игровым манипулятором служит объект GamePad. Сохранить состояние объекта можно в переменной типа GamePadState. Эта переменная хранит информацию об элементах управления, которые расположены на устройстве. Надо отметить, что игровой манипулятор поддерживает вибрацию – разрабатывая игру, рассчитанная на управление манипулятором, включая в нужный момент вибрацию можно сделать ее интереснее.