Solved

Keyboard handler (for game) with Delphi or C++ Builder

Posted on 1998-10-05
6
473 Views
Last Modified: 2010-04-06
How to make a keyboard handler (usually games use it, like
doom, duke nukeem so it can run very fast) with Delphi or C++ Builder. I want to get very immediate respons when I press keyboard so I can move fastly.
0
Comment
Question by:mince
6 Comments
 

Author Comment

by:mince
ID: 1341814
Please answer my question immediately because I need it very much to complete my
study.
0
 
LVL 4

Expert Comment

by:erajoj
ID: 1341815
Hi,
Isn't "OnKeyDown"/"OnKeyUp" fast enough?

/// John
0
 
LVL 1

Expert Comment

by:Roadrunner100598
ID: 1341816
If your program should recieve (and maybe process) the keyboard message first, try a hook function (see: SetWindowsHookEx). This will gain some extra microseconds.

And of course there is DirectX 5 - DirectInput as described in Mircosoft Press's 'Inside Direct X'. But I have never tried it myself...

Generally I would recommend using 'OnKeyDown'/'OnKeyUp' as the savest and easiest solution.

. and set the repetition rate in the control panel/keyboard to maximum.

Roadrunner
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 10

Expert Comment

by:viktornet
ID: 1341817
Yup, as the guys told you what you should do I guess I don't need to repeat that suggestion again.... OnKeyPress/OnKeyDown/OnKeyUp/SetWindowsHookEx/UnhookWindows.....and so on.....

P.S. Especially for games I guess the Hook is better, but it's more comlex to implement.... By complex I mean that you need more, code, more though, and a DLL which should be provided with your program...

Regards,
Viktor Ivanov
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1341818
though = thought, actually it's though too ;->
0
 
LVL 5

Accepted Solution

by:
scrapdog earned 200 total points
ID: 1341819
It is not a good idea to use events alone for a keyboard handler in a game.  In games, it is necessary to check whether or not several keys or pressed at a time.

The best way to do this is to use an array of booleans.  

var
  KeysDown :array[0..255] of boolean;

During your program, at any time you could check if a key is down or not by checking the array.  For example if you want to see if the A key is down, you would use:

if KeysDown[65] then ...

(where 65 is the key code for A).

And if you wanted to check if the A key AND the B key are both down, you could use:

if KeysDown[65] and KeysDown[66] then...



In order to keep this array updated, you can use the OnKeyUp and OnKeyDown events for your form.



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

  KeysDown[Key and 255] := true;
end;



When the key is pressed, its respective value in the array is set to true.  And then when the key is released, it is set back to false.

It is important that you intialize the KeysDown array to all false values before you start though. (like this)


procedure TForm1.FormCreate(Sender: TObject);
var i :integer;
begin
  for i := 0 to 255 do KeysDown[i] := false;
end;


---------------------------------------

This is the way DOS games handle the keyboard.  Any keypress or release generates make or break codes which are processed and the results are stored in an array.  Using this method allows to detect exactly which keys (even all of them) are down at any given moment.


Here is a demo program.  It shows which of the keys from a to z are pressed, in a label.


unit Unit1;

interface

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

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

var
  Form1: TForm1;
  KeysDown :array[0..255] of boolean;

implementation

{$R *.DFM}

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

  KeysDown[Key and 255] := true;
end;



procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  KeysDown[Key and 255] := false;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i :integer;
begin
  for i := 0 to 255 do KeysDown[i] := false;
end;

procedure TForm1.Timer1Timer(Sender: TObject);  //interval of 1 msec or so
var KeyStr :string;
    i      :integer;
begin
  KeyStr := '';
  for i := 65 to 90 do
    if KeysDown[i] then KeyStr := KeyStr + Chr(i);
  Label1.Caption := KeyStr;

end;

end.



Make sure you set the timer to a small interval (to make sure the label is updated quickly).  The keyboard handler is operating at all times though.


Here is a list of scan codes, taken from the Windows source code that came with Delphi
------------------------------------------

VK_LBUTTON = 1;
  VK_RBUTTON = 2;
  VK_CANCEL = 3;
  VK_MBUTTON = 4;  { NOT contiguous with L & RBUTTON }
  VK_BACK = 8;
  VK_TAB = 9;
  VK_CLEAR = 12;
  VK_RETURN = 13;
  VK_SHIFT = $10;
  VK_CONTROL = 17;
  VK_MENU = 18;
  VK_PAUSE = 19;
  VK_CAPITAL = 20;
  VK_ESCAPE = 27;
  VK_SPACE = $20;
  VK_PRIOR = 33;
  VK_NEXT = 34;
  VK_END = 35;
  VK_HOME = 36;
  VK_LEFT = 37;
  VK_UP = 38;
  VK_RIGHT = 39;
  VK_DOWN = 40;
  VK_SELECT = 41;
  VK_PRINT = 42;
  VK_EXECUTE = 43;
  VK_SNAPSHOT = 44;
  VK_INSERT = 45;
  VK_DELETE = 46;
  VK_HELP = 47;
{ VK_0 thru VK_9 are the same as ASCII '0' thru '9' ($30 - $39) }
{ VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' ($41 - $5A) }
  VK_LWIN = 91;
  VK_RWIN = 92;
  VK_APPS = 93;
  VK_NUMPAD0 = 96;
  VK_NUMPAD1 = 97;
  VK_NUMPAD2 = 98;
  VK_NUMPAD3 = 99;
  VK_NUMPAD4 = 100;
  VK_NUMPAD5 = 101;
  VK_NUMPAD6 = 102;
  VK_NUMPAD7 = 103;
  VK_NUMPAD8 = 104;
  VK_NUMPAD9 = 105;
  VK_MULTIPLY = 106;
  VK_ADD = 107;
  VK_SEPARATOR = 108;
  VK_SUBTRACT = 109;
  VK_DECIMAL = 110;
  VK_DIVIDE = 111;
  VK_F1 = 112;
  VK_F2 = 113;
  VK_F3 = 114;
  VK_F4 = 115;
  VK_F5 = 116;
  VK_F6 = 117;
  VK_F7 = 118;
  VK_F8 = 119;
  VK_F9 = 120;
  VK_F10 = 121;
  VK_F11 = 122;
  VK_F12 = 123;
  VK_F13 = 124;
  VK_F14 = 125;
  VK_F15 = 126;
  VK_F16 = 127;
  VK_F17 = 128;
  VK_F18 = 129;
  VK_F19 = 130;
  VK_F20 = 131;
  VK_F21 = 132;
  VK_F22 = 133;
  VK_F23 = 134;
  VK_F24 = 135;
  VK_NUMLOCK = 144;
  VK_SCROLL = 145;
{ VK_L & VK_R - left and right Alt, Ctrl and Shift virtual keys.
  Used only as parameters to GetAsyncKeyState() and GetKeyState().
  No other API or message will distinguish left and right keys in this way. }
  VK_LSHIFT = 160;
  VK_RSHIFT = 161;
  VK_LCONTROL = 162;
  VK_RCONTROL = 163;
  VK_LMENU = 164;
  VK_RMENU = 165;
  VK_PROCESSKEY = 229;
  VK_ATTN = 246;
  VK_CRSEL = 247;
  VK_EXSEL = 248;
  VK_EREOF = 249;
  VK_PLAY = 250;
  VK_ZOOM = 251;
  VK_NONAME = 252;
  VK_PA1 = 253;
  VK_OEM_CLEAR = 254;


Scrapdog

0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

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…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

707 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

18 Experts available now in Live!

Get 1:1 Help Now