Recent

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

Handoko

  • Hero Member
  • *****
  • Posts: 5389
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #30 on: September 27, 2017, 12:47:37 pm »
Lets start with some theory first. See the attached picture, it assumes you use an array to store the snake body information. The smallest (index = 1) is the snake's head and the largest is its tail.

Handoko

  • Hero Member
  • *****
  • Posts: 5389
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #31 on: September 27, 2017, 12:49:40 pm »
Now, you now should already understood how to use array to store the snake body information and how to move it. But you still have to solve this issue:

How to make the snake grow longer?

It is not hard. But you will get this problem:

How to declare an array for the snake that can grow longer?

You can set SnakeBody array to a very big size that you sure it won't reach it. You can use 2000 or bigger:
Code: Pascal  [Select][+][-]
  1. var
  2.   SnakeBody[1..2000] of TRect; // set the size to a very big value

Alternatively, you can use Dynamic Array (the better solution):
Code: Pascal  [Select][+][-]
  1. var
  2.   SnakeBody: array of TRect; // using dynamic array
Read more about Dynamic Array:
http://wiki.freepascal.org/Dynamic_array

Setting an array to a very big size is not a good solution, it wastes computer memory and you cannot be sure to know what is the best value for it. Using Dynamic array is okay, but using TList is easier.
« Last Edit: September 27, 2017, 12:55:58 pm by Handoko »

Handoko

  • Hero Member
  • *****
  • Posts: 5389
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #32 on: September 27, 2017, 12:50:50 pm »
Remember on the previous post, I explained that you can use For - Do loop for changing snake information when the snake is moving. You need to write similar code again for making the snake grow longer (new item insertion). But if you use TList, inserting a new item is very easy. You can code less and it also means the code is easier to maintain.

You can see picture below for the comparison. In general using array is faster than TList. But if the code is poorly writen by inexperienced programmers, using array can be as slow or slower than using TList.

As a programmer, you can choose for memory efficienty, performance or easy maintaining code. Same problem can be solved using different methods, it depends on what is the programmer's priority. In this case (snake game), TList will be easier. Using array is faster but it won't be noticable on this simple program.

Handoko

  • Hero Member
  • *****
  • Posts: 5389
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #33 on: September 27, 2017, 12:51:38 pm »
(I will come back later after I preapred some example codes)

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: how to delete the canvas rectangle
« Reply #34 on: September 27, 2017, 12:53:28 pm »
Hello! You're back finally :) :)

I'm so glad that you're back.

Thanks for the explanation and i have some question other than those explanatios.

1. How can I set the tails' movement? how can I make the tails to follow the head?
2. How can I use Tlist?

Handoko

  • Hero Member
  • *****
  • Posts: 5389
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #35 on: September 27, 2017, 12:56:02 pm »
If you use array (instead of TList), the code of in the snake1.png picture.

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: how to delete the canvas rectangle
« Reply #36 on: September 27, 2017, 01:08:45 pm »
so if i just do that snake can get longer?

Handoko

  • Hero Member
  • *****
  • Posts: 5389
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #37 on: September 27, 2017, 01:12:50 pm »
I'm preparing the code. Explanation is hard, programmers talk better using code. :D

Give me some time.

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: how to delete the canvas rectangle
« Reply #38 on: September 27, 2017, 01:17:10 pm »
Okay thank you very much :)

Handoko

  • Hero Member
  • *****
  • Posts: 5389
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #39 on: September 27, 2017, 02:19:18 pm »
1. Declare The SnakeBody Variable

It is easy, just put this code at at declaration area:
Code: Pascal  [Select][+][-]
  1. var
  2.   SnakeBody: TList;

2. Initial The SnakeBody When The Program Start

You need to put this on FormCreate:
Code: Pascal  [Select][+][-]
  1. var
  2.   SnakeSegment: PRect;
  3. begin  
  4.   SnakeBody := TList.Create;
  5.   // ...
  6.   SnakeSegment^ := snakepos; // Put this line after ...random(10)
  7.   SnakeBody.Add(SnakeSegment); // Put this line after SnakeSegment^ := ...
  8. // ...

3. Free SnakeBody When Not Needed

Put this on FormClose:
Code: Pascal  [Select][+][-]
  1. SnakeBody.Free;

4. Add A New Variable "SnakeIsGrowing"

This variable is needed to know if the snake is moving or growing. If it is moving, then the latest segment of the body (tail) will be deleted automatically.

Add this as a global variable:
Code: Pascal  [Select][+][-]
  1. var
  2.   SnakeIsGrowing: Boolean = False;

5. Add A New Procedure "MoveSnake"

Create a new procedure, I call it MoveSnake. It should be on private section of TForm1. Here is the code:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.MoveSnake(NewHead: TRect);
  2. var
  3.   SnakeSegment: PRect;
  4. begin
  5.   New(SnakeSegment);
  6.   SnakeSegment^ := NewHead;
  7.   SnakeBody.Insert(0, SnakeSegment);
  8.   if not(SnakeIsGrowing) then begin
  9.     SnakeSegment := SnakeBody[SnakeBody.Count-1];
  10.     PutItem(SnakeSegment^.Left, SnakeSegment^.Top, Emtpy);
  11.     Freemem(SnakeSegment);
  12.     SnakeBody.Delete(SnakeBody.Count-1);
  13.   end;
  14.   SnakeIsGrowing := False;
  15. end;

You can know from the code above, if the snake is not growing then the code will remove the tail.

6. Make It Move

Because you use Timer1 as the game main loop, so you should put this code on Timer1Timer:
Code: Pascal  [Select][+][-]
  1. MoveSnake(snakepos);

You should put the code above at the end of the procedure.

7. Fix An Error: PutItem

You should remove PutItem(snakepos.left, snakepos.top, snake) on the FormKeyDown because you already have it on Timer1Timer.

8. Fix An Error: ClearWorld

You should not call ClearWorld on Timer1Timer. ClearWorld is needed only when starting a new round of the game. So remove ClearWorld on Timer1Timer.

9. Write Code for Testing

Everything should be okay now. You can write some code to test if it working correctly.

Add the code on your key down testing section:
Code: Pascal  [Select][+][-]
  1.   if key=VK_ADD then
  2.   begin
  3.     SnakeIsGrowing := True;
  4.   end;

Now, you can try pressing '+' when moving the snake, the snake should grow longer.

I wrote this explanation on the same time coding it on your code. It works here on my test.
« Last Edit: September 27, 2017, 03:24:50 pm by Handoko »

Handoko

  • Hero Member
  • *****
  • Posts: 5389
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #40 on: September 27, 2017, 02:33:36 pm »
Novice may find it difficult to use TList because:

- You use pointer to access its items (in your case it is PRect)
- You need to understand how to use pointer
- You have to manually allocate memory for the items
- You have to manually free the items before calling TList.Delete
- It introduces some new functions: TList.Insert, TList.Delete

Some reading materials:
https://www.freepascal.org/docs-html/rtl/classes/tlist.html
https://www.freepascal.org/docs-html/rtl/system/new.html
https://freepascal.org/docs-html/ref/refse15.html
http://wiki.freepascal.org/Pointers
« Last Edit: September 27, 2017, 02:36:11 pm by Handoko »

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: how to delete the canvas rectangle
« Reply #41 on: September 27, 2017, 03:06:58 pm »
Hi i cannot compile it
error messages came up
Code: Pascal  [Select][+][-]
  1. SnakeSegment: PRect;  
identifier not found "prect"
Code: Pascal  [Select][+][-]
  1. SnakeSegment^:= snakepos;
illegal qualifier
identifiers not found snakepos
Code: Pascal  [Select][+][-]
  1.  New(SnakeSegment);      
pointer type expected but got "<erroneous type>"
Code: Pascal  [Select][+][-]
  1. SnakeBody.Insert(0, SnakeSegment);  
unit1.pas(86,35) Error: Incompatible type for arg no. 2: Got "<erroneous type>", expected "Pointer"

Handoko

  • Hero Member
  • *****
  • Posts: 5389
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #42 on: September 27, 2017, 03:14:14 pm »
Please send your code to the forum, I need try and inspect it.

Handoko

  • Hero Member
  • *****
  • Posts: 5389
  • My goal: build my own game engine using Lazarus
Re: how to delete the canvas rectangle
« Reply #43 on: September 27, 2017, 03:29:37 pm »
I guess you need to add LCLType in your uses clause section.

helmi

  • New Member
  • *
  • Posts: 21
Re: how to delete the canvas rectangle
« Reply #44 on: September 27, 2017, 03:35:47 pm »
Great explanation by Handoko. This kind of game, you must know very well how to using array or link list to implement in a game. Because it will help you to do the AI part (Another snake). For drawing part, you can use back buffer technique.

ps: sorry, long time not do game programming.

 

TinyPortal © 2005-2018