fire.pp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. {
  2. Ported to FPC by Nikolay Nikolov ([email protected])
  3. }
  4. {
  5. Fire demo for OpenPTC 1.0 C++ API
  6. Copyright (c) Glenn Fiedler ([email protected])
  7. This source code is licensed under the GNU GPL
  8. }
  9. program Fire;
  10. {$MODE objfpc}
  11. uses
  12. ptc;
  13. function pack(r, g, b: Uint32): Uint32;
  14. begin
  15. { pack color integer }
  16. pack := (r shl 16) or (g shl 8) or b;
  17. end;
  18. procedure generate(palette: IPTCPalette);
  19. var
  20. data: PUint32;
  21. i, c: Integer;
  22. begin
  23. { lock palette data }
  24. data := palette.Lock;
  25. try
  26. { black to red }
  27. i := 0;
  28. c := 0;
  29. while i < 64 do
  30. begin
  31. data[i] := pack(c, 0, 0);
  32. Inc(c, 4);
  33. Inc(i);
  34. end;
  35. { red to yellow }
  36. c := 0;
  37. while i < 128 do
  38. begin
  39. data[i] := pack(255, c, 0);
  40. Inc(c, 4);
  41. Inc(i);
  42. end;
  43. { yellow to white }
  44. c := 0;
  45. while i < {192}128 do
  46. begin
  47. data[i] := pack(255, 255, c);
  48. Inc(c, 4);
  49. Inc(i);
  50. end;
  51. { white }
  52. while i < 256 do
  53. begin
  54. data[i] := pack(255, 255, 255);
  55. Inc(i);
  56. end;
  57. finally
  58. { unlock palette }
  59. palette.Unlock;
  60. end;
  61. end;
  62. var
  63. format: IPTCFormat;
  64. console: IPTCConsole;
  65. surface: IPTCSurface;
  66. palette: IPTCPalette;
  67. state: Integer;
  68. intensity: Single;
  69. pixels, pixel, p: PUint8;
  70. width, height: Integer;
  71. x, y: Integer;
  72. top, bottom, c1, c2: Uint32;
  73. generator: PUint8;
  74. color: Integer;
  75. area: IPTCArea;
  76. begin
  77. try
  78. try
  79. { create format }
  80. format := TPTCFormatFactory.CreateNew(8);
  81. { create console }
  82. console := TPTCConsoleFactory.CreateNew;
  83. { open console }
  84. console.open('Fire demo', 320, 200, format);
  85. { create surface }
  86. surface := TPTCSurfaceFactory.CreateNew(320, 208, format);
  87. { create palette }
  88. palette := TPTCPaletteFactory.CreateNew;
  89. { generate palette }
  90. generate(palette);
  91. { set console palette }
  92. console.palette(palette);
  93. { set surface palette }
  94. surface.palette(palette);
  95. { flame data }
  96. state := 0;
  97. intensity := 0;
  98. { setup copy area }
  99. area := TPTCAreaFactory.CreateNew(0, 0, 320, 200);
  100. { main loop }
  101. repeat
  102. { lower flame on keypress }
  103. if console.KeyPressed then
  104. state := 2;
  105. { state machine }
  106. case state of
  107. 0: begin
  108. { raise flame }
  109. intensity := intensity + 0.007;
  110. { maximum flame height }
  111. if intensity > 0.8 then
  112. state := 1;
  113. end;
  114. 1: begin
  115. { constant flame }
  116. end;
  117. 2: begin
  118. { lower flame }
  119. intensity := intensity - 0.005;
  120. { exit program when flame is out }
  121. if intensity < 0.01 then
  122. begin
  123. console.close;
  124. exit;
  125. end;
  126. end;
  127. end;
  128. { lock surface pixels }
  129. pixels := surface.lock;
  130. try
  131. { get surface dimensions }
  132. width := surface.width;
  133. height := surface.height;
  134. { flame vertical loop }
  135. y := 1;
  136. while y < height - 4 do
  137. begin
  138. { current pixel pointer }
  139. pixel := pixels + y * width;
  140. { flame horizontal loop }
  141. for x := 0 to width - 1 do
  142. begin
  143. { sum top pixels }
  144. p := pixel + (width shl 1);
  145. top := p^;
  146. Inc(top, (p - 1)^);
  147. Inc(top, (p + 1)^);
  148. { bottom pixel }
  149. bottom := (pixel + (width shl 2))^;
  150. { combine pixels }
  151. c1 := (top + bottom) shr 2;
  152. if c1 > 1 then
  153. Dec(c1);
  154. { interpolate }
  155. c2 := (c1 + bottom) shr 1;
  156. { store pixels }
  157. pixel^ := c1;
  158. (pixel + width)^ := c2;
  159. { next pixel }
  160. Inc(pixel);
  161. end;
  162. Inc(y, 2);
  163. end;
  164. { setup flame generator pointer }
  165. generator := pixels + width * (height - 4);
  166. { update flame generator bar }
  167. x := 0;
  168. while x < width do
  169. begin
  170. { random block color taking intensity into account }
  171. color := random(Integer(Trunc(255 * intensity)));
  172. { write 4x4 color blocks }
  173. (generator + 0)^ := color;
  174. (generator + 1)^ := color;
  175. (generator + 2)^ := color;
  176. (generator + 3)^ := color;
  177. (generator + width + 0)^ := color;
  178. (generator + width + 1)^ := color;
  179. (generator + width + 2)^ := color;
  180. (generator + width + 3)^ := color;
  181. (generator + width * 2 + 0)^ := color;
  182. (generator + width * 2 + 1)^ := color;
  183. (generator + width * 2 + 2)^ := color;
  184. (generator + width * 2 + 3)^ := color;
  185. (generator + width * 3 + 0)^ := color;
  186. (generator + width * 3 + 1)^ := color;
  187. (generator + width * 3 + 2)^ := color;
  188. (generator + width * 3 + 3)^ := color;
  189. { next block }
  190. Inc(generator, 4);
  191. Inc(x, 4);
  192. end;
  193. finally
  194. { unlock surface }
  195. surface.unlock;
  196. end;
  197. { copy surface to console }
  198. surface.copy(console, area, area);
  199. { update console }
  200. console.update;
  201. until False;
  202. finally
  203. if Assigned(console) then
  204. console.Close;
  205. end;
  206. except
  207. on error: TPTCError do
  208. { report error }
  209. error.report;
  210. end;
  211. end.