MODULE LinesDemo;

(** ------------------------------------------------------------------

             Commodore Amiga line drawing demonstration module

      (c) Copyright 1986 Modula-2 Software Ltd.  All Rights Reserved
      (c) Copyright 1986 TDI Software, Inc.      All Rights Reserved

    ------------------------------------------------------------------ **)


(* VERSION FOR COMMODORE AMIGA

     Original Author : Paul Curtis, Modula-2 Software Ltd.  17-Jan-86

     Version         : 0.01a  05-Dec-86  Martin Fisher, Modula-2 Software Ltd.
                         Compiler 3.00a library modifications
                       0.00c  10-Jul-86  Paul Curtis, Modula-2 Software Ltd.
                         Compiler 2.20a modifications.
                       0.00b  11-Feb-86  Phil Camp, Modula-2 Software Ltd.
                         Changed for Screens.
                         Tidied up termination.
                       0.00a  17-Jan-86  Paul Curtis, Modula-2 Software Ltd.
                         Original

  *)


(*$S-,$T-,$A+*)

FROM SYSTEM IMPORT ADR;
FROM DemoScreen IMPORT InitDemoScreen, EndDemo, DemoScreen;
FROM RandomNumbers IMPORT Random;
FROM GraphicsLibrary IMPORT DrawingModes, DrawingModeSet;
FROM Pens IMPORT SetAPen, SetDrMd, Move, PolyDraw;
FROM Rasters IMPORT RastPort, RastPortPtr;
FROM Views IMPORT ModeSet ;

CONST
  depth = 1;
  width = 320;
  height = 200;

VAR 
  RP: RastPortPtr;

PROCEDURE DoDemo;
CONST
  maxLines = 128;
VAR
  DisplayedLines: ARRAY [0..maxLines-1] OF RECORD x0,y0,x1,y1: INTEGER; END;
  Ball: ARRAY [0..3] OF RECORD
                          x,y: INTEGER;  (* where the ball is *)
                          vx,vy: INTEGER;  (* velocity in x & y directions *)
                        END;

VAR
  index: CARDINAL;
  new, old, p, i, dl: CARDINAL;

  PROCEDURE Bounce(VAR x,v: INTEGER; max: INTEGER);
  VAR t: INTEGER;
  BEGIN
    t := x+v;
    IF t >= max THEN
      x := max*2-v-x-1;
      v := -v;
    ELSIF t < 0 THEN
      x := -t;
      v := -v;
    ELSE
      x := t;
    END;
  END Bounce;

BEGIN
  FOR index := 0 TO HIGH(Ball) DO
    WITH Ball[index] DO
      REPEAT vx := Random(16)-8; UNTIL vx # 0;
      REPEAT vy := Random(16)-8; UNTIL vy # 0;
      x := Random(width);
      y := Random(height);
    END;
  END;

  new := 0; old := 0;

  FOR index := 0 TO 3999 DO
    IF new >= maxLines THEN
      (* undraw old lines *)
      p := old MOD maxLines;
      Move(RP,DisplayedLines[p].x0,DisplayedLines[p].y0);
      PolyDraw(RP,8,DisplayedLines[p]);
      INC(old,HIGH(Ball)+1);
    END;

    dl := new MOD maxLines;
    FOR i := 0 TO HIGH(Ball) DO
      p := new MOD maxLines;
      DisplayedLines[p].x0 := Ball[i].x;
      DisplayedLines[p].y0 := Ball[i].y;
      DisplayedLines[p].x1 := Ball[(i+1) MOD (HIGH(Ball)+1)].x;
      DisplayedLines[p].y1 := Ball[(i+1) MOD (HIGH(Ball)+1)].y;
      INC(new);
    END;

    (* show new lines *)
    Move(RP,DisplayedLines[dl].x0,DisplayedLines[dl].y0);
    PolyDraw(RP,8,DisplayedLines[dl]);

    (* bounce balls off walls *)
    FOR i := 0 TO HIGH(Ball) DO 
      Bounce(Ball[i].x,Ball[i].vx,width);
      Bounce(Ball[i].y,Ball[i].vy,height);
    END;

  END
END DoDemo;


BEGIN
  IF InitDemoScreen(width,height,depth, ModeSet{}) THEN
    RP := ADR(DemoScreen^.RPort);  
    SetAPen(RP,255);
    SetDrMd(RP,DrawingModeSet{Complement});
    DoDemo;
  END;
  EndDemo;
END LinesDemo.
