* * *

Author Topic: Moving shape with keys  (Read 2602 times)

justnewbie

  • Full Member
  • ***
  • Posts: 129
Moving shape with keys
« on: April 28, 2018, 03:05:39 pm »
Hi,
This code works:
Code: Pascal  [Select]
  1. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  2. begin
  3.    case Key of
  4.     VK_LEFT:
  5.       Shape1.Left := Shape1.Left - 15;
  6.     VK_RIGHT:
  7.       Shape1.Left := Shape1.Left + 15;
  8.   end;
  9. end;

This code doesn't work:
Code: Pascal  [Select]
  1. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  2. begin
  3.    case Key of
  4.     VK_LSHIFT:
  5.       Shape1.Left := Shape1.Left - 15;
  6.     VK_RSHIFT:
  7.       Shape1.Left := Shape1.Left + 15;
  8.   end;
  9. end;

What is the problem in the second case (using shift keys)?
« Last Edit: April 28, 2018, 03:12:37 pm by justnewbie »

User137

  • Hero Member
  • *****
  • Posts: 1748
    • Nxpascal home
Re: Moving shape with keys
« Reply #1 on: April 28, 2018, 04:12:51 pm »
OnKeyDown can't distinct left and right shift presses, they both return VK_SHIFT (int 16). You can find that with:
Code: Pascal  [Select]
  1. caption:=inttostr(key);

But i don't know of easy way to do that. If it's important, you can give more details on what it's used for and if it's ok to have it only work on Windows platform.

ASerge

  • Hero Member
  • *****
  • Posts: 862
Re: Moving shape with keys
« Reply #2 on: April 28, 2018, 04:58:52 pm »
Code: Pascal  [Select]
  1. uses LclType, LclIntf;
  2.  
  3. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  4. begin
  5.   if Key = VK_SHIFT then
  6.     if GetKeyState(VK_LSHIFT) < 0 then
  7.       Shape1.Left := Shape1.Left - 15
  8.     else
  9.       Shape1.Left := Shape1.Left + 15;
  10. end;

Handoko

  • Hero Member
  • *****
  • Posts: 2443
  • My goal: build my own game engine using Lazarus
Re: Moving shape with keys
« Reply #3 on: April 28, 2018, 05:18:13 pm »
@justnewbie

Maybe you can find what you want here:
http://forum.lazarus.freepascal.org/index.php?topic=36590.0

The easiest way is to use a game engine that support reading the shift keys. For example Allegro, I used it to create Furious Paladin which the moving is controlled by using left/right ctrl:
http://forum.lazarus.freepascal.org/index.php/topic,35313.msg254588.html#msg254588

Code: Pascal  [Select]
  1.   // Moving or attacking
  2.   isMoveLeft  := al_key_down(KeyState, ALLEGRO_KEY_LCTRL);
  3.   isMoveRight := al_key_down(KeyState, ALLEGRO_KEY_RCTRL);
  4.  

The whole source code can be found here:
https://sourceforge.net/p/allegro-pas/code/HEAD/tree/TRUNK/demos/furiouspaladin/furiouspaladin.pas

justnewbie

  • Full Member
  • ***
  • Posts: 129
Re: Moving shape with keys
« Reply #4 on: April 28, 2018, 07:59:09 pm »
Guys, thank you for the answers!
It is a totally basic tennis/pong game.
It is not so important for me, but it is a bit strange that why is the difference between the left/right keys and shift keys.
I can live with left/right keys, not problem.

@ASerge: somehow this code doesn't work well.
1./ although I press the key continuously, only 1 step occurs
2./ the moving direction is from right to left only

jamie

  • Hero Member
  • *****
  • Posts: 786
Re: Moving shape with keys
« Reply #5 on: April 28, 2018, 10:08:39 pm »
maybe you have more than one key down ?

Try this

 If VK_SHIFT in [KEY] Then......

Edit:

  I made a boo boo  :)
if should be

 If ssShift in Shift Then......

« Last Edit: April 29, 2018, 12:05:47 am by jamie »

ASerge

  • Hero Member
  • *****
  • Posts: 862
