Практическая работа № 34

«Игра»

 

Цель работы -создать программу – игру. Игрок управляет пушкой зенитки, его боевое задание – справиться с нашествием воздушных шаров. Воздушные шары несут бомбы, которые они сбросят, как только окажутся над пушкой. Необходимо не допустить этого и уничтожить их все на подлете. Снаряды не ограничены, но следующий выстрел можно делать только после того, как выпущенный снаряд поразит цель, упадет на землю или уйдет из зоны видимости.

В игре участвуют:

· воздушные шары,

· знитная пушка,

· пушечный снаряд,

· бомба,

· внешняя среда.

Для шаров введен специальный тип TBalloon., в котором содержатся данные о координатах шара, его скорости, состоянии и цвете. Массив переменных Balloons типа TBalloon будет содержать полную информацию обо всех шарах. Индексирование идет, начиная с нуля. Общее число шаров в массиве задается соответствующей константой.

Кроме того, к шарам относятся константы, определяющие:

· количество шаров,

· их возможные цвета,

· возможную высоту над землей (всего предполагается четыре уровня),

· интервал между шарами и их радиус.

Type

TBalloon = record

x, y, v, Explosion: integer;

Color: TColor;

End;

Const

BallCount = 10;
BallColors:array [0 .. 9] of TColor = (clRed, clGreen, clNavy, clMaroon, clPurple, clOlive, clLime, clYellow, clFuchsia, clSilver);
BallAltitude:array [0 .. 3] ofinteger = (240, 160, 200, 120);
BallInterval = 40;
BallRadius = 15;
V = 150;
g = -9.8 * 3;
dt = 0.1;
var
Form1: TForm1;
x, y, Vx, Vy, BombY, BombV: double;
Angle, GunPosition, GunExplosion: integer;
Balloons: array [0 .. BallCount - 1] of TBalloon;

 

Зенитная пушка описывается переменными:

· угол наклона пушки,

· ее положение

· ее состояние.

Пушечный снаряд описывается переменными:

· координатами,

· текущей скоростью,

· начальной скоростью при выстреле.

Бомба, сбрасываемая с воздушного шара, имеет:

· координату,

· скорость.

Для расчета положений объектов нужно знать ускорение падения и шаг по времени.

В качестве состояния шара и пушки мы используем переменные TBalloon. В определенный момент времени каждый элемент должен находиться в каком-то состоянии, определяющем то, как элемент выглядит на экране. Шары и пушка могут быть боеспособными, взрывающимися и уничтоженными.

Если Explosion = 0 - шар боеспособен, если Explosion = 10, то он уничтожен, а значения от 1 до 9 обозначают фазы взрыва. Чтобы инициировать взрыв боеспособного шара, нужно присвоить Explosion := 1. То же самое касается и пушки.

Состояние, в котором скорость снаряда равна нулю: Vx = 0 и Vy = 0. В этом случае считают, что можно сделать новый выстрел. Пока же снаряд летит (то есть скорость его не нулевая), новый выстрел сделать нельзя.

Бомба будет сбрасываться шаром, когда он поравняется с пушкой. Таким образом, X - координата бомбы всегда равна X - координате пушки. Следовательно, необходимо хранить только Y-координату бомбы. Бомба не сброшена, если BombY = 1000. Если BombY < 1000, то она считается сброшенной и начинает падать.

Поместите на форму TrackBar, Button, Image и Timer и настройте их параметры.

Timer: Interval = 100; Image: Width = 440, Heigth = 260; Button: Caption = ‘Новая игра’; TrackBar: Min = -90, Max = 90, Frequency = 10.

Image - сражение в реальном времени. Timer - реальное время. Button - запуск новой игры. TrackBar - управление зенитной пушкой.

В обработчике нажатия на кнопку "Новая игра" необходимо обнулить параметры, расставить пушку и шары. Для каждого шара устанавливается случайное направление движения: v = 1 или –1. В зависимости от направления, определяется высота, на которой находится шар (на одном и том же уровне шары летят в одну сторону). По x-координате шары расставляются так, чтобы они шли с примерно равным интервалом в направлении пушки из-за границ экрана.

Каждый шар Balloons[i], элемент массива Balloons, имеет тип записи TBalloon, и для того, чтобы получить доступ к его элементам, нужно писать: Balloons[i].Explosion := 0, Color := BallColors[random(10)] и т.д. Конструкция with Balloons[i] do begin ..end позволяет избежать повторения.

procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
Caption := 'Нашествие';
TrackBar1.Position := 0;
GunPosition := 170 + random(100);
Vx := 0;
Vy := 0;
GunExplosion := 0;
for i := 0 to BallCount – 1 do
with Balloons[i] do
begin
if random < 0.5 thenv := –1 else v := 1;
y := BallAltitude[1 + v + random(2)] + random(10);
x := 220 - v * (220 + i * BallInterval + random(20));
Explosion := 0;
Color := BallColors[random(10)];
end;
BombY := 1000;
end;

 

В обработчик события формы OnCreate вводится датчик случайных чисел, устанавливается клиентский размер формы (ClientWidth := 455; ClientHeight := 315;). Размер клиентской области формы в приложениях определяется автоматически как Width и Height формы минус ширина заголовка и бордюров.

procedure TForm1.FormCreate(Sender: TObject);
begin
Randomize;
ClientWidth := 455;
ClientHeight := 315;
Button1.Click;
end;

 

Пушка танка будет управляться с помощью компонента TrackBar. Выстрел производится нажатием пробела на клавиатуре. При этом фокус ввода должен быть у TrackBar. В обработчике OnKeyPress реализуется выстрел, задавая начальную скорость и положение снаряду, а также издавая звук выстрела.

Процедура, проигрывающая этот звук из wav-файла, описана в модуле, который необходимо подключить в разделе uses. В модуле MMSystem имеется функция PlaySound, с помощью которой можно проигрывать файлы wav. Для асинхронного воспроизведения (приложение не приостанавливает работу на время воспроизведения, а проигрывает его в фоновом режиме) вызов выглядит так:

PlaySound(PChar('имяфайла.wav'), 0, SND_ASYNC).

В стандартных звуках Microsoft Office можно подобрать звуки для выстрела и взрыва. В зависимости от версии программы, эти файлы хранятся в C:\Windows\Media\ Microsoft Office 2000, C:\Program Files\Microsoft Office\Office\Media или в какой-то подобной папке. Найдите звуки для выстрела (условно назовем GunShot.wav) и взрыва (условно назовем Explode.wav) и скопируйте их в папку, в которой сохранен проект.

procedureTForm1.TrackBar1KeyPress(Sender: TObject; varKey: Char);
var
i: integer;
begin
if(Key = ' ') and (Vx = 0) and (Vy = 0) and (GunExplosion = 0)then
begin
try

PlaySound(PChar('GunShot.wav'), 0, SND_ASYNC);
except
end;
Vx := V * Sin(Angle * pi / 180);
Vy := V * Cos(Angle * pi / 180);
x := GunPosition + 15 * Sin(Angle * pi / 180);
y := 20 + 15 * Cos(Angle * pi / 180);
end;

if (Key = 'Q')then
begin
try
PlaySound(PChar('Explode.wav'), 0, SND_ASYNC);
except
end;
for
i := 0 to BallCount - 1 do
if
Balloons[i].Explosion = 0 then
Balloons[i].Explosion := 1;
Caption := 'Уничтожен';
end;
end;

 

В обработчике изменения положения бегунка TrackBar меняем наклон пушки.

procedure TForm1.TrackBar1Change(Sender: TObject);
begin
Angle := TrackBar1.Position;
end;

 

Выстрел происходит, если:
1) нажат пробел;
2) снаряд готов (Vx = 0) и (Vy = 0);
3) пушка боеспособна (GunExploion = 0).

 

Процедура MoveAll, вызываемая каждый такт таймера, отвечает за то, чтобы все процессы шли своим чередом. Вставьте ее сразу после implementation.

 

procedure MoveAll;
var i: integer;
begin
for i := 0 to BallCount - 1 do
with Balloons[i] do
if Explosion = 0 then
x := x + v
else begin
ifExplosion < 10 then
inc(Explosion);
end;
if (Vx <> 0) or (Vy <> 0) then
begin
x := x + Vx * dt;
y := y + Vy * dt;
Vy := Vy + g * dt;
end;
ifBombY < 1000then
begin
BombY := BombY + BombV * dt;
BombV := BombV + g * dt
end;
if (GunExplosion > 0) and(GunExplosion < 10) then
inc(GunExplosion);
end;

 

Процедура пододвигает все шары, которые живы (у них Explosion = 0), в направлении вектора их скорости. Остальные шары, если они находятся в фазе взрыва (0 < Explosion < 10), переходят в следующую фазу.

