Руководство пользователя
1.1 Описание игры
Арканоид впервые появился ещё в 80-х годах. В игре арканоид вы управляете доской, которую можно передвигать от одного края экрана к другому. Цель игры- разбить стену, состоящую из разноцветных блоков, расположенную вверху экрана, отбивая доской летающую по экрану звёздочку.
1.2 Правила игры
Основные элементы игры: доска, звёздочка и блоки на игровом поле. Отбивайте доской звёздочку, которая разрушает блоки. Промах приравнивается к потере одной жизни. За каждый выбитый блок начисляется определённое количество очков. Игрок контролирует небольшую доску, которую можно передвигать горизонтально от одной стенки к другой, подставляя её под звёздочку, предотвращая её падение вниз. Удар шарика по кирпичу приводит к его разрушению. После того, как все блоки на данном уровне уничтожены, происходит переход на следующий уровень.
1.3 Интерфейс игры
При запуске игры на экране отображается доска, звёздочка и стена, состоящая из разноцветных блоков. Клавиша «Enter» запускает игру. Клавишами «влево» и «вправо» мы передвигаем ракетку на одну позицию влево и вправо соответственно. Клавишей «пробел» можно приостановить игру. Снять игру с паузы можно любой клавишей, исключая пробел.
В центре экрана мы видим стену, состоящую из разноцветных блоков. В верхнем левом углу отображается текущий уровень. В правом верхнем углу отображаются баллы, набранные за время игры, а между ними показывается. Количество жизней. В нижней части экрана находится ракетка, с расположенной на ней звёздочкой.
Руководство разработчика структурная схема продукта
Arcanoid
Gamelib
Fieldlib
Levellib
Bricklib
Walllib
Starlib
Состав системы
Система состоит из следующих модулей:: Gamelib, Levellib, Fieldlib, Starlib, Walllib, Bricklib.
Схема подключения модулей
Описание модулей
а)Модуль BRICKLIB – в модуле используются процедуры и функции, в которых передаются начальная позиция и размер доски и символа доски, размеры кирпичей, которые будем сбивать в игре; расстояние, на которое доска сдвигается при нажатии клавиши управления доской и очки, начисляемые при сбивании одного кирпича; определяется позиция доски по Х и У.
К нему подключается модуль CRT:
Interface
Uses CRT;
Используемые в модуле константы: brickwidth задаёт ширину кирпича, brickfill – символ из которого состоят кирпичи, boardwidth – ширина доски, boardfill – символ из которого состоит доска, left – направление движения шарика влево, right – направление движения шарика вправо, brickcost – количество очков начисляемых игроку за один выбитый кирпич.
Const
BrickWidth = 5;
BrickFill = '█';
BoardWidth = 10;
BoardFill = '═';
Left = -1;
Rigth = 1;
brickcost=100 div brickwidth;
Type
brick = object
Private
x, y : integer;
width : byte;
c, bgcolor : byte;
visible : boolean;
fill : char;
Используемые в программе процедуры и функции:
procedure Init(x0, y0, c0, bgcolor0 : integer) инициализирует кирпич;
procedure Show показывает кирпич;
procedure Hide прячет кирпич;
procedure Break разбивает кирпич;
function GetX : integer определяет текущую позицию курсора по x;
function GetY : integer определяет текущую позицию курсора по y;
function GetWidth : byte определяет текущую ширину кирпича;
function Isvisible : boolean делает кирпич невидимым.
Каждому действию соответствует свой метод. Методы описаны в разделе PUBLIC, потому что они составляют интерфейс объекта.
Объект board является наследником объекта BRICK, поэтому он наследует все его методы.
Но объект также имеет и свои процедуры:
procedure Init(c0,bgcolor0 : byte)инициализирует доску;
procedure Move(direction : integer)двигает доску.
В разделе Implementation находятся описание методов(текст подпрограмм).
ROCEDURE brick.Init(x0, y0, c0, bgcolor0: integer);
Инициализирует кирпич, то есть присваивает начальные значения полям объекта:
begin
x := x0; y := y0;
width := BrickWidth;
c := c0; bgcolor := bgcolor0;
visible := true;
fill := BrickFill;
end;
procedure brick.Show;
Показывает кирпич, если он видим, в текущей позиции, заданным цветом на поле. Поле имеет цвет в зависимости от уровня.
var i:integer;
begin
if visible then
begin
gotoxy(x, y);
TextColor(c);
TextBackground(bgcolor);
for i:= 1 to width do
write(fill);
end;
end;
procedure brick.Hide;
Узнает цвет поля, и выводит пробел столько раз, какова ширина кирпича.
var i:integer;
begin
TextBackground(bgcolor);
gotoxy(x,y);
for i := 1 to width do
write(' ');
end;
procedure brick.Break;
Делает кирпич невидимым.
begin
Hide;
visible := false;
end;
function brick.GetX : integer;
Определяет текущую позицию x.
begin
GetX := x;
end;
function brick.GetY :integer;
Определяет текущую позицию y.
begin
GetY := y;
end;
function brick.GetWidth : byte;
Определяет ширину кирпича.
begin
GetWidth := width;
end;
function brick.Isvisible : boolean;
Определяет видим ли кирпич.
begin
Isvisible := visible;
end;
Процедуры наследуемого объекта.
procedure board.Init(c0,bgcolor0 : byte);
Выводит доску посреди последней строки, заданным цветом c0, шириной boardwidth, символами fill.
begin
inherited Init((80 - BoardWidth) div 2, 25, c0, bgcolor0);
width := BoardWidth;
fill := BoardFill;
end;
procedure board.Move(direction : integer);
Двигает доску: вначале стирает ее, затем выводит на новой позиции в зависимости от того, какая клавиша была нажата.
begin
Hide;
Case direction of
Left: if (x > 2) then dec(x);
Rigth: if (x + width <= 79) then inc(x);
end;
Show;
end;
Модуль заканчивается, словом END.
б) Модуль WALLLIB – в модуле передаётся область, по которой будет двигаться символ доски и сбивать кирпичи.
К нему подключаются модули CRT, Bricklib:
Interface
Uses CRT, Bricklib;
Используемые в модуле константы: wallwidth задаёт ширину стены, wallheigth определяет высоту стены.
CONST
WALLWIDTH = 10;
WALLHEIGTH = 5;
Type
wall = object
Private
x, y : integer;
width, heigth:byte;
bricks : array [1..WallHeigth,1..WallWidth] of brick;
Public
procedure Init(x0, y0, width0, heigth0, bgcolor0 : byte);
procedure Show;
procedure BreakBrick(r,c : byte);
function IsBroken : boolean;
function GetWidth : integer;
function GetHeigth : integer;
procedure GetBrick(r, c : byte;Var br : brick);
end;
Implementation
procedure wall.Init(x0, y0, width0, heigth0, bgcolor0 : byte);
Процедура инициализирует область
var r, c : byte;
begin
x := x0; y := y0;
width := width0; heigth := heigth0;
for r := 1 to heigth do
for c := 1 to width do
bricks[r,c].Init(x + (c - 1) * BrickWidth,
y + (r - 1),
random(11)+ 6,
bgcolor0);
end;
procedure wall.Show;
Процедура рисует кирпичи в области
var r, c : byte;
begin
for r := 1 to heigth do
for c := 1 to width do
bricks[r,c].Show;
end;
procedure wall.BreakBrick(r,c : byte);
Процедура прекращает рисование кирпича в указанном месте области
begin
bricks[r, c].Break;
end;
function wall.IsBroken : boolean;
Функция определяет, разбит ли кирпич
var r, c, count : integer;
begin
count := 0;
for r := 1 to heigth do
for c := 1 to width do
if bricks[r,c].IsVisible then
inc(count);
IsBroken := (count = 0);
end;
function wall.GetWidth : integer;
Функция определяет ширину области
begin
GetWidth := width;
end;
function wall.GetHeigth : integer;
Функция определяет высоту области
begin
GetHeigth := heigth;
end;
procedure wall.GetBrick(r, c : byte;Var br : brick);
Процедура возвращает текущее состояние кирпича
begin
br := bricks[r, c];
end;
в) Модуль Starlib – в модуле используются процедуры и функции, отслеживающие движение символа доски по области, определение позиции символа доски по X и Y.
К нему подключаются модули CRT, Bricklib, Walllib.
Interface
Uses CRT, BrickLib, Walllib;
Const
HorDir = 1;
VertDir = 2;
Type
star = object
Private
x, y : integer;
dx, dy : integer;
c,bgcolor : byte;
Public
procedure Show;
procedure Hide;
procedure Move;
procedure CheckBorders;
procedure CheckBoard(Var b : brick);
function CheckCollision(Var b : board; Var w : wall; Var sc:longint) : boolean;
function CheckWall(Var w : wall):longint;
procedure Init(c0,bgcolor0 : byte);
procedure Turn(direction : integer);
function GetX : integer;
function GetY : byte;
end;
Implementation
Procedure star.Show;
Процедура рисует звёздочку на экране
begin
gotoxy(x,y);
TextColor(c);
Write('щ');
end;
procedure star.Hide;
Процедура убирает звёздочку с экрана
begin
gotoxy(x,y);
TextColor(c);
Write(' ');
end;
procedure star.Move;
Процедура перемещает звёздочку по экрану
begin
Hide;
x := x + dx;
y := y + dy;
Show;
end;
procedure star.CheckBorders;
В процедуре отслеживается выход за границы
begin
if (x > 79) or (x < 3) then
Turn(HorDir);
if (y < 3) then
Turn(VertDir);
end;
procedure star.CheckBoard(Var b : brick);
В процедуре отслеживается движение звёздочки
var xb, wb : integer;
begin
xb := b.GetX;
wb := b.GetWidth;
if (y = 24) then
begin
if (x = xb - 1) or
(x = xb + wb) then
Turn(HorDir and VertDir);
if (x >= xb) and
(x <= xb + wb - 1) then
Turn(VertDir);
end;
end;
function star.CheckCollision(Var b : board;Var w : wall; Var sc:longint) : boolean;
В функции отслеживается падение звёздочки мимо доски
begin
CheckBorders;
CheckBoard(b);
sc:=CheckWall(w);
CheckCollision := (y = 25);
end;
function star.CheckWall(Var w : wall):longint;
var xb, wb, yb, xr : integer;
br: brick;
row, col : byte;
ReflectHor, ReflectVert : boolean;
s:longint;
begin
s:=0;
ReflectHor := false;
ReflectVert := false;
for row := 1 to w.GetHeigth do
for col := 1 to w.GetWidth do
begin
w.GetBrick(row, col, br);
xb := br.GetX;
yb := br.GetY;
wb := br.GetWidth;
xr := xb + wb - 1;
if (((yb = yb - 1) or (y = yb + 1)) and
((xb <= x) and (x <= xr))) and br.IsVisible then
begin
Turn(VertDir);
ReflectVert := true;
w.BreakBrick(row, col);
s:=s+Brickcost;
end;
end;
for row := 1 to w.GetHeigth do
for col := 1 to w.GetWidth do
begin
w.GetBrick(row, col, br);
xb := br.GetX;
yb := br.GetY;
wb := br.GetWidth;
xr := xb + wb - 1;
if ((y = yb) and ((x = xb - 1) or (x = xr + 1)))
and br.IsVisible then
begin
Turn(HorDir);
ReflectHor := true;
w.BreakBrick(row, col);
s:=s+Brickcost;
end;
end;
if not (ReflectVert or ReflectHor) then
begin
for row := 1 to w.GetHeigth do
for col := 1 to w.GetWidth do
begin
w.GetBrick(row, col, br);
xb := br.GetX;
yb := br.GetY;
wb := br.GetWidth;
xr := xb + wb - 1;
if (
((x = xb - 1) and (y = yb - 1) and (dx = 1) and (dy = 1)) or
((x = xr + 1) and (y = yb - 1) and (dx = -1) and (dy = 1)) or
((x = xb - 1) and (y = yb + 1) and (dx = 1) and (dy = -1)) or
((x = xr + 1) and (y = yb + 1) and (dx = -1) and (dy = -1))
) and br.IsVisible then
begin
Turn(HorDir and VertDir);
w.BreakBrick(row, col);
s:=s+Brickcost;
end;
end;
end;
if ReflectHor and ReflectVert then
s:=s+brickcost*(-4);
CheckWall:=s;
end;
procedure star.Init(c0,bgcolor0:byte);
Инициализация звёздочки
begin
x := 40; y := 24; dx := 1; dy := -1;
c := c0; bgcolor := bgcolor0;
end;
procedure star.Turn(direction:integer);
Движение звёздочки
begin
case direction of
HorDir : dx := -dx;
VertDir : dy := - dy
else
begin
dx := -dx;
dy := - dy;
end;
end;
end;
function star.GetX: integer;
Получение позиции звёздочки по X
begin
GetX := x;
end;
function star.GetY: byte;
Получение позиции звёздочки по Y
begin
GetY := y;
end;
Begin
End.
г) Модуль Levellib – в модуле используются процедуры и функции, в которых управляем положением доски, количеством набранных очков, а по окончанию игры и происходит построение таблицы рекордов.
К нему подключаются модули CRT, Starlib, Walllib, Bricklib.
Interface
Uses CRT, Starlib, Walllib, Bricklib;
Const
LevelsNumber = 2;
LevelBgColors : array[1..LevelsNumber] of byte = (blue,magenta);
BoardColor = Green;
StarColor = White;
Type
level = object
Private
s : star;
b : board;
w : wall;
lives : byte;
number : byte;
EndofLevel :boolean;
Public
procedure Init(number0:byte);
procedure Stop;
procedure Start( Var score:longint);
procedure PrintScore(score: longint);
function Passed:boolean;
end;
Implementation
procedure level.Init(number0:byte);
Инициализация уровня
begin
number := number0;
b.Init(BoardColor,LevelBgColors[Number]);
s.Init(StarColor,LevelBgColors[Number]);
w.Init((80 - WallWidth * BrickWidth) div 2, 5,
WallWidth, WallHeigth, LevelBgColors[Number]);
EndofLevel := false;
end;
procedure level.Stop;
begin
end;
procedure level.Start ( Var score:longint);
Запуск уровня игры
var miss : boolean;
i, x, y ,sc : longint;
ch : char;
begin
b.Show;
s.Show;
w.Show;
readln;
miss := false;
i := 0;
repeat
if i = 140000 then
begin
s.Move;
i := 0;
miss := s.CheckCollision(b,w,sc);
score:=score+sc;
PrintScore(score);
end
else
inc(i);
if keypressed then
begin
ch := readkey;
if ch = #0 then
ch := readkey;
case ch of
#75: b.Move(Left);
#77: b.Move(Rigth);
#27: EndofLevel := true;
#32: repeat until keypressed;
end;
end;
until (miss or EndofLevel);
end;
procedure Level.PrintScore(score: longint);
Вывод набранных очков на экран
begin
gotoxy (65,1);
textcolor ( yellow );
textbackground ( LevelBgColors[Number] );
write ('Score: ');
textcolor ( white );
write (score: 8);
end;
function level.Passed:boolean;
Определяет, остановлена ли игра
begin
Passed := EndofLevel;
end;
Begin
End.
д) Модуль Fieldlib – здесь используется процедура, которая выводит набираемые в игре: количество жизней и набираемый уровень, а также процедура которой передаётся цвет фона.
К нему подключаются модули CRT и dos.
Interface
Uses CRT, dos;
Type
field = object
Private
bgcolor:byte;
Public
procedure CoursorOff;
procedure Show ( curlevel:byte; curlives:byte; curscore:longint );
procedure Init(bgcolor0:byte);
end;
Implementation
procedure Field.CoursorOff;
Убирает курсор с экрана(делает его невидимым)
Var
Reg : Registers;
begin
with Reg do
begin
AH := 1;
CH := $20;
end;
Intr($10,Reg);
end;
procedure field.Show( curlevel:byte; curlives:byte; curscore:longint );
Выводит очки , набираемые в игре; количество жизней и проходимый уровень
begin
CoursorOff;
TextBackground(bgcolor);
ClrScr;
{**level**}
gotoxy (2,1);
textcolor ( yellow );
write ('Level: ');
textcolor ( white );
write (curlevel);
{**lives**}
gotoxy (35,1);
textcolor ( yellow );
write ('Lives: ');
textcolor ( white );
write (curlives);
{**score**}
gotoxy (65,1);
textcolor ( yellow );
write ('Score: ');
textcolor ( white );
write (curScore);
end;
procedure Field.Init(bgcolor0:byte);
Инициализация поля
begin
bgcolor := bgcolor0;
end;
Begin
End.
е) Модуль GAMELIB – в модуле используются процедуры и функции, с помощью которых игра запускается.
К нему подключаются модули CRT, Fieldlib, Levellib.
Interface
Uses CRT,Fieldlib, Levellib;
Const
MaxLives = 3;
Type
game = object
Private
f:field;
l : level;
EndofGame:boolean;
Lives : byte;
Score:longint;
Public
procedure Run;
procedure Init;
function GetScore:longint;
procedure SetScore(score0:longint);
procedure Over;
end;
Implementation
procedure Game.Run;
Запуск игры
var Curlevel:byte; curscore:longint;
begin
Curlevel := 1;
repeat
l.Init(Curlevel);
f.Init(LevelBgColors[curlevel]);
curscore:=Getscore;
f.Show ( curlevel, lives, curscore );
l.Start(curscore);
Setscore (Curscore);
if l.Passed then begin
if CurLevel = LevelsNumber then
EndofGame := true
else
inc(Curlevel);
end
else
begin
dec(lives);
if lives = 0 then
EndofGame := true;
end;
until EndofGame;
end;
procedure Game.Init;
Инициализация игры
begin
lives := MaxLives;
EndofGame := false;
Score:=0;
end;
function Game.GetScore:longint;
begin
GetScore:=Score;
end;
procedure Game.SetScore(score0:longint);
begin
Score:=score0;
end;
Begin
End.
Основная программа (ARKANOID)
Uses Gamelib;
Var g : game;
Begin
g.Init;
g.Run;
readln;
End.
ВЫВОДЫ
В ходе изучения игры арканоид мы научились пользоваться модулями. При разработке больших и сложных программных систем в среде Турбо Паскаля может возникнуть ситуация, когда выделяемого в программе сегмента памяти (64 Кбайт), недостаточно для компиляции программы. В этом случае удобно использовать так называемый модульный подход к разработке программ (модульное программирование), заключающийся в разбиении программы на отдельные конструктивно и функционально-законченные части, называемые модулями. Использование модулей, кроме того, целесообразно для создания собственных библиотек программ (процедур и функций), а также для разделения работы между отдельными программистами в группе. Для реализации концепции модульного программирования в Турбо Паскале (ТП) используются структурные единицы - модули, обозначаемые ключевым словом Unit . Важной особенностью модулей является то, что компилятор размещает программный код каждого модуля в отдельном сегменте памяти, размер которого не превышает 64 Кбайта.