Смекни!
smekni.com

Методические указания к курсу программирования для студентов физического факультета Сравнительное объектно-ориентированное проектирование (стр. 8 из 8)

/// Определяет факт пересечения прямоугольников двух спрайтов.

/// </summary>

/// <param name="First">

/// Индекс (слой) первого спрайта.

/// </param>

/// <param name="Second">

/// Индекс (слой) второго спрайта.

/// </param>

/// <returns>

/// true, если спрайты пересекаются, и false в противном случае.

/// </returns>

bool Intersect(int First, int Second)

{

return sprites[First].SpriteRect.IntersectsWith

(sprites[Second].SpriteRect);

}

/// <summary>

/// Создает конкретное изображение спрайта.

/// </summary>

/// <remarks>

/// Метод PaintPicture является абстрактным в этом классе и должен быть

/// перекрыт наследниками, формирующими изображение с помощью этого метода.

/// </remarks>

protected abstract void PaintPicture();

/// <summary>

/// Убирает спрайт с экрана.

/// </summary>

protected internal virtual void Restore()

{

sprites.Canvas.DrawImage(image, location);

}

/// <summary>

/// Помещает спрайт на экран.

/// </summary>

protected internal virtual void Paint()

{

bmpCanvas.CopyFromScreen(sprites.Parent.RectangleToScreen

(SpriteRect).Location, new Point(), image.Size);

PaintPicture();

}

/// <summary>

/// Смещает положение спрайта на плоскости XY.

/// </summary>

/// <param name="drift">

/// Вектор смещения.

/// </param>

/// <returns>

/// true, если смещение произошло, и false, если нет.

/// </returns>

public virtual bool Move(Size drift)

{

Point newPos = location + drift;

bool result = true;

if (onBeforeMove != null)

result = onBeforeMove(this, ref newPos);

if (result = result &&

sprites.ClientRect.Contains(new Rectangle(newPos, spriteSize)))

Set<Point>(ref location, newPos);

return result;

}

/// <summary>

/// Перемещает сайт в новое положение на плоскости XY.

/// </summary>

/// <param name="newLocation">

/// Новое положение левого верхнего угла спрайта.

/// </param>

/// <returns>

/// true, если перемещение произошло, false, если нет.

/// </returns>

public virtual bool MoveTo(Point newLocation)

{

return Move((Size)newLocation - (Size)location);

}

}

/// <summary>

/// Собирает и хранит информацию о следах спрайтов, формирующих список.

/// </summary>

/// <remarks>

/// Объекты класса TracedSpriteList в добавление к свойствам своего предка

/// SpriteList создают и поддерживают битовый массив, хранящий информацию о

/// каждом пикселе клиентской области. Если пиксел является следом спрайта,

/// то соответствующий элемент массива имеет значение true, если нет, то false.

/// Класс TracedSpriteList перекрывает методы RemoveSpriteAt и Clear, уничтожая

/// информацию о следе удаляемого спрайта.

/// </remarks>

public class TracedSpriteList : SpriteList

{

/// <summary>

/// Хранит двумерный битовый массив, отображающий состояние пикселей

/// прямоугольника объекта Control - принадлежит ли пиксел следу спрайта, или фону.

/// </summary>

BitArray[] traceMap;

/// <summary>

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

/// </summary>

internal BitArray[] TraceMap { get { return traceMap; } }

/// <summary>

/// Инициализирует экземпляр объекта класса TracedSpriteList.

/// </summary>

/// <param name="control">

/// Объект, на котором изображаются спрайты.

/// </param>

public TracedSpriteList(Control control) : base(control)

{

traceMap = new BitArray[ClientRect.Width];

for (int i = 0; i < traceMap.Length; i++)

traceMap[i] = new BitArray(ClientRect.Height);

}

/// <summary>

/// Убирает спрайт из списка.

/// </summary>

/// <param name="z">

/// Индекс-слой устраняемого спрайта.

/// </param>

public override void RemoveSpriteAt(int z)

{

if (z > -1 && z < Count)

{

((TracedSprite)this[z]).TracePoints.Clear();

base.RemoveSpriteAt(z);

}

}

/// <summary>

/// Очищает список от спрайтов.

/// </summary>

public override void Clear()

{

for (int i = 0; i < traceMap.Length; i++)

for (int j = 0; j < traceMap[i].Count; j++)

traceMap[i][j] = false;

base.Clear();

}

}