Re: Moving shape with keys
« Reply #6 on: April 29, 2018, 09:52:22 am »
@ASerge: somehow this code doesn't work well.
1./ although I press the key continuously, only 1 step occurs
2./ the moving direction is from right to left only
I tested only on Windows. Possible on other platforms:
1. Repeated press do not reach the OnKeyDown handler.
2. Not Left Shift key not equal Right Shift.

justnewbie

  • Full Member
  • ***
  • Posts: 129
Re: Moving shape with keys
« Reply #7 on: April 29, 2018, 10:39:01 am »
@jamie: unfortunately no success

@ASerge: yes, it seems your code is system-specific, it is a Linux system. OnKeyDown worked well using Left/Right keys, but the code you provided made only one step and only in the left direction on both keys

No problem, Left/Right is enough for me.

ASerge

  • Hero Member
  • *****
  • Posts: 862
Re: Moving shape with keys
« Reply #8 on: April 29, 2018, 02:43:16 pm »
No problem, Left/Right is enough for me.
Try this:
Code: Pascal  [Select]
  1. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  2. begin
  3.   if Key = VK_SHIFT then
  4.   begin
  5.     if GetKeyState(VK_LSHIFT) < 0 then
  6.       Shape1.Left := Shape1.Left - 15
  7.     else
  8.       if GetKeyState(VK_RSHIFT) < 0 then
  9.         Shape1.Left := Shape1.Left + 15;
  10.     Key := 0;
  11.   end;
  12. end;

justnewbie

  • Full Member
  • ***
  • Posts: 129
Re: Moving shape with keys
« Reply #9 on: April 29, 2018, 03:16:40 pm »
No problem, Left/Right is enough for me.
Try this:
Code: Pascal  [Select]
  1. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  2. begin
  3.   if Key = VK_SHIFT then
  4.   begin
  5.     if GetKeyState(VK_LSHIFT) < 0 then
  6.       Shape1.Left := Shape1.Left - 15
  7.     else
  8.       if GetKeyState(VK_RSHIFT) < 0 then
  9.         Shape1.Left := Shape1.Left + 15;
  10.     Key := 0;
  11.   end;
  12. end;
Thank you ASerge for your effort, but unfortunately it does the same as previously.

Handoko

  • Hero Member
  • *****
  • Posts: 2443
  • My goal: build my own game engine using Lazarus
Re: Moving shape with keys
« Reply #10 on: April 29, 2018, 03:25:30 pm »
I think we got a bug.

Thank your ASerge, your code works but with some issue. I tested on Lazarus 1.8.0 64-bit Gtk2 Linux. Maybe it is a bug that only happens on Gtk2 or Linux, I haven't tested it on Windows.

This is my test code:
Code: Pascal  [Select]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, LCLType, LclIntf, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Shape1: TShape;
  16.     Timer1: TTimer;
  17.     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  18.     procedure Timer1Timer(Sender: TObject);
  19.   private
  20.  
  21.   public
  22.  
  23.   end;
  24.  
  25. type
  26.   TDirection = (dirLeft, dirRight, dirNone);
  27.  
  28. var
  29.   Form1: TForm1;
  30.   Direction: TDirection = dirNone;
  31.  
  32. implementation
  33.  
  34. {$R *.lfm}
  35.  
  36. { TForm1 }
  37.  
  38. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
  39.   );
  40. begin
  41.   if Key = VK_SHIFT then
  42.   begin
  43.     if GetKeyState(VK_LSHIFT) < 0 then Direction := dirLeft;
  44.     if GetKeyState(VK_RSHIFT) < 0 then Direction := dirRight;
  45.     Key := 0;
  46.   end;
  47. end;
  48.  
  49. procedure TForm1.Timer1Timer(Sender: TObject);
  50. begin
  51.   case Direction of
  52.     dirLeft:  Shape1.Left := Shape1.Left - 10;
  53.     dirRight: Shape1.Left := Shape1.Left + 10;
  54.   end;
  55.   if (Shape1.Left < -70)   then Shape1.Left := Width;
  56.   if (Shape1.Left > Width) then Shape1.Left := -70;
  57.   Direction := dirNone;
  58. end;
  59.  
  60. end.

