SDLDemo.dpr 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. {
  2. Vampyre Imaging Library Demo
  3. SDL Demo (ObjectPascal, low level/SDL extension, Win32/Linux)
  4. tested in Delphi 7/10, Kylix 3, Free Pascal 2.2.2 (Win32/Linux)
  5. written by Marek Mauder
  6. Demo that shows how to create SDL surfaces from Imaging's
  7. images and vice versa. SDL window is opened and background
  8. and sprite surfaces are loaded and blitted to window. You can change
  9. sprite's data format by pressing SPACE key (it cycles trough all
  10. TImageFormat values) and toggle alpha blending (working only
  11. when sprite's current format has alpha channel) and color keying.
  12. Sprite can be moved accross the screen using arrow keys.
  13. Screenshots can also be taken. Status of the sprite
  14. and list of active keys are shown in the console window.
  15. }
  16. program SDLDemo;
  17. {$I ImagingOptions.inc}
  18. {$APPTYPE CONSOLE}
  19. {$R *.res}
  20. uses
  21. {$IFDEF MSWINDOWS}
  22. Windows,
  23. {$ENDIF}
  24. SysUtils,
  25. sdl,
  26. ImagingTypes,
  27. Imaging,
  28. ImagingSDL,
  29. ImagingUtility,
  30. DemoUtils;
  31. var
  32. VideoInfo: PSDL_VideoInfo;
  33. Flags: LongWord = SDL_HWPALETTE;
  34. DisplaySurface: PSDL_Surface = nil;
  35. BackSurface: PSDL_Surface = nil;
  36. SpriteSurface: PSDL_Surface = nil;
  37. SpriteImage: TImageData;
  38. Event : TSDL_Event;
  39. Running: Boolean = True;
  40. AlphaBlending: Boolean = True;
  41. ColorKeying: Boolean = True;
  42. SpriteFormat: TImageFormat = ifA8R8G8B8;
  43. SpriteX: LongInt = 100;
  44. SpriteY: LongInt = 50;
  45. Keys: PByteArray;
  46. Info: TImageFormatInfo;
  47. Frames: LongInt = 0;
  48. LastTime: LongInt = 0;
  49. const
  50. DisplayWidth = 800;
  51. DisplayHeight = 600;
  52. SIconFile = 'Icon.bmp';
  53. SBackImageFile = 'Tigers.jpg';
  54. SSpriteImageFile = 'Vezyr.png';
  55. SOutScreenFile = 'SDLScreen.png';
  56. SOutSpriteFile = 'SDLSprite.png';
  57. SWindowTitle = 'Vampyre Imaging Library (version: %s) SDL Demo';
  58. SWindowIconTitle = 'SDL Demo';
  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. begin
  169. MessageOut('Vampyre Imaging Library Demo - SDL (version %s)' + sLineBreak +
  170. 'written by Marek Mauder' + sLineBreak, [Imaging.GetVersionStr]);
  171. MessageOut('Keys (when SDL window has focus): ' + sLineBreak +
  172. ' SPACE - cycle image data formats' + sLineBreak +
  173. ' A - toggle alpha blending (only if alpha channel is present)' + sLinebreak +
  174. ' C - toggle color keying' + sLineBreak +
  175. ' S - take screenshot and save (%s)' + sLineBreak +
  176. ' D - save sprite surface (%s)' + sLineBreak +
  177. ' LEFT/RIGHT/UP/DOWN - move sprite' + sLineBreak +
  178. ' ESC/ALT+F4 - quit' + sLineBreak, [SOutScreenFile, SOutSpriteFile]);
  179. // Initialize SDL
  180. if (SDL_Init(SDL_INIT_VIDEO) < 0) then
  181. MessageOutAndHalt('SDL initialization failed: %s', [SDL_GetError]);
  182. // Get video info and set flags
  183. VideoInfo := SDL_GetVideoInfo;
  184. if VideoInfo = nil then
  185. MessageOutAndHalt('SDL GetVideoInfo failed: %s', [SDL_GetError]);
  186. if VideoInfo.hw_available <> 0 then
  187. Flags := Flags or SDL_HWSURFACE
  188. else
  189. Flags := Flags or SDL_SWSURFACE;
  190. SDL_WM_SetCaption(PAnsiChar(AnsiString(Format(SWindowTitle, [Imaging.GetVersionStr]))), SWindowIconTitle);
  191. SDL_WM_SetIcon(LoadSDLSurfaceFromFile(GetDataDir + PathDelim + SIconFile), 0);
  192. // Initialize video mode
  193. DisplaySurface := SDL_SetVideoMode(DisplayWidth, DisplayHeight, 32, Flags);
  194. if DisplaySurface = nil then
  195. MessageOutAndHalt('SDL SetVideoMode failed: %s', [SDL_GetError]);
  196. // Initialize surfaces and enter main loop
  197. Initialize;
  198. LastTime := SDL_GetTicks;
  199. while Running do
  200. begin
  201. while SDL_PollEvent(@Event) = 1 do
  202. begin
  203. case Event.type_ of
  204. SDL_QUITEV:
  205. begin
  206. Running := False;
  207. end;
  208. SDL_KEYDOWN:
  209. begin
  210. with Event.key.keysym do
  211. if ((sym = SDLK_F4) and ((modifier and KMOD_ALT) <> 0)) or
  212. (Event.key.keysym.sym = SDLK_ESCAPE) then
  213. Running := False;
  214. if Event.key.keysym.sym in [SDLK_A, SDLK_C, SDLK_SPACE] then
  215. begin
  216. // You can toggle alpha blending with A key,
  217. // color keying with C key, SPACE key
  218. // can be used to cycle sprite image formats
  219. case Event.key.keysym.sym of
  220. SDLK_A: AlphaBlending := not AlphaBlending;
  221. SDLK_C: ColorKeying := not ColorKeying;
  222. SDLK_SPACE: SpriteFormat := NextFormat(SpriteFormat);
  223. end;
  224. ConvertSprite(SpriteFormat);
  225. end;
  226. // Using S and D keys you can take screen shots and sprite
  227. // shots easily
  228. case Event.key.keysym.sym of
  229. SDLK_S: ImagingSDL.SaveSDLSurfaceToFile(SOutScreenFile, DisplaySurface);
  230. SDLK_D: ImagingSDL.SaveSDLSurfaceToFile(SOutSpriteFile, SpriteSurface);
  231. end;
  232. end;
  233. end;
  234. end;
  235. // Sprite can be moved around screen using arrow keys
  236. Keys := PByteArray(SDL_GetKeyState(nil));
  237. if Keys[SDLK_LEFT] > 0 then
  238. SpriteX := Max(0, SpriteX - 1);
  239. if Keys[SDLK_RIGHT] > 0 then
  240. SpriteX := Min(DisplayWidth - SpriteSurface.w, SpriteX + 1);
  241. if Keys[SDLK_UP] > 0 then
  242. SpriteY := Max(0, SpriteY - 1);
  243. if Keys[SDLK_DOWN] > 0 then
  244. SpriteY := Min(DisplayHeight - SpriteSurface.h, SpriteY + 1);
  245. // Calculate FPS
  246. if LongInt(SDL_GetTicks) - LastTime > 1000 then
  247. begin
  248. SDL_WM_SetCaption(PAnsiChar(AnsiString(Format(SWindowTitle + ' FPS: %d',
  249. [Imaging.GetVersionStr, Frames]))), SWindowIconTitle);
  250. Frames := 0;
  251. LastTime := SDL_GetTicks;
  252. end;
  253. Inc(Frames);
  254. // Blits background and sprite to display surface
  255. Present;
  256. end;
  257. // Frees all surfaces and images
  258. Finalize;
  259. SDL_Quit;
  260. {
  261. File Notes:
  262. -- TODOS ----------------------------------------------------
  263. - nothing now
  264. -- 0.26.1 Changes/Bug Fixes ---------------------------------
  265. - Changed resolution to 800x600.
  266. - Delphi 2009 compatibility pchar/string changes.
  267. }
  268. end.