Файл: Департамент образования ивановской области.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 30.11.2023

Просмотров: 18

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.




ДЕПАРТАМЕНТ ОБРАЗОВАНИЯ ИВАНОВСКОЙ ОБЛАСТИ

Областное государственное бюджетное профессиональное образовательное учреждение

«Ивановский промышленно-экономический колледж»














































КУРСОВОЙ ПРОЕКТ




Разработка игрового приложения «Контра»




ИвПЭК. 09.02.03.



















Специальность:

09.02.03 Программирование в компьютерных системах,

базовая подготовка

















Руководитель курсового проекта




А.С. Иродов

Выполнил обучающийся группы 402




В.К. Сухарев
















Курсовой проект выполнен и защищен с оценкой__________________________________




«___» ________________ 2020 г.




























Иваново 2020






Содержание


Введение 3

1.Пояснительная записка 4

2.Технико-рабочий проект 6

3. Рабочая документация 8

Заключение 17

Список используемой литературы 18

Приложение А. Фрагмент кода 19

Введение


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

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

Программа написана на языке программирования C# и дополнительном ПО «Monogame»


  1. Пояснительная записка





    1. Цель работы

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

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

На одной стороне поля находится игрок, которым и управляет пользователь. Задача пользователя – это защита находящейся на этой же стороне базы в виде орла. На противоположной стороне поля появляются враги, которые стремятся убить игрока(ков) или базу. При разрушении базы или потери игроком всех жизней игра закончится.




    1. Техническое задание




      1. Введение

Техническое задание – основополагающий документ при разработке программного обеспечения. В нем указаны все требования, используемые при разработке.

      1. Основания для разработки

Основанием для разработки является задание на курсовой проект.

      1. Назначение разработки

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

      1. Ограничения, условия функционирования и выполнения

Персональный компьютер пользователя должен соответствовать минимальным требованиям: процессор Intel Pentium D 935 2.3MHz, Microsoft Windows 7 или выше, 512MB RAM, 50MB свободного места на диске, монитор SVGA, наличие мыши.

Требования к дизайну:

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

      1. Требования к программной документации

Документация по проекту предоставляется в рамках курсового проекта.

      1. Стадии и этапы разработки.

При разработке проекта были выделены следующие стадии:

  • Составление классов, объектов, задач;

  • Проектирование связей между объектами;

  • Разработка готового решения;

  • Оптимизация продукта;

  • Разработка документации.




      1. Порядок приема и контроля

Прием и контроль разработки приложения осуществляется преподавателем. Исполнителем предоставляется вся требуемая документация и разработанное приложение на USB флешке.
  1. Технико-рабочий проект





    1. Построение иерархии классов



Рисунок 1 – Иерархия игрового приложения

Корнем иерархии являются объекты классов Карта, Игрок, Враги. Из карты наследуется объект, из которого в последующем наследуются блоки и база.

    1. Обоснование выбора средств разработки


C# нельзя рассматривать только как язык, это часть большой системы, которая включает в себя ОС Windows, среду разработки Visual Studio (и другие инструменты), ну и, конечно, саму Microsoft, которая обеспечивает поддержку этого языка. C# будет существовать и развиваться, пока существует Microsoft и пока люди пользуются Windows, а это будет ещё очень и очень долго.
Поскольку язык принадлежит компании майкрософт, то применяется практически во всех продуктах, которые были разработаны или куплены. 