/// <summary>

/// Спрайт, оставляющий след.

/// </summary>

/// <remarks>

/// Класс TracedSprite как и его предок является абстрактным.

/// Наследники класса TracedSprite получают возможность оставлять

/// след на клиентской области в форме отдельного пикселя на месте

/// положения своего центра в момент, предшествующий смене положения.

/// Порождать объекты класса TracedSprite должен метод Add, вызванный классом

/// TracedSpriteList. В противном случае будет сгенерирована

/// исключительная ситуация типа ArgumentException.

/// </remarks>

public abstract class TracedSprite : Sprite

{

/// <summary>

/// Хранит true, если спрайт оставляет след, и false, если нет.

/// </summary>

bool traced;

/// <summary>

/// Устанавливает и возвращает значение поля traced.

/// </summary>

public bool Traced { set { traced = value; } get { return traced; } }

/// <summary>

/// Хранит true, если пиксели следа

/// имеют специальный цвет, и false, если нет.

/// </summary>

/// <remarks>

/// Если пиксели следа не имеют специального цвета, то их цвет определяется

/// как дополнительный до белого от цвета пикселя фона.

/// </remarks>

bool traceColored;

/// <summary>

/// Устанавливает и возвращает значение поля traceColored.

/// </summary>

public bool TraceColored

{

set { traceColored = value; }

get { return traceColored; }

}

/// <summary>

/// Хранит цвет следа.

/// </summary>

Color traceColor = Color.White;

/// <summary>

/// Устанавливает и возвращает цвет следа.

/// </summary>

public Color TraceColor

{

set { traceColored = true; traceColor = value; }

get { return traceColor; }

}

/// <summary>

/// Хранит координаты точек следа.

/// </summary>

ArrayList tracePoints = new ArrayList();

/// <summary>

/// Возвращает ссылку на список координат точек следа.

/// </summary>

public ArrayList TracePoints { get { return tracePoints; } }

/// <summary>

/// Хранит относительное положение центра спрайта.

/// </summary>

Size centerOffset;

/// <summary>

/// Хранит абсолютное положение центра спрайта.

/// </summary>

Point center;

/// <summary>

/// Возвращает положение центра спрайта.

/// </summary>

public Point Center { get { return center; } }

/// <summary>

/// Инициализирует экземпляр объекта класса TracedSprite.

/// </summary>

/// <param name="SpriteRect">

/// Прямоугольник спрайта.

/// <param name="sprites">

/// Список спрайтов, которому принадлежит создаваемый экземпляр.

/// </param>

internal TracedSprite(Rectangle SpriteRect, SpriteList sprites) : base(SpriteRect, sprites)

{

if (!(Sprites is TracedSpriteList))

throw (new ArgumentException("Спрайт со следом может быть" +

" только членом списка - наследника TracedSpriteList!"));

centerOffset = new Size(SpriteSize.Width / 2, SpriteSize.Height / 2);

center = Location + centerOffset;

}

/// <summary>

/// Перемещает спрайт на плоскости XY.

/// </summary>

/// <param name="drift">

/// Вектор смещения.

/// </param>

/// <returns>

/// true, если перемещение произошло, и false, если нет.

/// </returns>

public override bool Move(Size drift)

{

if (Visible && Traced) PutTrace();

bool result = base.Move(drift);

if (result) center = Location + centerOffset;

return result;

}

/// <summary>

/// Изображает след спрайта.

/// </summary>

/// <remarks>

/// След спрайта изображается в виде пикселя измененного цвета в точке,

/// где находился центр спрайта на момент его перемещения.

/// </remarks>

public void PutTrace()

{

for (int i = Sprites.Count - 1; i >= 0; i--)

if (Sprites[i].Visible &&

Sprites[i].SpriteRect.Contains(center))

Sprites[i].Restore();

if (!((TracedSpriteList)Sprites).TraceMap[center.X - Sprites.ClientRect.Left]

[center.Y - Sprites.ClientRect.Top])

{

if (!traceColored)

using (Bitmap bitmap = new Bitmap(1, 1))

using (Graphics graphics = Graphics.FromImage(bitmap))

{

graphics.CopyFromScreen(Sprites.Parent.RectangleToScreen(

new Rectangle(center.X, center.Y, 1, 1)).Location,

new Point(), bitmap.Size);

Color clr = bitmap.GetPixel(0, 0);

using (Brush brush = new SolidBrush(

Color.FromArgb(0xff ^ clr.R, 0xff ^ clr.G, 0xff ^ clr.B)))

Sprites.Canvas.FillRectangle(brush, center.X, center.Y, 1, 1);

}

else

using (Brush brush = new SolidBrush(traceColor))

Sprites.Canvas.FillRectangle(brush, center.X, center.Y, 1, 1);

((TracedSpriteList)Sprites).TraceMap[center.X - Sprites.ClientRect.Left]

[center.Y - Sprites.ClientRect.Top] = true;

tracePoints.Add(new Point(center.X, center.Y));

}

foreach (TracedSprite sprite in Sprites)

if (sprite.Visible && sprite.SpriteRect.Contains(center))

sprite.Paint();

}

/// <summary>

/// Очищает коллекцию точек следа спрайта.

/// </summary>

~TracedSprite()

{

if (TracePoints != null && TracePoints.Count > 0) TracePoints.Clear();

}

}

