| Невозможно пройти тесты, в окне с вопросами пусто |
Опубликован: 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