Игровая программа "Wall on Wall"

Тип работы:
Курсовая
Предмет:
Программирование


Узнать стоимость

Детальная информация о работе

Выдержка из работы

Московский Государственный Горный Университет

Кафедра САПР

Отчет

по курсовой работе

по дисциплине «Технологии программирования»

Игровая программа «Wall on Wall»

Выполнил:

Студент группы АСП-Б-11

Иванов А.А.

Москва, 2013 г.

Содержание

Введение

1. Анализ требований и уточнение спецификаций

1.1 Анализ задания, выбор технологии, языка и среды программирования

1.2 Конструкции, реализованные в программе

1.3 Анализ обрабатываемой информации и выбор структур данных для ее хранения

1.4 Анализ структуры программы

2. Проектирование программного продукта

2.1 Разработка интерфейса пользователя

2.1.1 Разработка меню

2.1.2 Разработка форм вывода данных

  • 3. Выбор стратегии тестирования и разработка тестов
    • 3.1 Анализ программного продукта и выбор стратегии тестирования
    • 3.2 Непосредственное тестирование
    • 4. Код программы
    • 5. Диаграмма классов
  • Заключение

Введение

Целью данной курсовой работы является разработка популярной развлекательной игры Wall on Wall. Программа предоставляет возможность играть против компьютера, который играет согласно созданному алгоритму. В процессе разработки должны быть усвоены некоторые новые возможности Visual Studio. В программе должны быть учтены моменты, позволяющие пользователю легко освоить программу, для этого необходимо создать удобный интерфейс, который является «визитной карточкой» приложения.

1. Анализ технических требований и уточнение спецификаций

1.1 Анализ задания, выбор технологии, языка и среды

С# -- это новый язык программирования, в котором, по замыслу создателей, должны сочетаться выразительность и простота. Его цель -- позволить программисту создавать сложные высокопроизводительные программы

C# создавался параллельно с каркасом Framework. Net и в полной мере учитывает все его возможности — как FCL, так и CLR;

C# является полностью объектно-ориентированным языком, где даже типы, встроенные в язык, представлены классами;

C# является мощным объектным языком с возможностями наследования и универсализации;

C# является наследником языков C/C++, сохраняя лучшие черты этих популярных языков программирования. Общий с этими языками синтаксис, знакомые операторы языка облегчают переход программистов от С++ к C#; сохранив основные черты своего великого родителя, язык стал проще и надежнее.

Для полного понимания языка программирования С# и его программной среды, необходимо представить важную технологию, которая непосредственно связана с С# и называется. NET.

. NET -- это общий термин для многих важных служб, которые предоставляются и используются во время создания и исполнения программы на С#. Более того, С# полностью зависит от. NET. Неудивительно, что происхождение многих особенностей и концепций С# уходит своими корнями в. NET. Вот некоторые важные службы, предоставляемые инфраструктурой. NET-платформы.

1.. NET предоставляет средства для исполнения инструкций, содержащихся в программе, написанной на С#. Эта часть. NET называется средой исполнения (execution engine).

2.. NET помогает реализовать так называемую среду, безопасную к несоответствию типов данных (type safe environment). Образно говоря,. NET обеспечивает «треугольные дырки для треугольников, квадратные -- для квадратов».

3.. NET освобождает программиста от утомительного и нередко приводящего к ошибкам процесса управления компьютерной памятью, которая используется программой.

4.. NET предоставляет безопасную среду исполнения, пытаясь усложнить жизнь хакерам и им подобным.

5. В состав. NET-платформы входит библиотека, содержащая массу готовых программных компонентов, которые можно использовать в собственных программах. Она экономит немало времени, так как программист может воспользоваться готовыми фрагментами кода. Фактически, он повторно использует код, созданный и тщательно проверенный профессиональными программистами Microsoft.

6. В. NET упрощена подготовка программы к использованию (развертывание).

Программа, при создании которой была предусмотрена возможность повторного использования, называется компонентом (программным компонентом).

Все сказанное выше о. NET -- не более чем простое перечисление некоторых свойств платформы, в которой были реализованы многие современные программные технологии.

Реализация, сочетающая построение надежного и эффективного кода, является немаловажным фактором, способствующим успеху C#.

Среда разработки Visual Studio 2010 была специально создана для нужд. NET, и располагает всеми необходимыми инструментами.

