Solved

Keyboard access for Delphi game loop

Posted on 2004-08-13
11
878 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
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 

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
 

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

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Best Firemonkey component pack 1 101
Delphi : could not find program, '...exe' 2 165
Working with hours 3 57
Slow Restore if incremental backups using RDiff.exe 4 17
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

786 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