Recent

Author Topic: Sprite demo example  (Read 10569 times)

Zath

  • Sr. Member
  • ****
  • Posts: 391
Sprite demo example
« on: May 07, 2018, 10:13:51 am »
Sprite demo example

Is there any info regarding the examples available ?
I'm interested in the sprite demo but can't find an info on the code.
I've tried to change things and learn that way but it's not very promising.

Thanks

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 1209
    • Burdjia
Re: Sprite demo example
« Reply #1 on: May 07, 2018, 10:33:11 am »
What sprite demo? This one? ;D
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

wp

  • Hero Member
  • *****
  • Posts: 12859
Re: Sprite demo example
« Reply #2 on: May 07, 2018, 10:35:57 am »
I think the TS means the demo which comes with Lazarus in the examples folder. The demo is self-contained, short and rather easy at first glance. What is the problem with it?

Zath

  • Sr. Member
  • ****
  • Posts: 391
Re: Sprite demo example
« Reply #3 on: May 07, 2018, 10:46:04 am »
No, Ñuño, not that, but that is interesting none the less.

Wp is correct.

There's nothing wrong with it. I want to use is as a base to learn from but can't find info on methods etc.
Even something as basic as setting the background image size etc.
Ideally I'd want user movement to control one sprite and the program to control many more.

I have a scrolling asymmetric game but want to create small shoo]"]>Blockedp type version or attempt to.

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 1209
    • Burdjia
Re: Sprite demo example
« Reply #4 on: May 07, 2018, 01:35:24 pm »
If you want to do serious gaming you shouldn't use LCL but a game framework o a game engine instead.  You'll get better performance and code will be easier to write and maintain.  See the Game Portal link at my signature.
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

wp

  • Hero Member
  • *****
  • Posts: 12859
Re: Sprite demo example
« Reply #5 on: May 07, 2018, 02:06:40 pm »
I extended the demo by options to control the sprite position with the keyboard (arrow keys) and with the mouse (sprite follows the mouse with some delay).

Zath

  • Sr. Member
  • ****
  • Posts: 391
Re: Sprite demo example
« Reply #6 on: May 07, 2018, 09:24:15 pm »
I extended the demo by options to control the sprite position with the keyboard (arrow keys) and with the mouse (sprite follows the mouse with some delay).

Where is this extended version please ?

Nuno, I want to get my head around basics first before jumping in at the deep end.

wp

  • Hero Member
  • *****
  • Posts: 12859
Re: Sprite demo example
« Reply #7 on: May 07, 2018, 09:38:15 pm »
You need the development version, Lazarus trunk, to see the new version.

Or go to https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/examples/sprites/?root=lazarus and download the few files manually.

Zath

  • Sr. Member
  • ****
  • Posts: 391
Re: Sprite demo example
« Reply #8 on: May 08, 2018, 12:22:03 am »
You need the development version, Lazarus trunk, to see the new version.

Or go to https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/examples/sprites/?root=lazarus and download the few files manually.

Excellent.
Had to change the image location to my own project dir, once that was done, it works like a dream.
Thanks for taking the time to amend it.
I will also look at the svn for other titbits too from now on !

Zath

  • Sr. Member
  • ****
  • Posts: 391
Re: Sprite demo example
« Reply #9 on: May 08, 2018, 12:31:19 am »
Are the width and height of the background image found on the create method or perhaps the loadfromfile ?

wp

  • Hero Member
  • *****
  • Posts: 12859
Re: Sprite demo example
« Reply #10 on: May 08, 2018, 01:04:02 am »
I don't know what you mean here... Just guessing: The demo puts the background image into a so-called TPictureControlm similar to a TImage. I think this was done because it inherits from TWinControl (instead of TGraphicControl for TImage), and therefore can catch keyboard events. The PictureControl exposes the loaded image as property Picture from which you can get the image size as PictureControl.Picture.Width and PictureControl.Picture.Height.

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 1209
    • Burdjia
Re: Sprite demo example
« Reply #11 on: May 08, 2018, 10:27:01 am »
Nuno, I want to get my head around basics first before jumping in at the deep end.
As you wish, but I'll stand in my recommendation even if you want to learn the basics (in my experience LCL isn't the best way to learn Pascal basics ::)).  Also you should join the Pascal Game Development community (again in my signature).
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