В частности, в Visual Studio 2010 имеются различные шаблоны графического интерфейса пользователя, среди которых наиболее интересными являются Windows Forms. Приложение Windows Forms представляет собой событийно-ориентированное приложение, поддерживаемое Microsoft. NET Framework.

Данный интерфейс упрощает доступ к элементам интерфейса Microsoft Windows за счет создания обертки для существующего Win32 API в управляемом коде.

Именно поэтому, было принято решение использовать язык С# и среду разработки Visual Studio 2010 для реализации поставленной задачи.

1.2 Конструкции, реализованные в программе

Курсовая работа, как уже было сказано, использует интерфейс приложения Windows Forms. В частности используются следующие пространства имен, имеющиеся в базовой комплектации Visual Studio 2010:

System — основное пространство имен, содержит базовые типы данных, методы работы с данными, файлами и winAPI. Используется повсеместно в программе.

System. Collections. Generic — пространство имен, содержащее матричные типы данных и методы работы с ними. Используется для хранения игрового поля.

System. Drawing — пространство имен, содержащее в себе различные классы для работы с графикой. Используется для отрисовки на основном окне программы различных объектов: игровое поле, крестики, нолики

System. Text — пространство имен, содержащее в себе различные классы для работы с текстом. Используется повсеместно в программе.

System. Windows. Forms — основное пространство имен разрабатываемого приложения, содержит классы, реализующие интерфейс приложений Windows Forms. Используется для создания основного окна, а так же реализации обработки взаимодействия пользователя с программой.

1.3 Анализ обрабатываемой информации и выбор структур данных для ее хранения

Основной информацией, обрабатываемой программой является состояние игрового поля — матрица 3×3, в каждой из ячеек которой может содержаться какой-либо объект (крестик, нолик или пустота).

Для однозначного задания этой информации достаточно двумерного целочисленного массива, размерностью 3×3, при этом каждый элемент этого массива может принимать значения от 0 до 2 (0 — пустота, 1 — крестик, 2 — нолик).

Кроме игрового поля, в памяти хранятся еще несколько данных:

Тип игрового искусственного интеллекта: принимает значения от 0 до 2 (0- игра с человеком, 1 — «сложный» ИИ, 2 — «простой» ИИ), для хранения используется целочисленная переменная.

Текущий ход: крестик, нолик или конец игры, для хранения используется целочисленная переменная.

Результат проверки игровой ситуации: 0 — игра не завершена, 1 — победили крестики, 2 — победили нолики, 3 — ничья, для хранения используется целочисленная переменная.

1.4 Анализ внутренней структуры программы

Основной функционал программы решено вывести в класс, отвечающий за взаимодействие с пользователем, т.к. это позволяет избежать излишней связности компонент программы, и данный класс позволяется наиболее удобным способом реализовать обработку нажатий клавиш и вывод результата работы на экран.

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

Для уменьшения сложности основного класса программы, рационально вынести функционал проверки игровой ситуации в класс игровой логики, т.о. оставив в основном классе лишь методы для взаимодействия с игроком и вывода на экран результата работы.

Концептуальная схема взаимодействия классов будет выглядеть следующим образом

2. Проектирование программного продукта

2.1 Разработка интерфейса пользователя

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

2.1.1 Разработка меню

Для обеспечения быстрой и удобной навигации пользователя по программе основные функции программы целесообразно объединить в главном меню программы.

Исследовав интерфейс программ-аналогов, функции были разделены на 1 основную группу в этой игре:

Функции игры

2.1.2 Разработка форм ввода вывода

Для ведения обмена информацией между пользователем и программой в каждом из состояний интерфейса, необходимо разработать формы ввода и вывода этой информации. Для реализации диалога была выбрана табличная форма вывода диалога.

игра алгоритм интерфейс данные

Рисунок 2 — Игровое поле

Рисунок 3 — Игровой процесс

Рисунок 4 — Монстр доходит до края поля

