[Webinar] Streamline your web hosting managementRegister Today

x
?
Solved

Keyboard access for Delphi game loop

Posted on 2004-08-13
11
Medium Priority
?
920 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
8 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 672 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
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 

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 664 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 35

Assisted Solution

by:Slick812
Slick812 earned 664 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

Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

Question has a verified solution.

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

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…
This is an update to some code that someone else posted on Experts Exchange. It is an alternate approach, I think a little easier to use, & makes sure that things like the Task Bar will update.
How can you see what you are working on when you want to see it while you to save a copy? Add a "Save As" icon to the Quick Access Toolbar, or QAT. That way, when you save a copy of a query, form, report, or other object you are modifying, you…
Enter Foreign and Special Characters Enter characters you can't find on a keyboard using its ASCII code ... and learn how to make a handy reference for yourself using Excel ~ Use these codes in any Windows application! ... whether it is a Micr…
Suggested Courses
Course of the Month11 days, 6 hours left to enroll

612 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