Разработка приложения, состоящего из прикладного окна
Разработка оконного приложения на языке C#, в окне которого будет игра "Лабиринт. Диаграмма вариантов использования языка UML. Описание разрабатываемой программы с точки зрения программиста. Разработка прикладного окна, классов Enemy и Dot, Wall и Map.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 22.06.2015 |
Размер файла | 457,6 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Министерство общего и профессионального образования
Российской Федерации
Казанский государственный технический университет
имени. А.Н. Туполева
Кафедра АСОИУ
Курсовая работа
по дисциплине «Технология программирования»
Исполнитель:
студент группы
Руководитель:
Оценка _____________________
Подпись_____________________
Казань 2015
Оглавление
- 1. Введение
- 1.1 Задание
- 1.2 Уточнение задания
- 2. Аннотация
- 3. Описание разрабатываемой программы с точки зрения пользователя
- 4. Описание разрабатываемой программы с точки зрения программиста
- 4.1 Объектное представление программы
- 4.2 События
- 4.3. Потоки
- 5. Поэтапная разработка программной системы
- 5.1 Разработка класса обычного объекта
- 5.2 Разработка классов Enemy и Dot
- 5.3 Разработка классов Wall и Map
- 5.4 Разработка прикладного окна
- 5.5 Разработка собственных Exception и Логгера
- 6. Описание проблем, возникших при разработке программной системы.
- 7. Заключение
- 8. Список используемой литературы
- Приложения
- 1. Введение
1.1 Задание
Разработать оконное приложение, в окне которого будет лабиринт.
По лабиринту должны перемещать враг. Игрок, должен убегая от врагов собирать монетки.
Программа должна содержать:
1 классы
2 наследование
3 объекты
4 потоки
5 синхронизация потоков
6 делегаты и события
7 обработка исключений
8 Минимум 3 пункта меню, 2 из них должны содержать 3 подпункта.
1.2 Уточнение задания
Программа состоит их прикладного окна. В области клиента прикладного окна расположен лабиринт. В игре несколько уровней. Каждый уровень представлен в виде квадратной матрицы где 0 это монетка, 1 стена, 2 игрок, 3 враг. Враги и игрок представлены в виде квадратов, на которые наложены изображения. Каждый враг и игрок имеют свой поток.
Окно так же содержит меню, в котором есть кнопки запуска игры, выбора уровней, отключения изображений и включения коллизий.
Программы реализовать в среде Microsoft Visual Studio 2013 на языке C#.
2. Аннотация
В данной курсовой работе рассмотрены следующие инструменты для разработки программного обеспечения на языке C#: Классы, делегаты, работа с потоками, обработка исключений, наследование, работа с окнами и меню. Была рассмотрена пошаговая разработка приложения.
3. Описание разрабатываемой программы с точки зрения пользователя
Программа представлена прикладным окном. В окне перемещаются n врагов.
Окно так содержит меню, в котором есть кнопки запуска игры, выбора уровней, отключения изображений и включения коллизий.
Диаграмма вариантов использования языка UML изображает действия, выполняемые пользователем программы. С точки зрения пользователя приложение предполагает три варианта использования:
· запустить игру
· перезапустить уровень
· загрузить уровень
· отключить/включить изображения
· отключить/включить показ столкновений
· сбросить прохождение
· открыть окошко «об игре»
· управлять персонажем с помощью клавиш
Диаграмма вариантов использования представлена на рис. 3.1.
Рис. 3.1. Диаграмма вариантов использования приложения
Прекращение выполнения программы происходит при закрытии прикладного окна или при нажатии меню «выход»
4. Описание разрабатываемой программы с точки зрения программиста
4.1 Объектное представление программы
Программа включает объекты разных типов. Главными объектами программы являются объект прикладного окна класса MainWindow. При старте игры уровень считывается из файла в 2мерный List. Класс Map создает все Entity расположенные на уровне (классы Player, Enemy, Dot). Класс Wall строит лабиринт. После срабатывания события LevelLoad, экземпляры Player, Enemy и Map запускают потоки. Все все созданные игровые объекты хранятся в списке _entities. Map в цикле пробегается по каждого игрового объекта и проверяет его пересечение со всеми остальными, а также посылает в Wall для проверки пересечения со стеной. Wall приводит координаты объекта к индексу в матрице и проверяет ячейку на наличие там стены. В случае столкновения объекта с другим у обоих объектов вызывается соответственная функция:
При столкновения игрока с врагом тратится жизнь.
При столкновении игрока с монетой, увеличиваются очки, монета исчезает.
Если игрок столкнулся с врагом при 0 жизней, игрок умирает, а уровень перезагружается. Когда игрок съедает все монеты, загружается следующий уровень.
При столкновении со стеной объект выезжает из стены (Player останавливается, а Enemy произвольно меняет направление движения). Во время движения, каждый раз, когда по бокам от Enemy есть пустые ячейки, Enemy произвольно может сменить направление с шансом от 30 до 70% (процент смены направления генерируется случайно в пределах заданного значения для каждого экземпляра).
4.2 События
В программе имеются несколько событий.
LevelLoad - Генерирует Map когда полностью создан уровень.
RestartLevel - Генерирует Map когда уровень перезагружается.
OnKeyDown - системное событие нажатия клавиши;
onKeyUp - системное событие отпускания клавиши;
4.3 Потоки
приложение окно игра
Помимо основных потоков wpf, в программе используется дополнительные потоки. Класс Map создает поток для проверки коллизии. Враги и Игрок также имеют свой собственный поток для каждого экземпляра, в которых они перемещаются и реагируют на события.
5. Поэтапная разработка программной системы
Разработка приложения будет осуществляться поэтапно. Вначале разработаем класс Map и Wall, которые будут отвечать за сцену. Создадим класс Player, и сделаем передвижение игрока по нажатию на кнопки. Затем создадим базовый класс Entity от которого наследуем класс Player потокового объекта и протестируем его. Вынесем в Entity базовые свойства игровых объектов. Создадим механизм проверки столкновений со стеной. Затем создадим и отладим класс Enemy, и протестируем механизм столкновений между врагами и игроком. Сделаем чтобы при столкновении со стеной враг менял направление. Сделаем определение пустых ячеек по бокам от врага, и генерацию процента для случайной смены направления во время движения. Создадим класс Dot и отнаследуем от Entity. Сделаем механизм поедания монет. Далее сделаем жизни, и смерть игрока. Сделаем перезагрузку уровней. Добавим меню.
5.1 Разработка класса обычного объекта
На первом этапе создадим абстрактный базовый класс Entity, от которого будут наследоваться игровые объекты:
Перечисление типов игровых объектов:
public enum Type
{
Dot = 0,
Wall = 1,
Player = 2,
Enemy = 3,
None
}
Функции:
Entity(Canvas canvas, Map map, int x, int y)- Конструктор класса
virtual void OnRestart() Действия при перезагрузке уровня
void UpdateThread() функция потока
virtual void Sleep() приостановка потока
void StartUpdate() старт потока
void HideImage(bool isHide) скрыть изображения
void SetZIndex(int index) задает z-индекс для изображения
void InitImage() Инициализирует изображение
void SetImage(String path) Задает изображение
void SetLocation(int x, int y) Перемещает объект в указанные координаты
Rect GetRect() возвращает параллельный осям ограничивающий прямоугольник объекта AABB (axis-aligned bounding box)
virtual void Move(Vector velocity) перемещает объект по заданному вектору скорости
virtual void Update() функция обновления для объектов с потоком
Type GetEntityType() возвращает тип объекта
abstract void Collision(Collision c) срабатывает при коллизии объекта
virtual void Destroy() уничтожает объект
void Stop() останавливает поток
Далее создадим класс Player и пронаслеуем его от Entity
функции:
Player(Canvas canvas, Map map, MainWindow window, int x, int y)
: base(canvas, map, x, y) конструктор
void onLevelLoad() обработчик события LevelLoad
void UpdateImage() обновление изображения
void WallCollision() столкновение со стеной
void onKeyDown(object sender, KeyEventArgs e) обработчик нажатия клавиши
void onKeyUp(object sender, KeyEventArgs e) обработчик отпускания клавиши
void CheckDirection() проверяет можно ли двигаться дальше в заданном направлении
Результат:
Игрок перемещается по сцене по нажатию на клавиши.
5.2 Разработка классов Enemy и Dot
Добавим класс Enemy. Класс врагов, перемещается в произвольных направлениях.
Enemy(Canvas canvas, Map map,int x, int y):base(canvas,map, x, y)
void onLevelLoad() Обработчик события загрузки уровня
void СheckSideDirecktion() проверяет боковые стороны для смены движения
void RandomSpeed() генерирует случайную скорость
так же добавим класс Dot -- класс монетки. Исчезает при столкновении с игроком.
Dot(Canvas canvas, Map map, int x, int y, int width) конструктор
override void Collision(Collision c) обработка столкновений
5.3 Разработка классов Wall и Map
Создадим классы которые будут рисовать лабиринт и управлять столкновениями.
Класс Wall менеджер лабиринта
void Draw() Рисует лабиринт по матрице
void DrawBlock(int x, int y) создает квадраты для блоков лабиринта
void DrawImage(int x, int y) создает тайлы для лабиринта
void HideSprites(bool isHide) скрывает изображения
int GetIndex(int x) переводит координату в индекс
bool CheckCollision(Rect rect) проверяет пересечение прямоугольника со стеной
bool Intersect(Rect r1, Rect r2) проверяет пересечение 2х прямоугольников
Rect GetRect(int w, int h) возвращает прямоугольник эквивалентный индексу в массиве
List<Vector> CheckSides(Rect rect, Vector direction) возвращает список возможных направлений для смены направления движения.
int GetTail(int x, int y) приравнивает координаты к сетке
Класс Map Менеджер игровых объектов
Map(Canvas canvas, MainWindow parentWindow) конструктор класса
void LoadMap(String path) считывает уровень из файла
void Load(String path) загружает уровень
void AddChild(Entity entity) добавляет игровой объект на карту
void CreatePlayer(int x, int y) создает игрока
void CreateEnemy(int x, int y) создает врага
void CreateDot(int x, int y) создает монетку
bool IsEmpty(Rect r) проверяет прямоугольник на пересечение со стеной
void draw() создает и расставляет объекты на сцене
void InvokeEvent(MapEvent mapEvent) создает заданное событие
void PlayerDie() функция срабатывает при смерти игрока
void CollisionUpdate() проверка коллизий
void AddScore() срабатывает, когда игрок есть монетку
void CheckEntityCollision() проверяет столкновения между объектами
HideSprites(bool isHide) скрывает картинки
void ClearCollisions() скрывает прямоугольники, показывающие места столкновений
SolidColorBrush GetSolidBrush(Color color, float opacity = 0.3f) возвращает кисть с заданными параметрами
List<Vector> CheckNext(Rect rect, Vector direction) обертка для функции CheckSides() в классе Wall
Rect GetFlipping(Rect rect) приравнивает прямоугольник к сетке
Rect GetFlipping(Rect rect) Задает Rectangle размеры из Rect
Rectangle GetDebugRectangle(int index) достает Rectangle из пула объектов, либо создает новый, если свободных нет.
void Destroy() Уничтожает карту
Результат:
Объекты сталкиваются со стенами и между собой.
5.4 Разработка прикладного окна
Разработка функционала окошка.
MainWindow() конструктор
void InitLevels() инициализирует уровни
void OnLevelLoad() обработчик события LevelLoad
void NextLevel() загрузка следующего уровня
void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) обработчик закрытия окна
void StartGameMenu_OnClick(object sender, RoutedEventArgs e) Обработчик меню «новая игра»
void DebugMenu_OnClick(object sender, RoutedEventArgs e) обработчик меню «скрыть спрайты»
void CollisionMenu_OnClick(object sender, RoutedEventArgs e) обработчик меню «показать коллизию»
void ExitMenu_OnClick(object sender, RoutedEventArgs e) обработчик меню «выход»
void AboutMenu_OnClick(object sender, RoutedEventArgs e) обработчик меню «Об игре»
void MenuRestart_OnClick(object sender, RoutedEventArgs e) обработчик меню «Рестарт»
void MenuLevel1_OnClick(object sender, RoutedEventArgs e) обработчик меню «Левел1»
void MenuLevel2_OnClick(object sender, RoutedEventArgs e) обработчик меню «Левел2»
void MenuLevel3_OnClick(object sender, RoutedEventArgs e) обработчик меню «Левел3»
void MenuCancel_OnClick(object sender, RoutedEventArgs e) обработчик меню «Сбросить»
void LoadLevel() Загрузка уровня
void UpdateHP() обновляет хп на экране
Результат:
Появилось оформление окна и меню.
рис 5.4.1 Окно игры
5.5 Разработка собственных Exception и Логгера
Создадим класс LocalExeption для обработки собственных ошибок.
LocalExeption(string message):base(message) конструктор
Далее cсоздадим класс Logger который будет записывать ошибки в файл Log.txt
Logger() конструктор
static void Write(string str) Записывает сообщение в файл лога
static void Write(Exception e) Записывает содержание ошибки в файл лога
static void Open() открывает файл
static void Close() закрывает файл
После чего добавим конструкцию которая будет отлавливать пользовательские ошибки и записывать их в лог:
try
{
…
}
catch (LocalExeption e)
{
Logger.Write(e);
}
6. Описание проблем, возникших при разработке программной системы
Поэтапная разработка программы позволила быстро разработать её и отладить. Проблем не было.
7. Заключение
В ходе разработки приложения были закреплены навыки языка C#, а так же навыки поэтапной разработки программного обеспечения.
8. Список используемой литературы
1. Троелсен Э. Язык программирования C# 2010 и платформа .NET 4.0 Вильямс, 2010 -1392с
2. Медведев В.И. Программирование на С++, C++.NET и С#: - Казань: Мастер Лайн, 2005. - 270 c.: ил. - (Серия «Современная прикладная математика и информатика»).
3. Applications = Code + Markup: A Guide to the Microsoft® Windows® Presentation Foundation: A Guide to the Microsoft Windows Presentation Foundation (Developer Reference) Hardcover by Charles Petzold - September 13, 2006 -944 с
4. Microsoft Documentation https://msdn.microsoft.com/
Приложение 1. Диаграмма классов разработанной программы
Приложение 2. Исходный код разработанной программы
Entity.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace wpfman
{
abstract class Entity
{
public enum Type
{
Dot = 0,
Wall = 1,
Player = 2,
Enemy = 3,
None
}
protected Entity(Canvas canvas, Map map, int x, int y)
{
_map = map;
_canvas = canvas;
map.AddChild(this);
InitImage();
SetLocation(x, y);
_startX = x;
_startY = y;
IsRemoved = false;
}
protected virtual void OnRestart()
{
SetLocation(_startX, _startY);
}
private void UpdateThread()
{
while (IsWorking)
{
_image.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new
Action(() =>
{
lock (this)
{
try
{
Update();
}
catch (LocalExeption e)
{
Logger.Write(e);
}
}
}));
Sleep();
}
Logger.Write("End thread "+ GetEntityType());
}
protected virtual void Sleep()
{
Thread.Sleep(20);
}
protected void StartUpdate()
{
updateThread = new Thread(UpdateThread);
IsWorking = true;
updateThread.Start();
}
public void HideImage(bool isHide)
{
_image.Visibility = (isHide)?Visibility.Hidden : Visibility.Visible;
}
protected void SetZIndex(int index)
{
Canvas.SetZIndex(_image, index);
}
protected void InitImage()
{
_image = new Image();
Scale = new ScaleTransform();
Scale.ScaleX = 1;
Rotation = new RotateTransform();
Rotation.Angle = 0;
_image.Stretch = Stretch.Fill;
TransformGroup myTransformGroup = new TransformGroup();
myTransformGroup.Children.Add(Scale);
myTransformGroup.Children.Add(Rotation);
_image.RenderTransform = myTransformGroup;
_image.RenderTransformOrigin = new Point(0.5, 0.5);
_canvas.Children.Add(_image);
}
protected void SetImage(String path)
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(path, UriKind.Relative);
bi.EndInit();
_image.Source = bi;
}
public void SetLocation(int x, int y)
{
lock (this)
{
Canvas.SetLeft(_image, x);
Canvas.SetTop(_image, y);
}
}
public Rect GetRect()
{
if (_image == null) return new Rect();
long x = Convert.ToInt64(_image.GetValue(Canvas.LeftProperty));
long y = Convert.ToInt64(_image.GetValue(Canvas.TopProperty));
long width = Convert.ToInt64(_image.GetValue(Canvas.ActualWidthProperty));
long height = Convert.ToInt64(_image.GetValue(Canvas.ActualHeightProperty));
return new Rect(new Point(x, y), new Size(width, height));
}
public virtual void Move(Vector velocity)
{
Canvas.SetLeft(_image, Position.X + velocity.X);
Canvas.SetTop(_image, Position.Y + velocity.Y);
}
protected virtual void Update()
{
}
public abstract Type GetEntityType();
public virtual void Destroy()
{
if (IsRemoved) return;
lock (this)
{
Logger.Write("Begin destroy" + GetEntityType());
IsRemoved = true;
_map.RestartLevel -= OnRestart;
if (IsWorking)
{
IsWorking = false;
if (updateThread != null)
{
updateThread.Abort();
updateThread.Join();
}
}
_image.Source.Freeze();
_image.Source = null;
_image.RenderTransform = null;
_canvas.Children.Remove(_image);
_map = null;
_canvas = null;
Logger.Write("End destroy" + GetEntityType());
}
}
public void Stop()
{
IsWorking = false;
}
public abstract void Collision(Collision c);
public Point Position
{
get
{
try
{
long x = Convert.ToInt64(_image.GetValue(Canvas.LeftProperty));
long y = Convert.ToInt64(_image.GetValue(Canvas.TopProperty));
return new Point(x, y);
}
catch
{
Logger.Write("_image = null");
return new Point(0, 0);
}
}
}
public ScaleTransform Scale
{
get { return _scale; }
set { _scale = value; }
}
public RotateTransform Rotation
{
get { return _rotation; }
set { _rotation = value; }
}
public bool IsWorking { get; private set; }
public Vector Velocity { get; protected set; }
public bool IsDebug { get; protected set; }
public bool IsRemoved { get; protected set; }
protected Thread updateThread;
protected Map _map;
protected Image _image;
protected RotateTransform _rotation;
protected ScaleTransform _scale;
protected Canvas _canvas;
public readonly int _startX;
public readonly int _startY;
public readonly static Vector Up = new Vector(0, -1);
public readonly static Vector Down = new Vector(0, 1);
public readonly static Vector Left = new Vector(-1, 0);
public readonly static Vector Right = new Vector(1, 0);
public readonly static Vector Zero = new Vector(0, 0);
}
}
Player.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace wpfman
{
class Player: Entity
{
private MainWindow _window;
public Player(Canvas canvas, Map map, MainWindow window, int x, int y)
: base(canvas, map, x, y)
{
Logger.Write("create player");
SetImage("/pacman.png");
_window = window;
_window.KeyDown += onKeyDown;
_window.KeyUp += onKeyUp;
_newVelocity = new Vector();
_map.RestartLevel += OnRestart;
SetZIndex(5);
map.LevelLoad += OnLevelLoad;
}
private void OnLevelLoad()
{
StartUpdate();
}
public override void Collision(Collision c)
{
lock (this)
{
switch (c.Type)
{
case Type.Wall:
WallCollision();
break;
case Type.Enemy:
_map.PlayerDie();
break;
case Type.Dot:
_map.AddScore();
break;
}
}
}
private void UpdateImage()
{
int scale = 1;
int angle = 0;
if (Velocity == Up)
{
angle = -90;
}
if (Velocity == Down)
{
angle = 90;
}
if (Velocity == Left)
{
scale = -1;
}
Rotation.Angle = angle;
Scale.ScaleX = scale;
}
private void WallCollision()
{
Velocity = Zero;
}
protected override void Update()
{
base.Update();
if (_newVelocity != Velocity)
{
CheckDirection();
}
Move(Velocity * Global.PLAYER_SPEED);
if(Velocity != Zero) UpdateImage();
}
public void onKeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Left:
_newVelocity = Left;
break;
case Key.Right:
_newVelocity = Right;
break;
case Key.Down:
_newVelocity = Down;
break;
case Key.Up:
_newVelocity = Up;
break;
}
CheckDirection();
}
public void onKeyUp(object sender, KeyEventArgs e)
{
_newVelocity = Zero;
}
void CheckDirection()
{
if (_newVelocity != Zero)
{
var r = GetRect();
r.Offset(_newVelocity);
if (_map.IsEmpty(r))
{
Velocity = _newVelocity;
}
}
}
public override Type GetEntityType()
{
return Type.Player;
}
public override void Destroy()
{
base.Destroy();
_window.KeyDown -= onKeyDown;
_window.KeyUp -= onKeyUp;
_window = null;
}
private Vector _newVelocity;
}
}
Enemy.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace wpfman
{
class Enemy : Entity
{
readonly private int Chance;
readonly static Random Randomizer = new Random(DateTime.Now.Millisecond);
public Enemy(Canvas canvas, Map map,int x, int y):base(canvas,map, x, y)
{
Logger.Write("create player");
SetImage("/ghost.png");
RandomSpeed();
StartUpdate();
Chance = Randomizer.Next(3,7);
map.RestartLevel += OnRestart;
map.LevelLoad += OnLevelLoad;
SetZIndex(3);
}
private void OnLevelLoad()
{
StartUpdate();
}
public override Type GetEntityType()
{
return Type.Enemy;
}
protected override void Update()
{
if (IsWorking)
{
base.Update();
СheckSideDirecktion();
Move(Velocity*Global.ENEMY_SPEED);
}
}
protected override void Sleep()
{
Thread.Sleep(40);
}
public override void Collision(Collision c)
{
lock (this)
{
switch (c.Type)
{
case Type.Wall:
RandomSpeed();
break;
case Type.Enemy:
if (Velocity == c.Velocity) return;
Velocity = -Velocity;
Move(Velocity * Global.PLAYER_SPEED);
break;
}
}
}
void СheckSideDirecktion()
{
var currentRect = GetRect();
var flippingRect = _map.GetFlipping(currentRect);
if (currentRect != flippingRect) return;
var sides =_map.CheckNext(GetRect(),Velocity);
if (sides.Count == 0) return;
var k = Randomizer.Next(10);
if (k > Chance)
{
k = Randomizer.Next(sides.Count);
Velocity = sides[k];
}
}
private void RandomSpeed()
{
Random rnd=new Random();
var i = rnd.Next(4);
switch (i)
{
case 0:
Velocity = Up;
break;
case 1:
Velocity = Left;
break;
case 2:
Velocity = Down;
break;
default:
Velocity = Right;
break;
}
}
}
}
Dot.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace wpfman
{
class Dot : Entity
{
public Dot(Canvas canvas, Map map, int x, int y, int width)
: base(canvas, map, x, y)
{
SetImage("/dot.png");
SetZIndex(1);
}
public override void Collision(Collision c)
{
lock (this)
{
switch (c.Type)
{
case Type.Player:
Destroy();
break;
}
}
}
public override Type GetEntityType()
{
return Type.Dot;
}
}
}
Wall.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace wpfman
{
class Wall
{
readonly List<List<int>> _data = new List<List<int>>();
private readonly Canvas _canvas;
private bool IsDebug { get; set; }
private Rectangle DebugRect { get; set; }
private Rectangle DebugCollision { get; set; }
public bool IsActive { get; set; }
readonly private List<Image> _images = new List<Image>();
readonly private List<Rectangle> _debugBlocks = new List<Rectangle>();
public Wall(List<List<int>> data, Canvas c)
{
IsDebug = true;
_data = data;
_canvas = c;
}
public void Draw()
{
int h = 0;
foreach (var line in _data)
{
int w = 0;
foreach (var cell in line)
{
int x = w * Global.TILE;
int y = h * Global.TILE;
if (cell == 1)
{
DrawImage(x, y);
DrawBlock(x, y);
}
++w;
}
++h;
}
}
private void DrawBlock(int x, int y)
{
var rect = new Rectangle();
rect.Width = Global.TILE;
rect.Height = Global.TILE;
rect.Fill = new SolidColorBrush(Color.FromArgb(255,54,54,54));
rect.StrokeThickness = 1;
rect.Stroke = Brushes.Black;
_canvas.Children.Add(rect);
Canvas.SetLeft(rect, x);
Canvas.SetTop(rect, y);
Canvas.SetZIndex(rect, 0);
rect.Visibility = Visibility.Collapsed;
_debugBlocks.Add(rect);
}
private void DrawImage(int x, int y)
{
var img = new Image();
_canvas.Children.Add(img);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri("wall.png", UriKind.Relative);
bi.EndInit();
img.Source = bi;
Canvas.SetLeft(img, x);
Canvas.SetTop(img, y);
_images.Add(img);
}
public void HideSprites(bool isHide)
{
foreach (var debugBlock in _debugBlocks)
{
debugBlock.Visibility = (isHide) ? Visibility.Visible : Visibility.Collapsed;
}
Thread.Yield();
foreach (var img in _images)
{
img.Visibility = (isHide) ? Visibility.Collapsed : Visibility.Visible;
}
}
private int GetIndex(int x)
{
var index = x / Global.TILE;
if (index > _data.Count)
{
index = 0;
throw new LocalExeption("Выход за пределы карты; GetIndex index =" + index);
}
return index;
}
public bool CheckCollision(Rect rect)
{
int n = _data.Count;
for (int i = 0; i < n;i++)
{
int count = _data[i].Count;
for (int j = 0; j < count; j++)
{
if (_data[i][j] == 1)
{
var r = GetRect(j, i);
if (Intersect(rect, r))
{
return true;
}
}
}
}
return false;
}
private bool Intersect(Rect r1, Rect r2)
{
var x1 = Math.Max(r1.X, r2.X);
var y1 = Math.Max(r1.Y, r2.Y);
var x2 = Math.Min(r1.Right, r2.Right);
var y2 = Math.Min(r1.Bottom, r2.Bottom);
if ((x1 < x2) && (y1 < y2))
{
return true;
}
return false;
}
/*Возвращает прямоугольник по индексу в массиве*/
private Rect GetRect(int w, int h)
{
return new Rect(new Point(w * Global.TILE, h * Global.TILE), new Size(Global.TILE, Global.TILE));
}
public List<Vector> CheckSides(Rect rect, Vector direction)
{
var x = GetIndex((int)rect.X);
var y = GetIndex((int)rect.Y);
List<Vector> sides = new List<Vector>();
if ((direction == Entity.Down) || (direction == Entity.Up))
{
if (GetTail(x + 1, y) != 1)//право
{
sides.Add(Entity.Right);
}
if (GetTail(x - 1, y) != 1)//лево
{
sides.Add(Entity.Left);
}
}
else if ((direction == Entity.Right) || (direction == Entity.Left))
{
if (GetTail(x, y - 1) != 1)
{
sides.Add(Entity.Up);
}
if (GetTail(x, y + 1) != 1)
{
sides.Add(Entity.Down);
}
}
return sides;
}
public Rect GetFlipping(Rect rect)
{
Rect flippingRect = new Rect();
flippingRect.X = GetIndex((int)rect.X) * Global.TILE;
flippingRect.Y = GetIndex((int)rect.Y) * Global.TILE;
flippingRect.Width = Global.TILE;
flippingRect.Height = Global.TILE;
return flippingRect;
}
private int GetTail(int x, int y)
{
if ((y < _data.Count) && (x < _data[y].Count))
{
return _data[y][x];
}
else
{
throw new LocalExeption("Выход за пределы карты; GetTail() x="+x+" y="+y);
}
}
public void Destroy()
{
Global.ClearRectList(_debugBlocks, _canvas);
foreach (var image in _images)
{
image.Source.Freeze();
_canvas.Children.Remove(image);
}
_images.Clear();
_data.Clear();
}
}
}
Map.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Threading;
using wpfman.Properties;
namespace wpfman
{
class Map
{
public Map(Canvas canvas, MainWindow parentWindow)
{
LevelLoad += OnLevelLoad;
LevelLoad += parentWindow.OnLevelLoad;
_canvas = canvas;
_parentWindow = parentWindow;
_wall = new Wall(_data, _canvas);
IsDebug = true;
_debugPull = new List<Rectangle>();
_debugCollision = new List<Rectangle>();
}
private void LoadMap(String path)
{
String[] level = System.IO.File.ReadAllLines(path);
foreach (var str in level)
{
List<int> line = new List<int>();
foreach (var chr in str)
{
line.Add(Convert.ToInt32(chr.ToString()));
}
_data.Add(line);
}
}
public void Load(String path)
{
LoadMap(path);
draw();
_wall.Draw();
}
public void AddChild(Entity entity)
{
_entities.Add(entity);
}
private void CreatePlayer(int x, int y)
{
new Player(_canvas, this,_parentWindow, x, y);
}
private void CreateEnemy(int x, int y)
{
new Enemy(_canvas, this, x, y);
}
private void CreateDot(int x, int y)
{
var newX = x + ((Global.TILE) / 2)-5;
var newY = y + ((Global.TILE) / 2)-5;
new Dot(_canvas, this, newX, newY, 10);
++_maxScore;
}
public bool IsEmpty(Rect r)
{
return !_wall.CheckCollision(r);
}
private void draw()
{
int h = 0;
foreach (var line in _data)
{
int w = 0;
foreach (var cell in line)
{
int x = w * Global.TILE;
int y = h * Global.TILE;
if (cell == (int)Entity.Type.Dot)
{
CreateDot(x, y);
}
if (cell == (int)Entity.Type.Player)
{
CreatePlayer(x, y);
}
if (cell == (int)Entity.Type.Enemy)
{
CreateEnemy(x, y);
}
++w;
}
++h;
}
InvokeEvent(LevelLoad);
}
private void OnLevelLoad()
{
_collisionThread = new Thread(CollisionUpdate);
_collisionThread.Start();
}
private void InvokeEvent(MapEvent mapEvent)
{
MapEvent e;
lock (this) { e = mapEvent; }
if (e != null) e();
}
public void PlayerDie()
{
if (--Settings.Default.HP >= 0)
{
InvokeEvent(RestartLevel);
_parentWindow.UpdateHP();
}
else
{
Settings.Default.HP = Global.HP;
_score = Settings.Default.Score;
_parentWindow.LoadLevel();
}
}
private void CollisionUpdate()
{
IsWorking = true;
while (IsWorking)
{
_parentWindow.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new
Action(() => {
try
{
CheckEntityCollision();
Update();
}
catch (LocalExeption e)
{
Logger.Write(e);
}
}));
Thread.Sleep(10);
}
}
public void AddScore()
{
++_score;
_parentWindow.Score.Text = _score.ToString();
if (_score == _maxScore)
{
IsWorking = false;
Settings.Default.Score = _score;
IsWorking = false;
foreach (var entity in _entities)
{
entity.Stop();
}
_parentWindow.NextLevel();
}
}
private void CheckEntityCollision()
{
var count = _entities.Count;
for(int i=0; i < count; ++i)
{
var entity1 = _entities[i];
if (entity1.IsRemoved)
{
_entities.RemoveAt(i);
count = _entities.Count;
continue;
}
var rect1 = entity1.GetRect();
for (int j = 0; j < count; ++j)
{
var entity2 = _entities[j];
if (entity2.IsRemoved) continue;
if (entity1 == entity2) continue;
var rect2 = entity2.GetRect();
if (rect1.IntersectsWith(rect2))
{
Collision c1 = new Collision(entity2.GetEntityType(), entity2.Velocity);
Collision c2 = new Collision(entity1.GetEntityType(), entity1.Velocity);
entity1.Collision(c1);
entity2.Collision(c2);
count = _entities.Count;
}
}
lock (entity1)
{
var velocity = entity1.Velocity*-1;
bool isCollide = false;
while (_wall.CheckCollision(entity1.GetRect()))
{
entity1.Move(velocity);
isCollide = true;
_wall.IsActive = true;
if (Global.IS_SHOW_COLLISION)
{
var r = new Rectangle();
r.Fill = GetSolidBrush(Colors.Red, 0.1f);
_canvas.Children.Add(r);
Canvas.SetZIndex(r, DEBUG_LAYER);
RectToRectangle(entity1.GetRect(), r);
_debugCollision.Add(r);
}
}
if (isCollide) entity1.Collision(new Collision(Entity.Type.Wall));
}
}
}
public void HideSprites(bool isHide)
{
foreach(var entity in _entities)
{
entity.HideImage(isHide);
}
_wall.HideSprites(isHide);
if (!isHide) Global.ClearRectList(_debugPull,_canvas);
}
public void ClearCollisions()
{
Global.ClearRectList(_debugCollision,_canvas);
}
public void Update()
{
if (Global.IS_DEBUG)
{
int count = 0;
var rectList = new List<Rect>();
foreach (var entity in _entities)
{
var type = entity.GetEntityType();
if (type == Entity.Type.Player)
{
var debugRect = GetDebugRectangle(count);
debugRect.Fill = GetSolidBrush(Colors.Goldenrod,0.5f);
debugRect.StrokeThickness = 1;
debugRect.Stroke = Brushes.Chocolate;
var rect = entity.GetRect();
RectToRectangle(rect,debugRect);
++count;
} else if(type == Entity.Type.Enemy)
{
var debugRect = GetDebugRectangle(count);
debugRect.Fill = GetSolidBrush(Colors.CadetBlue,0.5f);
debugRect.StrokeThickness = 1;
debugRect.Stroke = Brushes.DarkSlateGray;
var rect = entity.GetRect();
RectToRectangle(rect,debugRect);
++count;
}
}
}
}
public static SolidColorBrush GetSolidBrush(Color color, float opacity = 0.3f)
{
var br = new SolidColorBrush(color);
br.Opacity = opacity;
return br;
}
public List<Vector> CheckNext(Rect rect, Vector direction)
{
return _wall.CheckSides(rect, direction);
}
public Rect GetFlipping(Rect rect)
{
return _wall.GetFlipping(rect);
}
public static void RectToRectangle(Rect rect,Rectangle rectangle)
{
rectangle.Width = rect.Width;
rectangle.Height = rect.Height;
Canvas.SetLeft(rectangle,rect.X);
Canvas.SetTop(rectangle,rect.Y);
}
Rectangle GetDebugRectangle(int index)
{
if (index < _debugPull.Count)
{
return _debugPull[index];
}
else
{
var r = new Rectangle();
r.Width = Global.TILE;
r.Height = Global.TILE;
_canvas.Children.Add(r);
Canvas.SetZIndex(r, DEBUG_LAYER);
_debugPull.Add(r);
return r;
}
}
public void Destroy()
{
if (!IsDestroyed)
{
IsWorking = false;
if (_collisionThread != null) _collisionThread.Join();
foreach (var entity in _entities)
{
entity.Destroy();
}
_entities.Clear();
_canvas.Children.Clear();
Global.ClearRectList(_debugCollision, _canvas);
Global.ClearRectList(_debugPull, _canvas);
_data.Clear();
_wall.Destroy();
}
}
private int _maxScore = 0;
private int _score = 0;
public bool IsWorking { get; private set ; }
private bool IsDestroyed { get; set ; }
private bool IsDebug { get; set; }
readonly List<List<int>> _data = new List<List<int>>();
private readonly Canvas _canvas;
public const int mapWidth = 16;
public const int mapHeight = 16;
private readonly List<Entity> _entities = new List<Entity>();
private Thread _collisionThread;
public delegate void MapEvent();
public event MapEvent LevelLoad;
public event MapEvent RestartLevel;
public delegate void CollisionEvent(Collision c);
private readonly Wall _wall;
private readonly List<Rectangle> _debugPull;
private readonly List<Rectangle> _debugCollision;
private readonly MainWindow _parentWindow;
private const int DEBUG_LAYER = 5;
}
}
Logger.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace wpfman
{
class Logger
{
private static Logger _instance;
private static bool isExist = false;
private static string path = @"log.txt";
private static StreamWriter _sw;
private Logger()
{
}
static public void Write(string str)
{
if (isExist)
{
lock (_instance)
{
string date = DateTime.Now.ToString() + " " + ": " + str;
_sw.WriteLine(date);
}
}
}
public static void Open()
{
_instance = new Logger();
if (File.Exists(path))
{
File.Delete(path);
}
_sw = File.CreateText(path);
isExist = true;
}
public static void Close()
{
if (isExist)
{
isExist = false;
_sw.Close();
_instance = null;
}
}
public static void Write(Exception e)
{
Write(e.Message);
}
}
}
LocalExeption.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace wpfman
{
class LocalExeption:Exception
{
public LocalExeption(string message):base(message)
{
}
}
}
Global.cs
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
namespace wpfman
{
public static class Global
{
public const int TILE = 30;
public const int PLAYER_SPEED =3;
public const int ENEMY_SPEED = 1;
public const int LEVEL_COUNT = 3;
public const int HP = 2;
public const string LEVEL1= @"level1.txt";
public const string LEVEL2 = @"level2.txt";
public const string LEVEL3 = @"level3.txt";
public static bool IS_DEBUG = false;
public static bool IS_SHOW_COLLISION = false;
public static int Score = 0;
public static void ClearRectList(List<Rectangle> list, Canvas canvas)
{
foreach (var rect in list)
{
canvas.Children.Remove(rect);
}
list.Clear();
}
}
}
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using wpfman.Properties;
namespace wpfman
{
public partial class MainWindow : Window
{
private Map _map;
private int _currentLevel = 1;
private Dictionary<int, string> _levels;
public MainWindow()
{
InitializeComponent();
Logger.Open();
InitLevels();
if (_currentLevel != 1) Start.Header = "Продолжить";
}
private void InitLevels()
{
_levels = new Dictionary<int, string>();
_levels[1] = Global.LEVEL1;
_levels[2] = Global.LEVEL2;
_levels[3] = Global.LEVEL3;
}
public void OnLevelLoad()
{
TopPanel.Visibility=Visibility.Visible;
Logger.Write("Level Load");
}
public void NextLevel()
{
if(++_currentLevel <= Global.LEVEL_COUNT) LoadLevel();
else
{
//MainCanvas.Visibility = Visibility.Collapsed;
MessageBox.Show("Вы набрали " + Settings.Default.Score + " очков!");
Settings.Default.ScoresList.Add(DateTime.Now.ToString()+" "+Settings.Default.Score.ToString());
Settings.Default.Save();
RecordViewer.Visibility = Visibility.Visible;
RecordsText.Text = "";
foreach (var rec in Settings.Default.ScoresList)
{
RecordsText.Text += rec + "\n";
}
_currentLevel = 1;
Settings.Default.IsCompleted = true;
Start.Header = "Новая игра";
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if(_map != null)_map.Destroy();
Logger.Close();
}
private void StartGameMenu_OnClick(object sender, RoutedEventArgs e)
{
if (Settings.Default.IsCompleted)Settings.Default.LastCompletedLevel = 1;
_currentLevel = Settings.Default.LastCompletedLevel;
LoadLevel();
Menu_Restart.IsEnabled = !Menu_Restart.IsEnabled;
}
private void DebugMenu_OnClick(object sender, RoutedEventArgs e)
{
if (_map != null)
{
Global.IS_DEBUG = !Global.IS_DEBUG;
_map.HideSprites(Global.IS_DEBUG);
}
}
private void CollisionMenu_OnClick(object sender, RoutedEventArgs e)
{
if (_map != null)
{
Global.IS_SHOW_COLLISION = !Global.IS_SHOW_COLLISION;
var menu = sender as MenuItem;
if (menu != null && !menu.IsChecked) _map.ClearCollisions();
}
}
private void ExitMenu_OnClick(object sender, RoutedEventArgs e)
{
Settings.Default.Save();
this.Close();
}
private void AboutMenu_OnClick(object sender, RoutedEventArgs e)
{
new About()
{
Visibility = Visibility.Visible
};
}
private void MenuRestart_OnClick(object sender, RoutedEventArgs e)
{
LoadLevel();
}
private void MenuLevel1_OnClick(object sender, RoutedEventArgs e)
{
_currentLevel = 1;
LoadLevel();
}
private void MenuLevel2_OnClick(object sender, RoutedEventArgs e)
{
_currentLevel = 2;
LoadLevel();
}
private void MenuLevel3_OnClick(object sender, RoutedEventArgs e)
{
_currentLevel = 3;
LoadLevel();
}
public void LoadLevel()
{
RecordViewer.Visibility = Visibility.Collapsed;
if(_map != null)_map.Destroy();
_map = new Map(MainCanvas, this);
_map.Load(_levels[_currentLevel]);
UpdateHP();
Score.Text = Settings.Default.Score.ToString();
}
public void UpdateHP()
{
HP_Text.Text = Settings.Default.HP.ToString();
}
private void MenuCancel_OnClick(object sender, RoutedEventArgs e)
{
Settings.Default.Reset();
_map.Destroy();
}
}
}
MainWindow.xaml
<Window x:Class="wpfman.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Zombie Pacman!" Height="538" Width="470" Closing="Window_Closing" ResizeMode="NoResize" Icon="pacman.png">
<Window.Resources>
<Style x:Key="ScrollBarLineButtonStyle" TargetType="{x:Type RepeatButton}">
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Canvas Height="18">
<Polygon Fill="#333333" Points="3,10 15,10 9,3"></Polygon>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarLineButtonBottomStyle" TargetType="{x:Type RepeatButton}">
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Canvas Height="18">
<Polygon Fill="#333333" Points="3,5 9,15 15,5"></Polygon>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarPageButtonStyle" TargetType="{x:Type RepeatButton}">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border BorderBrush="Transparent"></Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarThumbStyle" TargetType="{x:Type Thumb}">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="Margin" Value="1,0,1,0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Rectangle Fill="Black" Margin="2"></Rectangle>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="18"/>
<RowDefinition Height="*"/>
<RowDefinition MaxHeight="18"/>
</Grid.RowDefinitions>
<RepeatButton Grid.Row="0" Height="18"
Style="{StaticResource ScrollBarLineButtonStyle}"
Command="ScrollBar.LineUpCommand" >
</RepeatButton>
<Track Name="PART_Track" Grid.Row="1"
IsDirectionReversed="True">
<Track.DecreaseRepeatButton>
<RepeatButton Command="ScrollBar.PageUpCommand" Style="{StaticResource ScrollBarPageButtonStyle}">
</RepeatButton>
</Track.DecreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource ScrollBarThumbStyle}">
</Thumb>
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Command="ScrollBar.PageDownCommand" Style="{StaticResource ScrollBarPageButtonStyle}">
</RepeatButton>
</Track.IncreaseRepeatButton>
</Track>
<RepeatButton Grid.Row="3" Height="18"
Style="{StaticResource ScrollBarLineButtonBottomStyle}"
Command="ScrollBar.LineDownCommand">
</RepeatButton>
</Grid>
</ControlTemplate>
<Style TargetType="{x:Type ScrollBar}">
<Setter Property="Template" Value="{StaticResource VerticalScrollBar}"/>
</Style>
</Window.Resources>
<Window.TaskbarItemInfo>
<TaskbarItemInfo/>
</Window.TaskbarItemInfo>
<StackPanel Background="#FF444444">
<Menu DockPanel.Dock="Top" >
<MenuItem Header="Игра">
<MenuItem x:Name="Start" Header="Новая игра" Click="StartGameMenu_OnClick">
<MenuItem.Icon>
<Image Source="play.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="Menu_Restart" Header="Рестарт" IsEnabled="False" Click="MenuRestart_OnClick"/>
<MenuItem Header="Уровни" >
<MenuItem Header="1 уровень" Click="MenuLevel1_OnClick" />
<MenuItem Header="2 уровень" Click="MenuLevel2_OnClick"/>
<MenuItem Header="3 уровень" Click="MenuLevel3_OnClick"/>
</MenuItem>
<Separator />
<MenuItem Header="Выход" Click="ExitMenu_OnClick"/>
</MenuItem>
<MenuItem Header="Настройки">
<MenuItem Header="Режим отладки" >
<MenuItem x:Name="menu_sprite" Header="Отключить спрайты" Click="DebugMenu_OnClick" IsCheckable="True"/>
<MenuItem Header="Показывать столкновения" Click="CollisionMenu_OnClick" IsCheckable="True"/>
</MenuItem>
<MenuItem Header="Сбросить" IsEnabled="False" Click="MenuCancel_OnClick"/>
</MenuItem>
<MenuItem Header="Справка">
<MenuItem Header="Об игре" Click="AboutMenu_OnClick"/>
</MenuItem>
</Menu>
<Canvas x:Name="TopPanel" Height="24" Visibility="Collapsed">
<Image x:Name ="Heart" Source="heart.png" Stretch="Fill" Canvas.Left="10" Canvas.Top="3"/>
<TextBlock x:Name="HP_Text" Text="2" Canvas.Left="29" Canvas.Top="3" FontFamily="Batang" Height="20" VerticalAlignment="Center" TextAlignment="Center" FontSize="16" FontWeight="Bold" />
<TextBlock x:Name="ScoreText" Canvas.Top="3" Text="Score:" Canvas.Left="125" FontFamily="Batang" Height="20" VerticalAlignment="Center" TextAlignment="Center" FontSize="16" FontWeight="Bold"/>
<TextBlock x:Name="Score" Text="0" Canvas.Top="3" Canvas.Left="181" FontFamily="Batang" Height="20" VerticalAlignment="Center" TextAlignment="Center" FontSize="16" FontWeight="Bold" />
</Canvas>
<Grid>
<Canvas Name="MainCanvas" Width="449" Height="480" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,5,5,5" Visibility="Visible"/>
<ScrollViewer Name="RecordViewer" Margin="52,47,51,63" Background="#66000000" Visibility="Collapsed">
<TextBlock Name="RecordsText" Width="309" FontFamily="Courier New" FontSize="14" Foreground="#FFB9BABD"></TextBlock>
</ScrollViewer>
</Grid>
</StackPanel>
</Window>
About.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace wpfman
{
public partial class About : Window
{
public About()
{
InitializeComponent();
}
}
}
About.xaml
<Window x:Class="wpfman.About" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Об игре" Height="300" Width="300" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0*"/>
<ColumnDefinition/>
<ColumnDefinition Width="0*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.ColumnSpan="2" Margin="0,73,0,176" TextAlignment="Center" FontWeight="Bold" FontSize="14" FontFamily="Courier New">
<Run>Автор: Логвина Юлия</Run>
</TextBlock>
<TextBlock Margin="0,98,0,140" Grid.ColumnSpan="2" TextAlignment="Center" FontWeight="Bold" FontSize="14" FontFamily="Courier New">
<Run>Рекомендуемая оценка: 5</Run>
</TextBlock>
</Grid>
</Window>
Размещено на Allbest.ru
Подобные документы
Описание разрабатываемой программы с точки зрения пользователя. Диаграмма вариантов использования приложения. Объектное представление программы. Разработка класса корабля, прикладного окна и события but. Окно приложения с перемещающимися кораблями.
курсовая работа [207,0 K], добавлен 05.04.2014Разработка плана здания с помощью графического редактора AutoCAD. Описание предметной области и схемы модели данных. Разработка приложения, позволяющего работать с базой с помощью диалогового окна Windows. Программный код формы, прописывание кодов.
курсовая работа [2,2 M], добавлен 30.07.2010Разработка интернет-приложения (Web–сервиса), позволяющего делать заказы онлайн, выполнять их обработку. Диаграмма вариантов использования. Модель предметной области. Описание концептуальных классов. Моделирование процесса выполнения операций в языке UML.
курсовая работа [1,3 M], добавлен 21.11.2013Разработка тестирующего приложения, которое будет наглядно показывать, как должна выглядеть тестирующая программа для вычисления уровня интеллекта. Программная среда разработки, характеристика основных возможностей приложения. Стандартные диалоговые окна.
курсовая работа [716,9 K], добавлен 02.12.2013Анализ моделируемого приложения и постановка задачи. Диаграмма прецедентов, деятельности объектов и состояния классов. Разработка приложения-игры, выбор языка программирования и среды для разработки проекта, интерфейс приложения и ресурсы проекта.
курсовая работа [308,5 K], добавлен 14.10.2011Разработка справочной системы по визуальным компонентам языка программирования Delphi. Возможность сохранения измененных свойств компонент в файле с возможностью их загрузки в будущем. Логика работы приложения и разработка программного обеспечения.
курсовая работа [602,4 K], добавлен 22.01.2015Описание разрабатываемой программы с точки зрения пользователя и программиста. Поэтапная разработка программной системы. Создание базы данных в Access. Разработка структуры классов. Создание структуры для хранения данных. Проектирование интерфейса.
курсовая работа [1,4 M], добавлен 07.08.2013Разработка и создание игры "Змейка". Использование динамически-активных принципов языка Java. Графические объекты программы. Описание игры, правила, теоретические сведения. Классы приложения. Типы данных. Реализация. Метод. Объект. Блок-схема игры.
курсовая работа [12,4 K], добавлен 18.06.2008Анализ предметной области. Диаграмма классов. Проектирование программного продукта "Часы". Тестирование и отладка, руководство программиста. Описание работы приложения. Руководство оператора, модель жизненного цикла. Файл Times.cs, Arrow.cs, Form1.cs.
курсовая работа [1,7 M], добавлен 20.04.2015Разработка и реализация демонстрационного многопоточного приложения. Выбор основных средств реализации. Описание логики работы приложения и разработка программного обеспечения. Описание пользовательского интерфейса. Реализация потоков в Delphi.
курсовая работа [462,5 K], добавлен 10.08.2014