Плюсы C#:

  • поддержка майкрософтом. В отличии от Java, которой не пошел на пользу переход в собственность Oracle, C# хорошо развивается благодаря усилиям Microsoft;

  • в последнее время много совершенствуется. Так как C# был создан позже, чем Java и другие языки, то требовалось очень много доработать. Также это касается популяризации и бесплатности - было обещано открыть исходный код, а инструменты (Visual Studio, Xamarin) стали бесплатными для частных лиц и небольших компаний;

  • много синтаксического сахара. Синтаксический сахар - это такие конструкции, которые созданы для облегчения написания и понимания кода (особенно если это код другого программиста) и не играют роли при компиляции;

  • средний порог вхождения. Синтаксис похожий на C, С++ или Java облегчает переход для других программистов. Для новичков это также один из самых перспективных языков для изучения;

  • Xamarin. Благодаря покупке Xamarin на C# теперь можно писать под Android и iOS. Это, несомненно, большой плюс, так как их собственная мобильная ОС (Windows Phone) не завоевала большой популярности;

  • добавлено функциональное программирование (F#);

  • большое сообщество программистов;

  • много вакансий на должность C# программиста в любом регионе.

    1. Моделирование с использованием UML-диаграмм



Рисунок 2 – UML диаграмма
  1. Рабочая документация



3.1 Описание разработки приложения
Для создания приложения необходимо запустить MS Visual Studio и подключить Monogame(рисунок 3).



Рисунок 3 – Установка фреймворка

Затем создаем приложение с учетом monogame (рисунок 4).



Рисунок 4 – создание проекта

Приложение было разработано на языке С#. Код для управления персонажем:

using Microsoft.Xna.Framework;

using Microsoft.Xna.Framework.Graphics;

using Microsoft.Xna.Framework.Input;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


using System.Threading.Tasks;

using Contra.Models;

using Contra.Managers;

using Contra.Sprites;
namespace Contra.Sprites

{

public enum CollisionTypes

{

None,

Full,

Top,

}

public class Sprite : Component, ICloneable

{

protected Dictionary _animations;
protected AnimationManager _animationManager;
protected float _layer { get; set; }
protected Vector2 _origin { get; set; }
protected Vector2 _position { get; set; }
protected float _rotation { get; set; }
protected float _scale { get; set; }
public Vector2 Direction;
protected Texture2D _texture;
public Vector2 _velocity;
public List Children { get; set; }
public CollisionTypes CollisionType { get; set; }
public Color Colour { get; set; }
public bool IsRemoved { get; set; }
public float Layer

{

get { return _layer; }

set

{

_layer = value;

if (_animationManager != null)

_animationManager.Layer = _layer;

}

}
public Vector2 Origin

{

get { return _origin; }

set

{

_origin = value;
if (_animationManager != null)

_animationManager.Origin = _origin;

}

}
public Vector2 Position

{

get

{

return _position;

}

set

{

_position = value;
if (_animationManager != null)

_animationManager.Position = _position;

}

}
public Rectangle Rectangle

{

get

{

if (_texture != null)

{

return new Rectangle((int)Position.X - (int)Origin.X, (int)Position.Y - (int)Origin.Y, _texture.Width, _texture.Height);

}
if (_animationManager != null)

{

var animation = _animations.FirstOrDefault().Value;
return new Rectangle((int)Position.X - (int)Origin.X, (int)Position.Y - (int)Origin.Y, animation.FrameWidth, animation.FrameHeight);

}
throw new Exception("Unknown sprite");

}

}
public Vector2 Centre

{

get

{

return new Vector2(Rectangle.X + Origin.X, Rectangle.Y + Origin.Y);

}

}
public float Rotation

{

get { return _rotation; }

set

{

_rotation = value;
if (_animationManager != null)

_animationManager.Rotation = value;

}

}
public readonly Color[] TextureData;
public Matrix Transform

{

get

{

return Matrix.CreateTranslation(new Vector3(-Origin, 0)) *

Matrix.CreateRotationZ(_rotation) *

Matrix.CreateTranslation(new Vector3(Position, 0));

}

}
public Sprite Parent;
///

/// The area of the sprite that could "potentially" be collided with

///


public Rectangle CollisionArea

{

get

{

return new Rectangle(Rectangle.X, Rectangle.Y, MathHelper.Max(Rectangle.Width, Rectangle.Height), MathHelper.Max(Rectangle.Width, Rectangle.Height));

}

}
public Sprite(Texture2D texture)

{

_texture = texture;
Children = new List();
Origin = new Vector2(_texture.Width / 2, _texture.Height / 2);
CollisionType = CollisionTypes.None;
Colour = Color.White;
TextureData = new Color[_texture.Width * _texture.Height];

_texture.GetData(TextureData);

}
public Sprite(Dictionary animations)

{

_texture = null;
Children = new List();
Colour = Color.White;
TextureData = null;
_animations = animations;
var animation = _animations.FirstOrDefault().Value;
_animationManager = new AnimationManager(animation);
Origin = new Vector2(animation.FrameWidth / 2, animation.FrameHeight / 2);

}

public override void Update(GameTime gameTime)

{
}
public virtual void ApplyPhysics(GameTime gameTime)

{
}
public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)

{

if (_texture != null)

spriteBatch.Draw(_texture, Position, null, Colour, _rotation, Origin, 1f, SpriteEffects.None, Layer);

else if (_animationManager != null)

_animationManager.Draw(spriteBatch);

}
public bool Intersects(Sprite sprite)

{

if (this.TextureData == null)

return false;
if (sprite.TextureData == null)

return false;

var transformAToB = this.Transform * Matrix.Invert(sprite.Transform);

var stepX = Vector2.TransformNormal(Vector2.UnitX, transformAToB);

var stepY = Vector2.TransformNormal(Vector2.UnitY, transformAToB);

var yPosInB = Vector2.Transform(Vector2.Zero, transformAToB);
for (int yA = 0; yA < this.Rectangle.Height; yA++)

{

var posInB = yPosInB;
for (int xA = 0; xA < this.Rectangle.Width; xA++)

{

var xB = (int)Math.Round(posInB.X);

var yB = (int)Math.Round(posInB.Y);
if (0 <= xB && xB < sprite.Rectangle.Width &&

0 <= yB && yB < sprite.Rectangle.Height)

{

var colourA = this.TextureData[xA + yA * this.Rectangle.Width];

var colourB = sprite.TextureData[xB + yB * sprite.Rectangle.Width];
if (colourA.A != 0 && colourB.A != 0)

{

return true;

}

}

posInB += stepX;

}

yPosInB += stepY;

}

return false;

}

public virtual void OnCollides(Sprite sprite)

{
}

public object Clone()

{

var sprite = this.MemberwiseClone() as Sprite;
if (_animations != null)

{

sprite._animations = this._animations.ToDictionary(c => c.Key, v => v.Value.Clone() as Animation);

sprite._animationManager = sprite._animationManager.Clone() as AnimationManager;

}
return sprite;

}

public bool WillIntersect(Sprite sprite)

{

return this.WillIntersectBottom(sprite) ||

this.WillIntersectLeft(sprite) ||

this.WillIntersectRight(sprite) ||

this.WillIntersectTop(sprite);

}
public bool WillIntersectLeft(Sprite sprite)

{

return this.Rectangle.Right + this._velocity.X >= sprite.Rectangle.Left &&

this.Rectangle.Left + this._velocity.X < sprite.Rectangle.Left &&

this.Rectangle.Top /*+ this._velocity.Y */< sprite.Rectangle.Bottom &&

this.Rectangle.Bottom/* + this._velocity.Y*/ > sprite.Rectangle.Top;

}
public bool WillIntersectRight(Sprite sprite)

{

return this.Rectangle.Left + this._velocity.X <= sprite.Rectangle.Right &&

this.Rectangle.Right > sprite.Rectangle.Right &&

this.Rectangle.Top /*+ this._velocity.Y */< sprite.Rectangle.Bottom &&

this.Rectangle.Bottom/* + this._velocity.Y*/ > sprite.Rectangle.Top;

}
public bool WillIntersectTop(Sprite sprite)

{

return this.Rectangle.Bottom + this._velocity.Y >= sprite.Rectangle.Top &&

this.Rectangle.Top < sprite.Rectangle.Top &&

this.Rectangle.Right/* + this._velocity.X*/ > sprite.Rectangle.Left &&

this.Rectangle.Left /*+ this._velocity.Y */< sprite.Rectangle.Right;

}
public bool WillIntersectBottom(Sprite sprite)

{

return this.Rectangle.Top + this._velocity.Y <= sprite.Rectangle.Bottom &&

this.Rectangle.Bottom > sprite.Rectangle.Bottom &&

this.Rectangle.Right/* + this._velocity.X*/ > sprite.Rectangle.Left &&

this.Rectangle.Left /*+ this._velocity.Y */< sprite.Rectangle.Right;

}

}

}
Код обработки логики для врагов:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using Microsoft.Xna.Framework.Graphics;

