Когда далее при написании программы мы поставим оператор-точку “.” после какого-либо объекта структуры Rectangle, то увидим подсказку с двумя основными методами Intersect и IntersectsWith (рис. 5.2) для обнаружения пересечения двух прямоугольников.
Рис. 5.2. Подсказка с методами Intersect и IntersectsWith.
Определение для наиболее применяемого метода IntersectsWith (который далее и мы будем часто применять) с параметром (Rectangle rect) структуры Rectangle на главных (в мире программирования) языках приведено в табл. 5.2.
Таблица 5.2.
Определение метода Rectangle.IntersectsWith структуры Rectangle.
Visual Basic (Declaration)
Public Function IntersectsWith ( _
rect As Rectangle _
) As Boolean
Visual Basic (Usage)
Dim instance As Rectangle
Dim rect As Rectangle
Dim returnValue As Boolean
returnValue = instance.IntersectsWith(rect)
C#
public bool IntersectsWith (
Rectangle rect
)
C++
public:
bool IntersectsWith (
Rectangle rect
)
J#
public boolean IntersectsWith (
Rectangle rect
)
JScript
public function IntersectsWith (
rect : Rectangle
) : Boolean
Этот метод IntersectsWith обнаруживает пересечение заданного нами первого прямоугольника со вторым прямоугольником, объявленного здесь как параметр (Rectangle rect).
Если метод определит, что ни одна точка одного прямоугольника не находится внутри другого прямоугольника, то метод возвращает булево значение False.
А если метод определит, что хотя бы одна точка одного прямоугольника находится внутри другого прямоугольника, то метод IntersectsWith возвращает булево значение True, и это значение применяется для изменения направления движения какого-либо прямоугольника на противоположное (чтобы уйти от дальнейшего пересечения), например, в таком коде:
//We check the collision of objects:
if (cheeseRectangle.IntersectsWith(breadRectangle))
{
//We change the direction of the movement to opposite:
goingDown = !goingDown;
//At the time of collision, we give a sound signal Beep:
Microsoft.VisualBasic.Interaction.Beep();
}
5.3. Код и выполнение программы
Теперь в проекте, который мы начали разрабатывать в предыдущей главе (и продолжаем в данной главе) объявляем два прямоугольника, а приведённый выше код в теле метода Form1_Paint заменяем на тот, который дан на следующем листинге (с подробными комментариями).
Листинг 5.1. Метод для рисования изображения.
//The rectangle, described around the first object:
Rectangle cheeseRectangle;
//The rectangle, described around the second object:
Rectangle breadRectangle;
private void Form1_Paint(object sender, PaintEventArgs e)
{
//We load into objects of class System.Drawing.Image
//the image files of the set format, added to the project
//by means of ResourceStream:
cheeseImage =
new Bitmap(myAssembly.GetManifestResourceStream(
myName_of_project + "." + "cheese.JPG"));
breadImage =
new Bitmap(myAssembly.GetManifestResourceStream(
myName_of_project + "." + "bread.JPG"));
//We initialize the rectangles, described around objects:
cheeseRectangle = new Rectangle(cx, cy,
cheeseImage.Width, cheeseImage.Height);
breadRectangle = new Rectangle(bx, by,
breadImage.Width, breadImage.Height);
//If it is necessary, we create the new buffer:
if (backBuffer == null)
{
backBuffer = new Bitmap(this.ClientSize.Width,
this.ClientSize.Height);
}
//We createobject of the Graphics class from the buffer:
using (Graphics g = Graphics.FromImage(backBuffer))
{
//We clear the form:
g.Clear(Color.White);
//We draw the image in backBuffer:
g.DrawImage(cheeseImage, cx, cy);
g.DrawImage(breadImage, bx, by);
}
//We draw the image on Form1:
e.Graphics.DrawImage(backBuffer, 0, 0);
//We turn on the timer:
timer1.Enabled = true;
} //End of the method Form1_Paint.
А вместо приведённого выше метода updatePositions для изменения координат записываем следующий метод, дополненный кодом для обнаружения столкновения объектов.
Листинг 5.2. Метод для изменения координат и обнаружения столкновения объектов.
private void updatePositions()
{
if (goingRight)
{
cx += xSpeed;
}
else
{
cx -= xSpeed;
}
if ((cx + cheeseImage.Width) >= this.Width)
{
goingRight = false;
//At the time of collision,
//the sound signal Beep is given:
Microsoft.VisualBasic.Interaction.Beep();
}
if (cx <= 0)
{
goingRight = true;
//At the time of collision,
//the sound signal Beep is given:
Microsoft.VisualBasic.Interaction.Beep();
}
if (goingDown)
{
cy += ySpeed;
}
else
{
cy -= ySpeed;
}
//That cheese did not come for the button3.Location.Y:
if ((cy + cheeseImage.Height) >= button3.Location.Y)
{
goingDown = false;
//At the time of collision,
//the sound signal Beep is given:
Microsoft.VisualBasic.Interaction.Beep();
}
if (cy <= 0)
{
goingDown = true;
//At the time of collision,
//the sound signal Beep is given:
Microsoft.VisualBasic.Interaction.Beep();
}
//We set to rectangles of coordinates of objects:
cheeseRectangle.X = cx;
cheeseRectangle.Y = cy;
breadRectangle.X = bx;
breadRectangle.Y = by;
//We check the collision of objects:
if (cheeseRectangle.IntersectsWith(breadRectangle))
{
//We change the direction of the movement to opposite:
goingDown = !goingDown;
//At the time of collision,
//the sound signal Beep is given:
Microsoft.VisualBasic.Interaction.Beep();
}
} //End of the updatePositions method.
В режиме выполнения (Build, Build Selection; Debug, Start Without Debugging) при помощи кнопок и мыши мы можем перемещать хлеб и этим хлебом, как ракеткой, отбивать сыр или вверх, или вниз (рис. 5.3). Напомним, что, так как угол падения сыра на хлеб равен 45 градусам, то и угол отражения сыра от хлеба (и от границ экрана) также равен 45 градусам.
5.4. Основные схемы столкновений и их реализация
Приведённый на предыдущем листинге код обнаруживает столкновение только тогда, когда сыр падает на хлеб сверху вниз и соприкасается с верхней плоскостью хлеба. Если же сыр соприкасается с хлебом сбоку (слева или справа), то отскока сыра от хлеба не происходит. Поэтому устраним этот недостаток, чтобы игра была более реалистичной.
Если мы оперируем с окружностями, описанными вокруг объектов, то возможны три основные схемы столкновений, показанные на рис. 5.4. В схемах 1 и 3 маленький круг ударяется о большой круг под углом 45 градусов и отражается под этим же углом и по этой же линии. В схеме 2 маленький круг ударяется о большой круг под углом 90 градусов и также вертикально отражается вверх.
Если же мы оперируем с прямоугольниками, описанными вокруг объектов, то возможны четыре основные схемы столкновений, показанные на рис. 5.5.