Recent

Author Topic: Sprite Trails in Windows 64 but not GTK2  (Read 2929 times)

Windsurfer

  • Sr. Member
  • ****
  • Posts: 368
    • Windsurfer
Sprite Trails in Windows 64 but not GTK2
« on: January 21, 2019, 12:30:42 pm »
I run a local programming mixed ability group. I use Linux Mint 19.1 and they use Windows 7, 8, 10.
We are looking at the basics of sprites, using the LCL. (I know we should use BGRABitmap, but some of the group have never coded before, and they already have many new concepts to deal with.)

In Linux Mint 19.1 Cinnamon with GTK2 everything works correctly.
In Windows the sprites leave trails and heaptrace shows a memory leak.

I have tested with fpc 3.04 and both Laz 1.8 fixes and Laz 2.0 fixes in Linux and 1.8 fixes in Windows

The problems seem to occur at the imgBuffer.Assign(imgBackGround) statement in the following code. It seems that the assignment of the standard background to the buffer does not work properly when the procedure is triggered by a timer.
 
Code: Pascal  [Select][+][-]
  1. procedure TForm1.MoveSprite;
  2. beginIn Linux Mint 19.1 everything works correctly.
  3.   // Movement of sprite by keyboard: UP/DOWN/LEFT/RIGHT arrows advance smooth version
  4.   if (GetKeyState(VK_LEFT) < 0) then
  5.     if (iSpLeft >= 10) then
  6.       iSpLeft := iSpLeft - 10;
  7.  
  8.   if (GetKeyState(VK_RIGHT) < 0) then
  9.     if (iSpLeft <= Image1.Clientwidth - iSpwidth - 10) then
  10.       iSpLeft := iSpLeft + 10;
  11.  
  12.   if (GetKeyState(VK_UP) < 0) then
  13.     if (iSpTop >= 10) then
  14.       iSpTop := iSpTop - 10;
  15.  
  16.   if (GetKeyState(VK_DOWN) < 0) then
  17.     if (iSpTop <= Image1.ClientHeight - iSpHeight - 10) then
  18.       iSpTop := iSpTop + 10;
  19.  
  20.   imgBuffer.Assign(imgBackground);   // Write Background to Buffer
  21.   Imagelist1.Draw(imgBuffer.Canvas, iSpLeft, iSpTop, 0, True);  // Draw Sprite to Buffer.
  22.   Image1.Picture.Assign(imgBuffer); // Paint new image in Buffer to screen
  23. end;        

If anyone has the time could they please check the attached program? I suspect an error in the LCL, but it needs an independent check before I file a bug report.

Handoko

  • Hero Member
  • *****
  • Posts: 5129
  • My goal: build my own game engine using Lazarus
Re: Sprite Trails in Windows 64 but not GTK2
« Reply #1 on: January 21, 2019, 01:09:34 pm »
I tested your Sprite3, I got SIGSEGV error when closing the program. It happened because you need to put Timer1.Enabled := False on Form.OnClose event.

Other than that, everything seems to run correctly. Tested on Ubuntu 18.10 Lazarus 1.8.4 GTK 2.

I saw no image inside the ImageList, so I drew the stickman for testing.

Windsurfer

  • Sr. Member
  • ****
  • Posts: 368
    • Windsurfer
Re: Sprite Trails in Windows 64 but not GTK2
« Reply #2 on: January 21, 2019, 02:54:51 pm »
Thanks Handoko, I was hoping you might look at it. I have read your recent posts on sprites, and intend to pick up on the speed control that you and wp have added to the 2.0 release examples.

I would never have thought of disabling the timer, although it now seems obvious.

I'm not sure what happened to item 0 in the imagelist, so thanks for adding one.
I'll now ask my cohorts / students to check it on Windows.

Handoko

  • Hero Member
  • *****
  • Posts: 5129
  • My goal: build my own game engine using Lazarus
Re: Sprite Trails in Windows 64 but not GTK2
« Reply #3 on: January 21, 2019, 03:35:11 pm »
I cross compiled to win32 and tested it using WINE. Yes, I can see the issue you mentioned.

I'm going to go away from my computer, I will be back to check the issue later.

Windsurfer

  • Sr. Member
  • ****
  • Posts: 368
    • Windsurfer
Re: Sprite Trails in Windows 64 but not GTK2
« Reply #4 on: January 21, 2019, 03:38:27 pm »
Thanks. I now have no errors or memory leak in Windows.
I will check for units to include in the uses clause.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11382
  • FPC developer.
Re: Sprite Trails in Windows 64 but not GTK2
« Reply #5 on: January 21, 2019, 03:38:59 pm »
Afaik this is normal and happens with Delphi too, since you don't redraw the background.

