* * *

Author Topic: how to delete the canvas rectangle  (Read 6899 times)

Handoko

  • Hero Member
  • *****
  • Posts: 1644
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #120 on: October 07, 2017, 04:37:54 am »
Can you do the thing below, or do you need more explanation?

... simple call the Time1Timer after the keypressing event.

shs

  • Full Member
  • ***
  • Posts: 206
Re: how to delete the canvas rectangle
« Reply #121 on: October 07, 2017, 05:47:15 am »
umm nope more explanations please?
can you give me an example of the code please?

Handoko

  • Hero Member
  • *****
  • Posts: 1644
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #122 on: October 07, 2017, 06:13:41 am »
Replace your KeyDown with this:


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

  case key of
    vk_left:  if not(direction = 2) then direction := 1;
    vk_right: if not(direction = 1) then direction := 2;
    vk_up:    if not(direction = 4) then direction := 3;
    vk_down:  if not(direction = 3) then direction := 4;
  end;

  if score = 0 then
    begin
      if key=vk_left  then direction := 1;
      if key=vk_right then direction := 2;
      if key=vk_up    then direction := 3;
      if key=vk_down  then direction := 4;
    end;


  Timer1Timer(Sender);

end;



As I told you, it will introduce new problem:
Your snake can speed up by pressing forward. :D
« Last Edit: October 07, 2017, 06:22:56 am by Handoko »

shs

  • Full Member
  • ***
  • Posts: 206
Re: how to delete the canvas rectangle
« Reply #123 on: October 07, 2017, 07:40:22 am »
what should i do to solve that problem?

rvk

  • Hero Member
  • *****
  • Posts: 2814
Re: how to delete the canvas rectangle
« Reply #124 on: October 07, 2017, 08:30:10 am »
As I told you, it will introduce new problem:
Your snake can speed up by pressing forward. :D
Maybe I'm a bit late to the game...  ;) But isn't calling Timer1Timer in FormKeyDown the wrong thing to solve this problem? (it will indeed speed up the snake)

Isn't it better to just NOT accept any direction change (key-input) until the snake has moved?

For example introduce a boolean DontChangeDirection and do this:

Code: Pascal  [Select]
  1. var
  2.   DontChangeDirection: Boolean = true;
  3.  
  4. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  5. begin
  6.   if DontChangeDirection then exit;
  7.   DontChangeDirection := true;
Code: Pascal  [Select]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. begin
  3.   DontChangeDirection := false;

That way the direction can only change when the snake has really moved position.

shs

  • Full Member
  • ***
  • Posts: 206
Re: how to delete the canvas rectangle
« Reply #125 on: October 07, 2017, 09:14:01 am »
Code: Pascal  [Select]
  1.   if DontChangeDirection then exit;
  2.   DontChangeDirection := true;

what does that exit do?

Handoko

  • Hero Member
  • *****
  • Posts: 1644
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #126 on: October 07, 2017, 09:41:44 am »
https://www.freepascal.org/docs-html/rtl/system/exit.html
Exit is used to skip or ignore all the commands below and go directly to the end of the procedure or function.

@rvk
Nice trick. I use similar trick often on my codes to prevent unwanted events being triggered.

It depends on how the TS wants the game to behave. The ability to fast forward is good too if he wants the feature. Actually there are several solutions, at least I can think 2 solutions for this case:

