Студопедия — Практическая работа № 34
Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Практическая работа № 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] of integer = (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 then v:= –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) и скопируйте их в папку, в которой сохранен проект.

procedure TForm1.TrackBar1KeyPress(Sender: TObject; var Key: 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
if Explosion < 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;
if BombY < 1000 then
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 HappyEnd then
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 < 10 then
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 … en d, то именно к координате шара обращаются просто как к 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.Canvas do
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 * 10 do
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
with Balloons[i] do
if Explosion = 0 then DrawBalloon(x, 260 - y, Color) else if Explosion < 10 then DrawExplosion(x, 260 - y, Explosion);
if GunExplosion = 0 then DrawGun else if GunExplosion < 10 then DrawExplosion(GunPosition, 240, GunExplosion);
with Form1.Image1.Canvas do
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;

 

 







Дата добавления: 2015-09-04; просмотров: 454. Нарушение авторских прав; Мы поможем в написании вашей работы!



Аальтернативная стоимость. Кривая производственных возможностей В экономике Буридании есть 100 ед. труда с производительностью 4 м ткани или 2 кг мяса...

Вычисление основной дактилоскопической формулы Вычислением основной дактоформулы обычно занимается следователь. Для этого все десять пальцев разбиваются на пять пар...

Расчетные и графические задания Равновесный объем - это объем, определяемый равенством спроса и предложения...

Кардиналистский и ординалистский подходы Кардиналистский (количественный подход) к анализу полезности основан на представлении о возможности измерения различных благ в условных единицах полезности...

Различие эмпиризма и рационализма Родоначальником эмпиризма стал английский философ Ф. Бэкон. Основной тезис эмпиризма гласит: в разуме нет ничего такого...

Индекс гингивита (PMA) (Schour, Massler, 1948) Для оценки тяжести гингивита (а в последующем и ре­гистрации динамики процесса) используют папиллярно-маргинально-альвеолярный индекс (РМА)...

Методика исследования периферических лимфатических узлов. Исследование периферических лимфатических узлов производится с помощью осмотра и пальпации...

Деятельность сестер милосердия общин Красного Креста ярко проявилась в период Тритоны – интервалы, в которых содержится три тона. К тритонам относятся увеличенная кварта (ув.4) и уменьшенная квинта (ум.5). Их можно построить на ступенях натурального и гармонического мажора и минора.  ...

Понятие о синдроме нарушения бронхиальной проходимости и его клинические проявления Синдром нарушения бронхиальной проходимости (бронхообструктивный синдром) – это патологическое состояние...

Опухоли яичников в детском и подростковом возрасте Опухоли яичников занимают первое место в структуре опухолей половой системы у девочек и встречаются в возрасте 10 – 16 лет и в период полового созревания...

Studopedia.info - Студопедия - 2014-2024 год . (0.054 сек.) русская версия | украинская версия