Помощь - Поиск - Пользователи - Календарь
Полная версия: нажатие кнопок...
Форум «Всё о Паскале» > Pascal, Object Pascal > Теоретические вопросы
MuXa
я хотел бы знать как в цикле фиксировать нажатие кнопки не останавливая при этом цикл ...
т.е. например в теле цикла х имзеняется по форуле x:=x+1; ... нажал что нада
а цикл всё идёт и ёдет ... но уже x:=x+2; ... вот так вот ...


за ответы заранее благодарен !
volvo
Для какого компилятора? Если ТР (не под Windows) - то написанием своего обработчика прерывания 09Н
Guest
<< то написанием своего обработчика прерывания 09Н >>

а можно об этом поподробней ?...
volvo
Вот каркас (так как написание процедур обработки прерываний - достаточно опасная вещь, я не буду писать ничего кроме "каркаса" программы с коментариями ):
uses Dos, Crt;
var
 Int09Save : Pointer;
{$F+}
procedure KbdHandler; interrupt;
 begin
{Если пришли сюда, то была нажата клавиша. Здесь определяется нажатие на клавишу
и ее скэн-код записывается в какую-либо глобальную переменную, после чего вызывается
"настоящее" прерывание 9Н}
 end;
{$F-}
begin
 GetIntVec($09,Int09Save); { Запоминание настоящего вектора прерывания }
 SetIntVec($09,Addr(KbdHandler)); { и подмена его своей процедурой обработки}

 {здесь расположен тот цикл, в течении которого нужно отслеживать нажатия на клавиши}

 SetIntVec($09,Int09Save); { Возврат настоящего вектора прерывания }
end.
P.S. А для чего это нужно, более конкретно можно описать? Возможно есть другой, более безопасный способ...
xds
Цитата

procedure KbdHandler; interrupt;
begin
{Если пришли сюда, то была нажата клавиша. Здесь определяется нажатие на клавишу
и ее скэн-код записывается в какую-либо глобальную переменную, после чего вызывается
"настоящее" прерывание 9Н}
end;


Дополню:
1) скэн-код и флаг нажатия-отпускания можно получить из порта $60 (как значение элемента псевдомассива Port, e. g. x := Port[$60]). Младшие 7 бит полученного значения будут разны скэн-коду, а старший 7-й бит равен 0, если клавиша нажата и 1 - если отпущена;
2) вызывать "настоящий" обработчик Int 9 не всегда имеет смысл - например, в том случае, когда мы сами хотим организовать буферизацию событий клавиатуры (в этом случае необходимо перед выходом из обработчика сбрасывать контроллер прерываний: Port[$20] := $20).

Цитата
P.S. А для чего это нужно, более конкретно можно описать? Возможно есть другой, более безопасный способ...

Да, это важно. Во многих случаях можно обойтись без подобных "махинаций" c IRQ1, используя, например, службы BIOS.
Altair
а зачем такие трудности? Может быть тело цикла выполняется за довольно малое время, и достаточно обойтись
If Keypressed then begin c:=ord(readkey); {выполняем что нужно} end;

смысл думаю ясен...
И цикл не останавливается и никаких TSR и никаких обработчиков.
Но это при условии, что тело цикла выполняется достаточно быстро... (то есть если он выполняется за час, то это не приемлимо smile.gif )
Бродяжник
Зачастую этот вопрос возникает, когда важно знать не то, нажималась ли какая-то клавиша перед выполнением очередной итерации цикла, а то, нажата ли она именно сейчас, или нет. Например, это важно в играх. Кроме того, через Keypressed нельзя отследить Ctrl, Shift, Alt etc. Я раньше все хотел написать какую-нить игрушку на ТР, и всякий раз упирался в клавиатуру. В конце концов я таки написал свой корявый обработчик Int09... после чего уперся в другие проблемы. <_< ...и они меня обломали.
FreeMan
Отсюда вывод: работать с прерываниями в паскале - фигня, юзайте асм, проблем будет меньше.
Altair
Глупость. все разговоры о том, что в Паскале что-то хуже делать чем где-то еще упираются в неправилое проектирование программы.
FreeMan
... или недостаточный уровень умений программинга на данном языке.
MuXa
huh.gif

народ я то хотел змейку намутить ...
типа не прерывая цикл менять напрвление движения ...
я смотрю так это заморочки большие мож как то с другой стороны подойти к этому делу ?
volvo
MuXa
А можешь привести пример того цикла, в течении которого надо изменять направление движения? Как он у тебя реализован?
SHnur
MuXa , вот ! Делай так :
Код

