Нужно сделать так, чтобы система Windows не перерисовывала экран. Для этого следует переопределить метод OnPaintBackground
, отвечающий за перерисовку экрана, причем новая версия метода вообще ничего не будет делать, что иллюстрирует листинг 11.14.
protected override void OnPaintBackground(PaintEventArgs pevent) {
// He разрешаем перерисовывать фон
}
После добавления этого метода в программу мерцание исчезнет. Кусочек сыра теперь движется без всякого мерцания.
Но теперь появилась другая проблема. Когда кусочек сыра проходит через батон хлеба, то виден прямоугольник, обрамляющий изображение сыра. Кроме того, по условиям игры, сыр не может проходить через батон, а должен при столкновении изменить свое направление и двигаться в другую сторону. Именно этой проблемой и нужно заняться сейчас.
Хлеб — всему голова
Наша программа должна уметь перемещать батон хлеба таким образом, чтобы игрок мог отбивать кусок сыра, как будто играя им в теннис. Для этой цели игрок будет использовать клавиши навигации на телефоне. Чтобы управлять батоном хлеба, придется использовать события KeyDown
и KeyUp
. Событие KeyDown
наступает, когда пользователь нажимает на заданную кнопку. Событие KeyUp
инициируется при отпускании кнопки.
Необходимо установить флаг, который будет отслеживать нажатия и отпускания клавиш. Когда флаг будет активирован, это будет означать, что пользователь нажал на клавишу, и батон должен двигаться в указанном направлении. Когда пользователь отпустит клавишу, то флаг сбрасывается и объект прекращает движение.
Обработчики событий используют перечисления Keys
, показывающие конкретные кнопки навигации. Соответствующий код приведен в листинге 11.15.
/// <summary>
/// Используем keyArgs в качестве флага
/// </summary>
private System.Windows.Forms.KeyEventArgs keyArgs = null;
private void Form1_KeyDown(object sender,
System.Windows.Forms.KeyEventArgs e) {
keyArgs = e;
}
private void Form1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) {
keyArgs = null;
}
Когда программа получает вызов события Form1_KeyDown
, флаг keyArgs
ссылается на класс KeyEventArgs
. При наступлении события Form1_KeyUp
флаг keyArgs
сбрасывается в null
, и код нажатых клавиш игнорируется. Теперь надо переписать метод updatePositions
, как показано в листинге 11.16.
private void updatePositions() {
// Код для кусочка сыра остался прежним
...
// Для батона хлеба
if (keyArgs != null) {
switch (keyArgs.KeyCode) {
case Keys.Up:
by-=ySpeed;
break;
case Keys.Down:
by+=ySpeed;
break;
case Keys.Left:
bx-=xSpeed;
break;
case Keys.Right:
bx+=xSpeed;
break;
}
}
}
В данном коде используется оператор switch
, который определяет действия программы в зависимости от нажатой клавиши. Батон хлеба движется с той же скоростью, что и кусочек сыра. На этой стадии при запуске программы пользователь может перемещать батон хлеба по всему экрану, в то время как кусочек сыра по-прежнему самостоятельно двигается по экрану.
Обнаружение столкновений
Для контроля столкновений в играх используются прямоугольные области. Конечно, здесь далеко до реализма, так как предметы не всегда имеют прямоугольную форму. Но в некоторых случаях пользователь может и не заметить этого. Ограничивающий прямоугольник вокруг изображения хлеба выглядит так, как показано на рис. 11.4.
Рис. 11.4. Ограничивающий прямоугольник для объекта
Две точки позволяют оперировать координатами верхнего левого и нижнего правого углов прямоугольника. В .NET Compact Framework существует структура RECTANGLE
, использующая эти координаты для реализации прямоугольника. Несколько методов используют эту структуру для обнаружения пересечения двух прямоугольников. С их помощью и можно обнаружить столкновение объектов. Ранее использовавшиеся переменные надо заменить структурой RECTANGLE
, в которой будет содержаться информация о местонахождении объекта. Соответствующий код приведен в листинге 11.17.
/// <summary>
/// Позиция и ограничивающий прямоугольник для сыра
/// </summary>
private Rectangle cheeseRectangle;