Невозможно пройти тесты, в окне с вопросами пусто |
Опубликован: 14.08.2012 | Уровень: специалист | Доступ: платный
Самостоятельная работа 15:
Многоуровневые игры
Рассмотрим коды классов, которые используются в игре.
В листинге 21.1 приведен код класса Game1.
using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input.Touch; using Microsoft.Devices; namespace P15_1 { /// <summary> /// Это главный тип игры /// </summary> public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; //Текстуры Texture2D txtBack, txtBrick1, txtBrick2, txtBat, txtBall; Texture2D txtBrBuild1, txtBrBuild2, txtBrBuild0; Texture2D txtArrows, txtToGame, txtToConstr; //Массивы для хранения данных об уровнях public byte[,] Layer1, Layer2, Layer3, UserLayer; //Прямоугольник для фона Rectangle recBack = new Rectangle(0, 0, 480, 800); //Прямоугольник для "блока" Rectangle recBrick = new Rectangle(0, 0, 64, 16); //Прямоугольник для "мяча" Rectangle recBall = new Rectangle(0, 0, 10, 10); //Прямоугольник для биты Rectangle recBat = new Rectangle(0, 0, 96, 16); //Номер текущего уровня //1 - первый //2 - второй //3 - третий //-1 - пользовательский int currentLayer; //Установлена в false, если программа находится в //режиме игры, при установке в True включается //режим конструктора bool IsBuild; //Позиция указателя в режиме конструктора Vector2 PositionBuild; //Тип блока, который будет добавлен на игровое поле //при поступлении соответствующей команды в режиме //конструктора byte typeOfBuildBlock; //Прямоугольники для элементов управления Rectangle keyGameOrBuild = new Rectangle(0, 0, 480, 100); Rectangle keyChange = new Rectangle(90, 600, 100, 100); Rectangle keyUp = new Rectangle(190, 600, 100, 100); Rectangle keyOK = new Rectangle(290, 600, 100, 100); Rectangle keyLeft = new Rectangle(90, 700, 100, 100); Rectangle keyDown = new Rectangle(190, 700, 100, 100); Rectangle keyRight = new Rectangle(290, 700, 100, 100); public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; graphics.IsFullScreen = true; graphics.SupportedOrientations = DisplayOrientation.Portrait; graphics.PreferredBackBufferHeight = 800; graphics.PreferredBackBufferWidth = 480; // Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду. TargetElapsedTime = TimeSpan.FromTicks(333333); // Дополнительный заряд аккумулятора заблокирован. InactiveSleepTime = TimeSpan.FromSeconds(1); } /// <summary> /// Позволяет игре выполнить инициализацию, необходимую перед запуском. /// Здесь можно запросить нужные службы и загрузить неграфический /// контент. Вызов base.Initialize приведет к перебору всех компонентов и /// их инициализации. /// </summary> protected override void Initialize() { //Программа находится в игровом режиме IsBuild = false; //Позиция для указателя в режиме конструктора (0,0) PositionBuild = new Vector2(0, 0); //Тип блока по умолчанию в режиме конструктора - 1 typeOfBuildBlock = 1; //пользовательский уровень по умолчанию пуст - ячейки //заполнены нулями UserLayer = new byte[50, 7]; //Заполняем массивы для разных уровней //0 - пустая ячейка //1 - блок первого типа (уничтожимый) //2 - блок второго типа (неуничтожимый) Layer1 = new byte[50, 7]{ {1,1,1,1,1,1,1}, {0,1,0,1,0,1,0}, {1,0,1,0,1,0,1}, {0,1,0,1,0,1,0}, {1,0,1,0,1,0,1}, {0,1,0,1,0,1,0}, {0,0,0,0,0,0,0}, {2,0,0,2,0,0,2}, {0,1,0,0,0,0,0}, {0,0,1,0,0,0,1}, {0,0,0,1,0,1,0}, {0,0,0,0,1,0,0}, {1,1,1,1,1,1,1}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, }; Layer2 = new byte[50, 7]{ {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,1,2,1,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, }; Layer3 = new byte[50, 7]{ {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,1,2,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,1,1,1,1,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,1,2,0,2,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,1,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,1,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,1,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,1,1,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, }; //Текущий уровень - 1 currentLayer = 1; base.Initialize(); } /// <summary> /// LoadContent будет вызываться в игре один раз; здесь загружается /// весь контент. /// </summary> protected override void LoadContent() { // Загружаем ресурсы spriteBatch = new SpriteBatch(GraphicsDevice); Services.AddService(typeof(SpriteBatch), spriteBatch); txtBack = Content.Load<Texture2D>("Back"); txtBrick1 = Content.Load<Texture2D>("Brick1"); txtBrick2 = Content.Load<Texture2D>("Brick2"); txtBall = Content.Load<Texture2D>("Ball"); txtBat = Content.Load<Texture2D>("Bat"); txtBrBuild0 = Content.Load<Texture2D>("BrickBuild0"); txtBrBuild1 = Content.Load<Texture2D>("BrickBuild1"); txtBrBuild2 = Content.Load<Texture2D>("BrickBuild2"); txtArrows = Content.Load<Texture2D>("Arrows"); txtToGame = Content.Load<Texture2D>("ToGame"); txtToConstr = Content.Load<Texture2D>("ToConstr"); //Создаем уровень AddSprites(Layer1); //Добавляем биту и мяч addBallAndBAts(); } //Процедура создания уровня //расставляет элементы в соответствии с //массивом void AddSprites(byte[,] RenderLayer) { //Просматриваем массив for (int i = 0; i < 50; i++) { for (int j = 0; j < 7; j++) { if (RenderLayer[i, j] == 1) Components.Add(new Brick1(this, ref txtBrick1, new Vector2(j, i), recBrick, 64, 16)); if (RenderLayer[i, j] == 2) Components.Add(new Brick2(this, ref txtBrick2, new Vector2(j, i), recBrick, 64, 16)); } } } //Процедура для установки биты и мяча void addBallAndBAts() { Components.Add(new Ball(this, ref txtBall, new Vector2(300, 750), recBall, 1, 1)); Components.Add(new Bat(this, ref txtBat, new Vector2(300, (800 - 16)), recBat, 1, 1)); } /// <summary> /// UnloadContent будет вызываться в игре один раз; здесь выгружается /// весь контент. /// </summary> protected override void UnloadContent() { // ЗАДАЧА: выгрузите здесь весь контент, не относящийся к ContentManager } //Проверка попадания касания в область, занимаемую одним из элементов управления private bool MenuSelect(Rectangle m, Vector2 p) { bool res = false; if (p.X > m.X && p.X < m.X + m.Width && p.Y > m.Y && p.Y < m.Y + m.Height) { res = true; } return res; } /// <summary> /// Позволяет игре запускать логику обновления мира, /// проверки столкновений, получения ввода и воспроизведения звуков. /// </summary> /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param> protected override void Update(GameTime gameTime) { // Позволяет выйти из игры if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); TouchCollection touchLocations = TouchPanel.GetState(); //Если находимся в игровом режиме if (!IsBuild) { foreach (TouchLocation touchLocation in touchLocations) { if (touchLocation.State == TouchLocationState.Pressed) { //Если пользователь коснулся кнопки для перехода в режим конструктора if (MenuSelect(keyGameOrBuild, touchLocation.Position)) { //Включаем конструктор уровней IsBuild = true; builder(); } } } } //Если мы уже в конструкторе else { foreach (TouchLocation touchLocation in touchLocations) { if (touchLocation.State == TouchLocationState.Pressed) { //Ищем попадание точки касания в один из элементов управления //Стрелка вверх if (MenuSelect(keyUp, touchLocation.Position)) { if (PositionBuild.Y > 0) PositionBuild.Y--; } //Стрелка вниз if (MenuSelect(keyDown, touchLocation.Position)) { if (PositionBuild.Y < 49) PositionBuild.Y++; } //Стрелка влево if (MenuSelect(keyLeft, touchLocation.Position)) { if (PositionBuild.X > 0) PositionBuild.X--; } //Стрелка вправо if (MenuSelect(keyRight, touchLocation.Position)) { if (PositionBuild.X < 6) PositionBuild.X++; } //Кнопка изменения блока if (MenuSelect(keyChange, touchLocation.Position)) { //Всего три вида блоков //Циклически изменяем вид блока при нажатии typeOfBuildBlock++; if (typeOfBuildBlock == 3) typeOfBuildBlock = 0; } //Кнопка подтверждения if (MenuSelect(keyOK, touchLocation.Position)) { //Записываем данные о позиции блока в соответствующую ячейку массива //хранящего пользовательский уровень UserLayer[(int)PositionBuild.Y, (int)PositionBuild.X] = typeOfBuildBlock; } //очищаем массив компонентов Components.Clear(); //выводим пользовательский уровень AddSprites(UserLayer); //уничтожаем указатель и изменяем его в соответствии с типом выбранного блока BrickBuilder br = null; if (typeOfBuildBlock == 1) br = new BrickBuilder(this, ref txtBrBuild1, PositionBuild, recBrick, 64, 16); if (typeOfBuildBlock == 2) br = new BrickBuilder(this, ref txtBrBuild2, PositionBuild, recBrick, 64, 16); if (typeOfBuildBlock == 0) br = new BrickBuilder(this, ref txtBrBuild0, PositionBuild, recBrick, 64, 16); Components.Add(br); //Если нажата кнопка перехода в игровой режим if (MenuSelect(keyGameOrBuild, touchLocation.Position)) { //укажем, что режим конструирования не активен IsBuild = false; Components.Clear(); AddSprites(UserLayer); addBallAndBAts(); //запустим игру с уровнем -1 currentLayer = -1; } } } } //Если находимся в режиме игры //проверим - завершен ли текущий уровень //признак завершения уровня if (!IsBuild) { IsLayerCompleted(); } base.Update(gameTime); } //Процедура старта конструктора уровней //очищаем набор компонентов //Создаем и выводим указатель public void builder() { Components.Clear(); BrickBuilder br = new BrickBuilder(this, ref txtBrBuild1, PositionBuild, recBrick, 64, 16); Components.Add(br); } //Процедура проверки на завершенность //текущего уровня //Если на поле отсутствует мяч - игра начинается сначала //если на поле нет ни одного блока типа Brick1 - //переход на следующий уровень или переход на первый уровень //с выводом надписи "Вы выиграли" public void IsLayerCompleted() { //Предположим, что на поле нет ни одного блока //типа Brick1 bool f = false; //Предположим, что на поле нет мяча bool Ball = false; foreach (gBaseClass spr in this.Components) { //Если найден хотя бы один блок типа 1 //установим F в True if (spr.GetType() == (typeof(Brick1))) { f = true; } //Если найден мяч - установим Ball в True if (spr.GetType() == (typeof(Ball))) { Ball = true; } } //Если мяч не обнаружен //игра начинается сначала if (!Ball) { Components.Clear(); currentLayer = 1; AddSprites(Layer1); addBallAndBAts(); } //иначе else { //Если не было найдено ни одного блока //типа Brick1 if (!f) { //Очистим набор компонентов Components.Clear(); //Увеличим номер уровня currentLayer++; //в зависимости от номера //запустим соответствующий уровень if (currentLayer == 2) { AddSprites(Layer2); addBallAndBAts(); } if (currentLayer == 3) { AddSprites(Layer3); addBallAndBAts(); } //4 - если был пройден 3-й уровень //0 - при прохождении пользовательского уровня if (currentLayer == 4 | currentLayer == 0) { currentLayer = 1; AddSprites(Layer1); addBallAndBAts(); //Включим вибраацию на 0,1 секунды VibrateController.Default.Start(TimeSpan.FromMilliseconds(100)); } } } } /// <summary> /// Вызывается, когда игра отрисовывается. /// </summary> /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param> protected override void Draw(GameTime gameTime) { spriteBatch.Begin(); //выведем фоновое изображение spriteBatch.Draw(txtBack, recBack, Color.White); //Выведем игровые объекты base.Draw(gameTime); //Если в режиме конструктора - выведем экранные элементы управления if (IsBuild) { //для управления конструированием spriteBatch.Draw(txtArrows, new Rectangle(90, 600, 300, 200), Color.White); //для перехода в игровой режим spriteBatch.Draw(txtToGame, new Rectangle(0, 0, 480, 100), Color.White); } else { //Если в игровом режиме - выведем элемент управления //для перехода в конструктор spriteBatch.Draw(txtToConstr, new Rectangle(0, 0, 480, 100), Color.White); } spriteBatch.End(); } } }Листинг 21.1. Код класса Game1