Solved

Keyboard access for Delphi game loop

Posted on 2004-08-13
11
873 Views
Last Modified: 2008-01-09
Hello! I wonder whether anyone can help me -

I would like to write a simple loop with the ability to 'poll' the keyboard for key presses, so that if say the Down Arrow is pressed, something in the code will respond (I guess using a Case statement).

I have found some code that appears to work in exe form but that my version of Delphi will not compile - John Ayres Delphi Rocks (asteriods clone) - the code uses 'outdated' keyboard HOOKS.

HookProc:=MakeProcInstance(@KeyboardHook, HInstance);
KBHook:=SetWindowsHookEx(WH_KEYBOARD,THookProc(HookProc),HInstance,GetCurrentTask);
 
How can I access the Windows handles to check if any keys are being pressed?

Also if I'm right in my thinking am I limited to just detecting one keypress at a time?

As you might have guessed the loop is intended for simple games/simulators w/o Direct X (for now).
0
Comment
Question by:lefunkster
11 Comments
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 11791556
why not just use the key down/up on the draw or on the form ?
0
 
LVL 11

Accepted Solution

by:
Jase-Coder earned 168 total points
ID: 11791576
0
 
LVL 11

Expert Comment

by:shaneholmes
ID: 11792313
Procedure wmgetdlgCode(var Message:Twmgetdlgcode); message
WM_GetDlgCode;

Procedure TMycomponent.wmgetdlgCode(var Message:Twmgetdlgcode);
begin
 message.result:=DLGC_WantArrows;
end;

This will force the form to recognize the arrow key strokes and you can
do what ever you like with them
please keep in mind that you have to zero the key variable on the
onkeydown event if you don't want delphi's key handling procedure to
take any action on them.
like this...

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift:
TShiftState);
begin
  if key = vk_space then key := 0;
end;
0
 

Author Comment

by:lefunkster
ID: 11793340
OK - thanks for the response!

This is were I am with this:

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  // Let's move the sprite every time the arrow keys are pressed

  if Key = vk_left then PosX := PosX - 1; // Left
  if Key = vk_up  then PosY := PosY - 1; // Up
  if Key = 39 then PosX := PosX + 1; // Right
  if Key = 40 then PosY := PosY + 1; // Down
end;

This works but just for one keystroke - ie pressing 2 keys isn't processed; stepping through the code shows that the whole procedure is run through yet only one keystoke (ie move) is registered... is there a way around this?

I've only gone this way as this appears to be the simplest way to get the job done. I am a beginner and will of course look at Handles soon (I can't say I like the look of them - but I'm sure once I get a 'handle' on them...)

0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Assisted Solution

by:jonas78
jonas78 earned 166 total points
ID: 11796268
Here is a shortcut:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls;

type
  TForm1 = class(TForm)
    Shape1: TShape;
    Timer1: TTimer;
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure Timer1Timer(Sender: TObject);
    procedure FormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    { Private declarations }
  public
    { Public declarations }
    CKey:Word;

   CLeft,CRight,CUp,CDown:Boolean;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin

CKey := Key;

if Key = VK_LEFT then
  CLeft := True;
if Key = VK_RIGHT then
   CRight := True;
if Key = VK_UP then
   CUp := True;
if Key = VK_DOWN then
   CDown := True;

end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
if CLeft then
  Shape1.Left := Shape1.Left -2;
if CRight then
  Shape1.Left := Shape1.Left +2;
if CUp then
  Shape1.Top := Shape1.Top -2;
if CDown then
  Shape1.Top := Shape1.Top +2;
end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
if Key = VK_LEFT then
  CLeft := False;
if Key = VK_RIGHT then
   CRight := False;
if Key = VK_UP then
   CUp := False;
if Key = VK_DOWN then
   CDown := False;
end;

end.
0
 

Expert Comment

by:jonas78
ID: 11796321
It's probably not the best way to do this but it works.

Just remember to set the timer intervall to something low like 100 or 50 depending on what refresh rate you want.
0
 
LVL 5

Expert Comment

by:-Thespian-
ID: 11806117
The easy way - make an array of keys. The keyboard has <256 keys. So:
keys: array [0..255] of boolean; //the size is 256 if you will not use special keys.

Init somewere:
for i:=0 to 255 do
  keys[i]:=false;

In KeyDown proc:
  keys[Key]:=true;

In KeyUp proc:
  keys[Key]:=false;

In the procedure where you draw (for example before drawing scene):
if (keys[VK_UP])and(keys[VK_LEFT]) then
begin
  keys[VK_UP]:=false;
  keys[VK_LEFT]:=false;
  // Do anything;
end;

______
Best regards,
  Thespian.
0
 
LVL 33

Assisted Solution

by:Slick812
Slick812 earned 166 total points
ID: 11817369
hello lefunkster, , , I might use the API function  GetAsyncKeyState( ) to get a reading of wheather a Key is down or not

if GetAsyncKeyState(Ord('H')) < 0 then

if GetAsyncKeyState(VK_LEFT) < 0 then

 - - - - - - -  -

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  // Let's move the sprite every time the arrow keys are pressed

  if Key = vk_left then
    if GetAsyncKeyState(Ord('M')) < 0 then
    PosX := PosX - 2
    else
    PosX := PosX-1;

  if Key = vk_up  then
     if GetAsyncKeyState(VK_SHIFT) < 0 then
      PosX := PosY - 2
      else
      PosX := PosY-1;

  if Key = 39 then PosX := PosX + 1; // Right
  if Key = 40 then PosY := PosY + 1; // Down
end;
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
In this video I am going to show you how to back up and restore Office 365 mailboxes using CodeTwo Backup for Office 365. Learn more about the tool used in this video here: http://www.codetwo.com/backup-for-office-365/ (http://www.codetwo.com/ba…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, just open a new email message. In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now