Если снаряд выпущен (Vx <> 0) или (Vy <> 0), то его координата и скорость изменяются согласно законам природы.

Если бомба сброшена (BombY < 1000), то она также подчиняется закону всемирного тяготения.

Если танк находится в фазе взрыва (0 < GunExplosion < 10), он переходит в следующую фазу.

Ошибки, возникающие в обработчике таймера или процедурах, которые вызываются из обработчика, не останавливают таймер и, значит, через секунду возникают опять. Чтобы их остановить, приходится использовать Ctrl-Alt-Del…

В этой процедуре мы работаем с массивом. Одной из самых частых ошибок, которые не так-то просто найти, является выход за границы массива. Для предотвращения подобных ситуаций включите проверку на выход из диапазона допустимых значений (Project => Options => Compiler => Runtime errors => Range checking), которая по умолчанию отключена.

Перемещения сами по себе могли бы продолжаться бесконечно. Необходимо проконтролировать:

· не попал ли снаряд в шар, следовательно, взорвать его;

· не уничтожены ли все шары, следовательно, выдать надпись о победе;

· не поравнялся ли шар с пушкой, следовательно, сбросить бомбу;

· не упал ли снаряд и не вышел ли он из зоны контроля, следовательно, перезарядить пушку;

· не упала ли бомба на пушку, следовательно, закончить игру.

Для контроля за передвижениями предусмотрена процедура:

procedure CheckCollisions;
var
i, j: integer;
HappyEnd: boolean;
begin
for i := 0 to BallCount - 1 do
with Balloons[i] do
begin
if (Explosion = 0) then
begin
if(sqr(x - Unit1.x) + sqr(y - Unit1.y) < sqr(BallRadius)) then
begin
try
PlaySound(PChar('Explode.wav'), 0, SND_ASYNC);
except end;
Explosion := 1;
Unit1.x := 0;
Unit1.y := 0;
Unit1.Vx := 0;
Unit1.Vy := 0;
HappyEnd := (GunExplosion = 0);
for j := 0 to BallCount - 1 do
HappyEnd := HappyEnd and (Balloons[j].Explosion > 0);
if HappyEndthen
Form1.Caption := 'Победа!';
end;
if (x = GunPosition) and (BombY = 1000)and (GunExplosion = 0) then
begin
BombY := y - BallRadius - 5;
BombV := 0;
end;
end;
end;
if (y < 0) or(x < 0) or (x > 440) then
begin
x := 0;
y := 0;
Vx := 0;
Vy := 0;
end;
if BombY < 10then
begin
BombY := 1000;
GunExplosion := 1;
try
PlaySound(PChar('Explode.wav'), 0, SND_ASYNC);
except end;
Form1.Caption := 'Увы...';
end;
end;

В этом блоке возможная ошибка связана с использованием with … do begin … end.

X-координата снаряда хранится в глобальной переменной x, X-координата воздушного шара – в переменной Balloons[i].x. Однако когда пишут код внутри with Balloons[i] do begin … end, то именно к координате шара обращаются просто как к x. Если нужно добраться до глобальной переменной, то теперь уже перед ней нужно ставить уточнение: Unit1.x, где Unit1 – имя модуля.

Рисование отдельных элементов баталии также разумно поместить в специализированные для этого процедуры.

Художественные образы шаров, пушки и взрыва передаются с помощью процедур:

procedure DrawBalloon(x, y: integer; Color: TColor);
begin
with Form1.Image1.Canvas do
begin
Pen.Color := clBlack;
Brush.Color := Color;
Ellipse(x - BallRadius, y - BallRadius, x + BallRadius, y + BallRadius);
Pen.Color := clWhite;
Brush.Color := clWhite;
Ellipse(x - BallRadius div 2 - 3, y - BallRadius div 2 - 3, x - BallRadius div 2 + 3, y - BallRadius div 2 + 3);
Pen.Color := clBlack;
Brush.Color := clOlive;
Rectangle(x - 5, y + BallRadius + 5, x + 5, y + BallRadius + 10);
MoveTo(x - 5, y + BallRadius + 5);
LineTo(x - BallRadius, y);
MoveTo(x, y + BallRadius + 5);
LineTo(x, y);
MoveTo(x + 5, y + BallRadius + 5);
LineTo(x + BallRadius, y);
end;
end;

