Vb, Delphi, .net, framework, C++, Java, Pascal,Visual Studio, Asm, Ruby, C#, j#, Cs, Html, Php, Perl, Asp, xHtml Get Free Souce Code Here...



How to use the keyboard as input for games - Delphi

Using the following code to let the player move in a game works. However, it doesn't really work the way we want. The problem is that when the player, for example, holds down the left arrow key and then fires, then the left movement will stop because another key than left is sent to the FormKeyDown() procedure. This will result in a nearly unplayable game in most cases.

procedure TForm1.FormKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
  case Key of
    vk_left  : Dec(x);
    vk_right : Inc(x);
    vk_up    : Dec(y);
    vk_down  : Inc(x);
    vk_space : BulletFired;  // call to another procedure
  end;
end;

What we need is to detect key presses without interrupting already present keys which are down. The solution for this is to keep a state of each key. This is done with the following global variables.

var
  movingUp    : boolean;
  movingDown  : boolean;
  movingRight : boolean;
  movingLeft  : boolean;

Now, instead of triggering the result directly (i.e. increasing/decreasing x/y position) we use the FormKeyDown() and FormKeyUp() procedures to toggle the state of each key. In this way, multiple keys may be down at once (for example the user may move up and right (diagonally) the same time as he presses fire).

FormKeyDown sets respectively state to True. Because someone can't move both up AND down at the same time the "opposite" key has to be set to False.

procedure TForm1.FormKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
  case Key of
    vk_left:
      begin
        movingLeft  := True;
        movingRight := False;
      end;
    vk_right:
      begin
        movingLeft  := False;
        movingRight := True;
      end;
    vk_up:
      begin
        movingUp   := True;
        movingDown := False;
      end;
    vk_down:
      begin
        movingUp   := False;
        movingDown := True;
      end;
    vk_space: BulletFired;
  end;
end;

When a key is released the state is set to False in the FormKeyUp procedure.

procedure TForm1.FormKeyUp(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
  case Key of
    vk_left  : movingLeft  := False;
    vk_right : movingRight := False;
    vk_up    : movingUp    := False;
    vk_down  : movingDown  := False;
    end;
end;

The actual moving of the player is then performed from the game loop (Application.OnIdle for example) depending on each state. This is also the place to check to see if the player doesn't move out of bounds or collide into anything else.

procedure TForm1.MovePlayer;
  if movingUp    then Dec(y);
  if movingDown  then Inc(y);
  if movingLeft  then Dec(x);
  if movingRight then Inc(x);
end;

This article was an example of how it may be done. I've tried to make it as general as possible so it shouldn't be a problem to apply this to a project, no matter if it's a jump'n run, racing or a shoot'em up game.

(more than one year later...)

As commented below, there is also another approach of doing this by using GetKeyState. The reason for the above, quite lenghty, solution is basically that I didn't know of GetKeyState when I wrote it more than one year ago. Therefore I do this little rewrite and add the GetKeyState solution.

Simply get rid of all the code above, and just replace the MovePlayer procedure with this code:

procedure TMainForm.MovePlayer;
begin
  if (GetKeyState(VK_UP) and $80) = $80 then
    Dec(y);

  if (GetKeyState(VK_DOWN) and $80) = $80 then
    Inc(y);

  if (GetKeyState(VK_LEFT) and $80) = $80 then
    Dec(x);

  if (GetKeyState(VK_RIGHT) and $80) = $80 then
    Inc(x);
end;

0 comments:

Post a Comment