Рисунок 5 — Потеря 1 единицы Health`ов после прохода монстра за поле

3. Выбор стратегии тестирования и разработка тестов

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

3.1 Анализ программного продукта и выбор стратегии тестирования

Согласно методологии тестирования программного продукта различают два подхода к формированию тестовых наборов: структурный и функциональный.

Структурный подход-тестирование, при котором известна структура программного обеспечения («белый ящик»).

Функциональный подход-тестирование, при котором не известна структура программного обеспечения («черный ящик»). Этот подход целесообразно применить для тестирования алгоритмов хода и проверки игровой ситуации.

Оценочное тестирование-тестирование программы на соответсвии соответсвующим требованиям. Необходимо для анализа работы системы в целом.

В результате тестирования, проведенного на этапе разработки программы, были исправлены найденные ошибки и улучшены алгоритмы игрового процесса, используемые методами классов.

Оценочное тестирование.

Было проведено тестирование всех функций программы, в результате которого были обнаружены недостатки интерфейса, которые были устранены.

Было сделано заключение, что скорость выполнения программы практически не зависит от различных игровых ситуаций. Объем занимаемой оперативной памяти также остается практически неизменным — около 14, 5 МБ.

7 dows: о меню приведет к появлению стандартного окна вободное поле) от второго игрока, иначе ход перейдет к ИИ и после опять к

4. Код программы

Класс игрока

using System;

using System. Collections. Generic;

using System. Linq;

using System. Text;

using Microsoft. Xna. Framework;

using Microsoft. Xna. Framework. Input;

using Microsoft. Xna. Framework. Graphics;

namespace WoW2

{

public class Player

{

//Состояние игрока

private int money = 100;

private int lives = 10;

private Texture2D[] creepTextures; //Текстура «Монстра» игрока

private Texture2D bulletTexture; //Текстура снаряда

private List< Creep> creeps = new List< Creep>(); //Список «Монстров» игрока

private MouseState mouseState; //состояние мыши для данного фрейма

private MouseState oldState; //состояние мыши для предыдущего фрейма

//Расположение «Монстров» игрока

private int cellX;

private int cellY;

private int tileX;

private int tileY;

private string newCreepType; //тип «монстра» длядобавления

private int newCreepIndex; //показатель новой текстуры"монстра"

private Level level; //справка об уровне

public int Money

{

get { return money; }

set { money = value; }

}

public int Lives

{

get { return lives; }

set { lives = value; }

}

public string NewCreepType

{

set { newCreepType = value; }

}

public int NewCreepIndex

{

set { newCreepIndex = value; }

}

/// < summary>

/// Создание новго игрока

/// < /summary>

public Player (Level level, Texture2D[] creepTextures, Texture2D bulletTexture)

{

this. level = level;

this. creepTextures = creepTextures;

this. bulletTexture = bulletTexture;

}

/// < summary>

/// Returns wether the current cell is clear

/// < /summary>

private bool IsCellClear ()

{

bool inBounds = cellX >= 0 & & cellY >= 0 & &

cellX < level. Width & & cellY < level. Height;

bool spaceClear = true;

// Check that there is no creep in this spot

foreach (Creep creep in creeps)

{

spaceClear = (creep. Position ≠ new Vector2(tileX, tileY));

if (!spaceClear)

{

break;

}

}

bool onPath = (level. GetIndex (cellX, cellY) ≠ 1);

return inBounds & & spaceClear & & onPath; // If both checks are true return true

}

/// < summary>

/// Adds a creep to the player’s collection.

/// < /summary>

public void AddCreep ()

{

Creep creepToAdd = null;

switch (newCreepType)

{

case «Car Creep»:

{

creepToAdd = new CarCreep (creepTextures[0],

bulletTexture, new Vector2(tileX, tileY));

break;

}

case «Tank Creep»:

{

creepToAdd = new TankCreep (creepTextures[1],

bulletTexture, new Vector2(tileX, tileY));

break;

}

}

// Only add the tower if there is a space and if the player can afford it.

if (IsCellClear () == true & & creepToAdd. Cost <= money)

{

creeps. Add (creepToAdd);

money -= creepToAdd. Cost;

// Reset the newTowerType field.

newCreepType = string. Empty;

}

else

{

newCreepType = string. Empty;

}

}

/// < summary>

/// Updates the player.

/// < /summary>

public void Update (GameTime gameTime, List< Enemy> enemies)

{

mouseState = Mouse. GetState ();

cellX = (int)(mouseState.X / 32); // Convert the position of the mouse

cellY = (int)(mouseState.Y / 32); // from array space to level space

tileX = cellX * 32; // Convert from array space to level space

tileY = cellY * 32; // Convert from array space to level space

if (mouseState. LeftButton == ButtonState. Released

& & oldState. LeftButton == ButtonState. Pressed)

{

if (string. IsNullOrEmpty (newCreepType) == false)

{

AddCreep ();

}

}

foreach (Creep creep in creeps)

{

// Make sure the creep has no targets.

if (creep. HasTarget == false)

{

creep. GetClosestEnemy (enemies);

}

creep. Update (gameTime);

}

oldState = mouseState; // Set the oldState so it becomes the state of the previous frame.

}

public void Draw (SpriteBatch spriteBatch)

{

foreach (Creep creep in creeps)

{

creep. Draw (spriteBatch);

}

}

public void DrawPreview (SpriteBatch spriteBatch)

{

// Draw the creep preview.

if (string. IsNullOrEmpty (newCreepType) == false)

{

int cellX = (int)(mouseState.X / 32); // Convert the position of the mouse

int cellY = (int)(mouseState.Y / 32); // from array space to level space

int tileX = cellX * 32; // Convert from array space to level space

int tileY = cellY * 32; // Convert from array space to level space

Texture2D previewTexture = creepTextures[newCreepIndex];

spriteBatch. Draw (previewTexture, new Rectangle (tileX, tileY,

previewTexture. Width, previewTexture. Height), Color. White);

}

}

Класс меню

using System;

using System. Collections. Generic;

using System. Linq;

using System. Text;

using Microsoft. Xna. Framework. Input;

using Microsoft. Xna. Framework;

using Microsoft. Xna. Framework. Graphics;

namespace WoW2

{

public enum ButtonStatus//Описываем состояние кнопки

{

Normal,

MouseOver,

Pressed,

}

public class Button: Sprite //Хранит внешний вид и функциональность кнопки.

{

private MouseState previousState; //Сохраняет состояние мыши последнего фрейма

private Texture2D hoverTexture;

private Texture2D pressedTexture; //Состояния текстур

private Rectangle bounds; //Прямоугольник, охватывающий кнопку

private ButtonStatus state = ButtonStatus. Normal;//Сохраняет текущее состояние кнопки

public event EventHandler Clicked; //Срабатывает при клике кнопки

public event EventHandler OnPress; //Срабатывает при зажатой кнопке

///< summary>

///Создаем новую кнопку

///< /summary>

/// < param name="texture"> Нормальная текстура кнопки< /param>

/// < param name="hoverTexture"> Текстура рисуемая, когда наведенна мышь на кнопку< /param>

/// < param name="pressedTexture"> Текстура рисуемая, когда кнопка нажата< /param>

/// < param name="position"> Расположение, где кнопка будет нарисованна< /param>

public Button (Texture2D texture, Texture2D hoverTexture, Texture2D pressedTexture, Vector2 position)

: base (texture, position)

{

this. hoverTexture = hoverTexture;

this. pressedTexture = pressedTexture;

this. bounds = new Rectangle ((int)position. X, (int)position. Y,

texture. Width, texture. Height);

}

///< summary>

///Обновляем состояник кнопки

///< /summary>

///< param name="gameTime"> Текущее игровое время< /param>

public override void Update (GameTime gameTime)

{

MouseState mouseState = Mouse. GetState ();//Определение, находится ли мышь над кнопкой

int mouseX = mouseState. X;

int mouseY = mouseState. Y;

bool isMouseOver = bounds. Contains (mouseX, mouseY);

if (isMouseOver & & state ≠ ButtonStatus. Pressed)//Обновление состояния кнопки

{

state = ButtonStatus. MouseOver;

}

else if (isMouseOver == false & & state ≠ ButtonStatus. Pressed)

{

state = ButtonStatus. Normal;

}

if (mouseState. LeftButton == ButtonState. Pressed & &

previousState. LeftButton == ButtonState. Released)//Проверяем нажата ли кнопка игроком

{

if (isMouseOver == true)

{

state = ButtonStatus. Pressed;//обновляем состояние кнопки

if (OnPress ≠ null)

{

OnPress (this, EventArgs. Empty);//Запускаем событие Нажата (OnPress)

}

}

}

if (mouseState. LeftButton == ButtonState. Released & &

previousState. LeftButton == ButtonState. Pressed)//Проверяем отпустил ли игрок кнопку

{

if (isMouseOver == true)

{

state = ButtonStatus. MouseOver;//Обновляем состояние кнопки

if (Clicked ≠ null)

{

Clicked (this, EventArgs. Empty);//Запускаем событие Клика (Clicked)

}

}

else if (state == ButtonStatus. Pressed)

{

state = ButtonStatus. Normal;

}

}

previousState = mouseState;

}

/// < summary>

/// Рисуем кнопку

/// < /summary>

/// < param name="spriteBatch"> SpriteBatch, который начат< /param>

public override void Draw (SpriteBatch spriteBatch)

{

switch (state)

{

case ButtonStatus. Normal:

spriteBatch. Draw (texture, bounds, Color. White);

break;

case ButtonStatus. MouseOver:

spriteBatch. Draw (hoverTexture, bounds, Color. White);

break;

case ButtonStatus. Pressed:

spriteBatch. Draw (pressedTexture, bounds, Color. White);

break;

default:

spriteBatch. Draw (texture, bounds, Color. White);

break;

}

}

}

}

using System;

using System. Collections. Generic;

using System. Linq;

using System. Text;

using Microsoft. Xna. Framework;

using Microsoft. Xna. Framework. Graphics;

namespace WoW2

{

public class Toolbar

{

private Texture2D texture;

private SpriteFont font; //класс для доступа к шрифту, который создаем

private Vector2 position; //место расположения тулбара

private Vector2 textPosition; //место расположения текста

public Toolbar (Texture2D texture, SpriteFont font, Vector2 position)

{

this. texture = texture;

this. font = font;

this. position = position; //расположение текста в правом нижнем углу

textPosition = new Vector2(130, position. Y + 10);

}

public void Draw (SpriteBatch spriteBatch, Player player)

{

spriteBatch. Draw (texture, position, Color. White);

string text = string. Format («Gold: {0} Lives: {1}», player. Money, player. Lives);

spriteBatch. DrawString (font, text, textPosition, Color. White);

}

}

}

Класс передвижения и отрисовки противника

using System;

using System. Collections. Generic;

using System. Linq;

using System. Text;

using Microsoft. Xna. Framework;

using Microsoft. Xna. Framework. Graphics;

namespace WoW2

{

public class Enemy: Sprite

{

private Queue< Vector2> waypoints = new Queue< Vector2>();

private float speedModifier;

private float modifierDuration;

private float modiferCurrentTime;

protected float startHealth;

protected float currentHealth;

protected bool alive = true;

protected float speed = 0. 5f;

protected int bountyGiven;

/// < summary>

/// Изменяет скорость врага

/// < /summary>

public float SpeedModifier

{

get { return speedModifier; }

set { speedModifier = value; }

}

/// < summary>

/// Определяет, как долго модификация скорости продлится

/// < /summary>

public float ModifierDuration

{

get { return modifierDuration; }

set

{

modifierDuration = value;

modiferCurrentTime = 0;

}

}

public float CurrentHealth

{

get { return currentHealth; }

set { currentHealth = value; }

}

/// < summary>

/// % оставшегося у врага здоровья

/// < /summary>

public float HealthPercentage

{

get { return currentHealth / startHealth; }

}

public bool IsDead

{

get { return! alive; }

}

public int BountyGiven

{

get { return bountyGiven; }

}

public float DistanceToDestination

{

get { return Vector2. Distance (position, waypoints. Peek ()); }

}

public Enemy (Texture2D texture, Vector2 position, float health, int bountyGiven, float speed)

: base (texture, position)

{

this. startHealth = health;

this. currentHealth = startHealth;

this. bountyGiven = bountyGiven;

this. speed = speed;

}

public void SetWaypoints (Queue< Vector2> waypoints)

{

foreach (Vector2 waypoint in waypoints)

this. waypoints. Enqueue (waypoint);

this. position = this. waypoints. Dequeue ();

}

public override void Update (GameTime gameTime)

{

base. Update (gameTime);

if (waypoints. Count > 0)

{

if (DistanceToDestination < 1f)

{

position = waypoints. Peek ();

waypoints. Dequeue ();

}

else

{

Vector2 direction = waypoints. Peek () — position;

direction. Normalize ();

float temporarySpeed = speed; //СОдержит оригинальную скорость передвижения

if (modiferCurrentTime > modifierDuration)// если закончилась модификация

{

//Сбрасывает модификацию

speedModifier = 0;

modiferCurrentTime = 0;

}

if (speedModifier ≠ 0 & & modiferCurrentTime <= modifierDuration)

{

temporarySpeed *= speedModifier; // Изменить скорость врага

modiferCurrentTime += (float)gameTime. ElapsedGameTime. TotalSeconds;// Обновить время модификации

}

velocity = Vector2. Multiply (direction, temporarySpeed);

position += velocity;

}

}

else

alive = false;

if (currentHealth <= 0)

alive = false;

}

public override void Draw (SpriteBatch spriteBatch)

{

if (alive)

{

base. Draw (spriteBatch, Color. Black);

}

}

}

}

Класс игры

using System;

using System. Collections. Generic;

using System. Linq;

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. Media;

namespace WoW2

{

public class Game1: Microsoft. Xna. Framework. Game

{

GraphicsDeviceManager graphics;

SpriteBatch spriteBatch;

Level level = new Level ();

WaveManager waveManager;

Player player;

Button carButton;

Button tankButton;

Toolbar toolBar;

public Game1()

{

graphics = new GraphicsDeviceManager (this);

Content. RootDirectory = «Content»;

graphics. PreferredBackBufferWidth = level. Width * 32;

graphics. PreferredBackBufferHeight = 32 + level. Height * 32;

graphics. ApplyChanges ();

IsMouseVisible = true;

}

protected override void Initialize ()

{

base. Initialize ();

}

protected override void LoadContent ()

{

spriteBatch = new SpriteBatch (GraphicsDevice);

Texture2D topBar = Content. Load<Texture2D>(«tool bar»);

SpriteFont font = Content. Load<SpriteFont>(«Arial»);

toolBar = new Toolbar (topBar, font, new Vector2(0, level. Height * 32));

Texture2D grass = Content. Load<Texture2D>(«grass»);

Texture2D path = Content. Load<Texture2D>(«path»);

level. AddTexture (grass);

level. AddTexture (path);

Texture2D bulletTexture = Content. Load<Texture2D>(«bullet»);

Texture2D[] creepTexture = new Texture2D[]

{

Content. Load<Texture2D>(«Car»),

Content. Load<Texture2D>(«Tank»),

};

player = new Player (level, creepTexture, bulletTexture);

Texture2D enemyTexture = Content. Load<Texture2D>(«enemy»);

Texture2D healthTexture = Content. Load<Texture2D>(«health bar»);

waveManager = new WaveManager (player, level, 24, enemyTexture,

healthTexture);

Texture2D carNormal = Content. Load<Texture2D>(«GUI\Car creep\car button»);

Texture2D carHover = Content. Load<Texture2D>(«GUI\Car creep\car hover»);

Texture2D carPressed = Content. Load<Texture2D>(«GUI\Car creep\car pressed»);

Texture2D tankNormal = Content. Load<Texture2D>(«GUI\Tank creep\tank button»);

Texture2D tankHover = Content. Load<Texture2D>(«GUI\Tank creep\tank hover»);

Texture2D tankPressed = Content. Load<Texture2D>(«GUI\Tank creep\tank pressed»);

carButton = new Button (carNormal, carHover,

carPressed, new Vector2(0, level. Height * 32));

tankButton = new Button (tankNormal, tankHover,

tankPressed, new Vector2(32, level. Height * 32));

carButton. OnPress += new EventHandler (carButton_OnPress);

tankButton. OnPress += new EventHandler (tankButton_OnPress);

}

protected override void UnloadContent ()

{

}

private void carButton_OnPress (object sender, EventArgs e)

{

player. NewCreepType = «Car creep»;

player. NewCreepIndex = 0;

}

private void tankButton_OnPress (object sender, EventArgs e)

{

player. NewCreepType = «Tank creep»;

player. NewCreepIndex = 1;

}

protected override void Update (GameTime gameTime)

{

waveManager. Update (gameTime);

player. Update (gameTime, waveManager. Enemies);

carButton. Update (gameTime);

tankButton. Update (gameTime);

base. Update (gameTime);

}

protected override void Draw (GameTime gameTime)

{

GraphicsDevice. Clear (Color. CornflowerBlue);

spriteBatch. Begin ();

level. Draw (spriteBatch);

player. Draw (spriteBatch);

waveManager. Draw (spriteBatch);

toolBar. Draw (spriteBatch, player);

carButton. Draw (spriteBatch);

tankButton. Draw (spriteBatch);

player. DrawPreview (spriteBatch);

spriteBatch. End ();

base. Draw (gameTime);

}

}

}

Класс

using System;

using System. Collections. Generic;

using System. Linq;

using System. Text;

using Microsoft. Xna. Framework;

using Microsoft. Xna. Framework. Graphics;

namespace WoW2

{

public class WaveManager

{

private int numberOfWaves;

private float timeSinceLastWave;

private Queue< Wave> waves = new Queue< Wave>();

private Texture2D enemyTexture;

private bool waveFinished = false;

private Level level;

public Wave CurrentWave

{

get { return waves. Peek (); }

}

public List< Enemy> Enemies

{

get { return CurrentWave. Enemies; }

}

public int Round

{

get { return CurrentWave. RoundNumber + 1; }

}

public WaveManager (Player player, Level level, int numberOfWaves,

Texture2D enemyTexture, Texture2D healthTexture)

{

this. numberOfWaves = numberOfWaves;

this. enemyTexture = enemyTexture;

this. level = level;

for (int i = 0; i < numberOfWaves; i++)

{

int initialNumberOfEnemies = 10;

int numberModifier = (i / 10) + 1;

Wave wave = new Wave (i, initialNumberOfEnemies * numberModifier,

player, level, enemyTexture, healthTexture);

waves. Enqueue (wave);

}

StartNextWave ();

}

private void StartNextWave ()

{

if (waves. Count > 0)

{

waves. Peek (). Start ();

timeSinceLastWave = 0;

waveFinished = false;

}

}

public void Update (GameTime gameTime)

{

CurrentWave. Update (gameTime);

if (CurrentWave. RoundOver)

{

waveFinished = true;

}

if (waveFinished)

{

timeSinceLastWave += (float)gameTime. ElapsedGameTime. TotalSeconds;

}

if (timeSinceLastWave > 30. 0f)

{

waves. Dequeue ();

StartNextWave ();

}

}

public void Draw (SpriteBatch spriteBatch)

{

CurrentWave. Draw (spriteBatch);

}

}

}

Класс отрисовки карты

using System;

using System. Collections. Generic;

using System. Text;

using Microsoft. Xna. Framework;

using Microsoft. Xna. Framework. Graphics;

namespace WoW

{

public class Level

{

private List< Texture2D> tileTextures = new List< Texture2D>();

private Queue< Vector2> waypoints = new Queue< Vector2>();

int[,] map = new int[,]

{

{1,0,0,0,0,0,0,0,},

{1,0,0,0,0,0,0,0,},

{1,0,0,0,0,0,0,0,},

{1,0,0,0,0,0,0,0,},

{1,0,0,0,0,0,0,0,},

{1,0,0,0,0,0,0,0,},

{1,0,0,0,0,0,0,0,},

{1,0,0,0,0,0,0,0,},

};

public Queue< Vector2> Waypoints

{

get { return waypoints; }

}

public int Width

{

get { return map. GetLength (1); }

}

public int Height

{

get { return map. GetLength (0); }

}

public Level ()

{

waypoints. Enqueue (new Vector2(7, 0) * 32);

waypoints. Enqueue (new Vector2(0, 0) * 32);

}

public int GetIndex (int cellX, int cellY)

// It needed to be Width — 1 and Height — 1.

if (cellX < 0

public void AddTexture (Texture2D texture)

{

tileTextures. Add (texture);

}

public void Draw (SpriteBatch batch)

{

for (int x = 0; x < Width; x++)

{

for (int y = 0; y < Height; y++)

{

int textureIndex = map[y, x];

if (textureIndex == -1)

continue;

Texture2D texture = tileTextures[textureIndex];

batch. Draw (texture, new Rectangle (x * 32, y * 32, 32, 32), Color. White);

}

}

5. Диаграмма классов

Заключение

В результате курсовой работы была разработана игровая игра «Wall on Wall», реализующая базовый функционал данной игры, а так же простейшие алгоритмы искусственного интеллекта, позволяющие играть в одиночку.

ПоказатьСвернуть
Заполнить форму текущей работой