hRet := DIKeyboard.Acquire;
while hRet = DIERR_INPUTLOST do
hRet := DIKeyboard.Acquire;
end;
sMulti := '';
for i := 0 to 255 do // Вывод кодов нажатых клавиш
if diks[i] and $80 <> 0
then sMulti := sMulti + ' ' + Format ('Ox%02x', [i]);
Memol.Lines.Add (sMulti);
Result := DI_OK;
end;
Непосредственная схема основана на использовании метода GetDeviceState, по вызову которого массив заполняется данными о состоянии клавиш, точно также здесь возможны значения 0 и 128.
В примере происходит опрос состояния всех клавиш, что не обязательно делать, если вас интересуют только некоторые из них. Например, если требуется осуществить выход по нажатии клавиши , можно не пробегать в цикле по всем элементам массива, а обратиться только к единственному:
if diks [DIK^ESCAPE] = 128 then Close;
С помощью непосредственной схемы доступа легко обрабатывать нажатие нескольких клавиш одновременно, чем и пользуются часто в играх, как, например, в очередном примере - проекте каталога Ех06. От предыдущего варианта нашей тестовой игры пример отличается только тем, что здесь для управления используется библиотека Directlnput. Скорость ввода стала чрезвычайно стремительной, воин теперь резво передвигается по нажатии клавиш, буквально быстрее пули. Хотя шаг его нисколько не увеличился. Одним махом происходит обработка нескольких клавиш, и можно, например, стрелять вверх и вбок одновременно, или двигаться вправо и стрелять вверх. Пули тоже вылетают на порядок быстрее, и ограничение в сотню расходуется в считанные секунды.
Принципиально обработка ввода ничем не отличается от первого примера на основе библиотеки Directlnput. Здесь используется непосредственная схема доступа, только уровень доступа устанавливается в комбинацию
DISCL_FOKEGROUND or DISCL_EXCLUSIVE. Несмотря на негласное соглашение,
что неактивное приложение не будет считывать данные с клавиатуры, при запуске двух копий программы обе они сильно замедлятся.
Работа с мышью
После знакомства с возможностями ввода с клавиатуры нам будет легко научиться работать с мышью, принципы обработки ввода здесь точно такие же. Непосредственную схему доступа изучим на конкретном примере - проекте каталога Ех07. Это еще один вариант создания эффекта лупы, но более эффектный, чем предыдущие, поскольку здесь добавлены сферические искажения пикселов (рис. 5.7).
Представленные ниже константы и переменные связаны с параметрами искажений:
const
Diameter = 180; // Задает максимальный размер лупы
Scale =35; // Вспомогательный коэффициент
var
Radius : Integer = Diameter div 2; // Текущий размер лупы
SqrRad : Integer; // Вспомогательные величины
Sphere : Integer;
Вспомогательные переменные заполняются первоначально при создании формы:
SqrRad := Radius * Radius; // Квадрат радиуса
Sphere := (Radius * Radius) - (Scale * Scale); // Искажение
Во время перерисовки кадра накладываем фон, а искажения вносим сразу на поверхность заднего буфера:
function TfrmDD.UpdateFrame : HRESULT;
var
hRet : HRESULT;
begin
// Блиттинг фона
hRet := FDDSBack.BltFast (0, 0, FDDSBackGround, nil, DDBLTFAST_WAIT);
if Failed (hRet) then begin
Result := hRet;
Exit;
end;
hRet := Zoom; // Вызов функции создания эффекта
if Failed (hRet) then begin
Result := hRet;
Exit;
end;
Result := FlipPages; // Переключение буферов
end;
Эффект построен на простейшей математике - уравнениях круга и сферы:
function TfrmDD.Zoom : HRESULT;
var
descl : TDDSURFACEDESC2;
desc2 : TDDSURFACEDESC2;
X, Y : Integer;
XX,YY,YYXX : Integer;
mz : Single;
hRet : HRESULT;
begin
ZeroMemory (Sdescl, SizeOf(descl) );
descl.dwSize := SizeOf (descl);
ZeroMemory (@desc2, SizeOf(desc2));
desc2.dwSize := SizeOf (desc2);
hRet := FDDSBack.Lock (nil, descl, DDLOCK_WAIT, 0);
if Failed (hRet) then begin
Result := hRet;
Exit ;
end;
hRet := FDDSBackGround.Lock (nil, desc2, DDLOCK_WAIT, 0);
if Failed (hRet) then begin
Result := hRet;
Exit;
end;
for Y := -Radius to Radius do begin
YY := у * Y;
for X := -Radius to Radius do begin
XX := X * X; YYXX := YY + XX;
if YYXX < Sphere then begin // Точка внутри круга
mz := Scale / sqrt(SqrRad - YYXX); // Масштаб по третьей оси
// Пиксел на задней поверхности
PWord (Integer(descl.IpSurfасе) + (Y + mouseY) * descl.IPitch +
(mouseX + x) * 2)^ :=
// Источник на поверхности фона
PWord (Integer(desc2.IpSurfасе) +
trunc (mz * Y + mouseY) * desc2.IPitch +
trunc (mz * X + mouseX) * 2)^;
end;
end ;
end;
FDDSBackGround.Unlock (nil);
FDDSBack.Unlock (nil);
Result := DDJ3K;
end;
Для работы с устройством введены переменные уже знакомых нам типов:
DInput : IDIRECTINPUT8 = nil;
DIMouse : IDIRECTINPUTDEVICE8 = nil;
В коде подготовки устройства выполняются действия, аналогичные работе с клавиатурой, лишь поменялись константы:
function TfrmDD.OnCreateDevice : HRESULT;
var
hRet : HRESULT;
begin
hRet := DirectlnputBCreate (hlnstance, DIRECTINPUT_VERSION,
IID_IDirectInput8, DInput, nil) ;
// GUID соответствует устройству "мышь"
Читать дальше
Конец ознакомительного отрывка
Купить книгу