procedure DrawGun;
begin
with Form1.Image1.Canvasdo
begin
if (Vx = 0) and(Vy = 0) then
Pen.Color := RGB(0, 70, 0) else Pen.Color := clBlack;
Brush.Color := Pen.Color;
Pen.Width := 5;
MoveTo(GunPosition, 240);
LineTo(GunPosition + round(15 * sin(Angle * pi / 180)), 240 - round(15 * cos(Angle * pi / 180)));
Pen.Width := 1;
Ellipse(GunPosition - 8, 232, GunPosition + 8, 248);
Rectangle(GunPosition - 10, 240, GunPosition + 10, 260);
end;
end;

Процедура DrawExplosion обеспечивает доступ к координатам снаряда.

procedure DrawExplosion(x, y, Phase: integer);
var
i, xx, yy, Size: integer;
a, b: double;
begin
with Form1.Image1.Canvas do
for i := 0 to Phase * 10do
begin
a := random * 2 * pi;
b := random * sqr(Phase) / 3 + 5;
xx := x + round(l * sin(a));
yy := y + round(l * cos(a));
Size := round(sqr(10 - Phase) / 8 + 2);
Pen.Color := RGB(random(100), 0, 0);
Brush.Color := Pen.Color;
Ellipse(xx - random(Size) - 1, yy - random(Size) - 1, xx + random(Size), yy + random(Size));
end;
end;

Кроме того, пушка меняет цвет, когда готов очередной снаряд. В довершение, нужно соединить все написанное воедино.

Процедуры рисования объединяются в процедуре, рисующей все поле боя:

· небо,

· шары,

· пушка,

· ядро,

· бомба.

Объединять все вместе обработчик таймера.

 

procedure DrawBattleField;
var
i: integer;
begin
with Form1.Image1.Canvas do
for i := 0 to 259 do
begin
Pen.Color := RGB(i div 2, i div 2, 255);
MoveTo(0, i);
LineTo(440, i);
end;
for i := 0 to BallCount - 1 do
withBalloons[i] do
if Explosion = 0 then DrawBalloon(x, 260 - y, Color) else if Explosion < 10 then DrawExplosion(x, 260 - y, Explosion);
if GunExplosion = 0then DrawGun else if GunExplosion < 10 then DrawExplosion(GunPosition, 240, GunExplosion);
with Form1.Image1.Canvasdo
begin
Pen.Color := clMaroon;
Brush.Color := clRed;
if (Vx <> 0) or (Vy <> 0) then Ellipse(round(x) - 2, 260 - round(y) - 2, round(x) + 3, 260 - round(y) + 3);
if (BombY <> 1000) then Ellipse(GunPosition - 2, 260 - round(BombY) - 2, GunPosition + 3, 260 - round(BombY) + 3);
end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
MoveAll;
CheckCollisions;
DrawBattleField;
end;

 

Рисунок 56

 


Практическая работа № 35

«Тест»

 

Цель работы -создать программу, которая тестирует учащегося по информатике и математике.

Проект должен содержать последовательность форм, реализующих диалог с тестируемым учащимся.

На первой форме происходит регистрация учащегося.

 

 

Рисунок 57


 

Фрагмент программы (unit1):

uses Unit2;

{$R *.dfm}

 

procedure TForm1.Button2Click(Sender: TObject);

Begin

Close;

end;

 

procedure TForm1.Button1Click(Sender: TObject);

Begin

Form2.Label3.Caption:=Form1.Edit1.Text;

Form2.ShowModal;

end;
На второй форме предлагается выбрать один из тестов.

 

Рисунок 58

 


Фрагмент программы (unit2):

uses Unit3, Unit6;

{$R *.dfm}

 

procedure TForm2.Button1Click(Sender: TObject);

Begin

Form3.ShowModal;

end;

 

procedure TForm2.Button2Click(Sender: TObject);

Begin

Form2.Close;

end;

 

procedure TForm2.Button3Click(Sender: TObject);

Begin

Form6.Edit2.Text:='';

Form6.ShowModal;

end;

На третьей форме предлагается пройти тест по информатике.

 

Рисунок 59

 

 


 

Фрагмент программы (unit3):

uses Unit4, Unit2;

{$R *.dfm}

 

procedure TForm3.Button1Click(Sender: TObject);

Begin

k:=0;

if (Form3.Edit1.Text='монитор') or (Form3.Edit1.Text='Монитор') or

(Form3.Edit1.Text='МОНИТОР') then k:=k+1;

if (Form3.Edit2.Text='Клавиатура') or (Form3.Edit2.Text='клавиатура')

