lights.pp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. {
  2. Ported to FPC by Nikolay Nikolov ([email protected])
  3. }
  4. {
  5. Lights 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 Lights;
  10. {$MODE objfpc}
  11. {$INLINE on}
  12. uses
  13. ptc;
  14. var
  15. { distance lookup table }
  16. distance_table: array [0..299, 0..511] of DWord; { note: 16.16 fixed }
  17. { intensity calculation }
  18. function CalcIntensity(dx, dy: Integer; i: DWord): DWord; Inline;
  19. begin
  20. { lookup intensity at [dx,dy] }
  21. Result := i * distance_table[dy, dx];
  22. end;
  23. var
  24. console: IPTCConsole;
  25. surface: IPTCSurface;
  26. format: IPTCFormat;
  27. palette: IPTCPalette;
  28. dx, dy: Integer;
  29. divisor: Single;
  30. data: PUint32;
  31. pixels, line: PUint8;
  32. width: Integer;
  33. i: Integer;
  34. x, y, x1, y1, x2, y2, x3, y3, x4, y4: Integer;
  35. cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4: Single;
  36. dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4: Single;
  37. _dx1, _dx2, _dx3, _dx4: Integer;
  38. _dy1, _dy2, _dy3, _dy4: Integer;
  39. ix1, ix2, ix3, ix4: Integer;
  40. i1, i2, i3, i4: DWord;
  41. length: Integer;
  42. move_t, move_dt, move_ddt: Single;
  43. flash_t, flash_dt, flash_ddt: Single;
  44. intensity: DWord;
  45. max_intensity, max_intensity_inc: Single;
  46. begin
  47. try
  48. try
  49. { create console }
  50. console := TPTCConsoleFactory.CreateNew;
  51. format := TPTCFormatFactory.CreateNew(8);
  52. { open console }
  53. console.open('Lights demo', 320, 200, format);
  54. { create surface }
  55. surface := TPTCSurfaceFactory.CreateNew(320, 200, format);
  56. { setup intensity table }
  57. for dy := 0 to 199 do
  58. for dx := 0 to 511 do
  59. begin
  60. divisor := sqrt((dx * dx) + (dy * dy));
  61. if divisor < 0.3 then
  62. divisor := 0.3;
  63. distance_table[dy, dx] := Trunc(65535 / divisor);
  64. end;
  65. { create palette }
  66. palette := TPTCPaletteFactory.CreateNew;
  67. { generate greyscale palette }
  68. data := palette.Lock;
  69. try
  70. for i := 0 to 255 do
  71. data[i] := (i shl 16) or (i shl 8) or i;
  72. finally
  73. palette.Unlock;
  74. end;
  75. { set console palette }
  76. console.palette(palette);
  77. { set surface palette }
  78. surface.palette(palette);
  79. { data }
  80. cx1 := 60;
  81. cy1 := 110;
  82. cx2 := 100;
  83. cy2 := 80;
  84. cx3 := 250;
  85. cy3 := 110;
  86. cx4 := 200;
  87. cy4 := 90;
  88. dx1 := 0;
  89. dy1 := 0;
  90. dx2 := 0;
  91. dy2 := 0;
  92. dx3 := 0;
  93. dy3 := 0;
  94. dx4 := 0;
  95. dy4 := 0;
  96. i1 := 0;
  97. i2 := 0;
  98. i3 := 0;
  99. i4 := 0;
  100. { time data }
  101. move_t := 0.3;
  102. move_dt := 0.1;
  103. move_ddt := 0.0006;
  104. flash_t := 0.1;
  105. flash_dt := 0.0;
  106. flash_ddt := 0.0004;
  107. { control data }
  108. max_intensity := 30;
  109. max_intensity_inc := 0.2;
  110. { main loop }
  111. while not console.KeyPressed do
  112. begin
  113. { source positions }
  114. x1 := Trunc(cx1 + dx1);
  115. y1 := Trunc(cy1 + dy1);
  116. x2 := Trunc(cx2 + dx2);
  117. y2 := Trunc(cy2 + dy2);
  118. x3 := Trunc(cx3 + dx3);
  119. y3 := Trunc(cy3 + dy3);
  120. x4 := Trunc(cx4 + dx4);
  121. y4 := Trunc(cy4 + dy4);
  122. { lock surface }
  123. pixels := surface.lock;
  124. try
  125. { get surface dimensions }
  126. width := surface.width;
  127. { line loop }
  128. for y := 0 to 199 do
  129. begin
  130. { calcalate pointer to start of line }
  131. line := pixels + y * width;
  132. { get y deltas }
  133. _dy1 := abs(y - y1);
  134. _dy2 := abs(y - y2);
  135. _dy3 := abs(y - y3);
  136. _dy4 := abs(y - y4);
  137. { setup x }
  138. x := 0;
  139. { line loop }
  140. while x < width do
  141. begin
  142. { get x deltas }
  143. _dx1 := abs(x1 - x);
  144. _dx2 := abs(x2 - x);
  145. _dx3 := abs(x3 - x);
  146. _dx4 := abs(x4 - x);
  147. { get increments }
  148. ix1 := 1;
  149. ix2 := 1;
  150. ix3 := 1;
  151. ix4 := 1;
  152. if x1 > x then
  153. ix1 := -1;
  154. if x2 > x then
  155. ix2 := -1;
  156. if x3 > x then
  157. ix3 := -1;
  158. if x4 > x then
  159. ix4 := -1;
  160. { set span length to min delta }
  161. length := width - x;
  162. if (x1 > x) and (_dx1 < length) then
  163. length := _dx1;
  164. if (x2 > x) and (_dx2 < length) then
  165. length := _dx2;
  166. if (x3 > x) and (_dx3 < length) then
  167. length := _dx3;
  168. if (x4 > x) and (_dx4 < length) then
  169. length := _dx4;
  170. { pixel loop }
  171. while length > 0 do
  172. begin
  173. Dec(length);
  174. { calc intensities }
  175. intensity := CalcIntensity(_dx1, _dy1, i1);
  176. Inc(intensity, CalcIntensity(_dx2, _dy2, i2));
  177. Inc(intensity, CalcIntensity(_dx3, _dy3, i3));
  178. Inc(intensity, CalcIntensity(_dx4, _dy4, i4));
  179. intensity := intensity shr 16;
  180. if intensity > 255 then
  181. intensity := 255;
  182. { update deltas }
  183. Inc(_dx1, ix1);
  184. Inc(_dx2, ix2);
  185. Inc(_dx3, ix3);
  186. Inc(_dx4, ix4);
  187. { store the pixel }
  188. line[x] := intensity;
  189. Inc(x);
  190. end;
  191. end;
  192. end;
  193. finally
  194. { unlock surface }
  195. surface.unlock;
  196. end;
  197. { move the lights around }
  198. dx1 := 50 * sin((move_t + 0.0) * 0.10);
  199. dy1 := 80 * sin((move_t + 0.6) * 0.14);
  200. dx2 := 100 * sin((move_t + 0.1) * 0.10);
  201. dy2 := 30 * sin((move_t - 0.4) * 0.30);
  202. dx3 := 39 * sin((move_t + 9.9) * 0.20);
  203. dy3 := 50 * sin((move_t + 0.4) * 0.30);
  204. dx4 := 70 * sin((move_t - 0.3) * 0.25);
  205. dy4 := 40 * sin((move_t - 0.1) * 0.31);
  206. { flash intensity }
  207. i1 := Trunc(max_intensity * (sin((flash_t + 0.000) * 1.000) + 1));
  208. i2 := Trunc(max_intensity * (sin((flash_t + 2.199) * 0.781) + 1));
  209. i3 := Trunc(max_intensity * (sin((flash_t - 1.450) * 1.123) + 1));
  210. i4 := Trunc(max_intensity * (sin((flash_t + 0.000) * 0.500) + 1));
  211. { update time }
  212. move_t := move_t + move_dt;
  213. move_dt := move_dt + move_ddt;
  214. flash_t := flash_t + flash_dt;
  215. flash_dt := flash_dt + flash_ddt;
  216. { reset on big flash... }
  217. if (move_t > 600) and (i1 > 10000) and (i2 > 10000) and
  218. (i3 > 10000) and (i4 > 10000) then
  219. begin
  220. move_t := 0.3;
  221. move_dt := 0.1;
  222. move_ddt := 0.0006;
  223. flash_t := 0.1;
  224. flash_dt := 0.0;
  225. flash_ddt := 0.0004;
  226. max_intensity := 0.0;
  227. max_intensity_inc := 0.2;
  228. end;
  229. { update intensity }
  230. max_intensity := max_intensity + max_intensity_inc;
  231. max_intensity_inc := max_intensity_inc + 0.008;
  232. { copy surface to console }
  233. surface.copy(console);
  234. { update console }
  235. console.update;
  236. end;
  237. finally
  238. if Assigned(console) then
  239. console.close;
  240. end;
  241. except
  242. on error: TPTCError do
  243. { report error }
  244. error.report;
  245. end;
  246. end.