123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- MODULE Fire;
- IMPORT Out, Random, G := Graph, M := Math, Int;
- CONST signHeat = 63;
- introLen = 3000;
- signWaitDelay = 90;
- signChance = 2;
- fireRand = 3;
- K = 1; (* Pixel buffer resolution multiplier *)
- VAR clr: ARRAY 64 OF G.Color;
- w, h: INTEGER;
- heat: INTEGER;
- m: ARRAY 300 * K, 640 * K OF BYTE;
- intro, wait: INTEGER;
- PROCEDURE PutPixel(x, y, c: INTEGER);
- BEGIN
- IF m[y, x] # c THEN
- m[y, x] := c;
- G.PutPixel(x, y, clr[c])
- END
- END PutPixel;
- PROCEDURE PutPixelMaybe(x, y, c: INTEGER);
- BEGIN
- IF (0 <= x) & (x < w) & (0 <= y) & (y < h) THEN
- PutPixel(x, y, c)
- END
- END PutPixelMaybe;
- PROCEDURE SwapPoints(VAR x1, y1, x2, y2: INTEGER);
- VAR t: INTEGER;
- BEGIN
- t := x1; x1 := x2; x2 := t;
- t := y1; y1 := y2; y2 := t
- END SwapPoints;
- PROCEDURE Line(x1, y1, x2, y2, c: INTEGER);
- VAR dx, dy, x, y, half, t: INTEGER;
- BEGIN
- dx := ABS(x1 - x2); dy := ABS(y1 - y2);
- IF dx = 0 THEN
- IF y1 > y2 THEN t := y1; y1 := y2; y2 := t END;
- FOR y := y1 TO y2 DO PutPixelMaybe(x1, y, c) END
- ELSIF dy = 0 THEN
- IF x1 > x2 THEN t := x1; x1 := x2; x2 := t END;
- FOR x := x1 TO x2 DO PutPixelMaybe(x, y1, c) END
- ELSIF dx > dy THEN
- IF x1 > x2 THEN SwapPoints(x1, y1, x2, y2) END;
- half := dx DIV 2;
- FOR x := x1 TO x2 DO
- PutPixelMaybe(x, y1 + ((y2 - y1) * x + half) DIV dx, c)
- END
- ELSE
- IF y1 > y2 THEN SwapPoints(x1, y1, x2, y2) END;
- half := dy DIV 2;
- FOR y := y1 TO y2 DO
- PutPixelMaybe(x1 + ((x2 - x1) * y + half) DIV dy, y, c)
- END
- END
- END Line;
- PROCEDURE ThickLine(x1, y1, x2, y2, c: INTEGER);
- CONST T = 3;
- VAR x, y: INTEGER;
- BEGIN
- FOR y := 0 TO T DO
- FOR x := 0 TO T DO
- Line(x1 + x, y1 + y, x2 + x, y2 + y, c)
- END
- END
- END ThickLine;
- PROCEDURE C(x, y, W: INTEGER);
- BEGIN
- ThickLine(x, y, x + W, y, signHeat);
- ThickLine(x, y + W, x + W, y + W, signHeat);
- ThickLine(x, y, x, y + W, signHeat)
- END C;
- PROCEDURE P(x, y, W: INTEGER);
- VAR W2: INTEGER;
- BEGIN
- W2 := W DIV 2;
- ThickLine(x, y, x + W, y, signHeat);
- ThickLine(x, y, x, y + W, signHeat);
- ThickLine(x, y + W2, x + W, y + W2, signHeat);
- ThickLine(x + W, y, x + W, y + W2, signHeat)
- END P;
- PROCEDURE Sign;
- VAR x, y, i, W, pad: INTEGER;
- BEGIN
- pad := w DIV 20;
- W := (w - 5 * pad) DIV 6;
- y := (h - W) DIV 2 - Random.Int(pad * 2);
- x := (w - W * 4 - 3 * pad) DIV 2 + Random.Int(pad * 4 + 1) - pad * 2;
- FOR i := 0 TO 2 DO C(x, y, W); INC(x, W + pad) END;
- P(x, y, W);
- wait := signWaitDelay
- END Sign;
- PROCEDURE GoFire;
- VAR x, y, c: INTEGER;
- BEGIN
- FOR y := 0 TO h - 2 DO
- FOR x := 1 TO w - 2 DO
- c := (m[y + 1, x] * 2 + m[y, x - 1] + m[y, x + 1]) DIV 4;
- IF c # 0 THEN INC(c, Random.Int(2 * fireRand + 1) - fireRand) END;
- IF c < 0 THEN c := 0 ELSIF c > 63 THEN c := 63 END;
- PutPixel(x, y, c)
- END
- END
- END GoFire;
- PROCEDURE Run;
- VAR done: BOOLEAN;
- ch: CHAR;
- x, y: INTEGER;
- Z: ARRAY 20 OF CHAR;
- BEGIN
- done := FALSE;
- FOR x := 0 TO w - 1 DO
- FOR y := 0 TO h - 1 DO
- m[y, x] := 0
- END
- END;
- REPEAT
- IF intro # 0 THEN
- DEC(intro);
- Line(2, h - 1, w - 3, h - 1,
- FLOOR((1.0 - M.sin(FLT(intro) * (M.pi / 2.0) / FLT(introLen))) * 63.0))
- ELSE
- Line(2, h - 1, w - 3, h - 1, heat)
- END;
- IF wait = 0 THEN
- IF Random.Int(100) < signChance THEN Sign END
- ELSE DEC(wait)
- END;
- GoFire;
- G.Flip;
- IF G.KeyPressed() THEN
- ch := G.ReadKey();
- IF ch = CHR(27) THEN done := TRUE
- ELSIF ch = '=' (*'+'*) THEN
- IF heat < 63 THEN INC(heat) END
- ELSIF ch = '-' THEN
- IF heat > 0 THEN DEC(heat) END
- ELSIF ('0' <= ch) & (ch <= '9') THEN
- heat := (ORD(ch) - ORD('0')) * 7
- ELSIF (ch = ' ') THEN
- intro := 0;
- wait := 0
- END
- END
- UNTIL done
- END Run;
- PROCEDURE Do;
- VAR i: INTEGER;
- BEGIN
- G.Settings(320, 200, {G.smooth});
- G.Init();
- G.ShowMouse(FALSE);
- G.GetTargetSize(w, h);
- IF h > LEN(m) THEN h := LEN(m) END;
- IF w > LEN(m[0]) THEN w := LEN(m[0]) END;
- (* Initialize palette *)
- FOR i := 0 TO 15 DO
- G.MakeCol(clr[i], i * 8, 0, 0);
- G.MakeCol(clr[i + 16], (i + 16) * 8, 0, 0);
- G.MakeCol(clr[i + 32], 240, i * 16, 0);
- G.MakeCol(clr[i + 48], 240, 240, i * 16)
- END;
- heat := 63;
- intro := introLen;
- wait := intro;
- Run;
- G.Close
- END Do;
- BEGIN
- Do
- END Fire.
|