Теперь при каждом вызове метода Paint
программа перерисовывает изображение сыра в указанном месте. Но программа должна самостоятельно перемещать изображение через определенные промежутки времени. Также нужно иметь возможность управлять скоростью перемещения картинки. Для этой задачи подойдет объект Timer
. Соответствующий элемент нужно добавить на форму.
Следует помнить, что во время работы таймера смартфон не может использовать сберегающий энергорежим, так как устройство считает, что программа находится в активном состоянии, даже если она свернута. Это негативно влияет на работу аккумуляторов, сокращая срок работы без подзарядки. Поэтому нужно останавливать таймер, когда программа работает в фоновом режиме, и включать его снова при активации приложения.
Но вернемся к настройкам таймера. Интервал срабатывания таймера должен составлять 50 миллисекунд, а свойство Enabled
должно получить значение False
. Когда таймер будет включен, код в методе Tick
будет срабатывать 20 раз в секунду. При создании таймера нельзя для свойства Enable
устанавливать значение True, так как метод timer1_Tick
попытается отобразить изображения до того, как они будут загружены. Включать таймер можно только тогда, когда все необходимые картинки будут загружены, иначе программа выдаст сообщение об ошибке. В нашем примере таймер активируется в конструкторе формы после загрузки изображения сыра, как это показано в листинге 11.6.
public Form1() {
//
// Required for Windows Form Designer support.
//
InitializeComponent();
// Получим ссылку на сборку
System.Reflection.Assembly execAssem =
System.Reflection.Assembly.GetExecutingAssemblу();
// Получим доступ к картинке с сыром
cheeseImage = new System.Drawing.Bitmap
(execAssem.GetManifestResourceStream(@"Bouncer.cheese.gif"));
// Включаем таймер
this.timer1.Enabled = true;
}
Теперь при запуске программы конструктор загружает картинку и включает таймер.
Настало время создать код для события Tick
. Система перерисовывает содержимое экрана только при определенных условиях. Мы можем заставить систему перерисовать экран при каждом изменении местоположения картинки с помощью метода Invalidate
. Таким образом, через определенные промежутки времени приложение меняет координаты изображения и обновляет экран, чтобы пользователь увидел картинку на новом месте. Соответствующий код приведен в листинге 11.7.
private void timer1_Tick(object sender, System.EventArgs e) {
updatePositions();
Invalidate();
}
После запуска программы кусочек сыра по диагонали переместится в правый нижний угол экрана. Когда изображение достигнет края экрана, оно продолжит свое движение и скроется. При движении изображение сыра немного мерцает, что очень раздражает всех пользователей. В дальнейшем этот недостаток будет исправлен.
Нужно запрограммировать обработку отражений объекта от стенок. Для этого надо отслеживать текущую позицию объекта и направление движения. Когда объект достигнет края стенки, нужно изменить направление движения. Для начала упростим код программы, отвечающей за отражения. Пусть координаты объекта при движении увеличиваются на единицу, когда кусочек сыра движется вправо и вниз, и уменьшаются на единицу при движении влево и вверх. Новый код метода updatePositions
приведен в листинге 11.8.
///
/// Направление движения по оси X
///
private bool goingRight = true;
///
/// Направление движения по оси Y
///
private bool goingDown = true;
private void updatePositions() {
if (goingRight) {
cx++;
} else {
cx--;
}
if ((cx + cheeseImage.Width) >= this.Width) {
goingRight = false;
}
if (cx <= 0) {
goingRight = true;
}
if (goingDown) {
cy++;
} else {
cy--;
}
if ((cy + cheeseImage.Height ) >= this.Height) {
goingDown = false;
}
if (cy <= 0) {
goingDown = true;
}
}
Обратите внимание на то, что в коде используются ширина и высота изображения и экрана. Не прописывая жестко величины размеров экрана и изображения, мы можем быть уверенными в том, что программа будет работать корректно в устройствах с любыми разрешением экрана и размерами картинки.