Функции ответа
Название этой функции - функция ответа — целиком отвечает ее назначению. Эта функция реагирует на то, что произошло какое-то событие: наступило определенное время, изменилось значение переменной или что-то еще. С помощью функций ответа мы будем реагировать на события или состояния определенными действиями.
Например, с помощью такой функции мы могли бы следить за временем и каждые пять минут воспроизводить какой-либо звук. В данном случае функция ответа реагирует на то, что пять минут прошли, издавая звуковой сигнал. С другой стороны, мы могли бы написать и такую функцию ответа, которая следила бы за переменной, значение коей может меняться либо самой программой либо во время обработки прерывания, и реагировала бы на такое изменение.
На рисунке 12.5 показано взаимодействие функций ответа с другими частями системы.
Все, о чем мы сейчас говорим, относится к методам программирования задач "реального времени". Обычно их не обсуждают ни в книгах, ни в институтах (возможно, поэтому они и кажутся вам несколько странными).
Но не будем отвлекаться и напишем функцию ответа, следящую за переменной timer. Через каждые пять «тиков» системных часов эта функция обнуляет значение переменной timer и изображает в случайной точке экрана пиксель. Текст этой программы приведен в Листинге 12.4.
Листинг 12.4. Функция ответа (PRES.C).
// ВКЛЮЧАЕМЫЕ ФАЙЛЫ ////////////////////////////////////////
#include <dos.h>
#include <bios.h>
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <graph.h>
// ОПРЕДЕЛЕНИЯ /////////////////////////////////
#define time_keeper_int 0x1C
// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ /////////////////////////////////////////
void (_interrupt _far *01d_Isr)();
// хранит Старый обработчик прерывания
long time=0;
// функции //////////////////////////////////////////////
void _interrupt _far*Timer ()
{
// увеличивает глобальную переменную
// еще раз отметим, что мы можем это делать, так как при входе в
// процедуру обработки прерывания регистр DS
указывает-на сегмент
// глобальных данных нашей программы
time++;
} // конец Timer
////////////////////////////////////////////
void Plot_Responder(void)
{
static int first_time=l;
static long old_time;
// проверка первого вызова
if (first_time)
{
//сброс флага первого вызова
first_time=0;
old_time = time;
} // конец оператора if else
( // не первый вызов
// прошло ли пять "тиков"?
if ( (time-old_time)>=5)
{
old_time
= time; // сохранить новую точку отсчета
// вывод пикселя на экран
_setcolor(rand()%16);
_setpixel(rand()%320,rand()%200) ;
} // конец оператора if
} // конец else
}// конец Plot_Responder,
// ОСНОВНАЯ ПРОГРАММА /////////////////////////////////////////////
main()
{
_setvideomode(_MRES256COLOR);
printf('Hit any key to exit...");
// установка процедуры обработки прерывания
0ld_Isr = _dos_getvect(TIME_KEEPER_INT);
_dos_setvect(TIME_KEEPER_INT, Timer);
// ожидание нажатия клавиши пользователем
while(!kbhit())
// ... текст программы игры
// вызов всех функций ответа Plot_Responder() ;
// ... текст программы игры
} // конец while
_setvideomode(_DEFAULTMODE) ;
// восстановление старого обработчика прерывания
_dos_setvect(TIME_KEEPER_INT, 01d_Isr) ;
} // конец функции main
В программе, приведенной в Листинге 12.4, функция ответа следит за временем и каждые пять «тиков» системных часов или 5х55.4 миллисекунды рисует на экране пиксель. Значение 55.4 получается из того, что системный таймер по умолчанию настроен так, что генерирует прерывание 18.2 раза в секунду или каждые 55.4 миллисекунды. Обратите внимание и на то, что функция ответа автономна.
Автономные функции и функции ответа могут быть использованы для самых разнообразных целей. Они позволяют выделить часть задач, не связанных с непосредственным ходом игры в отдельную группу и решать их отдельно. Логика игры и так достаточно сложна - поэтому не стоит ее без необходимости загромождать мерцающими огоньками и прочими мелкими деталями.
На персональных компьютерах следить за временем и,управлять событиями связанными с ним, можно только с помощью внутренних таймеров системы. К сожалению, большинство из них используется для других целей. Однако один применяется специально для внутренних часов компьютера. Он «тикает» со тростью 18.2 раза в секунду. Что и говорить, необычная отправная точка для вычислений и, честно говоря, я понятия не имею, почему создатели персональных компьютеров выбрали именно это значение. Но мы можем перепрограммировать его и задать более разумное число, например, 20, 30 или 60 «тиков» в секунду. Естественно, такие значения удобнее использовать в нашей компьютерной игре. Итак, давайте разберемся, как можно перепрограммировать внутренний таймер системы.