Fire.Mod 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. MODULE Fire;
  2. IMPORT Out, Random, G := Graph, M := Math, Int;
  3. CONST signHeat = 63;
  4. introLen = 3000;
  5. signWaitDelay = 90;
  6. signChance = 2;
  7. fireRand = 3;
  8. K = 2; (* Pixel buffer resolution multiplier *)
  9. VAR clr: ARRAY 64 OF G.Color;
  10. w, h: INTEGER;
  11. heat: INTEGER;
  12. m: ARRAY 300*K, 640*K OF BYTE;
  13. intro, wait: INTEGER;
  14. f: G.Font;
  15. PROCEDURE PutPixel(x, y, c: INTEGER);
  16. BEGIN
  17. IF m[y, x] # c THEN
  18. m[y, x] := c;
  19. G.PutPixel(x, y, clr[c])
  20. END
  21. END PutPixel;
  22. PROCEDURE PutPixelMaybe(x, y, c: INTEGER);
  23. BEGIN
  24. IF (0 <= x) & (x < w) & (0 <= y) & (y < h) THEN
  25. PutPixel(x, y, c)
  26. END
  27. END PutPixelMaybe;
  28. PROCEDURE SwapPoints(VAR x1, y1, x2, y2: INTEGER);
  29. VAR t: INTEGER;
  30. BEGIN
  31. t := x1; x1 := x2; x2 := t;
  32. t := y1; y1 := y2; y2 := t
  33. END SwapPoints;
  34. PROCEDURE Line(x1, y1, x2, y2, c: INTEGER);
  35. VAR dx, dy, x, y, half, t: INTEGER;
  36. BEGIN
  37. dx := ABS(x1 - x2); dy := ABS(y1 - y2);
  38. IF dx = 0 THEN
  39. IF y1 > y2 THEN t := y1; y1 := y2; y2 := t END;
  40. FOR y := y1 TO y2 DO PutPixelMaybe(x1, y, c) END
  41. ELSIF dy = 0 THEN
  42. IF x1 > x2 THEN t := x1; x1 := x2; x2 := t END;
  43. FOR x := x1 TO x2 DO PutPixelMaybe(x, y1, c) END
  44. ELSIF dx > dy THEN
  45. IF x1 > x2 THEN SwapPoints(x1, y1, x2, y2) END;
  46. half := dx DIV 2;
  47. FOR x := x1 TO x2 DO
  48. PutPixelMaybe(x, y1 + ((y2 - y1) * x + half) DIV dx, c)
  49. END
  50. ELSE
  51. IF y1 > y2 THEN SwapPoints(x1, y1, x2, y2) END;
  52. half := dy DIV 2;
  53. FOR y := y1 TO y2 DO
  54. PutPixelMaybe(x1 + ((x2 - x1) * y + half) DIV dy, y, c)
  55. END
  56. END
  57. END Line;
  58. PROCEDURE ThickLine(x1, y1, x2, y2, c: INTEGER);
  59. CONST T = 3;
  60. VAR x, y: INTEGER;
  61. BEGIN
  62. FOR y := 0 TO T DO
  63. FOR x := 0 TO T DO
  64. Line(x1 + x, y1 + y, x2 + x, y2 + y, c)
  65. END
  66. END
  67. END ThickLine;
  68. PROCEDURE C(x, y, W: INTEGER);
  69. BEGIN
  70. ThickLine(x, y, x + W, y, signHeat);
  71. ThickLine(x, y + W, x + W, y + W, signHeat);
  72. ThickLine(x, y, x, y + W, signHeat)
  73. END C;
  74. PROCEDURE P(x, y, W: INTEGER);
  75. VAR W2: INTEGER;
  76. BEGIN
  77. W2 := W DIV 2;
  78. ThickLine(x, y, x + W, y, signHeat);
  79. ThickLine(x, y, x, y + W, signHeat);
  80. ThickLine(x, y + W2, x + W, y + W2, signHeat);
  81. ThickLine(x + W, y, x + W, y + W2, signHeat)
  82. END P;
  83. PROCEDURE Sign;
  84. VAR x, y, i, W, pad: INTEGER;
  85. BEGIN
  86. pad := w DIV 20;
  87. W := (w - 5 * pad) DIV 6;
  88. y := (h - W) DIV 2 - Random.Int(pad * 2);
  89. x := (w - W * 4 - 3 * pad) DIV 2 + Random.Int(pad * 4 + 1) - pad * 2;
  90. FOR i := 0 TO 2 DO C(x, y, W); INC(x, W + pad) END;
  91. P(x, y, W);
  92. wait := signWaitDelay
  93. END Sign;
  94. PROCEDURE GoFire;
  95. VAR x, y, c: INTEGER;
  96. BEGIN
  97. FOR y := 0 TO h - 2 DO
  98. FOR x := 1 TO w - 2 DO
  99. c := (m[y + 1, x] * 2 + m[y, x - 1] + m[y, x + 1]) DIV 4;
  100. IF c # 0 THEN INC(c, Random.Int(2 * fireRand + 1) - fireRand) END;
  101. IF c < 0 THEN c := 0 ELSIF c > 63 THEN c := 63 END;
  102. PutPixel(x, y, c)
  103. END
  104. END
  105. END GoFire;
  106. PROCEDURE Run;
  107. VAR done: BOOLEAN;
  108. ch: CHAR;
  109. x, y: INTEGER;
  110. Z: ARRAY 20 OF CHAR;
  111. BEGIN
  112. done := FALSE;
  113. FOR x := 0 TO w - 1 DO
  114. FOR y := 0 TO h - 1 DO
  115. m[y, x] := 0
  116. END
  117. END;
  118. REPEAT
  119. IF intro # 0 THEN
  120. DEC(intro);
  121. Line(2, h - 1, w - 3, h - 1,
  122. FLOOR((1 - M.sin(intro * (M.pi / 2) / introLen)) * 63))
  123. ELSE
  124. Line(2, h - 1, w - 3, h - 1, heat)
  125. END;
  126. IF wait = 0 THEN
  127. IF Random.Int(100) < signChance THEN Sign END
  128. ELSE DEC(wait)
  129. END;
  130. GoFire;
  131. G.Flip;
  132. IF G.KeyPressed() THEN
  133. ch := G.ReadKey();
  134. IF ch = CHR(27) THEN done := TRUE
  135. ELSIF ch = '=' (*'+'*) THEN
  136. IF heat < 63 THEN INC(heat) END
  137. ELSIF ch = '-' THEN
  138. IF heat > 0 THEN DEC(heat) END
  139. ELSIF ('0' <= ch) & (ch <= '9') THEN
  140. heat := (ORD(ch) - ORD('0')) * 7
  141. ELSIF (ch = ' ') THEN
  142. intro := 0;
  143. wait := 0
  144. END
  145. END
  146. UNTIL done
  147. END Run;
  148. PROCEDURE Do;
  149. VAR i: INTEGER;
  150. BEGIN
  151. G.Settings(320, 200, {});
  152. G.Settings(640, 400, {G.smooth});
  153. G.Init();
  154. f := G.LoadFont('../Data/Fonts/Main');
  155. G.ShowMouse(FALSE);
  156. G.GetTargetSize(w, h);
  157. IF h > LEN(m) THEN h := LEN(m) END;
  158. IF w > LEN(m[0]) THEN w := LEN(m[0]) END;
  159. (* Initialize palette *)
  160. FOR i := 0 TO 15 DO
  161. G.MakeCol(clr[i], i * 8, 0, 0);
  162. G.MakeCol(clr[i + 16], (i + 16) * 8, 0, 0);
  163. G.MakeCol(clr[i + 32], 240, i * 16, 0);
  164. G.MakeCol(clr[i + 48], 240, 240, i * 16)
  165. END;
  166. heat := 63;
  167. intro := introLen;
  168. wait := intro;
  169. Run;
  170. G.Close
  171. END Do;
  172. BEGIN
  173. Do
  174. END Fire.