Solved

Keyboard access for Delphi game loop

Posted on 2004-08-13
11
867 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
Comment Utility
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
Comment Utility
0
 
LVL 11

Expert Comment

by:shaneholmes
Comment Utility
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
Comment Utility
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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

Assisted Solution

by:jonas78
jonas78 earned 166 total points
Comment Utility
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
Comment Utility
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-
Comment Utility
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
Comment Utility
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

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

743 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

8 Experts available now in Live!

Get 1:1 Help Now