packages feed

language-Modula2-0.1: examples/Modula-2_Libraries/PMOS/sources/general/bounce.mod

IMPLEMENTATION MODULE Bounce;

	(********************************************************)
	(*							*)
	(*		Bouncing ball demonstration.		*)
	(*							*)
	(*  This module is not intended to be of any practical	*)
	(*  use, but it tests the time delay functions of the	*)
	(*  kernel and acts as a demonstration that multiple	*)
	(*  tasks really can coexist.				*)
	(*							*)
	(*  Programmer:		P. Moylan			*)
	(*  Last edited:	15 February 1994		*)
	(*  Status:		Working, behaviour not quite	*)
	(*			ideal.  For now, improvements	*)
	(*			probably not worth the effort.	*)
	(*							*)
	(********************************************************)

FROM TaskControl IMPORT
    (* proc *)	CreateTask;

FROM Timer IMPORT
    (* proc *)	Sleep;

FROM Windows IMPORT
    (* type *)	Window, Colour, FrameType, DividerType,
    (* proc *)	OpenWindow, CloseWindow, WriteString, WriteChar,
		SetCursor;

FROM UserInterface IMPORT
    (* type *)	UIWindow, Capability, CapabilitySet,
    (* proc *)	AllowMouseControl;

(************************************************************************)

VAR w: Window;
    debug: Window;

    (* The ball is confined inside window w.  The following four bounds	*)
    (* define where within the window it can go.			*)

    xmin, xmax, ymin, ymax: REAL;

    (* We must remember where the ball was, so we can delete it.	*)

    oldx, oldy: CARDINAL;

(************************************************************************)

PROCEDURE DisplayBall (x, y: REAL);

    (* Displays the ball at the given screen coordinates.	*)

    BEGIN
	SetCursor (w, oldy, oldx);  WriteChar (w, " ");
	oldx := CARDINAL(x+0.5);  oldy := CARDINAL(y+0.5);
	SetCursor (w, oldy, oldx);  WriteChar (w, CHR(9));
	WriteString (debug, " .. moved");
    END DisplayBall;

(************************************************************************)

PROCEDURE BouncingBall;

    (* This procedure runs as a separate task.	*)

    CONST delay = 40;
	  g = 0.1;  reflection = 0.79;

    VAR xposition, yposition, xspeed, yspeed: REAL;

    BEGIN
	oldx := 1;  oldy := 1;
	xposition := 2.0;  yposition := 2.0;
	xspeed := 1.0;  yspeed := 0.7;
	LOOP
	    (* Display current position *)
	    DisplayBall (xposition, yposition);
	    Sleep (delay);
	    (* Update position and speed *)
	    xposition := xposition + xspeed;
	    yposition := yposition + yspeed;
	    yspeed := yspeed + g;
	    (* Reverse direction if we hit a wall *)
	    IF xposition < xmin THEN
		xposition := 2.0*xmin - xposition;
		xspeed := -xspeed;
	    ELSIF xposition > xmax THEN
		xposition :=  2.0*xmax - xposition;
		xspeed := -xspeed;
	    END (*IF*);
	    IF yposition < ymin THEN
		yposition := 2.0*ymin - yposition;
		yspeed := -reflection*yspeed;
	    ELSIF yposition > ymax THEN
		yposition :=  2.0*ymax - yposition;
		yspeed := -reflection*yspeed;
	    END (*IF*);
	END (*LOOP*);
    END BouncingBall;

(************************************************************************)

PROCEDURE Bouncing (top, bottom: RowRange;  left, right: ColumnRange);

    (* Creates a screen window, and runs a bouncing ball demonstration	*)
    (* inside this window.						*)

    VAR UIW1, UIW2: UIWindow;

    BEGIN
	xmin := 0.5;  xmax := FLOAT(right - left) - 0.5;
	ymin := 0.5;  ymax := FLOAT(bottom - top) - 0.5;
	OpenWindow (w,yellow,red,top,bottom,left,right,simpleframe,nodivider);
	UIW1 := AllowMouseControl (w, "Bouncing ball",
				CapabilitySet {wmove, wshow, whide});
	OpenWindow (debug,yellow,red,20,24,0,39,simpleframe,nodivider);
	UIW2 := AllowMouseControl (debug, "Bounce/debug",
				CapabilitySet {wmove, wshow, whide});
	CreateTask (BouncingBall, 2, "Bounce");
    END Bouncing;

END Bounce.