1. Add a variable to store and use only the first key when several keys are pressed quickly on the given time (so the Timer1Timer won't use the last key but use only the one stored in the variable).

2. Create a buffer but limit its size (maybe 2 or 3 only). The movement happens only inside Timer1Timer and the direction is based on the buffer (not directly on the keypressing). If the buffer is empty then use the previous direction.
« Last Edit: October 07, 2017, 09:51:27 am by Handoko »

shs

  • Full Member
  • ***
  • Posts: 206
Re: how to delete the canvas rectangle
« Reply #127 on: October 07, 2017, 10:06:55 am »
As I told you, it will introduce new problem:
Your snake can speed up by pressing forward. :D
Maybe I'm a bit late to the game...  ;) But isn't calling Timer1Timer in FormKeyDown the wrong thing to solve this problem? (it will indeed speed up the snake)

Isn't it better to just NOT accept any direction change (key-input) until the snake has moved?

For example introduce a boolean DontChangeDirection and do this:

Code: Pascal  [Select]
  1. var
  2.   DontChangeDirection: Boolean = true;
  3.  
  4. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  5. begin
  6.   if DontChangeDirection then exit;
  7.   DontChangeDirection := true;
Code: Pascal  [Select]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. begin
  3.   DontChangeDirection := false;

That way the direction can only change when the snake has really moved position.


the direction still changes when the snake has not moved position

rvk

  • Hero Member
  • *****
  • Posts: 2814
Re: how to delete the canvas rectangle
« Reply #128 on: October 07, 2017, 10:41:56 am »
the direction still changes when the snake has not moved position
That is strange.
According to my changes the direction can only change when the timer has fired. And when the timer fires the snake moves. So i.e. the direction can only change when the snake moved.

I'm working with outdated code from you so I can't be sure what the problem is (you could post your complete code). But how are you determining that the direction has changed without the snake moving?

B.T.W. Do you want the first key AFTER the snake has moved to determine the direction-change (like my suggestion does) or do you want the first key before the snake even moved to be the direction-changer (regardless what is used afterwards)?

Handoko

  • Hero Member
  • *****
  • Posts: 1644
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #129 on: October 07, 2017, 11:01:19 am »
I think there is some misunderstanding. You may need to go back to the see originial problem:
http://forum.lazarus.freepascal.org/index.php/topic,38136.msg261549.html#msg261549

rvk

  • Hero Member
  • *****
  • Posts: 2814
Re: how to delete the canvas rectangle
« Reply #130 on: October 07, 2017, 11:17:11 am »
for example, the snake is in direction 1 (left) but if i press key down and then key right very quickly, the direction becomes 2 (right) instead of becoming 4 (down) and then 2(right)
Yes I understand. So if the snake is going left it may not go directly right again. It needs to go up or down first (so it doesn't traverse back over itself).

That's why my suggestion to only accept a key when the snake has really moved one position should work. You already don't accept the right direction if going left. So when you press up (or down) you shouldn't accept ANY keys anymore until the snake has really moved one up or down. So only the first key determines the eventual move.

The other suggestion from Handoko would also work and that is to use the first key just before the actual move. But in that case you shouldn't change direction directly in FormKeyDown but you should save the first pressed key. And then in the timer you can do the direction change according to that saved key. In that case you would get something like this:

Code: Pascal  [Select]
  1. var
  2.   FirstPressedKey: Word = 0;
  3.  
  4. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  5. begin
  6.   if FirstKeyPressed = 0 then
  7.     FirstPressedKey := Key;
  8. end;
And you would move the "case FirstPressedKey of" with all the direction-changes to the top of Timer1Timer(). Below the case statement the FirstKeyPressed should be set to 0 again so the FormKeyDown can accept keys again.

The other suggestion from Handoko was buffering all the keys (or last few ones) which is also a way to go (but I think a bit annoying in the game, game-wise).
« Last Edit: October 07, 2017, 11:24:26 am by rvk »

Handoko

  • Hero Member
  • *****
  • Posts: 1644
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #131 on: October 07, 2017, 11:26:45 am »
Was I misunderstand that TS said?

Quote
for example, the snake is in direction 1 (left) but if i press key down and then key right very quickly, the direction becomes 2 (right) instead of becoming 4 (down) and then 2(right)

The behavior works correctly as what TS (and me) experiencing:
1. In less than 1/10 second, press down and then right
2. The snake move right only (ignoring the down)
3. What TS wants, go down and then right.

I said it works correctly, because:
- After the keypressing event, no movement call
- The movement is processed in the Timer1Timer
- That's why I suggest him to call Timer1Timer at the end of keypressing
- The movement only follows the variable "direction"
- The direction (currently) only reads the last key in the interval time given
- That's why the "down" key is ignored.

One possible solution is to use "buffer" to store the keys pressed by user. We should limit the size, I suggested 2 or 3. Using the first-key-only is okay but I don't think that is what TS wants.
« Last Edit: October 07, 2017, 11:34:02 am by Handoko »

rvk

  • Hero Member
  • *****
  • Posts: 2814
Re: how to delete the canvas rectangle
« Reply #132 on: October 07, 2017, 11:38:53 am »
Was I misunderstand that TS said?
No, I think we all understand it correctly.
As I said:
Quote
So if the snake is going left it may not go directly right again. It needs to go up or down first (so it doesn't traverse back over itself).
But as the last code I saw from TS was, the FormKeyDown is processed more times then the timer. So if you change direction in FormKeyDown, if direction is left, you can do up and right real quick and direction is right before the timer even fires. So the snake goes right over itself.

The suggested solutions so far:
  • Call Timer1Timer in FormKeyDown (with the "downside" that the snake speeds up)
  • Only accept the first key pressed. This can be done with my suggested DontChangeDirection boolean or with the by you suggested FirstKeyPressed variable. (also see my code in prev post)
  • Only use the LastKeyPressed. This can be done with the same code as I gave with the FirstKeyPressed but without the if-statement. Just fill LastKeyPressed in FormKeyDown and process that key in Timer1Timer.
  • Create a small buffer which is filled in FormKeyDown and process all the directions in Timer1Timer one by one. That will delay the snakes movements somewhat and it will not react directly on the keys anymore (which would make the game harder, but that might be a good thing, I don't know)

One possible solution is to use "buffer" to store the keys pressed by user. We should limit the size, I suggested 2 or 3. Using the first-key-only is okay but I don't think that is what TS wants.
No, but the LastKeyPressed method might be more intuitive than the FirstKeyPressed method.

Code: Pascal  [Select]
  1. var
  2.   LastPressedKey: Word = 0;
  3.  
  4. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  5. begin
  6.   LastPressedKey := Key;
  7. end;
  8.  
  9. procedure TForm1.Timer1Timer(Sender: TObject);
  10. begin
  11.  case LastKeyPressed of
  12. // ... etc
« Last Edit: October 07, 2017, 11:45:58 am by rvk »

shs

  • Full Member
  • ***
  • Posts: 206
Re: how to delete the canvas rectangle
« Reply #133 on: October 07, 2017, 11:43:36 am »
the direction still changes when the snake has not moved position
That is strange.
According to my changes the direction can only change when the timer has fired. And when the timer fires the snake moves. So i.e. the direction can only change when the snake moved.

I'm working with outdated code from you so I can't be sure what the problem is (you could post your complete code). But how are you determining that the direction has changed without the snake moving?

B.T.W. Do you want the first key AFTER the snake has moved to determine the direction-change (like my suggestion does) or do you want the first key before the snake even moved to be the direction-changer (regardless what is used afterwards)?


i know that the direction is changed without the snake moving because

Quote
so let's say the direction is 1 so it's going left. And if i press right it won't work because it only works when the direction is not 1. But if change directions really quickly bu pressing up key and right key, it just goes left instead of going up and left.

please find the attachment for the code


rvk

  • Hero Member
  • *****
  • Posts: 2814
Re: how to delete the canvas rectangle
« Reply #134 on: October 07, 2017, 11:47:34 am »
please find the attachment for the code
Also please read the last few post. It has multiple solutions for your problem.

 

Recent

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