using Microsoft.Xna.Framework;
namespace Contra.Sprites

{

public class Enemy : Body

{

private float _timer;
public bool fire;
public float ShootingTimer = 1.75f;
public Enemy(Texture2D texture)

: base(texture)

{

Speed = 2f;

}
public override void Update(GameTime gameTime)

{

Direction = new Vector2((float)Math.Cos(_rotation), (float)Math.Sin(_rotation));
_timer += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (_timer >= ShootingTimer)

{

Shoot2(Direction,-5f);

_timer = 0;

}
Position += new Vector2(-Speed, 0);
// if the enemy is off the left side of the screen

if (Position.X < -_texture.Width)

IsRemoved = false;
ApplyPhysics(gameTime);

}
public override void OnCollide(Sprite sprite)

{

// If we crash into a player that is still alive

if (sprite is Player && !((Player)sprite).IsDead)

{

((Player)sprite).Score.Value++;
// We want to remove the ship completely

IsRemoved = true;

}
// If we hit a bullet that belongs to a player

if (sprite is Bullet && ((Bullet)sprite).Parent is Player)

{

Health--;
if (Health <= 0)

{

IsRemoved = true;

((Player)sprite.Parent).Score.Value++;

}

}

}

}

}
3.2 Руководство пользователя

После запуска приложения вас встречает главное меню:



Рисунок 3 – Главное меню приложения

По центру приложения расположены главные кнопки управления. Необходимые для смены состояний игры.



Рисунок 4 – Экран Игры

На нем отображены: игрок(и), база, блоки, враги



Рисунок 5 – Экран результатов

Чтобы закончить работу с приложением можно закрыть главное окно.



Заключение



В ходе курсового проекта было разработано игровое приложение «Контра». В трех разделах пояснительной записки описано проектирование и разработка приложения.

Приложение выполнено с помощью среды разработки Visual Studio и дополнительного ПО «Monogame» и протестировано согласно приведенной программе проведения испытаний.

Цели, поставленные перед разработкой курсового проекта достигнуты

Список используемой литературы





  1. Албахари, Джозеф C# 3.0. Справочник / Джозеф Албахари, Бен Албахари. - М.: БХВ-Петербург, 2013. - 944 c.

  2. Бишоп, Дж. C# в кратком изложении / Дж. Бишоп, Н. Хорспул. - М.: Бином. Лаборатория знаний, 2013. - 472 c.

  3. Вагнер, Билл С# Эффективное программирование / Билл Вагнер. - М.: ЛОРИ, 2013. - 320 c.

  4. Банк, В.С. Информационные технологии в экономике / В.С. Банк, В.С. Зверевю – М.: Финансы и статистика, 2013. – 547 с.

  5. Докучаев, А.А. Средства информатики в офисе торговой фирмы. Средства компьютерных коммуникаций. / А.А. Докучаев, С.А. Мошенский, О.В. Назаров – СПб.: ТЭИ, 2006. – 320 с.

  6. Клименко, С.В. Internet: среда обитания информационного общества. / С.В. Клименко, В.Ф. Уразметов – М.: РЦ ФТИ, 2005.

  7. Климова, Р.Н. Информатика торговой фирмы / Учебное пособие. Для студентов всех специальностей всех форм обучения. / Р.Н. Климова, М.В. Сорокина, И.А. Хахаев, С.А. Мошенский – СПб.: ТЭИ, 2008. – 320 с.

  8. Monogame Introduction (руководство пользования) Monogame team. https://docs.monogame.net/

