home *** CD-ROM | disk | FTP | other *** search
-
- { Copyright (c) 1989,90 by Borland International, Inc. }
-
- unit Bounds;
- { Turbo Pascal 6.0 object-oriented example.
- See BREAKOUT.PAS.
- Contains the Paddle object type and the object types that
- define the boundaries of the playfield.
- This unit is part of the BREAKOUT.PAS example.
- }
-
- interface
-
- uses Screen, Bricks, Count, Crt;
-
- type
- ObstaclePtr = ^Obstacle;
-
- { An ObstacleList is a list of instances of objects derived from the
- object Obstacle. In order to use all these instances polymorphically,
- All their virtual functions have to have corresponding virtual functions
- in Obstacle, even if they are never used. }
-
- Obstacle = object(Location)
- Width : Integer;
- Trap : Boolean;
- NextPtr : ObstaclePtr;
- constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
- destructor Done; virtual;
- function Collide(var B : Ball) : Boolean; virtual;
- function IsTrap : Boolean; virtual;
- function GetValue : Integer; virtual;
- end;
-
- ObstacleList = object
- Head : Obstacle;
- Tail : ObstaclePtr;
- constructor Init;
- destructor Done; virtual;
- procedure Append(NewObstacle : ObstaclePtr);
- procedure Show;
- procedure Hide;
- function CheckCollisions(var B : Ball; var Score : Counter) : Boolean;
- end;
-
- Paddle = object(Obstacle)
- Color : Integer;
- constructor Init(InitX, InitY, InitColor : Integer);
- destructor Done; virtual;
- procedure Show; virtual;
- procedure Hide; virtual;
- procedure MoveTo(NewX, NewY : Integer); virtual;
- function Collide(var B : Ball) : Boolean; virtual;
- end;
-
- { There are no instances of the object Boundary. It's here to provide
- a common basis for the next four objects. }
- Boundary = object(Obstacle)
- constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
- end;
-
- LeftBound = object(Boundary)
- constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
- function Collide(var B : Ball) : Boolean; virtual;
- end;
-
- UpperBound = object(Boundary)
- constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
- function Collide(var B : Ball) : Boolean; virtual;
- end;
-
- RightBound = object(Boundary)
- constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
- function Collide(var B : Ball) : Boolean; virtual;
- end;
-
- LowerBound = object(Boundary)
- constructor Init(InitX, InitY, InitWidth : Integer; SetTrap : Boolean);
- function Collide(var B : Ball) : Boolean; virtual;
- end;
-
- implementation
-
- constructor Obstacle.Init(InitX, InitY, InitWidth : Integer;
- SetTrap : Boolean);
- begin
- Location.Init(InitX, InitY);
- Width := InitWidth;
- Trap := SetTrap;
- NextPtr := nil;
- end;
-
- destructor Obstacle.Done;
- begin
- end;
-
- function Obstacle.Collide(var B : Ball) : Boolean;
- begin
- Collide := True;
- end;
-
- function Obstacle.IsTrap : Boolean;
- begin
- IsTrap := Trap;
- end;
-
- function Obstacle.GetValue : Integer;
- begin
- GetValue := 0;
- end;
-
- constructor ObstacleList.Init;
- begin
- Head.Init(0, 0, 0, False);
- Tail := @Head;
- end;
-
- destructor ObstacleList.Done;
- var
- Temp1, Temp2 : ObstaclePtr;
- begin
- Temp1 := Head.NextPtr;
- while Temp1 <> nil do
- begin
- Temp2 := Temp1;
- Temp1 := Temp1^.NextPtr;
- Temp2^.Done;
- end;
- end;
-
- procedure ObstacleList.Append(NewObstacle : ObstaclePtr);
- begin
- Tail^.NextPtr := NewObstacle;
- Tail := NewObstacle;
- end;
-
- procedure ObstacleList.Show;
- var
- Current : ObstaclePtr;
- begin
- Current := Head.NextPtr;
- while Current <> nil do
- begin
- Current^.Show;
- Current := Current^.NextPtr;
- end;
- end;
-
- procedure ObstacleList.Hide;
- var
- Current : ObstaclePtr;
- begin
- Current := Head.NextPtr;
- while Current <> nil do
- begin
- Current^.Hide;
- Current := Current^.NextPtr;
- end;
- end;
-
-
- { This function is a little more complex than I like. It checks
- whether a collision occurs, and updates the score if one does. }
-
- function ObstacleList.CheckCollisions(var B : Ball;
- var Score : Counter) : Boolean;
- var
- Current : ObstaclePtr;
- begin
- CheckCollisions := False;
- Current := Head.NextPtr;
- while Current <> nil do
- begin
- if Current^.Collide(B) then
- begin
- Score.Add(Current^.GetValue);
- if Current^.IsTrap then
- CheckCollisions := True;
- end;
- Current := Current^.NextPtr;
- end;
- end;
-
- constructor Paddle.Init(InitX, InitY, InitColor : Integer);
- begin
- Obstacle.Init(InitX, InitY, 5, False);
- Color := InitColor;
- end;
-
- destructor Paddle.Done;
- begin
- Obstacle.Done;
- end;
-
- procedure Paddle.Show;
- var
- Str : String[10];
- begin
- FillChar(Str[1], Width, Chr(223));
- Str[0] := Chr(Width);
- Location.Show;
- TextColor(Color);
- GoToXY(X, Y);
- Write(Str);
- end;
-
- procedure Paddle.Hide;
- begin
- Location.Hide;
- GoToXY(X, Y);
- Write('' : Width);
- end;
-
- { The motion of Paddle is restricted to the 80-character screen }
-
- procedure Paddle.MoveTo(NewX, NewY : Integer);
- begin
- Hide;
- if NewX < 1 then
- X := 1
- else if NewX > 81 - Width then
- X := 81 - Width
- else
- X := NewX;
- Y := NewY;
- Show;
- end;
-
- { If the ball hits the paddle we have to change the ball's direction.
- Also, to keep the overall logic simpler, if the paddle is at the
- edge of the screen and the ball would miss the paddle and go off the
- edge, we call it a hit. If we don't do this here, we get into some
- complications with bouncing off the sides of the screen }
-
- function Paddle.Collide(var B : Ball) : Boolean;
- var
- NewX, NewY : Integer;
- begin
- NewX := B.NextX;
- NewY := B.NextY;
- Collide := False;
- if (NewY = Y) then
- if ((NewX >= X) and (NewX < X + Width)) or
- ((NewX < 1) and (X = 1)) or
- ((NewX > 80) and (X + Width = 81)) then
- begin
- B.ReverseY;
- {$IFDEF Test} { If the paddle is following the ball, we have to put
- in some random behavior so it doesn't get boring. }
- B.ChangeXVel(Integer(Random(2))*2-1);
- {$ELSE}
- B.ChangeXVel(B.GetX - X - 2);
- {$ENDIF}
- Collide := True;
- end;
- end;
-
- constructor Boundary.Init(InitX, InitY, InitWidth : Integer;
- SetTrap : Boolean);
- begin
- Obstacle.Init(InitX, InitY, InitWidth, SetTrap);
- end;
-
- constructor LeftBound.Init(InitX, InitY, InitWidth : Integer;
- SetTrap : Boolean);
- begin
- Boundary.Init(InitX, InitY, InitWidth, SetTrap);
- end;
-
- function LeftBound.Collide(var B : Ball) : Boolean;
- begin
- Collide := False;
- if (B.NextX <= X) and (B.NextY >= Y) and (B.NextY <= Y + Width) then
- begin
- B.ReverseX;
- Collide := True;
- end;
- end;
-
- constructor UpperBound.Init(InitX, InitY, InitWidth : Integer;
- SetTrap : Boolean);
- begin
- Boundary.Init(InitX, InitY, InitWidth, SetTrap);
- end;
-
- function UpperBound.Collide(var B : Ball) : Boolean;
- begin
- Collide := False;
- if (B.NextY <= Y) and (B.NextX >= X) and (B.NextX <= X + Width) then
- begin
- B.ReverseY;
- Collide := True;
- end;
- end;
-
- constructor RightBound.Init(InitX, InitY, InitWidth : Integer;
- SetTrap : Boolean);
- begin
- Boundary.Init(InitX, InitY, InitWidth, SetTrap);
- end;
-
- function RightBound.Collide(var B : Ball) : Boolean;
- begin
- Collide := False;
- if (B.NextX >= X) and (B.NextY >= Y) and (B.NextY <= Y + Width) then
- begin
- B.ReverseX;
- Collide := True;
- end;
- end;
-
- constructor LowerBound.Init(InitX, InitY, InitWidth : Integer;
- SetTrap : Boolean);
- begin
- Boundary.Init(InitX, InitY, InitWidth, SetTrap);
- end;
-
- function LowerBound.Collide(var B : Ball) : Boolean;
- begin
- Collide := False;
- if (B.NextY >= Y) and (B.NextX >= X) and (B.NextX <= X + Width) then
- begin
- B.ReverseY;
- Collide := True;
- end;
- end;
-
- end.
-