/// <summary>

/// Спрайт в форме заполненного эллипса, заданного цвета и градиента.

/// </summary>

public class FillEllipseSprite : TracedSprite

{

/// <summary>

/// Хранит цвет спрайта.

/// </summary>

Color color = System.Drawing.Color.Gray;

/// <summary>

/// Возвращает и устанавливает цвет спрайта.

/// </summary>

public Color Color

{

set { Set<Color>(ref color, value); }

get { return color; }

}

/// <summary>

/// Хранит указание на то, является ли заполнение эллипса градиентным.

/// </summary>

bool isGradient = true;

/// <summary>

/// Устанавливает и возвращает поле isGradient.

/// </summary>

public bool IsGradient

{

set { Set<bool>(ref isGradient, value); }

get { return isGradient; }

}

/// <summary>

/// Хранит цвета границы градиентного заполнения.

/// </summary>

Color[] colors = { Color.FromArgb(0, 0, 0) };

/// <summary>

/// Устанавливает и возвращает цвета границы градиентного заполнения.

/// </summary>

public Color[] Colors

{

set { Set<Color[]>(ref colors, value); }

get { return colors; }

}

/// <summary>

/// Инициализирует экземпляр объекта класса FillEllipseSprite.

/// </summary>

/// <param name="SpriteRect">

/// Прямоугольник эллипса.

/// <param name="sprites">

/// Список спрайтов, которому принадлежит создаваемый экземпляр.

/// </param>

public FillEllipseSprite(Rectangle SpriteRect, SpriteList sprites)

: base(SpriteRect, sprites) { }

/// <summary>

/// Изображает спрайт в форме заполненного эллипса.

/// </summary>

protected override void PaintPicture()

{

if (!isGradient)

using (Brush brush = new SolidBrush(color))

Sprites.Canvas.FillEllipse(brush, SpriteRect);

else

using (GraphicsPath path = new GraphicsPath())

{

path.AddEllipse(SpriteRect);

using (PathGradientBrush pthGrBrush = new PathGradientBrush(path))

{

pthGrBrush.CenterColor = color;

pthGrBrush.SurroundColors = colors;

Sprites.Canvas.FillEllipse(pthGrBrush, SpriteRect);

}

}

}

}

}

Предлагается в среде MS Visual Studio 2005 составить проект, тестирующий описанные классы спрайтов.