or (Form3.Edit2.Text='КЛАВИАТУРА') then k:=k+1;

if Form3.Edit3.Text='8' then k:=k+1;

Form4.Label2.Caption:=IntToStr(k);

if k=0 then Form4.Label1.Caption:='Очень плохо' else

if k=1 then Form4.Label1.Caption:='Плохо' else

if k=2 then Form4.Label1.Caption:='Хорошо' else

if k=3 then Form4.Label1.Caption:='Очень хорошо';

Form3.Edit1.Text:='';

Form3.Edit2.Text:='';

Form3.Edit3.Text:='';

Form4.ShowModal;

end;

 

procedure TForm3.Button2Click(Sender: TObject);

Begin

Form3.Close;

end;

На следующей форме отображается результат тестирования и предложение о промотре ответа.

Рисунок 60

 


Фрагмент программы (unit4):

uses Unit1, Unit5, Unit3, Unit2;

{$R *.dfm}

 

procedure TForm4.Button2Click(Sender: TObject);

Begin

Form4.Close;

end;

 

procedure TForm4.Button1Click(Sender: TObject);

Begin

Form4.Close;

Form3.Close;

end;

 

procedure TForm4.Button3Click(Sender: TObject);

Begin

Form5.ShowModal;

end;

На следующей форме отображаются правильные ответы.

 

Рисунок 61

 


Фрагмент программы (unit5):

uses Unit4, Unit3, Unit2, Unit1;

{$R *.dfm}

 

procedure TForm5.Button1Click(Sender: TObject);

Begin

Form4.Close;

Form3.Close;

Form2.Close;

Form1.Close;

Form5.Close; end;

Если учащийся выбрал тест по математике, то ему предлагается проверить свои знания таблицы умножения. На следующей форме случайным образом выбираются числа. Учащийся должен ввести значение произведения в текстовое поле. С помощью кнопки «проверка» выясняется правильность введенного ответа. Если ответ правильный, то можно сгенерировать следующий пример. После нескольких примеров можно проверить свой рейтинг.

 

 

Рисунок 62

 


Фрагмент программы (unit6):

uses Unit7, Unit1;

{$R *.dfm}

 

procedure TForm6.Button1Click(Sender: TObject);

var n,i:integer;

Begin

randomize;

a:=random(10)-0;

b:=random(10)-0;

Form6.Label1.Caption:=IntToStr(a);

Form6.Label2.Caption:=IntToStr(b);

Form6.Edit2.Text:='';

Form6.Label6.Caption:='';

end;

 

procedure TForm6.Button2Click(Sender: TObject);

Begin

if (a*b=StrToInt(Form6.Edit2.Text)) then

Begin

Form6.Label6.Caption:='Правильно';

m:=m+1;

r:=r+1;

q:=q+1;

End

Else

Begin

Form6.Label6.Caption:='Не правильно';

r:=r-1;

q:=q+1;

end;

Form6.Label1.Caption:='';

Form6.Label2.Caption:='';

end;

 

procedure TForm6.Button3Click(Sender: TObject);

Var

c:real;

Begin

Form7.Label2.Caption:=Form1.Edit1.Text;

Form7.Label1.Caption:='Вы ответили на '+IntToStr(q)+' вопросов, из них правильно '+IntToStr(m);

Form7.Label4.Caption:='Ваш рейтинг = '+IntToStr(r);

c:=m/q;

ifc=0 then Form7.Label3.Caption:='Очень плохо' else

if (c>0)and(c<0.5) then Form7.Label3.Caption:='Плохо' else

if c=0.5 then Form7.Label3.Caption:='Надо доучить' else

if(c>0.5) and (c<1) then Form7.Label3.Caption:='Хорошо' else

if c=1 then Form7.Label3.Caption:='Молодец!';

Form7.ShowModal;

end;

При нажатии на кнопке «Ваш рейтинг» на следующей форме появляется результаты рейтенга. Тестирование можно завершить.

Рисунок 63

 


Фрагмент программы (unit7):

uses Unit6;

{$R *.dfm}

 

procedure TForm7.Button1Click(Sender: TObject);

Begin

Form7.Close;

Form6.Close;

end;

Обратите внимание на подключение модулей в строке Uses. Таким образом, происходит обращение к соответствующей форме. Для отображения формы используется функция

function ShowModal: Integer;

Данная функция позволяет показывать форму в работе режима диалога.

 

 









Дата добавления: 2014-12-02; просмотров: 1281;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.138 сек.