Приложение А. Фрагмент кода


  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using System.Threading.Tasks;

  6. using Microsoft.Xna.Framework;

  7. using Microsoft.Xna.Framework.Content;

  8. using Microsoft.Xna.Framework.Graphics;

  9. using Contra.Sprites;

  10. using Microsoft.Xna.Framework.Input;

  11. using Contra.Managers;

  12. using System.Reflection;

  13. using Contra.States;

  14. using Contra.Models;

  15. using System.Reflection.Metadata;



  16. namespace Contra.status

  17. {

  18. public class GameState : State

  19. {

  20. private EnemyManager _enemyManager;



  21. private BlockManager _blockManager;



  22. private SpriteFont _font;



  23. private List
    _players;



  24. private ScoreManager _scoreManager;



  25. private List _sprites;



  26. private Camera _camera;



  27. private Texture2D _map;



  28. public int PlayerCount;



  29. public bool Spawn;



  30. public int Lindex = 0;



  31. public int ind;



  32. public GameState(Game1 game, ContentManager content)

  33. : base(game, content)

  34. {



  35. }



  36. public override void LoadContent()

  37. {

  38. var playerTexture = _content.Load("player1");

  39. var bulletTexture = _content.Load("bullet");

  40. _map = _content.Load("Map");



  41. _font = _content.Load("text2");



  42. _scoreManager = ScoreManager.Load();



  43. _camera = new Camera();



  44. var texture = _content.Load("trava");



  45. _sprites = new List()

  46. {

  47. //new Sprite(_content.Load("Map"))

  48. //{

  49. // Layer = 0.0f,

  50. // Position = new Vector2(0,0),

  51. // CollisionType = CollisionTypes.None,

  52. //},

  53. };



  54. var bulletPrefab = new Bullet(bulletTexture)

  55. {



  56. };



  57. if (PlayerCount >= 1)

  58. {

  59. _sprites.Add(new Player(playerTexture)

  60. {

  61. index = 0,

  62. Position = new Vector2(122, 275),

  63. Layer = 0.3f,

  64. Bullet = bulletPrefab,

  65. Input = new Input()

  66. {

  67. Up = Keys.W,

  68. Down = Keys.S,

  69. Left = Keys.A,

  70. Right = Keys.D,

  71. Jump = Keys.Space,

  72. Shoot = Keys.F,

  73. },

  74. Health = 4,

  75. Score = new Score()

  76. {

  77. PlayerName = "Player 1",

  78. Value = 0,

  79. },

  80. });

  81. }



  82. if (PlayerCount >= 2)

  83. {

  84. ind = 1;

  85. _sprites.Add(new Player(playerTexture)

  86. {

  87. index= 1,

  88. Colour = Color.Green,

  89. Position = new Vector2(172, 275),

  90. Layer = 0.4f,

  91. Bullet = bulletPrefab,

  92. Input = new Input()

  93. {

  94. Up = Keys.Up,

  95. Down = Keys.Down,

  96. Left = Keys.Left,

  97. Right = Keys.Right,

  98. Jump = Keys.RightShift,

  99. Shoot = Keys.Enter,

  100. },

  101. Health = 4,

  102. Score = new Score()

  103. {

  104. PlayerName = "Player 2",

  105. Value = 0,

  106. },

  107. });

  108. }



  109. _players = _sprites.Where(c => c is Player).Select(c => (Player)c).ToList();



  110. _enemyManager = new EnemyManager(_content)

  111. {

  112. Bullet = bulletPrefab,

  113. };

  114. _blockManager = new BlockManager(_content)

  115. {



  116. };

  117. }



  118. public override void Update(GameTime gameTime)

  119. {

  120. if (Keyboard.GetState().IsKeyDown(Keys.Escape))

  121. _game.ChangeState(new MenuState(_game, _content));



  122. foreach (var sprite in _sprites)

  123. sprite.Update(gameTime);



  124. if (ind > 0)

  125. if (_players[0].IsDead)

  126. Lindex = 1;



  127. _enemyManager.Update(gameTime);

  128. if (_enemyManager.CanAdd && _sprites.Where(c => c is Enemy).Count() < _enemyManager.MaxEnemies)

  129. {

  130. _sprites.Add(_enemyManager.GetEnemy());

  131. }

  132. _blockManager.Update(gameTime);

  133. if (Spawn)

  134. {

  135. int c = 0;

  136. for(int x = 137; x < 11000; x +=94)

  137. {

  138. for(int y = 0; y < 700; y +=1)

  139. {

  140. //c = 1;

  141. //if (x >= 2299 && x < 2779 && y == 311)

  142. //{

  143. // _sprites.Add(_blockManager.GetBlock(x, y, c));

  144. //}

  145. c = 0;

  146. if (x >= 4038 && x < 5542 && y == 223 || x >= 6012 && x < 6482 && y == 223



  147. || x >= 137 && x < 4226 && y == 321 || x >= 5448 && x < 6106 && y == 321 || x >= 6576 && x < 6764 && y == 321

  148. || x >= 6952 && x < 7140 && y == 321 || x >= 7422 && x < 7798 && y == 321





  149. || x>= 513 && x <795 && y == 415 || x >= 1265 && x < 1453 && y == 415 || x >= 4696 && x < 5354 && y == 415

  150. || x >= 6388 && x < 6670 && y == 415 || x >= 6858 && x < 7046 && y == 415 || x >= 7234 && x < 7422 && y == 415

  151. || x >= 7798 && x < 7892 && y == 415



  152. || x >= 1923 && x < 2205 && y == 458 || x >= 4414 && x < 4602 && y == 458 || x >= 6200 && x < 6294 && y == 458

  153. || x >= 7516 && x < 7798 && y == 458



  154. || x >= 795 && x < 889 && y == 509 || x >= 1077 && x < 1171 && y == 509 || x >= 5636 && x < 5824 && y == 509

  155. || x >= 5918 && x < 6106 && y == 509 || x >= 7892 && x < 7986 && y == 509



  156. || x >= 889 && x < 1077 && y == 600 || x >= 1829 && x < 2017 && y == 600 || x >= 4132 && x < 4414 && y == 600

  157. || x >= 5072 && x < 5636 && y == 600 || x >= 7422 && x < 8174 && y == 600 )



  158. {

  159. _sprites.Add(_blockManager.GetBlock(x,y,c));

  160. }

  161. }

  162. }

  163. Spawn= false;

  164. }

  165. CheckCollision(gameTime);

  166. }



  167. public void CheckCollision(GameTime gameTime)

  168. {

  169. var collidableSprites = _sprites.Where(c => c is ICollidable);



  170. foreach (var spriteA in collidableSprites)

  171. {

  172. foreach (var spriteB in collidableSprites)

  173. {

  174. // Don't do anything if they're the same sprite!

  175. if (spriteA == spriteB)

  176. continue;



  177. if (spriteA.WillIntersect(spriteB))

  178. //if (spriteA.Rectangle.Intersects(spriteB.Rectangle))

  179. spriteA.OnCollides(spriteB);

  180. }

  181. }

  182. }



  183. public override void PostUpdate(GameTime gameTime)

  184. {

  185. var collidableSprites = _sprites.Where(c => c is ICollidable);



  186. foreach (var spriteA in collidableSprites)

  187. {

  188. foreach (var spriteB in collidableSprites)

  189. {

  190. // Don't do anything if they're the same sprite!

  191. if (spriteA == spriteB)

  192. continue;



  193. if (!spriteA.CollisionArea.Intersects(spriteB.CollisionArea))

  194. continue;



  195. if (spriteA.Intersects(spriteB))

  196. ((ICollidable)spriteA).OnCollide(spriteB);

  197. }

  198. }



  199. // Add the children sprites to the list of sprites (ie bullets)

  200. int spriteCount = _sprites.Count;

  201. for (int i = 0; i < spriteCount; i++)

  202. {

  203. var sprite = _sprites[i];

  204. foreach (var child in sprite.Children)

  205. _sprites.Add(child);



  206. sprite.Children = new List();

  207. }



  208. for (int i = 0; i < _sprites.Count; i++)

  209. {

  210. if (_sprites[i].IsRemoved)

  211. {

  212. _sprites.RemoveAt(i);

  213. i--;

  214. }

  215. }



  216. // If all the players are dead, we save the scores, and return to the highscore state

  217. if (_players.All(c => c.IsDead))

  218. {

  219. foreach (var player in _players)

  220. _scoreManager.Add(player.Score);



  221. ScoreManager.Save(_scoreManager);



  222. _game.ChangeState(new HighscoresState(_game, _content));

  223. }



  224. }



  225. public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)

  226. {

  227. float playerX = MathHelper.Clamp(_players[Lindex].Position.X, 300, 10000);

  228. float offsetX = 300 - playerX;



  229. Matrix transform;



  230. //back

  231. transform = Matrix.CreateTranslation(offsetX, 0, 0);

  232. spriteBatch.Begin(transformMatrix: transform);

  233. spriteBatch.Draw(_map, Vector2.Zero, Color.White);

  234. spriteBatch.End();

  235. //block

  236. //transform = Matrix.CreateTranslation(offsetX * 0.6f, 0, 0);

  237. //spriteBatch.Begin();

  238. // spriteBatch.Draw(_map, Vector2.Zero, Color.White);

  239. //spriteBatch.End();



  240. spriteBatch.Begin(SpriteSortMode.FrontToBack, transformMatrix: transform);

  241. foreach (var sprite in _sprites)

  242. sprite.Draw(gameTime, spriteBatch);

  243. spriteBatch.End();



  244. spriteBatch.Begin();

  245. float x = 10f;

  246. foreach (var player in _players)

  247. {

  248. spriteBatch.DrawString(_font, "Player: " + player.Score.PlayerName, new Vector2(x, 10f), Color.White);

  249. spriteBatch.DrawString(_font, "Health: " + player.Health, new Vector2(x, 30f), Color.White);

  250. spriteBatch.DrawString(_font, "Score: " + player.Score.Value, new Vector2(x, 50f), Color.White);

  251. spriteBatch.DrawString(_font, Convert.ToString(player.Position), new Vector2(x, 120), Color.White);



  252. x += 150;

  253. }

  254. spriteBatch.End();

  255. }

  256. }

  257. }

795>