Handoko

  • Hero Member
  • *****
  • Posts: 5436
  • My goal: build my own game engine using Lazarus
Re: Sprite demo example
« Reply #12 on: May 11, 2018, 06:26:09 am »
Are the width and height of the background image found on the create method or perhaps the loadfromfile ?

I examined the code. I usually will do the graphic things using different way, but there are some interesting techniques in the code that worth to mention:

1. All the images do not paint directly to the screen, instead it paints them on BufferImg (TCustomBitmap).
2. The width and height of BufferImg are adjusted to the background image (splash_logo.png). See line #69 & #70.
3. The movement speed is constant on different hardware because it includes computer time in the calculation. See line #111...#113.
4. It uses PictureControl (TPictureControl) as the target output, and it is the same size as the form. See line #60.
5. The output is resizable because it uses StretchDraw for painting the PictureControl. See line #158.
6. The flow of the painting is : BufferImg > PictureControl.Picture > PictureControl.OnPaint.
7. The painting of sprite to BufferImg is on the line #114.
8. The painting of BufferImg to PictureControl.Picture is on the line #120.
9. The painting of PictureControl.Picture to the screen is in PictureControl.OnPaint event line #154.
10. It uses PictureControl.OnPictureChanged event to detect the need to refresh the image. See line #136 & #145.
11. The animation main loop is TPlayGroundForm.UpdateImage, which is called by Timer1.OnTimer. See line #94.
12. Line #133 serves no use, at least on my tests on my Linux computer.

Here is the code I copy/paste from the example that bundled in Lazarus 1.8.0:

Code: Pascal  [Select][+][-]
  1. unit PlayGround;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, LMessages,
  9.   ExtCtrls;
  10.  
  11. type
  12.  
  13.   { TPictureControl }
  14.  
  15.   TPictureControl = class(TCustomControl)
  16.     procedure PictureChanged(Sender: TObject);
  17.   private
  18.     FPicture: TPicture;
  19.     procedure SetPicture(const AValue: TPicture);
  20.     procedure WMEraseBkgnd(var Msg: TLMessage); message LM_ERASEBKGND;
  21.   public
  22.     constructor Create(TheOwner: TComponent); override;
  23.     destructor Destroy; override;
  24.     procedure Paint; override;
  25.   published
  26.     property Picture: TPicture read FPicture write SetPicture;
  27.   end;
  28.  
  29.   { TPlayGroundForm }
  30.  
  31.   TPlayGroundForm = class(TForm)
  32.     Timer1: TTimer;
  33.     procedure PlayGroundFormClose(Sender: TObject; var CloseAction: TCloseAction);
  34.     procedure PlayGroundFormCreate(Sender: TObject);
  35.     procedure PlayGroundFormDestroy(Sender: TObject);
  36.     procedure Timer1Timer(Sender: TObject);
  37.   private
  38.     procedure UpdateImage;
  39.   public
  40.     PictureControl: TPictureControl;
  41.     SpriteImg: TCustomBitmap;
  42.     BackgroundImg: TCustomBitmap;
  43.     BufferImg: TCustomBitmap;
  44.   end;
  45.  
  46. var
  47.   PlayGroundForm: TPlayGroundForm;
  48.  
  49. implementation
  50.  
  51. {$R playground.lfm}
  52.  
  53. { TPlayGroundForm }
  54.  
  55. procedure TPlayGroundForm.PlayGroundFormCreate(Sender: TObject);
  56. begin
  57.   PictureControl:=TPictureControl.Create(Self);
  58.   with PictureControl do begin
  59.     Parent:=Self;
  60.     Align:=alClient;
  61.   end;
  62.  
  63.   SpriteImg:=TPortableNetworkGraphic.Create;
  64.   BackgroundImg:=TPortableNetworkGraphic.Create;
  65.   BufferImg:=TBitmap.Create;
  66.  
  67.   SpriteImg.LoadFromFile(SetDirSeparators('../images/ide_icon48x48.png'));
  68.   BackgroundImg.LoadFromFile(SetDirSeparators('../images/splash_logo.png'));
  69.   BufferImg.Width:=BackgroundImg.Width;
  70.   BufferImg.Height:=BackgroundImg.Height;
  71.  
  72.   UpdateImage;
  73. end;
  74.  
  75. procedure TPlayGroundForm.PlayGroundFormClose(Sender: TObject;
  76.   var CloseAction: TCloseAction);
  77. begin
  78.   Timer1.Enabled:=false;
  79. end;
  80.  
  81. procedure TPlayGroundForm.PlayGroundFormDestroy(Sender: TObject);
  82. begin
  83.   SpriteImg.Free;
  84.   BackgroundImg.Free;
  85.   BufferImg.Free;
  86. end;
  87.  
  88. procedure TPlayGroundForm.Timer1Timer(Sender: TObject);
  89. begin
  90.   if csDestroying in ComponentState then exit;
  91.   UpdateImage;
  92. end;
  93.  
  94. procedure TPlayGroundForm.UpdateImage;
  95. var
  96.   DestImg: TBitmap;
  97.   t: Double;
  98.   x: Int64;
  99.   y: Integer;
  100.   CenterX: Integer;
  101.   CenterY: Integer;
  102. begin
  103.   // paint first on the buffer
  104.  
  105.   // paint background
  106.   BufferImg.Canvas.CopyRect(Rect(0,0,BufferImg.Width,BufferImg.Height),
  107.        BackgroundImg.Canvas,Rect(0,0,BackgroundImg.Width,BackgroundImg.Height));
  108.   // paint sprite
  109.   CenterX:=BufferImg.Width div 2;
  110.   CenterY:=BufferImg.Height div 2;
  111.   t:=Now*86400;
  112.   x:=CenterX+round(cos(t)*CenterX*2/3)-(SpriteImg.Width div 2);
  113.   y:=CenterY+round(sin(t*0.7)*CenterY*2/3)-(SpriteImg.Height div 2);
  114.   BufferImg.Canvas.Draw(x, y, SpriteImg);
  115.  
  116.   // copy to image
  117.   DestImg:=PictureControl.Picture.Bitmap;
  118.   DestImg.Width:=BufferImg.Width;
  119.   DestImg.Height:=BufferImg.Height;
  120.   DestImg.Canvas.Draw(0,0,BufferImg);
  121. end;
  122.  
  123. { TPictureControl }
  124.  
  125. procedure TPictureControl.SetPicture(const AValue: TPicture);
  126. begin
  127.   if FPicture=AValue then exit;
  128.   FPicture.Assign(AValue);
  129. end;
  130.  
  131. procedure TPictureControl.WMEraseBkgnd(var Msg: TLMessage);
  132. begin
  133.   Msg.Result := 1;
  134. end;
  135.  
  136. procedure TPictureControl.PictureChanged(Sender: TObject);
  137. begin
  138.   Invalidate;
  139. end;
  140.  
  141. constructor TPictureControl.Create(TheOwner: TComponent);
  142. begin
  143.   inherited Create(TheOwner);
  144.   FPicture:=TPicture.Create;
  145.   FPicture.OnChange:=@PictureChanged;
  146. end;
  147.  
  148. destructor TPictureControl.Destroy;
  149. begin
  150.   FreeAndNil(FPicture);
  151.   inherited Destroy;
  152. end;
  153.  
  154. procedure TPictureControl.Paint;
  155. begin
  156.   if Picture.Graphic<>nil then
  157.     // Canvas.Draw(0,0,Picture.Graphic); // copy is fast
  158.     Canvas.StretchDraw(Rect(0,0,Width,Height),Picture.Graphic); // stretch is slow
  159.   inherited Paint;
  160. end;
  161.  
  162. end.
  163.  

For your information, you can change the Timer's interval to 30 to get smoother animation without changing the movement speed, as mentioned on point no. 3 above.
« Last Edit: May 11, 2018, 06:28:19 am by Handoko »

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 1209
    • Burdjia
Re: Sprite demo example
« Reply #13 on: May 11, 2018, 11:17:06 am »
That point no. 3 is called "Delta time" and is used quite often in game programming, specially when physics are involved.

[Personal reminder] I must take a deep look to your code, Handoko. May be I can port it to Allegro.pas as an example.
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

Handoko

  • Hero Member
  • *****
  • Posts: 5436
  • My goal: build my own game engine using Lazarus
Re: Sprite demo example
« Reply #14 on: May 11, 2018, 11:21:51 am »
I'm not the author of that code. You can find it at:
Lazarus main menu > Tools > Example Projects > spriteexample.lpi

 

TinyPortal © 2005-2018