if keypressed then begin
  key := readkey;
  if (key = #0) then key := readkey;
end;


А потом в зависимости от key изменяй координаты ...
MuXa
Цитата
MuXa , вот ! Делай так :

Код 
Код

if keypressed then begin
 key := readkey;
 if (key = #0) then key := readkey;
end;



А потом в зависимости от key изменяй координаты ...


ВОТ ! ... это то что мне и было нужно ! спасибо !
suriv
Цитата
так как написание процедур обработки прерываний - достаточно опасная вещ

А почему опасная ? :p2:
volvo
suriv
Малейшая ошибка - и вектор прерывания "засылается в космос" - то есть неведомо куда, результат может быть самым плачевным, вплоть до потери информации на харде... sad.gif
Guest

program MuXaZ_zmeika;
uses crt,graph;
label 1,2,3,4,5;
var
rx1,rx2,ry2,ry1,i,i1,i2,i3,i4,i5,i6,i7,gd,gm:integer;
st,st1,st2,st3:string;
sx:array[0..50] of integer;
sy:array[0..50] of integer;
key:char;
begin
rx1:=0;
rx2:=640;
ry1:=0;
ry2:=480;
writeln('BBeDuTe DJIuHHy 3Meu (1-50)');
readln(i7);
writeln('BBeDuTe DJIuHHy CKopPocTb 3Meu (1-32)');
readln(i6);
Gd:=Detect;
InitGraph(Gd, Gm, 'e:\bp\bgi');
If GraphResult <> grOk Then Halt(1);
i1:=20;
i2:=20;
for i:= 1 to 20 do
begin
 sx[i]:=1;
 sy[i]:=1;
end;

i:=0;
while i<240 do
begin
if keypressed then
begin
 key:=readkey;
 if key=#52 then i3:=1;
 if key=#50 then i3:=2;
 if key=#54 then i3:=3;
 if key=#56 then i3:=4;
 if (key=#43) or (key=#27) then i3:=9
end;

if i1>rx2 then i1:=rx1;
if i2>ry2 then i2:=ry1;
if i1<rx1 then i1:=rx2;
if i2<ry1 then i2:=ry2;

if i3=1 then i1:=i1-5;
if i3=2 then i2:=i2+5;
if i3=3 then i1:=i1+5;
if i3=4 then i2:=i2-5;
if i3=9 then goto 1;
delay(trunc(32000/i6));
setcolor(green);

line(i1,i2,i1+5,i2+5);
line(i1+5,i2,i1,i2+5);
i4:=i7+1;
while i4>1 do
begin
 sx[i4]:=sx[i4-1];
 sy[i4]:=sy[i4-1];
 i4:=i4-1;
end;
sx[1]:=i1;
sy[1]:=i2;
setcolor(black);
line(sx[i7+1],sy[i7+1],sx[i7+1]+5,sy[i7+1]+5);
line(sx[i7+1]+5,sy[i7+1],sx[i7+1],sy[i7+1]+5);
setcolor(white);
end;

1:outtextxy(20,460,'THE END');
readkey;
end.
вот я собССно чё намутил кому интересно ...
можно выбирать скорость длинну и граници поля ...

СПАСИБО всем за помшь !
xds
Oleg_Z, интересно, каким боком TSR относятся к "Змейке"?.. ;) :D (хотя TSR-"Змейка" - это забавно...)
xds
Цитата
Код

if keypressed then begin
key := readkey;
if (key = #0) then key := readkey;
end;

Расширенные коды BIOS всё же стоит обрабатывать отдельно от ASCII, в противном случае мы, например, получим дополнительное управление клавишами H, K, M, P (что, впрочем, можно рассматривать как "undocumented feature") smile.gif


if KeyPressed then
 case ReadKey of
 { обработка ASCII }
 ...
 #0:
   case ReadKey of
   { обработка расширенных кодов }
   ...
   end;    
 end;

Guest
вот в догонку кому еще интересно ...
всё выглядит как нормальная змейка толко пака без собирания фруктов
и терь она сама в себя врезается и транспортикуется при врезании в стену ...
короче почти полноценная змея!

program MuXaZ_zmeika;
uses crt,graph;
label 1,2,3,4,5;
var
dl,dl1,start,xx,sp,yy,rx1,rx2,ry2,ry1,i,i1,i2,i3,i4,i5,i6,i7,gd,gm:integer;
st,st1,st2,st3:string;
sx:array[0..880] of integer;
sy:array[0..880] of integer;

key:char;
begin
rx1:=20;
rx2:=318;
ry1:=20;
ry2:=234;
writeln('BBeDuTe DJIuHHy 3Meu (1-50)');
readln(i7);
writeln('BBeDuTe DJIuHHy CKopPocTb 3Meu (1-32)');
readln(i6);
Gd:=Detect;
InitGraph(Gd, Gm, 'e:\bp\bgi');
If GraphResult <> grOk Then Halt(1);
setcolor(13);
SetTextStyle(2, HorizDir, 4);
outtextxy(490,450,'CDeJIaHo B Poccuu');
outtextxy(490,460,'BepboJII0K MuXauJI 812 rp.');
outtextxy(490,470,'yII MAu CePIIyXoB 2005');
SetTextStyle(12, HorizDir,1);
setcolor(12);
dl:=0;
sp:=0;
line(rx1-2,ry1-2,rx2+2,ry1-2);
line(rx1-2,ry1-2,rx1-2,ry2+2);
line(rx2+2,ry1-2,rx2+2,ry2+2);
line(rx1-2,ry2+2,rx2+2,ry2+2);

setcolor(green);

line(20,250,110,250);
line(20,265,20,250);
line(110,250,110,265);
line(110,265,20,265);

line(120,250,210,250);
line(120,265,120,250);
line(210,250,210,265);
line(210,265,120,265);

line(220,250,317,250);
line(317,250,317,265);
line(317,265,220,265);
line(220,265,220,250);

setcolor(yellow);
outtextxy(25,255,'XaBaJIo:');
outtextxy(125,255,'Pa3MeP:');
outtextxy(225,255,'CKOPOCTb:');

i:=7;
setcolor(8);
while i<=318 do
begin
i:=i+12;
line(i,20,i,234);
end;
i:=7;
setcolor(8);
while i<=233 do
begin
i:=i+12;
line(20,i,318,i);
end;

i1:=20;
i2:=20;
for i:= 1 to 50 do
begin
sx[i]:=1;
sy[i]:=1;
end;
randomize;
xx:=trunc((1590-random(1490))/5);
yy:=trunc((1170-random(1070))/5);
bar(xx,yy,xx+5,yy+5);
{knopki}
i:=0;
i3:=2;
readkey;
while i<240 do
begin
if keypressed then
begin
key:=readkey;
if key=#52 then i3:=1;
if key=#50 then i3:=2;
if key=#54 then begin  i3:=3; end;
if key=#56 then begin  i3:=4; end;
if (key=#43) or (key=#27) then i3:=9;
if key=#42 then i7:=i7+1;
if key=#47 then i6:=i6+1;
if key=#45 then i6:=i6-1;
end;


 {dvigenie}
if i3=1 then i1:=i1-12;
if i3=2 then i2:=i2+12;
if i3=3 then i1:=i1+12;
if i3=4 then i2:=i2-12;
if i3=9 then goto 1;

  {proverka udara}

for i:= 1 to i7 do
begin
if (i1=sx[i]) and (i2=sy[i]) then goto 1;
end;

  {zargranica}
if i1+10>rx2 then i1:=rx1;
if i2+10>ry2 then i2:=ry1;
if i1<rx1 then i1:=rx2-10;
if i2<ry1 then i2:=ry2-10;

 {skorost`}
if i6<>dl then begin
str(sp,st1);
setcolor(black);
outtextxy(300,255,st1);
str(i6,st1);
setcolor(11);
outtextxy(300,255,st1);
sp:=i6;
end;
if i6>0 then
delay(trunc(52000/i6)) else begin
i6:=1;
delay(trunc(52000/i6));
end;
setcolor(green);
{zmeya}
line(i1,i2,i1+10,i2);
line(i1+10,i2,i1+10,i2+10);
line(i1+10,i2+10,i1,i2+10);
line(i1,i2+10,i1,i2);
   {dlinna}
if i7<>dl then begin
str(dl,st1);
setcolor(black);
outtextxy(180,255,st1);
str(i7,st1);
setcolor(11);
outtextxy(180,255,st1);
dl:=i7;
end;

  {massiv zmei}
i4:=i7+1;
while i4>1 do
begin
sx[i4]:=sx[i4-1];
sy[i4]:=sy[i4-1];
i4:=i4-1;
end;
sx[1]:=i1;
sy[1]:=i2;
setcolor(black);
   {zatiranie zmei}
line(sx[i7+1],sy[i7+1],sx[i7+1]+10,sy[i7+1]);
line(sx[i7+1]+10,sy[i7+1],sx[i7+1]+10,sy[i7+1]+10);
line(sx[i7+1]+10,sy[i7+1]+10,sx[i7+1],sy[i7+1]+10);
line(sx[i7+1],sy[i7+1]+10,sx[i7+1],sy[i7+1]);
setcolor(green);

end;

1:outtextxy(20,460,'THE END');
readkey;
end.
SHnur
MuXa , если хочеш , то можеш посмотреть мой вариант змейки.
Вот тут :
http://forum.pascal.net.ru/index.php?showtopic=3681
FreeMan
Цитата
вплоть до потери информации на харде...

какое прерывание и в каком состоянии надо цеплять, чтоб такого результата добится <_< ? или может IAT потасовать smile.gif
Altair
Цитата
какое прерывание и в каком состоянии надо цеплять, чтоб такого результата добится  ?

Со статусом модератора форума "Ассемблер" не поспоришь, ;) smile.gif однако INT13h!!!
Сам лично потерял информацию с харда таким образом однажды...

ЗЫ: да иногда и с INT21 можно делов натворить smile.gif
Romtek
Флейм пошёл жестокий...

Код
repeat

 key := readkey;
 if key=#0 then
   key := readkey;

 case key of
 #75:; {Left}
  begin
     x:=x-stepX;
     if (x < minX) then
        stepX := -stepX; {поменять направление движения на обратное}
  end;

 #77: {Right}
  begin
     x:=x+stepX;
     if (x > maxX) then
        stepX := -stepX;
  end;

 #72:; {Up} аналогично

 #80:; {Down}
 end;

until key=#27; {Esc}
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.