### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Moving shape with keys  (Read 12015 times)

#### justnewbie

• Sr. Member
• Posts: 292
##### 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: 1791
##### 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: 2259
##### 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: 5201
• 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

• Sr. Member
• Posts: 292
##### 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: 6219
##### 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 »
The only true wisdom is knowing you know nothing

#### ASerge

• Hero Member
• Posts: 2259
##### 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

• Sr. Member
• Posts: 292
##### 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: 2259
##### 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

• Sr. Member
• Posts: 292
##### 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: 5201
• 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: 6219
##### 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.
The only true wisdom is knowing you know nothing

#### justnewbie

• Sr. Member
• Posts: 292
##### 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: 5201
• 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: 5201
• 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 »