Студопедия — Практическая работа № 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; просмотров: 452. Нарушение авторских прав; Мы поможем в написании вашей работы!



Важнейшие способы обработки и анализа рядов динамики Не во всех случаях эмпирические данные рядов динамики позволяют определить тенденцию изменения явления во времени...

ТЕОРЕТИЧЕСКАЯ МЕХАНИКА Статика является частью теоретической механики, изучающей условия, при ко­торых тело находится под действием заданной системы сил...

Теория усилителей. Схема Основная масса современных аналоговых и аналого-цифровых электронных устройств выполняется на специализированных микросхемах...

Логические цифровые микросхемы Более сложные элементы цифровой схемотехники (триггеры, мультиплексоры, декодеры и т.д.) не имеют...

Различия в философии античности, средневековья и Возрождения ♦Венцом античной философии было: Единое Благо, Мировой Ум, Мировая Душа, Космос...

Характерные черты немецкой классической философии 1. Особое понимание роли философии в истории человечества, в развитии мировой культуры. Классические немецкие философы полагали, что философия призвана быть критической совестью культуры, «душой» культуры. 2. Исследовались не только человеческая...

Обзор компонентов Multisim Компоненты – это основа любой схемы, это все элементы, из которых она состоит...

Броматометрия и бромометрия Броматометрический метод основан на окислении вос­становителей броматом калия в кислой среде...

Метод Фольгарда (роданометрия или тиоцианатометрия) Метод Фольгарда основан на применении в качестве осадителя титрованного раствора, содержащего роданид-ионы SCN...

Потенциометрия. Потенциометрическое определение рН растворов Потенциометрия - это электрохимический метод иссле­дования и анализа веществ, основанный на зависимости равновесного электродного потенциала Е от активности (концентрации) определяемого вещества в исследуемом рас­творе...

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