If I change line #43, #44 to the lines below, then it only moves left:
Code: Pascal  [Select]
  1.     if GetKeyState(VK_LSHIFT) < 0 then
  2.       Direction := dirLeft
  3.     else
  4.       if GetKeyState(VK_RSHIFT) < 0 then
  5.         Direction := dirRight;

My guess, it is a bug in GetKeyState. Because on my test right shift key always generates both VK_RSHIFT and VK_LSHIFT.
« Last Edit: April 29, 2018, 03:28:47 pm by Handoko »

jamie

  • Hero Member
  • *****
  • Posts: 786
Re: Moving shape with keys
« Reply #11 on: April 29, 2018, 03:33:35 pm »
You may need to use GetKeyBoardState which retrieves all 256 key states placed in a buffer..

Look here for the example
TKeyboardState is an array of bytes but it makes it handy to use  :)
http://www.delphipages.com/forum/showthread.php?t=18108

I suppose one could do this while inside the OnKeyDown event but not sure if all will be captured.

justnewbie

  • Full Member
  • ***
  • Posts: 129
Re: Moving shape with keys
« Reply #12 on: April 29, 2018, 04:20:02 pm »
An other "issue".
Currently I'm using this code (with Left/Right keys):
   
Code: Pascal  [Select]
  1. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  2.     begin
  3.        case Key of
  4.         VK_LEFT:
  5.           Shape1.Left := Shape1.Left - 15;
  6.         VK_RIGHT:
  7.           Shape1.Left := Shape1.Left + 15;
  8.       end;
  9.     end;

My problem is the latency. When I'm pressing the Left/Right key, the shape first moves only one step (15), then waits a bit, and after moves continuously.
Is it possible somehow to get instant and continuous reaction without the little pause?

Handoko

  • Hero Member
  • *****
  • Posts: 2443
  • My goal: build my own game engine using Lazarus
Re: Moving shape with keys
« Reply #13 on: April 29, 2018, 04:28:50 pm »
You may need to use GetKeyBoardState which retrieves all 256 key states placed in a buffer..

Thank you jamie. If I'm not wrong it is only available on Windows, unfortunately I'm a Linux user.

My problem is the latency. When I'm pressing the Left/Right key, the shape first moves only one step (15), then waits a bit, and after moves continuously.
Is it possible somehow to get instant and continuous reaction without the little pause?

Wait, give me some minutes. I'm trying to improve the code.

Handoko

  • Hero Member
  • *****
  • Posts: 2443
  • My goal: build my own game engine using Lazarus
Re: Moving shape with keys
« Reply #14 on: April 29, 2018, 04:35:04 pm »
Is it possible somehow to get instant and continuous reaction without the little pause?
That happens because you use OnKeyDown event, don't use that.

The code below should works as what you want now:

Code: Pascal  [Select]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, LCLType, LclIntf, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Shape1: TShape;
  16.     Timer1: TTimer;
  17.     procedure Timer1Timer(Sender: TObject);
  18.   private
  19.  
  20.   public
  21.  
  22.   end;
  23.  
  24. type
  25.   TDirection = (dirLeft, dirRight, dirNone);
  26.  
  27. var
  28.   Form1: TForm1;
  29.   Direction: TDirection = dirNone;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TForm1 }
  36.  
  37. procedure TForm1.Timer1Timer(Sender: TObject);
  38. begin
  39.   if GetKeyState(VK_LSHIFT) < 0 then Direction := dirLeft;
  40.   if GetKeyState(VK_RSHIFT) < 0 then Direction := dirRight;
  41.   case Direction of
  42.     dirLeft:  Shape1.Left := Shape1.Left - 3;
  43.     dirRight: Shape1.Left := Shape1.Left + 3;
  44.   end;
  45.   if (Shape1.Left < -70)   then Shape1.Left := Width;
  46.   if (Shape1.Left > Width) then Shape1.Left := -70;
  47.   Direction := dirNone;
  48. end;
  49.  
  50. end.

Edit:
Sorry I didn't read your post carefully. I now saw you use Left/Right keys, you should change the keys in my example to VK_RIGHT and VK_LEFT.
« Last Edit: April 29, 2018, 04:43:19 pm by Handoko »

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus