DemoUnit.pas 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. {
  2. Vampyre Imaging Library Demo
  3. SDL Demo (SDL extension)
  4. Demo that shows how to create SDL surfaces from Imaging's
  5. images and vice versa. SDL window is opened and background
  6. and sprite surfaces are loaded and blitted to window. You can change
  7. sprite's data format by pressing SPACE key (it cycles trough all
  8. TImageFormat values) and toggle alpha blending (working only
  9. when sprite's current format has alpha channel) and color keying.
  10. Sprite can be moved across the screen using arrow keys.
  11. Screenshots can also be taken. Status of the sprite
  12. and list of active keys are shown in the console window.
  13. }
  14. unit DemoUnit;
  15. {$I ImagingOptions.inc}
  16. {$R ..\Common\MainIcon.res}
  17. interface
  18. procedure RunDemo;
  19. implementation
  20. uses
  21. {$IFDEF MSWINDOWS}
  22. Windows,
  23. {$ENDIF}
  24. SysUtils,
  25. sdl,
  26. ImagingTypes,
  27. Imaging,
  28. ImagingSdl,
  29. ImagingUtility,
  30. DemoUtils;
  31. const
  32. DisplayWidth = 800;
  33. DisplayHeight = 600;
  34. SIconFile = 'Icon.png';
  35. SBackImageFile = 'Tigers.jpg';
  36. SSpriteImageFile = 'Vezyr.png';
  37. SOutScreenFile = 'SDLScreen.png';
  38. SOutSpriteFile = 'SDLSprite.png';
  39. SWindowTitle = 'Vampyre Imaging Library (version: %s) SDL Demo';
  40. SWindowIconTitle = 'SDL Demo';
  41. var
  42. VideoInfo: PSDL_VideoInfo;
  43. Flags: LongWord = SDL_HWPALETTE;
  44. DisplaySurface: PSDL_Surface = nil;
  45. BackSurface: PSDL_Surface = nil;
  46. SpriteSurface: PSDL_Surface = nil;
  47. SpriteImage: TImageData;
  48. Event : TSDL_Event;
  49. Running: Boolean = True;
  50. AlphaBlending: Boolean = True;
  51. ColorKeying: Boolean = True;
  52. SpriteFormat: TImageFormat = ifA8R8G8B8;
  53. SpriteX: LongInt = 100;
  54. SpriteY: LongInt = 50;
  55. Keys: PByteArray;
  56. Info: TImageFormatInfo;
  57. Frames: LongInt = 0;
  58. LastTime: LongInt = 0;
  59. procedure MessageOut(const Msg: string; const Args: array of const);
  60. begin
  61. WriteLn(Format(Msg, Args));
  62. end;
  63. procedure MessageOutAndHalt(const Msg: string; const Args: array of const);
  64. begin
  65. WriteLn('Error: ');
  66. MessageOut(' ' + Msg, Args);
  67. WriteLn('Press RETURN to exit');
  68. ReadLn;
  69. Halt(1);
  70. end;
  71. procedure ConvertSprite(Format: TImageFormat);
  72. var
  73. Surface: PSDL_Surface;
  74. AlphaMsg: string;
  75. Key: UInt32;
  76. begin
  77. Key := 0;
  78. SDL_FreeSurface(SpriteSurface);
  79. // Convert sprite image to SDL surface with Format override
  80. Surface := ImagingSDL.CreateSDLSurfaceFromImage(SpriteImage, SDL_SWSURFACE, Format);
  81. // Convert to display format for faster blits and use alpha
  82. // if enabled and present
  83. if (Surface.format.Aloss <> 8) and AlphaBlending then
  84. begin
  85. if ColorKeying then
  86. begin
  87. // Set color key if enabled
  88. Move(Surface.pixels^, Key, Surface.format.BytesPerPixel);
  89. SDL_SetColorKey(Surface, SDL_SRCCOLORKEY or SDL_RLEACCEL, Key);
  90. end;
  91. SpriteSurface := SDL_DisplayFormatAlpha(Surface);
  92. end
  93. else
  94. begin
  95. SpriteSurface := SDL_DisplayFormat(Surface);
  96. if ColorKeying then
  97. begin
  98. // Set color key if enabled
  99. Move(SpriteSurface.pixels^, Key, SpriteSurface.format.BytesPerPixel);
  100. SDL_SetColorKey(SpriteSurface, SDL_SRCCOLORKEY or SDL_RLEACCEL, Key);
  101. end;
  102. end;
  103. if SpriteSurface = nil then
  104. MessageOutAndHalt('Cannot create sprite surface: %s', [SDL_GetError]);
  105. SDL_FreeSurface(Surface);
  106. // Output sprite info
  107. Imaging.GetImageFormatInfo(Format, Info);
  108. MessageOut('Sprite converted', []);
  109. MessageOut(' Current sprite format: %s', [Info.Name]);
  110. AlphaMsg := Iff((SpriteSurface.format.Aloss <> 8) and (SpriteSurface.format.palette = nil),
  111. 'Enabled', 'Disabled or not supported in this format');
  112. MessageOut(' Alpha blending: %s', [AlphaMsg]);
  113. MessageOut(' Color keying: %s', [Iff(ColorKeying, 'Enabled', 'Disabled')]);
  114. end;
  115. procedure Initialize;
  116. var
  117. Image: TImageData;
  118. Surface: PSDL_Surface;
  119. {$IFDEF MSWINDOWS}
  120. Caption, Icon: PAnsiChar;
  121. WindowHandle: THandle;
  122. {$ENDIF}
  123. begin
  124. {$IFDEF MSWINDOWS}
  125. SDL_WM_GetCaption(Caption, Icon);
  126. WindowHandle := FindWindowA('SDL_app', Caption);
  127. if WindowHandle <> 0 then
  128. // Place window to the center of the screen
  129. SetWindowPos(WindowHandle, 0, (GetSystemMetrics(SM_CXSCREEN) - DisplayWidth) div 2,
  130. (GetSystemMetrics(SM_CYSCREEN) - DisplayHeight - 20) div 2, 0, 0, SWP_NOSIZE or SWP_NOZORDER);
  131. {$ENDIF}
  132. // Load background image from file, resize it to fit the window,
  133. // convert it to SDL surface and convert this surface to
  134. // display format for faster blitting
  135. if not Imaging.LoadImageFromFile(GetDataDir + PathDelim + SBackImageFile, Image) then
  136. MessageOutAndHalt('Cannot load background image: %s', [SBackImageFile]);
  137. Imaging.ResizeImage(Image, DisplayWidth, DisplayHeight, rfBilinear);
  138. Surface := ImagingSDL.CreateSDLSurfaceFromImage(Image, SDL_SWSURFACE);
  139. BackSurface := SDL_DisplayFormat(Surface);
  140. Imaging.FreeImage(Image);
  141. SDL_FreeSurface(Surface);
  142. if BackSurface = nil then
  143. MessageOutAndHalt('Cannot create background surface.', []);
  144. // Load sprite image
  145. if not Imaging.LoadImageFromFile(GetDataDir + PathDelim + SSpriteImageFile, SpriteImage) then
  146. MessageOutAndHalt('Cannot load sprite image: %s', [SSpriteImageFile]);
  147. ConvertSprite(SpriteFormat);
  148. end;
  149. procedure Present;
  150. var
  151. Dest: TSDL_Rect;
  152. begin
  153. Dest.x := SpriteX;
  154. Dest.y := SpriteY;
  155. Dest.w := SpriteSurface.w;
  156. Dest.h := SpriteSurface.h;
  157. SDL_BlitSurface(BackSurface, nil, DisplaySurface, nil);
  158. SDL_BlitSurface(SpriteSurface, nil, DisplaySurface, @Dest);
  159. SDL_UpdateRect(DisplaySurface, 0, 0, DisplayWidth, DisplayHeight);
  160. end;
  161. procedure Finalize;
  162. begin
  163. // Free all surfaces and images
  164. SDL_FreeSurface(BackSurface);
  165. SDL_FreeSurface(SpriteSurface);
  166. Imaging.FreeImage(SpriteImage);
  167. end;
  168. procedure RunDemo;
  169. begin
  170. MessageOut('Vampyre Imaging Library Demo - SDL (version %s)' + sLineBreak +
  171. 'written by Marek Mauder' + sLineBreak, [Imaging.GetVersionStr]);
  172. MessageOut('Keys (when SDL window has focus): ' + sLineBreak +
  173. ' SPACE - cycle image data formats' + sLineBreak +
  174. ' A - toggle alpha blending (only if alpha channel is present)' + sLinebreak +
  175. ' C - toggle color keying' + sLineBreak +
  176. ' S - take screenshot and save (%s)' + sLineBreak +
  177. ' D - save sprite surface (%s)' + sLineBreak +
  178. ' LEFT/RIGHT/UP/DOWN - move sprite' + sLineBreak +
  179. ' ESC/ALT+F4 - quit' + sLineBreak, [SOutScreenFile, SOutSpriteFile]);
  180. // Initialize SDL
  181. if (SDL_Init(SDL_INIT_VIDEO) < 0) then
  182. MessageOutAndHalt('SDL initialization failed: %s', [SDL_GetError]);
  183. // Get video info and set flags
  184. VideoInfo := SDL_GetVideoInfo;
  185. if VideoInfo = nil then
  186. MessageOutAndHalt('SDL GetVideoInfo failed: %s', [SDL_GetError]);
  187. if VideoInfo.hw_available <> 0 then
  188. Flags := Flags or SDL_HWSURFACE
  189. else
  190. Flags := Flags or SDL_SWSURFACE;
  191. SDL_WM_SetCaption(PAnsiChar(AnsiString(Format(SWindowTitle, [Imaging.GetVersionStr]))), SWindowIconTitle);
  192. SDL_WM_SetIcon(LoadSDLSurfaceFromFile(GetDataDir + PathDelim + SIconFile), 0);
  193. // Initialize video mode
  194. DisplaySurface := SDL_SetVideoMode(DisplayWidth, DisplayHeight, 32, Flags);
  195. if DisplaySurface = nil then
  196. MessageOutAndHalt('SDL SetVideoMode failed: %s', [SDL_GetError]);
  197. // Initialize surfaces and enter main loop
  198. Initialize;
  199. LastTime := SDL_GetTicks;
  200. while Running do
  201. begin
  202. while SDL_PollEvent(@Event) = 1 do
  203. begin
  204. case Event.type_ of
  205. SDL_QUITEV:
  206. begin
  207. Running := False;
  208. end;
  209. SDL_KEYDOWN:
  210. begin
  211. with Event.key.keysym do
  212. if ((sym = SDLK_F4) and ((modifier and KMOD_ALT) <> 0)) or
  213. (Event.key.keysym.sym = SDLK_ESCAPE) then
  214. Running := False;
  215. if Event.key.keysym.sym in [SDLK_A, SDLK_C, SDLK_SPACE] then
  216. begin
  217. // You can toggle alpha blending with A key,
  218. // color keying with C key, SPACE key
  219. // can be used to cycle sprite image formats
  220. case Event.key.keysym.sym of
  221. SDLK_A: AlphaBlending := not AlphaBlending;
  222. SDLK_C: ColorKeying := not ColorKeying;
  223. SDLK_SPACE: SpriteFormat := NextFormat(SpriteFormat);
  224. end;
  225. ConvertSprite(SpriteFormat);
  226. end;
  227. // Using S and D keys you can take screen shots and sprite
  228. // shots easily
  229. case Event.key.keysym.sym of
  230. SDLK_S: ImagingSDL.SaveSDLSurfaceToFile(SOutScreenFile, DisplaySurface);
  231. SDLK_D: ImagingSDL.SaveSDLSurfaceToFile(SOutSpriteFile, SpriteSurface);
  232. end;
  233. end;
  234. end;
  235. end;
  236. // Sprite can be moved around screen using arrow keys
  237. Keys := PByteArray(SDL_GetKeyState(nil));
  238. if Keys[SDLK_LEFT] > 0 then
  239. SpriteX := Max(0, SpriteX - 1);
  240. if Keys[SDLK_RIGHT] > 0 then
  241. SpriteX := Min(DisplayWidth - SpriteSurface.w, SpriteX + 1);
  242. if Keys[SDLK_UP] > 0 then
  243. SpriteY := Max(0, SpriteY - 1);
  244. if Keys[SDLK_DOWN] > 0 then
  245. SpriteY := Min(DisplayHeight - SpriteSurface.h, SpriteY + 1);
  246. // Calculate FPS
  247. if LongInt(SDL_GetTicks) - LastTime > 1000 then
  248. begin
  249. SDL_WM_SetCaption(PAnsiChar(AnsiString(Format(SWindowTitle + ' FPS: %d',
  250. [Imaging.GetVersionStr, Frames]))), SWindowIconTitle);
  251. Frames := 0;
  252. LastTime := SDL_GetTicks;
  253. end;
  254. Inc(Frames);
  255. // Blits background and sprite to display surface
  256. Present;
  257. end;
  258. // Frees all surfaces and images
  259. Finalize;
  260. SDL_Quit;
  261. end;
  262. {
  263. File Notes:
  264. -- 0.77.1 ---------------------------------------------------
  265. - Refactored the demo (moved stuff to unit from dpr) and
  266. added Lazarus project files.
  267. -- 0.26.1 Changes/Bug Fixes ---------------------------------
  268. - Changed resolution to 800x600.
  269. - Delphi 2009 compatibility pchar/string changes.
  270. }
  271. end.