Maybe GTK does this automatically, but that is not an universal principle.

Windsurfer

  • Sr. Member
  • ****
  • Posts: 368
    • Windsurfer
Re: Sprite Trails in Windows 64 but not GTK2
« Reply #6 on: January 21, 2019, 06:28:29 pm »
marcov,
That is what the code is intended to do. imgBackGround never changes. Before every move imgBackground is first assigned to the imgBuffer and then the sprite is added to imgBuffer. The altered imgBuffer is then assigned to Image1.

Code: Pascal  [Select][+][-]
  1.  imgBuffer.Assign(imgBackground);   // Write Background to Buffer
  2.   Imagelist1.Draw(imgBuffer.Canvas, iSpLeft, iSpTop, 0, True);  // Draw Sprite to Buffer.
  3.   Image1.Picture.Assign(imgBuffer); // Paint new image in Buffer to screen

It looks as though in Windows the line of code to assign the background to the buffer only works the first time. From then on they seem to be the same image, rather than the buffer being a copy.

EDIT
I'll try copying the background to another image to see if that is so.
« Last Edit: January 21, 2019, 06:31:08 pm by Windsurfer »

Handoko

  • Hero Member
  • *****
  • Posts: 5129
  • My goal: build my own game engine using Lazarus
Re: Sprite Trails in Windows 64 but not GTK2
« Reply #7 on: January 21, 2019, 06:49:53 pm »
Your code works if you change this
imgBuffer.Assign(imgBackground);

to this:
  imgBuffer.Canvas.CopyRect(Rect(0,0,imgBuffer.Width, imgBuffer.Height),
    imgBackGround.Canvas, Rect(0,0,imgBackGround.Width, imgBackGround.Height));


Tested on WINE win32.

Maybe it is a bug, but I suggest we should test it on Delphi first. Because I checked the documentation of TBitmap.Assign on both FPC and Delphi, they're different and it sounds suspicious to me:

https://lazarus-ccr.sourceforge.io/docs/lcl/graphics/tcustombitmap.assign.html

http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Graphics_TBitmap_Assign.html

Delphi version says, it copies the bitmap image contained in Source to the bitmap object. The FPC version is a bit different: If the BitMap data are already in use, the data are shared; if not, a new BitMap is produced.

So in FPC, it may not actually copy the data. Could it be the cause of the issue?

You know, if you modify (in this case do painting) on the shared data (imgBuffer), the original image (imgBackground) also get painted. That's why the trails won't be deleted.

But why it doesn't happen on GTK?
So if you follow the documentation of FPC version, the bug is on the GTK. :-X
« Last Edit: January 21, 2019, 07:26:52 pm by Handoko »

Windsurfer

  • Sr. Member
  • ****
  • Posts: 368
    • Windsurfer
Re: Sprite Trails in Windows 64 but not GTK2
« Reply #8 on: January 21, 2019, 08:02:30 pm »
I did try something like that in Linux, but it did not work, probably because I had an error.

It just occurred to me that changing
Code: Pascal  [Select][+][-]
  1. Image1.Picture.Assign(imgBuffer); // Paint new image in Buffer to screen
to
Code: Pascal  [Select][+][-]
  1. Image1.Picture.Assign(imgBackground); // Paint new image in Buffer to screen
should show if they are both the same image rather than separate copies.

If you could test it in Windows, I would be grateful. I have terrible problems with permissions in Windows 10. If Wine works, I'll install it for testing.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11382
  • FPC developer.
Re: Sprite Trails in Windows 64 but not GTK2
« Reply #9 on: January 22, 2019, 11:10:03 am »
Afaik it is not a bug, but winapi. TPaintbox was created partially to make this more uniform over platforms.

Windsurfer

  • Sr. Member
  • ****
  • Posts: 368
    • Windsurfer
Re: Sprite Trails in Windows 64 but not GTK2
« Reply #10 on: January 22, 2019, 08:52:23 pm »
Thanks marcov. Knowing it is an API issue prevents further searching. Our group met this morning.  It allowed me to introduce compiler directives to them, and I showed them the solution below.

Code: Pascal  [Select][+][-]
  1. {$ifdef mswindows}
  2.   imgBuffer.Canvas.CopyRect(Rect(0,0,imgBuffer.Width, imgBuffer.Height),
  3.     imgBackGround.Canvas, Rect(0,0,imgBackGround.Width, imgBackGround.Height));
  4. {$else}
  5. imgBuffer.Assign(imgBackground);
  6. {$endif}

It may be that one is faster than the other, but we did not investigate that.
Handoku, would this be worth including in your sprite example code. It might help someone else to avoid the wrong path.

 

TinyPortal © 2005-2018